Page MenuHomePhabricator

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/Core/Code/Algorithms/mitkClippedSurfaceBoundsCalculator.cpp b/Core/Code/Algorithms/mitkClippedSurfaceBoundsCalculator.cpp
index 8cf5763fd9..aff97b6af2 100644
--- a/Core/Code/Algorithms/mitkClippedSurfaceBoundsCalculator.cpp
+++ b/Core/Code/Algorithms/mitkClippedSurfaceBoundsCalculator.cpp
@@ -1,354 +1,354 @@
/*===================================================================
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 "mitkClippedSurfaceBoundsCalculator.h"
#include "mitkLine.h"
#define ROUND_P(x) ((x)>=0?(int)((x)+0.5):(int)((x)-0.5))
mitk::ClippedSurfaceBoundsCalculator::ClippedSurfaceBoundsCalculator(
const mitk::PlaneGeometry* geometry,
mitk::Image::Pointer image)
: m_PlaneGeometry(NULL)
, m_Geometry3D(NULL)
, m_Image(NULL)
{
this->InitializeOutput();
this->SetInput(geometry, image);
}
mitk::ClippedSurfaceBoundsCalculator::ClippedSurfaceBoundsCalculator(
- const mitk::Geometry3D* geometry,
+ const mitk::BaseGeometry* geometry,
mitk::Image::Pointer image)
: m_PlaneGeometry(NULL)
, m_Geometry3D(NULL)
, m_Image(NULL)
{
this->InitializeOutput();
this->SetInput(geometry, image);
}
mitk::ClippedSurfaceBoundsCalculator::ClippedSurfaceBoundsCalculator( const PointListType pointlist, mitk::Image::Pointer image )
: m_PlaneGeometry(NULL)
, m_Geometry3D(NULL)
, m_Image(image)
{
this->InitializeOutput();
m_ObjectPointsInWorldCoordinates = pointlist;
}
void mitk::ClippedSurfaceBoundsCalculator::InitializeOutput()
{
// initialize with meaningless slice indices
m_MinMaxOutput.clear();
for(int i = 0; i < 3; i++)
{
m_MinMaxOutput.push_back(
OutputType( std::numeric_limits<int>::max() ,
std::numeric_limits<int>::min() ));
}
}
mitk::ClippedSurfaceBoundsCalculator::~ClippedSurfaceBoundsCalculator()
{
}
void
mitk::ClippedSurfaceBoundsCalculator::SetInput(
const mitk::PlaneGeometry* geometry,
mitk::Image* image)
{
if(geometry && image)
{
this->m_PlaneGeometry = geometry;
this->m_Image = image;
this->m_Geometry3D = NULL; //Not possible to set both
m_ObjectPointsInWorldCoordinates.clear();
}
}
void
mitk::ClippedSurfaceBoundsCalculator::SetInput(
- const mitk::Geometry3D* geometry,
+ const mitk::BaseGeometry* geometry,
mitk::Image* image)
{
if(geometry && image)
{
this->m_Geometry3D = geometry;
this->m_Image = image;
this->m_PlaneGeometry = NULL; //Not possible to set both
m_ObjectPointsInWorldCoordinates.clear();
}
}
void mitk::ClippedSurfaceBoundsCalculator::SetInput( const std::vector<mitk::Point3D> pointlist, mitk::Image *image )
{
if ( !pointlist.empty() && image )
{
m_Geometry3D = NULL;
m_PlaneGeometry = NULL;
m_Image = image;
m_ObjectPointsInWorldCoordinates = pointlist;
}
}
mitk::ClippedSurfaceBoundsCalculator::OutputType
mitk::ClippedSurfaceBoundsCalculator::GetMinMaxSpatialDirectionX()
{
return this->m_MinMaxOutput[0];
}
mitk::ClippedSurfaceBoundsCalculator::OutputType
mitk::ClippedSurfaceBoundsCalculator::GetMinMaxSpatialDirectionY()
{
return this->m_MinMaxOutput[1];
}
mitk::ClippedSurfaceBoundsCalculator::OutputType
mitk::ClippedSurfaceBoundsCalculator::GetMinMaxSpatialDirectionZ()
{
return this->m_MinMaxOutput[2];
}
void mitk::ClippedSurfaceBoundsCalculator::Update()
{
this->m_MinMaxOutput.clear();
for(int i = 0; i < 3; i++)
{
this->m_MinMaxOutput.push_back(OutputType( std::numeric_limits<int>::max() , std::numeric_limits<int>::min() ));
}
if(m_PlaneGeometry.IsNotNull())
{
this->CalculateIntersectionPoints(m_PlaneGeometry);
}
else if(m_Geometry3D.IsNotNull())
{
// go through all slices of the image, ...
const mitk::SlicedGeometry3D* slicedGeometry3D = dynamic_cast<const mitk::SlicedGeometry3D*>( m_Geometry3D.GetPointer() );
int allSlices = slicedGeometry3D->GetSlices();
- this->CalculateIntersectionPoints(dynamic_cast<mitk::PlaneGeometry*>(slicedGeometry3D->GetGeometry2D(0)));
- this->CalculateIntersectionPoints(dynamic_cast<mitk::PlaneGeometry*>(slicedGeometry3D->GetGeometry2D(allSlices-1)));
+ this->CalculateIntersectionPoints(dynamic_cast<mitk::PlaneGeometry*>(slicedGeometry3D->GetPlaneGeometry(0)));
+ this->CalculateIntersectionPoints(dynamic_cast<mitk::PlaneGeometry*>(slicedGeometry3D->GetPlaneGeometry(allSlices-1)));
}
else if( !m_ObjectPointsInWorldCoordinates.empty() )
{
this->CalculateIntersectionPoints( m_ObjectPointsInWorldCoordinates );
}
}
void mitk::ClippedSurfaceBoundsCalculator::CalculateIntersectionPoints(const mitk::PlaneGeometry* geometry)
{
// SEE HEADER DOCUMENTATION for explanation
typedef std::vector< std::pair<mitk::Point3D, mitk::Point3D> > EdgesVector;
Point3D origin;
Vector3D xDirection, yDirection, zDirection;
const Vector3D spacing = m_Image->GetGeometry()->GetSpacing();
origin = m_Image->GetGeometry()->GetOrigin(); //Left, bottom, front
//Get axis vector for the spatial directions
xDirection = m_Image->GetGeometry()->GetAxisVector(1);
yDirection = m_Image->GetGeometry()->GetAxisVector(0);
zDirection = m_Image->GetGeometry()->GetAxisVector(2);
/*
* For the calculation of the intersection points we need as corner points the center-based image coordinates.
* With the method GetCornerPoint() of the class Geometry3D we only get the corner-based coordinates.
* Therefore we need to calculate the center-based corner points here. For that we add/substract the corner-
* based coordinates with the spacing of the geometry3D.
*/
for( int i = 0; i < 3; i++ )
{
if(xDirection[i] < 0)
{
xDirection[i] += spacing[i];
}
else if( xDirection[i] > 0 )
{
xDirection[i] -= spacing[i];
}
if(yDirection[i] < 0)
{
yDirection[i] += spacing[i];
}
else if( yDirection[i] > 0 )
{
yDirection[i] -= spacing[i];
}
if(zDirection[i] < 0)
{
zDirection[i] += spacing[i];
}
else if( zDirection[i] > 0 )
{
zDirection[i] -= spacing[i];
}
}
Point3D leftBottomFront, leftTopFront, leftBottomBack, leftTopBack;
Point3D rightBottomFront, rightTopFront, rightBottomBack, rightTopBack;
leftBottomFront = origin;
leftTopFront = origin + yDirection;
leftBottomBack = origin + zDirection;
leftTopBack = origin + yDirection + zDirection;
rightBottomFront = origin + xDirection;
rightTopFront = origin + xDirection + yDirection;
rightBottomBack = origin + xDirection + zDirection;
rightTopBack = origin + xDirection + yDirection + zDirection;
EdgesVector edgesOf3DBox;
edgesOf3DBox.push_back(std::make_pair(leftBottomBack, // x = left=xfront, y=bottom=yfront, z=front=zfront
leftTopFront)); // left, top, front
edgesOf3DBox.push_back(std::make_pair(leftBottomFront, // left, bottom, front
leftBottomBack)); // left, bottom, back
edgesOf3DBox.push_back(std::make_pair(leftBottomFront, // left, bottom, front
rightBottomFront)); // right, bottom, front
edgesOf3DBox.push_back(std::make_pair(leftTopFront, // left, top, front
rightTopFront)); // right, top, front
edgesOf3DBox.push_back(std::make_pair(leftTopFront, // left, top, front
leftTopBack)); // left, top, back
edgesOf3DBox.push_back(std::make_pair(rightTopFront, // right, top, front
rightTopBack)); // right, top, back
edgesOf3DBox.push_back(std::make_pair(rightTopFront, // right, top, front
rightBottomFront)); // right, bottom, front
edgesOf3DBox.push_back(std::make_pair(rightBottomFront, // right, bottom, front
rightBottomBack)); // right, bottom, back
edgesOf3DBox.push_back(std::make_pair(rightBottomBack, // right, bottom, back
leftBottomBack)); // left, bottom, back
edgesOf3DBox.push_back(std::make_pair(rightBottomBack, // right, bottom, back
rightTopBack)); // right, top, back
edgesOf3DBox.push_back(std::make_pair(rightTopBack, // right, top, back
leftTopBack)); // left, top, back
edgesOf3DBox.push_back(std::make_pair(leftTopBack, // left, top, back
leftBottomBack)); // left, bottom, back
for (EdgesVector::iterator iterator = edgesOf3DBox.begin(); iterator != edgesOf3DBox.end();iterator++)
{
Point3D startPoint = (*iterator).first; // start point of the line
Point3D endPoint = (*iterator).second; // end point of the line
Vector3D lineDirection = endPoint - startPoint;
mitk::Line3D line(startPoint, lineDirection);
Point3D intersectionWorldPoint;
intersectionWorldPoint.Fill(std::numeric_limits<int>::min());
// Get intersection point of line and plane geometry
geometry->IntersectionPoint(line, intersectionWorldPoint);
double t = -1.0;
bool doesLineIntersectWithPlane(false);
if(line.GetDirection().GetNorm() < mitk::eps && geometry->Distance(line.GetPoint1()) < mitk::sqrteps)
{
t = 1.0;
doesLineIntersectWithPlane = true;
intersectionWorldPoint = line.GetPoint1();
}
else
{
geometry->IntersectionPoint(line, intersectionWorldPoint);
doesLineIntersectWithPlane = geometry->IntersectionPointParam(line, t);
}
mitk::Point3D intersectionIndexPoint;
//Get index point
m_Image->GetGeometry()->WorldToIndex(intersectionWorldPoint, intersectionIndexPoint);
if ( doesLineIntersectWithPlane && -mitk::sqrteps <= t && t <= 1.0 + mitk::sqrteps )
{
for(int dim = 0; dim < 3; dim++)
{
// minimum
//If new point value is lower than old
if( this->m_MinMaxOutput[dim].first > ROUND_P(intersectionIndexPoint[dim]) )
{
this->m_MinMaxOutput[dim].first = ROUND_P(intersectionIndexPoint[dim]); //set new value
}
// maximum
//If new point value is higher than old
if( this->m_MinMaxOutput[dim].second < ROUND_P(intersectionIndexPoint[dim]) )
{
this->m_MinMaxOutput[dim].second = ROUND_P(intersectionIndexPoint[dim]); //set new value
}
}
this->EnforceImageBounds();
}
}
}
void mitk::ClippedSurfaceBoundsCalculator::CalculateIntersectionPoints( PointListType pointList )
{
PointListType::iterator pointIterator;
mitk::SlicedGeometry3D::Pointer imageGeometry = m_Image->GetSlicedGeometry();
for ( pointIterator = pointList.begin(); pointIterator != pointList.end(); pointIterator++ )
{
mitk::Point3D pntInIndexCoordinates;
imageGeometry->WorldToIndex( (*pointIterator), pntInIndexCoordinates );
m_MinMaxOutput[0].first = pntInIndexCoordinates[0] < m_MinMaxOutput[0].first ? ROUND_P(pntInIndexCoordinates[0]) : m_MinMaxOutput[0].first;
m_MinMaxOutput[0].second = pntInIndexCoordinates[0] > m_MinMaxOutput[0].second ? ROUND_P(pntInIndexCoordinates[0]) : m_MinMaxOutput[0].second;
m_MinMaxOutput[1].first = pntInIndexCoordinates[1] < m_MinMaxOutput[1].first ? ROUND_P(pntInIndexCoordinates[1]) : m_MinMaxOutput[1].first;
m_MinMaxOutput[1].second = pntInIndexCoordinates[1] > m_MinMaxOutput[1].second ? ROUND_P(pntInIndexCoordinates[1]) : m_MinMaxOutput[1].second;
m_MinMaxOutput[2].first = pntInIndexCoordinates[2] < m_MinMaxOutput[2].first ? ROUND_P(pntInIndexCoordinates[2]) : m_MinMaxOutput[2].first;
m_MinMaxOutput[2].second = pntInIndexCoordinates[2] > m_MinMaxOutput[2].second ? ROUND_P(pntInIndexCoordinates[2]) : m_MinMaxOutput[2].second;
}
this->EnforceImageBounds();
}
void mitk::ClippedSurfaceBoundsCalculator::EnforceImageBounds()
{
m_MinMaxOutput[0].first = std::max( m_MinMaxOutput[0].first, 0 );
m_MinMaxOutput[1].first = std::max( m_MinMaxOutput[1].first, 0 );
m_MinMaxOutput[2].first = std::max( m_MinMaxOutput[2].first, 0 );
m_MinMaxOutput[0].second = std::min( m_MinMaxOutput[0].second, (int) m_Image->GetDimension(0)-1 );
m_MinMaxOutput[1].second = std::min( m_MinMaxOutput[1].second, (int) m_Image->GetDimension(1)-1 );
m_MinMaxOutput[2].second = std::min( m_MinMaxOutput[2].second, (int) m_Image->GetDimension(2)-1 );
}
diff --git a/Core/Code/Algorithms/mitkClippedSurfaceBoundsCalculator.h b/Core/Code/Algorithms/mitkClippedSurfaceBoundsCalculator.h
index 690c10e554..8d9fe18283 100644
--- a/Core/Code/Algorithms/mitkClippedSurfaceBoundsCalculator.h
+++ b/Core/Code/Algorithms/mitkClippedSurfaceBoundsCalculator.h
@@ -1,122 +1,122 @@
/*===================================================================
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 ClippedSurfaceBoundsCalculator_h_included
#define ClippedSurfaceBoundsCalculator_h_included
#include "mitkImage.h"
#include "mitkPlaneGeometry.h"
#include <vector>
/**
* \brief Find image slices visible on a given plane.
*
* The class name is not helpful in finding this class. Good suggestions welcome.
*
* Given a PlaneGeometry (e.g. the 2D plane of a render window), this class
* calculates which slices of an mitk::Image are visible on this plane.
* Calculation is done for X, Y, and Z direction, the result is available in
* form of a pair (minimum,maximum) slice index.
*
* Such calculations are useful if you want to display information about the
* currently visible slice (overlays, statistics, ...) and you don't want to
* depend on any prior information about hat the renderwindow is currently showing.
*
* \warning The interface attempts to look like an ITK filter but it is far from being one.
*/
namespace mitk
{
class MITK_CORE_EXPORT ClippedSurfaceBoundsCalculator
{
public:
typedef std::vector<mitk::Point3D> PointListType;
ClippedSurfaceBoundsCalculator(const mitk::PlaneGeometry* geometry = NULL,
mitk::Image::Pointer image = NULL);
- ClippedSurfaceBoundsCalculator(const mitk::Geometry3D* geometry,
+ ClippedSurfaceBoundsCalculator(const mitk::BaseGeometry* geometry,
mitk::Image::Pointer image);
ClippedSurfaceBoundsCalculator(const PointListType pointlist,
mitk::Image::Pointer image);
void InitializeOutput();
virtual ~ClippedSurfaceBoundsCalculator();
void SetInput(const mitk::PlaneGeometry* geometry, mitk::Image* image);
- void SetInput(const mitk::Geometry3D *geometry, mitk::Image *image);
+ void SetInput(const mitk::BaseGeometry *geometry, mitk::Image *image);
void SetInput(const PointListType pointlist, mitk::Image *image);
/**
\brief Request calculation.
How cut/visible slice indices are determined:
1. construct a bounding box of the image. This is the box that connect the outer voxel centers(!).
2. check the edges of this box.
3. intersect each edge with the plane geometry
- if the intersection point is within the image box,
we update the visible/cut slice indices for all dimensions.
- else we ignore the cut
*/
void Update();
/**
\brief Minimum (first) and maximum (second) slice index.
*/
typedef std::pair<int, int> OutputType;
/**
\brief What X coordinates (slice indices) are cut/visible in given plane.
*/
OutputType GetMinMaxSpatialDirectionX();
/**
\brief What Y coordinates (slice indices) are cut/visible in given plane.
*/
OutputType GetMinMaxSpatialDirectionY();
/**
\brief What Z coordinates (slice indices) are cut/visible in given plane.
*/
OutputType GetMinMaxSpatialDirectionZ();
protected:
void CalculateIntersectionPoints(const mitk::PlaneGeometry* geometry);
void CalculateIntersectionPoints( PointListType pointList );
/**
* \brief Clips the resulting index-coordinates to make sure they do
* not exceed the imagebounds.
*/
void EnforceImageBounds();
mitk::PlaneGeometry::ConstPointer m_PlaneGeometry;
- mitk::Geometry3D::ConstPointer m_Geometry3D;
+ mitk::BaseGeometry::ConstPointer m_Geometry3D;
mitk::Image::Pointer m_Image;
std::vector<mitk::Point3D> m_ObjectPointsInWorldCoordinates;
std::vector< OutputType > m_MinMaxOutput;
};
} //namespace mitk
#endif
diff --git a/Core/Code/Algorithms/mitkExtractSliceFilter.cpp b/Core/Code/Algorithms/mitkExtractSliceFilter.cpp
index f0f3a58634..7c49cd1940 100644
--- a/Core/Code/Algorithms/mitkExtractSliceFilter.cpp
+++ b/Core/Code/Algorithms/mitkExtractSliceFilter.cpp
@@ -1,486 +1,486 @@
/*===================================================================
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 "mitkExtractSliceFilter.h"
#include <vtkImageData.h>
#include <vtkSmartPointer.h>
#include <vtkLinearTransform.h>
#include <vtkImageChangeInformation.h>
#include <mitkAbstractTransformGeometry.h>
#include <vtkGeneralTransform.h>
#include <mitkPlaneClipping.h>
mitk::ExtractSliceFilter::ExtractSliceFilter(vtkImageReslice* reslicer ){
if(reslicer == NULL){
m_Reslicer = vtkSmartPointer<vtkImageReslice>::New();
}
else
{
m_Reslicer = reslicer;
}
m_TimeStep = 0;
m_Reslicer->ReleaseDataFlagOn();
m_InterpolationMode = ExtractSliceFilter::RESLICE_NEAREST;
m_ResliceTransform = NULL;
m_InPlaneResampleExtentByGeometry = false;
m_OutPutSpacing = new mitk::ScalarType[2];
m_OutputDimension = 2;
m_ZSpacing = 1.0;
m_ZMin = 0;
m_ZMax = 0;
m_VtkOutputRequested = false;
}
mitk::ExtractSliceFilter::~ExtractSliceFilter(){
m_ResliceTransform = NULL;
m_WorldGeometry = NULL;
delete [] m_OutPutSpacing;
}
void mitk::ExtractSliceFilter::GenerateOutputInformation(){
Superclass::GenerateOutputInformation();
//TODO try figure out how to set the specs of the slice before it is actually extracted
/*Image::Pointer output = this->GetOutput();
Image::ConstPointer input = this->GetInput();
if (input.IsNull()) return;
unsigned int dimensions[2];
dimensions[0] = m_WorldGeometry->GetExtent(0);
dimensions[1] = m_WorldGeometry->GetExtent(1);
output->Initialize(input->GetPixelType(), 2, dimensions, 1);*/
}
void mitk::ExtractSliceFilter::GenerateInputRequestedRegion(){
//As we want all pixel information fo the image in our plane, the requested region
//is set to the largest possible region in the image.
//This is needed because an oblique plane has a larger extent then the image
//and the in pipeline it is checked via PropagateResquestedRegion(). But the
//extent of the slice is actually fitting because it is oblique within the image.
ImageToImageFilter::InputImagePointer input = const_cast< ImageToImageFilter::InputImageType* > ( this->GetInput() );
input->SetRequestedRegionToLargestPossibleRegion();
}
mitk::ScalarType* mitk::ExtractSliceFilter::GetOutputSpacing(){
return m_OutPutSpacing;
}
void mitk::ExtractSliceFilter::GenerateData(){
mitk::Image *input = const_cast< mitk::Image * >( this->GetInput() );
if (!input)
{
MITK_ERROR << "mitk::ExtractSliceFilter: No input image available. Please set the input!" << std::endl;
itkExceptionMacro("mitk::ExtractSliceFilter: No input image available. Please set the input!");
return;
}
if(!m_WorldGeometry)
{
MITK_ERROR << "mitk::ExtractSliceFilter: No Geometry for reslicing available." << std::endl;
itkExceptionMacro("mitk::ExtractSliceFilter: No Geometry for reslicing available.");
return;
}
const TimeGeometry* inputTimeGeometry = this->GetInput()->GetTimeGeometry();
if ( ( inputTimeGeometry == NULL )
|| ( inputTimeGeometry->CountTimeSteps() <= 0 ) )
{
itkWarningMacro(<<"Error reading input image TimeGeometry.");
return;
}
// is it a valid timeStep?
if ( inputTimeGeometry->IsValidTimeStep( m_TimeStep ) == false )
{
itkWarningMacro(<<"This is not a valid timestep: "<< m_TimeStep );
return;
}
// check if there is something to display.
if ( ! input->IsVolumeSet( m_TimeStep ) )
{
itkWarningMacro(<<"No volume data existent at given timestep "<< m_TimeStep );
return;
}
/*================#BEGIN setup vtkImageRslice properties================*/
Point3D origin;
Vector3D right, bottom, normal;
double widthInMM, heightInMM;
Vector2D extent;
const PlaneGeometry* planeGeometry = dynamic_cast<const PlaneGeometry*>(m_WorldGeometry);
if ( planeGeometry != NULL )
{
//if the worldGeomatry is a PlaneGeometry everthing is straight forward
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.
Vector3D rightInIndex, bottomInIndex;
inputTimeGeometry->GetGeometryForTimeStep( m_TimeStep )->WorldToIndex( right, rightInIndex );
inputTimeGeometry->GetGeometryForTimeStep( m_TimeStep )->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 );
m_OutPutSpacing[0] = widthInMM / extent[0];
m_OutPutSpacing[1] = heightInMM / extent[1];
right.Normalize();
bottom.Normalize();
normal.Normalize();
/*
* Transform the origin to center based coordinates.
* Note:
* This is needed besause vtk's origin is center based too (!!!) ( see 'The VTK book' page 88 )
* and the worldGeometry surrouding the image is no imageGeometry. So the worldGeometry
* has its origin at the corner of the voxel and needs to be transformed.
*/
origin += right * ( m_OutPutSpacing[0] * 0.5 );
origin += bottom * ( m_OutPutSpacing[1] * 0.5 );
//set the tranform for reslicing.
// Use inverse transform of the input geometry for reslicing the 3D image.
// This is needed if the image volume already transformed
if(m_ResliceTransform.IsNotNull())
m_Reslicer->SetResliceTransform(m_ResliceTransform->GetVtkTransform()->GetLinearInverse());
- // Set background level to TRANSLUCENT (see Geometry2DDataVtkMapper3D),
+ // Set background level to TRANSLUCENT (see PlaneGeometryDataVtkMapper3D),
// else the background of the image turns out gray
m_Reslicer->SetBackgroundLevel( -32768 );
}
else{
//Code for curved planes, mostly taken 1:1 from imageVtkMapper2D and not tested yet.
// Do we have an AbstractTransformGeometry?
// This is the case for AbstractTransformGeometry's (e.g. a ThinPlateSplineCurvedGeometry )
const mitk::AbstractTransformGeometry* abstractGeometry =
dynamic_cast< const AbstractTransformGeometry * >(m_WorldGeometry);
if(abstractGeometry != NULL)
{
m_ResliceTransform = abstractGeometry;
extent[0] = abstractGeometry->GetParametricExtent(0);
extent[1] = abstractGeometry->GetParametricExtent(1);
widthInMM = abstractGeometry->GetParametricExtentInMM(0);
heightInMM = abstractGeometry->GetParametricExtentInMM(1);
m_OutPutSpacing[0] = widthInMM / extent[0];
m_OutPutSpacing[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
vtkSmartPointer<vtkGeneralTransform> composedResliceTransform = vtkSmartPointer<vtkGeneralTransform>::New();
composedResliceTransform->Identity();
composedResliceTransform->Concatenate(
inputTimeGeometry->GetGeometryForTimeStep( m_TimeStep )->GetVtkTransform()->GetLinearInverse() );
composedResliceTransform->Concatenate(
abstractGeometry->GetVtkAbstractTransform()
);
m_Reslicer->SetResliceTransform( composedResliceTransform );
// Set background level to BLACK instead of translucent, to avoid
- // boundary artifacts (see Geometry2DDataVtkMapper3D)
+ // boundary artifacts (see PlaneGeometryDataVtkMapper3D)
m_Reslicer->SetBackgroundLevel( -1023 );
}
else
{
itkExceptionMacro("mitk::ExtractSliceFilter: No fitting geometry for reslice axis!");
return;
}
}
if(m_ResliceTransform.IsNotNull()){
//if the resliceTransform is set the reslice axis are recalculated.
//Thus the geometry information is not fitting. Therefor a unitSpacingFilter
//is used to set up a global spacing of 1 and compensate the transform.
vtkSmartPointer<vtkImageChangeInformation> unitSpacingImageFilter = vtkSmartPointer<vtkImageChangeInformation>::New() ;
unitSpacingImageFilter->ReleaseDataFlagOn();
unitSpacingImageFilter->SetOutputSpacing( 1.0, 1.0, 1.0 );
unitSpacingImageFilter->SetInputData( input->GetVtkImageData(m_TimeStep) );
m_Reslicer->SetInputConnection(unitSpacingImageFilter->GetOutputPort() );
}
else
{
//if no tranform is set the image can be used directly
m_Reslicer->SetInputData(input->GetVtkImageData(m_TimeStep));
}
/*setup the plane where vktImageReslice extracts the slice*/
//ResliceAxesOrigin is the ancor point of the plane
double originInVtk[3];
itk2vtk(origin, originInVtk);
m_Reslicer->SetResliceAxesOrigin(originInVtk);
//the cosines define the plane: x and y are the direction vectors, n is the planes normal
//this specifies a matrix 3x3
// x1 y1 n1
// x2 y2 n2
// x3 y3 n3
double cosines[9];
vnl2vtk(right.GetVnlVector(), cosines);//x
vnl2vtk(bottom.GetVnlVector(), cosines + 3);//y
vnl2vtk(normal.GetVnlVector(), cosines + 6);//n
m_Reslicer->SetResliceAxesDirectionCosines(cosines);
//we only have one slice, not a volume
m_Reslicer->SetOutputDimensionality(m_OutputDimension);
//set the interpolation mode for slicing
switch(this->m_InterpolationMode){
case RESLICE_NEAREST:
m_Reslicer->SetInterpolationModeToNearestNeighbor();
break;
case RESLICE_LINEAR:
m_Reslicer->SetInterpolationModeToLinear();
break;
case RESLICE_CUBIC:
m_Reslicer->SetInterpolationModeToCubic();
break;
default:
//the default interpolation used by mitk
m_Reslicer->SetInterpolationModeToNearestNeighbor();
}
/*========== BEGIN setup extent of the slice ==========*/
int xMin, xMax, yMin, yMax;
xMin = yMin = 0;
xMax = static_cast< int >( extent[0]);
yMax = static_cast< int >( extent[1]);
double sliceBounds[6];
if (m_WorldGeometry->GetReferenceGeometry())
{
for ( int i = 0; i < 6; ++i )
{
sliceBounds[i] = 0.0;
}
if (this->GetClippedPlaneBounds( m_WorldGeometry->GetReferenceGeometry(), planeGeometry, sliceBounds ))
{
// Calculate output extent (integer values)
xMin = static_cast< int >( sliceBounds[0] / m_OutPutSpacing[0] + 0.5 );
xMax = static_cast< int >( sliceBounds[1] / m_OutPutSpacing[0] + 0.5 );
yMin = static_cast< int >( sliceBounds[2] / m_OutPutSpacing[1] + 0.5 );
yMax = static_cast< int >( sliceBounds[3] / m_OutPutSpacing[1] + 0.5 );
} // ELSE we use the default values
}
// Set the output extents! First included pixel index and last included pixel index
// xMax and yMax are one after the last pixel. so they have to be decremented by 1.
// In case we have a 2D image, xMax or yMax might be 0. in this case, do not decrement, but take 0.
m_Reslicer->SetOutputExtent(xMin, std::max(0, xMax-1), yMin, std::max(0, yMax-1), m_ZMin, m_ZMax );
/*========== END setup extent of the slice ==========*/
m_Reslicer->SetOutputOrigin( 0.0, 0.0, 0.0 );
m_Reslicer->SetOutputSpacing( m_OutPutSpacing[0], m_OutPutSpacing[1], m_ZSpacing );
//TODO check the following lines, they are responsible wether vtk error outputs appear or not
m_Reslicer->UpdateWholeExtent(); //this produces a bad allocation error for 2D images
//m_Reslicer->GetOutput()->UpdateInformation();
//m_Reslicer->GetOutput()->SetUpdateExtentToWholeExtent();
//start the pipeline
m_Reslicer->Update();
/*================ #END setup vtkImageRslice properties================*/
if(m_VtkOutputRequested){
return;
//no converting to mitk
//no mitk geometry will be set, as the output is vtkImageData only!!!
}
else
{
/*================ #BEGIN Get the slice from vtkImageReslice and convert it to mit::Image================*/
vtkImageData* reslicedImage;
reslicedImage = m_Reslicer->GetOutput();
if(!reslicedImage)
{
itkWarningMacro(<<"Reslicer returned empty image");
return;
}
mitk::Image::Pointer resultImage = this->GetOutput();
//initialize resultimage with the specs of the vtkImageData object returned from vtkImageReslice
if (reslicedImage->GetDataDimension() == 1)
{
// If original image was 2D, the slice might have an y extent of 0.
// Still i want to ensure here that Image is 2D
resultImage->Initialize(reslicedImage,1,-1,-1,1);
}
else
{
resultImage->Initialize(reslicedImage);
}
//transfer the voxel data
resultImage->SetVolume(reslicedImage->GetScalarPointer());
//set the geometry from current worldgeometry for the reusultimage
//this is needed that the image has the correct mitk geometry
//the originalGeometry is the Geometry of the result slice
// mitk::AffineGeometryFrame3D::Pointer originalGeometryAGF = m_WorldGeometry->Clone();
-// Geometry2D::Pointer originalGeometry = dynamic_cast<Geometry2D*>( originalGeometryAGF.GetPointer() );
- Geometry2D::Pointer originalGeometry = m_WorldGeometry->Clone();
+// PlaneGeometry::Pointer originalGeometry = dynamic_cast<PlaneGeometry*>( originalGeometryAGF.GetPointer() );
+ PlaneGeometry::Pointer originalGeometry = m_WorldGeometry->Clone();
originalGeometry->GetIndexToWorldTransform()->SetMatrix(m_WorldGeometry->GetIndexToWorldTransform()->GetMatrix());
//the origin of the worldGeometry is transformed to center based coordinates to be an imageGeometry
Point3D sliceOrigin = originalGeometry->GetOrigin();
sliceOrigin += right * ( m_OutPutSpacing[0] * 0.5 );
sliceOrigin += bottom * ( m_OutPutSpacing[1] * 0.5 );
//a worldGeometry is no imageGeometry, thus it is manually set to true
originalGeometry->ImageGeometryOn();
/*At this point we have to adjust the geometry because the origin isn't correct.
The wrong origin is related to the rotation of the current world geometry plane.
This causes errors on transfering world to index coordinates. We just shift the
origin in each direction about the amount of the expanding (needed while rotating
the plane).
*/
Vector3D axis0 = originalGeometry->GetAxisVector(0);
Vector3D axis1 = originalGeometry->GetAxisVector(1);
axis0.Normalize();
axis1.Normalize();
//adapt the origin. Note that for orthogonal planes the minima are '0' and thus the origin stays the same.
sliceOrigin += (axis0 * (xMin * m_OutPutSpacing[0])) + (axis1 * (yMin * m_OutPutSpacing[1]));
originalGeometry->SetOrigin(sliceOrigin);
originalGeometry->Modified();
resultImage->SetGeometry( originalGeometry );
/*the bounds as well as the extent of the worldGeometry are not adapted correctly during crosshair rotation.
This is only a quick fix and has to be evaluated.
The new bounds are set via the max values of the calcuted slice extent. It will look like [ 0, x, 0, y, 0, 1].
*/
mitk::BoundingBox::BoundsArrayType boundsCopy;
boundsCopy[0] = boundsCopy[2] = boundsCopy[4] = 0;
boundsCopy[5] = 1;
boundsCopy[1] = xMax - xMin;
boundsCopy[3] = yMax - yMin;
resultImage->GetGeometry()->SetBounds(boundsCopy);
/*================ #END Get the slice from vtkImageReslice and convert it to mitk Image================*/
}
}
bool mitk::ExtractSliceFilter::GetClippedPlaneBounds(double bounds[6]){
if(!m_WorldGeometry || !this->GetInput())
return false;
return this->GetClippedPlaneBounds(m_WorldGeometry->GetReferenceGeometry(), dynamic_cast< const PlaneGeometry * >( m_WorldGeometry ), bounds);
}
-bool mitk::ExtractSliceFilter::GetClippedPlaneBounds( const Geometry3D *boundingGeometry,
+bool mitk::ExtractSliceFilter::GetClippedPlaneBounds( const BaseGeometry *boundingGeometry,
const PlaneGeometry *planeGeometry, double *bounds )
{
bool b = mitk::PlaneClipping::CalculateClippedPlaneBounds(boundingGeometry, planeGeometry, bounds);
return b;
}
diff --git a/Core/Code/Algorithms/mitkExtractSliceFilter.h b/Core/Code/Algorithms/mitkExtractSliceFilter.h
index 9431a89d1b..9f6e1f75e9 100644
--- a/Core/Code/Algorithms/mitkExtractSliceFilter.h
+++ b/Core/Code/Algorithms/mitkExtractSliceFilter.h
@@ -1,175 +1,175 @@
/*===================================================================
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 mitkExtractSliceFilter_h_Included
#define mitkExtractSliceFilter_h_Included
#include "MitkCoreExports.h"
#include "mitkImageToImageFilter.h"
#include <vtkSmartPointer.h>
#include <vtkImageReslice.h>
#include <vtkMatrix4x4.h>
#include <vtkImageData.h>
#include <vtkPoints.h>
#include <vtkTransform.h>
#include <vtkAbstractTransform.h>
namespace mitk
{
/**
\brief ExtractSliceFilter extracts a 2D abitrary oriented slice from a 3D volume.
The filter can reslice in all orthogonal planes such as sagittal, coronal and axial,
and is also able to reslice a abitrary oriented oblique plane.
Curved planes are specified via an AbstractTransformGeometry as the input worldgeometry.
The convinient workflow is:
1. Set an image as input.
- 2. Set the worldGeometry2D. This defines a grid where the slice is being extracted
+ 2. Set the worldPlaneGeometry. This defines a grid where the slice is being extracted
3. And then start the pipeline.
There are a few more properties that can be set to modify the behavior of the slicing.
The properties are:
- interpolation mode either Nearestneighbor, Linear or Cubic.
- a transform this is a convinient way to adapt the reslice axis for the case
that the image is transformed e.g. rotated.
- time step the time step in a times volume.
- resample by geometry wether the resampling grid corresponds to the specs of the
worldgeometry or is directly derived from the input image
By default the properties are set to:
- interpolation mode Nearestneighbor.
- a transform NULL (No transform is set).
- time step 0.
- resample by geometry false (Corresponds to input image).
*/
class MITK_CORE_EXPORT ExtractSliceFilter : public ImageToImageFilter
{
public:
mitkClassMacro(ExtractSliceFilter, ImageToImageFilter);
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
mitkNewMacro1Param(Self, vtkImageReslice*);
/** \brief Set the axis where to reslice at.*/
- void SetWorldGeometry(const Geometry2D* geometry ){
+ void SetWorldGeometry(const PlaneGeometry* geometry ){
this->m_WorldGeometry = geometry;
this->Modified(); }
/** \brief Set the time step in the 4D volume */
void SetTimeStep( unsigned int timestep){ this->m_TimeStep = timestep; }
unsigned int GetTimeStep(){ return this->m_TimeStep; }
/** \brief Set a transform for the reslice axes.
* This transform is needed if the image volume itself is transformed. (Effects the reslice axis)
*/
- void SetResliceTransformByGeometry(const Geometry3D* transform){ this->m_ResliceTransform = transform; }
+ void SetResliceTransformByGeometry(const BaseGeometry* transform){ this->m_ResliceTransform = transform; }
/** \brief Resampling grid corresponds to: false->image true->worldgeometry*/
void SetInPlaneResampleExtentByGeometry(bool inPlaneResampleExtentByGeometry){ this->m_InPlaneResampleExtentByGeometry = inPlaneResampleExtentByGeometry; }
/** \brief Sets the output dimension of the slice*/
void SetOutputDimensionality(unsigned int dimension){ this->m_OutputDimension = dimension; }
/** \brief Set the spacing in z direction manually.
* Required if the outputDimension is > 2.
*/
void SetOutputSpacingZDirection(double zSpacing){ this->m_ZSpacing = zSpacing; }
/** \brief Set the extent in pixel for direction z manualy.
Required if the output dimension is > 2.
*/
void SetOutputExtentZDirection(int zMin, int zMax) { this->m_ZMin = zMin; this->m_ZMax = zMax; }
/** \brief Get the bounding box of the slice [xMin, xMax, yMin, yMax, zMin, zMax]
* The method uses the input of the filter to calculate the bounds.
* It is recommended to use
- * GetClippedPlaneBounds(const Geometry3D*, const PlaneGeometry*, double*)
+ * GetClippedPlaneBounds(const BaseGeometry*, const PlaneGeometry*, double*)
* if you are not sure about the input.
*/
bool GetClippedPlaneBounds(double bounds[6]);
/** \brief Get the bounding box of the slice [xMin, xMax, yMin, yMax, zMin, zMax]*/
- bool GetClippedPlaneBounds( const Geometry3D *boundingGeometry,
+ bool GetClippedPlaneBounds( const BaseGeometry *boundingGeometry,
const PlaneGeometry *planeGeometry, double *bounds );
/** \brief Get the spacing of the slice. returns mitk::ScalarType[2] */
mitk::ScalarType* GetOutputSpacing();
/** \brief Get Output as vtkImageData.
* Note:
* SetVtkOutputRequest(true) has to be called at least once before
* GetVtkOutput(). Otherwise the output is empty for the first update step.
*/
vtkImageData* GetVtkOutput(){ m_VtkOutputRequested = true; return m_Reslicer->GetOutput(); }
/** Set VtkOutPutRequest to suppress the convertion of the image.
* It is suggested to use this with GetVtkOutput().
* Note:
* SetVtkOutputRequest(true) has to be called at least once before
* GetVtkOutput(). Otherwise the output is empty for the first update step.
*/
void SetVtkOutputRequest(bool isRequested){ m_VtkOutputRequested = isRequested; }
/** \brief Get the reslices axis matrix.
* Note: the axis are recalculated when calling SetResliceTransformByGeometry.
*/
vtkMatrix4x4* GetResliceAxes(){
return this->m_Reslicer->GetResliceAxes();
}
enum ResliceInterpolation { RESLICE_NEAREST=0, RESLICE_LINEAR=1, RESLICE_CUBIC=3 };
void SetInterpolationMode( ExtractSliceFilter::ResliceInterpolation interpolation){ this->m_InterpolationMode = interpolation; }
protected:
ExtractSliceFilter(vtkImageReslice* reslicer = NULL);
virtual ~ExtractSliceFilter();
virtual void GenerateData();
virtual void GenerateOutputInformation();
virtual void GenerateInputRequestedRegion();
- const Geometry2D* m_WorldGeometry;
+ const PlaneGeometry* m_WorldGeometry;
vtkSmartPointer<vtkImageReslice> m_Reslicer;
unsigned int m_TimeStep;
unsigned int m_OutputDimension;
double m_ZSpacing;
int m_ZMin;
int m_ZMax;
ResliceInterpolation m_InterpolationMode;
- Geometry3D::ConstPointer m_ResliceTransform;
+ BaseGeometry::ConstPointer m_ResliceTransform;
bool m_InPlaneResampleExtentByGeometry;//Resampling grid corresponds to: false->image true->worldgeometry
mitk::ScalarType* m_OutPutSpacing;
bool m_VtkOutputRequested;
};
}
#endif // mitkExtractSliceFilter_h_Included
diff --git a/Core/Code/Algorithms/mitkGeometry2DDataToSurfaceFilter.h b/Core/Code/Algorithms/mitkGeometry2DDataToSurfaceFilter.h
deleted file mode 100644
index 3a44adb4fd..0000000000
--- a/Core/Code/Algorithms/mitkGeometry2DDataToSurfaceFilter.h
+++ /dev/null
@@ -1,228 +0,0 @@
-/*===================================================================
-
-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 MITKGEOMETRY2DDATATOSURFACEDATAFILTER_H_HEADER_INCLUDED_C10B22CD
-#define MITKGEOMETRY2DDATATOSURFACEDATAFILTER_H_HEADER_INCLUDED_C10B22CD
-
-#include "mitkSurfaceSource.h"
-#include "mitkGeometry3D.h"
-#include "vtkSystemIncludes.h"
-
-class vtkPlaneSource;
-class vtkTransformPolyDataFilter;
-class vtkCubeSource;
-class vtkTransform;
-class vtkPlane;
-class vtkCutter;
-class vtkStripper;
-class vtkPolyData;
-class vtkPPolyDataNormals;
-class vtkTriangleFilter;
-class vtkTextureMapToPlane;
-class vtkBox;
-class vtkClipPolyData;
-
-namespace mitk {
-
-class Geometry2DData;
-
-/** \brief Superclass of all classes having a Geometry2DData as input and
- * generating Images as output
- *
- * Currently implemented for PlaneGeometry and AbstractTransformGeometry.
- * Currently, this class does not really have subclasses, but does the job
- * for itself. It checks which kind of Geometry2D is stored in the
- * Geometry2DData and - if it knows how - it generates the respective
- * Surface. Of course, this has the disadvantage that for any new type of
- * Geometry2D this class (Geometry2DDataToSurfaceFilter) has to be
- * changed/extended. The idea is to move the type specific generation code in
- * subclasses, and internally (within this class) use a factory to create an
- * instance of the required subclass and delegate the surface generation to
- * it.
- *
- * \sa mitk::DeformablePlane
- * \todo make extension easier
- * \ingroup Process
- */
-class MITK_CORE_EXPORT Geometry2DDataToSurfaceFilter : public SurfaceSource
-{
- public:
- mitkClassMacro(Geometry2DDataToSurfaceFilter, SurfaceSource);
- itkFactorylessNewMacro(Self)
- itkCloneMacro(Self)
-
- virtual void GenerateOutputInformation();
-
- virtual void GenerateData();
-
- const Geometry2DData *GetInput(void);
- const Geometry2DData *GetInput(unsigned int idx);
-
- virtual void SetInput(const Geometry2DData *image);
- using itk::ProcessObject::SetInput;
- virtual void SetInput(unsigned int index, const Geometry2DData *image);
-
- /** \brief If \a true (default), use Geometry3D::GetParametricBounds() to define the resolution in parameter space,
- * otherwise use m_XResolution and m_YResolution
- */
- itkGetMacro(UseGeometryParametricBounds, bool);
- /** \brief If \a true (default), use Geometry3D::GetParametricBounds() to define the resolution in parameter space,
- * otherwise use m_XResolution and m_YResolution
- */
- itkSetMacro(UseGeometryParametricBounds, bool);
-
- /** \brief Get x-resolution in parameter space
- *
- * The m_PlaneSource will create this many sub-rectangles
- * in x-direction (see vtkPlaneSource::SetXResolution)
- * \note Only used, when GetUseGeometryParametricBounds() is \a false, otherwise the
- * the x-bounds of Geometry3D::GetParametricBounds() are used.
- * \sa m_XResolution
- */
- itkGetMacro(XResolution, int);
- /** \brief Set x-resolution in parameter space
- *
- * The m_PlaneSource will create this many sub-rectangles
- * in x-direction (see vtkPlaneSource::SetXResolution)
- * \note Only used, when GetUseGeometryParametricBounds() is \a false, otherwise the
- * the x-bounds of Geometry3D::GetParametricBounds() are used.
- * \sa m_XResolution
- */
- itkSetMacro(XResolution, int);
-
- /** \brief Get y-resolution in parameter space
- *
- * The m_PlaneSource will create this many sub-rectangles
- * in y-direction (see vtkPlaneSource::SetYResolution)
- * \note Only used, when GetUseGeometryParametricBounds() is \a false, otherwise the
- * the y-bounds of Geometry3D::GetParametricBounds() are used.
- * \sa m_YResolution
- */
- itkGetMacro(YResolution, int);
-
- /** \brief Set y-resolution in parameter space
- *
- * The m_PlaneSource will create this many sub-rectangles
- * in y-direction (see vtkPlaneSource::SetYResolution)
- * \note Only used, when GetUseGeometryParametricBounds() is \a false, otherwise the
- * the y-bounds of Geometry3D::GetParametricBounds() are used.
- * \sa m_YResolution
- */
- itkSetMacro(YResolution, int);
-
- /** \brief Get whether the Surface is at the origin and placed using the Geometry
- *
- * Default is \a false, i.e., the transform of the Geometry is the identity, thus
- * the points within the Surface are at their final position. Otherwise
- * (m_PlaceByGeometry==\a true), the first cornerpoint of the created Surface is
- * at the origin and the actual position is determined by the transform of the
- * Geometry.
- * \sa m_PlaceByGeometry
- */
- itkGetConstMacro(PlaceByGeometry, bool);
-
- /** \brief Set whether the Surface is at the origin and placed using the Geometry
- *
- * Default is \a false, i.e., the transform of the Geometry is the identity, thus
- * the points within the Surface are at their final position. Otherwise
- * (m_PlaceByGeometry==\a true), the first cornerpoint of the created Surface is
- * at the origin and the actual position is determined by the transform of the
- * Geometry.
- * \sa m_PlaceByGeometry
- */
- itkSetMacro(PlaceByGeometry, bool);
- itkBooleanMacro(PlaceByGeometry);
-
- itkGetConstMacro( UseBoundingBox, bool );
- itkSetMacro( UseBoundingBox, bool );
- itkBooleanMacro( UseBoundingBox );
-
- void SetBoundingBox( const BoundingBox *boundingBox );
- const BoundingBox *GetBoundingBox() const;
-
- protected:
-
- Geometry2DDataToSurfaceFilter();
-
- virtual ~Geometry2DDataToSurfaceFilter();
-
- /** \brief Source to create the vtk-representation of the parameter space rectangle of the Geometry2D
- */
- vtkPlaneSource* m_PlaneSource;
-
- /** \brief Filter to create the vtk-representation of the Geometry2D, which is a
- * transformation of the m_PlaneSource
- */
- vtkTransformPolyDataFilter* m_VtkTransformPlaneFilter;
-
- /** \brief If \a true, use Geometry3D::GetParametricBounds() to define the resolution in parameter space,
- * otherwise use m_XResolution and m_YResolution
- */
- bool m_UseGeometryParametricBounds;
-
- /** \brief X-resolution in parameter space
- *
- * The m_PlaneSource will create this many sub-rectangles
- * in x-direction (see vtkPlaneSource::SetXResolution)
- * \note Only used, when GetUseGeometryParametricBounds() is \a false, otherwise the
- * the x-bounds of Geometry3D::GetParametricBounds() are used.
- * \sa m_XResolution
- */
- int m_XResolution;
-
- /** \brief Y-resolution in parameter space
- *
- * The m_PlaneSource will create this many sub-rectangles
- * in y-direction (see vtkPlaneSource::SetYResolution)
- * \note Only used, when GetUseGeometryParametricBounds() is \a false, otherwise the
- * the y-bounds of Geometry3D::GetParametricBounds() are used.
- */
- int m_YResolution;
-
- /** \brief Define whether the Surface is at the origin and placed using the Geometry
- *
- * Default is \a false, i.e., the transform of the Geometry is the identity, thus
- * the points within the Surface are at their final position. Otherwise
- * (m_PlaceByGeometry==\a true), the first cornerpoint of the created Surface is
- * at the origin and the actual position is determined by the transform of the
- * Geometry.
- */
- bool m_PlaceByGeometry;
-
- bool m_UseBoundingBox;
-
- BoundingBox::ConstPointer m_BoundingBox;
-
- vtkCubeSource *m_CubeSource;
- vtkTransform *m_Transform;
- vtkTransformPolyDataFilter *m_PolyDataTransformer;
-
- vtkPlane *m_Plane;
- vtkCutter *m_PlaneCutter;
- vtkStripper *m_PlaneStripper;
- vtkPolyData *m_PlanePolyData;
- vtkPPolyDataNormals * m_NormalsUpdater;
- vtkTriangleFilter *m_PlaneTriangler;
- vtkTextureMapToPlane *m_TextureMapToPlane;
-
- vtkBox *m_Box;
- vtkClipPolyData *m_PlaneClipper;
-};
-
-} // namespace mitk
-
-#endif /* MITKGEOMETRY2DDATATOSURFACEDATAFILTER_H_HEADER_INCLUDED_C10B22CD */
diff --git a/Core/Code/Algorithms/mitkImageSliceSelector.cpp b/Core/Code/Algorithms/mitkImageSliceSelector.cpp
index d8d62f30d2..173c1c99ac 100644
--- a/Core/Code/Algorithms/mitkImageSliceSelector.cpp
+++ b/Core/Code/Algorithms/mitkImageSliceSelector.cpp
@@ -1,77 +1,77 @@
/*===================================================================
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 "mitkImageSliceSelector.h"
void mitk::ImageSliceSelector::GenerateOutputInformation()
{
mitk::Image::ConstPointer input = this->GetInput();
mitk::Image::Pointer output = this->GetOutput();
itkDebugMacro(<<"GenerateOutputInformation()");
output->Initialize(input->GetPixelType(), 2, input->GetDimensions());
if( (unsigned int)m_SliceNr >= input->GetDimension(2) )
{
m_SliceNr = input->GetDimension(2)-1;
}
if( (unsigned int)m_TimeNr >= input->GetDimension(3) )
{
m_TimeNr = input->GetDimension(3)-1;
}
// initialize geometry
- output->SetGeometry(dynamic_cast<Geometry3D*>(input->GetSlicedGeometry(m_TimeNr)->GetGeometry2D(m_SliceNr)->Clone().GetPointer()));
+ output->SetGeometry(dynamic_cast<BaseGeometry*>(input->GetSlicedGeometry(m_TimeNr)->GetPlaneGeometry(m_SliceNr)->Clone().GetPointer()));
output->SetPropertyList(input->GetPropertyList()->Clone());
}
void mitk::ImageSliceSelector::GenerateData()
{
SetSliceItem(GetSliceData(m_SliceNr, m_TimeNr, m_ChannelNr), 0);
}
mitk::ImageSliceSelector::ImageSliceSelector() : m_SliceNr(0), m_TimeNr(0), m_ChannelNr(0)
{
}
mitk::ImageSliceSelector::~ImageSliceSelector()
{
}
void mitk::ImageSliceSelector::GenerateInputRequestedRegion()
{
Superclass::GenerateInputRequestedRegion();
mitk::ImageToImageFilter::InputImagePointer input =
const_cast< mitk::ImageToImageFilter::InputImageType * > ( this->GetInput() );
mitk::Image::Pointer output = this->GetOutput();
Image::RegionType requestedRegion;
requestedRegion = output->GetRequestedRegion();
requestedRegion.SetIndex(2, m_SliceNr);
requestedRegion.SetIndex(3, m_TimeNr);
requestedRegion.SetIndex(4, m_ChannelNr);
requestedRegion.SetSize(2, 1);
requestedRegion.SetSize(3, 1);
requestedRegion.SetSize(4, 1);
input->SetRequestedRegion( & requestedRegion );
}
diff --git a/Core/Code/Algorithms/mitkImageTimeSelector.cpp b/Core/Code/Algorithms/mitkImageTimeSelector.cpp
index 57a8952a17..8cbd73a08e 100644
--- a/Core/Code/Algorithms/mitkImageTimeSelector.cpp
+++ b/Core/Code/Algorithms/mitkImageTimeSelector.cpp
@@ -1,99 +1,99 @@
/*===================================================================
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 "mitkImageTimeSelector.h"
mitk::ImageTimeSelector::ImageTimeSelector() : m_TimeNr(0), m_ChannelNr(0)
{
}
mitk::ImageTimeSelector::~ImageTimeSelector()
{
}
void mitk::ImageTimeSelector::GenerateOutputInformation()
{
Image::ConstPointer input = this->GetInput();
Image::Pointer output = this->GetOutput();
itkDebugMacro(<<"GenerateOutputInformation()");
int dim=(input->GetDimension()<3?input->GetDimension():3);
output->Initialize(input->GetPixelType(), dim, input->GetDimensions());
if( (unsigned int) m_TimeNr >= input->GetDimension(3) )
{
m_TimeNr = input->GetDimension(3)-1;
}
// initialize geometry
mitk::SlicedGeometry3D::Pointer sliced_geo = input->GetSlicedGeometry(m_TimeNr);
if( sliced_geo.IsNull() )
{
mitkThrow() << "Failed to retrieve SlicedGeometry from input at timestep " << m_TimeNr;
}
mitk::SlicedGeometry3D::Pointer sliced_geo_clone = sliced_geo->Clone();
if( sliced_geo_clone.IsNull() )
{
mitkThrow() << "Failed to clone the retrieved sliced geometry.";
}
- mitk::Geometry3D::Pointer geom_3d = dynamic_cast<Geometry3D*>(sliced_geo_clone.GetPointer());
+ mitk::BaseGeometry::Pointer geom_3d = dynamic_cast<BaseGeometry*>(sliced_geo_clone.GetPointer());
if( geom_3d.IsNotNull() )
{
output->SetGeometry(geom_3d.GetPointer() );
}
else
{
mitkThrow() << "Failed to cast the retrieved SlicedGeometry to a Geometry3D object.";
}
output->SetPropertyList(input->GetPropertyList()->Clone());
}
void mitk::ImageTimeSelector::GenerateData()
{
const Image::RegionType& requestedRegion = this->GetOutput()->GetRequestedRegion();
//do we really need a complete volume at a time?
if(requestedRegion.GetSize(2)>1)
this->SetVolumeItem( this->GetVolumeData(m_TimeNr, m_ChannelNr), 0 );
else
//no, so take just a slice!
this->SetSliceItem( this->GetSliceData(requestedRegion.GetIndex(2), m_TimeNr, m_ChannelNr), requestedRegion.GetIndex(2), 0 );
}
void mitk::ImageTimeSelector::GenerateInputRequestedRegion()
{
Superclass::GenerateInputRequestedRegion();
ImageToImageFilter::InputImagePointer input =
const_cast< mitk::ImageToImageFilter::InputImageType * > ( this->GetInput() );
Image::Pointer output = this->GetOutput();
Image::RegionType requestedRegion;
requestedRegion = output->GetRequestedRegion();
requestedRegion.SetIndex(3, m_TimeNr);
requestedRegion.SetIndex(4, m_ChannelNr);
requestedRegion.SetSize(3, 1);
requestedRegion.SetSize(4, 1);
input->SetRequestedRegion( & requestedRegion );
}
diff --git a/Core/Code/Algorithms/mitkPlaneClipping.h b/Core/Code/Algorithms/mitkPlaneClipping.h
index 256fbcd8c1..047976bafb 100644
--- a/Core/Code/Algorithms/mitkPlaneClipping.h
+++ b/Core/Code/Algorithms/mitkPlaneClipping.h
@@ -1,141 +1,141 @@
/*===================================================================
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 MITKPLANECLIPPING_H_HEADER_INCLUDED
#define MITKPLANECLIPPING_H_HEADER_INCLUDED
#include <vtkPoints.h>
#include <mitkGeometry3D.h>
#include <mitkPlaneGeometry.h>
#include <vtkTransform.h>
namespace mitk {
namespace PlaneClipping {
/** \brief Internal helper method for intersection testing used only in CalculateClippedPlaneBounds() */
static bool LineIntersectZero( vtkPoints *points, int p1, int p2, double *bounds )
{
double point1[3];
double 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;
}
/** \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. */
-static bool CalculateClippedPlaneBounds( const Geometry3D *boundingGeometry, const PlaneGeometry *planeGeometry, double *bounds )
+static bool CalculateClippedPlaneBounds( const BaseGeometry *boundingGeometry, const PlaneGeometry *planeGeometry, double *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<vtkPoints> points = vtkSmartPointer<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] );
}
vtkSmartPointer<vtkPoints> newPoints = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<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;
LineIntersectZero( newPoints, 0, 1, bounds );
LineIntersectZero( newPoints, 1, 2, bounds );
LineIntersectZero( newPoints, 2, 3, bounds );
LineIntersectZero( newPoints, 3, 0, bounds );
LineIntersectZero( newPoints, 0, 4, bounds );
LineIntersectZero( newPoints, 1, 5, bounds );
LineIntersectZero( newPoints, 2, 6, bounds );
LineIntersectZero( newPoints, 3, 7, bounds );
LineIntersectZero( newPoints, 4, 5, bounds );
LineIntersectZero( newPoints, 5, 6, bounds );
LineIntersectZero( newPoints, 6, 7, bounds );
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();
+ const mitk::Vector3D planeSpacing = planeGeometry->GetSpacing();
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;
}
}
}
}
#endif
diff --git a/Core/Code/Algorithms/mitkGeometry2DDataToSurfaceFilter.cpp b/Core/Code/Algorithms/mitkPlaneGeometryDataToSurfaceFilter.cpp
similarity index 87%
rename from Core/Code/Algorithms/mitkGeometry2DDataToSurfaceFilter.cpp
rename to Core/Code/Algorithms/mitkPlaneGeometryDataToSurfaceFilter.cpp
index fb1251d18d..a4d5df2f1d 100644
--- a/Core/Code/Algorithms/mitkGeometry2DDataToSurfaceFilter.cpp
+++ b/Core/Code/Algorithms/mitkPlaneGeometryDataToSurfaceFilter.cpp
@@ -1,447 +1,447 @@
/*===================================================================
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 "mitkGeometry2DDataToSurfaceFilter.h"
+#include "mitkPlaneGeometryDataToSurfaceFilter.h"
#include "mitkSurface.h"
#include "mitkGeometry3D.h"
-#include "mitkGeometry2DData.h"
+#include "mitkPlaneGeometryData.h"
#include "mitkPlaneGeometry.h"
#include "mitkAbstractTransformGeometry.h"
#include <vtkPolyData.h>
#include <vtkPlaneSource.h>
#include <vtkTransformPolyDataFilter.h>
#include <vtkCubeSource.h>
#include <vtkTransformPolyDataFilter.h>
#include <vtkTransform.h>
#include <vtkGeneralTransform.h>
#include <vtkPlane.h>
#include <vtkPPolyDataNormals.h>
#include <vtkCutter.h>
#include <vtkStripper.h>
#include <vtkTriangleFilter.h>
#include <vtkBox.h>
#include <vtkClipPolyData.h>
#include <vtkTextureMapToPlane.h>
-mitk::Geometry2DDataToSurfaceFilter::Geometry2DDataToSurfaceFilter()
+mitk::PlaneGeometryDataToSurfaceFilter::PlaneGeometryDataToSurfaceFilter()
: m_UseGeometryParametricBounds( true ), m_XResolution( 10 ),
m_YResolution( 10 ), m_PlaceByGeometry( false ), m_UseBoundingBox( false )
{
m_PlaneSource = vtkPlaneSource::New();
m_Transform = vtkTransform::New();
m_CubeSource = vtkCubeSource::New();
m_PolyDataTransformer = vtkTransformPolyDataFilter::New();
m_Plane = vtkPlane::New();
m_PlaneCutter = vtkCutter::New();
m_PlaneStripper = vtkStripper::New();
m_PlanePolyData = vtkPolyData::New();
m_NormalsUpdater = vtkPPolyDataNormals::New();
m_PlaneTriangler = vtkTriangleFilter::New();
m_TextureMapToPlane = vtkTextureMapToPlane::New();
m_Box = vtkBox::New();
m_PlaneClipper = vtkClipPolyData::New();
m_VtkTransformPlaneFilter = vtkTransformPolyDataFilter::New();
m_VtkTransformPlaneFilter->SetInputConnection(m_PlaneSource->GetOutputPort() );
}
-mitk::Geometry2DDataToSurfaceFilter::~Geometry2DDataToSurfaceFilter()
+mitk::PlaneGeometryDataToSurfaceFilter::~PlaneGeometryDataToSurfaceFilter()
{
m_PlaneSource->Delete();
m_Transform->Delete();
m_CubeSource->Delete();
m_PolyDataTransformer->Delete();
m_Plane->Delete();
m_PlaneCutter->Delete();
m_PlaneStripper->Delete();
m_PlanePolyData->Delete();
m_NormalsUpdater->Delete();
m_PlaneTriangler->Delete();
m_TextureMapToPlane->Delete();
m_Box->Delete();
m_PlaneClipper->Delete();
m_VtkTransformPlaneFilter->Delete();
}
-void mitk::Geometry2DDataToSurfaceFilter::GenerateOutputInformation()
+void mitk::PlaneGeometryDataToSurfaceFilter::GenerateOutputInformation()
{
- mitk::Geometry2DData::ConstPointer input = this->GetInput();
+ mitk::PlaneGeometryData::ConstPointer input = this->GetInput();
mitk::Surface::Pointer output = this->GetOutput();
- if ( input.IsNull() || (input->GetGeometry2D() == NULL)
- || (input->GetGeometry2D()->IsValid() == false)
+ if ( input.IsNull() || (input->GetPlaneGeometry() == NULL)
+ || (input->GetPlaneGeometry()->IsValid() == false)
|| (m_UseBoundingBox && (m_BoundingBox.IsNull() || (m_BoundingBox->GetDiagonalLength2() < mitk::eps))) )
{
return;
}
Point3D origin;
Point3D right, bottom;
vtkPolyData *planeSurface = NULL;
- // Does the Geometry2DData contain a PlaneGeometry?
- if ( dynamic_cast< PlaneGeometry * >( input->GetGeometry2D() ) != NULL )
+ // Does the PlaneGeometryData contain a PlaneGeometry?
+ if ( dynamic_cast< PlaneGeometry * >( input->GetPlaneGeometry() ) != NULL )
{
mitk::PlaneGeometry *planeGeometry =
- dynamic_cast< PlaneGeometry * >( input->GetGeometry2D() );
+ dynamic_cast< PlaneGeometry * >( input->GetPlaneGeometry() );
if ( m_PlaceByGeometry )
{
// Let the output use the input geometry to appropriately transform the
// coordinate system.
mitk::Geometry3D::TransformType *affineTransform =
planeGeometry->GetIndexToWorldTransform();
TimeGeometry *timeGeometry = output->GetTimeGeometry();
- Geometry3D *geometrie3d = timeGeometry->GetGeometryForTimeStep( 0 );
+ BaseGeometry *geometrie3d = timeGeometry->GetGeometryForTimeStep( 0 );
geometrie3d->SetIndexToWorldTransform( affineTransform );
}
if ( !m_UseBoundingBox)
{
// We do not have a bounding box, so no clipping is required.
if ( m_PlaceByGeometry )
{
// Derive coordinate axes and origin from input geometry extent
origin.Fill( 0.0 );
FillVector3D( right, planeGeometry->GetExtent(0), 0.0, 0.0 );
FillVector3D( bottom, 0.0, planeGeometry->GetExtent(1), 0.0 );
}
else
{
// Take the coordinate axes and origin directly from the input geometry.
origin = planeGeometry->GetOrigin();
right = planeGeometry->GetCornerPoint( false, true );
bottom = planeGeometry->GetCornerPoint( true, false );
}
// Since the plane is planar, there is no need to subdivide the grid
// (cf. AbstractTransformGeometry case)
m_PlaneSource->SetXResolution( 1 );
m_PlaneSource->SetYResolution( 1 );
m_PlaneSource->SetOrigin( origin[0], origin[1], origin[2] );
m_PlaneSource->SetPoint1( right[0], right[1], right[2] );
m_PlaneSource->SetPoint2( bottom[0], bottom[1], bottom[2] );
m_PlaneSource->Update();
planeSurface = m_PlaneSource->GetOutput();
}
else
{
// Set up a cube with the extent and origin of the bounding box. This
// cube will be clipped by a plane later on. The intersection of the
// cube and the plane will be the surface we are interested in. Note
// that the bounding box needs to be explicitly specified by the user
// of this class, since it is not necessarily clear from the data
// available herein which bounding box to use. In most cases, this
// would be the bounding box of the input geometry's reference
// geometry, but this is not an inevitable requirement.
mitk::BoundingBox::PointType boundingBoxMin = m_BoundingBox->GetMinimum();
mitk::BoundingBox::PointType boundingBoxMax = m_BoundingBox->GetMaximum();
mitk::BoundingBox::PointType boundingBoxCenter = m_BoundingBox->GetCenter();
m_CubeSource->SetXLength( boundingBoxMax[0] - boundingBoxMin[0] );
m_CubeSource->SetYLength( boundingBoxMax[1] - boundingBoxMin[1] );
m_CubeSource->SetZLength( boundingBoxMax[2] - boundingBoxMin[2] );
m_CubeSource->SetCenter(
boundingBoxCenter[0],
boundingBoxCenter[1],
boundingBoxCenter[2] );
// Now we have to transform the cube, so that it will cut our plane
// appropriately. (As can be seen below, the plane corresponds to the
// z-plane in the coordinate system and is *not* transformed.) Therefore,
// we get the inverse of the plane geometry's transform and concatenate
// it with the transform of the reference geometry, if available.
m_Transform->Identity();
m_Transform->Concatenate(
planeGeometry->GetVtkTransform()->GetLinearInverse()
);
- Geometry3D *referenceGeometry = planeGeometry->GetReferenceGeometry();
+ BaseGeometry *referenceGeometry = planeGeometry->GetReferenceGeometry();
if ( referenceGeometry )
{
m_Transform->Concatenate(
referenceGeometry->GetVtkTransform()
);
}
// Transform the cube accordingly (s.a.)
m_PolyDataTransformer->SetInputConnection( m_CubeSource->GetOutputPort() );
m_PolyDataTransformer->SetTransform( m_Transform );
// Initialize the plane to clip the cube with, as lying on the z-plane
m_Plane->SetOrigin( 0.0, 0.0, 0.0 );
m_Plane->SetNormal( 0.0, 0.0, 1.0 );
// Cut the plane with the cube.
m_PlaneCutter->SetInputConnection( m_PolyDataTransformer->GetOutputPort() );
m_PlaneCutter->SetCutFunction( m_Plane );
// The output of the cutter must be converted into appropriate poly data.
m_PlaneStripper->SetInputConnection( m_PlaneCutter->GetOutputPort() );
m_PlaneStripper->Update();
if ( m_PlaneStripper->GetOutput()->GetNumberOfPoints() < 3 )
{
return;
}
m_PlanePolyData->SetPoints( m_PlaneStripper->GetOutput()->GetPoints() );
m_PlanePolyData->SetPolys( m_PlaneStripper->GetOutput()->GetLines() );
m_PlaneTriangler->SetInputData( m_PlanePolyData );
// Get bounds of the resulting surface and use it to generate the texture
// mapping information
m_PlaneTriangler->Update();
m_PlaneTriangler->GetOutput()->ComputeBounds();
double *surfaceBounds =
m_PlaneTriangler->GetOutput()->GetBounds();
origin[0] = surfaceBounds[0];
origin[1] = surfaceBounds[2];
origin[2] = surfaceBounds[4];
right[0] = surfaceBounds[1];
right[1] = surfaceBounds[2];
right[2] = surfaceBounds[4];
bottom[0] = surfaceBounds[0];
bottom[1] = surfaceBounds[3];
bottom[2] = surfaceBounds[4];
// Now we tell the data how it shall be textured afterwards;
// description see above.
m_TextureMapToPlane->SetInputConnection( m_PlaneTriangler->GetOutputPort() );
m_TextureMapToPlane->AutomaticPlaneGenerationOn();
m_TextureMapToPlane->SetOrigin( origin[0], origin[1], origin[2] );
m_TextureMapToPlane->SetPoint1( right[0], right[1], right[2] );
m_TextureMapToPlane->SetPoint2( bottom[0], bottom[1], bottom[2] );
// Need to call update so that output data and bounds are immediately
// available
m_TextureMapToPlane->Update();
// Return the output of this generation process
planeSurface = dynamic_cast< vtkPolyData * >(
m_TextureMapToPlane->GetOutput()
);
}
}
- // Does the Geometry2DData contain an AbstractTransformGeometry?
+ // Does the PlaneGeometryData contain an AbstractTransformGeometry?
else if ( mitk::AbstractTransformGeometry *abstractGeometry =
- dynamic_cast< AbstractTransformGeometry * >( input->GetGeometry2D() ) )
+ dynamic_cast< AbstractTransformGeometry * >( input->GetPlaneGeometry() ) )
{
// In the case of an AbstractTransformGeometry (which holds a possibly
// non-rigid transform), we proceed slightly differently: since the
// plane can be arbitrarily deformed, we need to transform it by the
// abstract transform before clipping it. The setup for this is partially
// done in the constructor.
origin = abstractGeometry->GetPlane()->GetOrigin();
right = origin + abstractGeometry->GetPlane()->GetAxisVector( 0 );
bottom = origin + abstractGeometry->GetPlane()->GetAxisVector( 1 );
// Define the plane
m_PlaneSource->SetOrigin( origin[0], origin[1], origin[2] );
m_PlaneSource->SetPoint1( right[0], right[1], right[2] );
m_PlaneSource->SetPoint2( bottom[0], bottom[1], bottom[2] );
// Set the plane's resolution (unlike for non-deformable planes, the plane
// grid needs to have a certain resolution so that the deformation has the
// desired effect).
if ( m_UseGeometryParametricBounds )
{
m_PlaneSource->SetXResolution(
(int)abstractGeometry->GetParametricExtent(0)
);
m_PlaneSource->SetYResolution(
(int)abstractGeometry->GetParametricExtent(1)
);
}
else
{
m_PlaneSource->SetXResolution( m_XResolution );
m_PlaneSource->SetYResolution( m_YResolution );
}
if ( m_PlaceByGeometry )
{
// Let the output use the input geometry to appropriately transform the
// coordinate system.
mitk::Geometry3D::TransformType *affineTransform =
abstractGeometry->GetIndexToWorldTransform();
TimeGeometry *timeGeometry = output->GetTimeGeometry();
- Geometry3D *g3d = timeGeometry->GetGeometryForTimeStep( 0 );
+ BaseGeometry *g3d = timeGeometry->GetGeometryForTimeStep( 0 );
g3d->SetIndexToWorldTransform( affineTransform );
vtkGeneralTransform *composedResliceTransform = vtkGeneralTransform::New();
composedResliceTransform->Identity();
composedResliceTransform->Concatenate(
abstractGeometry->GetVtkTransform()->GetLinearInverse() );
composedResliceTransform->Concatenate(
abstractGeometry->GetVtkAbstractTransform()
);
// Use the non-rigid transform for transforming the plane.
m_VtkTransformPlaneFilter->SetTransform(
composedResliceTransform
);
}
else
{
// Use the non-rigid transform for transforming the plane.
m_VtkTransformPlaneFilter->SetTransform(
abstractGeometry->GetVtkAbstractTransform()
);
}
if ( m_UseBoundingBox )
{
mitk::BoundingBox::PointType boundingBoxMin = m_BoundingBox->GetMinimum();
mitk::BoundingBox::PointType boundingBoxMax = m_BoundingBox->GetMaximum();
//mitk::BoundingBox::PointType boundingBoxCenter = m_BoundingBox->GetCenter();
m_Box->SetXMin( boundingBoxMin[0], boundingBoxMin[1], boundingBoxMin[2] );
m_Box->SetXMax( boundingBoxMax[0], boundingBoxMax[1], boundingBoxMax[2] );
}
else
{
// Plane will not be clipped
m_Box->SetXMin( -10000.0, -10000.0, -10000.0 );
m_Box->SetXMax( 10000.0, 10000.0, 10000.0 );
}
m_Transform->Identity();
- m_Transform->Concatenate( input->GetGeometry2D()->GetVtkTransform() );
+ m_Transform->Concatenate( input->GetPlaneGeometry()->GetVtkTransform() );
m_Transform->PreMultiply();
m_Box->SetTransform( m_Transform );
m_PlaneClipper->SetInputConnection(m_VtkTransformPlaneFilter->GetOutputPort() );
m_PlaneClipper->SetClipFunction( m_Box );
m_PlaneClipper->GenerateClippedOutputOff(); // important to NOT generate normals data for clipped part
m_PlaneClipper->InsideOutOn();
m_PlaneClipper->SetValue( 0.0 );
m_PlaneClipper->Update();
planeSurface = m_PlaneClipper->GetOutput();
}
m_NormalsUpdater->SetInputData( planeSurface );
m_NormalsUpdater->AutoOrientNormalsOn(); // that's the trick! Brings consistency between
// normals direction and front/back faces direction (see bug 1440)
m_NormalsUpdater->ComputePointNormalsOn();
m_NormalsUpdater->Update();
output->SetVtkPolyData( m_NormalsUpdater->GetOutput() );
output->CalculateBoundingBox();
}
-void mitk::Geometry2DDataToSurfaceFilter::GenerateData()
+void mitk::PlaneGeometryDataToSurfaceFilter::GenerateData()
{
mitk::Surface::Pointer output = this->GetOutput();
if (output.IsNull()) return;
if (output->GetVtkPolyData()==NULL) return;
// output->GetVtkPolyData()->Update(); //VTK6_TODO vtk pipeline
}
-const mitk::Geometry2DData *mitk::Geometry2DDataToSurfaceFilter::GetInput()
+const mitk::PlaneGeometryData *mitk::PlaneGeometryDataToSurfaceFilter::GetInput()
{
if (this->GetNumberOfInputs() < 1)
{
return 0;
}
- return static_cast<const mitk::Geometry2DData * >
+ return static_cast<const mitk::PlaneGeometryData * >
( this->ProcessObject::GetInput(0) );
}
-const mitk::Geometry2DData *
-mitk::Geometry2DDataToSurfaceFilter
+const mitk::PlaneGeometryData *
+mitk::PlaneGeometryDataToSurfaceFilter
::GetInput(unsigned int idx)
{
- return static_cast< const mitk::Geometry2DData * >
+ return static_cast< const mitk::PlaneGeometryData * >
( this->ProcessObject::GetInput(idx) );
}
void
-mitk::Geometry2DDataToSurfaceFilter
-::SetInput(const mitk::Geometry2DData *input)
+mitk::PlaneGeometryDataToSurfaceFilter
+::SetInput(const mitk::PlaneGeometryData *input)
{
// Process object is not const-correct so the const_cast is required here
this->ProcessObject::SetNthInput( 0,
- const_cast< mitk::Geometry2DData * >( input )
+ const_cast< mitk::PlaneGeometryData * >( input )
);
}
void
-mitk::Geometry2DDataToSurfaceFilter
-::SetInput(unsigned int index, const mitk::Geometry2DData *input)
+mitk::PlaneGeometryDataToSurfaceFilter
+::SetInput(unsigned int index, const mitk::PlaneGeometryData *input)
{
if( index+1 > this->GetNumberOfInputs() )
{
this->SetNumberOfRequiredInputs( index + 1 );
}
// Process object is not const-correct so the const_cast is required here
this->ProcessObject::SetNthInput(index,
- const_cast< mitk::Geometry2DData *>( input )
+ const_cast< mitk::PlaneGeometryData *>( input )
);
}
void
-mitk::Geometry2DDataToSurfaceFilter
+mitk::PlaneGeometryDataToSurfaceFilter
::SetBoundingBox( const mitk::BoundingBox *boundingBox )
{
m_BoundingBox = boundingBox;
this->UseBoundingBoxOn();
}
const mitk::BoundingBox *
-mitk::Geometry2DDataToSurfaceFilter
+mitk::PlaneGeometryDataToSurfaceFilter
::GetBoundingBox() const
{
return m_BoundingBox.GetPointer();
}
diff --git a/Core/Code/Algorithms/mitkPlaneGeometryDataToSurfaceFilter.h b/Core/Code/Algorithms/mitkPlaneGeometryDataToSurfaceFilter.h
new file mode 100644
index 0000000000..810c4712dd
--- /dev/null
+++ b/Core/Code/Algorithms/mitkPlaneGeometryDataToSurfaceFilter.h
@@ -0,0 +1,227 @@
+/*===================================================================
+
+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 MITKGEOMETRY2DDATATOSURFACEDATAFILTER_H_HEADER_INCLUDED_C10B22CD
+#define MITKGEOMETRY2DDATATOSURFACEDATAFILTER_H_HEADER_INCLUDED_C10B22CD
+
+#include "mitkSurfaceSource.h"
+#include "mitkGeometry3D.h"
+#include "vtkSystemIncludes.h"
+
+class vtkPlaneSource;
+class vtkTransformPolyDataFilter;
+class vtkCubeSource;
+class vtkTransform;
+class vtkPlane;
+class vtkCutter;
+class vtkStripper;
+class vtkPolyData;
+class vtkPPolyDataNormals;
+class vtkTriangleFilter;
+class vtkTextureMapToPlane;
+class vtkBox;
+class vtkClipPolyData;
+
+namespace mitk {
+ class PlaneGeometryData;
+ class PlaneGeometryDataToSurfaceFilter;
+ /** \deprecatedSince{2014_06} This class is deprecated. Please use PlaneGeometryDataToSurfaceFilter instead. */
+ DEPRECATED( typedef PlaneGeometryDataToSurfaceFilter Geometry2DDataToSurfaceFilter);
+ /** \brief Superclass of all classes having a PlaneGeometryData as input and
+ * generating Images as output
+ *
+ * Currently implemented for PlaneGeometry and AbstractTransformGeometry.
+ * Currently, this class does not really have subclasses, but does the job
+ * for itself. It checks which kind of PlaneGeometry is stored in the
+ * PlaneGeometryData and - if it knows how - it generates the respective
+ * Surface. Of course, this has the disadvantage that for any new type of
+ * PlaneGeometry this class (PlaneGeometryDataToSurfaceFilter) has to be
+ * changed/extended. The idea is to move the type specific generation code in
+ * subclasses, and internally (within this class) use a factory to create an
+ * instance of the required subclass and delegate the surface generation to
+ * it.
+ *
+ * \sa mitk::DeformablePlane
+ * \todo make extension easier
+ * \ingroup Process
+ */
+ class MITK_CORE_EXPORT PlaneGeometryDataToSurfaceFilter : public SurfaceSource
+ {
+ public:
+ mitkClassMacro(PlaneGeometryDataToSurfaceFilter, SurfaceSource);
+ itkFactorylessNewMacro(Self)
+ itkCloneMacro(Self)
+
+ virtual void GenerateOutputInformation();
+
+ virtual void GenerateData();
+
+ const PlaneGeometryData *GetInput(void);
+ const PlaneGeometryData *GetInput(unsigned int idx);
+
+ virtual void SetInput(const PlaneGeometryData *image);
+ using itk::ProcessObject::SetInput;
+ virtual void SetInput(unsigned int index, const PlaneGeometryData *image);
+
+ /** \brief If \a true (default), use Geometry3D::GetParametricBounds() to define the resolution in parameter space,
+ * otherwise use m_XResolution and m_YResolution
+ */
+ itkGetMacro(UseGeometryParametricBounds, bool);
+ /** \brief If \a true (default), use Geometry3D::GetParametricBounds() to define the resolution in parameter space,
+ * otherwise use m_XResolution and m_YResolution
+ */
+ itkSetMacro(UseGeometryParametricBounds, bool);
+
+ /** \brief Get x-resolution in parameter space
+ *
+ * The m_PlaneSource will create this many sub-rectangles
+ * in x-direction (see vtkPlaneSource::SetXResolution)
+ * \note Only used, when GetUseGeometryParametricBounds() is \a false, otherwise the
+ * the x-bounds of Geometry3D::GetParametricBounds() are used.
+ * \sa m_XResolution
+ */
+ itkGetMacro(XResolution, int);
+ /** \brief Set x-resolution in parameter space
+ *
+ * The m_PlaneSource will create this many sub-rectangles
+ * in x-direction (see vtkPlaneSource::SetXResolution)
+ * \note Only used, when GetUseGeometryParametricBounds() is \a false, otherwise the
+ * the x-bounds of Geometry3D::GetParametricBounds() are used.
+ * \sa m_XResolution
+ */
+ itkSetMacro(XResolution, int);
+
+ /** \brief Get y-resolution in parameter space
+ *
+ * The m_PlaneSource will create this many sub-rectangles
+ * in y-direction (see vtkPlaneSource::SetYResolution)
+ * \note Only used, when GetUseGeometryParametricBounds() is \a false, otherwise the
+ * the y-bounds of Geometry3D::GetParametricBounds() are used.
+ * \sa m_YResolution
+ */
+ itkGetMacro(YResolution, int);
+
+ /** \brief Set y-resolution in parameter space
+ *
+ * The m_PlaneSource will create this many sub-rectangles
+ * in y-direction (see vtkPlaneSource::SetYResolution)
+ * \note Only used, when GetUseGeometryParametricBounds() is \a false, otherwise the
+ * the y-bounds of Geometry3D::GetParametricBounds() are used.
+ * \sa m_YResolution
+ */
+ itkSetMacro(YResolution, int);
+
+ /** \brief Get whether the Surface is at the origin and placed using the Geometry
+ *
+ * Default is \a false, i.e., the transform of the Geometry is the identity, thus
+ * the points within the Surface are at their final position. Otherwise
+ * (m_PlaceByGeometry==\a true), the first cornerpoint of the created Surface is
+ * at the origin and the actual position is determined by the transform of the
+ * Geometry.
+ * \sa m_PlaceByGeometry
+ */
+ itkGetConstMacro(PlaceByGeometry, bool);
+
+ /** \brief Set whether the Surface is at the origin and placed using the Geometry
+ *
+ * Default is \a false, i.e., the transform of the Geometry is the identity, thus
+ * the points within the Surface are at their final position. Otherwise
+ * (m_PlaceByGeometry==\a true), the first cornerpoint of the created Surface is
+ * at the origin and the actual position is determined by the transform of the
+ * Geometry.
+ * \sa m_PlaceByGeometry
+ */
+ itkSetMacro(PlaceByGeometry, bool);
+ itkBooleanMacro(PlaceByGeometry);
+
+ itkGetConstMacro( UseBoundingBox, bool );
+ itkSetMacro( UseBoundingBox, bool );
+ itkBooleanMacro( UseBoundingBox );
+
+ void SetBoundingBox( const BoundingBox *boundingBox );
+ const BoundingBox *GetBoundingBox() const;
+
+ protected:
+
+ PlaneGeometryDataToSurfaceFilter();
+
+ virtual ~PlaneGeometryDataToSurfaceFilter();
+
+ /** \brief Source to create the vtk-representation of the parameter space rectangle of the PlaneGeometry
+ */
+ vtkPlaneSource* m_PlaneSource;
+
+ /** \brief Filter to create the vtk-representation of the PlaneGeometry, which is a
+ * transformation of the m_PlaneSource
+ */
+ vtkTransformPolyDataFilter* m_VtkTransformPlaneFilter;
+
+ /** \brief If \a true, use Geometry3D::GetParametricBounds() to define the resolution in parameter space,
+ * otherwise use m_XResolution and m_YResolution
+ */
+ bool m_UseGeometryParametricBounds;
+
+ /** \brief X-resolution in parameter space
+ *
+ * The m_PlaneSource will create this many sub-rectangles
+ * in x-direction (see vtkPlaneSource::SetXResolution)
+ * \note Only used, when GetUseGeometryParametricBounds() is \a false, otherwise the
+ * the x-bounds of Geometry3D::GetParametricBounds() are used.
+ * \sa m_XResolution
+ */
+ int m_XResolution;
+
+ /** \brief Y-resolution in parameter space
+ *
+ * The m_PlaneSource will create this many sub-rectangles
+ * in y-direction (see vtkPlaneSource::SetYResolution)
+ * \note Only used, when GetUseGeometryParametricBounds() is \a false, otherwise the
+ * the y-bounds of Geometry3D::GetParametricBounds() are used.
+ */
+ int m_YResolution;
+
+ /** \brief Define whether the Surface is at the origin and placed using the Geometry
+ *
+ * Default is \a false, i.e., the transform of the Geometry is the identity, thus
+ * the points within the Surface are at their final position. Otherwise
+ * (m_PlaceByGeometry==\a true), the first cornerpoint of the created Surface is
+ * at the origin and the actual position is determined by the transform of the
+ * Geometry.
+ */
+ bool m_PlaceByGeometry;
+
+ bool m_UseBoundingBox;
+
+ BoundingBox::ConstPointer m_BoundingBox;
+
+ vtkCubeSource *m_CubeSource;
+ vtkTransform *m_Transform;
+ vtkTransformPolyDataFilter *m_PolyDataTransformer;
+
+ vtkPlane *m_Plane;
+ vtkCutter *m_PlaneCutter;
+ vtkStripper *m_PlaneStripper;
+ vtkPolyData *m_PlanePolyData;
+ vtkPPolyDataNormals * m_NormalsUpdater;
+ vtkTriangleFilter *m_PlaneTriangler;
+ vtkTextureMapToPlane *m_TextureMapToPlane;
+
+ vtkBox *m_Box;
+ vtkClipPolyData *m_PlaneClipper;
+ };
+} // namespace mitk
+
+#endif /* MITKGEOMETRY2DDATATOSURFACEDATAFILTER_H_HEADER_INCLUDED_C10B22CD */
diff --git a/Core/Code/Algorithms/mitkSurfaceToImageFilter.cpp b/Core/Code/Algorithms/mitkSurfaceToImageFilter.cpp
index d68c61baff..7cbb76e444 100644
--- a/Core/Code/Algorithms/mitkSurfaceToImageFilter.cpp
+++ b/Core/Code/Algorithms/mitkSurfaceToImageFilter.cpp
@@ -1,223 +1,221 @@
/*===================================================================
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 "mitkSurfaceToImageFilter.h"
#include "mitkTimeHelper.h"
#include "mitkImageWriteAccessor.h"
#include <vtkPolyData.h>
#include <vtkPolyDataToImageStencil.h>
#include <vtkImageStencil.h>
#include <vtkImageData.h>
#include <vtkPolyData.h>
#include <vtkLinearTransform.h>
#include <vtkTriangleFilter.h>
#include <vtkLinearExtrusionFilter.h>
#include <vtkDataSetTriangleFilter.h>
#include <vtkImageThreshold.h>
#include <vtkImageMathematics.h>
#include <vtkPolyDataNormals.h>
#include <vtkTransformPolyDataFilter.h>
#include <vtkTransform.h>
#include <vtkSmartPointer.h>
#include <mitkImageReadAccessor.h>
mitk::SurfaceToImageFilter::SurfaceToImageFilter()
: m_MakeOutputBinary( false ),
m_BackgroundValue( -10000 )
{
}
mitk::SurfaceToImageFilter::~SurfaceToImageFilter()
{
}
void mitk::SurfaceToImageFilter::GenerateInputRequestedRegion()
{
mitk::Image* output = this->GetOutput();
if((output->IsInitialized()==false) )
return;
GenerateTimeInInputRegion(output, const_cast< mitk::Image * > ( this->GetImage() ));
}
void mitk::SurfaceToImageFilter::GenerateOutputInformation()
{
mitk::Image *inputImage = (mitk::Image*)this->GetImage();
mitk::Image::Pointer output = this->GetOutput();
itkDebugMacro(<<"GenerateOutputInformation()");
if((inputImage == NULL) ||
(inputImage->IsInitialized() == false) ||
(inputImage->GetTimeGeometry() == NULL)) return;
if (m_MakeOutputBinary)
output->Initialize(mitk::MakeScalarPixelType<unsigned char>() , *inputImage->GetTimeGeometry());
else
output->Initialize(inputImage->GetPixelType(), *inputImage->GetTimeGeometry());
output->SetPropertyList(inputImage->GetPropertyList()->Clone());
}
void mitk::SurfaceToImageFilter::GenerateData()
{
mitk::Image::ConstPointer inputImage = this->GetImage();
mitk::Image::Pointer output = this->GetOutput();
if(inputImage.IsNull())
return;
if(output->IsInitialized()==false )
return;
mitk::Image::RegionType outputRegion = output->GetRequestedRegion();
int tstart=outputRegion.GetIndex(3);
int tmax=tstart+outputRegion.GetSize(3);
if ( tmax > 0)
{
int t;
for(t=tstart;t<tmax;++t)
{
Stencil3DImage( t );
}
}
else
{
Stencil3DImage( 0 );
}
}
void mitk::SurfaceToImageFilter::Stencil3DImage(int time)
{
mitk::Image::Pointer output = this->GetOutput();
mitk::Image::Pointer binaryImage = mitk::Image::New();
unsigned int size = sizeof(unsigned char);
if (m_MakeOutputBinary)
binaryImage->Initialize(mitk::MakeScalarPixelType<unsigned char>(), *this->GetImage()->GetTimeGeometry(),1,1);
else
{
binaryImage->Initialize(this->GetImage()->GetPixelType(), *this->GetImage()->GetTimeGeometry(),1,1);
size = this->GetImage()->GetPixelType().GetSize();
}
for (unsigned int i = 0; i < binaryImage->GetDimension(); ++i)
size *= binaryImage->GetDimension(i);
mitk::ImageWriteAccessor accessor( binaryImage );
memset( accessor.GetData(), 1, size );
const mitk::TimeGeometry *surfaceTimeGeometry = GetInput()->GetTimeGeometry();
const mitk::TimeGeometry *imageTimeGeometry = GetImage()->GetTimeGeometry();
// Convert time step from image time-frame to surface time-frame
mitk::TimePointType matchingTimePoint = imageTimeGeometry->TimeStepToTimePoint(time);
mitk::TimeStepType surfaceTimeStep = surfaceTimeGeometry->TimePointToTimeStep(matchingTimePoint);
vtkPolyData * polydata = ( (mitk::Surface*)GetInput() )->GetVtkPolyData( surfaceTimeStep );
if(polydata)
{
vtkSmartPointer<vtkTransformPolyDataFilter> move=vtkTransformPolyDataFilter::New();
move->SetInputData(polydata);
move->ReleaseDataFlagOn();
vtkSmartPointer<vtkTransform> transform=vtkTransform::New();
- Geometry3D* geometry = surfaceTimeGeometry->GetGeometryForTimeStep( surfaceTimeStep );
+ BaseGeometry* geometry = surfaceTimeGeometry->GetGeometryForTimeStep( surfaceTimeStep );
if(!geometry)
{
geometry = GetInput()->GetGeometry();
}
- geometry->TransferItkToVtkTransform();
transform->PostMultiply();
transform->Concatenate(geometry->GetVtkTransform()->GetMatrix());
// take image geometry into account. vtk-Image information will be changed to unit spacing and zero origin below.
- Geometry3D* imageGeometry = imageTimeGeometry->GetGeometryForTimeStep(time);
- imageGeometry->TransferItkToVtkTransform();
+ BaseGeometry* imageGeometry = imageTimeGeometry->GetGeometryForTimeStep(time);
transform->Concatenate(imageGeometry->GetVtkTransform()->GetLinearInverse());
move->SetTransform(transform);
vtkSmartPointer<vtkPolyDataNormals> normalsFilter = vtkPolyDataNormals::New();
normalsFilter->SetFeatureAngle(50);
normalsFilter->SetConsistency(1);
normalsFilter->SetSplitting(1);
normalsFilter->SetFlipNormals(0);
normalsFilter->ReleaseDataFlagOn();
normalsFilter->SetInputConnection(move->GetOutputPort());
vtkSmartPointer<vtkPolyDataToImageStencil> surfaceConverter = vtkPolyDataToImageStencil::New();
surfaceConverter->SetTolerance( 0.0 );
surfaceConverter->ReleaseDataFlagOn();
surfaceConverter->SetInputConnection( normalsFilter->GetOutputPort() );
vtkImageData *image = m_MakeOutputBinary
? binaryImage->GetVtkImageData()
: const_cast<mitk::Image *>(this->GetImage())->GetVtkImageData(time);
// Create stencil and use numerical minimum of pixel type as background value
vtkSmartPointer<vtkImageStencil> stencil = vtkImageStencil::New();
stencil->SetInputData(image);
stencil->ReverseStencilOff();
stencil->ReleaseDataFlagOn();
stencil->SetStencilConnection(surfaceConverter->GetOutputPort());
stencil->SetBackgroundValue(m_MakeOutputBinary ? 0 : m_BackgroundValue);
stencil->Update();
output->SetVolume( stencil->GetOutput()->GetScalarPointer(), time );
MITK_INFO << "stencil ref count: " << stencil->GetReferenceCount() << std::endl;
}
else
{
memset( accessor.GetData(), 0, size );
output->SetVolume(accessor.GetData(),time);
}
}
const mitk::Surface *mitk::SurfaceToImageFilter::GetInput(void)
{
if (this->GetNumberOfInputs() < 1)
{
return 0;
}
return static_cast<const mitk::Surface * >
( this->ProcessObject::GetInput(0) );
}
void mitk::SurfaceToImageFilter::SetInput(const mitk::Surface *input)
{
// Process object is not const-correct so the const_cast is required here
this->ProcessObject::SetNthInput(0,
const_cast< mitk::Surface * >( input ) );
}
void mitk::SurfaceToImageFilter::SetImage(const mitk::Image *source)
{
this->ProcessObject::SetNthInput( 1, const_cast< mitk::Image * >( source ) );
}
const mitk::Image *mitk::SurfaceToImageFilter::GetImage(void)
{
return static_cast< const mitk::Image * >(this->ProcessObject::GetInput(1));
}
diff --git a/Core/Code/Common/mitkCoreObjectFactory.cpp b/Core/Code/Common/mitkCoreObjectFactory.cpp
index f7a82a87ad..630b814b15 100644
--- a/Core/Code/Common/mitkCoreObjectFactory.cpp
+++ b/Core/Code/Common/mitkCoreObjectFactory.cpp
@@ -1,446 +1,446 @@
/*===================================================================
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 "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 "mitkPlaneGeometryData.h"
+#include "mitkPlaneGeometryDataMapper2D.h"
+#include "mitkPlaneGeometryDataVtkMapper3D.h"
#include "mitkGeometry3D.h"
#include "mitkGeometryData.h"
#include "mitkImage.h"
#include <mitkImageVtkMapper2D.h>
#include "mitkLevelWindowProperty.h"
#include "mitkLookupTable.h"
#include "mitkLookupTableProperty.h"
#include "mitkPlaneGeometry.h"
#include "mitkPointSet.h"
#include "mitkPointSetVtkMapper2D.h"
#include "mitkPointSetVtkMapper3D.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 "mitkTimeGeometry.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 "mitkImageWriter.h"
#include "mitkPointSetWriterFactory.h"
#include "mitkSurfaceVtkWriterFactory.h"
void mitk::CoreObjectFactory::RegisterExtraFactory(CoreObjectFactoryBase* factory) {
MITK_DEBUG << "CoreObjectFactory: registering extra factory of type " << factory->GetNameOfClass();
m_ExtraFactories.insert(CoreObjectFactoryBase::Pointer(factory));
}
void mitk::CoreObjectFactory::UnRegisterExtraFactory(CoreObjectFactoryBase *factory)
{
MITK_DEBUG << "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 <mitkDataNodeFactory.h>
void mitk::CoreObjectFactory::SetDefaultProperties(mitk::DataNode* node)
{
if(node==NULL)
return;
mitk::DataNode::Pointer nodePointer = node;
mitk::Image::Pointer image = dynamic_cast<mitk::Image*>(node->GetData());
if(image.IsNotNull() && image->IsInitialized())
{
mitk::ImageVtkMapper2D::SetDefaultProperties(node);
mitk::VolumeDataVtkMapper3D::SetDefaultProperties(node);
}
mitk::Surface::Pointer surface = dynamic_cast<mitk::Surface*>(node->GetData());
if(surface.IsNotNull())
{
mitk::SurfaceGLMapper2D::SetDefaultProperties(node);
mitk::SurfaceVtkMapper3D::SetDefaultProperties(node);
}
mitk::PointSet::Pointer pointSet = dynamic_cast<mitk::PointSet*>(node->GetData());
if(pointSet.IsNotNull())
{
mitk::PointSetVtkMapper2D::SetDefaultProperties(node);
mitk::PointSetVtkMapper3D::SetDefaultProperties(node);
}
for (ExtraFactoriesContainer::iterator it = m_ExtraFactories.begin(); it != m_ExtraFactories.end() ; it++ ) {
(*it)->SetDefaultProperties(node);
}
}
mitk::CoreObjectFactory::CoreObjectFactory()
: m_PointSetIOFactory(PointSetIOFactory::New().GetPointer())
, m_STLFileIOFactory(STLFileIOFactory::New().GetPointer())
, m_VtkSurfaceIOFactory(VtkSurfaceIOFactory::New().GetPointer())
, m_VtkImageIOFactory(VtkImageIOFactory::New().GetPointer())
, m_VtiFileIOFactory(VtiFileIOFactory::New().GetPointer())
, m_ItkImageFileIOFactory(ItkImageFileIOFactory::New().GetPointer())
, m_SurfaceVtkWriterFactory(SurfaceVtkWriterFactory::New().GetPointer())
, m_PointSetWriterFactory(PointSetWriterFactory::New().GetPointer())
, m_ImageWriterFactory(ImageWriterFactory::New().GetPointer())
{
static bool alreadyDone = false;
if (!alreadyDone)
{
MITK_DEBUG << "CoreObjectFactory c'tor" << std::endl;
itk::ObjectFactoryBase::RegisterFactory( m_PointSetIOFactory );
itk::ObjectFactoryBase::RegisterFactory( m_STLFileIOFactory );
itk::ObjectFactoryBase::RegisterFactory( m_VtkSurfaceIOFactory );
itk::ObjectFactoryBase::RegisterFactory( m_VtkImageIOFactory );
itk::ObjectFactoryBase::RegisterFactory( m_VtiFileIOFactory );
itk::ObjectFactoryBase::RegisterFactory( m_ItkImageFileIOFactory );
itk::ObjectFactoryBase::RegisterFactory( m_SurfaceVtkWriterFactory );
itk::ObjectFactoryBase::RegisterFactory( m_PointSetWriterFactory );
itk::ObjectFactoryBase::RegisterFactory( m_ImageWriterFactory );
m_FileWriters.push_back(mitk::ImageWriter::New().GetPointer());
CreateFileExtensionsMap();
alreadyDone = true;
}
}
mitk::CoreObjectFactory::~CoreObjectFactory()
{
itk::ObjectFactoryBase::UnRegisterFactory( m_PointSetIOFactory );
itk::ObjectFactoryBase::UnRegisterFactory( m_STLFileIOFactory );
itk::ObjectFactoryBase::UnRegisterFactory( m_VtkSurfaceIOFactory );
itk::ObjectFactoryBase::UnRegisterFactory( m_VtkImageIOFactory );
itk::ObjectFactoryBase::UnRegisterFactory( m_VtiFileIOFactory );
itk::ObjectFactoryBase::UnRegisterFactory( m_ItkImageFileIOFactory );
itk::ObjectFactoryBase::UnRegisterFactory( m_SurfaceVtkWriterFactory );
itk::ObjectFactoryBase::UnRegisterFactory( m_PointSetWriterFactory );
itk::ObjectFactoryBase::UnRegisterFactory( m_ImageWriterFactory );
}
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<Image*>(data)!=NULL))
{
newMapper = mitk::ImageVtkMapper2D::New();
newMapper->SetDataNode(node);
}
- else if((dynamic_cast<Geometry2DData*>(data)!=NULL))
+ else if((dynamic_cast<PlaneGeometryData*>(data)!=NULL))
{
- newMapper = mitk::Geometry2DDataMapper2D::New();
+ newMapper = mitk::PlaneGeometryDataMapper2D::New();
newMapper->SetDataNode(node);
}
else if((dynamic_cast<Surface*>(data)!=NULL))
{
newMapper = mitk::SurfaceGLMapper2D::New();
// cast because SetDataNode is not virtual
mitk::SurfaceGLMapper2D *castedMapper = dynamic_cast<mitk::SurfaceGLMapper2D*>(newMapper.GetPointer());
castedMapper->SetDataNode(node);
}
else if((dynamic_cast<PointSet*>(data)!=NULL))
{
newMapper = mitk::PointSetVtkMapper2D::New();
newMapper->SetDataNode(node);
}
}
else if ( id == mitk::BaseRenderer::Standard3D )
{
if((dynamic_cast<Image*>(data) != NULL))
{
newMapper = mitk::VolumeDataVtkMapper3D::New();
newMapper->SetDataNode(node);
}
- else if((dynamic_cast<Geometry2DData*>(data)!=NULL))
+ else if((dynamic_cast<PlaneGeometryData*>(data)!=NULL))
{
- newMapper = mitk::Geometry2DDataVtkMapper3D::New();
+ newMapper = mitk::PlaneGeometryDataVtkMapper3D::New();
newMapper->SetDataNode(node);
}
else if((dynamic_cast<Surface*>(data)!=NULL))
{
newMapper = mitk::SurfaceVtkMapper3D::New();
newMapper->SetDataNode(node);
}
else if((dynamic_cast<PointSet*>(data)!=NULL))
{
newMapper = mitk::PointSetVtkMapper3D::New();
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<MultimapType::iterator, MultimapType::iterator> 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<std::string, std::string>((*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<std::string, std::string>("*.dcm", "DICOM files"));
m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.DCM", "DICOM files"));
m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.dc3", "DICOM files"));
m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.DC3", "DICOM files"));
m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.gdcm", "DICOM files"));
m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.seq", "DKFZ Pic"));
m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.pic", "DKFZ Pic"));
m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.pic.gz", "DKFZ Pic"));
m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.mhd", "MetaImage"));
m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.seq.gz", "DKFZ Pic"));
m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.hdr", "Analyze Format"));
m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.img", "Analyze Format"));
m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.img.gz", "Analyze Format"));
m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.nrrd", "Nearly Raw Raster Data"));
m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.nhdr", "NRRD with detached header"));
m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.mps", "Point sets"));
m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.pic", "Sets of 2D slices"));
m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.pic.gz", "Sets of 2D slices"));
m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.bmp", "Sets of 2D slices"));
m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.png", "Sets of 2D slices"));
m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.jpg", "Sets of 2D slices"));
m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.jpeg", "Sets of 2D slices"));
m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.dcm", "Sets of 2D slices"));
m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.gdcm", "Sets of 2D slices"));
m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.ima", "Sets of 2D slices"));
m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.tiff", "Sets of 2D slices"));
m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.tif", "Sets of 2D slices"));
m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.stl", "Surface files"));
m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.vtk", "Surface files"));
m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.vtp", "Surface files"));
m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.obj", "Surface files"));
m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.nii", "NIfTI format"));
m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.nii.gz", "NIfTI format"));
m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.gipl", "UMDS GIPL Format Files"));
m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.gipl.gz", "UMDS GIPL Format Files"));
//m_SaveFileExtensionsMap.insert(std::pair<std::string, std::string>("*.pic", "DKFZ Pic"));
m_SaveFileExtensionsMap.insert(std::pair<std::string, std::string>("*.mhd", "MetaImage"));
m_SaveFileExtensionsMap.insert(std::pair<std::string, std::string>("*.vtk", "Surface Files"));
m_SaveFileExtensionsMap.insert(std::pair<std::string, std::string>("*.vti", "VTK Image Data Files"));
m_SaveFileExtensionsMap.insert(std::pair<std::string, std::string>("*.hdr", "Analyze Format"));
m_SaveFileExtensionsMap.insert(std::pair<std::string, std::string>("*.png", "Sets of 2D slices"));
m_SaveFileExtensionsMap.insert(std::pair<std::string, std::string>("*.tiff", "Sets of 2D slices"));
m_SaveFileExtensionsMap.insert(std::pair<std::string, std::string>("*.tif", "Sets of 2D slices"));
m_SaveFileExtensionsMap.insert(std::pair<std::string, std::string>("*.jpg", "Sets of 2D slices"));
m_SaveFileExtensionsMap.insert(std::pair<std::string, std::string>("*.jpeg", "Sets of 2D slices"));
m_SaveFileExtensionsMap.insert(std::pair<std::string, std::string>("*.bmp", "Sets of 2D slices"));
m_SaveFileExtensionsMap.insert(std::pair<std::string, std::string>("*.dcm", "Sets of 2D slices"));
m_SaveFileExtensionsMap.insert(std::pair<std::string, std::string>("*.gipl", "UMDS GIPL Format Files"));
m_SaveFileExtensionsMap.insert(std::pair<std::string, std::string>("*.gipl.gz", "UMDS compressed GIPL Format Files"));
m_SaveFileExtensionsMap.insert(std::pair<std::string, std::string>("*.nii", "NIfTI format"));
m_SaveFileExtensionsMap.insert(std::pair<std::string, std::string>("*.nii.gz", "NIfTI compressed format"));
m_SaveFileExtensionsMap.insert(std::pair<std::string, std::string>("*.nrrd", "Nearly Raw Raster Data"));
m_SaveFileExtensionsMap.insert(std::pair<std::string, std::string>("*.nhdr", "NRRD with detached header"));
m_SaveFileExtensionsMap.insert(std::pair<std::string, std::string>("*.lsm", "Microscope Images"));
m_SaveFileExtensionsMap.insert(std::pair<std::string, std::string>("*.dwi", "Diffusion Weighted Images"));
m_SaveFileExtensionsMap.insert(std::pair<std::string, std::string>("*.hdwi", "Diffusion Weighted Images"));
m_SaveFileExtensionsMap.insert(std::pair<std::string, std::string>("*.qbi", "Q-Ball Images"));
m_SaveFileExtensionsMap.insert(std::pair<std::string, std::string>("*.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;
//sort to merge lists later on
typedef std::set<mitk::FileWriterWithInformation::Pointer> FileWriterSet;
FileWriterSet fileWritersSet;
fileWritersSet.insert(allWriters.begin(), allWriters.end());
//collect all extra factories
for (ExtraFactoriesContainer::iterator it = m_ExtraFactories.begin();
it != m_ExtraFactories.end(); it++ )
{
FileWriterList list2 = (*it)->GetFileWriters();
//add them to the sorted set
fileWritersSet.insert(list2.begin(), list2.end());
}
//write back to allWriters to return a list
allWriters.clear();
allWriters.insert(allWriters.end(), fileWritersSet.begin(), fileWritersSet.end());
return allWriters;
}
void mitk::CoreObjectFactory::MapEvent(const mitk::Event*, const int) {
}
diff --git a/Core/Code/Controllers/mitkPlanePositionManager.cpp b/Core/Code/Controllers/mitkPlanePositionManager.cpp
index e22b217498..2587d0fd0c 100644
--- a/Core/Code/Controllers/mitkPlanePositionManager.cpp
+++ b/Core/Code/Controllers/mitkPlanePositionManager.cpp
@@ -1,106 +1,106 @@
/*===================================================================
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 "mitkPlanePositionManager.h"
#include "mitkInteractionConst.h"
mitk::PlanePositionManagerService::PlanePositionManagerService()
{
}
mitk::PlanePositionManagerService::~PlanePositionManagerService()
{
for (unsigned int i = 0; i < m_PositionList.size(); ++i)
delete m_PositionList[i];
}
-unsigned int mitk::PlanePositionManagerService::AddNewPlanePosition ( const Geometry2D* plane, unsigned int sliceIndex )
+unsigned int mitk::PlanePositionManagerService::AddNewPlanePosition ( const PlaneGeometry* plane, unsigned int sliceIndex )
{
for (unsigned int i = 0; i < m_PositionList.size(); ++i)
{
if (m_PositionList[i] != 0)
{
bool isSameMatrix(true);
bool isSameOffset(true);
isSameOffset = mitk::Equal(m_PositionList[i]->GetTransform()->GetOffset(), plane->GetIndexToWorldTransform()->GetOffset());
if(!isSameOffset || sliceIndex != m_PositionList[i]->GetPos())
continue;
isSameMatrix = mitk::MatrixEqualElementWise(m_PositionList[i]->GetTransform()->GetMatrix(), plane->GetIndexToWorldTransform()->GetMatrix());
if(isSameMatrix)
return i;
}
}
AffineTransform3D::Pointer transform = AffineTransform3D::New();
Matrix3D matrix;
matrix.GetVnlMatrix().set_column(0, plane->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(0));
matrix.GetVnlMatrix().set_column(1, plane->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(1));
matrix.GetVnlMatrix().set_column(2, plane->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(2));
transform->SetMatrix(matrix);
transform->SetOffset(plane->GetIndexToWorldTransform()->GetOffset());
mitk::Vector3D direction;
direction[0] = plane->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(2)[0];
direction[1] = plane->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(2)[1];
direction[2] = plane->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(2)[2];
direction.Normalize();
mitk::RestorePlanePositionOperation* newOp = new mitk::RestorePlanePositionOperation (OpRESTOREPLANEPOSITION, plane->GetExtent(0),
plane->GetExtent(1), plane->GetSpacing(), sliceIndex, direction, transform);
m_PositionList.push_back( newOp );
return GetNumberOfPlanePositions()-1;
}
bool mitk::PlanePositionManagerService::RemovePlanePosition( unsigned int ID )
{
if (m_PositionList.size() > ID)
{
delete m_PositionList[ID];
m_PositionList.erase(m_PositionList.begin()+ID);
return true;
}
else
{
return false;
}
}
mitk::RestorePlanePositionOperation* mitk::PlanePositionManagerService::GetPlanePosition ( unsigned int ID )
{
if ( ID < m_PositionList.size() )
{
return m_PositionList[ID];
}
else
{
MITK_WARN<<"GetPlanePosition returned NULL!";
return 0;
}
}
unsigned int mitk::PlanePositionManagerService::GetNumberOfPlanePositions()
{
return m_PositionList.size();
}
void mitk::PlanePositionManagerService::RemoveAllPlanePositions()
{
for (unsigned int i = 0; i < m_PositionList.size(); ++i)
delete m_PositionList[i];
m_PositionList.clear();
}
diff --git a/Core/Code/Controllers/mitkPlanePositionManager.h b/Core/Code/Controllers/mitkPlanePositionManager.h
index ecb3f35b3f..cddb1e9f95 100644
--- a/Core/Code/Controllers/mitkPlanePositionManager.h
+++ b/Core/Code/Controllers/mitkPlanePositionManager.h
@@ -1,94 +1,94 @@
/*===================================================================
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 mitkPlanePositionManager_h_Included
#define mitkPlanePositionManager_h_Included
#include "mitkCommon.h"
#include "mitkRestorePlanePositionOperation.h"
#include "mitkDataStorage.h"
#include <usServiceInterface.h>
-#include <mitkGeometry2D.h>
+#include <mitkPlaneGeometry.h>
class MitkCoreActivator;
namespace mitk
{
/**
The mitk::PlanePositionManagerService holds and manages a list of certain planepositions.
To store a new position you need to specify the first slice of your slicestack and the
slicenumber you want to restore in the mitk::PlanePositionManager::AddNewPlanePosition() function.
To restore a position call mitk::PlanePositionManagerService::GetPlanePosition(ID) where ID is the position
in the plane positionlist (returned by AddNewPlanePostion). This will give a mitk::RestorePlanePositionOperation
which can be executed by the SliceNavigationController of the slicestack.
\sa QmitkSegmentationView.cpp
*/
class MITK_CORE_EXPORT PlanePositionManagerService
{
public:
PlanePositionManagerService();
~PlanePositionManagerService();
/**
\brief Adds a new plane position to the list. If this geometry is identical to one of the list nothing will be added
\a plane THE FIRST! slice of the slice stack
\a sliceIndex the slice number of the selected slice
\return returns the ID i.e. the position in the positionlist. If the PlaneGeometry which is to be added already exists the existing
ID will be returned.
*/
- unsigned int AddNewPlanePosition(const mitk::Geometry2D* plane, unsigned int sliceIndex = 0);
+ unsigned int AddNewPlanePosition(const mitk::PlaneGeometry* plane, unsigned int sliceIndex = 0);
/**
\brief Removes the plane at the position \a ID from the list.
\a ID the plane ID which should be removed, i.e. its position in the list
\return true if the plane was removed successfully and false if it is an invalid ID
*/
bool RemovePlanePosition(unsigned int ID);
/// \brief Clears the complete positionlist
void RemoveAllPlanePositions();
/**
\brief Getter for a specific plane position with a given ID
\a ID the ID of the plane position
\return Returns a RestorePlanePositionOperation which can be executed by th SliceNavigationController or NULL for an invalid ID
*/
mitk::RestorePlanePositionOperation* GetPlanePosition( unsigned int ID);
/// \brief Getting the number of all stored planes
unsigned int GetNumberOfPlanePositions();
private:
// Disable copy constructor and assignment operator.
PlanePositionManagerService(const PlanePositionManagerService&);
PlanePositionManagerService& operator=(const PlanePositionManagerService&);
std::vector<mitk::RestorePlanePositionOperation*> m_PositionList;
};
}
US_DECLARE_SERVICE_INTERFACE(mitk::PlanePositionManagerService, "org.mitk.PlanePositionManagerService")
#endif
diff --git a/Core/Code/Controllers/mitkRenderingManager.cpp b/Core/Code/Controllers/mitkRenderingManager.cpp
index 045251f982..e40878169f 100644
--- a/Core/Code/Controllers/mitkRenderingManager.cpp
+++ b/Core/Code/Controllers/mitkRenderingManager.cpp
@@ -1,926 +1,926 @@
/*===================================================================
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 "mitkRenderingManager.h"
#include "mitkRenderingManagerFactory.h"
#include "mitkBaseRenderer.h"
#include "mitkGlobalInteraction.h"
#include "mitkNodePredicateNot.h"
#include "mitkNodePredicateProperty.h"
#include "mitkProportionalTimeGeometry.h"
#include <vtkRenderWindow.h>
#include <itkCommand.h>
#include "mitkVector.h"
#include <itkAffineGeometryFrame.h>
#include <itkScalableAffineTransform.h>
#include <mitkVtkPropRenderer.h>
#include <algorithm>
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( SliceNavigationController::New("dummy") ),
m_DataStorage( NULL ),
m_ConstrainedPaddingZooming ( true )
{
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);
if (callbacks_it != this->m_RenderWindowCallbacksList.end())
{
(*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 );
// 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);
if(callbacks_it != this->m_RenderWindowCallbacksList.end())
{
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 );
if(rw_it != m_AllRenderWindows.end())
{
// 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 )
{
// If the renderWindow is not valid, we do not want to inadvertantly create
// an entry in the m_RenderWindowList map. It is possible if the user is
// regularly calling AddRenderer and RemoveRenderer for a rendering update
// to come into this method with a renderWindow pointer that is valid in the
// sense that the window does exist within the application, but that
// renderWindow has been temporarily removed from this RenderingManager for
// performance reasons.
if (m_RenderWindowList.find( renderWindow ) == m_RenderWindowList.end())
{
return;
}
m_RenderWindowList[renderWindow] = RENDERING_REQUESTED;
if ( !m_UpdatePending )
{
m_UpdatePending = true;
this->GenerateRenderingRequestEvent();
}
}
void
RenderingManager
::ForceImmediateUpdate( vtkRenderWindow *renderWindow )
{
// If the renderWindow is not valid, we do not want to inadvertantly create
// an entry in the m_RenderWindowList map. It is possible if the user is
// regularly calling AddRenderer and RemoveRenderer for a rendering update
// to come into this method with a renderWindow pointer that is valid in the
// sense that the window does exist within the application, but that
// renderWindow has been temporarily removed from this RenderingManager for
// performance reasons.
if (m_RenderWindowList.find( renderWindow ) == m_RenderWindowList.end())
{
return;
}
// 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::VtkPropRenderer*>(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 );
}
}
}
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)) )
{
// Immediately repaint this window (implementation platform specific)
// If the size is 0, it crashes
this->ForceImmediateUpdate(it->first);
}
}
}
void RenderingManager::InitializeViewsByBoundingObjects( const DataStorage *ds)
{
if (!ds)
return;
// get all nodes that have not set "includeInBoundingBox" to false
mitk::NodePredicateNot::Pointer pred
= mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("includeInBoundingBox"
, mitk::BoolProperty::New(false)));
mitk::DataStorage::SetOfObjects::ConstPointer rs = ds->GetSubset(pred);
// calculate bounding geometry of these nodes
mitk::TimeGeometry::Pointer bounds = ds->ComputeBoundingGeometry3D(rs, "visible");
// initialize the views to the bounding geometry
this->InitializeViews(bounds);
}
//TODO_GOETZ
// Remove old function, so only this one is working.
bool
RenderingManager
-::InitializeViews( const Geometry3D * dataGeometry, RequestType type, bool preserveRoughOrientationInWorldSpace )
+::InitializeViews( const BaseGeometry * dataGeometry, RequestType type, bool preserveRoughOrientationInWorldSpace )
{
ProportionalTimeGeometry::Pointer propTimeGeometry = ProportionalTimeGeometry::New();
- propTimeGeometry->Initialize(dynamic_cast<Geometry3D *>(dataGeometry->Clone().GetPointer()), 1);
+ propTimeGeometry->Initialize(dynamic_cast<BaseGeometry *>(dataGeometry->Clone().GetPointer()), 1);
return InitializeViews(propTimeGeometry,type, preserveRoughOrientationInWorldSpace);
}
bool
RenderingManager
::InitializeViews( const TimeGeometry * dataGeometry, RequestType type, bool /*preserveRoughOrientationInWorldSpace*/ )
{
MITK_DEBUG << "initializing views";
bool boundingBoxInitialized = false;
TimeGeometry::ConstPointer timeGeometry = dataGeometry;
TimeGeometry::Pointer modifiedGeometry = NULL;
if (dataGeometry!=NULL)
{
modifiedGeometry = dataGeometry->Clone();
}
// //TODO_GOETZ previously this code section has been disabled by
// a later asignment to geometry (e.g. timeGeometry)
// This has been fixed during Geometry-1-Plattform Project
// Propably this code is not working anymore, test!!
/*
if (dataGeometry && preserveRoughOrientationInWorldSpace)
{
// clone the input geometry
assert(modifiedGeometry.IsNotNull());
// construct an affine transform from it
Geometry3D::TransformType::Pointer transform = Geometry3D::TransformType::New();
assert( modifiedGeometry->GetGeometryForTimeStep(0)->GetIndexToWorldTransform() );
transform->SetMatrix( modifiedGeometry->GetGeometryForTimeStep(0)->GetIndexToWorldTransform()->GetMatrix() );
transform->SetOffset( modifiedGeometry->GetGeometryForTimeStep(0)->GetIndexToWorldTransform()->GetOffset() );
// get transform matrix
Geometry3D::TransformType::MatrixType::InternalMatrixType& oldMatrix =
const_cast< Geometry3D::TransformType::MatrixType::InternalMatrixType& > ( transform->GetMatrix().GetVnlMatrix() );
Geometry3D::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
ScalarType max = std::numeric_limits<ScalarType>::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<ScalarType> 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
Geometry3D::TransformType::MatrixType newMatrixITK( newMatrix );
transform->SetMatrix( newMatrixITK );
transform->SetOffset( offset );
modifiedGeometry->SetIndexToWorldTransform( transform );
geometry = modifiedGeometry;
}*/
int warningLevel = vtkObject::GetGlobalWarningDisplay();
vtkObject::GlobalWarningDisplayOff();
if ( (timeGeometry.IsNotNull() ) && (const_cast< mitk::BoundingBox * >(
timeGeometry->GetBoundingBoxInWorld())->GetDiagonalLength2() > mitk::eps) )
{
boundingBoxInitialized = true;
}
if (timeGeometry.IsNotNull() )
{// make sure bounding box has an extent bigger than zero in any direction
// clone the input geometry
//Old Geometry3D::Pointer modifiedGeometry = dynamic_cast<Geometry3D*>( dataGeometry->Clone().GetPointer() );
assert(modifiedGeometry.IsNotNull());
for (TimeStepType step = 0; step < modifiedGeometry->CountTimeSteps(); ++step)
{
- Geometry3D::BoundsArrayType newBounds = modifiedGeometry->GetGeometryForTimeStep(step)->GetBounds();
+ BaseGeometry::BoundsArrayType newBounds = modifiedGeometry->GetGeometryForTimeStep(step)->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;
}
}
modifiedGeometry->GetGeometryForTimeStep(step)->SetBounds(newBounds);
}
}
timeGeometry = 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, timeGeometry,
boundingBoxInitialized, id );
}
}
if ( boundingBoxInitialized )
{
m_TimeNavigationController->SetInputWorldTimeGeometry( timeGeometry );
}
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 Geometry3D * geometry, bool initializeGlobalTimeSNC )
+bool RenderingManager::InitializeView( vtkRenderWindow * renderWindow, const BaseGeometry * geometry, bool initializeGlobalTimeSNC )
{
ProportionalTimeGeometry::Pointer propTimeGeometry = ProportionalTimeGeometry::New();
- propTimeGeometry->Initialize(dynamic_cast<Geometry3D *>(geometry->Clone().GetPointer()), 1);
+ propTimeGeometry->Initialize(dynamic_cast<BaseGeometry *>(geometry->Clone().GetPointer()), 1);
return InitializeView(renderWindow, propTimeGeometry, initializeGlobalTimeSNC );
}
bool RenderingManager::InitializeView( vtkRenderWindow * renderWindow, const TimeGeometry * geometry, bool initializeGlobalTimeSNC )
{
bool boundingBoxInitialized = false;
int warningLevel = vtkObject::GetGlobalWarningDisplay();
vtkObject::GlobalWarningDisplayOff();
if ( (geometry != NULL ) && (const_cast< mitk::BoundingBox * >(
geometry->GetBoundingBoxInWorld())->GetDiagonalLength2() > mitk::eps) )
{
boundingBoxInitialized = true;
}
mitk::BaseRenderer *baseRenderer =
mitk::BaseRenderer::GetInstance( renderWindow );
int id = baseRenderer->GetMapperID();
this->InternalViewInitialization( baseRenderer, geometry,
boundingBoxInitialized, id );
if ( boundingBoxInitialized && initializeGlobalTimeSNC )
{
m_TimeNavigationController->SetInputWorldTimeGeometry( 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::TimeGeometry *geometry, bool boundingBoxInitialized, int mapperID )
{
mitk::SliceNavigationController *nc = baseRenderer->GetSliceNavigationController();
// Re-initialize view direction
nc->SetViewDirectionToDefault();
if ( boundingBoxInitialized )
{
// Set geometry for NC
nc->SetInputWorldTimeGeometry( 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();
}
}
const SliceNavigationController* RenderingManager::GetTimeNavigationController() const
{
return m_TimeNavigationController.GetPointer();
}
SliceNavigationController* RenderingManager::GetTimeNavigationController()
{
return m_TimeNavigationController.GetPointer();
}
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::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(); iter<m_AllRenderWindows.end(); iter++ )
{
mitk::BaseRenderer::GetInstance( (*iter) )->SetDataStorage( 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/Controllers/mitkRenderingManager.h b/Core/Code/Controllers/mitkRenderingManager.h
index 10e531ab86..2652835e2c 100644
--- a/Core/Code/Controllers/mitkRenderingManager.h
+++ b/Core/Code/Controllers/mitkRenderingManager.h
@@ -1,407 +1,407 @@
/*===================================================================
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 MITKRENDERINGMANAGER_H_HEADER_INCLUDED_C135A197
#define MITKRENDERINGMANAGER_H_HEADER_INCLUDED_C135A197
#include <MitkCoreExports.h>
#include <vtkCallbackCommand.h>
#include <string>
#include <itkObject.h>
#include <itkObjectFactory.h>
#include "mitkPropertyList.h"
#include "mitkProperties.h"
#include "mitkTimeGeometry.h"
class vtkRenderWindow;
class vtkObject;
namespace mitk
{
class RenderingManager;
class RenderingManagerFactory;
-class Geometry3D;
+class BaseGeometry;
class SliceNavigationController;
class BaseRenderer;
class DataStorage;
class GlobalInteraction;
/**
* \brief Manager for coordinating the rendering process.
*
* RenderingManager is a central instance retrieving and executing
* RenderWindow update requests. Its main purpose is to coordinate
* distributed requests which cannot be aware of each other - lacking the
* knowledge of whether they are really necessary or not. For example, two
* objects might determine that a specific RenderWindow needs to be updated.
* This would result in one unnecessary update, if both executed the update
* on their own.
*
* The RenderingManager addresses this by letting each such object
* <em>request</em> an update, and waiting for other objects to possibly
* issue the same request. The actual update will then only be executed at a
* well-defined point in the main event loop (this may be each time after
* event processing is done).
*
* Convinience methods for updating all RenderWindows which have been
* registered with the RenderingManager exist. If theses methods are not
* used, it is not required to register (add) RenderWindows prior to using
* the RenderingManager.
*
* The methods #ForceImmediateUpdate() and #ForceImmediateUpdateAll() can
* be used to force the RenderWindow update execution without any delay,
* bypassing the request functionality.
*
* The interface of RenderingManager is platform independent. Platform
* specific subclasses have to be implemented, though, to supply an
* appropriate event issueing for controlling the update execution process.
* See method documentation for a description of how this can be done.
*
* \sa TestingRenderingManager An "empty" RenderingManager implementation which
* can be used in tests etc.
*
*/
class MITK_CORE_EXPORT RenderingManager : public itk::Object
{
public:
mitkClassMacro(RenderingManager,itk::Object);
typedef std::vector< vtkRenderWindow* > RenderWindowVector;
typedef std::vector< float > FloatVector;
typedef std::vector< bool > BoolVector;
typedef itk::SmartPointer< DataStorage > DataStoragePointer;
typedef itk::SmartPointer< GlobalInteraction > GlobalInteractionPointer;
enum RequestType
{
REQUEST_UPDATE_ALL = 0,
REQUEST_UPDATE_2DWINDOWS,
REQUEST_UPDATE_3DWINDOWS
};
static Pointer New();
/** Set the object factory which produces the desired platform specific
* RenderingManager singleton instance. */
static void SetFactory( RenderingManagerFactory *factory );
/** Get the object factory which produces the platform specific
* RenderingManager instances. */
static const RenderingManagerFactory *GetFactory();
/** Returns true if a factory has already been set. */
static bool HasFactory();
/** Get the RenderingManager singleton instance. */
static RenderingManager *GetInstance();
/** Returns true if the singleton instance does already exist. */
static bool IsInstantiated();
/** Adds a RenderWindow. This is required if the methods #RequestUpdateAll
* or #ForceImmediateUpdate are to be used. */
void AddRenderWindow( vtkRenderWindow *renderWindow );
/** Removes a RenderWindow. */
void RemoveRenderWindow( vtkRenderWindow *renderWindow );
/** Get a list of all registered RenderWindows */
const RenderWindowVector &GetAllRegisteredRenderWindows();
/** Requests an update for the specified RenderWindow, to be executed as
* soon as the main loop is ready for rendering. */
void RequestUpdate( vtkRenderWindow *renderWindow );
/** Immediately executes an update of the specified RenderWindow. */
void ForceImmediateUpdate( vtkRenderWindow *renderWindow );
/** Requests all currently registered RenderWindows to be updated.
* If only 2D or 3D windows should be updated, this can be specified
* via the parameter requestType. */
void RequestUpdateAll( RequestType type = REQUEST_UPDATE_ALL );
/** Immediately executes an update of all registered RenderWindows.
* If only 2D or 3D windows should be updated, this can be specified
* via the parameter requestType. */
void ForceImmediateUpdateAll( RequestType type = REQUEST_UPDATE_ALL );
/** Initializes the windows specified by requestType to the geometry of the
* given DataStorage. */
//virtual bool InitializeViews( const DataStorage *storage, const DataNode* node = NULL,
// RequestType type = REQUEST_UPDATE_ALL, bool preserveRoughOrientationInWorldSpace = false );
/** Initializes the windows specified by requestType to the given
* geometry. PLATFORM SPECIFIC. TODO: HOW IS THIS PLATFORM SPECIFIC? */
- virtual bool InitializeViews( const Geometry3D *geometry,
+ virtual bool InitializeViews( const BaseGeometry *geometry,
RequestType type = REQUEST_UPDATE_ALL, bool preserveRoughOrientationInWorldSpace = false );
virtual bool InitializeViews( const TimeGeometry *geometry,
RequestType type = REQUEST_UPDATE_ALL, bool preserveRoughOrientationInWorldSpace = false );
/** Initializes the windows to the default viewing direction
* (geomtry information is NOT changed). PLATFORM SPECIFIC. */
virtual bool InitializeViews( RequestType type = REQUEST_UPDATE_ALL );
/** Initializes the specified window to the geometry of the given
* DataNode. Set "initializeGlobalTimeSNC" to true in order to use this
* geometry as global TimeGeometry. PLATFORM SPECIFIC. */
//virtual bool InitializeView( vtkRenderWindow *renderWindow, const DataStorage* ds, const DataNode* node = NULL, bool initializeGlobalTimeSNC = false );
/** Initializes the specified window to the given geometry. Set
* "initializeGlobalTimeSNC" to true in order to use this geometry as
* global TimeGeometry. PLATFORM SPECIFIC. */
- virtual bool InitializeView( vtkRenderWindow *renderWindow, const Geometry3D *geometry, bool initializeGlobalTimeSNC = false);
+ virtual bool InitializeView( vtkRenderWindow *renderWindow, const BaseGeometry *geometry, bool initializeGlobalTimeSNC = false);
virtual bool InitializeView( vtkRenderWindow *renderWindow, const TimeGeometry *geometry, bool initializeGlobalTimeSNC = false);
/** Initializes the specified window to the default viewing direction
* (geomtry information is NOT changed). PLATFORM SPECIFIC. */
virtual bool InitializeView( vtkRenderWindow *renderWindow );
/**
* @brief Initializes the renderwindows by the aggregated geometry of
* all objects that are held in the data storage.
* This is basically a global reinit
* @param The data storage from which the bounding object can be retrieved
*/
virtual void InitializeViewsByBoundingObjects(const DataStorage * );
/** Gets the (global) SliceNavigationController responsible for
* time-slicing. */
const SliceNavigationController *GetTimeNavigationController() const;
/** Gets the (global) SliceNavigationController responsible for
* time-slicing. */
SliceNavigationController *GetTimeNavigationController();
virtual ~RenderingManager();
/** Executes all pending requests. This method has to be called by the
* system whenever a RenderingManager induced request event occurs in
* the system pipeline (see concrete RenderingManager implementations). */
virtual void ExecutePendingRequests();
bool IsRendering() const;
void AbortRendering();
/** En-/Disable LOD increase globally. */
itkSetMacro( LODIncreaseBlocked, bool );
/** En-/Disable LOD increase globally. */
itkGetMacro( LODIncreaseBlocked, bool );
/** En-/Disable LOD increase globally. */
itkBooleanMacro( LODIncreaseBlocked );
/** En-/Disable LOD abort mechanism. */
itkSetMacro( LODAbortMechanismEnabled, bool );
/** En-/Disable LOD abort mechanism. */
itkGetMacro( LODAbortMechanismEnabled, bool );
/** En-/Disable LOD abort mechanism. */
itkBooleanMacro( LODAbortMechanismEnabled );
/** Force a sub-class to start a timer for a pending hires-rendering request */
virtual void StartOrResetTimer() {};
/** To be called by a sub-class from a timer callback */
void ExecutePendingHighResRenderingRequest();
virtual void DoStartRendering() {};
virtual void DoMonitorRendering() {};
virtual void DoFinishAbortRendering() {};
int GetNextLOD( BaseRenderer* renderer );
/** Set current LOD (NULL means all renderers)*/
void SetMaximumLOD( unsigned int max );
void SetShading( bool state, unsigned int lod );
bool GetShading( unsigned int lod );
void SetClippingPlaneStatus( bool status );
bool GetClippingPlaneStatus();
void SetShadingValues( float ambient, float diffuse,
float specular, float specpower );
FloatVector &GetShadingValues();
/** Returns a property list */
PropertyList::Pointer GetPropertyList() const;
/** Returns a property from m_PropertyList */
BaseProperty* GetProperty(const char *propertyKey) const;
/** Sets or adds (if not present) a property in m_PropertyList */
void SetProperty(const char *propertyKey, BaseProperty* propertyValue);
/**
* \brief Setter / Getter for internal DataStorage
*
* Sets / returns the mitk::DataStorage that is used internally. This instance holds all mitk::DataNodes that are
* rendered by the registered BaseRenderers.
*
* If this DataStorage is changed at runtime by calling SetDataStorage(),
* all currently registered BaseRenderers are automatically given the correct instance.
* When a new BaseRenderer is added, it is automatically initialized with the currently active DataStorage.
*/
void SetDataStorage( mitk::DataStorage* storage );
/**
* \brief Setter / Getter for internal DataStorage
*
* Sets / returns the mitk::DataStorage that is used internally. This instance holds all mitk::DataNodes that are
* rendered by the registered BaseRenderers.
*
* If this DataStorage is changed at runtime by calling SetDataStorage(),
* all currently registered BaseRenderers are automatically given the correct instance.
* When a new BaseRenderer is added, it is automatically initialized with the currently active DataStorage.
*/
mitk::DataStorage* GetDataStorage();
/**
* \brief Setter / Getter for internal GloabInteraction
*
* Sets / returns the instance of mitk::GlobalInteraction that is internally held.
* It'S not actually used by this class but offers it to all registered BaseRenderers.
* These need it for their own internal initialization of the FocusManager and the corresponding EventMappers.
*/
void SetGlobalInteraction( mitk::GlobalInteraction* globalInteraction );
/**
* \brief Setter / Getter for internal GloabInteraction
*
* Sets / returns the instance of mitk::GlobalInteraction that is internally held.
* It'S not actually used by this class but offers it to all registered BaseRenderers.
* These need it for their own internal initialization of the FocusManager and the corresponding EventMappers.
*/
mitk::GlobalInteraction* GetGlobalInteraction();
itkSetMacro(ConstrainedPaddingZooming, bool);
protected:
enum
{
RENDERING_INACTIVE = 0,
RENDERING_REQUESTED,
RENDERING_INPROGRESS
};
RenderingManager();
/** Abstract method for generating a system specific event for rendering
* request. This method is called whenever an update is requested */
virtual void GenerateRenderingRequestEvent() = 0;
virtual void InitializePropertyList();
bool m_UpdatePending;
typedef std::map< BaseRenderer *, unsigned int > RendererIntMap;
typedef std::map< BaseRenderer *, bool > RendererBoolMap;
RendererBoolMap m_RenderingAbortedMap;
RendererIntMap m_NextLODMap;
unsigned int m_MaxLOD;
bool m_LODIncreaseBlocked;
bool m_LODAbortMechanismEnabled;
BoolVector m_ShadingEnabled;
bool m_ClippingPlaneEnabled;
FloatVector m_ShadingValues;
static void RenderingStartCallback(
vtkObject *caller, unsigned long eid, void *clientdata, void *calldata );
static void RenderingProgressCallback(
vtkObject *caller, unsigned long eid, void *clientdata, void *calldata );
static void RenderingEndCallback(
vtkObject *caller, unsigned long eid, void *clientdata, void *calldata );
typedef std::map< vtkRenderWindow *, int > RenderWindowList;
RenderWindowList m_RenderWindowList;
RenderWindowVector m_AllRenderWindows;
struct RenderWindowCallbacks
{
vtkCallbackCommand* commands[3u];
};
typedef std::map<vtkRenderWindow*, RenderWindowCallbacks> RenderWindowCallbacksList;
RenderWindowCallbacksList m_RenderWindowCallbacksList;
itk::SmartPointer<SliceNavigationController> m_TimeNavigationController;
static RenderingManager::Pointer s_Instance;
static RenderingManagerFactory *s_RenderingManagerFactory;
PropertyList::Pointer m_PropertyList;
DataStoragePointer m_DataStorage;
GlobalInteractionPointer m_GlobalInteraction;
bool m_ConstrainedPaddingZooming;
private:
void InternalViewInitialization(
mitk::BaseRenderer *baseRenderer, const mitk::TimeGeometry *geometry,
bool boundingBoxInitialized, int mapperID );
};
#pragma GCC visibility push(default)
itkEventMacro( RenderingManagerEvent, itk::AnyEvent );
itkEventMacro( RenderingManagerViewsInitializedEvent, RenderingManagerEvent );
#pragma GCC visibility pop
/**
* Generic RenderingManager implementation for "non-rendering-plattform",
* e.g. for tests. Its factory (TestingRenderingManagerFactory) is
* automatically on start-up and is used by default if not other
* RenderingManagerFactory is instantiated explicitly thereafter.
* (see mitkRenderingManager.cpp)
*/
class MITK_CORE_EXPORT TestingRenderingManager : public RenderingManager
{
public:
mitkClassMacro(TestingRenderingManager,RenderingManager);
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
protected:
virtual void GenerateRenderingRequestEvent()
{
// ForceImmediateUpdateAll();
};
};
} // namespace mitk
#endif /* MITKRenderingManager_H_HEADER_INCLUDED_C135A197 */
diff --git a/Core/Code/Controllers/mitkSliceNavigationController.cpp b/Core/Code/Controllers/mitkSliceNavigationController.cpp
index ed681526be..07af28be43 100644
--- a/Core/Code/Controllers/mitkSliceNavigationController.cpp
+++ b/Core/Code/Controllers/mitkSliceNavigationController.cpp
@@ -1,841 +1,837 @@
/*===================================================================
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 "mitkSliceNavigationController.h"
#include "mitkBaseRenderer.h"
#include "mitkSlicedGeometry3D.h"
#include "mitkPlaneGeometry.h"
#include "mitkOperation.h"
#include "mitkOperationActor.h"
#include "mitkStateEvent.h"
#include "mitkCrosshairPositionEvent.h"
#include "mitkPositionEvent.h"
#include "mitkProportionalTimeGeometry.h"
#include "mitkInteractionConst.h"
#include "mitkAction.h"
#include "mitkGlobalInteraction.h"
#include "mitkEventMapper.h"
#include "mitkFocusManager.h"
#include "mitkVtkPropRenderer.h"
#include "mitkRenderingManager.h"
#include "mitkInteractionConst.h"
#include "mitkPointOperation.h"
#include "mitkPlaneOperation.h"
#include "mitkUndoController.h"
#include "mitkOperationEvent.h"
#include "mitkNodePredicateDataType.h"
#include "mitkStatusBar.h"
#include "mitkImage.h"
#include "mitkApplyTransformMatrixOperation.h"
#include "mitkMemoryUtilities.h"
#include <itkCommand.h>
namespace mitk {
-
SliceNavigationController::SliceNavigationController( const char *type )
: BaseController( type ),
m_InputWorldGeometry3D( NULL ),
m_InputWorldTimeGeometry( NULL ),
m_CreatedWorldGeometry( NULL ),
m_ViewDirection( Axial ),
m_DefaultViewDirection( Axial ),
m_RenderingManager( NULL ),
m_Renderer( NULL ),
m_Top( false ),
m_FrontSide( false ),
m_Rotated( false ),
m_BlockUpdate( false ),
m_SliceLocked( false ),
m_SliceRotationLocked( false ),
m_OldPos(0)
{
typedef itk::SimpleMemberCommand< SliceNavigationController > SNCCommandType;
SNCCommandType::Pointer sliceStepperChangedCommand, timeStepperChangedCommand;
sliceStepperChangedCommand = SNCCommandType::New();
timeStepperChangedCommand = SNCCommandType::New();
sliceStepperChangedCommand->SetCallbackFunction(
this, &SliceNavigationController::SendSlice );
timeStepperChangedCommand->SetCallbackFunction(
this, &SliceNavigationController::SendTime );
m_Slice->AddObserver( itk::ModifiedEvent(), sliceStepperChangedCommand );
m_Time->AddObserver( itk::ModifiedEvent(), timeStepperChangedCommand );
m_Slice->SetUnitName( "mm" );
m_Time->SetUnitName( "ms" );
m_Top = false;
m_FrontSide = false;
m_Rotated = false;
}
SliceNavigationController::~SliceNavigationController()
{
}
void
-SliceNavigationController::SetInputWorldGeometry3D( const Geometry3D *geometry )
+SliceNavigationController::SetInputWorldGeometry3D( const BaseGeometry *geometry )
{
if ( geometry != NULL )
{
if ( const_cast< BoundingBox * >( geometry->GetBoundingBox())
->GetDiagonalLength2() < eps )
{
itkWarningMacro( "setting an empty bounding-box" );
geometry = NULL;
}
}
if ( m_InputWorldGeometry3D != geometry )
{
m_InputWorldGeometry3D = geometry;
m_InputWorldTimeGeometry = NULL;
this->Modified();
}
}
void
SliceNavigationController::SetInputWorldTimeGeometry( const TimeGeometry *geometry )
{
if ( geometry != NULL )
{
if ( const_cast< BoundingBox * >( geometry->GetBoundingBoxInWorld())
->GetDiagonalLength2() < eps )
{
itkWarningMacro( "setting an empty bounding-box" );
geometry = NULL;
}
}
if ( m_InputWorldTimeGeometry != geometry )
{
m_InputWorldTimeGeometry = geometry;
m_InputWorldGeometry3D = NULL;
this->Modified();
}
}
RenderingManager *
SliceNavigationController::GetRenderingManager() const
{
mitk::RenderingManager* renderingManager = m_RenderingManager.GetPointer();
if (renderingManager != NULL)
return renderingManager;
if ( m_Renderer != NULL )
{
renderingManager = m_Renderer->GetRenderingManager();
if (renderingManager != NULL)
return renderingManager;
}
return mitk::RenderingManager::GetInstance();
}
void SliceNavigationController::SetViewDirectionToDefault()
{
m_ViewDirection = m_DefaultViewDirection;
}
const char* SliceNavigationController::GetViewDirectionAsString()
{
const char* viewDirectionString;
switch(m_ViewDirection)
{
case SliceNavigationController::Axial:
viewDirectionString = "Axial";
break;
case SliceNavigationController::Sagittal:
viewDirectionString = "Sagittal";
break;
case SliceNavigationController::Frontal:
viewDirectionString = "Coronal";
break;
case SliceNavigationController::Original:
viewDirectionString = "Original";
break;
default:
viewDirectionString = "No View Direction Available";
break;
}
return viewDirectionString;
}
void SliceNavigationController::Update()
{
if ( !m_BlockUpdate )
{
if ( m_ViewDirection == Axial )
{
this->Update( Axial, false, false, true );
}
else
{
this->Update( m_ViewDirection );
}
}
}
void
SliceNavigationController::Update(
SliceNavigationController::ViewDirection viewDirection,
bool top, bool frontside, bool rotated )
{
TimeGeometry::ConstPointer worldTimeGeometry = m_InputWorldTimeGeometry;
if( m_BlockUpdate ||
( m_InputWorldTimeGeometry.IsNull() && m_InputWorldGeometry3D.IsNull() ) ||
( (worldTimeGeometry.IsNotNull()) && (worldTimeGeometry->CountTimeSteps() == 0) )
)
{
return;
}
m_BlockUpdate = true;
if ( m_InputWorldTimeGeometry.IsNotNull() &&
m_LastUpdateTime < m_InputWorldTimeGeometry->GetMTime() )
{
Modified();
}
if ( m_InputWorldGeometry3D.IsNotNull() &&
m_LastUpdateTime < m_InputWorldGeometry3D->GetMTime() )
{
Modified();
}
this->SetViewDirection( viewDirection );
this->SetTop( top );
this->SetFrontSide( frontside );
this->SetRotated( rotated );
if ( m_LastUpdateTime < GetMTime() )
{
m_LastUpdateTime = GetMTime();
// initialize the viewplane
SlicedGeometry3D::Pointer slicedWorldGeometry = NULL;
- Geometry3D::ConstPointer currentGeometry = NULL;
+ BaseGeometry::ConstPointer currentGeometry = NULL;
if (m_InputWorldTimeGeometry.IsNotNull())
if (m_InputWorldTimeGeometry->IsValidTimeStep(GetTime()->GetPos()))
currentGeometry = m_InputWorldTimeGeometry->GetGeometryForTimeStep(GetTime()->GetPos());
else
currentGeometry = m_InputWorldTimeGeometry->GetGeometryForTimeStep(0);
else
currentGeometry = m_InputWorldGeometry3D;
m_CreatedWorldGeometry = NULL;
switch ( viewDirection )
{
case Original:
if ( worldTimeGeometry.IsNotNull())
{
m_CreatedWorldGeometry = worldTimeGeometry->Clone();
worldTimeGeometry = m_CreatedWorldGeometry.GetPointer();
slicedWorldGeometry = dynamic_cast< SlicedGeometry3D * >(
m_CreatedWorldGeometry->GetGeometryForTimeStep( this->GetTime()->GetPos() ).GetPointer() );
if ( slicedWorldGeometry.IsNotNull() )
{
break;
}
}
else
{
const SlicedGeometry3D *worldSlicedGeometry =
dynamic_cast< const SlicedGeometry3D * >(
currentGeometry.GetPointer());
if ( worldSlicedGeometry != NULL )
{
slicedWorldGeometry = static_cast< SlicedGeometry3D * >(
currentGeometry->Clone().GetPointer());
break;
}
}
//else: use Axial: no "break" here!!
case Axial:
slicedWorldGeometry = SlicedGeometry3D::New();
slicedWorldGeometry->InitializePlanes(
currentGeometry, PlaneGeometry::Axial,
top, frontside, rotated );
slicedWorldGeometry->SetSliceNavigationController( this );
break;
case Frontal:
slicedWorldGeometry = SlicedGeometry3D::New();
slicedWorldGeometry->InitializePlanes( currentGeometry,
PlaneGeometry::Frontal, top, frontside, rotated );
slicedWorldGeometry->SetSliceNavigationController( this );
break;
case Sagittal:
slicedWorldGeometry = SlicedGeometry3D::New();
slicedWorldGeometry->InitializePlanes( currentGeometry,
PlaneGeometry::Sagittal, top, frontside, rotated );
slicedWorldGeometry->SetSliceNavigationController( this );
break;
default:
itkExceptionMacro("unknown ViewDirection");
}
m_Slice->SetPos( 0 );
m_Slice->SetSteps( (int)slicedWorldGeometry->GetSlices() );
if ( m_CreatedWorldGeometry.IsNull() )
{
// initialize TimeGeometry
m_CreatedWorldGeometry = ProportionalTimeGeometry::New();
}
if ( worldTimeGeometry.IsNull())
{
m_CreatedWorldGeometry = ProportionalTimeGeometry::New();
dynamic_cast<ProportionalTimeGeometry *>(m_CreatedWorldGeometry.GetPointer())->Initialize(slicedWorldGeometry, 1);
m_Time->SetSteps( 0 );
m_Time->SetPos( 0 );
m_Time->InvalidateRange();
}
else
{
m_BlockUpdate = true;
m_Time->SetSteps( worldTimeGeometry->CountTimeSteps() );
m_Time->SetPos( 0 );
const TimeBounds &timeBounds = worldTimeGeometry->GetTimeBounds();
m_Time->SetRange( timeBounds[0], timeBounds[1] );
m_BlockUpdate = false;
assert( worldTimeGeometry->GetGeometryForTimeStep( this->GetTime()->GetPos() ).IsNotNull() );
- slicedWorldGeometry->SetTimeBounds(
- worldTimeGeometry->GetGeometryForTimeStep( this->GetTime()->GetPos() )->GetTimeBounds() );
+ TimePointType minimumTimePoint = worldTimeGeometry->TimeStepToTimePoint(this->GetTime()->GetPos());
+ TimePointType stepDuration = worldTimeGeometry->TimeStepToTimePoint(this->GetTime()->GetPos()+1)-worldTimeGeometry->TimeStepToTimePoint(this->GetTime()->GetPos());
//@todo implement for non-evenly-timed geometry!
m_CreatedWorldGeometry = ProportionalTimeGeometry::New();
dynamic_cast<ProportionalTimeGeometry *>(m_CreatedWorldGeometry.GetPointer())->Initialize(slicedWorldGeometry, worldTimeGeometry->CountTimeSteps());
+ dynamic_cast<ProportionalTimeGeometry *>(m_CreatedWorldGeometry.GetPointer())->GetMinimumTimePoint(minimumTimePoint);
+ dynamic_cast<ProportionalTimeGeometry *>(m_CreatedWorldGeometry.GetPointer())->SetStepDuration(stepDuration);
}
}
// unblock update; we may do this now, because if m_BlockUpdate was already
// true before this method was entered, then we will never come here.
m_BlockUpdate = false;
// Send the geometry. Do this even if nothing was changed, because maybe
// Update() was only called to re-send the old geometry and time/slice data.
this->SendCreatedWorldGeometry();
this->SendSlice();
this->SendTime();
// Adjust the stepper range of slice stepper according to geometry
this->AdjustSliceStepperRange();
}
void
SliceNavigationController::SendCreatedWorldGeometry()
{
// Send the geometry. Do this even if nothing was changed, because maybe
// Update() was only called to re-send the old geometry.
if ( !m_BlockUpdate )
{
this->InvokeEvent( GeometrySendEvent(m_CreatedWorldGeometry, 0) );
}
}
void
SliceNavigationController::SendCreatedWorldGeometryUpdate()
{
if ( !m_BlockUpdate )
{
this->InvokeEvent(
GeometryUpdateEvent(m_CreatedWorldGeometry, m_Slice->GetPos()) );
}
}
void
SliceNavigationController::SendSlice()
{
if ( !m_BlockUpdate )
{
if ( m_CreatedWorldGeometry.IsNotNull() )
{
this->InvokeEvent(
GeometrySliceEvent(m_CreatedWorldGeometry, m_Slice->GetPos()) );
// send crosshair event
crosshairPositionEvent.Send();
// Request rendering update for all views
this->GetRenderingManager()->RequestUpdateAll();
}
}
}
void
SliceNavigationController::SendTime()
{
if ( !m_BlockUpdate )
{
if ( m_CreatedWorldGeometry.IsNotNull() )
{
this->InvokeEvent(
GeometryTimeEvent(m_CreatedWorldGeometry, m_Time->GetPos()) );
// Request rendering update for all views
this->GetRenderingManager()->RequestUpdateAll();
}
}
}
void
SliceNavigationController::SetGeometry( const itk::EventObject & )
{
}
void
SliceNavigationController
::SetGeometryTime( const itk::EventObject &geometryTimeEvent )
{
const SliceNavigationController::GeometryTimeEvent *timeEvent =
dynamic_cast< const SliceNavigationController::GeometryTimeEvent * >(
&geometryTimeEvent);
assert( timeEvent != NULL );
TimeGeometry *timeGeometry = timeEvent->GetTimeGeometry();
assert( timeGeometry != NULL );
if ( m_CreatedWorldGeometry.IsNotNull() )
{
int timeStep = (int) timeEvent->GetPos();
ScalarType timeInMS;
timeInMS = timeGeometry->TimeStepToTimePoint( timeStep );
timeStep = m_CreatedWorldGeometry->TimePointToTimeStep( timeInMS );
this->GetTime()->SetPos( timeStep );
}
}
void
SliceNavigationController
::SetGeometrySlice(const itk::EventObject & geometrySliceEvent)
{
const SliceNavigationController::GeometrySliceEvent* sliceEvent =
dynamic_cast<const SliceNavigationController::GeometrySliceEvent *>(
&geometrySliceEvent);
assert(sliceEvent!=NULL);
this->GetSlice()->SetPos(sliceEvent->GetPos());
}
void
SliceNavigationController::SelectSliceByPoint( const Point3D &point )
{
//@todo add time to PositionEvent and use here!!
SlicedGeometry3D* slicedWorldGeometry = dynamic_cast< SlicedGeometry3D * >(
m_CreatedWorldGeometry->GetGeometryForTimeStep( this->GetTime()->GetPos() ).GetPointer() );
if ( slicedWorldGeometry )
{
int bestSlice = -1;
double bestDistance = itk::NumericTraits<double>::max();
int s, slices;
slices = slicedWorldGeometry->GetSlices();
if ( slicedWorldGeometry->GetEvenlySpaced() )
{
- mitk::Geometry2D *plane = slicedWorldGeometry->GetGeometry2D( 0 );
+ mitk::PlaneGeometry *plane = slicedWorldGeometry->GetPlaneGeometry( 0 );
const Vector3D &direction = slicedWorldGeometry->GetDirectionVector();
Point3D projectedPoint;
plane->Project( point, projectedPoint );
// Check whether the point is somewhere within the slice stack volume;
// otherwise, the defualt slice (0) will be selected
if ( direction[0] * (point[0] - projectedPoint[0])
+ direction[1] * (point[1] - projectedPoint[1])
+ direction[2] * (point[2] - projectedPoint[2]) >= 0 )
{
bestSlice = (int)(plane->Distance( point )
/ slicedWorldGeometry->GetSpacing()[2] + 0.5);
}
}
else
{
Point3D projectedPoint;
for ( s = 0; s < slices; ++s )
{
- slicedWorldGeometry->GetGeometry2D( s )->Project( point, projectedPoint );
+ slicedWorldGeometry->GetPlaneGeometry( s )->Project( point, projectedPoint );
Vector3D distance = projectedPoint - point;
ScalarType currentDistance = distance.GetSquaredNorm();
if ( currentDistance < bestDistance )
{
bestDistance = currentDistance;
bestSlice = s;
}
}
}
if ( bestSlice >= 0 )
{
this->GetSlice()->SetPos( bestSlice );
}
else
{
this->GetSlice()->SetPos( 0 );
}
this->SendCreatedWorldGeometryUpdate();
}
}
void
SliceNavigationController::ReorientSlices( const Point3D &point,
const Vector3D &normal )
{
PlaneOperation op( OpORIENT, point, normal );
m_CreatedWorldGeometry->ExecuteOperation( &op );
this->SendCreatedWorldGeometryUpdate();
}
void SliceNavigationController::ReorientSlices(const mitk::Point3D &point,
const mitk::Vector3D &axisVec0, const mitk::Vector3D &axisVec1 )
{
PlaneOperation op( OpORIENT, point, axisVec0, axisVec1 );
m_CreatedWorldGeometry->ExecuteOperation( &op );
this->SendCreatedWorldGeometryUpdate();
}
mitk::TimeGeometry *
SliceNavigationController::GetCreatedWorldGeometry()
{
return m_CreatedWorldGeometry;
}
-const mitk::Geometry3D *
+const mitk::BaseGeometry *
SliceNavigationController::GetCurrentGeometry3D()
{
if ( m_CreatedWorldGeometry.IsNotNull() )
{
return m_CreatedWorldGeometry->GetGeometryForTimeStep( this->GetTime()->GetPos() );
}
else
{
return NULL;
}
}
const mitk::PlaneGeometry *
SliceNavigationController::GetCurrentPlaneGeometry()
{
const mitk::SlicedGeometry3D *slicedGeometry =
dynamic_cast< const mitk::SlicedGeometry3D * >
( this->GetCurrentGeometry3D() );
if ( slicedGeometry )
{
const mitk::PlaneGeometry *planeGeometry =
dynamic_cast< mitk::PlaneGeometry * >
- ( slicedGeometry->GetGeometry2D(this->GetSlice()->GetPos()) );
+ ( slicedGeometry->GetPlaneGeometry(this->GetSlice()->GetPos()) );
return planeGeometry;
}
else
{
return NULL;
}
}
void
SliceNavigationController::SetRenderer( BaseRenderer *renderer )
{
m_Renderer = renderer;
}
BaseRenderer *
SliceNavigationController::GetRenderer() const
{
return m_Renderer;
}
void
SliceNavigationController::AdjustSliceStepperRange()
{
const mitk::SlicedGeometry3D *slicedGeometry =
dynamic_cast< const mitk::SlicedGeometry3D * >
( this->GetCurrentGeometry3D() );
const Vector3D &direction = slicedGeometry->GetDirectionVector();
int c = 0;
int i, k = 0;
for ( i = 0; i < 3; ++i )
{
if ( fabs(direction[i]) < 0.000000001 ) { ++c; }
else { k = i; }
}
if ( c == 2 )
{
ScalarType min = slicedGeometry->GetOrigin()[k];
ScalarType max = min + slicedGeometry->GetExtentInMM( k );
m_Slice->SetRange( min, max );
}
else
{
m_Slice->InvalidateRange();
}
-
}
void
SliceNavigationController::ExecuteOperation( Operation *operation )
{
// switch on type
// - select best slice for a given point
// - rotate created world geometry according to Operation->SomeInfo()
if ( !operation )
{
return;
}
switch ( operation->GetOperationType() )
{
case OpMOVE: // should be a point operation
{
if ( !m_SliceLocked ) //do not move the cross position
{
// select a slice
PointOperation *po = dynamic_cast< PointOperation * >( operation );
if ( po && po->GetIndex() == -1 )
{
this->SelectSliceByPoint( po->GetPoint() );
}
else if ( po && po->GetIndex() != -1 ) // undo case because index != -1, index holds the old position of this slice
{
this->GetSlice()->SetPos( po->GetIndex() );
}
}
break;
}
case OpRESTOREPLANEPOSITION:
{
m_CreatedWorldGeometry->ExecuteOperation( operation );
this->SendCreatedWorldGeometryUpdate();
break;
}
case OpAPPLYTRANSFORMMATRIX:
{
m_CreatedWorldGeometry->ExecuteOperation( operation );
this->SendCreatedWorldGeometryUpdate();
break;
}
default:
{
// do nothing
break;
}
}
}
mitk::DataNode::Pointer SliceNavigationController::GetTopLayerNode(mitk::DataStorage::SetOfObjects::ConstPointer nodes,mitk::Point3D worldposition)
{
mitk::DataNode::Pointer node;
int maxlayer = -32768;
bool isHelper (false);
if(nodes.IsNotNull())
{
for (unsigned int x = 0; x < nodes->size(); x++)
{
nodes->at(x)->GetBoolProperty("helper object", isHelper);
if(nodes->at(x)->GetData()->GetGeometry()->IsInside(worldposition) && isHelper == false)
{
int layer = 0;
if(!(nodes->at(x)->GetIntProperty("layer", layer))) continue;
if(layer > maxlayer)
{
if(static_cast<mitk::DataNode::Pointer>(nodes->at(x))->IsVisible(m_Renderer))
{
node = nodes->at(x);
maxlayer = layer;
}
}
}
}
}
return node;
}
// Relict from the old times, when automous decisions were accepted
// behavior. Remains in here, because some RenderWindows do exist outside
// of StdMultiWidgets.
bool
SliceNavigationController
::ExecuteAction( Action* action, StateEvent const* stateEvent )
{
bool ok = false;
const PositionEvent* posEvent = dynamic_cast< const PositionEvent * >(
stateEvent->GetEvent() );
if ( posEvent != NULL )
{
if ( m_CreatedWorldGeometry.IsNull() )
{
return true;
}
switch (action->GetActionId())
{
case AcMOVE:
{
BaseRenderer *baseRenderer = posEvent->GetSender();
if ( !baseRenderer )
{
baseRenderer = const_cast<BaseRenderer *>(
GlobalInteraction::GetInstance()->GetFocus() );
}
if ( baseRenderer )
if ( baseRenderer->GetMapperID() == 1 )
{
PointOperation doOp(OpMOVE, posEvent->GetWorldPosition());
this->ExecuteOperation( &doOp );
// If click was performed in this render window than we have to update the status bar information about position and pixel value.
if(baseRenderer == m_Renderer)
{
{
std::string statusText;
TNodePredicateDataType<mitk::Image>::Pointer isImageData = TNodePredicateDataType<mitk::Image>::New();
mitk::DataStorage::SetOfObjects::ConstPointer nodes = baseRenderer->GetDataStorage()->GetSubset(isImageData).GetPointer();
mitk::Point3D worldposition = posEvent->GetWorldPosition();
//int maxlayer = -32768;
mitk::Image::Pointer image3D;
mitk::DataNode::Pointer node;
mitk::DataNode::Pointer topSourceNode;
bool isBinary (false);
node = this->GetTopLayerNode(nodes,worldposition);
if(node.IsNotNull())
{
node->GetBoolProperty("binary", isBinary);
if(isBinary)
{
mitk::DataStorage::SetOfObjects::ConstPointer sourcenodes = baseRenderer->GetDataStorage()->GetSources(node, NULL, true);
if(!sourcenodes->empty())
{
topSourceNode = this->GetTopLayerNode(sourcenodes,worldposition);
}
if(topSourceNode.IsNotNull())
{
image3D = dynamic_cast<mitk::Image*>(topSourceNode->GetData());
}
else
{
image3D = dynamic_cast<mitk::Image*>(node->GetData());
}
}
else
{
image3D = dynamic_cast<mitk::Image*>(node->GetData());
}
}
std::stringstream stream;
stream.imbue(std::locale::classic());
// get the position and gray value from the image and build up status bar text
if(image3D.IsNotNull())
{
Index3D p;
image3D->GetGeometry()->WorldToIndex(worldposition, p);
stream.precision(2);
stream<<"Position: <" << std::fixed <<worldposition[0] << ", " << std::fixed << worldposition[1] << ", " << std::fixed << worldposition[2] << "> mm";
stream<<"; Index: <"<<p[0] << ", " << p[1] << ", " << p[2] << "> ";
mitk::ScalarType pixelValue = image3D->GetPixelValueByIndex(p, baseRenderer->GetTimeStep());
if (fabs(pixelValue)>1000000 || fabs(pixelValue) < 0.01)
{
stream<<"; Time: " << baseRenderer->GetTime() << " ms; Pixelvalue: " << std::scientific<< pixelValue <<" ";
}
else
{
stream<<"; Time: " << baseRenderer->GetTime() << " ms; Pixelvalue: "<< pixelValue <<" ";
}
}
else
{
stream << "No image information at this position!";
}
statusText = stream.str();
mitk::StatusBar::GetInstance()->DisplayGreyValueText(statusText.c_str());
-
}
-
}
ok = true;
break;
}
}
default:
ok = true;
break;
}
return ok;
}
const DisplayPositionEvent *displPosEvent =
dynamic_cast< const DisplayPositionEvent * >( stateEvent->GetEvent() );
if ( displPosEvent != NULL )
{
return true;
}
return false;
}
-
} // namespace
-
diff --git a/Core/Code/Controllers/mitkSliceNavigationController.h b/Core/Code/Controllers/mitkSliceNavigationController.h
index 74efc11c4c..16b740845a 100644
--- a/Core/Code/Controllers/mitkSliceNavigationController.h
+++ b/Core/Code/Controllers/mitkSliceNavigationController.h
@@ -1,599 +1,599 @@
/*===================================================================
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 SLICENAVIGATIONCONTROLLER_H_HEADER_INCLUDED_C1C55A2F
#define SLICENAVIGATIONCONTROLLER_H_HEADER_INCLUDED_C1C55A2F
#include <MitkCoreExports.h>
#include "mitkBaseController.h"
#include "mitkRenderingManager.h"
#include "mitkTimeGeometry.h"
#include "mitkMessage.h"
#pragma GCC visibility push(default)
#include <itkEventObject.h>
#pragma GCC visibility pop
#include <itkCommand.h>
#include <sstream>
#include "mitkRestorePlanePositionOperation.h"
#include "mitkDataStorage.h"
//DEPRECATED
#include <mitkTimeSlicedGeometry.h>
namespace mitk {
#define mitkTimeSlicedGeometryEventMacro( classname , super ) \
class MITK_CORE_EXPORT DEPRECATED(classname) : public super { \
public: \
typedef classname Self; \
typedef super Superclass; \
classname(TimeGeometry* aTimeGeometry, unsigned int aPos) \
: Superclass(aTimeGeometry, aPos) {} \
virtual ~classname() {} \
virtual const char * GetEventName() const { return #classname; } \
virtual bool CheckEvent(const ::itk::EventObject* e) const \
{ return dynamic_cast<const Self*>(e); } \
virtual ::itk::EventObject* MakeObject() const \
{ return new Self(GetTimeGeometry(), GetPos()); } \
private: \
void operator=(const Self&); \
}
#define mitkTimeGeometryEventMacro( classname , super ) \
class MITK_CORE_EXPORT classname : public super { \
public: \
typedef classname Self; \
typedef super Superclass; \
classname(TimeGeometry* aTimeGeometry, unsigned int aPos) \
: Superclass(aTimeGeometry, aPos) {} \
virtual ~classname() {} \
virtual const char * GetEventName() const { return #classname; } \
virtual bool CheckEvent(const ::itk::EventObject* e) const \
{ return dynamic_cast<const Self*>(e); } \
virtual ::itk::EventObject* MakeObject() const \
{ return new Self(GetTimeGeometry(), GetPos()); } \
private: \
void operator=(const Self&); \
}
class PlaneGeometry;
-class Geometry3D;
+class BaseGeometry;
class BaseRenderer;
/**
* \brief Controls the selection of the slice the associated BaseRenderer
* will display
*
- * A SliceNavigationController takes a Geometry3D or a TimeGeometry as input world geometry
+ * A SliceNavigationController takes a BaseGeometry or a TimeGeometry as input world geometry
* (TODO what are the exact requirements?) and generates a TimeGeometry
* as output. The TimeGeometry holds a number of SlicedGeometry3Ds and
- * these in turn hold a series of Geometry2Ds. One of these Geometry2Ds is
+ * these in turn hold a series of PlaneGeometries. One of these PlaneGeometries is
* selected as world geometry for the BaseRenderers associated to 2D views.
*
* The SliceNavigationController holds has Steppers (one for the slice, a
* second for the time step), which control the selection of a single
- * Geometry2D from the TimeGeometry. SliceNavigationController generates
+ * PlaneGeometry from the TimeGeometry. SliceNavigationController generates
* ITK events to tell observers, like a BaseRenderer, when the selected slice
* or timestep changes.
*
* SliceNavigationControllers are registered as listeners to GlobalInteraction
* by the QmitkStdMultiWidget. In ExecuteAction, the controllers react to
* PositionEvents by setting the steppers to the slice which is nearest to the
* point of the PositionEvent.
*
* Example:
* \code
* // Initialization
* sliceCtrl = mitk::SliceNavigationController::New();
*
* // Tell the navigator the geometry to be sliced (with geometry a
- * // Geometry3D::ConstPointer)
+ * // BaseGeometry::ConstPointer)
* sliceCtrl->SetInputWorldGeometry(geometry.GetPointer());
*
* // Tell the navigator in which direction it shall slice the data
* sliceCtrl->SetViewDirection(mitk::SliceNavigationController::Axial);
*
* // Connect one or more BaseRenderer to this navigator, i.e.: events sent
* // by the navigator when stepping through the slices (e.g. by
* // sliceCtrl->GetSlice()->Next()) will be received by the BaseRenderer
* // (in this example only slice-changes, see also ConnectGeometryTimeEvent
* // and ConnectGeometryEvents.)
* sliceCtrl->ConnectGeometrySliceEvent(renderer.GetPointer());
*
* //create a world geometry and send the information to the connected renderer(s)
* sliceCtrl->Update();
* \endcode
*
*
* You can connect visible navigators to a SliceNavigationController, e.g., a
* QmitkSliderNavigator (for Qt):
*
* \code
* // Create the visible navigator (a slider with a spin-box)
* QmitkSliderNavigator* navigator =
* new QmitkSliderNavigator(parent, "slidernavigator");
*
* // Connect the navigator to the slice-stepper of the
* // SliceNavigationController. For initialization (position, mininal and
* // maximal values) the values of the SliceNavigationController are used.
* // Thus, accessing methods of a navigator is normally not necessary, since
* // everything can be set via the (Qt-independent) SliceNavigationController.
* // The QmitkStepperAdapter converts the Qt-signals to Qt-independent
* // itk-events.
* new QmitkStepperAdapter(navigator, sliceCtrl->GetSlice(), "navigatoradaptor");
* \endcode
*
* If you do not want that all renderwindows are updated when a new slice is
* selected, you can use a specific RenderingManager, which updates only those
* renderwindows that should be updated. This is sometimes useful when a 3D view
* does not need to be updated when the slices in some 2D views are changed.
* QmitkSliderNavigator (for Qt):
*
* \code
* // create a specific RenderingManager
* mitk::RenderingManager::Pointer myManager = mitk::RenderingManager::New();
*
* // tell the RenderingManager to update only renderwindow1 and renderwindow2
* myManager->AddRenderWindow(renderwindow1);
* myManager->AddRenderWindow(renderwindow2);
*
* // tell the SliceNavigationController of renderwindow1 and renderwindow2
* // to use the specific RenderingManager instead of the global one
* renderwindow1->GetSliceNavigationController()->SetRenderingManager(myManager);
* renderwindow2->GetSliceNavigationController()->SetRenderingManager(myManager);
* \endcode
*
* \todo implement for non-evenly-timed geometry!
* \ingroup NavigationControl
*/
class MITK_CORE_EXPORT SliceNavigationController : public BaseController
{
public:
mitkClassMacro(SliceNavigationController,BaseController);
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
mitkNewMacro1Param(Self, const char *);
/**
* \brief Possible view directions, \a Original will uses
- * the Geometry2D instances in a SlicedGeometry3D provided
+ * the PlaneGeometry instances in a SlicedGeometry3D provided
* as input world geometry (by SetInputWorldGeometry).
*/
enum ViewDirection
{
Axial,
Sagittal,
Frontal,
Original
};
/**
* \brief Set the input world geometry3D out of which the
* geometries for slicing will be created.
*
* Any previous previous set input geometry (3D or Time) will
* be ignored in future.
*/
- void SetInputWorldGeometry3D(const mitk::Geometry3D* geometry);
- itkGetConstObjectMacro(InputWorldGeometry3D, mitk::Geometry3D);
+ void SetInputWorldGeometry3D(const mitk::BaseGeometry* geometry);
+ itkGetConstObjectMacro(InputWorldGeometry3D, mitk::BaseGeometry);
/**
* \brief Set the input world geometry3D out of which the
* geometries for slicing will be created.
*
* Any previous previous set input geometry (3D or Time) will
* be ignored in future.
* \deprecatedSince{2013_09} Please use TimeGeometry instead of TimeSlicedGeometry. For more information see http://www.mitk.org/Development/Refactoring%20of%20the%20Geometry%20Classes%20-%20Part%201
*/
DEPRECATED(void SetInputWorldGeometry(const mitk::TimeSlicedGeometry* geometry));
/**
* \deprecatedSince{2013_09} Please use TimeGeometry instead of TimeSlicedGeometry. For more information see http://www.mitk.org/Development/Refactoring%20of%20the%20Geometry%20Classes%20-%20Part%201
*/
DEPRECATED(TimeSlicedGeometry* GetInputWorldGeometry());
void SetInputWorldTimeGeometry(const mitk::TimeGeometry* geometry);
itkGetConstObjectMacro(InputWorldTimeGeometry, mitk::TimeGeometry);
/**
* \brief Access the created geometry
*/
itkGetConstObjectMacro(CreatedWorldGeometry, mitk::TimeGeometry);
/**
* \brief Set the desired view directions
*
* \sa ViewDirection
* \sa Update(ViewDirection viewDirection, bool top = true,
* bool frontside = true, bool rotated = false)
*/
itkSetEnumMacro(ViewDirection, ViewDirection);
itkGetEnumMacro(ViewDirection, ViewDirection);
/**
* \brief Set the default view direction
*
* This is used to re-initialize the view direction of the SNC to the
* default value with SetViewDirectionToDefault()
*
* \sa ViewDirection
* \sa Update(ViewDirection viewDirection, bool top = true,
* bool frontside = true, bool rotated = false)
*/
itkSetEnumMacro(DefaultViewDirection, ViewDirection);
itkGetEnumMacro(DefaultViewDirection, ViewDirection);
const char* GetViewDirectionAsString();
virtual void SetViewDirectionToDefault();
/**
* \brief Do the actual creation and send it to the connected
* observers (renderers)
*
*/
virtual void Update();
/**
* \brief Extended version of Update, additionally allowing to
* specify the direction/orientation of the created geometry.
*
*/
virtual void Update(ViewDirection viewDirection, bool top = true,
bool frontside = true, bool rotated = false);
/**
* \brief Send the created geometry to the connected
* observers (renderers)
*
* Called by Update().
*/
virtual void SendCreatedWorldGeometry();
/**
* \brief Tell observers to re-read the currently selected 2D geometry
*
* Called by mitk::SlicesRotator during rotation.
*/
virtual void SendCreatedWorldGeometryUpdate();
/**
* \brief Send the currently selected slice to the connected
* observers (renderers)
*
* Called by Update().
*/
virtual void SendSlice();
/**
* \brief Send the currently selected time to the connected
* observers (renderers)
*
* Called by Update().
*/
virtual void SendTime();
/**
* \brief Set the RenderingManager to be used
*
* If \a NULL, the default RenderingManager will be used.
*/
itkSetObjectMacro(RenderingManager, RenderingManager);
mitk::RenderingManager* GetRenderingManager() const;
#pragma GCC visibility push(default)
itkEventMacro( UpdateEvent, itk::AnyEvent );
#pragma GCC visibility pop
class MITK_CORE_EXPORT TimeGeometryEvent : public itk::AnyEvent
{
public:
typedef TimeGeometryEvent Self;
typedef itk::AnyEvent Superclass;
TimeGeometryEvent(
TimeGeometry* aTimeGeometry, unsigned int aPos)
: m_TimeGeometry(aTimeGeometry), m_Pos(aPos)
{}
virtual ~TimeGeometryEvent()
{}
virtual const char * GetEventName() const
{ return "TimeGeometryEvent"; }
virtual bool CheckEvent(const ::itk::EventObject* e) const
{ return dynamic_cast<const Self*>(e); }
virtual ::itk::EventObject* MakeObject() const
{ return new Self(m_TimeGeometry, m_Pos); }
TimeGeometry* GetTimeGeometry() const
{ return m_TimeGeometry; }
unsigned int GetPos() const
{ return m_Pos; }
private:
TimeGeometry::Pointer m_TimeGeometry;
unsigned int m_Pos;
// TimeGeometryEvent(const Self&);
void operator=(const Self&); //just hide
};
/**
* \deprecatedSince{2013_09} Please use TimeGeometryEvent instead: For additional information see http://www.mitk.org/Development/Refactoring%20of%20the%20Geometry%20Classes%20-%20Part%201
*/
DEPRECATED(typedef TimeGeometryEvent TimeSlicedGeometryEvent);
mitkTimeGeometryEventMacro(
GeometrySendEvent,TimeGeometryEvent );
mitkTimeGeometryEventMacro(
GeometryUpdateEvent, TimeGeometryEvent );
mitkTimeGeometryEventMacro(
GeometryTimeEvent, TimeGeometryEvent );
mitkTimeGeometryEventMacro(
GeometrySliceEvent, TimeGeometryEvent );
template <typename T>
void ConnectGeometrySendEvent(T* receiver)
{
typedef typename itk::ReceptorMemberCommand<T>::Pointer
ReceptorMemberCommandPointer;
ReceptorMemberCommandPointer eventReceptorCommand =
itk::ReceptorMemberCommand<T>::New();
eventReceptorCommand->SetCallbackFunction(receiver, &T::SetGeometry);
unsigned long tag = AddObserver(GeometrySendEvent(NULL,0), eventReceptorCommand);
m_ReceiverToObserverTagsMap[static_cast<void*>(receiver)].push_back(tag);
}
template <typename T>
void ConnectGeometryUpdateEvent(T* receiver)
{
typedef typename itk::ReceptorMemberCommand<T>::Pointer
ReceptorMemberCommandPointer;
ReceptorMemberCommandPointer eventReceptorCommand =
itk::ReceptorMemberCommand<T>::New();
eventReceptorCommand->SetCallbackFunction(receiver, &T::UpdateGeometry);
unsigned long tag = AddObserver(GeometryUpdateEvent(NULL,0), eventReceptorCommand);
m_ReceiverToObserverTagsMap[static_cast<void*>(receiver)].push_back(tag);
}
template <typename T>
void ConnectGeometrySliceEvent(T* receiver, bool connectSendEvent=true)
{
typedef typename itk::ReceptorMemberCommand<T>::Pointer
ReceptorMemberCommandPointer;
ReceptorMemberCommandPointer eventReceptorCommand =
itk::ReceptorMemberCommand<T>::New();
eventReceptorCommand->SetCallbackFunction(receiver, &T::SetGeometrySlice);
unsigned long tag = AddObserver(GeometrySliceEvent(NULL,0), eventReceptorCommand);
m_ReceiverToObserverTagsMap[static_cast<void*>(receiver)].push_back(tag);
if(connectSendEvent)
ConnectGeometrySendEvent(receiver);
}
template <typename T>
void ConnectGeometryTimeEvent(T* receiver, bool connectSendEvent=true)
{
typedef typename itk::ReceptorMemberCommand<T>::Pointer
ReceptorMemberCommandPointer;
ReceptorMemberCommandPointer eventReceptorCommand =
itk::ReceptorMemberCommand<T>::New();
eventReceptorCommand->SetCallbackFunction(receiver, &T::SetGeometryTime);
unsigned long tag = AddObserver(GeometryTimeEvent(NULL,0), eventReceptorCommand);
m_ReceiverToObserverTagsMap[static_cast<void*>(receiver)].push_back(tag);
if(connectSendEvent)
ConnectGeometrySendEvent(receiver);
}
template <typename T>
void ConnectGeometryEvents(T* receiver)
{
//connect sendEvent only once
ConnectGeometrySliceEvent(receiver, false);
ConnectGeometryTimeEvent(receiver);
}
// use a templated method to get the right offset when casting to void*
template <typename T>
void Disconnect(T* receiver)
{
ObserverTagsMapType::iterator i = m_ReceiverToObserverTagsMap.find(static_cast<void*>(receiver));
if (i == m_ReceiverToObserverTagsMap.end()) return;
const std::list<unsigned long>& tags = i->second;
for (std::list<unsigned long>::const_iterator tagIter = tags.begin();
tagIter != tags.end(); ++tagIter)
{
RemoveObserver(*tagIter);
}
m_ReceiverToObserverTagsMap.erase(i);
}
Message<> crosshairPositionEvent;
/**
* \brief To connect multiple SliceNavigationController, we can
* act as an observer ourselves: implemented interface
* \warning not implemented
*/
virtual void SetGeometry(const itk::EventObject & geometrySliceEvent);
/**
* \brief To connect multiple SliceNavigationController, we can
* act as an observer ourselves: implemented interface
*/
virtual void SetGeometrySlice(const itk::EventObject & geometrySliceEvent);
/**
* \brief To connect multiple SliceNavigationController, we can
* act as an observer ourselves: implemented interface
*/
virtual void SetGeometryTime(const itk::EventObject & geometryTimeEvent);
/** \brief Positions the SNC according to the specified point */
void SelectSliceByPoint( const mitk::Point3D &point );
/** \brief Returns the TimeGeometry created by the SNC. */
mitk::TimeGeometry *GetCreatedWorldGeometry();
- /** \brief Returns the Geometry3D of the currently selected time step. */
- const mitk::Geometry3D *GetCurrentGeometry3D();
+ /** \brief Returns the BaseGeometry of the currently selected time step. */
+ const mitk::BaseGeometry *GetCurrentGeometry3D();
/** \brief Returns the currently selected Plane in the current
- * Geometry3D (if existent).
+ * BaseGeometry (if existent).
*/
const mitk::PlaneGeometry *GetCurrentPlaneGeometry();
/** \brief Sets the BaseRenderer associated with this SNC (if any). While
* the BaseRenderer is not directly used by SNC, this is a convenience
* method to enable BaseRenderer access via the SNC. */
void SetRenderer( BaseRenderer *renderer );
/** \brief Gets the BaseRenderer associated with this SNC (if any). While
* the BaseRenderer is not directly used by SNC, this is a convenience
* method to enable BaseRenderer access via the SNC. Returns NULL if no
* BaseRenderer has been specified*/
BaseRenderer *GetRenderer() const;
/** \brief Re-orients the slice stack. All slices will be oriented to the given normal vector.
The given point (world coordinates) defines the selected slice.
Careful: The resulting axis vectors are not clearly defined this way. If you want to define them clearly, use
ReorientSlices (const mitk::Point3D &point, const mitk::Vector3D &axisVec0, const mitk::Vector3D &axisVec1).
*/
void ReorientSlices(
const mitk::Point3D &point, const mitk::Vector3D &normal );
/** \brief Re-orients the slice stack so that all planes are oriented according to the
* given axis vectors. The given Point eventually defines selected slice.
*/
void ReorientSlices(
const mitk::Point3D &point, const mitk::Vector3D &axisVec0, const mitk::Vector3D &axisVec1 );
virtual bool ExecuteAction(
Action* action, mitk::StateEvent const* stateEvent);
void ExecuteOperation(Operation* operation);
/**
* \brief Feature option to lock planes during mouse interaction.
* This option flag disables the mouse event which causes the center
* cross to move near by.
*/
itkSetMacro(SliceLocked, bool);
itkGetMacro(SliceLocked, bool);
itkBooleanMacro(SliceLocked);
/**
* \brief Feature option to lock slice rotation.
*
* This option flag disables separately the rotation of a slice which is
* implemented in mitkSliceRotator.
*/
itkSetMacro(SliceRotationLocked, bool);
itkGetMacro(SliceRotationLocked, bool);
itkBooleanMacro(SliceRotationLocked);
/**
* \brief Adjusts the numerical range of the slice stepper according to
* the current geometry orientation of this SNC's SlicedGeometry.
*/
void AdjustSliceStepperRange();
protected:
SliceNavigationController(const char * type = NULL);
virtual ~SliceNavigationController();
mitk::DataNode::Pointer GetTopLayerNode(mitk::DataStorage::SetOfObjects::ConstPointer nodes,mitk::Point3D worldposition);
/*
template <class T>
static void buildstring( mitkIpPicDescriptor *pic, itk::Point<int, 3> p, std::string &s, T = 0)
{
std::string value;
std::stringstream stream;
stream.imbue(std::locale::classic());
stream<<s<<"; Pixelvalue: ";
if ( (p[0]>=0 && p[1] >=0 && p[2]>=0) && (unsigned int)p[0] < pic->n[0] && (unsigned int)p[1] < pic->n[1] && (unsigned int)p[2] < pic->n[2] )
{
if(pic->bpe!=24)
{
stream<<(((T*) pic->data)[ p[0] + p[1]*pic->n[0] + p[2]*pic->n[0]*pic->n[1] ]);
}
else
{
stream<<(((T*) pic->data)[p[0]*3 + 0 + p[1]*pic->n[0]*3 + p[2]*pic->n[0]*pic->n[1]*3 ]);
stream<<(((T*) pic->data)[p[0]*3 + 1 + p[1]*pic->n[0]*3 + p[2]*pic->n[0]*pic->n[1]*3 ]);
stream<<(((T*) pic->data)[p[0]*3 + 2 + p[1]*pic->n[0]*3 + p[2]*pic->n[0]*pic->n[1]*3 ]);
}
s = stream.str();
}
else
{
s+= "point out of data";
}
};
*/
- mitk::Geometry3D::ConstPointer m_InputWorldGeometry3D;
+ mitk::BaseGeometry::ConstPointer m_InputWorldGeometry3D;
mitk::TimeGeometry::ConstPointer m_InputWorldTimeGeometry;
mitk::TimeGeometry::Pointer m_CreatedWorldGeometry;
ViewDirection m_ViewDirection;
ViewDirection m_DefaultViewDirection;
mitk::RenderingManager::Pointer m_RenderingManager;
mitk::BaseRenderer *m_Renderer;
itkSetMacro(Top, bool);
itkGetMacro(Top, bool);
itkBooleanMacro(Top);
itkSetMacro(FrontSide, bool);
itkGetMacro(FrontSide, bool);
itkBooleanMacro(FrontSide);
itkSetMacro(Rotated, bool);
itkGetMacro(Rotated, bool);
itkBooleanMacro(Rotated);
bool m_Top;
bool m_FrontSide;
bool m_Rotated;
bool m_BlockUpdate;
bool m_SliceLocked;
bool m_SliceRotationLocked;
unsigned int m_OldPos;
typedef std::map<void*, std::list<unsigned long> > ObserverTagsMapType;
ObserverTagsMapType m_ReceiverToObserverTagsMap;
};
} // namespace mitk
#endif /* SLICENAVIGATIONCONTROLLER_H_HEADER_INCLUDED_C1C55A2F */
diff --git a/Core/Code/Controllers/mitkSlicesRotator.cpp b/Core/Code/Controllers/mitkSlicesRotator.cpp
index 92d3480778..280c7bbd1f 100644
--- a/Core/Code/Controllers/mitkSlicesRotator.cpp
+++ b/Core/Code/Controllers/mitkSlicesRotator.cpp
@@ -1,512 +1,512 @@
/*===================================================================
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 <mitkSlicesRotator.h>
#include <mitkSliceNavigationController.h>
#include <mitkStateEvent.h>
#include <mitkAction.h>
#include <mitkInteractionConst.h>
#include <mitkDisplayPositionEvent.h>
#include <mitkRotationOperation.h>
#include <mitkBaseRenderer.h>
#include <mitkRenderingManager.h>
#include <mitkLine.h>
#include <mitkGeometry3D.h>
-#include <mitkGeometry2D.h>
+#include <mitkPlaneGeometry.h>
#include <mitkPlaneGeometry.h>
#include <mitkDisplayGeometry.h>
#include <mitkSlicedGeometry3D.h>
#include <vtkLinearTransform.h>
#include <math.h>
#include "rotate_cursor.xpm"
namespace mitk {
SlicesRotator::Pointer SlicesRotator::New()
{
return SlicesRotator::New("slices-rotator");
}
SlicesRotator::SlicesRotator(const char* machine)
: SlicesCoordinator(machine)
{
// make sure that AcSWITCHON and AcSWITCHOFF are defined int constants somewhere (e.g. mitkInteractionConst.h)
CONNECT_ACTION( AcMOVE, DoSelectSlice );
CONNECT_ACTION( AcCHECKPOINT, DoDecideBetweenRotationAndSliceSelection );
CONNECT_ACTION( AcROTATESTART, DoStartRotation );
CONNECT_ACTION( AcROTATE, DoRotationStep );
CONNECT_ACTION( AcROTATEEND, DoEndRotation );
}
SlicesRotator::~SlicesRotator()
{
}
void SlicesRotator::OnSliceControllerAdded(SliceNavigationController* snc)
{
if (!snc) return;
snc->ConnectGeometrySendEvent(this); // connects creation of new world geometry to Self::SetGeometry
}
void SlicesRotator::OnSliceControllerRemoved(SliceNavigationController* snc)
{
if (!snc) return;
// nothing to do, base class does the bookkeeping
}
/// Is called whenever a SliceNavigationController invokes an event. Will update the list
/// of SliceNavigationControllers that can handle rotation
void SlicesRotator::SetGeometry(const itk::EventObject& /*EventObject*/)
{
// there is no way to determine the sender?
// ==> update whole list of SNCs
UpdateRotatableSNCs();
}
void SlicesRotator::RotateToPoint( SliceNavigationController *rotationPlaneSNC,
SliceNavigationController *rotatedPlaneSNC,
const Point3D &point, bool linked )
{
MITK_WARN << "Deprecated function! Use SliceNavigationController::ReorientSlices() instead";
SliceNavigationController *thirdSNC = NULL;
SNCVector::iterator iter;
for ( iter = m_RotatableSNCs.begin(); iter != m_RotatableSNCs.end(); ++iter )
{
if ( ((*iter) != rotationPlaneSNC)
&& ((*iter) != rotatedPlaneSNC) )
{
thirdSNC = *iter;
break;
}
}
if ( thirdSNC == NULL )
{
return;
}
const PlaneGeometry *rotationPlane = rotationPlaneSNC->GetCurrentPlaneGeometry();
const PlaneGeometry *rotatedPlane = rotatedPlaneSNC->GetCurrentPlaneGeometry();
const PlaneGeometry *thirdPlane = thirdSNC->GetCurrentPlaneGeometry();
if ( (rotationPlane == NULL) || (rotatedPlane == NULL)
|| (thirdPlane == NULL) )
{
return;
}
if ( rotatedPlane->DistanceFromPlane( point ) < 0.001 )
{
// Skip irrelevant rotations
return;
}
Point3D projectedPoint;
Line3D intersection;
Point3D rotationCenter;
if ( !rotationPlane->Project( point, projectedPoint )
|| !rotationPlane->IntersectionLine( rotatedPlane, intersection )
|| !thirdPlane->IntersectionPoint( intersection, rotationCenter ) )
{
return;
}
// All pre-requirements are met; execute the rotation
Point3D referencePoint = intersection.Project( projectedPoint );
Vector3D toProjected = referencePoint - rotationCenter;
Vector3D toCursor = projectedPoint - rotationCenter;
// cross product: | A x B | = |A| * |B| * sin(angle)
Vector3D axisOfRotation;
vnl_vector_fixed< ScalarType, 3 > vnlDirection =
vnl_cross_3d( toCursor.GetVnlVector(), toProjected.GetVnlVector() );
axisOfRotation.SetVnlVector( vnlDirection );
// scalar product: A * B = |A| * |B| * cos(angle)
// tan = sin / cos
ScalarType angle = - atan2(
(double)(axisOfRotation.GetNorm()),
(double)(toCursor * toProjected) );
angle *= 180.0 / vnl_math::pi;
// create RotationOperation and apply to all SNCs that should be rotated
RotationOperation op(OpROTATE, rotationCenter, axisOfRotation, angle);
if ( !linked )
{
BaseRenderer *renderer = rotatedPlaneSNC->GetRenderer();
if ( renderer == NULL )
{
return;
}
DisplayGeometry *displayGeometry = renderer->GetDisplayGeometry();
Point2D point2DWorld, point2DDisplayPre, point2DDisplayPost;
displayGeometry->Map( rotationCenter, point2DWorld );
displayGeometry->WorldToDisplay( point2DWorld, point2DDisplayPre );
TimeGeometry *timeGeometry= rotatedPlaneSNC->GetCreatedWorldGeometry();
if ( !timeGeometry )
{
return;
}
timeGeometry->ExecuteOperation( &op );
displayGeometry->Map( rotationCenter, point2DWorld );
displayGeometry->WorldToDisplay( point2DWorld, point2DDisplayPost );
Vector2D vector2DDisplayDiff = point2DDisplayPost - point2DDisplayPre;
//Vector2D origin = displayGeometry->GetOriginInMM();
displayGeometry->MoveBy( vector2DDisplayDiff );
rotatedPlaneSNC->SendCreatedWorldGeometryUpdate();
}
else
{
SNCVector::iterator iter;
for ( iter = m_RotatableSNCs.begin(); iter != m_RotatableSNCs.end(); ++iter )
{
BaseRenderer *renderer = (*iter)->GetRenderer();
if ( renderer == NULL )
{
continue;
}
DisplayGeometry *displayGeometry = renderer->GetDisplayGeometry();
Point2D point2DWorld, point2DDisplayPre, point2DDisplayPost;
displayGeometry->Map( rotationCenter, point2DWorld );
displayGeometry->WorldToDisplay( point2DWorld, point2DDisplayPre );
TimeGeometry* timeGeometry = (*iter)->GetCreatedWorldGeometry();
if ( !timeGeometry )
{
continue;
}
timeGeometry->ExecuteOperation( &op );
displayGeometry->Map( rotationCenter, point2DWorld );
displayGeometry->WorldToDisplay( point2DWorld, point2DDisplayPost );
Vector2D vector2DDisplayDiff = point2DDisplayPost - point2DDisplayPre;
//Vector2D origin = displayGeometry->GetOriginInMM();
displayGeometry->MoveBy( vector2DDisplayDiff );
(*iter)->SendCreatedWorldGeometryUpdate();
}
}
} // end RotateToPoint
/// Updates the list of SliceNavigationControllers that can handle rotation
void SlicesRotator::UpdateRotatableSNCs()
{
m_RotatableSNCs.clear();
for (SNCVector::iterator iter = m_SliceNavigationControllers.begin(); iter != m_SliceNavigationControllers.end(); ++iter)
{
const TimeGeometry* timeGeometry = (*iter)->GetCreatedWorldGeometry();
if (!timeGeometry) continue;
const SlicedGeometry3D* slicedGeometry = dynamic_cast<const SlicedGeometry3D*>( timeGeometry->GetGeometryForTimeStep(0).GetPointer() );
if (!slicedGeometry) continue;
if (slicedGeometry->IsValidSlice(0))
{
// there were some lines of additional checks here in previous versions,
// all of which would always evaluate to true, so the check was irrelevant.
// Since the original intent was not documented, I removed all checks,
// i.e. m_RotatableSNCs ends up being a list of all the registered
// SliceNavigationControllers which have a SlicedGeometry3D with at least one slice,
// which covers most standard cases.
m_RotatableSNCs.push_back( *iter );
}
}
}
bool SlicesRotator::DoSelectSlice(Action* a, const StateEvent* e)
{
// just reach through
for (SNCVector::iterator iter = m_RotatableSNCs.begin(); iter != m_RotatableSNCs.end(); ++iter)
{
if ( !(*iter)->GetSliceLocked() )
{
(*iter)->ExecuteAction(a,e);
}
}
return true;
}
bool SlicesRotator::DoDecideBetweenRotationAndSliceSelection(Action*, const StateEvent* e)
{
// Decide between moving and rotation slices.
// For basic decision logic see class documentation.
/*
Detail logic:
1. Find the SliceNavigationController that has sent the event: this one defines our rendering plane and will NOT be rotated. Must not even be counted or checked..
2. Inspect every other SliceNavigationController
- calculate the line intersection of this SliceNavigationController's plane with our rendering plane
- if there is no interesection, ignore and continue
- IF there is an intersection
- check the mouse cursor's distance from that line.
0. if the line is NOT near the cursor, remember the plane as "one of the other planes" (which can be rotated in "locked" mode)
1. on first line near the cursor, just remember this intersection line as THE other plane that we want to rotate
2. on every consecutive line near the cursor, check if the line is geometrically identical to the line that we want to rotate
- if yes, we just push this line to the "other" lines and rotate it along
- if no, then we have a situation where the mouse is near two other lines (e.g. crossing point) and don't want to rotate
*/
const DisplayPositionEvent* posEvent = dynamic_cast<const DisplayPositionEvent*>(e->GetEvent());
if (!posEvent) return false;
BaseRenderer* clickedRenderer = e->GetEvent()->GetSender();
- const PlaneGeometry* ourViewportGeometry = dynamic_cast<const PlaneGeometry*>( clickedRenderer->GetCurrentWorldGeometry2D() );
+ const PlaneGeometry* ourViewportGeometry = dynamic_cast<const PlaneGeometry*>( clickedRenderer->GetCurrentWorldPlaneGeometry() );
if (!ourViewportGeometry) return false;
DisplayGeometry* clickedDisplayGeometry = clickedRenderer->GetDisplayGeometry();
if (!clickedDisplayGeometry) return false;
MITK_DEBUG << "=============================================";
MITK_DEBUG << "Renderer under cursor is " << clickedRenderer->GetName();
Point3D cursorPosition = posEvent->GetWorldPosition();
const PlaneGeometry* geometryToBeRotated = NULL; // this one is under the mouse cursor
const PlaneGeometry* anyOtherGeometry = NULL; // this is also visible (for calculation of intersection ONLY)
Line3D intersectionLineWithGeometryToBeRotated;
bool hitMultipleLines(false);
m_SNCsToBeRotated.clear();
const double threshholdDistancePixels = 12.0;
for (SNCVector::iterator iter = m_RotatableSNCs.begin(); iter != m_RotatableSNCs.end(); ++iter)
{
// If the mouse cursor is in 3D Renderwindow, do not check for intersecting planes.
if (clickedRenderer->GetMapperID() == BaseRenderer::Standard3D)
break;
const PlaneGeometry* otherRenderersRenderPlane = (*iter)->GetCurrentPlaneGeometry();
if (otherRenderersRenderPlane == NULL) continue; // ignore, we don't see a plane
MITK_DEBUG << " Checking plane of renderer " << (*iter)->GetRenderer()->GetName();
// check if there is an intersection
Line3D intersectionLine; // between rendered/clicked geometry and the one being analyzed
if (!ourViewportGeometry->IntersectionLine( otherRenderersRenderPlane, intersectionLine ))
{
continue; // we ignore this plane, it's parallel to our plane
}
// check distance from intersection line
double distanceFromIntersectionLine = intersectionLine.Distance( cursorPosition );
ScalarType distancePixels = distanceFromIntersectionLine / clickedDisplayGeometry->GetScaleFactorMMPerDisplayUnit();
MITK_DEBUG << " Distance of plane from cursor " << distanceFromIntersectionLine << " mm, which is around " << distancePixels << " px" ;
// far away line, only remember for linked rotation if necessary
if (distanceFromIntersectionLine > threshholdDistancePixels)
{
MITK_DEBUG << " Plane is too far away --> remember as otherRenderersRenderPlane";
anyOtherGeometry = otherRenderersRenderPlane; // we just take the last one, so overwrite each iteration (we just need some crossing point)
// TODO what about multiple crossings? NOW we have undefined behavior / random crossing point is used
if (m_LinkPlanes)
{
m_SNCsToBeRotated.push_back(*iter);
}
}
else // close to cursor
{
MITK_DEBUG << " Plane is close enough to cursor...";
if ( geometryToBeRotated == NULL ) // first one close to the cursor
{
MITK_DEBUG << " It is the first close enough geometry, remember as geometryToBeRotated";
geometryToBeRotated = otherRenderersRenderPlane;
intersectionLineWithGeometryToBeRotated = intersectionLine;
m_SNCsToBeRotated.push_back(*iter);
}
else
{
MITK_DEBUG << " Second or later close enough geometry";
// compare to the line defined by geometryToBeRotated: if identical, just rotate this otherRenderersRenderPlane together with the primary one
// if different, DON'T rotate
if ( intersectionLine.IsParallel( intersectionLineWithGeometryToBeRotated )
&& intersectionLine.Distance( intersectionLineWithGeometryToBeRotated.GetPoint1() ) < mitk::eps )
{
MITK_DEBUG << " This line is the same as intersectionLineWithGeometryToBeRotated which we already know";
m_SNCsToBeRotated.push_back(*iter);
}
else
{
MITK_DEBUG << " This line is NOT the same as intersectionLineWithGeometryToBeRotated which we already know";
hitMultipleLines = true;
}
}
}
}
bool moveSlices(true);
if ( geometryToBeRotated && anyOtherGeometry && ourViewportGeometry && !hitMultipleLines )
{
// assure all three are valid, so calculation of center of rotation can be done
moveSlices = false;
}
MITK_DEBUG << "geometryToBeRotated: " << (void*)geometryToBeRotated;
MITK_DEBUG << "anyOtherGeometry: " << (void*)anyOtherGeometry;
MITK_DEBUG << "ourViewportGeometry: " << (void*)ourViewportGeometry;
MITK_DEBUG << "hitMultipleLines? " << hitMultipleLines;
MITK_DEBUG << "moveSlices? " << moveSlices;
std::auto_ptr<StateEvent> decidedEvent;
// question in state machine is: "rotate?"
if (moveSlices) // i.e. NOT rotate
{
// move all planes to posEvent->GetWorldPosition()
decidedEvent.reset( new StateEvent(EIDNO, e->GetEvent()) );
MITK_DEBUG << "Rotation not possible, not enough information (other planes crossing rendering plane) ";
}
else
{ // we DO have enough information for rotation
m_LastCursorPosition = intersectionLineWithGeometryToBeRotated.Project(cursorPosition); // remember where the last cursor position ON THE LINE has been observed
if (anyOtherGeometry->IntersectionPoint(intersectionLineWithGeometryToBeRotated, m_CenterOfRotation)) // find center of rotation by intersection with any of the OTHER lines
{
decidedEvent.reset( new StateEvent(EIDYES, e->GetEvent()) );
MITK_DEBUG << "Rotation possible";
}
else
{
MITK_DEBUG << "Rotation not possible, cannot determine the center of rotation!?";
decidedEvent.reset( new StateEvent(EIDNO, e->GetEvent()) );
}
}
this->HandleEvent( decidedEvent.get() );
return true;
}
bool SlicesRotator::DoStartRotation(Action*, const StateEvent*)
{
this->SetMouseCursor( rotate_cursor_xpm, 0, 0 );
this->InvokeEvent( SliceRotationEvent() ); // notify listeners
return true;
}
bool SlicesRotator::DoEndRotation(Action*, const StateEvent*)
{
this->ResetMouseCursor();
this->InvokeEvent( SliceRotationEvent() ); // notify listeners
return true;
}
bool SlicesRotator::DoRotationStep(Action*, const StateEvent* e)
{
const DisplayPositionEvent* posEvent = dynamic_cast<const DisplayPositionEvent*>(e->GetEvent());
if (!posEvent) return false;
Point3D cursor = posEvent->GetWorldPosition();
Vector3D toProjected = m_LastCursorPosition - m_CenterOfRotation;
Vector3D toCursor = cursor - m_CenterOfRotation;
// cross product: | A x B | = |A| * |B| * sin(angle)
Vector3D axisOfRotation;
vnl_vector_fixed< ScalarType, 3 > vnlDirection = vnl_cross_3d( toCursor.GetVnlVector(), toProjected.GetVnlVector() );
axisOfRotation.SetVnlVector(vnlDirection);
// scalar product: A * B = |A| * |B| * cos(angle)
// tan = sin / cos
ScalarType angle = - atan2( (double)(axisOfRotation.GetNorm()), (double)(toCursor * toProjected) );
angle *= 180.0 / vnl_math::pi;
m_LastCursorPosition = cursor;
// create RotationOperation and apply to all SNCs that should be rotated
RotationOperation rotationOperation(OpROTATE, m_CenterOfRotation, axisOfRotation, angle);
// iterate the OTHER slice navigation controllers: these are filled in DoDecideBetweenRotationAndSliceSelection
for (SNCVector::iterator iter = m_SNCsToBeRotated.begin(); iter != m_SNCsToBeRotated.end(); ++iter)
{
// - remember the center of rotation on the 2D display BEFORE rotation
// - execute rotation
// - calculate new center of rotation on 2D display
// - move display IF the center of rotation has moved slightly before and after rotation
// DM 2012-10: this must probably be due to rounding errors only, right?
// We don't have documentation on if/why this code is needed
BaseRenderer *renderer = (*iter)->GetRenderer();
if ( !renderer ) continue;
DisplayGeometry *displayGeometry = renderer->GetDisplayGeometry();
Point2D rotationCenter2DWorld, point2DDisplayPreRotation, point2DDisplayPostRotation;
displayGeometry->Map( m_CenterOfRotation, rotationCenter2DWorld );
displayGeometry->WorldToDisplay( rotationCenter2DWorld, point2DDisplayPreRotation );
TimeGeometry* timeGeometry = (*iter)->GetCreatedWorldGeometry();
if (!timeGeometry) continue;
timeGeometry->ExecuteOperation(&rotationOperation);
displayGeometry->Map( m_CenterOfRotation, rotationCenter2DWorld );
displayGeometry->WorldToDisplay( rotationCenter2DWorld, point2DDisplayPostRotation );
Vector2D vector2DDisplayDiff = point2DDisplayPostRotation - point2DDisplayPreRotation;
displayGeometry->MoveBy( vector2DDisplayDiff );
(*iter)->SendCreatedWorldGeometryUpdate();
}
RenderingManager::GetInstance()->RequestUpdateAll();
this->InvokeEvent( SliceRotationEvent() ); // notify listeners
return true;
}
} // namespace
diff --git a/Core/Code/Controllers/mitkSlicesRotator.h b/Core/Code/Controllers/mitkSlicesRotator.h
index 7e815e1c70..68d61afea9 100644
--- a/Core/Code/Controllers/mitkSlicesRotator.h
+++ b/Core/Code/Controllers/mitkSlicesRotator.h
@@ -1,165 +1,165 @@
/*===================================================================
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 SLICESROTATOR_H_HEADER_INCLUDED_C1C55A2F
#define SLICESROTATOR_H_HEADER_INCLUDED_C1C55A2F
#include <mitkSlicesCoordinator.h>
#pragma GCC visibility push(default)
#include <itkEventObject.h>
#pragma GCC visibility pop
#include <mitkVector.h>
namespace mitk {
/**
\brief Coordinates rotation of multiple visible rendering planes (represented as lines in other render windows).
\ingroup NavigationControl
This class takes care of several SliceNavigationControllers and handles slice selection
/ slice rotation. It is added as listener to GlobalInteraction by QmitkStdMultiWidget.
The SlicesRotator class adds the possibility of slice rotation to the "normal" behaviour
of SliceNavigationControllers (which is picking one plane from a stack of planes).
This additional class SlicesRotator is needed, because one has to be aware of multiple
- "visible slices" (selected Geometry2Ds of some SliceNavigationControllers) in order to
+ "visible slices" (selected PlaneGeometries of some SliceNavigationControllers) in order to
choose between rotation and slice selection. Such functionality could not be implemented
by a single SliceNavigationController.
Rotation is achieved by modifying (rotating) the generated TimeGeometry of the
corresponding SliceNavigationControllers.
\section mitkSlicesRotator_StandardCase The standard case: three orthogonal views (MPR)
With SlicesRotator, the rule to choose between slice rotation and selection is simple:
For a mouse down event, count the number of visible planes, which are "near" the cursor.
If this number is 2 (one for the window, which currently holds the cursor, one for the
intersection line of another visible slice), then initiate rotation, else select slices
near the cursor. If the "LinkPlanes" flag is set, the rotation is applied to the planes
of all registered SNCs, not only of the one associated with the directly selected plane.
In contrast to the situation without the SlicesRotator, the SliceNavigationControllers
are now NOT directly registered as listeners to GlobalInteraction. SlicesRotator is
registered as a listener and decides whether something should be rotated or whether
another slice should be selected. In the latter case, a PositionEvent is just forwarded
to the SliceNavigationController.
\section mitkSlicesRotator_GeneralizedCase The generalized case: any number of views
Above section as well as the original implementation of this class assumes that we have
exactly three 2D vies in our scene. This used to be the standard setup of the MITK
associated application for a long time. With custom applications based on MITK it is
easy to create different situations. One usual use case would be to have one extra
render window display the contents of any of the other ones and behave exactly like it
(could e.g. be used on a second screen).
In this situation the above assumption "we rotate when there are exactly 2 slices close
to the cursor" will not hold: since we always have two render windows displaying the
exact same slice, the number of 2 is the minimum we get. Whenever the user clicks in one
of those windows and the cursor is close to one of the orthogonal planes, we will get a
count of 3 or more planes that are "close to the cursor".
For the class to behave correctly, we actually need to distinguish three separate cases:
1. the cursor is not close to any orthogonal planes. This should result in slice selection.
2. the cursor is close to just one orthogonal plane OR multiple which are not distinguishable visually. This should result in rotation.
3. the cursor is close to multiple orthogonal planes which are rendered as distinguishable lines on the render window. This is the case when we hit the crosshair-center of the view. In this case, we need to also just select slices.
\section mitkSlicesRotator_Solution Deciding between slice selection and rotation
The "counting nearby lines in the renderwindow" can also work for the general case
described above. Only one details needs to be accounted for: we must not count a line
when it is identical to another line. I.e. we just count how many visible lines on the
screen are very close to the cursor. When this number is 1, we rotate, otherwise we let
the SliceNavigationControllers do their slice selection job.
\sa SlicesSwiveller
*/
class MITK_CORE_EXPORT SlicesRotator : public SlicesCoordinator
{
public:
mitkClassMacro(SlicesRotator, SlicesCoordinator);
static Pointer New();
/**
\brief New Macro with one parameter for creating this object with static New(..) method.
Needs to be the "slices-rotator" pattern of StateMachine.xml to work as expected.
**/
mitkNewMacro1Param(Self, const char*);
/**
\brief Callback for modifications in observed SliceNavigationControllers -- forwards to UpdateRotatableSNCs().
This method is called when an observed SliceNavigationController changes its
world geometry. The connection is established by calling the other SliceNavigationController's
method ConnectGeometrySendEvent (or similar).
*/
virtual void SetGeometry(const itk::EventObject& EventObject);
/**
\brief NOT USED by anything open-source. Deprecated. Highly obfuscated code. Use SliceNavigationController::ReorientSlices() instead!
#Deprecated
*/
virtual void RotateToPoint( SliceNavigationController *rotationPlaneSNC,
SliceNavigationController *rotatedPlaneSNC,
const Point3D &point,
bool linked = false );
protected:
SlicesRotator(const char* machine);
virtual ~SlicesRotator();
/**
\brief Called from SlicesCoordinator after a new controller is added (to internal list m_SliceNavigationControllers).
*/
virtual void OnSliceControllerAdded(SliceNavigationController* snc);
/*
\brief Called from SlicesCoordinator after a new controller is being removed (to internal list m_SliceNavigationControllers).
*/
virtual void OnSliceControllerRemoved(SliceNavigationController* snc);
/**
\brief Check all observed SliceNavigationControllers: remember those that are rotatable in m_RotatableSNCs.
*/
virtual void UpdateRotatableSNCs();
// following methods called from superclass ExecuteAction
bool DoSelectSlice(Action*, const StateEvent*);
bool DoDecideBetweenRotationAndSliceSelection(Action*, const StateEvent*);
bool DoStartRotation(Action*, const StateEvent*);
bool DoEndRotation(Action*, const StateEvent*);
bool DoRotationStep(Action*, const StateEvent*);
SNCVector m_RotatableSNCs; /// all SNCs that currently have CreatedWorldGeometries, that can be rotated.
SNCVector m_SNCsToBeRotated; /// all SNCs that will be rotated (exceptions are the ones parallel to the one being clicked)
Point3D m_LastCursorPosition; /// used for calculation of the rotation angle
Point3D m_CenterOfRotation; /// used for calculation of the rotation angle
};
} // namespace
#endif
diff --git a/Core/Code/Controllers/mitkSlicesSwiveller.cpp b/Core/Code/Controllers/mitkSlicesSwiveller.cpp
index 35b415ca1d..6eea6f8759 100644
--- a/Core/Code/Controllers/mitkSlicesSwiveller.cpp
+++ b/Core/Code/Controllers/mitkSlicesSwiveller.cpp
@@ -1,395 +1,395 @@
/*===================================================================
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 "mitkSlicesSwiveller.h"
#include "mitkSliceNavigationController.h"
#include "mitkStateEvent.h"
#include "mitkAction.h"
#include "mitkInteractionConst.h"
#include "mitkDisplayPositionEvent.h"
#include "mitkRotationOperation.h"
#include "mitkBaseRenderer.h"
#include "mitkRenderingManager.h"
#include "mitkLine.h"
#include "mitkGeometry3D.h"
-#include "mitkGeometry2D.h"
+#include "mitkPlaneGeometry.h"
#include "mitkPlaneGeometry.h"
#include "mitkDisplayGeometry.h"
#include "mitkSlicedGeometry3D.h"
#include <math.h>
namespace mitk {
SlicesSwiveller::Pointer SlicesSwiveller::New()
{
return SlicesSwiveller::New("slices-rotator");
}
SlicesSwiveller::SlicesSwiveller(const char* machine)
: SlicesCoordinator(machine),
m_PreviousRotationAngle( 0.0 )
{
}
SlicesSwiveller::~SlicesSwiveller()
{
}
// check if the slices of this SliceNavigationController can be rotated (???) Possible
void SlicesSwiveller::OnSliceControllerAdded(SliceNavigationController* snc)
{
if (!snc) return;
// connects creation of new world geometry to Self::SetGeometry
snc->ConnectGeometrySendEvent(this);
}
void SlicesSwiveller::OnSliceControllerRemoved(SliceNavigationController* snc)
{
if (!snc) return;
// nothing to do
}
/// Is called whenever a SliceNavigationController invokes an event. Will
// update the list of SliceNavigationControllers that can handle rotation
void SlicesSwiveller::SetGeometry(const itk::EventObject& /*EventObject*/)
{
// there is no way to determine the sender?
// ==> update whole list of SNCs
UpdateRelevantSNCs();
}
/// Updates the list of SliceNavigationControllers that can handle rotation
void SlicesSwiveller::UpdateRelevantSNCs()
{
m_RelevantSNCs.clear();
SNCVector::iterator iter;
for ( iter = m_SliceNavigationControllers.begin();
iter != m_SliceNavigationControllers.end();
++iter)
{
const TimeGeometry* timeGeometry = (*iter)->GetCreatedWorldGeometry();
if (!timeGeometry) continue;
const SlicedGeometry3D* slicedGeometry =
dynamic_cast<const SlicedGeometry3D*>(
timeGeometry->GetGeometryForTimeStep(0).GetPointer() );
if (!slicedGeometry) continue;
- Geometry2D *firstSlice( NULL );
- //Geometry2D *secondSlice( NULL );
+ PlaneGeometry *firstSlice( NULL );
+ //PlaneGeometry *secondSlice( NULL );
if (slicedGeometry->IsValidSlice(0))
{
- firstSlice = slicedGeometry->GetGeometry2D(0);
+ firstSlice = slicedGeometry->GetPlaneGeometry(0);
}
// if (slicedGeometry->IsValidSlice(1))
// {
-// secondSlice = slicedGeometry->GetGeometry2D(1);
+// secondSlice = slicedGeometry->GetPlaneGeometry(1);
// }
// If the direction vector of these two slices is the same, then accept
// this slice stack as rotatable
Vector3D right1 = firstSlice->GetAxisVector(0);
Vector3D up1 = firstSlice->GetAxisVector(1);
vnl_vector_fixed< ScalarType, 3 > vnlDirection1 =
vnl_cross_3d(right1.GetVnlVector(), up1.GetVnlVector());
Vector3D direction1;
direction1.SetVnlVector(vnlDirection1);
Vector3D right2 = firstSlice->GetAxisVector(0);
Vector3D up2 = firstSlice->GetAxisVector(1);
vnl_vector_fixed< ScalarType, 3 > vnlDirection2 =
vnl_cross_3d(right2.GetVnlVector(), up2.GetVnlVector());
Vector3D direction2;
direction2.SetVnlVector(vnlDirection2);
bool equal = true;
const ScalarType eps = 0.0001;
for (int i = 0; i < 3; ++i)
{
if ( fabs(direction1[i] - direction2[i]) > eps )
{
equal = false;
}
}
if (equal) // equal direction vectors
{
m_RelevantSNCs.push_back( *iter );
}
}
}
bool SlicesSwiveller
::ExecuteAction(Action* action, StateEvent const* stateEvent)
{
const ScalarType ThresholdDistancePixels = 6.0;
bool ok = false;
switch ( action->GetActionId() )
{
case AcMOVE:
{
// just reach through
SNCVector::iterator iter;
for ( iter = m_RelevantSNCs.begin();
iter != m_RelevantSNCs.end();
++iter )
{
if ( !(*iter)->GetSliceRotationLocked() )
{
(*iter)->ExecuteAction(action, stateEvent);
}
}
ok = true;
break;
}
case AcROTATE:
{
const DisplayPositionEvent *posEvent =
dynamic_cast<const DisplayPositionEvent*>(stateEvent->GetEvent());
if (!posEvent) break;
// Determine relative mouse movement projected onto world space
Point2D cursor = posEvent->GetDisplayPosition();
Vector2D relativeCursor = cursor - m_ReferenceCursor;
Vector3D relativeCursorAxis =
m_RotationPlaneXVector * relativeCursor[0]
+ m_RotationPlaneYVector * relativeCursor[1];
// Determine rotation axis (perpendicular to rotation plane and cursor
// movement)
Vector3D rotationAxis = itk::CrossProduct(
m_RotationPlaneNormal, relativeCursorAxis );
ScalarType rotationAngle = relativeCursor.GetNorm() / 2.0;
// Restore the initial plane pose by undoing the previous rotation
// operation
RotationOperation op( OpROTATE, m_CenterOfRotation,
m_PreviousRotationAxis, -m_PreviousRotationAngle );
SNCVector::iterator iter;
for ( iter = m_SNCsToBeRotated.begin();
iter != m_SNCsToBeRotated.end();
++iter )
{
if ( !(*iter)->GetSliceRotationLocked() )
{
TimeGeometry* timeGeometry = (*iter)->GetCreatedWorldGeometry();
if (!timeGeometry) continue;
timeGeometry->ExecuteOperation(&op);
(*iter)->SendCreatedWorldGeometryUpdate();
}
}
// Apply new rotation operation to all relevant SNCs
RotationOperation op2( OpROTATE, m_CenterOfRotation,
rotationAxis, rotationAngle );
for ( iter = m_SNCsToBeRotated.begin();
iter != m_SNCsToBeRotated.end();
++iter)
{
if ( !(*iter)->GetSliceRotationLocked() )
{
//// Map rotation center onto display geometry (will be used as
//// pre-rotation vector for compensating a visual shift of the
//// rotation center)
//BaseRenderer *renderer = (*iter)->GetRenderer();
//DisplayGeometry *displayGeometry = renderer->GetDisplayGeometry();
//Point2D point2DWorld, point2DDisplayPre, point2DDisplayPost;
//displayGeometry->Map( m_CenterOfRotation, point2DWorld );
//displayGeometry->WorldToDisplay( point2DWorld, point2DDisplayPre );
// Retrieve the TimeGeometry of this SliceNavigationController
TimeGeometry* timeGeometry = (*iter)->GetCreatedWorldGeometry();
if (!timeGeometry) continue;
// Execute the new rotation
timeGeometry->ExecuteOperation(&op2);
//// After rotation: map rotation center onto new display geometry...
//displayGeometry->Map( m_CenterOfRotation, point2DWorld );
//displayGeometry->WorldToDisplay( point2DWorld, point2DDisplayPost );
//Vector2D vector2DDisplayDiff = point2DDisplayPost - point2DDisplayPre;
//// And use the difference between pre- and post-rotation vectors to
//// compensate for display geometry shift:
//Vector2D origin = displayGeometry->GetOriginInMM();
//displayGeometry->MoveBy( vector2DDisplayDiff );
// Notify listeners
(*iter)->SendCreatedWorldGeometryUpdate();
}
}
m_PreviousRotationAxis = rotationAxis;
m_PreviousRotationAngle = rotationAngle;
RenderingManager::GetInstance()->RequestUpdateAll();
this->InvokeEvent( SliceRotationEvent() ); // notify listeners
ok = true;
break;
}
case AcCHECKPOINT:
{
// Decide between moving and rotation: if we're close to the crossing
// point of the planes, moving mode is entered, otherwise
// rotation/swivel mode
const DisplayPositionEvent *posEvent =
dynamic_cast<const DisplayPositionEvent*>(stateEvent->GetEvent());
BaseRenderer *renderer = stateEvent->GetEvent()->GetSender();
if ( !posEvent || !renderer )
{
break;
}
const Point3D &cursor = posEvent->GetWorldPosition();
m_SNCsToBeRotated.clear();
const PlaneGeometry *clickedGeometry( NULL );
const PlaneGeometry *otherGeometry1( NULL );
const PlaneGeometry *otherGeometry2( NULL );
SNCVector::iterator iter;
for ( iter = m_RelevantSNCs.begin(); iter != m_RelevantSNCs.end(); ++iter )
{
//unsigned int slice = (*iter)->GetSlice()->GetPos();
//unsigned int time = (*iter)->GetTime()->GetPos();
const PlaneGeometry *planeGeometry = (*iter)->GetCurrentPlaneGeometry();
if ( !planeGeometry ) continue;
if ( *iter == renderer->GetSliceNavigationController() )
{
clickedGeometry = planeGeometry;
m_SNCsToBeRotated.push_back(*iter);
}
else
{
if ( otherGeometry1 == NULL )
{
otherGeometry1 = planeGeometry;
}
else
{
otherGeometry2 = planeGeometry;
}
if ( m_LinkPlanes )
{
// If planes are linked, apply rotation to all planes
m_SNCsToBeRotated.push_back(*iter);
}
}
}
std::auto_ptr<StateEvent> newStateEvent;
mitk::Line3D line;
mitk::Point3D point;
if ( (clickedGeometry != NULL) && (otherGeometry1 != NULL)
&& (otherGeometry2 != NULL)
&& clickedGeometry->IntersectionLine( otherGeometry1, line )
&& otherGeometry2->IntersectionPoint( line, point ))
{
m_CenterOfRotation = point;
if ( m_CenterOfRotation.EuclideanDistanceTo( cursor )
< ThresholdDistancePixels )
{
newStateEvent.reset(new StateEvent(EIDNO, stateEvent->GetEvent()));
}
else
{
m_ReferenceCursor = posEvent->GetDisplayPosition();
// Get main axes of rotation plane and store it for rotation step
m_RotationPlaneNormal = clickedGeometry->GetNormal();
ScalarType xVector[] = { 1.0, 0.0, 0.0 };
ScalarType yVector[] = { 0.0, 1.0, 0.0 };
- clickedGeometry->Geometry3D::IndexToWorld(
+ clickedGeometry->BaseGeometry::IndexToWorld(
Vector3D( xVector), m_RotationPlaneXVector );
- clickedGeometry->Geometry3D::IndexToWorld(
+ clickedGeometry->BaseGeometry::IndexToWorld(
Vector3D( yVector), m_RotationPlaneYVector );
m_RotationPlaneNormal.Normalize();
m_RotationPlaneXVector.Normalize();
m_RotationPlaneYVector.Normalize();
m_PreviousRotationAxis.Fill( 0.0 );
m_PreviousRotationAxis[2] = 1.0;
m_PreviousRotationAngle = 0.0;
newStateEvent.reset(new StateEvent(EIDYES, stateEvent->GetEvent()));
}
}
else
{
newStateEvent.reset(new StateEvent(EIDNO, stateEvent->GetEvent()));
}
this->HandleEvent( newStateEvent.get() );
ok = true;
break;
}
case AcROTATESTART:
{
this->InvokeEvent( SliceRotationEvent() ); // notify listeners
break;
}
case AcROTATEEND:
{
this->InvokeEvent( SliceRotationEvent() ); // notify listeners
break;
}
default:
{
break;
}
}
return ok;
}
} // namespace
diff --git a/Core/Code/Controllers/mitkSlicesSwiveller.h b/Core/Code/Controllers/mitkSlicesSwiveller.h
index e8ab8d8790..def17b0dd7 100644
--- a/Core/Code/Controllers/mitkSlicesSwiveller.h
+++ b/Core/Code/Controllers/mitkSlicesSwiveller.h
@@ -1,119 +1,119 @@
/*===================================================================
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 SLICESSWIVELLER_H_HEADER_INCLUDED
#define SLICESSWIVELLER_H_HEADER_INCLUDED
#include <mitkSlicesCoordinator.h>
#include <mitkVector.h>
#pragma GCC visibility push(default)
#include <itkEventObject.h>
#pragma GCC visibility pop
namespace mitk {
/**
* \brief Enables arbitrary rotation of visible slices around a swivel point
* (for sliced geometries).
* \ingroup NavigationControl
*
* This class takes care of several SliceNavigationControllers and handles
* slice selection / slice rotation. It is added as listener to
* GlobalInteraction by QmitkStdMultiWidget.
*
* The SlicesSwiveller class adds the possibility of slice rotation to the
* "normal" behaviour of SliceNavigationControllers. This additional class
* is needed, because one has to be aware of several "visible slices"
- * (selected Geometry2Ds of some SliceNavigationControllers) in order to
+ * (selected PlaneGeometries of some SliceNavigationControllers) in order to
* choose between rotation and slice selection.
*
* Rotation is achieved by modifying (rotating) the generated
* TimeGeometry of the corresponding SliceNavigationController.
*
* With SlicesSwiveller, slice rotation works as follows: the user clicks onto
* a 2D view (2D plane) and drags the mouse; the relative direction and angle
* of the dragged mouse movement directly effects the rotation axis and
* angle. If "LinkPlanes" is set to true, the rotation is applied to the
* planes of all registered SNCs, not only of the one associated with the
* plane clicked on.
*
* In contrast to the situation without the SlicesRotator, the
* SliceNavigationControllers are now not directly registered as listeners to
* GlobalInteraction. SlicesRotator is registered as a listener and decides
* whether something should be rotated or whether another slice should be
* selected. In the latter case, a PositionEvent is just forwarded to the
* SliceNavigationController.
*
* \sa SlicesRotator
*/
class MITK_CORE_EXPORT SlicesSwiveller : public SlicesCoordinator
{
public:
mitkClassMacro(SlicesSwiveller, SlicesCoordinator);
static Pointer New();
/**
* @brief New Macro with one parameter for creating this object with static New(..) method
**/
mitkNewMacro1Param(Self, const char*);
virtual void SetGeometry(const itk::EventObject& EventObject);
protected:
SlicesSwiveller(const char* machine);
// clear list of controllers
virtual ~SlicesSwiveller();
// check if the slices of this SliceNavigationController can be rotated (???) Possible
virtual void OnSliceControllerAdded(SliceNavigationController* snc);
virtual void OnSliceControllerRemoved(SliceNavigationController* snc);
virtual void UpdateRelevantSNCs();
virtual bool ExecuteAction(Action * action, StateEvent const* stateEvent);
/** All SNCs that currently have CreatedWorldGeometries, that can be rotated */
SNCVector m_RelevantSNCs;
/** SNCs that will be rotated (clicked plane + all relevant others, if linked) */
SNCVector m_SNCsToBeRotated;
Point3D m_LastCursorPosition;
Point3D m_CenterOfRotation;
Point2D m_ReferenceCursor;
Vector3D m_RotationPlaneNormal;
Vector3D m_RotationPlaneXVector;
Vector3D m_RotationPlaneYVector;
Vector3D m_PreviousRotationAxis;
ScalarType m_PreviousRotationAngle;
};
} // namespace
#endif
diff --git a/Core/Code/DataManagement/mitkAbstractTransformGeometry.cpp b/Core/Code/DataManagement/mitkAbstractTransformGeometry.cpp
index c0743239ac..7e42b82396 100644
--- a/Core/Code/DataManagement/mitkAbstractTransformGeometry.cpp
+++ b/Core/Code/DataManagement/mitkAbstractTransformGeometry.cpp
@@ -1,283 +1,318 @@
/*===================================================================
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 "mitkAbstractTransformGeometry.h"
#include <vtkAbstractTransform.h>
mitk::AbstractTransformGeometry::AbstractTransformGeometry() : m_Plane(NULL), m_FrameGeometry(NULL)
{
Initialize();
}
-mitk::AbstractTransformGeometry::AbstractTransformGeometry(const AbstractTransformGeometry& other) : Superclass(other)
+mitk::AbstractTransformGeometry::AbstractTransformGeometry(const AbstractTransformGeometry& other) : Superclass(other), m_ParametricBoundingBox(other.m_ParametricBoundingBox)
{
if(other.m_ParametricBoundingBox.IsNotNull())
{
+ m_ParametricBoundingBox = other.m_ParametricBoundingBox->DeepCopy();
this->SetParametricBounds(m_ParametricBoundingBox->GetBounds());
}
this->SetPlane(other.m_Plane);
this->SetFrameGeometry(other.m_FrameGeometry);
}
-
mitk::AbstractTransformGeometry::~AbstractTransformGeometry()
{
}
-void mitk::AbstractTransformGeometry::Initialize()
+void mitk::AbstractTransformGeometry::PostInitialize()
{
- Superclass::Initialize();
-
m_ItkVtkAbstractTransform = itk::VtkAbstractTransform<ScalarType>::New();
}
vtkAbstractTransform* mitk::AbstractTransformGeometry::GetVtkAbstractTransform() const
{
return m_ItkVtkAbstractTransform->GetVtkAbstractTransform();
}
mitk::ScalarType mitk::AbstractTransformGeometry::GetParametricExtentInMM(int direction) const
{
if(m_Plane.IsNull())
{
itkExceptionMacro(<<"m_Plane is NULL.");
}
return m_Plane->GetExtentInMM(direction);
}
const mitk::Transform3D* mitk::AbstractTransformGeometry::GetParametricTransform() const
{
return m_ItkVtkAbstractTransform;
}
bool mitk::AbstractTransformGeometry::Project(const mitk::Point3D &pt3d_mm, mitk::Point3D &projectedPt3d_mm) const
{
- assert(m_BoundingBox.IsNotNull());
+ assert(this->IsBoundingBoxNull()==false);
mitk::Point2D pt2d_mm;
bool isInside;
isInside = Map(pt3d_mm, pt2d_mm);
Map(pt2d_mm, projectedPt3d_mm);
return isInside;
//Point3D pt3d_units;
//pt3d_units = m_ItkVtkAbstractTransform->BackTransform(pt3d_mm);
//pt3d_units[2] = 0;
//projectedPt3d_mm = m_ItkVtkAbstractTransform->TransformPoint(pt3d_units);
//return const_cast<BoundingBox*>(m_BoundingBox.GetPointer())->IsInside(pt3d_units);
}
bool mitk::AbstractTransformGeometry::Map(const mitk::Point3D &pt3d_mm, mitk::Point2D &pt2d_mm) const
{
assert((m_ItkVtkAbstractTransform.IsNotNull()) && (m_Plane.IsNotNull()));
Point3D pt3d_units;
pt3d_units = m_ItkVtkAbstractTransform->BackTransform(pt3d_mm);
return m_Plane->Map(pt3d_units, pt2d_mm);
}
void mitk::AbstractTransformGeometry::Map(const mitk::Point2D &pt2d_mm, mitk::Point3D &pt3d_mm) const
{
assert((m_ItkVtkAbstractTransform.IsNotNull()) && (m_Plane.IsNotNull()));
m_Plane->Map(pt2d_mm, pt3d_mm);
pt3d_mm = m_ItkVtkAbstractTransform->TransformPoint(pt3d_mm);
}
bool mitk::AbstractTransformGeometry::Project(const mitk::Point3D & atPt3d_mm, const mitk::Vector3D &vec3d_mm, mitk::Vector3D &projectedVec3d_mm) const
{
itkExceptionMacro("not implemented yet - replace GetIndexToWorldTransform by m_ItkVtkAbstractTransform->GetInverseVtkAbstractTransform()");
- assert(m_BoundingBox.IsNotNull());
+ assert(this->IsBoundingBoxNull()==false);
Vector3D vec3d_units;
vec3d_units = GetIndexToWorldTransform()->GetInverseMatrix() * vec3d_mm;
vec3d_units[2] = 0;
projectedVec3d_mm = GetIndexToWorldTransform()->TransformVector(vec3d_units);
Point3D pt3d_units;
mitk::ScalarType temp[3];
unsigned int i, j;
for (j = 0; j < 3; ++j)
temp[j] = atPt3d_mm[j] - GetIndexToWorldTransform()->GetOffset()[j];
for (i = 0; i < 3; ++i)
{
pt3d_units[i] = 0.0;
for (j = 0; j < 3; ++j)
pt3d_units[i] += GetIndexToWorldTransform()->GetInverseMatrix()[i][j] * temp[j];
}
- return const_cast<BoundingBox*>(m_BoundingBox.GetPointer())->IsInside(pt3d_units);
+ return const_cast<BoundingBox*>(this->GetBoundingBox())->IsInside(pt3d_units);
}
bool mitk::AbstractTransformGeometry::Project(const mitk::Vector3D &/*vec3d_mm*/, mitk::Vector3D &/*projectedVec3d_mm*/) const
{
- MITK_WARN << "Need additional point! No standard value defined. Please use Project(const mitk::Point3D & atPt3d_mm, const mitk::Vector3D &vec3d_mm, mitk::Vector3D &projectedVec3d_mm). Unfortunatley this one is not implemented at the moment. Sorry :(";
- itkExceptionMacro("not implemented yet - replace GetIndexToWorldTransform by m_ItkVtkAbstractTransform->GetInverseVtkAbstractTransform()");
- return false;
+ MITK_WARN << "Need additional point! No standard value defined. Please use Project(const mitk::Point3D & atPt3d_mm, const mitk::Vector3D &vec3d_mm, mitk::Vector3D &projectedVec3d_mm). Unfortunatley this one is not implemented at the moment. Sorry :(";
+ itkExceptionMacro("not implemented yet - replace GetIndexToWorldTransform by m_ItkVtkAbstractTransform->GetInverseVtkAbstractTransform()");
+ return false;
}
-
bool mitk::AbstractTransformGeometry::Map(const mitk::Point3D & atPt3d_mm, const mitk::Vector3D &vec3d_mm, mitk::Vector2D &vec2d_mm) const
{
assert((m_ItkVtkAbstractTransform.IsNotNull()) && (m_Plane.IsNotNull()));
ScalarType vtkpt[3], vtkvec[3];
itk2vtk(atPt3d_mm, vtkpt);
itk2vtk(vec3d_mm, vtkvec);
m_ItkVtkAbstractTransform->GetInverseVtkAbstractTransform()->TransformVectorAtPoint(vtkpt, vtkvec, vtkvec);
mitk::Vector3D vec3d_units;
vtk2itk(vtkvec, vec3d_units);
return m_Plane->Map(atPt3d_mm, vec3d_units, vec2d_mm);
}
void mitk::AbstractTransformGeometry::Map(const mitk::Point2D & atPt2d_mm, const mitk::Vector2D &vec2d_mm, mitk::Vector3D &vec3d_mm) const
{
m_Plane->Map(atPt2d_mm, vec2d_mm, vec3d_mm);
Point3D atPt3d_mm;
Map(atPt2d_mm, atPt3d_mm);
float vtkpt[3], vtkvec[3];
itk2vtk(atPt3d_mm, vtkpt);
itk2vtk(vec3d_mm, vtkvec);
m_ItkVtkAbstractTransform->GetVtkAbstractTransform()->TransformVectorAtPoint(vtkpt, vtkvec, vtkvec);
vtk2itk(vtkvec, vec3d_mm);
}
void mitk::AbstractTransformGeometry::IndexToWorld(const mitk::Point2D &pt_units, mitk::Point2D &pt_mm) const
{
m_Plane->IndexToWorld(pt_units, pt_mm);
}
void mitk::AbstractTransformGeometry::WorldToIndex(const mitk::Point2D &pt_mm, mitk::Point2D &pt_units) const
{
m_Plane->WorldToIndex(pt_mm, pt_units);
}
void mitk::AbstractTransformGeometry::IndexToWorld(const mitk::Point2D & /*atPt2d_units*/, const mitk::Vector2D &vec_units, mitk::Vector2D &vec_mm) const
{
MITK_WARN<<"Warning! Call of the deprecated function AbstractTransformGeometry::IndexToWorld(point, vec, vec). Use AbstractTransformGeometry::IndexToWorld(vec, vec) instead!";
this->IndexToWorld(vec_units, vec_mm);
}
void mitk::AbstractTransformGeometry::IndexToWorld(const mitk::Vector2D &vec_units, mitk::Vector2D &vec_mm) const
{
m_Plane->IndexToWorld(vec_units, vec_mm);
}
void mitk::AbstractTransformGeometry::WorldToIndex(const mitk::Point2D & /*atPt2d_mm*/, const mitk::Vector2D &vec_mm, mitk::Vector2D &vec_units) const
{
MITK_WARN<<"Warning! Call of the deprecated function AbstractTransformGeometry::WorldToIndex(point, vec, vec). Use AbstractTransformGeometry::WorldToIndex(vec, vec) instead!";
this->WorldToIndex(vec_mm, vec_units);
}
void mitk::AbstractTransformGeometry::WorldToIndex(const mitk::Vector2D &vec_mm, mitk::Vector2D &vec_units) const
{
m_Plane->WorldToIndex(vec_mm, vec_units);
}
-
bool mitk::AbstractTransformGeometry::IsAbove(const mitk::Point3D& pt3d_mm) const
{
assert((m_ItkVtkAbstractTransform.IsNotNull()) && (m_Plane.IsNotNull()));
Point3D pt3d_ParametricWorld;
pt3d_ParametricWorld = m_ItkVtkAbstractTransform->BackTransform(pt3d_mm);
Point3D pt3d_ParametricUnits;
- ((Geometry3D*)m_Plane)->WorldToIndex(pt3d_ParametricWorld, pt3d_ParametricUnits);
+ ((BaseGeometry*)m_Plane)->WorldToIndex(pt3d_ParametricWorld, pt3d_ParametricUnits);
return (pt3d_ParametricUnits[2] > m_ParametricBoundingBox->GetBounds()[4]);
}
void mitk::AbstractTransformGeometry::SetVtkAbstractTransform(vtkAbstractTransform* aVtkAbstractTransform)
{
m_ItkVtkAbstractTransform->SetVtkAbstractTransform(aVtkAbstractTransform);
}
void mitk::AbstractTransformGeometry::SetPlane(const mitk::PlaneGeometry* aPlane)
{
if(aPlane!=NULL)
{
m_Plane = static_cast<mitk::PlaneGeometry*>(aPlane->Clone().GetPointer());
BoundingBox::BoundsArrayType b=m_Plane->GetBoundingBox()->GetBounds();
SetParametricBounds(b);
CalculateFrameGeometry();
}
else
{
if(m_Plane.IsNull())
return;
m_Plane=NULL;
}
Modified();
}
void mitk::AbstractTransformGeometry::CalculateFrameGeometry()
{
if((m_Plane.IsNull()) || (m_FrameGeometry.IsNotNull()))
return;
//@warning affine-transforms and bounding-box should be set by specific sub-classes!
SetBounds(m_Plane->GetBoundingBox()->GetBounds());
}
-void mitk::AbstractTransformGeometry::SetFrameGeometry(const mitk::Geometry3D* frameGeometry)
+void mitk::AbstractTransformGeometry::SetFrameGeometry(const mitk::BaseGeometry* frameGeometry)
{
if((frameGeometry != NULL) && (frameGeometry->IsValid()))
{
- m_FrameGeometry = static_cast<mitk::Geometry3D*>(frameGeometry->Clone().GetPointer());
+ m_FrameGeometry = static_cast<mitk::BaseGeometry*>(frameGeometry->Clone().GetPointer());
SetIndexToWorldTransform(m_FrameGeometry->GetIndexToWorldTransform());
SetBounds(m_FrameGeometry->GetBounds());
}
else
{
m_FrameGeometry = NULL;
}
}
unsigned long mitk::AbstractTransformGeometry::GetMTime() const
{
if(Superclass::GetMTime()<m_ItkVtkAbstractTransform->GetMTime())
return m_ItkVtkAbstractTransform->GetMTime();
return Superclass::GetMTime();
}
void mitk::AbstractTransformGeometry::SetOversampling(mitk::ScalarType oversampling)
{
if(m_Plane.IsNull())
{
itkExceptionMacro(<< "m_Plane is not set.");
}
mitk::BoundingBox::BoundsArrayType bounds = m_Plane->GetBounds();
bounds[1]*=oversampling; bounds[3]*=oversampling; bounds[5]*=oversampling;
SetParametricBounds(bounds);
}
itk::LightObject::Pointer mitk::AbstractTransformGeometry::InternalClone() const
{
Self::Pointer newGeometry = new AbstractTransformGeometry(*this);
newGeometry->UnRegister();
return newGeometry.GetPointer();
}
+
+void mitk::AbstractTransformGeometry::SetParametricBounds(const BoundingBox::BoundsArrayType& bounds)
+{
+ m_ParametricBoundingBox = BoundingBoxType::New();
+
+ BoundingBoxType::PointsContainer::Pointer pointscontainer =
+ BoundingBoxType::PointsContainer::New();
+ BoundingBoxType::PointType p;
+ BoundingBoxType::PointIdentifier pointid;
+
+ for(pointid=0; pointid<2;++pointid)
+ {
+ unsigned int i;
+ for(i=0; i<GetNDimensions(); ++i)
+ {
+ p[i] = bounds[2*i+pointid];
+ }
+ pointscontainer->InsertElement(pointid, p);
+ }
+
+ m_ParametricBoundingBox->SetPoints(pointscontainer);
+ m_ParametricBoundingBox->ComputeBoundingBox();
+ this->Modified();
+}
+
+const mitk::BoundingBox::BoundsArrayType& mitk::AbstractTransformGeometry::GetParametricBounds() const
+{
+ assert(m_ParametricBoundingBox.IsNotNull());
+ return m_ParametricBoundingBox->GetBounds();
+}
+
+mitk::ScalarType mitk::AbstractTransformGeometry::GetParametricExtent(int direction) const
+{
+ if (direction < 0 || direction>=3)
+ mitkThrow() << "Invalid direction. Must be between either 0, 1 or 2. ";
+ assert(m_ParametricBoundingBox.IsNotNull());
+
+ BoundingBoxType::BoundsArrayType bounds = m_ParametricBoundingBox->GetBounds();
+ return bounds[direction*2+1]-bounds[direction*2];
+}
diff --git a/Core/Code/DataManagement/mitkAbstractTransformGeometry.h b/Core/Code/DataManagement/mitkAbstractTransformGeometry.h
index faf8a23874..536a0166b4 100644
--- a/Core/Code/DataManagement/mitkAbstractTransformGeometry.h
+++ b/Core/Code/DataManagement/mitkAbstractTransformGeometry.h
@@ -1,193 +1,218 @@
/*===================================================================
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 MITKVTKABSTRACTTRANSFORMPLANEGEOMETRY_H_HEADER_INCLUDED_C1C68A2C
#define MITKVTKABSTRACTTRANSFORMPLANEGEOMETRY_H_HEADER_INCLUDED_C1C68A2C
#include <MitkCoreExports.h>
-#include "mitkGeometry2D.h"
#include "mitkPlaneGeometry.h"
+
#include "itkVtkAbstractTransform.h"
class vtkAbstractTransform;
namespace mitk {
-
-//##Documentation
-//## @brief Describes a geometry defined by an vtkAbstractTransform and a plane
-//##
-//## vtkAbstractTransform is the most general transform in vtk (superclass for
-//## all vtk geometric transformations). It defines an arbitrary 3D transformation,
-//## i.e., a transformation of 3D space into 3D space. In contrast,
-//## AbstractTransformGeometry (since it is a subclass of Geometry2D) describes a
-//## 2D manifold in 3D space. The 2D manifold is defined as the manifold that results
-//## from transforming a rectangle (given in m_Plane as a PlaneGeometry) by the
-//## vtkAbstractTransform (given in m_VtkAbstractTransform).
-//## The PlaneGeometry m_Plane is used to define the parameter space. 2D coordinates are
-//## first mapped by the PlaneGeometry and the resulting 3D coordinates are put into
-//## the vtkAbstractTransform.
-//## @note This class is the superclass of concrete geometries. Since there is no
-//## write access to the vtkAbstractTransform and m_Plane, this class is somehow
-//## abstract. For full write access from extern, use ExternAbstractTransformGeometry.
-//## @note The bounds of the PlaneGeometry are used as the parametric bounds.
-//## @sa ExternAbstractTransformGeometry
-//## @ingroup Geometry
-class MITK_CORE_EXPORT AbstractTransformGeometry : public Geometry2D
-{
-public:
- mitkClassMacro(AbstractTransformGeometry, Geometry2D);
-
- itkFactorylessNewMacro(Self)
- itkCloneMacro(Self)
-
- //##Documentation
- //## @brief Get the vtkAbstractTransform (stored in m_VtkAbstractTransform)
- virtual vtkAbstractTransform* GetVtkAbstractTransform() const;
-
- virtual unsigned long GetMTime() const;
-
//##Documentation
- //## @brief Get the rectangular area that is used for transformation by
- //## m_VtkAbstractTransform and therewith defines the 2D manifold described by
- //## AbstractTransformGeometry
- itkGetConstObjectMacro(Plane, PlaneGeometry);
-
- /**
- * \brief projects the given point onto the curved plane
- */
- virtual bool Project(const mitk::Point3D &pt3d_mm, mitk::Point3D &projectedPt3d_mm) const;
-
- /**
- * \brief projects a given vector starting from given point onto the curved plane
- * \warning no satisfiyng implementation existing yet
- */
- virtual bool Project(const mitk::Point3D & atPt3d_mm, const mitk::Vector3D &vec3d_mm, mitk::Vector3D &projectedVec3d_mm) const;
-
- /**
- * \brief projects a given vector starting from standard point onto the curved plane
- * \warning no satisfying implementation existing yet
- */
- virtual bool Project(const mitk::Vector3D &vec3d_mm, mitk::Vector3D &projectedVec3d_mm) const;
-
- virtual bool Map(const mitk::Point3D &pt3d_mm, mitk::Point2D &pt2d_mm) const;
-
- virtual void Map(const mitk::Point2D &pt2d_mm, mitk::Point3D &pt3d_mm) const;
-
- virtual bool Map(const mitk::Point3D & atPt3d_mm, const mitk::Vector3D &vec3d_mm, mitk::Vector2D &vec2d_mm) const;
-
- virtual void Map(const mitk::Point2D & atPt2d_mm, const mitk::Vector2D &vec2d_mm, mitk::Vector3D &vec3d_mm) const;
-
- virtual void IndexToWorld(const mitk::Point2D &pt_units, mitk::Point2D &pt_mm) const;
-
- virtual void WorldToIndex(const mitk::Point2D &pt_mm, mitk::Point2D &pt_units) const;
-
- //##Documentation
- //## @brief Convert (continuous or discrete) index coordinates of a \em vector
- //## \a vec_units to world coordinates (in mm)
- //## @deprecated First parameter (Point2D) is not used. If possible, please use void IndexToWorld(const mitk::Vector2D& vec_units, mitk::Vector2D& vec_mm) const.
- //## For further information about coordinates types, please see the Geometry documentation
- virtual void IndexToWorld(const mitk::Point2D &atPt2d_units, const mitk::Vector2D &vec_units, mitk::Vector2D &vec_mm) const;
-
- //##Documentation
- //## @brief Convert (continuous or discrete) index coordinates of a \em vector
- //## \a vec_units to world coordinates (in mm)
- //## For further information about coordinates types, please see the Geometry documentation
- virtual void IndexToWorld(const mitk::Vector2D &vec_units, mitk::Vector2D &vec_mm) const;
-
- //##Documentation
- //## @brief Convert world coordinates (in mm) of a \em vector
- //## \a vec_mm to (continuous!) index coordinates.
- //## @deprecated First parameter (Point2D) is not used. If possible, please use void WorldToIndex(const mitk::Vector2D& vec_mm, mitk::Vector2D& vec_units) const.
- //## For further information about coordinates types, please see the Geometry documentation
- virtual void WorldToIndex(const mitk::Point2D &atPt2d_mm, const mitk::Vector2D &vec_mm, mitk::Vector2D &vec_units) const;
-
- //##Documentation
- //## @brief Convert world coordinates (in mm) of a \em vector
- //## \a vec_mm to (continuous!) index coordinates.
- //## For further information about coordinates types, please see the Geometry documentation
- virtual void WorldToIndex(const mitk::Vector2D &vec_mm, mitk::Vector2D &vec_units) const;
-
- virtual bool IsAbove(const Point3D& pt3d_mm) const;
-
- virtual mitk::ScalarType GetParametricExtentInMM(int direction) const;
-
- virtual const Transform3D* GetParametricTransform() const;
-
- //##Documentation
- //## @brief Change the parametric bounds to @a oversampling times
- //## the bounds of m_Plane.
- //##
- //## The change is done once (immediately). Later changes of the bounds
- //## of m_Plane will not influence the parametric bounds. (Consequently,
- //## there is no method to get the oversampling.)
- virtual void SetOversampling(mitk::ScalarType oversampling);
-
- virtual void Initialize();
-
- //##Documentation
- //## @brief Calculates the standard part of a Geometry3D
- //## (IndexToWorldTransform and bounding box) around the
- //## curved geometry. Has to be implemented in subclasses.
- //##
- //## \sa SetFrameGeometry
- virtual void CalculateFrameGeometry();
-
- //##Documentation
- //## @brief Set the frame geometry which is used as the standard
- //## part of an Geometry3D (IndexToWorldTransform and bounding box)
- //##
- //## Maybe used as a hint within which the interpolation shall occur
- //## by concrete sub-classes.
- //## \sa CalculateFrameGeometry
- virtual void SetFrameGeometry(const mitk::Geometry3D* frameGeometry);
-
- virtual itk::LightObject::Pointer InternalClone() const;
-protected:
- AbstractTransformGeometry();
- AbstractTransformGeometry(const AbstractTransformGeometry& other);
-
- virtual ~AbstractTransformGeometry();
-
- //##Documentation
- //## @brief Set the vtkAbstractTransform (stored in m_VtkAbstractTransform)
- //##
- //## Protected in this class, made public in ExternAbstractTransformGeometry.
- virtual void SetVtkAbstractTransform(vtkAbstractTransform* aVtkAbstractTransform);
-
- //##Documentation
- //## @brief Set the rectangular area that is used for transformation by
- //## m_VtkAbstractTransform and therewith defines the 2D manifold described by
- //## ExternAbstractTransformGeometry
+ //## @brief Describes a geometry defined by an vtkAbstractTransform and a plane
//##
- //## Protected in this class, made public in ExternAbstractTransformGeometry.
+ //## vtkAbstractTransform is the most general transform in vtk (superclass for
+ //## all vtk geometric transformations). It defines an arbitrary 3D transformation,
+ //## i.e., a transformation of 3D space into 3D space. In contrast,
+ //## AbstractTransformGeometry (since it is a subclass of PlaneGeometry) describes a
+ //## 2D manifold in 3D space. The 2D manifold is defined as the manifold that results
+ //## from transforming a rectangle (given in m_Plane as a PlaneGeometry) by the
+ //## vtkAbstractTransform (given in m_VtkAbstractTransform).
+ //## The PlaneGeometry m_Plane is used to define the parameter space. 2D coordinates are
+ //## first mapped by the PlaneGeometry and the resulting 3D coordinates are put into
+ //## the vtkAbstractTransform.
+ //## @note This class is the superclass of concrete geometries. Since there is no
+ //## write access to the vtkAbstractTransform and m_Plane, this class is somehow
+ //## abstract. For full write access from extern, use ExternAbstractTransformGeometry.
//## @note The bounds of the PlaneGeometry are used as the parametric bounds.
- //## @note The PlaneGeometry is cloned, @em not linked/referenced.
- virtual void SetPlane(const mitk::PlaneGeometry* aPlane);
-
- //##Documentation
- //## @brief The rectangular area that is used for transformation by
- //## m_VtkAbstractTransform and therewith defines the 2D manifold described by
- //## AbstractTransformGeometry.
- mitk::PlaneGeometry::Pointer m_Plane;
-
- itk::VtkAbstractTransform<ScalarType>::Pointer m_ItkVtkAbstractTransform;
-
- mitk::Geometry3D::Pointer m_FrameGeometry;
-};
-
+ //## @sa ExternAbstractTransformGeometry
+ //## @ingroup Geometry
+ class MITK_CORE_EXPORT AbstractTransformGeometry : public PlaneGeometry
+ {
+ public:
+ mitkClassMacro(AbstractTransformGeometry, PlaneGeometry);
+
+ itkFactorylessNewMacro(Self)
+ itkCloneMacro(Self)
+
+ //##Documentation
+ //## @brief Get the vtkAbstractTransform (stored in m_VtkAbstractTransform)
+ virtual vtkAbstractTransform* GetVtkAbstractTransform() const;
+
+ virtual unsigned long GetMTime() const;
+
+ //##Documentation
+ //## @brief Get the rectangular area that is used for transformation by
+ //## m_VtkAbstractTransform and therewith defines the 2D manifold described by
+ //## AbstractTransformGeometry
+ itkGetConstObjectMacro(Plane, PlaneGeometry);
+
+ /**
+ * \brief projects the given point onto the curved plane
+ */
+ virtual bool Project(const mitk::Point3D &pt3d_mm, mitk::Point3D &projectedPt3d_mm) const;
+
+ /**
+ * \brief projects a given vector starting from given point onto the curved plane
+ * \warning no satisfiyng implementation existing yet
+ */
+ virtual bool Project(const mitk::Point3D & atPt3d_mm, const mitk::Vector3D &vec3d_mm, mitk::Vector3D &projectedVec3d_mm) const;
+
+ /**
+ * \brief projects a given vector starting from standard point onto the curved plane
+ * \warning no satisfying implementation existing yet
+ */
+ virtual bool Project(const mitk::Vector3D &vec3d_mm, mitk::Vector3D &projectedVec3d_mm) const;
+
+ virtual bool Map(const mitk::Point3D &pt3d_mm, mitk::Point2D &pt2d_mm) const;
+
+ virtual void Map(const mitk::Point2D &pt2d_mm, mitk::Point3D &pt3d_mm) const;
+
+ virtual bool Map(const mitk::Point3D & atPt3d_mm, const mitk::Vector3D &vec3d_mm, mitk::Vector2D &vec2d_mm) const;
+
+ virtual void Map(const mitk::Point2D & atPt2d_mm, const mitk::Vector2D &vec2d_mm, mitk::Vector3D &vec3d_mm) const;
+
+ virtual void IndexToWorld(const mitk::Point2D &pt_units, mitk::Point2D &pt_mm) const;
+
+ virtual void WorldToIndex(const mitk::Point2D &pt_mm, mitk::Point2D &pt_units) const;
+
+ //##Documentation
+ //## @brief Convert (continuous or discrete) index coordinates of a \em vector
+ //## \a vec_units to world coordinates (in mm)
+ //## @deprecated First parameter (Point2D) is not used. If possible, please use void IndexToWorld(const mitk::Vector2D& vec_units, mitk::Vector2D& vec_mm) const.
+ //## For further information about coordinates types, please see the Geometry documentation
+ virtual void IndexToWorld(const mitk::Point2D &atPt2d_units, const mitk::Vector2D &vec_units, mitk::Vector2D &vec_mm) const;
+
+ //##Documentation
+ //## @brief Convert (continuous or discrete) index coordinates of a \em vector
+ //## \a vec_units to world coordinates (in mm)
+ //## For further information about coordinates types, please see the Geometry documentation
+ virtual void IndexToWorld(const mitk::Vector2D &vec_units, mitk::Vector2D &vec_mm) const;
+
+ //##Documentation
+ //## @brief Convert world coordinates (in mm) of a \em vector
+ //## \a vec_mm to (continuous!) index coordinates.
+ //## @deprecated First parameter (Point2D) is not used. If possible, please use void WorldToIndex(const mitk::Vector2D& vec_mm, mitk::Vector2D& vec_units) const.
+ //## For further information about coordinates types, please see the Geometry documentation
+ virtual void WorldToIndex(const mitk::Point2D &atPt2d_mm, const mitk::Vector2D &vec_mm, mitk::Vector2D &vec_units) const;
+
+ //##Documentation
+ //## @brief Convert world coordinates (in mm) of a \em vector
+ //## \a vec_mm to (continuous!) index coordinates.
+ //## For further information about coordinates types, please see the Geometry documentation
+ virtual void WorldToIndex(const mitk::Vector2D &vec_mm, mitk::Vector2D &vec_units) const;
+
+ virtual bool IsAbove(const Point3D& pt3d_mm) const;
+
+ virtual mitk::ScalarType GetParametricExtentInMM(int direction) const;
+
+ virtual const Transform3D* GetParametricTransform() const;
+
+ //##Documentation
+ //## @brief Change the parametric bounds to @a oversampling times
+ //## the bounds of m_Plane.
+ //##
+ //## The change is done once (immediately). Later changes of the bounds
+ //## of m_Plane will not influence the parametric bounds. (Consequently,
+ //## there is no method to get the oversampling.)
+ virtual void SetOversampling(mitk::ScalarType oversampling);
+
+ //##Documentation
+ //## @brief Calculates the standard part of a BaseGeometry
+ //## (IndexToWorldTransform and bounding box) around the
+ //## curved geometry. Has to be implemented in subclasses.
+ //##
+ //## \sa SetFrameGeometry
+ virtual void CalculateFrameGeometry();
+
+ //##Documentation
+ //## @brief Set the frame geometry which is used as the standard
+ //## part of an BaseGeometry (IndexToWorldTransform and bounding box)
+ //##
+ //## Maybe used as a hint within which the interpolation shall occur
+ //## by concrete sub-classes.
+ //## \sa CalculateFrameGeometry
+ virtual void SetFrameGeometry(const mitk::BaseGeometry* frameGeometry);
+
+ virtual itk::LightObject::Pointer InternalClone() const;
+
+ //##Documentation
+ //## @brief Get the parametric bounding-box
+ //##
+ //## See AbstractTransformGeometry for an example usage of this.
+ itkGetConstObjectMacro(ParametricBoundingBox, BoundingBox);
+
+ //##Documentation
+ //## @brief Get the parametric bounds
+ //##
+ //## See AbstractTransformGeometry for an example usage of this.
+ const BoundingBox::BoundsArrayType& GetParametricBounds() const;
+
+ //##Documentation
+ //## @brief Get the parametric extent
+ //##
+ //## See AbstractTransformGeometry for an example usage of this.
+ mitk::ScalarType GetParametricExtent(int direction) const;
+
+ protected:
+ AbstractTransformGeometry();
+ AbstractTransformGeometry(const AbstractTransformGeometry& other);
+
+ virtual ~AbstractTransformGeometry();
+
+ //##Documentation
+ //## @brief Set the vtkAbstractTransform (stored in m_VtkAbstractTransform)
+ //##
+ //## Protected in this class, made public in ExternAbstractTransformGeometry.
+ virtual void SetVtkAbstractTransform(vtkAbstractTransform* aVtkAbstractTransform);
+
+ //##Documentation
+ //## @brief Set the rectangular area that is used for transformation by
+ //## m_VtkAbstractTransform and therewith defines the 2D manifold described by
+ //## ExternAbstractTransformGeometry
+ //##
+ //## Protected in this class, made public in ExternAbstractTransformGeometry.
+ //## @note The bounds of the PlaneGeometry are used as the parametric bounds.
+ //## @note The PlaneGeometry is cloned, @em not linked/referenced.
+ virtual void SetPlane(const mitk::PlaneGeometry* aPlane);
+
+ //##Documentation
+ //## @brief The rectangular area that is used for transformation by
+ //## m_VtkAbstractTransform and therewith defines the 2D manifold described by
+ //## AbstractTransformGeometry.
+ mitk::PlaneGeometry::Pointer m_Plane;
+
+ itk::VtkAbstractTransform<ScalarType>::Pointer m_ItkVtkAbstractTransform;
+
+ mitk::BaseGeometry::Pointer m_FrameGeometry;
+
+ //##Documentation
+ //## @brief Set the parametric bounds
+ //##
+ //## Protected in this class, made public in some sub-classes, e.g.,
+ //## ExternAbstractTransformGeometry.
+ virtual void SetParametricBounds(const BoundingBox::BoundsArrayType& bounds);
+
+ mutable mitk::BoundingBox::Pointer m_ParametricBoundingBox;
+ private:
+ virtual void PostInitialize();
+ };
} // namespace mitk
#endif /* MITKVTKABSTRACTTRANSFORMPLANEGEOMETRY_H_HEADER_INCLUDED_C1C68A2C */
diff --git a/Core/Code/DataManagement/mitkBaseData.cpp b/Core/Code/DataManagement/mitkBaseData.cpp
index a48a9dd05b..7504bdb97c 100644
--- a/Core/Code/DataManagement/mitkBaseData.cpp
+++ b/Core/Code/DataManagement/mitkBaseData.cpp
@@ -1,296 +1,292 @@
/*===================================================================
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 "mitkBaseData.h"
#include <mitkProportionalTimeGeometry.h>
#include <itkObjectFactoryBase.h>
#include <mitkException.h>
+#include <mitkGeometry3D.h>
mitk::BaseData::BaseData() :
m_RequestedRegionInitialized(false),
m_SourceOutputIndexDuplicate(0), m_Initialized(true)
{
m_TimeGeometry = mitk::ProportionalTimeGeometry::New();
m_PropertyList = PropertyList::New();
}
mitk::BaseData::BaseData( const BaseData &other ):
itk::DataObject(), mitk::OperationActor(),
m_RequestedRegionInitialized(other.m_RequestedRegionInitialized),
m_SourceOutputIndexDuplicate(other.m_SourceOutputIndexDuplicate),
m_Initialized(other.m_Initialized)
{
m_TimeGeometry = dynamic_cast<TimeGeometry *>(other.m_TimeGeometry->Clone().GetPointer());
m_PropertyList = other.m_PropertyList->Clone();
}
mitk::BaseData::~BaseData()
{
}
void mitk::BaseData::InitializeTimeGeometry(unsigned int timeSteps)
{
- mitk::Geometry3D::Pointer g3d = mitk::Geometry3D::New();
- g3d->Initialize();
-
- if ( timeSteps > 1 )
- {
- mitk::ScalarType timeBounds[] = {0.0, 1.0};
- g3d->SetTimeBounds( timeBounds );
- }
+ mitk::Geometry3D::Pointer geo3D = mitk::Geometry3D::New();
+ mitk::BaseGeometry::Pointer baseGeo = dynamic_cast<BaseGeometry*>(geo3D.GetPointer());
+ baseGeo->Initialize();
// The geometry is propagated automatically to the other items,
// if EvenlyTimed is true...
//Old timeGeometry->InitializeEvenlyTimed( g3d.GetPointer(), timeSteps );
TimeGeometry::Pointer timeGeometry = this->GetTimeGeometry();
timeGeometry->Initialize();
timeGeometry->Expand(timeSteps);
for (TimeStepType step = 0; step < timeSteps; ++step)
{
- timeGeometry->SetTimeStepGeometry(g3d.GetPointer(),step);
+ timeGeometry->SetTimeStepGeometry(baseGeo.GetPointer(),step);
}
}
void mitk::BaseData::UpdateOutputInformation()
{
if ( this->GetSource() )
{
this->GetSource()->UpdateOutputInformation();
}
if (m_TimeGeometry.IsNotNull())
{
m_TimeGeometry->UpdateBoundingBox();
}
}
const mitk::TimeGeometry* mitk::BaseData::GetUpdatedTimeGeometry()
{
SetRequestedRegionToLargestPossibleRegion();
UpdateOutputInformation();
return GetTimeGeometry();
}
void mitk::BaseData::Expand( unsigned int timeSteps )
{
if (m_TimeGeometry.IsNotNull() )
{
ProportionalTimeGeometry * propTimeGeometry = dynamic_cast<ProportionalTimeGeometry*> (m_TimeGeometry.GetPointer());
if (propTimeGeometry)
{
propTimeGeometry->Expand(timeSteps);
return;
}
mitkThrow() << "TimeGeometry is of an unkown Type. Could not expand it. ";
}
else
{
this->InitializeTimeGeometry(timeSteps);
}
}
-const mitk::Geometry3D* mitk::BaseData::GetUpdatedGeometry(int t)
+const mitk::BaseGeometry* mitk::BaseData::GetUpdatedGeometry(int t)
{
SetRequestedRegionToLargestPossibleRegion();
UpdateOutputInformation();
return GetGeometry(t);
}
-void mitk::BaseData::SetGeometry(Geometry3D* geometry)
+void mitk::BaseData::SetGeometry(BaseGeometry* geometry)
{
ProportionalTimeGeometry::Pointer timeGeometry = ProportionalTimeGeometry::New();
if(geometry!=NULL)
{
timeGeometry->Initialize(geometry, 1);
}
SetTimeGeometry(timeGeometry);
return;
}
void mitk::BaseData::SetTimeGeometry(TimeGeometry* geometry)
{
m_TimeGeometry = geometry;
this->Modified();
}
-void mitk::BaseData::SetClonedGeometry(const Geometry3D* aGeometry3D)
+void mitk::BaseData::SetClonedGeometry(const BaseGeometry* aGeometry3D)
{
- SetGeometry(static_cast<mitk::Geometry3D*>(aGeometry3D->Clone().GetPointer()));
+ SetGeometry(static_cast<mitk::BaseGeometry*>(aGeometry3D->Clone().GetPointer()));
}
void mitk::BaseData::SetClonedTimeGeometry(const TimeGeometry* geometry)
{
TimeGeometry::Pointer clonedGeometry = geometry->Clone();
SetTimeGeometry(clonedGeometry.GetPointer());
}
-void mitk::BaseData::SetClonedGeometry(const Geometry3D* aGeometry3D, unsigned int time)
+void mitk::BaseData::SetClonedGeometry(const BaseGeometry* aGeometry3D, unsigned int time)
{
if (m_TimeGeometry)
{
- m_TimeGeometry->SetTimeStepGeometry(static_cast<mitk::Geometry3D*>(aGeometry3D->Clone().GetPointer()),time);
+ m_TimeGeometry->SetTimeStepGeometry(static_cast<mitk::BaseGeometry*>(aGeometry3D->Clone().GetPointer()),time);
}
}
bool mitk::BaseData::IsEmptyTimeStep(unsigned int) const
{
return IsInitialized() == false;
}
bool mitk::BaseData::IsEmpty() const
{
if(IsInitialized() == false)
return true;
const TimeGeometry* timeGeometry = const_cast<BaseData*>(this)->GetUpdatedTimeGeometry();
if(timeGeometry == NULL)
return true;
unsigned int timeSteps = timeGeometry->CountTimeSteps();
for ( unsigned int t = 0 ; t < timeSteps ; ++t )
{
if(IsEmptyTimeStep(t) == false)
return false;
}
return true;
}
itk::SmartPointer<mitk::BaseDataSource> mitk::BaseData::GetSource() const
{
return static_cast<mitk::BaseDataSource*>(Superclass::GetSource().GetPointer());
}
mitk::PropertyList::Pointer mitk::BaseData::GetPropertyList() const
{
return m_PropertyList;
}
mitk::BaseProperty::Pointer mitk::BaseData::GetProperty(const char *propertyKey) const
{
return m_PropertyList->GetProperty(propertyKey);
}
void mitk::BaseData::SetProperty(const char *propertyKey,
BaseProperty* propertyValue)
{
m_PropertyList->SetProperty(propertyKey, propertyValue);
}
void mitk::BaseData::SetPropertyList(PropertyList *pList)
{
m_PropertyList = pList;
}
void mitk::BaseData::SetOrigin(const mitk::Point3D& origin)
{
TimeGeometry* timeGeom = GetTimeGeometry();
assert (timeGeom != NULL);
- Geometry3D* geometry;
+ BaseGeometry* geometry;
TimeStepType steps = timeGeom->CountTimeSteps();
for (TimeStepType timestep = 0; timestep < steps; ++timestep)
{
geometry = GetGeometry(timestep);
if (geometry != NULL)
{
geometry->SetOrigin(origin);
}
}
}
unsigned long mitk::BaseData::GetMTime() const
{
unsigned long time = Superclass::GetMTime();
if(m_TimeGeometry.IsNotNull())
{
if((time < m_TimeGeometry->GetMTime()))
{
Modified();
return Superclass::GetMTime();
}
}
return time;
}
void mitk::BaseData::Graft(const itk::DataObject*)
{
itkExceptionMacro(<< "Graft not implemented for mitk::BaseData subclass " << this->GetNameOfClass())
}
void mitk::BaseData::CopyInformation( const itk::DataObject* data )
{
const Self* bd = dynamic_cast<const Self*>(data);
if (bd != NULL)
{
m_PropertyList = bd->GetPropertyList()->Clone();
if (bd->GetTimeGeometry()!=NULL)
{
m_TimeGeometry = bd->GetTimeGeometry()->Clone();
}
}
else
{
// pointer could not be cast back down; this can be the case if your filters input
// and output objects differ in type; then you have to write your own GenerateOutputInformation method
itkExceptionMacro(<< "mitk::BaseData::CopyInformation() cannot cast "
<< typeid(data).name() << " to "
<< typeid(Self*).name() );
}
}
bool mitk::BaseData::IsInitialized() const
{
return m_Initialized;
}
void mitk::BaseData::Clear()
{
this->ClearData();
this->InitializeEmpty();
}
void mitk::BaseData::ClearData()
{
if(m_Initialized)
{
ReleaseData();
m_Initialized = false;
}
}
void mitk::BaseData::ExecuteOperation(mitk::Operation* /*operation*/)
{
//empty by default. override if needed!
}
void mitk::BaseData::PrintSelf(std::ostream& os, itk::Indent indent) const
{
os << std::endl;
os << indent << " TimeGeometry: ";
if(GetTimeGeometry() == NULL)
os << "NULL" << std::endl;
else
GetTimeGeometry()->Print(os, indent);
}
diff --git a/Core/Code/DataManagement/mitkBaseData.h b/Core/Code/DataManagement/mitkBaseData.h
index 0331b4f57e..7084c82641 100644
--- a/Core/Code/DataManagement/mitkBaseData.h
+++ b/Core/Code/DataManagement/mitkBaseData.h
@@ -1,429 +1,429 @@
/*===================================================================
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 BASEDATA_H_HEADER_INCLUDED_C1EBB6FA
#define BASEDATA_H_HEADER_INCLUDED_C1EBB6FA
#include <itkDataObject.h>
#include "mitkBaseProcess.h"
#include "mitkTimeGeometry.h"
#include <MitkCoreExports.h>
#include "mitkOperationActor.h"
#include "mitkPropertyList.h"
namespace mitk {
//class BaseProcess;
//##Documentation
//## @brief Base of all data objects
//##
//## Base of all data objects, e.g., images, contours, surfaces etc. Inherits
//## from itk::DataObject and thus can be included in a pipeline.
//## Inherits also from OperationActor and can be used as a destination for Undo
//## @ingroup Data
class MITK_CORE_EXPORT BaseData : public itk::DataObject, public OperationActor
{
public:
mitkClassMacro(BaseData,itk::DataObject)
/**
* \brief Return the TimeGeometry of the data as const pointer.
*
* \warning No update will be called. Use GetUpdatedGeometry() if you cannot
* be sure that the geometry is up-to-date.
*
* Normally used in GenerateOutputInformation of subclasses of BaseProcess.
*/
const mitk::TimeGeometry* GetTimeGeometry() const
{
return m_TimeGeometry.GetPointer();
}
/**
* \brief Return the TimeGeometry of the data as const pointer.
*
* \warning No update will be called. Use GetUpdatedGeometry() if you cannot
* be sure that the geometry is up-to-date.
*
* Normally used in GenerateOutputInformation of subclasses of BaseProcess.
* \deprecatedSince{2013_09} Please use GetTimeGeometry instead: For additional information see http://www.mitk.org/Development/Refactoring%20of%20the%20Geometry%20Classes%20-%20Part%201
*/
DEPRECATED(const mitk::TimeGeometry* GetTimeSlicedGeometry() const)
{
return GetTimeGeometry();
}
/**
* @brief Return the TimeGeometry of the data as pointer.
*
* \warning No update will be called. Use GetUpdatedGeometry() if you cannot
* be sure that the geometry is up-to-date.
*
* Normally used in GenerateOutputInformation of subclasses of BaseProcess.
*/
mitk::TimeGeometry* GetTimeGeometry()
{
return m_TimeGeometry.GetPointer();
}
/**
- * @brief Return the Geometry3D of the data.
+ * @brief Return the TimeGeometry of the data.
*
* The method does not simply return the value of the m_TimeGeometry
* member. Before doing this, it makes sure that the TimeGeometry
* is up-to-date (by setting the update extent to largest possible and
* calling UpdateOutputInformation).
*/
const mitk::TimeGeometry* GetUpdatedTimeGeometry();
/**
- * @brief Return the Geometry3D of the data.
+ * @brief Return the TimeGeometry of the data.
*
* The method does not simply return the value of the m_TimeGeometry
* member. Before doing this, it makes sure that the TimeGeometry
* is up-to-date (by setting the update extent to largest possible and
* calling UpdateOutputInformation).
* \deprecatedSince{2013_09} Please use GetUpdatedTimeGeometry instead: For additional information see http://www.mitk.org/Development/Refactoring%20of%20the%20Geometry%20Classes%20-%20Part%201
*/
DEPRECATED(const mitk::TimeGeometry* GetUpdatedTimeSliceGeometry())
{
return GetUpdatedTimeGeometry();
}
/**
* \brief Expands the TimeGeometry to a number of TimeSteps.
*
* The method expands the TimeGeometry to the given number of TimeSteps,
* filling newly created elements with empty geometries. Sub-classes should override
* this method to handle the elongation of their data vectors, too.
* Note that a shrinking is neither possible nor intended.
*/
virtual void Expand( unsigned int timeSteps );
/**
- * \brief Return the Geometry3D of the data at time \a t.
+ * \brief Return the BaseGeometry of the data at time \a t.
*
* The method does not simply return
* m_TimeGeometry->GetGeometry(t).
- * Before doing this, it makes sure that the Geometry3D is up-to-date
+ * Before doing this, it makes sure that the BaseGeometry is up-to-date
* (by setting the update extent appropriately and calling
* UpdateOutputInformation).
*
* @todo Appropriate setting of the update extent is missing.
*/
- const mitk::Geometry3D* GetUpdatedGeometry(int t=0);
+ const mitk::BaseGeometry* GetUpdatedGeometry(int t=0);
//##Documentation
//## @brief Return the geometry, which is a TimeGeometry, of the data
//## as non-const pointer.
//##
//## \warning No update will be called. Use GetUpdatedGeometry() if you cannot
//## be sure that the geometry is up-to-date.
//##
//## Normally used in GenerateOutputInformation of subclasses of BaseProcess.
- mitk::Geometry3D* GetGeometry(int t=0) const
+ mitk::BaseGeometry* GetGeometry(int t=0) const
{
if(m_TimeGeometry.IsNull())
return NULL;
return m_TimeGeometry->GetGeometryForTimeStep(t);
}
//##Documentation
//## @brief Update the information for this BaseData (the geometry in particular)
//## so that it can be used as an output of a BaseProcess.
//##
//## This method is used in the pipeline mechanism to propagate information and
//## initialize the meta data associated with a BaseData. Any implementation
//## of this method in a derived class is assumed to call its source's
//## BaseProcess::UpdateOutputInformation() which determines modified
//## times, LargestPossibleRegions, and any extra meta data like spacing,
//## origin, etc. Default implementation simply call's it's source's
//## UpdateOutputInformation().
//## \note Implementations of this methods in derived classes must take care
//## that the geometry is updated by calling
//## GetTimeGeometry()->UpdateInformation()
//## \em after calling its source's BaseProcess::UpdateOutputInformation().
void UpdateOutputInformation();
//##Documentation
//## @brief Set the RequestedRegion to the LargestPossibleRegion.
//##
//## This forces a filter to produce all of the output in one execution
//## (i.e. not streaming) on the next call to Update().
virtual void SetRequestedRegionToLargestPossibleRegion()=0;
//##Documentation
//## @brief Determine whether the RequestedRegion is outside of the BufferedRegion.
//##
//## This method returns true if the RequestedRegion
//## is outside the BufferedRegion (true if at least one pixel is
//## outside). This is used by the pipeline mechanism to determine
//## whether a filter needs to re-execute in order to satisfy the
//## current request. If the current RequestedRegion is already
//## inside the BufferedRegion from the previous execution (and the
//## current filter is up to date), then a given filter does not need
//## to re-execute
virtual bool RequestedRegionIsOutsideOfTheBufferedRegion()=0;
//##Documentation
//## @brief Verify that the RequestedRegion is within the LargestPossibleRegion.
//##
//## If the RequestedRegion is not within the LargestPossibleRegion,
//## then the filter cannot possibly satisfy the request. This method
//## returns true if the request can be satisfied (even if it will be
//## necessary to process the entire LargestPossibleRegion) and
//## returns false otherwise. This method is used by
//## PropagateRequestedRegion(). PropagateRequestedRegion() throws a
//## InvalidRequestedRegionError exception if the requested region is
//## not within the LargestPossibleRegion.
virtual bool VerifyRequestedRegion() = 0;
//##Documentation
//## @brief Copy information from the specified data set.
//##
//## This method is part of the pipeline execution model. By default, a
//## BaseProcess will copy meta-data from the first input to all of its
//## outputs. See ProcessObject::GenerateOutputInformation(). Each
//## subclass of DataObject is responsible for being able to copy
//## whatever meta-data it needs from another DataObject.
//## The default implementation of this method copies the time sliced geometry
//## and the property list of an object. If a subclass overrides this
//## method, it should always call its superclass' version.
void CopyInformation(const itk::DataObject* data);
//##Documentation
//## @brief Check whether the data has been initialized, i.e.,
//## at least the Geometry and other header data has been set
//##
//## \warning Set to \a true by default for compatibility reasons.
//## Set m_Initialized=false in constructors of sub-classes that
//## support distinction between initialized and uninitialized state.
virtual bool IsInitialized() const;
//##Documentation
//## @brief Calls ClearData() and InitializeEmpty();
//## \warning Only use in subclasses that reimplemented these methods.
//## Just calling Clear from BaseData will reset an object to a not initialized,
//## invalid state.
virtual void Clear();
//##Documentation
//## @brief Check whether object contains data (at
//## a specified time), e.g., a set of points may be empty
//##
//## \warning Returns IsInitialized()==false by default for
//## compatibility reasons. Override in sub-classes that
//## support distinction between empty/non-empty state.
virtual bool IsEmptyTimeStep(unsigned int t) const;
//##Documentation
//## @brief Check whether object contains data (at
//## least at one point in time), e.g., a set of points
//## may be empty
//##
//## \warning Returns IsInitialized()==false by default for
//## compatibility reasons. Override in sub-classes that
//## support distinction between empty/non-empty state.
virtual bool IsEmpty() const;
//##Documentation
//## @brief Set the requested region from this data object to match the requested
//## region of the data object passed in as a parameter.
//##
//## This method is implemented in the concrete subclasses of BaseData.
virtual void SetRequestedRegion(const itk::DataObject *data)=0;
//##Documentation
//##@brief overwrite if the Data can be called by an Interactor (StateMachine).
//##
//## Empty by default. Overwrite and implement all the necessary operations here
//## and get the necessary information from the parameter operation.
void ExecuteOperation(Operation* operation);
/**
- * \brief Set the Geometry3D of the data, which will be referenced (not copied!).
+ * \brief Set the BaseGeometry of the data, which will be referenced (not copied!).
* Assumes the data object has only 1 time step ( is a 3D object ) and creates a
- * new TimeGeometry which saves the given Geometry3D. If an TimeGeometry has already
+ * new TimeGeometry which saves the given BaseGeometry. If an TimeGeometry has already
* been set for the object, it will be replaced after calling this function.
*
* @warning This method will normally be called internally by the sub-class of BaseData
* during initialization.
* \sa SetClonedGeometry
*/
- virtual void SetGeometry(Geometry3D* aGeometry3D);
+ virtual void SetGeometry(BaseGeometry* aGeometry3D);
/**
* \brief Set the TimeGeometry of the data, which will be referenced (not copied!).
*
* @warning This method will normally be called internally by the sub-class of BaseData
* during initialization.
* \sa SetClonedTimeGeometry
*/
virtual void SetTimeGeometry (TimeGeometry* geometry);
/**
* \brief Set a clone of the provided TimeGeometry as TimeGeometry of the data.
* Assumes the data object has only 1 time step ( is a 3D object ) and
* creates a new TimeGeometry. If an TimeGeometry has already
* been set for the object, it will be replaced after calling this function.
*
* \sa SetGeometry
*/
- virtual void SetClonedGeometry(const Geometry3D* aGeometry3D);
+ virtual void SetClonedGeometry(const BaseGeometry* aGeometry3D);
/**
* \brief Set a clone of the provided TimeGeometry as TimeGeometry of the data.
*
* \sa SetGeometry
*/
virtual void SetClonedTimeGeometry (const TimeGeometry* geometry);
//##Documentation
- //## @brief Set a clone of the provided geometry as Geometry3D of a given time step.
+ //## @brief Set a clone of the provided geometry as BaseGeometry of a given time step.
//##
//## \sa SetGeometry
- virtual void SetClonedGeometry(const Geometry3D* aGeometry3D, unsigned int time);
+ virtual void SetClonedGeometry(const BaseGeometry* aGeometry3D, unsigned int time);
//##Documentation
//## @brief Get the data's property list
//## @sa GetProperty
//## @sa m_PropertyList
mitk::PropertyList::Pointer GetPropertyList() const;
//##Documentation
//## @brief Set the data's property list
//## @sa SetProperty
//## @sa m_PropertyList
void SetPropertyList(PropertyList* propertyList);
//##Documentation
//## @brief Get the property (instance of BaseProperty) with key @a propertyKey from the PropertyList,
//## and set it to this, respectively;
//## @sa GetPropertyList
//## @sa m_PropertyList
//## @sa m_MapOfPropertyLists
mitk::BaseProperty::Pointer GetProperty(const char *propertyKey) const;
void SetProperty(const char *propertyKey, BaseProperty* property);
//##Documentation
//## @brief Convenience method for setting the origin of
- //## the Geometry3D instances of all time steps
+ //## the BaseGeometry instances of all time steps
//##
- //## \warning Geometries contained in the Geometry3D will
- //## \em not be changed, e.g. in case the Geometry3D is a
+ //## \warning Geometries contained in the BaseGeometry will
+ //## \em not be changed, e.g. in case the BaseGeometry is a
//## SlicedGeometry3D the origin will \em not be propagated
//## to the contained slices. The sub-class SlicedData
//## does this for the case that the SlicedGeometry3D is
//## evenly spaced.
virtual void SetOrigin(const Point3D& origin);
/** \brief Get the process object that generated this data object.
*
* If there is no process object, then the data object has
* been disconnected from the pipeline, or the data object
* was created manually. (Note: we cannot use the GetObjectMacro()
* defined in itkMacro because the mutual dependency of
* DataObject and ProcessObject causes compile problems. Also,
* a forward reference smart pointer is returned, not a smart pointer,
* because of the circular dependency between the process and data object.)
*
* GetSource() returns a SmartPointer and not a WeakPointer
* because it is assumed the code calling GetSource() wants to hold a
* long term reference to the source. */
itk::SmartPointer<mitk::BaseDataSource> GetSource() const;
//##Documentation
//## @brief Get the number of time steps from the TimeGeometry
//## As the base data has not a data vector given by itself, the number
//## of time steps is defined over the time sliced geometry. In sub classes,
//## a better implementation could be over the length of the data vector.
unsigned int GetTimeSteps() const
{
return m_TimeGeometry->CountTimeSteps();
}
//##Documentation
//## @brief Get the modified time of the last change of the contents
//## this data object or its geometry.
virtual unsigned long GetMTime() const;
/**
* \sa itk::ProcessObject::Graft
*/
virtual void Graft(const DataObject*);
protected:
BaseData();
BaseData(const BaseData &other);
~BaseData();
//##Documentation
//## \brief Initialize the TimeGeometry for a number of time steps.
//## The TimeGeometry is initialized empty and evenly timed.
//## In many cases it will be necessary to overwrite this in sub-classes.
virtual void InitializeTimeGeometry( unsigned int timeSteps = 1 );
/**
* \brief Initialize the TimeGeometry for a number of time steps.
* The TimeGeometry is initialized empty and evenly timed.
* In many cases it will be necessary to overwrite this in sub-classes.
* \deprecatedSince{2013_09} Please use GetUpdatedTimeGeometry instead: For additional information see http://www.mitk.org/Development/Refactoring%20of%20the%20Geometry%20Classes%20-%20Part%201
*/
DEPRECATED(virtual void InitializeTimeSlicedGeometry( unsigned int timeSteps = 1 ))
{
InitializeTimeGeometry(timeSteps);
}
//##Documentation
//## @brief reset to non-initialized state, release memory
virtual void ClearData();
//##Documentation
//## @brief Pure virtual; Must be used in subclasses to get a data object to a
//## valid state. Should at least create one empty object and call
//## Superclass::InitializeTimeGeometry() to ensure an existing valid geometry
virtual void InitializeEmpty(){}
virtual void PrintSelf(std::ostream& os, itk::Indent indent) const;
bool m_RequestedRegionInitialized;
bool m_LastRequestedRegionWasOutsideOfTheBufferedRegion;
mutable unsigned int m_SourceOutputIndexDuplicate;
bool m_Initialized;
private:
//##Documentation
//## @brief PropertyList, f.e. to hold pic-tags, tracking-data,..
//##
PropertyList::Pointer m_PropertyList;
TimeGeometry::Pointer m_TimeGeometry;
};
} // namespace mitk
#endif /* BASEDATA_H_HEADER_INCLUDED_C1EBB6FA */
diff --git a/Core/Code/DataManagement/mitkGeometry3D.cpp b/Core/Code/DataManagement/mitkBaseGeometry.cpp
similarity index 61%
copy from Core/Code/DataManagement/mitkGeometry3D.cpp
copy to Core/Code/DataManagement/mitkBaseGeometry.cpp
index 70789582b1..5b4a6a0397 100644
--- a/Core/Code/DataManagement/mitkGeometry3D.cpp
+++ b/Core/Code/DataManagement/mitkBaseGeometry.cpp
@@ -1,978 +1,1095 @@
/*===================================================================
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 <sstream>
#include <iomanip>
-#include "mitkGeometry3D.h"
+#include "mitkBaseGeometry.h"
+#include "mitkvector.h"
#include "mitkMatrixConvert.h"
+#include <vtkMatrixToLinearTransform.h>
+#include <vtkMatrix4x4.h>
#include "mitkRotationOperation.h"
#include "mitkRestorePlanePositionOperation.h"
#include "mitkApplyTransformMatrixOperation.h"
#include "mitkPointOperation.h"
#include "mitkInteractionConst.h"
+#include "mitkModifiedLock.h"
-#include <vtkMatrixToLinearTransform.h>
-#include <vtkMatrix4x4.h>
-
-// Standard constructor for the New() macro. Sets the geometry to 3 dimensions
-mitk::Geometry3D::Geometry3D()
- : m_ParametricBoundingBox(NULL),
- m_ImageGeometry(false), m_Valid(true), m_FrameOfReferenceID(0), m_IndexToWorldTransformLastModified(0)
+mitk::BaseGeometry::BaseGeometry(): Superclass(), mitk::OperationActor(),
+ m_FrameOfReferenceID(0), m_IndexToWorldTransformLastModified(0), m_ImageGeometry(false), m_ModifiedLockFlag(false), m_ModifiedCalledFlag(false)
{
- FillVector3D(m_FloatSpacing, 1,1,1);
m_VtkMatrix = vtkMatrix4x4::New();
m_VtkIndexToWorldTransform = vtkMatrixToLinearTransform::New();
m_VtkIndexToWorldTransform->SetInput(m_VtkMatrix);
Initialize();
}
-mitk::Geometry3D::Geometry3D(const Geometry3D& other) : Superclass(), mitk::OperationActor(), m_ParametricBoundingBox(other.m_ParametricBoundingBox),m_TimeBounds(other.m_TimeBounds),
- m_ImageGeometry(other.m_ImageGeometry), m_Valid(other.m_Valid), m_FrameOfReferenceID(other.m_FrameOfReferenceID), m_IndexToWorldTransformLastModified(other.m_IndexToWorldTransformLastModified), m_RotationQuaternion( other.m_RotationQuaternion ) , m_Origin(other.m_Origin)
+
+mitk::BaseGeometry::BaseGeometry(const BaseGeometry& other): Superclass(), //m_TimeBounds(other.m_TimeBounds),
+ m_FrameOfReferenceID(other.m_FrameOfReferenceID), m_IndexToWorldTransformLastModified(other.m_IndexToWorldTransformLastModified), m_Origin(other.m_Origin),
+ m_ImageGeometry(other.m_ImageGeometry), m_ModifiedLockFlag(false), m_ModifiedCalledFlag(false)
{
+ // DEPRECATED(m_RotationQuaternion = other.m_RotationQuaternion);
// AffineGeometryFrame
SetBounds(other.GetBounds());
- //SetIndexToObjectTransform(other.GetIndexToObjectTransform());
- //SetObjectToNodeTransform(other.GetObjectToNodeTransform());
- //SetIndexToWorldTransform(other.GetIndexToWorldTransform());
- // this is not used in AffineGeometryFrame of ITK, thus there are not Get and Set methods
- // m_IndexToNodeTransform = other.m_IndexToNodeTransform;
- // m_InvertedTransform = TransformType::New();
- // m_InvertedTransform = TransformType::New();
- // m_InvertedTransform->DeepCopy(other.m_InvertedTransform);
m_VtkMatrix = vtkMatrix4x4::New();
m_VtkMatrix->DeepCopy(other.m_VtkMatrix);
- if (other.m_ParametricBoundingBox.IsNotNull())
- {
- m_ParametricBoundingBox = other.m_ParametricBoundingBox->DeepCopy();
- }
- FillVector3D(m_FloatSpacing,other.m_FloatSpacing[0],other.m_FloatSpacing[1],other.m_FloatSpacing[2]);
+
m_VtkIndexToWorldTransform = vtkMatrixToLinearTransform::New();
m_VtkIndexToWorldTransform->DeepCopy(other.m_VtkIndexToWorldTransform);
m_VtkIndexToWorldTransform->SetInput(m_VtkMatrix);
other.InitializeGeometry(this);
}
-mitk::Geometry3D::~Geometry3D()
+mitk::BaseGeometry::~BaseGeometry()
{
m_VtkMatrix->Delete();
m_VtkIndexToWorldTransform->Delete();
}
+const mitk::Point3D& mitk::BaseGeometry::GetOrigin() const
+{
+ return m_Origin;
+}
+
+void mitk::BaseGeometry::SetOrigin(const Point3D & origin)
+{
+ mitk::ModifiedLock lock(this);
+
+ if(origin!=GetOrigin())
+ {
+ m_Origin = origin;
+ m_IndexToWorldTransform->SetOffset(m_Origin.GetVectorFromOrigin());
+ Modified();
+ TransferItkToVtkTransform();
+ }
+}
-static void CopySpacingFromTransform(mitk::AffineTransform3D* transform, mitk::Vector3D& spacing, float floatSpacing[3])
+void mitk::BaseGeometry::TransferItkToVtkTransform()
+{
+ mitk::ModifiedLock lock(this);
+ // copy m_IndexToWorldTransform into m_VtkIndexToWorldTransform
+
+ TransferItkTransformToVtkMatrix(m_IndexToWorldTransform.GetPointer(), m_VtkMatrix);
+ m_VtkIndexToWorldTransform->Modified();
+}
+
+static void CopySpacingFromTransform(mitk::AffineTransform3D* transform, mitk::Vector3D& spacing)
{
mitk::AffineTransform3D::MatrixType::InternalMatrixType vnlmatrix;
vnlmatrix = transform->GetMatrix().GetVnlMatrix();
spacing[0]=vnlmatrix.get_column(0).magnitude();
spacing[1]=vnlmatrix.get_column(1).magnitude();
spacing[2]=vnlmatrix.get_column(2).magnitude();
- floatSpacing[0]=spacing[0];
- floatSpacing[1]=spacing[1];
- floatSpacing[2]=spacing[2];
}
-
-void mitk::Geometry3D::Initialize()
+void mitk::BaseGeometry::Initialize()
{
float b[6] = {0,1,0,1,0,1};
SetFloatBounds(b);
if(m_IndexToWorldTransform.IsNull())
m_IndexToWorldTransform = TransformType::New();
else
m_IndexToWorldTransform->SetIdentity();
- CopySpacingFromTransform(m_IndexToWorldTransform, m_Spacing, m_FloatSpacing);
+ CopySpacingFromTransform(m_IndexToWorldTransform, m_Spacing);
vtk2itk(m_IndexToWorldTransform->GetOffset(), m_Origin);
m_VtkMatrix->Identity();
- m_TimeBounds[0]=ScalarTypeNumericTraits::NonpositiveMin(); m_TimeBounds[1]=ScalarTypeNumericTraits::max();
+ //m_TimeBounds[0]=ScalarTypeNumericTraits::NonpositiveMin(); m_TimeBounds[1]=ScalarTypeNumericTraits::max();
m_FrameOfReferenceID = 0;
m_ImageGeometry = false;
-}
-
-void mitk::Geometry3D::TransferItkToVtkTransform()
-{
- // copy m_IndexToWorldTransform into m_VtkIndexToWorldTransform
- TransferItkTransformToVtkMatrix(m_IndexToWorldTransform.GetPointer(), m_VtkMatrix);
- m_VtkIndexToWorldTransform->Modified();
-}
-void mitk::Geometry3D::TransferVtkToItkTransform()
-{
- TransferVtkMatrixToItkTransform(m_VtkMatrix, m_IndexToWorldTransform.GetPointer());
- CopySpacingFromTransform(m_IndexToWorldTransform, m_Spacing, m_FloatSpacing);
- vtk2itk(m_IndexToWorldTransform->GetOffset(), m_Origin);
+ this->PostInitialize();
}
-void mitk::Geometry3D::SetIndexToWorldTransformByVtkMatrix(vtkMatrix4x4* vtkmatrix)
+void mitk::BaseGeometry::PostInitializeGeometry(BaseGeometry * newGeometry) const
{
- m_VtkMatrix->DeepCopy(vtkmatrix);
- TransferVtkToItkTransform();
-}
-
-void mitk::Geometry3D::SetTimeBounds(const TimeBounds& timebounds)
-{
- if(m_TimeBounds != timebounds)
- {
- m_TimeBounds = timebounds;
- Modified();
- }
+ newGeometry->m_ImageGeometry = m_ImageGeometry;
}
-void mitk::Geometry3D::SetFloatBounds(const float bounds[6])
+void mitk::BaseGeometry::SetFloatBounds(const float bounds[6])
{
mitk::BoundingBox::BoundsArrayType b;
const float *input = bounds;
int i=0;
for(mitk::BoundingBox::BoundsArrayType::Iterator it = b.Begin(); i < 6 ;++i) *it++ = (mitk::ScalarType)*input++;
SetBounds(b);
}
-void mitk::Geometry3D::SetFloatBounds(const double bounds[6])
+void mitk::BaseGeometry::SetFloatBounds(const double bounds[6])
{
mitk::BoundingBox::BoundsArrayType b;
const double *input = bounds;
int i=0;
for(mitk::BoundingBox::BoundsArrayType::Iterator it = b.Begin(); i < 6 ;++i) *it++ = (mitk::ScalarType)*input++;
SetBounds(b);
}
-void mitk::Geometry3D::SetParametricBounds(const BoundingBox::BoundsArrayType& bounds)
+/** Initialize the geometry */
+void
+ mitk::BaseGeometry::InitializeGeometry(BaseGeometry* newGeometry) const
{
- m_ParametricBoundingBox = BoundingBoxType::New();
+ newGeometry->SetBounds(m_BoundingBox->GetBounds());
+ // we have to create a new transform!!
+ //newGeometry->SetTimeBounds(m_TimeBounds);
+ newGeometry->SetFrameOfReferenceID(GetFrameOfReferenceID());
+
+ if(m_IndexToWorldTransform)
+ {
+ TransformType::Pointer indexToWorldTransform = TransformType::New();
+ indexToWorldTransform->SetCenter( m_IndexToWorldTransform->GetCenter() );
+ indexToWorldTransform->SetMatrix( m_IndexToWorldTransform->GetMatrix() );
+ indexToWorldTransform->SetOffset( m_IndexToWorldTransform->GetOffset() );
+ newGeometry->SetIndexToWorldTransform(indexToWorldTransform);
+ }
+
+ this->PostInitializeGeometry(newGeometry);
+}
+void mitk::BaseGeometry::PostInitialize()
+{
+}
+
+/** Set the bounds */
+void mitk::BaseGeometry::SetBounds(const BoundsArrayType& bounds)
+{
+ mitk::ModifiedLock lock(this);
+
+ PreSetBounds(bounds);
+
+ m_BoundingBox = BoundingBoxType::New();
BoundingBoxType::PointsContainer::Pointer pointscontainer =
- BoundingBoxType::PointsContainer::New();
+ BoundingBoxType::PointsContainer::New();
BoundingBoxType::PointType p;
BoundingBoxType::PointIdentifier pointid;
for(pointid=0; pointid<2;++pointid)
- {
+ {
unsigned int i;
- for(i=0; i<NDimensions; ++i)
- {
+ for(i=0; i<m_NDimensions; ++i)
+ {
p[i] = bounds[2*i+pointid];
- }
- pointscontainer->InsertElement(pointid, p);
}
+ pointscontainer->InsertElement(pointid, p);
+ }
- m_ParametricBoundingBox->SetPoints(pointscontainer);
- m_ParametricBoundingBox->ComputeBoundingBox();
+ m_BoundingBox->SetPoints(pointscontainer);
+ m_BoundingBox->ComputeBoundingBox();
this->Modified();
}
-void mitk::Geometry3D::WorldToIndex(const mitk::Point3D &pt_mm, mitk::Point3D &pt_units) const
+void mitk::BaseGeometry::PreSetBounds(const BoundsArrayType& bounds){};
+
+void mitk::BaseGeometry::SetIndexToWorldTransform(mitk::AffineTransform3D* transform)
{
- BackTransform(pt_mm, pt_units);
+ mitk::ModifiedLock lock(this);
+
+ PreSetIndexToWorldTransform(transform);
+ if(m_IndexToWorldTransform.GetPointer() != transform)
+ {
+ m_IndexToWorldTransform = transform;
+ CopySpacingFromTransform(m_IndexToWorldTransform, m_Spacing);
+ vtk2itk(m_IndexToWorldTransform->GetOffset(), m_Origin);
+ TransferItkToVtkTransform();
+ Modified();
+ }
+ PostSetIndexToWorldTransform(transform);
}
-void mitk::Geometry3D::IndexToWorld(const mitk::Point3D &pt_units, mitk::Point3D &pt_mm) const
+void mitk::BaseGeometry::PreSetIndexToWorldTransform(mitk::AffineTransform3D* transform)
+{}
+void mitk::BaseGeometry::PostSetIndexToWorldTransform(mitk::AffineTransform3D* transform)
+{}
+
+const mitk::BaseGeometry::BoundsArrayType mitk::BaseGeometry::GetBounds() const
{
- pt_mm = m_IndexToWorldTransform->TransformPoint(pt_units);
+ assert(m_BoundingBox.IsNotNull());
+ return m_BoundingBox->GetBounds();
}
-void mitk::Geometry3D::WorldToIndex(const mitk::Point3D & /*atPt3d_mm*/, const mitk::Vector3D &vec_mm, mitk::Vector3D &vec_units) const
+bool mitk::BaseGeometry::IsValid() const
{
- MITK_WARN<<"Warning! Call of the deprecated function Geometry3D::WorldToIndex(point, vec, vec). Use Geometry3D::WorldToIndex(vec, vec) instead!";
- //BackTransform(atPt3d_mm, vec_mm, vec_units);
- this->WorldToIndex(vec_mm, vec_units);
+ return true;
}
-void mitk::Geometry3D::WorldToIndex( const mitk::Vector3D &vec_mm, mitk::Vector3D &vec_units) const
+void mitk::BaseGeometry::SetSpacing(const mitk::Vector3D& aSpacing, bool enforceSetSpacing )
{
- BackTransform( vec_mm, vec_units);
+ PreSetSpacing(aSpacing);
+ _SetSpacing(aSpacing, enforceSetSpacing);
+}
+
+void mitk::BaseGeometry::PreSetSpacing(const mitk::Vector3D& aSpacing)
+{}
+void mitk::BaseGeometry::_SetSpacing(const mitk::Vector3D& aSpacing, bool enforceSetSpacing){
+ if(mitk::Equal(m_Spacing, aSpacing) == false || enforceSetSpacing)
+ {
+ assert(aSpacing[0]>0 && aSpacing[1]>0 && aSpacing[2]>0);
+
+ m_Spacing = aSpacing;
+
+ AffineTransform3D::MatrixType::InternalMatrixType vnlmatrix;
+
+ vnlmatrix = m_IndexToWorldTransform->GetMatrix().GetVnlMatrix();
+
+ mitk::VnlVector col;
+ col = vnlmatrix.get_column(0); col.normalize(); col*=aSpacing[0]; vnlmatrix.set_column(0, col);
+ col = vnlmatrix.get_column(1); col.normalize(); col*=aSpacing[1]; vnlmatrix.set_column(1, col);
+ col = vnlmatrix.get_column(2); col.normalize(); col*=aSpacing[2]; vnlmatrix.set_column(2, col);
+
+ Matrix3D matrix;
+ matrix = vnlmatrix;
+
+ AffineTransform3D::Pointer transform = AffineTransform3D::New();
+ transform->SetMatrix(matrix);
+ transform->SetOffset(m_IndexToWorldTransform->GetOffset());
+
+ SetIndexToWorldTransform(transform.GetPointer());
+ }
}
-void mitk::Geometry3D::IndexToWorld(const mitk::Point3D &/*atPt3d_units*/, const mitk::Vector3D &vec_units, mitk::Vector3D &vec_mm) const
+mitk::Vector3D mitk::BaseGeometry::GetAxisVector(unsigned int direction) const
{
- MITK_WARN<<"Warning! Call of the deprecated function Geometry3D::IndexToWorld(point, vec, vec). Use Geometry3D::IndexToWorld(vec, vec) instead!";
- //vec_mm = m_IndexToWorldTransform->TransformVector(vec_units);
- this->IndexToWorld(vec_units, vec_mm);
+ Vector3D frontToBack;
+ frontToBack.SetVnlVector(m_IndexToWorldTransform->GetMatrix().GetVnlMatrix().get_column(direction));
+ frontToBack *= GetExtent(direction);
+ return frontToBack;
}
-void mitk::Geometry3D::IndexToWorld(const mitk::Vector3D &vec_units, mitk::Vector3D &vec_mm) const
+mitk::ScalarType mitk::BaseGeometry::GetExtent(unsigned int direction) const
{
- vec_mm = m_IndexToWorldTransform->TransformVector(vec_units);
+ assert(m_BoundingBox.IsNotNull());
+ if (direction>=m_NDimensions)
+ mitkThrow() << "Direction is too big. This geometry is for 3D Data";
+ BoundsArrayType bounds = m_BoundingBox->GetBounds();
+ return bounds[direction*2+1]-bounds[direction*2];
}
-void mitk::Geometry3D::SetIndexToWorldTransform(mitk::AffineTransform3D* transform)
+bool mitk::BaseGeometry::Is2DConvertable()
{
- if(m_IndexToWorldTransform.GetPointer() != transform)
+ bool isConvertableWithoutLoss = true;
+ do
{
- m_IndexToWorldTransform = transform;
- CopySpacingFromTransform(m_IndexToWorldTransform, m_Spacing, m_FloatSpacing);
- vtk2itk(m_IndexToWorldTransform->GetOffset(), m_Origin);
- TransferItkToVtkTransform();
- Modified();
- }
+ if (this->GetSpacing()[2] != 1)
+ {
+ isConvertableWithoutLoss = false;
+ break;
+ }
+ if (this->GetOrigin()[2] != 0)
+ {
+ isConvertableWithoutLoss = false;
+ break;
+ }
+ mitk::Vector3D col0, col1, col2;
+ col0.SetVnlVector(this->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(0));
+ col1.SetVnlVector(this->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(1));
+ col2.SetVnlVector(this->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(2));
+
+ if ((col0[2] != 0) || (col1[2] != 0) || (col2[0] != 0) || (col2[1] != 0) || (col2[2] != 1))
+ {
+ isConvertableWithoutLoss = false;
+ break;
+ }
+ } while (0);
+
+ return isConvertableWithoutLoss;
}
-itk::LightObject::Pointer mitk::Geometry3D::InternalClone() const
+mitk::Point3D mitk::BaseGeometry::GetCenter() const
{
- Self::Pointer newGeometry = new Self(*this);
- newGeometry->UnRegister();
- return newGeometry.GetPointer();
+ assert(m_BoundingBox.IsNotNull());
+ return m_IndexToWorldTransform->TransformPoint(m_BoundingBox->GetCenter());
}
-/*
-void mitk::Geometry3D::InitializeGeometry(Geometry3D * newGeometry) const
+
+double mitk::BaseGeometry::GetDiagonalLength2() const
{
- Superclass::InitializeGeometry(newGeometry);
+ Vector3D diagonalvector = GetCornerPoint()-GetCornerPoint(false, false, false);
+ return diagonalvector.GetSquaredNorm();
+}
- newGeometry->SetTimeBounds(m_TimeBounds);
+//##Documentation
+//## @brief Get the length of the diagonal of the bounding-box in mm
+//##
+double mitk::BaseGeometry::GetDiagonalLength() const
+{
+ return sqrt(GetDiagonalLength2());
+}
- //newGeometry->GetVtkTransform()->SetMatrix(m_VtkIndexToWorldTransform->GetMatrix()); IW
- //newGeometry->TransferVtkToItkTransform(); //MH
+mitk::Point3D mitk::BaseGeometry::GetCornerPoint(int id) const
+{
+ assert(id >= 0);
+ assert(this->IsBoundingBoxNull()==false);
- newGeometry->SetFrameOfReferenceID(GetFrameOfReferenceID());
- newGeometry->m_ImageGeometry = m_ImageGeometry;
+ BoundingBox::BoundsArrayType bounds = this->GetBoundingBox()->GetBounds();
+
+ Point3D cornerpoint;
+ switch(id)
+ {
+ case 0: FillVector3D(cornerpoint, bounds[0],bounds[2],bounds[4]); break;
+ case 1: FillVector3D(cornerpoint, bounds[0],bounds[2],bounds[5]); break;
+ case 2: FillVector3D(cornerpoint, bounds[0],bounds[3],bounds[4]); break;
+ case 3: FillVector3D(cornerpoint, bounds[0],bounds[3],bounds[5]); break;
+ case 4: FillVector3D(cornerpoint, bounds[1],bounds[2],bounds[4]); break;
+ case 5: FillVector3D(cornerpoint, bounds[1],bounds[2],bounds[5]); break;
+ case 6: FillVector3D(cornerpoint, bounds[1],bounds[3],bounds[4]); break;
+ case 7: FillVector3D(cornerpoint, bounds[1],bounds[3],bounds[5]); break;
+ default:
+ {
+ itkExceptionMacro(<<"A cube only has 8 corners. These are labeled 0-7.");
+ }
+ }
+ if(m_ImageGeometry)
+ {
+ // Here i have to adjust the 0.5 offset manually, because the cornerpoint is the corner of the
+ // bounding box. The bounding box itself is no image, so it is corner-based
+ FillVector3D(cornerpoint, cornerpoint[0]-0.5, cornerpoint[1]-0.5, cornerpoint[2]-0.5);
+ }
+ return this->GetIndexToWorldTransform()->TransformPoint(cornerpoint);
+}
+
+mitk::Point3D mitk::BaseGeometry::GetCornerPoint(bool xFront, bool yFront, bool zFront) const
+{
+ assert(this->IsBoundingBoxNull()==false);
+ BoundingBox::BoundsArrayType bounds = this->GetBoundingBox()->GetBounds();
+
+ Point3D cornerpoint;
+ cornerpoint[0] = (xFront ? bounds[0] : bounds[1]);
+ cornerpoint[1] = (yFront ? bounds[2] : bounds[3]);
+ cornerpoint[2] = (zFront ? bounds[4] : bounds[5]);
+ if(m_ImageGeometry)
+ {
+ // Here i have to adjust the 0.5 offset manually, because the cornerpoint is the corner of the
+ // bounding box. The bounding box itself is no image, so it is corner-based
+ FillVector3D(cornerpoint, cornerpoint[0]-0.5, cornerpoint[1]-0.5, cornerpoint[2]-0.5);
+ }
+
+ return this->GetIndexToWorldTransform()->TransformPoint(cornerpoint);
}
-*/
-void mitk::Geometry3D::SetExtentInMM(int direction, ScalarType extentInMM)
+
+mitk::ScalarType mitk::BaseGeometry::GetExtentInMM(int direction) const
+{
+ return m_IndexToWorldTransform->GetMatrix().GetVnlMatrix().get_column(direction).magnitude()*GetExtent(direction);
+}
+
+void mitk::BaseGeometry::SetExtentInMM(int direction, ScalarType extentInMM)
{
+ mitk::ModifiedLock lock(this);
+
ScalarType len = GetExtentInMM(direction);
if(fabs(len - extentInMM)>=mitk::eps)
{
AffineTransform3D::MatrixType::InternalMatrixType vnlmatrix;
vnlmatrix = m_IndexToWorldTransform->GetMatrix().GetVnlMatrix();
if(len>extentInMM)
vnlmatrix.set_column(direction, vnlmatrix.get_column(direction)/len*extentInMM);
else
vnlmatrix.set_column(direction, vnlmatrix.get_column(direction)*extentInMM/len);
Matrix3D matrix;
matrix = vnlmatrix;
m_IndexToWorldTransform->SetMatrix(matrix);
Modified();
}
+ PostSetExtentInMM(direction,extentInMM);
}
-mitk::BoundingBox::Pointer mitk::Geometry3D::CalculateBoundingBoxRelativeToTransform(const mitk::AffineTransform3D* transform) const
-{
- mitk::BoundingBox::PointsContainer::Pointer pointscontainer=mitk::BoundingBox::PointsContainer::New();
+void mitk::BaseGeometry::PostSetExtentInMM(int direction, ScalarType extentInMM){};
- mitk::BoundingBox::PointIdentifier pointid=0;
+bool mitk::BaseGeometry::IsInside(const mitk::Point3D& p) const
+{
+ mitk::Point3D index;
+ WorldToIndex(p, index);
+ return IsIndexInside(index);
+}
- unsigned char i;
- if(transform!=NULL)
+bool mitk::BaseGeometry::IsIndexInside(const mitk::Point3D& index) const
+{
+ bool inside = false;
+ //if it is an image geometry, we need to convert the index to discrete values
+ //this is done by applying the rounding function also used in WorldToIndex (see line 323)
+ if (m_ImageGeometry)
{
- mitk::AffineTransform3D::Pointer inverse = mitk::AffineTransform3D::New();
- transform->GetInverse(inverse);
- for(i=0; i<8; ++i)
- pointscontainer->InsertElement( pointid++, inverse->TransformPoint( GetCornerPoint(i) ));
+ mitk::Point3D discretIndex;
+ discretIndex[0]=itk::Math::RoundHalfIntegerUp<mitk::ScalarType>( index[0] );
+ discretIndex[1]=itk::Math::RoundHalfIntegerUp<mitk::ScalarType>( index[1] );
+ discretIndex[2]=itk::Math::RoundHalfIntegerUp<mitk::ScalarType>( index[2] );
+
+ inside = this->GetBoundingBox()->IsInside(discretIndex);
+ //we have to check if the index is at the upper border of each dimension,
+ // because the boundingbox is not centerbased
+ if (inside)
+ {
+ const BoundingBox::BoundsArrayType& bounds = this->GetBoundingBox()->GetBounds();
+ if((discretIndex[0] == bounds[1]) ||
+ (discretIndex[1] == bounds[3]) ||
+ (discretIndex[2] == bounds[5]))
+ inside = false;
+ }
}
else
+ inside = this->GetBoundingBox()->IsInside(index);
+
+ return inside;
+}
+
+void mitk::BaseGeometry::WorldToIndex(const mitk::Point3D &pt_mm, mitk::Point3D &pt_units) const
+{
+ BackTransform(pt_mm, pt_units);
+}
+
+void mitk::BaseGeometry::WorldToIndex( const mitk::Vector3D &vec_mm, mitk::Vector3D &vec_units) const
+{
+ BackTransform( vec_mm, vec_units);
+}
+
+void mitk::BaseGeometry::BackTransform(const mitk::Vector3D& in, mitk::Vector3D& out) const
+{
+ // Get WorldToIndex transform
+ if (m_IndexToWorldTransformLastModified != m_IndexToWorldTransform->GetMTime())
{
- for(i=0; i<8; ++i)
- pointscontainer->InsertElement( pointid++, GetCornerPoint(i) );
+ m_InvertedTransform = TransformType::New();
+ if (!m_IndexToWorldTransform->GetInverse( m_InvertedTransform.GetPointer() ))
+ {
+ itkExceptionMacro( "Internal ITK matrix inversion error, cannot proceed." );
+ }
+ m_IndexToWorldTransformLastModified = m_IndexToWorldTransform->GetMTime();
}
- mitk::BoundingBox::Pointer result = mitk::BoundingBox::New();
- result->SetPoints(pointscontainer);
- result->ComputeBoundingBox();
+ // Check for valid matrix inversion
+ const TransformType::MatrixType& inverse = m_InvertedTransform->GetMatrix();
+ if(inverse.GetVnlMatrix().has_nans())
+ {
+ itkExceptionMacro( "Internal ITK matrix inversion error, cannot proceed. Matrix was: " << std::endl
+ << m_IndexToWorldTransform->GetMatrix() << "Suggested inverted matrix is:" << std::endl
+ << inverse );
+ }
- return result;
+ // Transform vector
+ for (unsigned int i = 0; i < 3; i++)
+ {
+ out[i] = 0.0;
+ for (unsigned int j = 0; j < 3; j++)
+ {
+ out[i] += inverse[i][j]*in[j];
+ }
+ }
+}
+
+void mitk::BaseGeometry::BackTransform(const mitk::Point3D &in, mitk::Point3D& out) const
+{
+ ScalarType temp[3];
+ unsigned int i, j;
+ const TransformType::OffsetType& offset = m_IndexToWorldTransform->GetOffset();
+
+ // Remove offset
+ for (j = 0; j < 3; j++)
+ {
+ temp[j] = in[j] - offset[j];
+ }
+
+ // Get WorldToIndex transform
+ if (m_IndexToWorldTransformLastModified != m_IndexToWorldTransform->GetMTime())
+ {
+ m_InvertedTransform = TransformType::New();
+ if (!m_IndexToWorldTransform->GetInverse( m_InvertedTransform.GetPointer() ))
+ {
+ itkExceptionMacro( "Internal ITK matrix inversion error, cannot proceed." );
+ }
+ m_IndexToWorldTransformLastModified = m_IndexToWorldTransform->GetMTime();
+ }
+
+ // Check for valid matrix inversion
+ const TransformType::MatrixType& inverse = m_InvertedTransform->GetMatrix();
+ if(inverse.GetVnlMatrix().has_nans())
+ {
+ itkExceptionMacro( "Internal ITK matrix inversion error, cannot proceed. Matrix was: " << std::endl
+ << m_IndexToWorldTransform->GetMatrix() << "Suggested inverted matrix is:" << std::endl
+ << inverse );
+ }
+
+ // Transform point
+ for (i = 0; i < 3; i++)
+ {
+ out[i] = 0.0;
+ for (j = 0; j < 3; j++)
+ {
+ out[i] += inverse[i][j]*temp[j];
+ }
+ }
+}
+
+mitk::VnlVector mitk::BaseGeometry::GetOriginVnl() const
+{
+ return const_cast<Self*>(this)->m_Origin.GetVnlVector();
+}
+
+vtkLinearTransform* mitk::BaseGeometry::GetVtkTransform() const
+{
+ return (vtkLinearTransform*)m_VtkIndexToWorldTransform;
+}
+
+void mitk::BaseGeometry::SetIdentity()
+{
+ mitk::ModifiedLock lock(this);
+
+ m_IndexToWorldTransform->SetIdentity();
+ m_Origin.Fill(0);
+ CopySpacingFromTransform(m_IndexToWorldTransform, m_Spacing);
+ Modified();
+ TransferItkToVtkTransform();
+}
+
+void mitk::BaseGeometry::TransferVtkToItkTransform()
+{
+ TransferVtkMatrixToItkTransform(m_VtkMatrix, m_IndexToWorldTransform.GetPointer());
+ CopySpacingFromTransform(m_IndexToWorldTransform, m_Spacing);
+ vtk2itk(m_IndexToWorldTransform->GetOffset(), m_Origin);
+}
+
+void mitk::BaseGeometry::Compose( const mitk::BaseGeometry::TransformType * other, bool pre )
+{
+ mitk::ModifiedLock lock(this);
+
+ m_IndexToWorldTransform->Compose(other, pre);
+ CopySpacingFromTransform(m_IndexToWorldTransform, m_Spacing);
+ vtk2itk(m_IndexToWorldTransform->GetOffset(), m_Origin);
+ Modified();
+ TransferItkToVtkTransform();
+}
+
+void mitk::BaseGeometry::Compose( const vtkMatrix4x4 * vtkmatrix, bool pre )
+{
+ mitk::BaseGeometry::TransformType::Pointer itkTransform = mitk::BaseGeometry::TransformType::New();
+ TransferVtkMatrixToItkTransform(vtkmatrix, itkTransform.GetPointer());
+ Compose(itkTransform, pre);
+}
+
+void mitk::BaseGeometry::Translate(const Vector3D & vector)
+{
+ if((vector[0] != 0) || (vector[1] != 0) || (vector[2] != 0))
+ {
+ this->SetOrigin(m_Origin + vector);
+ }
+}
+
+void mitk::BaseGeometry::IndexToWorld(const mitk::Point3D &pt_units, mitk::Point3D &pt_mm) const
+{
+ pt_mm = m_IndexToWorldTransform->TransformPoint(pt_units);
+}
+
+void mitk::BaseGeometry::IndexToWorld(const mitk::Vector3D &vec_units, mitk::Vector3D &vec_mm) const
+{
+ vec_mm = m_IndexToWorldTransform->TransformVector(vec_units);
}
#include <vtkTransform.h>
-void mitk::Geometry3D::ExecuteOperation(Operation* operation)
+void mitk::BaseGeometry::ExecuteOperation(Operation* operation)
{
+ mitk::ModifiedLock lock(this);
+
vtkTransform *vtktransform = vtkTransform::New();
vtktransform->SetMatrix(m_VtkMatrix);
switch (operation->GetOperationType())
{
case OpNOTHING:
break;
case OpMOVE:
{
mitk::PointOperation *pointOp = dynamic_cast<mitk::PointOperation *>(operation);
if (pointOp == NULL)
{
//mitk::StatusBar::GetInstance()->DisplayText("received wrong type of operation!See mitkAffineInteractor.cpp", 10000);
return;
}
mitk::Point3D newPos = pointOp->GetPoint();
ScalarType data[3];
vtktransform->GetPosition(data);
vtktransform->PostMultiply();
vtktransform->Translate(newPos[0], newPos[1], newPos[2]);
vtktransform->PreMultiply();
break;
}
case OpSCALE:
{
mitk::PointOperation *pointOp = dynamic_cast<mitk::PointOperation *>(operation);
if (pointOp == NULL)
{
//mitk::StatusBar::GetInstance()->DisplayText("received wrong type of operation!See mitkAffineInteractor.cpp", 10000);
return;
}
mitk::Point3D newScale = pointOp->GetPoint();
ScalarType data[3];
/* calculate new scale: newscale = oldscale * (oldscale + scaletoadd)/oldscale */
data[0] = 1 + (newScale[0] / GetMatrixColumn(0).magnitude());
data[1] = 1 + (newScale[1] / GetMatrixColumn(1).magnitude());
data[2] = 1 + (newScale[2] / GetMatrixColumn(2).magnitude());
mitk::Point3D center = const_cast<mitk::BoundingBox*>(m_BoundingBox.GetPointer())->GetCenter();
ScalarType pos[3];
vtktransform->GetPosition(pos);
vtktransform->PostMultiply();
vtktransform->Translate(-pos[0], -pos[1], -pos[2]);
vtktransform->Translate(-center[0], -center[1], -center[2]);
vtktransform->PreMultiply();
vtktransform->Scale(data[0], data[1], data[2]);
vtktransform->PostMultiply();
vtktransform->Translate(+center[0], +center[1], +center[2]);
vtktransform->Translate(pos[0], pos[1], pos[2]);
vtktransform->PreMultiply();
break;
}
case OpROTATE:
{
mitk::RotationOperation *rotateOp = dynamic_cast<mitk::RotationOperation *>(operation);
if (rotateOp == NULL)
{
//mitk::StatusBar::GetInstance()->DisplayText("received wrong type of operation!See mitkAffineInteractor.cpp", 10000);
return;
}
Vector3D rotationVector = rotateOp->GetVectorOfRotation();
Point3D center = rotateOp->GetCenterOfRotation();
ScalarType angle = rotateOp->GetAngleOfRotation();
vtktransform->PostMultiply();
vtktransform->Translate(-center[0], -center[1], -center[2]);
vtktransform->RotateWXYZ(angle, rotationVector[0], rotationVector[1], rotationVector[2]);
vtktransform->Translate(center[0], center[1], center[2]);
vtktransform->PreMultiply();
break;
}
case OpRESTOREPLANEPOSITION:
- {
+ {
//Copy necessary to avoid vtk warning
vtkMatrix4x4* matrix = vtkMatrix4x4::New();
TransferItkTransformToVtkMatrix(dynamic_cast<mitk::RestorePlanePositionOperation*>(operation)->GetTransform().GetPointer(), matrix);
vtktransform->SetMatrix(matrix);
break;
- }
+ }
case OpAPPLYTRANSFORMMATRIX:
- {
- ApplyTransformMatrixOperation *applyMatrixOp = dynamic_cast< ApplyTransformMatrixOperation* >( operation );
- vtktransform->SetMatrix(applyMatrixOp->GetMatrix());
- break;
- }
+ {
+ ApplyTransformMatrixOperation *applyMatrixOp = dynamic_cast< ApplyTransformMatrixOperation* >( operation );
+ vtktransform->SetMatrix(applyMatrixOp->GetMatrix());
+ break;
+ }
default:
vtktransform->Delete();
return;
}
m_VtkMatrix->DeepCopy(vtktransform->GetMatrix());
TransferVtkToItkTransform();
Modified();
vtktransform->Delete();
}
-void mitk::Geometry3D::BackTransform(const mitk::Point3D &in, mitk::Point3D& out) const
+mitk::VnlVector mitk::BaseGeometry::GetMatrixColumn(unsigned int direction) const
{
- ScalarType temp[3];
- unsigned int i, j;
- const TransformType::OffsetType& offset = m_IndexToWorldTransform->GetOffset();
+ return m_IndexToWorldTransform->GetMatrix().GetVnlMatrix().get_column(direction);
+}
- // Remove offset
- for (j = 0; j < 3; j++)
- {
- temp[j] = in[j] - offset[j];
- }
+mitk::BoundingBox::Pointer mitk::BaseGeometry::CalculateBoundingBoxRelativeToTransform(const mitk::AffineTransform3D* transform) const
+{
+ mitk::BoundingBox::PointsContainer::Pointer pointscontainer=mitk::BoundingBox::PointsContainer::New();
- // Get WorldToIndex transform
- if (m_IndexToWorldTransformLastModified != m_IndexToWorldTransform->GetMTime())
+ mitk::BoundingBox::PointIdentifier pointid=0;
+
+ unsigned char i;
+ if(transform!=NULL)
{
- m_InvertedTransform = TransformType::New();
- if (!m_IndexToWorldTransform->GetInverse( m_InvertedTransform.GetPointer() ))
- {
- itkExceptionMacro( "Internal ITK matrix inversion error, cannot proceed." );
- }
- m_IndexToWorldTransformLastModified = m_IndexToWorldTransform->GetMTime();
+ mitk::AffineTransform3D::Pointer inverse = mitk::AffineTransform3D::New();
+ transform->GetInverse(inverse);
+ for(i=0; i<8; ++i)
+ pointscontainer->InsertElement( pointid++, inverse->TransformPoint( GetCornerPoint(i) ));
}
-
- // Check for valid matrix inversion
- const TransformType::MatrixType& inverse = m_InvertedTransform->GetMatrix();
- if(inverse.GetVnlMatrix().has_nans())
+ else
{
- itkExceptionMacro( "Internal ITK matrix inversion error, cannot proceed. Matrix was: " << std::endl
- << m_IndexToWorldTransform->GetMatrix() << "Suggested inverted matrix is:" << std::endl
- << inverse );
+ for(i=0; i<8; ++i)
+ pointscontainer->InsertElement( pointid++, GetCornerPoint(i) );
}
- // Transform point
- for (i = 0; i < 3; i++)
+ mitk::BoundingBox::Pointer result = mitk::BoundingBox::New();
+ result->SetPoints(pointscontainer);
+ result->ComputeBoundingBox();
+
+ return result;
+}
+
+//void mitk::BaseGeometry::SetTimeBounds(const TimeBounds& timebounds)
+//{
+// mitk::ModifiedLock lock(this);
+//
+// if(m_TimeBounds != timebounds)
+// {
+// m_TimeBounds = timebounds;
+// Modified();
+// }
+// PostSetTimeBounds(timebounds);
+//}
+//
+//void mitk::BaseGeometry::PostSetTimeBounds(const TimeBounds& timebounds)
+//{}
+
+const std::string mitk::BaseGeometry::GetTransformAsString( TransformType* transformType )
+{
+ std::ostringstream out;
+
+ out << '[';
+
+ for( int i=0; i<3; ++i )
{
- out[i] = 0.0;
- for (j = 0; j < 3; j++)
- {
- out[i] += inverse[i][j]*temp[j];
- }
+ out << '[';
+ for( int j=0; j<3; ++j )
+ out << transformType->GetMatrix().GetVnlMatrix().get(i, j) << ' ';
+ out << ']';
}
+
+ out << "][";
+
+ for( int i=0; i<3; ++i )
+ out << transformType->GetOffset()[i] << ' ';
+
+ out << "]\0";
+
+ return out.str();
+}
+
+void mitk::BaseGeometry::SetIndexToWorldTransformByVtkMatrix(vtkMatrix4x4* vtkmatrix)
+{
+ m_VtkMatrix->DeepCopy(vtkmatrix);
+ TransferVtkToItkTransform();
+}
+
+void mitk::BaseGeometry::WorldToIndex(const mitk::Point3D & /*atPt3d_mm*/, const mitk::Vector3D &vec_mm, mitk::Vector3D &vec_units) const
+{
+ MITK_WARN<<"Warning! Call of the deprecated function BaseGeometry::WorldToIndex(point, vec, vec). Use BaseGeometry::WorldToIndex(vec, vec) instead!";
+ //BackTransform(atPt3d_mm, vec_mm, vec_units);
+ this->WorldToIndex(vec_mm, vec_units);
+}
+
+void mitk::BaseGeometry::IndexToWorld(const mitk::Point3D &/*atPt3d_units*/, const mitk::Vector3D &vec_units, mitk::Vector3D &vec_mm) const
+{
+ MITK_WARN<<"Warning! Call of the deprecated function BaseGeometry::IndexToWorld(point, vec, vec). Use BaseGeometry::IndexToWorld(vec, vec) instead!";
+ //vec_mm = m_IndexToWorldTransform->TransformVector(vec_units);
+ this->IndexToWorld(vec_units, vec_mm);
}
-void mitk::Geometry3D::BackTransform(const mitk::Point3D &/*at*/, const mitk::Vector3D &in, mitk::Vector3D& out) const
+void mitk::BaseGeometry::BackTransform(const mitk::Point3D &/*at*/, const mitk::Vector3D &in, mitk::Vector3D& out) const
{
- MITK_INFO<<"Warning! Call of the deprecated function Geometry3D::BackTransform(point, vec, vec). Use Geometry3D::BackTransform(vec, vec) instead!";
+ MITK_INFO<<"Warning! Call of the deprecated function BaseGeometry::BackTransform(point, vec, vec). Use BaseGeometry::BackTransform(vec, vec) instead!";
//// Get WorldToIndex transform
//if (m_IndexToWorldTransformLastModified != m_IndexToWorldTransform->GetMTime())
//{
// m_InvertedTransform = TransformType::New();
// if (!m_IndexToWorldTransform->GetInverse( m_InvertedTransform.GetPointer() ))
// {
// itkExceptionMacro( "Internal ITK matrix inversion error, cannot proceed." );
// }
// m_IndexToWorldTransformLastModified = m_IndexToWorldTransform->GetMTime();
//}
//// Check for valid matrix inversion
//const TransformType::MatrixType& inverse = m_InvertedTransform->GetMatrix();
//if(inverse.GetVnlMatrix().has_nans())
//{
// itkExceptionMacro( "Internal ITK matrix inversion error, cannot proceed. Matrix was: " << std::endl
// << m_IndexToWorldTransform->GetMatrix() << "Suggested inverted matrix is:" << std::endl
// << inverse );
//}
//// Transform vector
//for (unsigned int i = 0; i < 3; i++)
//{
// out[i] = 0.0;
// for (unsigned int j = 0; j < 3; j++)
// {
// out[i] += inverse[i][j]*in[j];
// }
//}
this->BackTransform(in, out);
}
-void mitk::Geometry3D::BackTransform(const mitk::Vector3D& in, mitk::Vector3D& out) const
-{
- // Get WorldToIndex transform
- if (m_IndexToWorldTransformLastModified != m_IndexToWorldTransform->GetMTime())
- {
- m_InvertedTransform = TransformType::New();
- if (!m_IndexToWorldTransform->GetInverse( m_InvertedTransform.GetPointer() ))
- {
- itkExceptionMacro( "Internal ITK matrix inversion error, cannot proceed." );
- }
- m_IndexToWorldTransformLastModified = m_IndexToWorldTransform->GetMTime();
- }
-
- // Check for valid matrix inversion
- const TransformType::MatrixType& inverse = m_InvertedTransform->GetMatrix();
- if(inverse.GetVnlMatrix().has_nans())
- {
- itkExceptionMacro( "Internal ITK matrix inversion error, cannot proceed. Matrix was: " << std::endl
- << m_IndexToWorldTransform->GetMatrix() << "Suggested inverted matrix is:" << std::endl
- << inverse );
- }
-
- // Transform vector
- for (unsigned int i = 0; i < 3; i++)
- {
- out[i] = 0.0;
- for (unsigned int j = 0; j < 3; j++)
- {
- out[i] += inverse[i][j]*in[j];
- }
- }
-}
-
-const float* mitk::Geometry3D::GetFloatSpacing() const
-{
- return m_FloatSpacing;
-}
-
-void mitk::Geometry3D::SetSpacing(const mitk::Vector3D& aSpacing)
-{
- if(mitk::Equal(m_Spacing, aSpacing) == false)
- {
- assert(aSpacing[0]>0 && aSpacing[1]>0 && aSpacing[2]>0);
-
- m_Spacing = aSpacing;
-
- AffineTransform3D::MatrixType::InternalMatrixType vnlmatrix;
-
- vnlmatrix = m_IndexToWorldTransform->GetMatrix().GetVnlMatrix();
-
- mitk::VnlVector col;
- col = vnlmatrix.get_column(0); col.normalize(); col*=aSpacing[0]; vnlmatrix.set_column(0, col);
- col = vnlmatrix.get_column(1); col.normalize(); col*=aSpacing[1]; vnlmatrix.set_column(1, col);
- col = vnlmatrix.get_column(2); col.normalize(); col*=aSpacing[2]; vnlmatrix.set_column(2, col);
-
- Matrix3D matrix;
- matrix = vnlmatrix;
-
- AffineTransform3D::Pointer transform = AffineTransform3D::New();
- transform->SetMatrix(matrix);
- transform->SetOffset(m_IndexToWorldTransform->GetOffset());
-
- SetIndexToWorldTransform(transform.GetPointer());
-
- itk2vtk(m_Spacing, m_FloatSpacing);
- }
-}
-
-void mitk::Geometry3D::SetOrigin(const Point3D & origin)
-{
- if(origin!=GetOrigin())
- {
- m_Origin = origin;
- m_IndexToWorldTransform->SetOffset(m_Origin.GetVectorFromOrigin());
- Modified();
- TransferItkToVtkTransform();
- }
+vtkMatrix4x4* mitk::BaseGeometry::GetVtkMatrix(){
+ return m_VtkMatrix;
}
-void mitk::Geometry3D::Translate(const Vector3D & vector)
-{
- if((vector[0] != 0) || (vector[1] != 0) || (vector[2] != 0))
- {
- this->SetOrigin(m_Origin + vector);
-// m_IndexToWorldTransform->SetOffset(m_IndexToWorldTransform->GetOffset()+vector);
-// TransferItkToVtkTransform();
-// Modified();
- }
+bool mitk::BaseGeometry::IsBoundingBoxNull() const{
+ return m_BoundingBox.IsNull();
}
-void mitk::Geometry3D::SetIdentity()
-{
- m_IndexToWorldTransform->SetIdentity();
- m_Origin.Fill(0);
- Modified();
- TransferItkToVtkTransform();
+bool mitk::BaseGeometry::IsIndexToWorldTransformNull() const{
+ return m_IndexToWorldTransform.IsNull();
}
-void mitk::Geometry3D::Compose( const mitk::Geometry3D::TransformType * other, bool pre )
+void
+ mitk::BaseGeometry::ChangeImageGeometryConsideringOriginOffset( const bool isAnImageGeometry )
{
- m_IndexToWorldTransform->Compose(other, pre);
- CopySpacingFromTransform(m_IndexToWorldTransform, m_Spacing, m_FloatSpacing);
- vtk2itk(m_IndexToWorldTransform->GetOffset(), m_Origin);
- Modified();
- TransferItkToVtkTransform();
-}
+ // If Geometry is switched to ImageGeometry, you have to put an offset to the origin, because
+ // imageGeometries origins are pixel-center-based
+ // ... and remove the offset, if you switch an imageGeometry back to a normal geometry
+ // For more information please see the Geometry documentation page
-void mitk::Geometry3D::Compose( const vtkMatrix4x4 * vtkmatrix, bool pre )
-{
- mitk::Geometry3D::TransformType::Pointer itkTransform = mitk::Geometry3D::TransformType::New();
- TransferVtkMatrixToItkTransform(vtkmatrix, itkTransform.GetPointer());
- Compose(itkTransform, pre);
-}
+ if(m_ImageGeometry == isAnImageGeometry)
+ return;
-const std::string mitk::Geometry3D::GetTransformAsString( TransformType* transformType )
-{
- std::ostringstream out;
+ const BoundingBox::BoundsArrayType& boundsarray =
+ this->GetBoundingBox()->GetBounds();
- out << '[';
+ Point3D originIndex;
+ FillVector3D(originIndex, boundsarray[0], boundsarray[2], boundsarray[4]);
- for( int i=0; i<3; ++i )
- {
- out << '[';
- for( int j=0; j<3; ++j )
- out << transformType->GetMatrix().GetVnlMatrix().get(i, j) << ' ';
- out << ']';
- }
+ if(isAnImageGeometry == true)
+ FillVector3D( originIndex,
+ originIndex[0] + 0.5,
+ originIndex[1] + 0.5,
+ originIndex[2] + 0.5 );
+ else
+ FillVector3D( originIndex,
+ originIndex[0] - 0.5,
+ originIndex[1] - 0.5,
+ originIndex[2] - 0.5 );
- out << "][";
+ Point3D originWorld;
- for( int i=0; i<3; ++i )
- out << transformType->GetOffset()[i] << ' ';
+ originWorld = GetIndexToWorldTransform()
+ ->TransformPoint( originIndex );
+ // instead could as well call IndexToWorld(originIndex,originWorld);
- out << "]\0";
+ SetOrigin(originWorld);
- return out.str();
+ this->SetImageGeometry(isAnImageGeometry);
}
-
-void mitk::Geometry3D::PrintSelf(std::ostream& os, itk::Indent indent) const
+//itk::LightObject::Pointer mitk::BaseGeometry::InternalClone() const
+//{
+// Self::Pointer newGeometry = new Self(*this);
+// newGeometry->UnRegister();
+// return newGeometry.GetPointer();
+//}
+
+void mitk::BaseGeometry::PrintSelf(std::ostream& os, itk::Indent indent) const
{
os << indent << " IndexToWorldTransform: ";
- if(m_IndexToWorldTransform.IsNull())
+ if(this->IsIndexToWorldTransformNull())
os << "NULL" << std::endl;
else
{
// from itk::MatrixOffsetTransformBase
unsigned int i, j;
os << std::endl;
os << indent << "Matrix: " << std::endl;
for (i = 0; i < 3; i++)
{
os << indent.GetNextIndent();
for (j = 0; j < 3; j++)
{
- os << m_IndexToWorldTransform->GetMatrix()[i][j] << " ";
+ os << this->GetIndexToWorldTransform()->GetMatrix()[i][j] << " ";
}
os << std::endl;
}
- os << indent << "Offset: " << m_IndexToWorldTransform->GetOffset() << std::endl;
- os << indent << "Center: " << m_IndexToWorldTransform->GetCenter() << std::endl;
- os << indent << "Translation: " << m_IndexToWorldTransform->GetTranslation() << std::endl;
+ os << indent << "Offset: " << this->GetIndexToWorldTransform()->GetOffset() << std::endl;
+ os << indent << "Center: " << this->GetIndexToWorldTransform()->GetCenter() << std::endl;
+ os << indent << "Translation: " << this->GetIndexToWorldTransform()->GetTranslation() << std::endl;
os << indent << "Inverse: " << std::endl;
for (i = 0; i < 3; i++)
{
os << indent.GetNextIndent();
for (j = 0; j < 3; j++)
{
- os << m_IndexToWorldTransform->GetInverseMatrix()[i][j] << " ";
+ os << this->GetIndexToWorldTransform()->GetInverseMatrix()[i][j] << " ";
}
os << std::endl;
}
// from itk::ScalableAffineTransform
os << indent << "Scale : ";
for (i = 0; i < 3; i++)
{
- os << m_IndexToWorldTransform->GetScale()[i] << " ";
+ os << this->GetIndexToWorldTransform()->GetScale()[i] << " ";
}
os << std::endl;
}
os << indent << " BoundingBox: ";
- if(m_BoundingBox.IsNull())
+ if(this->IsBoundingBoxNull())
os << "NULL" << std::endl;
else
{
os << indent << "( ";
for (unsigned int i=0; i<3; i++)
{
- os << m_BoundingBox->GetBounds()[2*i] << "," << m_BoundingBox->GetBounds()[2*i+1] << " ";
+ os << this->GetBoundingBox()->GetBounds()[2*i] << "," << this->GetBoundingBox()->GetBounds()[2*i+1] << " ";
}
os << " )" << std::endl;
}
- os << indent << " Origin: " << m_Origin << std::endl;
- os << indent << " ImageGeometry: " << m_ImageGeometry << std::endl;
- os << indent << " Spacing: " << m_Spacing << std::endl;
- os << indent << " TimeBounds: " << m_TimeBounds << std::endl;
-}
-
-mitk::Point3D mitk::Geometry3D::GetCornerPoint(int id) const
-{
- assert(id >= 0);
- assert(m_BoundingBox.IsNotNull());
-
- BoundingBox::BoundsArrayType bounds = m_BoundingBox->GetBounds();
-
- Point3D cornerpoint;
- switch(id)
- {
- case 0: FillVector3D(cornerpoint, bounds[0],bounds[2],bounds[4]); break;
- case 1: FillVector3D(cornerpoint, bounds[0],bounds[2],bounds[5]); break;
- case 2: FillVector3D(cornerpoint, bounds[0],bounds[3],bounds[4]); break;
- case 3: FillVector3D(cornerpoint, bounds[0],bounds[3],bounds[5]); break;
- case 4: FillVector3D(cornerpoint, bounds[1],bounds[2],bounds[4]); break;
- case 5: FillVector3D(cornerpoint, bounds[1],bounds[2],bounds[5]); break;
- case 6: FillVector3D(cornerpoint, bounds[1],bounds[3],bounds[4]); break;
- case 7: FillVector3D(cornerpoint, bounds[1],bounds[3],bounds[5]); break;
- default:
- {
- itkExceptionMacro(<<"A cube only has 8 corners. These are labeled 0-7.");
- }
- }
- if(m_ImageGeometry)
- {
- // Here i have to adjust the 0.5 offset manually, because the cornerpoint is the corner of the
- // bounding box. The bounding box itself is no image, so it is corner-based
- FillVector3D(cornerpoint, cornerpoint[0]-0.5, cornerpoint[1]-0.5, cornerpoint[2]-0.5);
- }
- return m_IndexToWorldTransform->TransformPoint(cornerpoint);
-}
-
-mitk::Point3D mitk::Geometry3D::GetCornerPoint(bool xFront, bool yFront, bool zFront) const
-{
- assert(m_BoundingBox.IsNotNull());
- BoundingBox::BoundsArrayType bounds = m_BoundingBox->GetBounds();
-
- Point3D cornerpoint;
- cornerpoint[0] = (xFront ? bounds[0] : bounds[1]);
- cornerpoint[1] = (yFront ? bounds[2] : bounds[3]);
- cornerpoint[2] = (zFront ? bounds[4] : bounds[5]);
- if(m_ImageGeometry)
- {
- // Here i have to adjust the 0.5 offset manually, because the cornerpoint is the corner of the
- // bounding box. The bounding box itself is no image, so it is corner-based
- FillVector3D(cornerpoint, cornerpoint[0]-0.5, cornerpoint[1]-0.5, cornerpoint[2]-0.5);
- }
-
- return m_IndexToWorldTransform->TransformPoint(cornerpoint);
-}
-
-void
-mitk::Geometry3D::ResetSubTransforms()
-{
+ os << indent << " Origin: " << this->GetOrigin() << std::endl;
+ os << indent << " ImageGeometry: " << this->GetImageGeometry() << std::endl;
+ os << indent << " Spacing: " << this->GetSpacing() << std::endl;
+ //os << indent << " TimeBounds: " << this->GetTimeBounds() << std::endl;
}
-void
-mitk::Geometry3D::ChangeImageGeometryConsideringOriginOffset( const bool isAnImageGeometry )
-{
- // If Geometry is switched to ImageGeometry, you have to put an offset to the origin, because
- // imageGeometries origins are pixel-center-based
- // ... and remove the offset, if you switch an imageGeometry back to a normal geometry
- // For more information please see the Geometry documentation page
-
- if(m_ImageGeometry == isAnImageGeometry)
- return;
-
- const BoundingBox::BoundsArrayType& boundsarray =
- this->GetBoundingBox()->GetBounds();
-
- Point3D originIndex;
- FillVector3D(originIndex, boundsarray[0], boundsarray[2], boundsarray[4]);
-
- if(isAnImageGeometry == true)
- FillVector3D( originIndex,
- originIndex[0] + 0.5,
- originIndex[1] + 0.5,
- originIndex[2] + 0.5 );
+void mitk::BaseGeometry::Modified() const{
+ if(!m_ModifiedLockFlag)
+ Superclass::Modified();
else
- FillVector3D( originIndex,
- originIndex[0] - 0.5,
- originIndex[1] - 0.5,
- originIndex[2] - 0.5 );
-
- Point3D originWorld;
-
- originWorld = GetIndexToWorldTransform()
- ->TransformPoint( originIndex );
- // instead could as well call IndexToWorld(originIndex,originWorld);
-
- SetOrigin(originWorld);
-
- this->SetImageGeometry(isAnImageGeometry);
-}
-
-bool mitk::Geometry3D::Is2DConvertable()
-{
- bool isConvertableWithoutLoss = true;
- do
- {
- if (this->GetSpacing()[2] != 1)
- {
- isConvertableWithoutLoss = false;
- break;
- }
- if (this->GetOrigin()[2] != 0)
- {
- isConvertableWithoutLoss = false;
- break;
- }
- mitk::Vector3D col0, col1, col2;
- col0.SetVnlVector(this->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(0));
- col1.SetVnlVector(this->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(1));
- col2.SetVnlVector(this->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(2));
-
- if ((col0[2] != 0) || (col1[2] != 0) || (col2[0] != 0) || (col2[1] != 0) || (col2[2] != 1))
- {
- isConvertableWithoutLoss = false;
- break;
- }
- } while (0);
-
- return isConvertableWithoutLoss;
+ m_ModifiedCalledFlag = true;
}
-bool mitk::Equal( const mitk::Geometry3D::BoundingBoxType *leftHandSide, const mitk::Geometry3D::BoundingBoxType *rightHandSide, ScalarType eps, bool verbose )
+bool mitk::Equal( const mitk::BaseGeometry::BoundingBoxType *leftHandSide, const mitk::BaseGeometry::BoundingBoxType *rightHandSide, ScalarType eps, bool verbose )
{
if(( leftHandSide == NULL) || ( rightHandSide == NULL ))
{
MITK_ERROR << "mitk::Equal( const mitk::Geometry3D::BoundingBoxType *leftHandSide, const mitk::Geometry3D::BoundingBoxType *rightHandSide, ScalarType eps, bool verbose ) does not with NULL pointer input.";
return false;
}
return Equal( *leftHandSide, *rightHandSide, eps, verbose);
}
-bool mitk::Equal( const mitk::Geometry3D::BoundingBoxType& leftHandSide, const mitk::Geometry3D::BoundingBoxType& rightHandSide, ScalarType eps, bool verbose )
+bool mitk::Equal( const mitk::BaseGeometry::BoundingBoxType& leftHandSide, const mitk::BaseGeometry::BoundingBoxType& rightHandSide, ScalarType eps, bool verbose )
{
bool result = true;
- Geometry3D::BoundsArrayType rightBounds = rightHandSide.GetBounds();
- Geometry3D::BoundsArrayType leftBounds = leftHandSide.GetBounds();
- Geometry3D::BoundsArrayType::Iterator itLeft = leftBounds.Begin();
- for( Geometry3D::BoundsArrayType::Iterator itRight = rightBounds.Begin(); itRight != rightBounds.End(); ++itRight)
+ BaseGeometry::BoundsArrayType rightBounds = rightHandSide.GetBounds();
+ BaseGeometry::BoundsArrayType leftBounds = leftHandSide.GetBounds();
+ BaseGeometry::BoundsArrayType::Iterator itLeft = leftBounds.Begin();
+ for( BaseGeometry::BoundsArrayType::Iterator itRight = rightBounds.Begin(); itRight != rightBounds.End(); ++itRight)
{
if(( !mitk::Equal( *itLeft, *itRight, eps )) )
{
if(verbose)
{
MITK_INFO << "[( Geometry3D::BoundingBoxType )] bounds are not equal.";
MITK_INFO << "rightHandSide is " << setprecision(12) << *itRight << " : leftHandSide is " << *itLeft << " and tolerance is " << eps;
}
result = false;
}
itLeft++;
}
return result;
}
-bool mitk::Equal(const mitk::Geometry3D *leftHandSide, const mitk::Geometry3D *rightHandSide, ScalarType eps, bool verbose)
+bool mitk::Equal(const mitk::BaseGeometry *leftHandSide, const mitk::BaseGeometry *rightHandSide, ScalarType eps, bool verbose)
{
if(( leftHandSide == NULL) || ( rightHandSide == NULL ))
{
MITK_ERROR << "mitk::Equal(const mitk::Geometry3D *leftHandSide, const mitk::Geometry3D *rightHandSide, ScalarType eps, bool verbose) does not with NULL pointer input.";
return false;
}
return Equal( *leftHandSide, *rightHandSide, eps, verbose);
}
-bool mitk::Equal(const mitk::Geometry3D& leftHandSide, const mitk::Geometry3D& rightHandSide, ScalarType eps, bool verbose)
+bool mitk::Equal(const mitk::BaseGeometry& leftHandSide, const mitk::BaseGeometry& rightHandSide, ScalarType eps, bool verbose)
{
bool result = true;
//Compare spacings
if( !mitk::Equal( leftHandSide.GetSpacing(), rightHandSide.GetSpacing(), eps ) )
{
if(verbose)
{
MITK_INFO << "[( Geometry3D )] Spacing differs.";
MITK_INFO << "rightHandSide is " << setprecision(12) << rightHandSide.GetSpacing() << " : leftHandSide is " << leftHandSide.GetSpacing() << " and tolerance is " << eps;
}
result = false;
}
//Compare Origins
if( !mitk::Equal( leftHandSide.GetOrigin(), rightHandSide.GetOrigin(), eps ) )
{
if(verbose)
{
MITK_INFO << "[( Geometry3D )] Origin differs.";
MITK_INFO << "rightHandSide is " << setprecision(12) << rightHandSide.GetOrigin() << " : leftHandSide is " << leftHandSide.GetOrigin() << " and tolerance is " << eps;
}
result = false;
}
//Compare Axis and Extents
for( unsigned int i=0; i<3; ++i)
{
if( !mitk::Equal( leftHandSide.GetAxisVector(i), rightHandSide.GetAxisVector(i), eps))
{
if(verbose)
{
MITK_INFO << "[( Geometry3D )] AxisVector #" << i << " differ";
MITK_INFO << "rightHandSide is " << setprecision(12) << rightHandSide.GetAxisVector(i) << " : leftHandSide is " << leftHandSide.GetAxisVector(i) << " and tolerance is " << eps;
}
result = false;
}
if( !mitk::Equal( leftHandSide.GetExtent(i), rightHandSide.GetExtent(i), eps) )
{
if(verbose)
{
MITK_INFO << "[( Geometry3D )] Extent #" << i << " differ";
MITK_INFO << "rightHandSide is " << setprecision(12) << rightHandSide.GetExtent(i) << " : leftHandSide is " << leftHandSide.GetExtent(i) << " and tolerance is " << eps;
}
result = false;
}
}
//Compare ImageGeometry Flag
if( rightHandSide.GetImageGeometry() != leftHandSide.GetImageGeometry() )
{
if(verbose)
{
MITK_INFO << "[( Geometry3D )] GetImageGeometry is different.";
MITK_INFO << "rightHandSide is " << rightHandSide.GetImageGeometry() << " : leftHandSide is " << leftHandSide.GetImageGeometry();
}
result = false;
}
//Compare BoundingBoxes
if( !mitk::Equal( *leftHandSide.GetBoundingBox(), *rightHandSide.GetBoundingBox(), eps, verbose) )
{
result = false;
}
//Compare IndexToWorldTransform Matrix
if( !mitk::Equal( *leftHandSide.GetIndexToWorldTransform(), *rightHandSide.GetIndexToWorldTransform(), eps, verbose) )
{
result = false;
}
return result;
}
-bool mitk::Equal(const Geometry3D::TransformType *leftHandSide, const Geometry3D::TransformType *rightHandSide, ScalarType eps, bool verbose )
+bool mitk::Equal(const BaseGeometry::TransformType *leftHandSide, const BaseGeometry::TransformType *rightHandSide, ScalarType eps, bool verbose )
{
if(( leftHandSide == NULL) || ( rightHandSide == NULL ))
{
MITK_ERROR << "mitk::Equal(const Geometry3D::TransformType *leftHandSide, const Geometry3D::TransformType *rightHandSide, ScalarType eps, bool verbose ) does not with NULL pointer input.";
return false;
}
return Equal( *leftHandSide, *rightHandSide, eps, verbose);
}
-bool mitk::Equal(const Geometry3D::TransformType& leftHandSide, const Geometry3D::TransformType& rightHandSide, ScalarType eps, bool verbose )
+bool mitk::Equal(const BaseGeometry::TransformType& leftHandSide, const BaseGeometry::TransformType& rightHandSide, ScalarType eps, bool verbose )
{
//Compare IndexToWorldTransform Matrix
if( !mitk::MatrixEqualElementWise( leftHandSide.GetMatrix(),
- rightHandSide.GetMatrix() ) )
+ rightHandSide.GetMatrix() ) )
{
if(verbose)
{
MITK_INFO << "[( Geometry3D::TransformType )] Index to World Transformation matrix differs.";
MITK_INFO << "rightHandSide is " << setprecision(12) << rightHandSide.GetMatrix() << " : leftHandSide is " << leftHandSide.GetMatrix() << " and tolerance is " << eps;
}
return false;
}
return true;
}
-
-/** Initialize the geometry */
-void
-mitk::Geometry3D::InitializeGeometry(Geometry3D* newGeometry) const
-{
- newGeometry->SetBounds(m_BoundingBox->GetBounds());
- // we have to create a new transform!!
-
- if(m_IndexToWorldTransform)
- {
- TransformType::Pointer indexToWorldTransform = TransformType::New();
- indexToWorldTransform->SetCenter( m_IndexToWorldTransform->GetCenter() );
- indexToWorldTransform->SetMatrix( m_IndexToWorldTransform->GetMatrix() );
- indexToWorldTransform->SetOffset( m_IndexToWorldTransform->GetOffset() );
- newGeometry->SetIndexToWorldTransform(indexToWorldTransform);
- }
-}
-
-/** Set the bounds */
-void mitk::Geometry3D::SetBounds(const BoundsArrayType& bounds)
-{
- m_BoundingBox = BoundingBoxType::New();
-
- BoundingBoxType::PointsContainer::Pointer pointscontainer =
- BoundingBoxType::PointsContainer::New();
- BoundingBoxType::PointType p;
- BoundingBoxType::PointIdentifier pointid;
-
- for(pointid=0; pointid<2;++pointid)
- {
- unsigned int i;
- for(i=0; i<NDimensions; ++i)
- {
- p[i] = bounds[2*i+pointid];
- }
- pointscontainer->InsertElement(pointid, p);
- }
-
- m_BoundingBox->SetPoints(pointscontainer);
- m_BoundingBox->ComputeBoundingBox();
- this->Modified();
-}
diff --git a/Core/Code/DataManagement/mitkBaseGeometry.h b/Core/Code/DataManagement/mitkBaseGeometry.h
new file mode 100644
index 0000000000..61783ff39a
--- /dev/null
+++ b/Core/Code/DataManagement/mitkBaseGeometry.h
@@ -0,0 +1,759 @@
+/*===================================================================
+
+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 BaseGeometry_H_HEADER_INCLUDED
+#define BaseGeometry_H_HEADER_INCLUDED
+
+#include <MitkCoreExports.h>
+#include <mitkCommon.h>
+#include "mitkoperationactor.h"
+
+#include <itkBoundingBox.h>
+#include "mitkvector.h"
+#include <itkAffineGeometryFrame.h>
+#include <itkQuaternionRigidTransform.h>
+#include "itkScalableAffineTransform.h"
+#include <itkIndex.h>
+
+class vtkMatrix4x4;
+class vtkMatrixToLinearTransform;
+class vtkLinearTransform;
+
+namespace mitk {
+ //##Documentation
+ //## @brief Standard 3D-BoundingBox typedef
+ //##
+ //## Standard 3D-BoundingBox typedef to get rid of template arguments (3D, type).
+ typedef itk::BoundingBox<unsigned long, 3, ScalarType> BoundingBox;
+
+ //##Documentation
+ //## @brief Standard typedef for time-bounds
+ typedef itk::FixedArray<ScalarType,2> TimeBounds;
+ typedef itk::FixedArray<ScalarType, 3> FixedArrayType;
+
+ typedef itk::AffineGeometryFrame<ScalarType, 3> AffineGeometryFrame3D;
+
+ //##Documentation
+ //## @brief BaseGeometry Describes the geometry of a data object
+ //##
+ //## The class holds
+ //## \li a bounding box which is axes-parallel in intrinsic coordinates
+ //## (often integer indices of pixels), to be accessed by
+ //## GetBoundingBox()
+ //## \li a transform to convert intrinsic coordinates into a
+ //## world-coordinate system with coordinates in millimeters
+ //## and milliseconds (all are floating point values), to
+ //## be accessed by GetIndexToWorldTransform()
+ //## \li an origin and spacing to define the geometry
+ //##
+ //## BaseGeometry and its sub-classes allow converting between
+ //## intrinsic coordinates (called index or unit coordinates)
+ //## and world-coordinates (called world or mm coordinates),
+ //## e.g. WorldToIndex.
+ //## In case you need integer index coordinates, provide an
+ //## mitk::Index3D (or itk::Index) as target variable to
+ //## WorldToIndex, otherwise you will get a continuous index
+ //## (floating point values).
+ //##
+ //## An important sub-class is SlicedGeometry3D, which descibes
+ //## data objects consisting of slices, e.g., objects of type Image.
+ //## Conversions between world coordinates (in mm) and unit coordinates
+ //## (e.g., pixels in the case of an Image) can be performed.
+ //##
+ //## For more information on related classes, see \ref Geometry.
+ //##
+ //## BaseGeometry instances referring to an Image need a slightly
+ //## different definition of corners, see SetImageGeometry. This
+ //## is usualy automatically called by Image.
+ //##
+ //## BaseGeometry have to be initialized in the method GenerateOutputInformation()
+ //## of BaseProcess (or CopyInformation/ UpdateOutputInformation of BaseData,
+ //## if possible, e.g., by analyzing pic tags in Image) subclasses. See also
+ //## itk::ProcessObject::GenerateOutputInformation(),
+ //## itk::DataObject::CopyInformation() and
+ //## itk::DataObject::UpdateOutputInformation().
+ //##
+ //## At least, it can return the bounding box of the data object.
+ //##
+ //## The BaseGeometry class is an abstract class. The most simple implementation
+ //## is the sublass Geometry3D.
+ //##
+ //## Rule: everything is in mm (ms) if not stated otherwise.
+ //## @ingroup Geometry
+ class MITK_CORE_EXPORT BaseGeometry : public itk::Object, public OperationActor
+ {
+ public:
+ mitkClassMacro(BaseGeometry, itk::Object);
+
+ // ********************************** TypeDef **********************************
+
+ typedef itk::ScalableAffineTransform<ScalarType, 3> TransformType;
+ typedef itk::BoundingBox<unsigned long, 3, ScalarType> BoundingBoxType;
+ typedef BoundingBoxType::BoundsArrayType BoundsArrayType;
+ typedef BoundingBoxType::Pointer BoundingBoxPointer;
+
+ // ********************************** Origin, Spacing **********************************
+
+ //##Documentation
+ //## @brief Get the origin, e.g. the upper-left corner of the plane
+ const Point3D& GetOrigin() const;
+
+ //##Documentation
+ //## @brief Set the origin, i.e. the upper-left corner of the plane
+ //##
+ void SetOrigin(const Point3D& origin);
+
+ //##Documentation
+ //## @brief Get the spacing (size of a pixel).
+ //##
+ itkGetConstReferenceMacro(Spacing, mitk::Vector3D);
+
+ //##Documentation
+ //## @brief Set the spacing (m_Spacing).
+ //##
+ //##The spacing is also changed in the IndexToWorldTransform.
+ void SetSpacing(const mitk::Vector3D& aSpacing, bool enforceSetSpacing = false);
+
+ //##Documentation
+ //## @brief Get the origin as VnlVector
+ //##
+ //## \sa GetOrigin
+ VnlVector GetOriginVnl() const;
+
+ // ********************************** other functions **********************************
+
+ //##Documentation
+ //## @brief Get the DICOM FrameOfReferenceID referring to the
+ //## used world coordinate system
+ itkGetConstMacro(FrameOfReferenceID, unsigned int);
+ //##Documentation
+ //## @brief Set the DICOM FrameOfReferenceID referring to the
+ //## used world coordinate system
+ itkSetMacro(FrameOfReferenceID, unsigned int);
+
+ itkGetConstMacro(IndexToWorldTransformLastModified, unsigned long);
+
+ //##Documentation
+ //## @brief Overload of function Modified() to prohibit several calls of Modified() using the ModifiedLock class.
+ //##
+ //## For the use of Modified(), see class ModifiedLock.
+ void Modified() const;
+
+ friend class ModifiedLock;
+
+ //##Documentation
+ //## @brief Is this BaseGeometry in a state that is valid?
+ //##
+ //## This function returns always true in the BaseGeometry class. Other implementations are possible in subclasses.
+ virtual bool IsValid() const;
+
+ // ********************************** Initialize **********************************
+
+ //##Documentation
+ //## @brief Initialize the BaseGeometry
+ void Initialize();
+
+ void InitializeGeometry(Self * newGeometry) const;
+
+ // ********************************** Transformations Set/Get **********************************
+
+ // a bit of a misuse, but we want only doxygen to see the following:
+#ifdef DOXYGEN_SKIP
+ //##Documentation
+ //## @brief Get the transformation used to convert from index
+ //## to world coordinates
+ itkGetObjectMacro(IndexToWorldTransform, AffineTransform3D);
+#endif
+ //## @brief Set the transformation used to convert from index
+ //## to world coordinates. The spacing of the new transform is
+ //## copied to m_spacing.
+ void SetIndexToWorldTransform(mitk::AffineTransform3D* transform);
+
+ //##Documentation
+ //## @brief Convenience method for setting the ITK transform
+ //## (m_IndexToWorldTransform) via an vtkMatrix4x4.The spacing of
+ //## the new transform is copied to m_spacing.
+ //## \sa SetIndexToWorldTransform
+ virtual void SetIndexToWorldTransformByVtkMatrix(vtkMatrix4x4* vtkmatrix);
+
+ //## Get the IndexToWorldTransform
+ itkGetConstObjectMacro(IndexToWorldTransform, AffineTransform3D);
+ itkGetObjectMacro(IndexToWorldTransform, AffineTransform3D);
+
+ //## Get the Vtk Matrix which describes the transform.
+ vtkMatrix4x4* GetVtkMatrix();
+
+ //##Documentation
+ //## @brief Get the m_IndexToWorldTransform as a vtkLinearTransform
+ vtkLinearTransform* GetVtkTransform() const;
+
+ //##Documentation
+ //## @brief Set the transform to identity, the spacing to 1 and origin to 0
+ //##
+ virtual void SetIdentity();
+
+ // ********************************** Transformations **********************************
+
+ //##Documentation
+ //## @brief Compose new IndexToWorldTransform with a given transform.
+ //##
+ //## This method composes m_IndexToWorldTransform with another transform,
+ //## modifying self to be the composition of self and other.
+ //## If the argument pre is true, then other is precomposed with self;
+ //## that is, the resulting transformation consists of first applying
+ //## other to the source, followed by self. If pre is false or omitted,
+ //## then other is post-composed with self; that is the resulting
+ //## transformation consists of first applying self to the source,
+ //## followed by other.
+ //## This method also changes m_spacing.
+ void Compose( const BaseGeometry::TransformType * other, bool pre = 0 );
+
+ //##Documentation
+ //## @brief Compose new IndexToWorldTransform with a given vtkMatrix4x4.
+ //##
+ //## Converts the vtkMatrix4x4 into a itk-transform and calls the previous method.
+ void Compose( const vtkMatrix4x4 * vtkmatrix, bool pre = 0 );
+
+ //##Documentation
+ //## @brief Translate the origin by a vector
+ //##
+ void Translate(const Vector3D& vector);
+
+ //##Documentation
+ //##@brief executes affine operations (translate, rotate, scale)
+ virtual void ExecuteOperation(Operation* operation);
+
+ //##Documentation
+ //## @brief Convert world coordinates (in mm) of a \em point to (continuous!) index coordinates
+ //## \warning If you need (discrete) integer index coordinates (e.g., for iterating easily over an image),
+ //## use WorldToIndex(const mitk::Point3D& pt_mm, itk::Index<VIndexDimension> &index).
+ //## For further information about coordinates types, please see the Geometry documentation
+ void WorldToIndex(const mitk::Point3D& pt_mm, mitk::Point3D& pt_units) const;
+
+ //##Documentation
+ //## @brief Convert world coordinates (in mm) of a \em vector
+ //## \a vec_mm to (continuous!) index coordinates.
+ //## For further information about coordinates types, please see the Geometry documentation
+ void WorldToIndex(const mitk::Vector3D& vec_mm, mitk::Vector3D& vec_units) const;
+
+ //##Documentation
+ //## @brief Convert world coordinates (in mm) of a \em point to (discrete!) index coordinates.
+ //## This method rounds to integer indices!
+ //## For further information about coordinates types, please see the Geometry documentation
+ template <unsigned int VIndexDimension>
+ void WorldToIndex(const mitk::Point3D& pt_mm, itk::Index<VIndexDimension> &index) const
+ {
+ typedef itk::Index<VIndexDimension> IndexType;
+ mitk::Point3D pt_units;
+ this->WorldToIndex(pt_mm, pt_units);
+ int i, dim=index.GetIndexDimension();
+ if(dim>3)
+ {
+ index.Fill(0);
+ dim=3;
+ }
+ for(i=0;i<dim;++i){
+ index[i]=itk::Math::RoundHalfIntegerUp<typename IndexType::IndexValueType>( pt_units[i] );
+ }
+ }
+
+ //##Documentation
+ //## @brief Convert (continuous or discrete) index coordinates of a \em vector
+ //## \a vec_units to world coordinates (in mm)
+ //## For further information about coordinates types, please see the Geometry documentation
+ void IndexToWorld(const mitk::Vector3D& vec_units, mitk::Vector3D& vec_mm) const;
+
+ //##Documentation
+ //## @brief Convert (continuous or discrete) index coordinates of a \em point to world coordinates (in mm)
+ //## For further information about coordinates types, please see the Geometry documentation
+ void IndexToWorld(const mitk::Point3D& pt_units, mitk::Point3D& pt_mm) const;
+
+ //##Documentation
+ //## @brief Convert (discrete) index coordinates of a \em point to world coordinates (in mm)
+ //## For further information about coordinates types, please see the Geometry documentation
+ template <unsigned int VIndexDimension>
+ void IndexToWorld(const itk::Index<VIndexDimension> &index, mitk::Point3D& pt_mm ) const
+ {
+ mitk::Point3D pt_units;
+ pt_units.Fill(0);
+ int i, dim=index.GetIndexDimension();
+ if(dim>3)
+ {
+ dim=3;
+ }
+ for(i=0;i<dim;++i)
+ {
+ pt_units[i] = index[i];
+ }
+
+ IndexToWorld(pt_units,pt_mm);
+ }
+
+ //##Documentation
+ //## @brief Convert (continuous or discrete) index coordinates of a \em vector
+ //## \a vec_units to world coordinates (in mm)
+ //## @deprecated First parameter (Point3D) is not used. If possible, please use void IndexToWorld(const mitk::Vector3D& vec_units, mitk::Vector3D& vec_mm) const.
+ //## For further information about coordinates types, please see the Geometry documentation
+ void IndexToWorld(const mitk::Point3D& atPt3d_units, const mitk::Vector3D& vec_units, mitk::Vector3D& vec_mm) const;
+
+ //##Documentation
+ //## @brief Convert world coordinates (in mm) of a \em vector
+ //## \a vec_mm to (continuous!) index coordinates.
+ //## @deprecated First parameter (Point3D) is not used. If possible, please use void WorldToIndex(const mitk::Vector3D& vec_mm, mitk::Vector3D& vec_units) const.
+ //## For further information about coordinates types, please see the Geometry documentation
+ void WorldToIndex(const mitk::Point3D& atPt3d_mm, const mitk::Vector3D& vec_mm, mitk::Vector3D& vec_units) const;
+
+ //##Documentation
+ //## @brief Deprecated for use with ITK version 3.10 or newer.
+ //## Convert ITK physical coordinates of a \em point (in mm,
+ //## but without a rotation) into MITK world coordinates (in mm)
+ //##
+ //## For more information, see WorldToItkPhysicalPoint.
+ template<class TCoordRep>
+ void ItkPhysicalPointToWorld(const itk::Point<TCoordRep, 3>& itkPhysicalPoint,
+ mitk::Point3D& pt_mm) const
+ {
+ mitk::vtk2itk(itkPhysicalPoint, pt_mm);
+ }
+
+ //##Documentation
+ //## @brief Deprecated for use with ITK version 3.10 or newer.
+ //## Convert world coordinates (in mm) of a \em point to
+ //## ITK physical coordinates (in mm, but without a possible rotation)
+ //##
+ //## This method is useful if you have want to access an mitk::Image
+ //## via an itk::Image. ITK v3.8 and older did not support rotated (tilted)
+ //## images, i.e., ITK images are always parallel to the coordinate axes.
+ //## When accessing a (possibly rotated) mitk::Image via an itk::Image
+ //## the rotational part of the transformation in the BaseGeometry is
+ //## simply discarded; in other word: only the origin and spacing is
+ //## used by ITK, not the complete matrix available in MITK.
+ //## With WorldToItkPhysicalPoint you can convert an MITK world
+ //## coordinate (including the rotation) into a coordinate that
+ //## can be used with the ITK image as a ITK physical coordinate
+ //## (excluding the rotation).
+ template<class TCoordRep>
+ void WorldToItkPhysicalPoint(const mitk::Point3D& pt_mm,
+ itk::Point<TCoordRep, 3>& itkPhysicalPoint) const
+ {
+ mitk::vtk2itk(pt_mm, itkPhysicalPoint);
+ }
+
+ // ********************************** BoundingBox **********************************
+
+ /** Get the bounding box */
+ itkGetConstObjectMacro(BoundingBox, BoundingBoxType);
+
+ //##Documentation
+ //## @brief Get the time bounds (in ms)
+ //itkGetConstReferenceMacro(TimeBounds, TimeBounds);
+
+ // a bit of a misuse, but we want only doxygen to see the following:
+#ifdef DOXYGEN_SKIP
+ //##Documentation
+ //## @brief Get bounding box (in index/unit coordinates)
+ itkGetConstObjectMacro(BoundingBox, BoundingBoxType);
+ //##Documentation
+ //## @brief Get bounding box (in index/unit coordinates) as a BoundsArrayType
+ const BoundsArrayType GetBounds() const;
+#endif
+ const BoundsArrayType GetBounds() const;
+
+ //##Documentation
+ //## \brief Set the bounding box (in index/unit coordinates)
+ //##
+ //## Only possible via the BoundsArray to make clear that a
+ //## copy of the bounding-box is stored, not a reference to it.
+ void SetBounds(const BoundsArrayType& bounds);
+
+ //##Documentation
+ //## @brief Set the bounding box (in index/unit coordinates) via a float array
+ void SetFloatBounds(const float bounds[6]);
+ //##Documentation
+ //## @brief Set the bounding box (in index/unit coordinates) via a double array
+ void SetFloatBounds(const double bounds[6]);
+
+ //##Documentation
+ //## @brief Get a VnlVector along bounding-box in the specified
+ //## @a direction, length is spacing
+ //##
+ //## \sa GetAxisVector
+ VnlVector GetMatrixColumn(unsigned int direction) const;
+
+ //##Documentation
+ //## @brief Calculates a bounding-box around the geometry relative
+ //## to a coordinate system defined by a transform
+ //##
+ mitk::BoundingBox::Pointer CalculateBoundingBoxRelativeToTransform(const mitk::AffineTransform3D* transform) const;
+
+ //##Documentation
+ //## @brief Set the time bounds (in ms)
+ //void SetTimeBounds(const TimeBounds& timebounds);
+
+ // ********************************** Geometry **********************************
+
+#ifdef DOXYGEN_SKIP
+ //##Documentation
+ //## @brief Get the extent of the bounding box (in index/unit coordinates)
+ //##
+ //## To access the extent in mm use GetExtentInMM
+ ScalarType GetExtent(unsigned int direction) const;
+#endif
+
+ /** Get the extent of the bounding box */
+ ScalarType GetExtent(unsigned int direction) const;
+
+ //##Documentation
+ //## @brief Get the extent of the bounding-box in the specified @a direction in mm
+ //##
+ //## Equals length of GetAxisVector(direction).
+ ScalarType GetExtentInMM(int direction) const;
+
+ //##Documentation
+ //## @brief Get vector along bounding-box in the specified @a direction in mm
+ //##
+ //## The length of the vector is the size of the bounding-box in the
+ //## specified @a direction in mm
+ //## \sa GetMatrixColumn
+ Vector3D GetAxisVector(unsigned int direction) const;
+
+ //##Documentation
+ //## @brief Checks, if the given geometry can be converted to 2D without information loss
+ //## e.g. when a 2D image is saved, the matrix is usually cropped to 2x2, and when you load it back to MITK
+ //## it will be filled with standard values. This function checks, if information would be lost during this
+ //## procedure
+ virtual bool Is2DConvertable();
+
+ //##Documentation
+ //## @brief Get the center of the bounding-box in mm
+ //##
+ Point3D GetCenter() const;
+
+ //##Documentation
+ //## @brief Get the squared length of the diagonal of the bounding-box in mm
+ //##
+ double GetDiagonalLength2() const;
+
+ //##Documentation
+ //## @brief Get the length of the diagonal of the bounding-box in mm
+ //##
+ double GetDiagonalLength() const;
+
+ //##Documentation
+ //## @brief Get the position of the corner number \a id (in world coordinates)
+ //##
+ //## See SetImageGeometry for how a corner is defined on images.
+ Point3D GetCornerPoint(int id) const;
+
+ //##Documentation
+ //## @brief Get the position of a corner (in world coordinates)
+ //##
+ //## See SetImageGeometry for how a corner is defined on images.
+ Point3D GetCornerPoint(bool xFront=true, bool yFront=true, bool zFront=true) const;
+
+ //##Documentation
+ //## @brief Set the extent of the bounding-box in the specified @a direction in mm
+ //##
+ //## @note This changes the matrix in the transform, @a not the bounds, which are given in units!
+ void SetExtentInMM(int direction, ScalarType extentInMM);
+
+ //##Documentation
+ //## @brief Test whether the point \a p (world coordinates in mm) is
+ //## inside the bounding box
+ bool IsInside(const mitk::Point3D& p) const;
+
+ //##Documentation
+ //## @brief Test whether the point \a p ((continous!)index coordinates in units) is
+ //## inside the bounding box
+ bool IsIndexInside(const mitk::Point3D& index) const;
+
+ //##Documentation
+ //## @brief Convenience method for working with ITK indices
+ template <unsigned int VIndexDimension>
+ bool IsIndexInside(const itk::Index<VIndexDimension> &index) const
+ {
+ int i, dim=index.GetIndexDimension();
+ Point3D pt_index;
+ pt_index.Fill(0);
+ for ( i = 0; i < dim; ++i )
+ {
+ pt_index[i] = index[i];
+ }
+ return IsIndexInside(pt_index);
+ }
+
+ // ********************************* Image Geometry ********************************
+ //##Documentation
+ //## @brief When switching from an Image Geometry to a normal Geometry (and the other way around), you have to change the origin as well (See Geometry Documentation)! This function will change the "isImageGeometry" bool flag and changes the origin respectively.
+ virtual void ChangeImageGeometryConsideringOriginOffset( const bool isAnImageGeometry );
+
+ //##Documentation
+ //## @brief Is this an ImageGeometry?
+ //##
+ //## For more information, see SetImageGeometry
+ itkGetConstMacro(ImageGeometry, bool);
+ //##Documentation
+ //## @brief Define that this BaseGeometry is refering to an Image
+ //##
+ //## A geometry referring to an Image needs a slightly different
+ //## definition of the position of the corners (see GetCornerPoint).
+ //## The position of a voxel is defined by the position of its center.
+ //## If we would use the origin (position of the (center of) the first
+ //## voxel) as a corner and display this point, it would seem to be
+ //## \em not at the corner but a bit within the image. Even worse for
+ //## the opposite corner of the image: here the corner would appear
+ //## outside the image (by half of the voxel diameter). Thus, we have
+ //## to correct for this and to be able to do that, we need to know
+ //## that the BaseGeometry is referring to an Image.
+ itkSetMacro(ImageGeometry, bool);
+ itkBooleanMacro(ImageGeometry);
+
+ protected:
+
+ // ********************************** Constructor **********************************
+ BaseGeometry();
+ BaseGeometry(const BaseGeometry& other);
+ virtual ~BaseGeometry();
+
+ //##Documentation
+ //## @brief clones the geometry
+ //##
+ //## Overwrite in all sub-classes.
+ //## Normally looks like:
+ //## \code
+ //## Self::Pointer newGeometry = new Self(*this);
+ //## newGeometry->UnRegister();
+ //## return newGeometry.GetPointer();
+ //## \endcode
+ virtual itk::LightObject::Pointer InternalClone() const =0;
+
+ virtual void PrintSelf(std::ostream& os, itk::Indent indent) const;
+
+ void BackTransform(const mitk::Point3D& in, mitk::Point3D& out) const;
+
+ //Without redundant parameter Point3D
+ void BackTransform(const mitk::Vector3D& in, mitk::Vector3D& out) const;
+
+ //##Documentation
+ //## @brief Deprecated
+ void BackTransform(const mitk::Point3D& at, const mitk::Vector3D& in, mitk::Vector3D& out) const;
+
+ //##Documentation
+ //## @brief Copy the ITK transform
+ //## (m_IndexToWorldTransform) to the VTK transform
+ //## \sa SetIndexToWorldTransform
+ void TransferItkToVtkTransform();
+
+ //##Documentation
+ //## @brief Copy the VTK transform
+ //## to the ITK transform (m_IndexToWorldTransform)
+ //## \sa SetIndexToWorldTransform
+ void TransferVtkToItkTransform();
+
+ static const std::string GetTransformAsString( TransformType* transformType );
+
+ itkGetConstMacro(NDimensions, unsigned int);
+
+ bool IsBoundingBoxNull() const;
+
+ bool IsIndexToWorldTransformNull() const;
+
+ //##Documentation
+ //## @brief Intern functions to assure a consistent behaviour of SetSpacing.
+ void _SetSpacing(const mitk::Vector3D& aSpacing, bool enforceSetSpacing = false);
+
+ private:
+ //##Documentation
+ //## @brief Pre- and Post-functions are empty in BaseGeometry
+ //##
+ //## These virtual functions allow for a different beahiour in subclasses.
+ virtual void PreSetBounds(const BoundsArrayType& bounds);
+
+ virtual void PostInitialize();
+ virtual void PostInitializeGeometry(Self * newGeometry) const;
+
+ virtual void PostSetExtentInMM(int direction, ScalarType extentInMM);
+
+ //virtual void PostSetTimeBounds(const TimeBounds& timebounds);
+
+ virtual void PreSetIndexToWorldTransform(mitk::AffineTransform3D* transform);
+ virtual void PostSetIndexToWorldTransform(mitk::AffineTransform3D* transform);
+
+ virtual void PreSetSpacing(const mitk::Vector3D& aSpacing);
+
+ // ********************************** Variables **********************************
+ //##Documentation
+ //## @brief Spacing, measurement of the resolution
+ //##
+ mitk::Vector3D m_Spacing;
+
+ //##Documentation
+ //## @brief Index to World Transform, contains a transformation matrix to convert
+ //## points from indes coordinates to world coordinates (mm). The Spacing is included in this variable.
+ AffineTransform3D::Pointer m_IndexToWorldTransform;
+
+ //##Documentation
+ //## @brief Bounding Box, which is axes-parallel in intrinsic coordinates
+ //## (often integer indices of pixels)
+ BoundingBoxPointer m_BoundingBox;
+
+ vtkMatrixToLinearTransform* m_VtkIndexToWorldTransform;
+
+ vtkMatrix4x4* m_VtkMatrix;
+
+ unsigned int m_FrameOfReferenceID;
+
+ //mitk::TimeBounds m_TimeBounds;
+
+ //##Documentation
+ //## @brief Origin, i.e. upper-left corner of the plane
+ //##
+ Point3D m_Origin;
+
+ static const unsigned int m_NDimensions = 3;
+
+ mutable TransformType::Pointer m_InvertedTransform;
+
+ mutable unsigned long m_IndexToWorldTransformLastModified;
+
+ bool m_ImageGeometry;
+
+ //##Documentation
+ //## @brief ModifiedLockFlag is used to prohibit the call of Modified()
+ //##
+ //## For the use of this Flag, see class ModifiedLock. This flag should only be set
+ //## by the ModifiedLock class!
+ bool m_ModifiedLockFlag;
+
+ //##Documentation
+ //## @brief ModifiedcalledFlag is used to collect calls of Modified().
+ //##
+ //## For the use of this Flag, see class ModifiedLock. This flag should only be set
+ //## by the Modified() function!
+ mutable bool m_ModifiedCalledFlag;
+ };
+
+ // ********************************** Equal Functions **********************************
+ //
+ // Static compare functions mainly for testing
+ //
+ /**
+ * @brief Equal A function comparing two geometries for beeing identical.
+ * @warning This method is deprecated and will not be available in the future. Use the \a bool mitk::Equal(const mitk::mitk::BaseGeometry& g1, const mitk::BaseGeometry& g2) instead.
+ *
+ * @ingroup MITKTestingAPI
+ *
+ * The function compares the spacing, origin, axisvectors, extents, the matrix of the
+ * IndexToWorldTransform (elementwise), the bounding (elementwise) and the ImageGeometry flag.
+ *
+ * The parameter eps is a tolarence value for all methods which are internally used for comparion.
+ * If you want to use different tolarance values for different parts of the geometry, feel free to use
+ * the other comparison methods and write your own implementation of Equal.
+ * @param rightHandSide Compare this against leftHandSide.
+ * @param leftHandSide Compare this against rightHandSide.
+ * @param eps Tolarence for comparison. You can use mitk::eps in most cases.
+ * @param verbose Flag indicating if the user wants detailed console output or not.
+ * @return True, if all comparison are true. False in any other case.
+ */
+ DEPRECATED( MITK_CORE_EXPORT bool Equal(const mitk::BaseGeometry* leftHandSide, const mitk::BaseGeometry* rightHandSide, ScalarType eps, bool verbose));
+
+ /**
+ * @brief Equal A function comparing two geometries for beeing identical.
+ *
+ * @ingroup MITKTestingAPI
+ *
+ * The function compares the spacing, origin, axisvectors, extents, the matrix of the
+ * IndexToWorldTransform (elementwise), the bounding (elementwise) and the ImageGeometry flag.
+ *
+ * The parameter eps is a tolarence value for all methods which are internally used for comparion.
+ * If you want to use different tolarance values for different parts of the geometry, feel free to use
+ * the other comparison methods and write your own implementation of Equal.
+ * @param rightHandSide Compare this against leftHandSide.
+ * @param leftHandSide Compare this against rightHandSide.
+ * @param eps Tolarence for comparison. You can use mitk::eps in most cases.
+ * @param verbose Flag indicating if the user wants detailed console output or not.
+ * @return True, if all comparison are true. False in any other case.
+ */
+ MITK_CORE_EXPORT bool Equal(const mitk::BaseGeometry& leftHandSide, const mitk::BaseGeometry& rightHandSide, ScalarType eps, bool verbose);
+
+ /**
+ * @brief Equal A function comparing two transforms (TransformType) for beeing identical.
+ * @warning This method is deprecated and will not be available in the future. Use the \a bool mitk::Equal(const mitk::mitk::BaseGeometry::TransformType& t1, const mitk::BaseGeometry::TransformType& t2) instead.
+ *
+ * @ingroup MITKTestingAPI
+ *
+ * The function compares the IndexToWorldTransform (elementwise).
+ *
+ * The parameter eps is a tolarence value for all methods which are internally used for comparion.
+ * @param rightHandSide Compare this against leftHandSide.
+ * @param leftHandSide Compare this against rightHandSide.
+ * @param eps Tolarence for comparison. You can use mitk::eps in most cases.
+ * @param verbose Flag indicating if the user wants detailed console output or not.
+ * @return True, if all comparison are true. False in any other case.
+ */
+ DEPRECATED( MITK_CORE_EXPORT bool Equal(const mitk::BaseGeometry::TransformType *leftHandSide, const mitk::BaseGeometry::TransformType *rightHandSide, ScalarType eps, bool verbose));
+
+ /**
+ * @brief Equal A function comparing two transforms (TransformType) for beeing identical.
+ *
+ * @ingroup MITKTestingAPI
+ *
+ * The function compares the IndexToWorldTransform (elementwise).
+ *
+ * The parameter eps is a tolarence value for all methods which are internally used for comparion.
+ * @param rightHandSide Compare this against leftHandSide.
+ * @param leftHandSide Compare this against rightHandSide.
+ * @param eps Tolarence for comparison. You can use mitk::eps in most cases.
+ * @param verbose Flag indicating if the user wants detailed console output or not.
+ * @return True, if all comparison are true. False in any other case.
+ */
+ MITK_CORE_EXPORT bool Equal(const mitk::BaseGeometry::TransformType& leftHandSide, const mitk::BaseGeometry::TransformType& rightHandSide, ScalarType eps, bool verbose);
+
+ /**
+ * @brief Equal A function comparing two bounding boxes (BoundingBoxType) for beeing identical.
+ * @warning This method is deprecated and will not be available in the future. Use the \a bool mitk::Equal(const mitk::mitk::BaseGeometry::BoundingBoxType& b1, const mitk::BaseGeometry::BoundingBoxType& b2) instead.
+ *
+ * @ingroup MITKTestingAPI
+ *
+ * The function compares the bounds (elementwise).
+ *
+ * The parameter eps is a tolarence value for all methods which are internally used for comparion.
+ * @param rightHandSide Compare this against leftHandSide.
+ * @param leftHandSide Compare this against rightHandSide.
+ * @param eps Tolarence for comparison. You can use mitk::eps in most cases.
+ * @param verbose Flag indicating if the user wants detailed console output or not.
+ * @return True, if all comparison are true. False in any other case.
+ */
+ DEPRECATED( MITK_CORE_EXPORT bool Equal( const mitk::BaseGeometry::BoundingBoxType *leftHandSide, const mitk::BaseGeometry::BoundingBoxType *rightHandSide, ScalarType eps, bool verbose));
+
+ /**
+ * @brief Equal A function comparing two bounding boxes (BoundingBoxType) for beeing identical.
+ *
+ * @ingroup MITKTestingAPI
+ *
+ * The function compares the bounds (elementwise).
+ *
+ * The parameter eps is a tolarence value for all methods which are internally used for comparion.
+ * @param rightHandSide Compare this against leftHandSide.
+ * @param leftHandSide Compare this against rightHandSide.
+ * @param eps Tolarence for comparison. You can use mitk::eps in most cases.
+ * @param verbose Flag indicating if the user wants detailed console output or not.
+ * @return True, if all comparison are true. False in any other case.
+ */
+ MITK_CORE_EXPORT bool Equal( const mitk::BaseGeometry::BoundingBoxType& leftHandSide, const mitk::BaseGeometry::BoundingBoxType& rightHandSide, ScalarType eps, bool verbose);
+} // namespace mitk
+
+#endif /* BaseGeometry_H_HEADER_INCLUDED */
diff --git a/Core/Code/DataManagement/mitkDataNode.cpp b/Core/Code/DataManagement/mitkDataNode.cpp
index bce35ab0c0..23ea6a7b13 100644
--- a/Core/Code/DataManagement/mitkDataNode.cpp
+++ b/Core/Code/DataManagement/mitkDataNode.cpp
@@ -1,579 +1,579 @@
/*===================================================================
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 "mitkDataNode.h"
#include "mitkCoreObjectFactory.h"
#include <vtkTransform.h>
#include "mitkProperties.h"
#include "mitkStringProperty.h"
#include "mitkGroupTagProperty.h"
#include "mitkSmartPointerProperty.h"
//#include "mitkMaterialProperty.h"
#include "mitkColorProperty.h"
#include "mitkLevelWindowProperty.h"
#include "mitkGeometry3D.h"
#include "mitkRenderingManager.h"
#include "mitkGlobalInteraction.h"
#include "mitkEventMapper.h"
#include "mitkGenericProperty.h"
#include "mitkImageSource.h"
#include "mitkCoreObjectFactory.h"
mitk::Mapper* mitk::DataNode::GetMapper(MapperSlotId id) const
{
if( (id >= m_Mappers.size()) || (m_Mappers[id].IsNull()) )
{
if(id >= m_Mappers.capacity())
{
// int i, size=id-m_Mappers.capacity()+10;
m_Mappers.resize(id+10);
}
m_Mappers[id] = CoreObjectFactory::GetInstance()->CreateMapper(const_cast<DataNode*>(this),id);
}
return m_Mappers[id];
}
mitk::BaseData* mitk::DataNode::GetData() const
{
return m_Data;
}
mitk::Interactor* mitk::DataNode::GetInteractor() const
{
return m_Interactor;
}
void mitk::DataNode::SetData(mitk::BaseData* baseData)
{
if(m_Data!=baseData)
{
m_Data=baseData;
m_Mappers.clear();
m_Mappers.resize(10);
mitk::CoreObjectFactory::GetInstance()->SetDefaultProperties(this);
m_DataReferenceChangedTime.Modified();
Modified();
//inform the interactor about the change
if (m_Interactor.IsNotNull())
m_Interactor->DataChanged();
}
}
void mitk::DataNode::SetInteractor(mitk::Interactor* interactor)
{
m_Interactor = interactor;
if(m_Interactor.IsNotNull())
m_Interactor->SetDataNode(this);
}
mitk::DataNode::DataNode() : m_Data(NULL), m_PropertyListModifiedObserverTag(0)
{
m_Mappers.resize(10);
m_PropertyList = PropertyList::New();
// subscribe for modified event
itk::MemberCommand<mitk::DataNode>::Pointer _PropertyListModifiedCommand =
itk::MemberCommand<mitk::DataNode>::New();
_PropertyListModifiedCommand->SetCallbackFunction(this, &mitk::DataNode::PropertyListModified);
m_PropertyListModifiedObserverTag = m_PropertyList->AddObserver(itk::ModifiedEvent(), _PropertyListModifiedCommand);
}
mitk::DataNode::~DataNode()
{
if(m_PropertyList.IsNotNull())
// remove modified event listener
m_PropertyList->RemoveObserver(m_PropertyListModifiedObserverTag);
Interactor* interactor = this->GetInteractor();
if ( interactor )
{
mitk::GlobalInteraction::GetInstance()->RemoveInteractor( interactor );
}
m_Mappers.clear();
m_Data = NULL;
}
mitk::DataNode& mitk::DataNode::operator=(const DataNode& right)
{
mitk::DataNode* node=mitk::DataNode::New();
node->SetData(right.GetData());
return *node;
}
mitk::DataNode& mitk::DataNode::operator=(mitk::BaseData* right)
{
mitk::DataNode* node=mitk::DataNode::New();
node->SetData(right);
return *node;
}
#if (_MSC_VER > 1200) || !defined(_MSC_VER)
MBI_STD::istream& mitk::operator>>( MBI_STD::istream& i, mitk::DataNode::Pointer& dtn )
#endif
#if ((defined(_MSC_VER)) && (_MSC_VER <= 1200))
MBI_STD::istream& operator>>( MBI_STD::istream& i, mitk::DataNode::Pointer& dtn )
#endif
{
dtn = mitk::DataNode::New();
//i >> av.get();
return i;
}
#if (_MSC_VER > 1200) || !defined(_MSC_VER)
MBI_STD::ostream& mitk::operator<<( MBI_STD::ostream& o, mitk::DataNode::Pointer& dtn)
#endif
#if ((defined(_MSC_VER)) && (_MSC_VER <= 1200))
MBI_STD::ostream& operator<<( MBI_STD::ostream& o, mitk::DataNode::Pointer& dtn)
#endif
{
if(dtn->GetData()!=NULL)
o<<dtn->GetData()->GetNameOfClass();
else
o<<"empty data";
return o;
}
void mitk::DataNode::SetMapper(MapperSlotId id, mitk::Mapper* mapper)
{
m_Mappers[id] = mapper;
if (mapper!=NULL)
mapper->SetDataNode(this);
}
void mitk::DataNode::UpdateOutputInformation()
{
if (this->GetSource())
{
this->GetSource()->UpdateOutputInformation();
}
}
void mitk::DataNode::SetRequestedRegionToLargestPossibleRegion()
{
}
bool mitk::DataNode::RequestedRegionIsOutsideOfTheBufferedRegion()
{
return false;
}
bool mitk::DataNode::VerifyRequestedRegion()
{
return true;
}
void mitk::DataNode::SetRequestedRegion( const itk::DataObject * /*data*/)
{
}
void mitk::DataNode::CopyInformation(const itk::DataObject * /*data*/)
{
}
mitk::PropertyList* mitk::DataNode::GetPropertyList(const mitk::BaseRenderer* renderer) const
{
if(renderer==NULL)
return m_PropertyList;
return this->GetPropertyList(renderer->GetName());
}
mitk::PropertyList* mitk::DataNode::GetPropertyList(const std::string& rendererName) const
{
if (rendererName.empty())
return m_PropertyList;
mitk::PropertyList::Pointer & propertyList = m_MapOfPropertyLists[rendererName];
if(propertyList.IsNull())
propertyList = mitk::PropertyList::New();
assert(m_MapOfPropertyLists[rendererName].IsNotNull());
return propertyList;
}
void mitk::DataNode::ConcatenatePropertyList(PropertyList *pList, bool replace)
{
m_PropertyList->ConcatenatePropertyList(pList, replace);
}
mitk::BaseProperty* mitk::DataNode::GetProperty(const char *propertyKey, const mitk::BaseRenderer* renderer) const
{
if(propertyKey==NULL)
return NULL;
//renderer specified?
if (renderer)
{
std::string rendererName = renderer->GetName();
MapOfPropertyLists::const_iterator it;
//check for the renderer specific property
it=m_MapOfPropertyLists.find(rendererName);
if(it!=m_MapOfPropertyLists.end()) //found
{
mitk::BaseProperty::Pointer property;
property=it->second->GetProperty(propertyKey);
if(property.IsNotNull())//found an enabled property in the render specific list
return property;
else //found a renderer specific list, but not the desired property
return m_PropertyList->GetProperty(propertyKey); //return renderer unspecific property
}
else //didn't find the property list of the given renderer
{
//return the renderer unspecific property if there is one
return m_PropertyList->GetProperty(propertyKey);
}
}
else //no specific renderer given; use the renderer independent one
{
mitk::BaseProperty::Pointer property;
property=m_PropertyList->GetProperty(propertyKey);
if(property.IsNotNull())
return property;
}
//only to satisfy compiler!
return NULL;
}
mitk::DataNode::GroupTagList mitk::DataNode::GetGroupTags() const
{
GroupTagList groups;
const PropertyList::PropertyMap* propertyMap = m_PropertyList->GetMap();
for ( PropertyList::PropertyMap::const_iterator groupIter = propertyMap->begin(); // m_PropertyList is created in the constructor, so we don't check it here
groupIter != propertyMap->end();
++groupIter )
{
const BaseProperty* bp = groupIter->second;
if ( dynamic_cast<const GroupTagProperty*>(bp) )
{
groups.insert( groupIter->first );
}
}
return groups;
}
bool mitk::DataNode::GetBoolProperty(const char* propertyKey, bool& boolValue, mitk::BaseRenderer* renderer) const
{
mitk::BoolProperty::Pointer boolprop = dynamic_cast<mitk::BoolProperty*>(GetProperty(propertyKey, renderer));
if(boolprop.IsNull())
return false;
boolValue = boolprop->GetValue();
return true;
}
bool mitk::DataNode::GetIntProperty(const char* propertyKey, int &intValue, mitk::BaseRenderer* renderer) const
{
mitk::IntProperty::Pointer intprop = dynamic_cast<mitk::IntProperty*>(GetProperty(propertyKey, renderer));
if(intprop.IsNull())
return false;
intValue = intprop->GetValue();
return true;
}
bool mitk::DataNode::GetFloatProperty(const char* propertyKey, float &floatValue, mitk::BaseRenderer* renderer) const
{
mitk::FloatProperty::Pointer floatprop = dynamic_cast<mitk::FloatProperty*>(GetProperty(propertyKey, renderer));
if(floatprop.IsNull())
return false;
floatValue = floatprop->GetValue();
return true;
}
bool mitk::DataNode::GetStringProperty(const char* propertyKey, std::string& string, mitk::BaseRenderer* renderer) const
{
mitk::StringProperty::Pointer stringProp = dynamic_cast<mitk::StringProperty*>(GetProperty(propertyKey, renderer));
if(stringProp.IsNull())
{
return false;
}
else
{
//memcpy((void*)string, stringProp->GetValue(), strlen(stringProp->GetValue()) + 1 ); // looks dangerous
string = stringProp->GetValue();
return true;
}
}
bool mitk::DataNode::GetColor(float rgb[3], mitk::BaseRenderer* renderer, const char* propertyKey) const
{
mitk::ColorProperty::Pointer colorprop = dynamic_cast<mitk::ColorProperty*>(GetProperty(propertyKey, renderer));
if(colorprop.IsNull())
return false;
memcpy(rgb, colorprop->GetColor().GetDataPointer(), 3*sizeof(float));
return true;
}
bool mitk::DataNode::GetOpacity(float &opacity, mitk::BaseRenderer* renderer, const char* propertyKey) const
{
mitk::FloatProperty::Pointer opacityprop = dynamic_cast<mitk::FloatProperty*>(GetProperty(propertyKey, renderer));
if(opacityprop.IsNull())
return false;
opacity=opacityprop->GetValue();
return true;
}
bool mitk::DataNode::GetLevelWindow(mitk::LevelWindow &levelWindow, mitk::BaseRenderer* renderer, const char* propertyKey) const
{
mitk::LevelWindowProperty::Pointer levWinProp = dynamic_cast<mitk::LevelWindowProperty*>(GetProperty(propertyKey, renderer));
if(levWinProp.IsNull())
return false;
levelWindow=levWinProp->GetLevelWindow();
return true;
}
void mitk::DataNode::SetColor(const mitk::Color &color, mitk::BaseRenderer* renderer, const char* propertyKey)
{
mitk::ColorProperty::Pointer prop;
prop = mitk::ColorProperty::New(color);
GetPropertyList(renderer)->SetProperty(propertyKey, prop);
}
void mitk::DataNode::SetColor(float red, float green, float blue, mitk::BaseRenderer* renderer, const char* propertyKey)
{
float color[3];
color[0]=red;
color[1]=green;
color[2]=blue;
SetColor(color, renderer, propertyKey);
}
void mitk::DataNode::SetColor(const float rgb[3], mitk::BaseRenderer* renderer, const char* propertyKey)
{
mitk::ColorProperty::Pointer prop;
prop = mitk::ColorProperty::New(rgb);
GetPropertyList(renderer)->SetProperty(propertyKey, prop);
}
void mitk::DataNode::SetVisibility(bool visible, mitk::BaseRenderer* renderer, const char* propertyKey)
{
mitk::BoolProperty::Pointer prop;
prop = mitk::BoolProperty::New(visible);
GetPropertyList(renderer)->SetProperty(propertyKey, prop);
}
void mitk::DataNode::SetOpacity(float opacity, mitk::BaseRenderer* renderer, const char* propertyKey)
{
mitk::FloatProperty::Pointer prop;
prop = mitk::FloatProperty::New(opacity);
GetPropertyList(renderer)->SetProperty(propertyKey, prop);
}
void mitk::DataNode::SetLevelWindow(mitk::LevelWindow levelWindow, mitk::BaseRenderer* renderer, const char* propertyKey)
{
mitk::LevelWindowProperty::Pointer prop;
prop = mitk::LevelWindowProperty::New(levelWindow);
GetPropertyList(renderer)->SetProperty(propertyKey, prop);
}
void mitk::DataNode::SetIntProperty(const char* propertyKey, int intValue, mitk::BaseRenderer* renderer)
{
GetPropertyList(renderer)->SetProperty(propertyKey, mitk::IntProperty::New(intValue));
}
void mitk::DataNode::SetBoolProperty( const char* propertyKey, bool boolValue, mitk::BaseRenderer* renderer/*=NULL*/ )
{
GetPropertyList(renderer)->SetProperty(propertyKey, mitk::BoolProperty::New(boolValue));
}
void mitk::DataNode::SetFloatProperty( const char* propertyKey, float floatValue, mitk::BaseRenderer* renderer/*=NULL*/ )
{
GetPropertyList(renderer)->SetProperty(propertyKey, mitk::FloatProperty::New(floatValue));
}
void mitk::DataNode::SetStringProperty( const char* propertyKey, const char* stringValue, mitk::BaseRenderer* renderer/*=NULL*/ )
{
GetPropertyList(renderer)->SetProperty(propertyKey, mitk::StringProperty::New(stringValue));
}
void mitk::DataNode::SetProperty(const char *propertyKey,
BaseProperty* propertyValue,
const mitk::BaseRenderer* renderer)
{
GetPropertyList(renderer)->SetProperty(propertyKey, propertyValue);
}
void mitk::DataNode::ReplaceProperty(const char *propertyKey,
BaseProperty* propertyValue,
const mitk::BaseRenderer* renderer)
{
GetPropertyList(renderer)->ReplaceProperty(propertyKey, propertyValue);
}
void mitk::DataNode::AddProperty(const char *propertyKey,
BaseProperty* propertyValue,
const mitk::BaseRenderer* renderer,
bool overwrite)
{
if((overwrite) || (GetProperty(propertyKey, renderer) == NULL))
{
SetProperty(propertyKey, propertyValue, renderer);
}
}
vtkLinearTransform* mitk::DataNode::GetVtkTransform(int t) const
{
assert(m_Data.IsNotNull());
- mitk::Geometry3D* geometry = m_Data->GetGeometry(t);
+ mitk::BaseGeometry* geometry = m_Data->GetGeometry(t);
if(geometry == NULL)
return NULL;
return geometry->GetVtkTransform();
}
unsigned long mitk::DataNode::GetMTime() const
{
unsigned long time = Superclass::GetMTime();
if(m_Data.IsNotNull())
{
if((time < m_Data->GetMTime()) ||
((m_Data->GetSource().IsNotNull()) && (time < m_Data->GetSource()->GetMTime()))
)
{
Modified();
return Superclass::GetMTime();
}
}
return time;
}
void mitk::DataNode::SetSelected(bool selected, mitk::BaseRenderer* renderer)
{
mitk::BoolProperty::Pointer selectedProperty = dynamic_cast<mitk::BoolProperty*>(GetProperty("selected"));
if ( selectedProperty.IsNull() )
{
selectedProperty = mitk::BoolProperty::New();
selectedProperty->SetValue(false);
SetProperty("selected", selectedProperty, renderer);
}
if( selectedProperty->GetValue() != selected )
{
selectedProperty->SetValue(selected);
itk::ModifiedEvent event;
InvokeEvent( event );
}
}
/*
class SelectedEvent : public itk::ModifiedEvent
{
public:
typedef SelectedEvent Self;
typedef itk::ModifiedEvent Superclass;
SelectedEvent(DataNode* dataNode)
{ m_DataNode = dataNode; };
DataNode* GetDataNode()
{ return m_DataNode; };
virtual const char * GetEventName() const
{ return "SelectedEvent"; }
virtual bool CheckEvent(const ::itk::EventObject* e) const
{ return dynamic_cast<const Self*>(e); }
virtual ::itk::EventObject* MakeObject() const
{ return new Self(m_DataNode); }
private:
DataNode* m_DataNode;
SelectedEvent(const Self& event)
{ m_DataNode = event.m_DataNode; };
void operator=(const Self& event)
{ m_DataNode = event.m_DataNode; }
};
*/
bool mitk::DataNode::IsSelected(mitk::BaseRenderer* renderer)
{
bool selected;
if ( !GetBoolProperty("selected", selected, renderer) )
return false;
return selected;
}
void mitk::DataNode::SetInteractorEnabled( const bool& enabled )
{
if ( m_Interactor.IsNull() )
{
itkWarningMacro("Interactor is NULL. Couldn't enable or disable interaction.");
return;
}
if ( enabled )
mitk::GlobalInteraction::GetInstance()->AddInteractor( m_Interactor.GetPointer() );
else
mitk::GlobalInteraction::GetInstance()->RemoveInteractor( m_Interactor.GetPointer() );
}
void mitk::DataNode::EnableInteractor()
{
SetInteractorEnabled( true );
}
void mitk::DataNode::DisableInteractor()
{
SetInteractorEnabled( false );
}
bool mitk::DataNode::IsInteractorEnabled() const
{
return mitk::GlobalInteraction::GetInstance()->InteractorRegistered( m_Interactor.GetPointer() );
}
void mitk::DataNode::SetDataInteractor(const DataInteractor::Pointer& interactor)
{
m_DataInteractor = interactor;
Modified();
// the interactor has changed, so we have ti invoke an InteractorChangedEvent
const mitk::DataNode::InteractorChangedEvent changedEvent;
InvokeEvent( changedEvent );
}
mitk::DataInteractor::Pointer mitk::DataNode::GetDataInteractor() const
{
return m_DataInteractor;
}
void mitk::DataNode::PropertyListModified( const itk::Object* /*caller*/, const itk::EventObject& )
{
Modified();
}
diff --git a/Core/Code/DataManagement/mitkDataStorage.cpp b/Core/Code/DataManagement/mitkDataStorage.cpp
index d025827d4b..9d6f8e14a5 100644
--- a/Core/Code/DataManagement/mitkDataStorage.cpp
+++ b/Core/Code/DataManagement/mitkDataStorage.cpp
@@ -1,504 +1,502 @@
/*===================================================================
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 "mitkDataStorage.h"
#include "mitkDataNode.h"
#include "mitkProperties.h"
#include "mitkNodePredicateBase.h"
#include "mitkNodePredicateProperty.h"
#include "mitkGroupTagProperty.h"
#include "mitkImage.h"
#include "itkMutexLockHolder.h"
#include "itkCommand.h"
mitk::DataStorage::DataStorage() : itk::Object()
, m_BlockNodeModifiedEvents(false)
{
}
mitk::DataStorage::~DataStorage()
{
///// we can not call GetAll() in destructor, because it is implemented in a subclass
//SetOfObjects::ConstPointer all = this->GetAll();
//for (SetOfObjects::ConstIterator it = all->Begin(); it != all->End(); ++it)
// this->RemoveListeners(it->Value());
//m_NodeModifiedObserverTags.clear();
//m_NodeDeleteObserverTags.clear();
}
void mitk::DataStorage::Add(mitk::DataNode* node, mitk::DataNode* parent)
{
mitk::DataStorage::SetOfObjects::Pointer parents = mitk::DataStorage::SetOfObjects::New();
if (parent != NULL) //< Return empty set if parent is null
parents->InsertElement(0, parent);
this->Add(node, parents);
}
void mitk::DataStorage::Remove(const mitk::DataStorage::SetOfObjects* nodes)
{
if (nodes == NULL)
return;
for (mitk::DataStorage::SetOfObjects::ConstIterator it = nodes->Begin(); it != nodes->End(); it++)
this->Remove(it.Value());
}
mitk::DataStorage::SetOfObjects::ConstPointer mitk::DataStorage::GetSubset(const NodePredicateBase* condition) const
{
mitk::DataStorage::SetOfObjects::ConstPointer result = this->FilterSetOfObjects(this->GetAll(), condition);
return result;
}
mitk::DataNode* mitk::DataStorage::GetNamedNode(const char* name) const
{
if (name == NULL)
return NULL;
mitk::StringProperty::Pointer s(mitk::StringProperty::New(name));
mitk::NodePredicateProperty::Pointer p = mitk::NodePredicateProperty::New("name", s);
mitk::DataStorage::SetOfObjects::ConstPointer rs = this->GetSubset(p);
if (rs->Size() >= 1)
return rs->GetElement(0);
else
return NULL;
}
mitk::DataNode* mitk::DataStorage::GetNode(const NodePredicateBase* condition) const
{
if (condition == NULL)
return NULL;
mitk::DataStorage::SetOfObjects::ConstPointer rs = this->GetSubset(condition);
if (rs->Size() >= 1)
return rs->GetElement(0);
else
return NULL;
}
mitk::DataNode* mitk::DataStorage::GetNamedDerivedNode(const char* name, const mitk::DataNode* sourceNode, bool onlyDirectDerivations) const
{
if (name == NULL)
return NULL;
mitk::StringProperty::Pointer s(mitk::StringProperty::New(name));
mitk::NodePredicateProperty::Pointer p = mitk::NodePredicateProperty::New("name", s);
mitk::DataStorage::SetOfObjects::ConstPointer rs = this->GetDerivations(sourceNode, p, onlyDirectDerivations);
if (rs->Size() >= 1)
return rs->GetElement(0);
else
return NULL;
}
void mitk::DataStorage::PrintSelf(std::ostream& os, itk::Indent indent) const
{
//Superclass::PrintSelf(os, indent);
mitk::DataStorage::SetOfObjects::ConstPointer all = this->GetAll();
os << indent << "DataStorage " << this << " is managing " << all->Size() << " objects. List of objects:" << std::endl;
for (mitk::DataStorage::SetOfObjects::ConstIterator allIt = all->Begin(); allIt != all->End(); allIt++)
{
std::string name;
allIt.Value()->GetName(name);
std::string datatype;
if (allIt.Value()->GetData() != NULL)
datatype = allIt.Value()->GetData()->GetNameOfClass();
os << indent << " " << allIt.Value().GetPointer() << "<" << datatype << ">: " << name << std::endl;
mitk::DataStorage::SetOfObjects::ConstPointer parents = this->GetSources(allIt.Value());
if (parents->Size() > 0)
{
os << indent << " Direct sources: ";
for (mitk::DataStorage::SetOfObjects::ConstIterator parentIt = parents->Begin(); parentIt != parents->End(); parentIt++)
os << parentIt.Value().GetPointer() << ", ";
os << std::endl;
}
mitk::DataStorage::SetOfObjects::ConstPointer derivations = this->GetDerivations(allIt.Value());
if (derivations->Size() > 0)
{
os << indent << " Direct derivations: ";
for (mitk::DataStorage::SetOfObjects::ConstIterator derivationIt = derivations->Begin(); derivationIt != derivations->End(); derivationIt++)
os << derivationIt.Value().GetPointer() << ", ";
os << std::endl;
}
}
os << std::endl;
}
mitk::DataStorage::SetOfObjects::ConstPointer mitk::DataStorage::FilterSetOfObjects(const SetOfObjects* set, const NodePredicateBase* condition) const
{
if (set == NULL)
return NULL;
mitk::DataStorage::SetOfObjects::Pointer result = mitk::DataStorage::SetOfObjects::New();
for (mitk::DataStorage::SetOfObjects::ConstIterator it = set->Begin(); it != set->End(); it++)
if (condition == NULL || condition->CheckNode(it.Value()) == true) //alway copy the set, otherwise the iterator in mitk::DataStorage::Remove() will crash
result->InsertElement(result->Size(), it.Value());
return mitk::DataStorage::SetOfObjects::ConstPointer(result);
}
const mitk::DataNode::GroupTagList mitk::DataStorage::GetGroupTags() const
{
DataNode::GroupTagList result;
SetOfObjects::ConstPointer all = this->GetAll();
if (all.IsNull())
return result;
for (mitk::DataStorage::SetOfObjects::ConstIterator nodeIt = all->Begin(); nodeIt != all->End(); nodeIt++) // for each node
{
mitk::PropertyList* pl = nodeIt.Value()->GetPropertyList();
for (mitk::PropertyList::PropertyMap::const_iterator propIt = pl->GetMap()->begin(); propIt != pl->GetMap()->end(); propIt++)
if (dynamic_cast<mitk::GroupTagProperty*>(propIt->second.GetPointer()) != NULL)
result.insert(propIt->first);
}
return result;
}
void mitk::DataStorage::EmitAddNodeEvent(const mitk::DataNode* node)
{
AddNodeEvent.Send(node);
}
void mitk::DataStorage::EmitRemoveNodeEvent(const mitk::DataNode* node)
{
RemoveNodeEvent.Send(node);
}
void mitk::DataStorage::OnNodeInteractorChanged( itk::Object *caller, const itk::EventObject& )
{
const mitk::DataNode* _Node = dynamic_cast<const mitk::DataNode*>(caller);
if(_Node)
{
InteractorChangedNodeEvent.Send( _Node );
}
}
void mitk::DataStorage::OnNodeModifiedOrDeleted( const itk::Object *caller, const itk::EventObject &event )
{
if( m_BlockNodeModifiedEvents )
return;
const mitk::DataNode* _Node = dynamic_cast<const mitk::DataNode*>(caller);
if(_Node)
{
const itk::ModifiedEvent* modEvent = dynamic_cast<const itk::ModifiedEvent*>(&event);
if(modEvent)
ChangedNodeEvent.Send(_Node);
else
DeleteNodeEvent.Send(_Node);
}
}
void mitk::DataStorage::AddListeners( const mitk::DataNode* _Node )
{
itk::MutexLockHolder<itk::SimpleFastMutexLock> locked(m_MutexOne);
// node must not be 0 and must not be yet registered
mitk::DataNode* NonConstNode = const_cast<mitk::DataNode*>(_Node);
if(_Node && m_NodeModifiedObserverTags
.find(NonConstNode) == m_NodeModifiedObserverTags.end())
{
itk::MemberCommand<mitk::DataStorage>::Pointer nodeModifiedCommand =
itk::MemberCommand<mitk::DataStorage>::New();
nodeModifiedCommand->SetCallbackFunction(this
, &mitk::DataStorage::OnNodeModifiedOrDeleted);
m_NodeModifiedObserverTags[NonConstNode]
= NonConstNode->AddObserver(itk::ModifiedEvent(), nodeModifiedCommand);
itk::MemberCommand<mitk::DataStorage>::Pointer interactorChangedCommand = itk::MemberCommand<mitk::DataStorage>::New();
interactorChangedCommand->SetCallbackFunction(this, &mitk::DataStorage::OnNodeInteractorChanged);
m_NodeInteractorChangedObserverTags[NonConstNode] = NonConstNode->AddObserver( mitk::DataNode::InteractorChangedEvent(), interactorChangedCommand);
// add itk delete listener on datastorage
itk::MemberCommand<mitk::DataStorage>::Pointer deleteCommand =
itk::MemberCommand<mitk::DataStorage>::New();
deleteCommand->SetCallbackFunction(this, &mitk::DataStorage::OnNodeModifiedOrDeleted);
// add observer
m_NodeDeleteObserverTags[NonConstNode]
= NonConstNode->AddObserver(itk::DeleteEvent(), deleteCommand);
}
}
void mitk::DataStorage::RemoveListeners( const mitk::DataNode* _Node )
{
itk::MutexLockHolder<itk::SimpleFastMutexLock> locked(m_MutexOne) ;
// node must not be 0 and must be registered
mitk::DataNode* NonConstNode = const_cast<mitk::DataNode*>(_Node);
if(_Node && m_NodeModifiedObserverTags
.find(NonConstNode) != m_NodeModifiedObserverTags.end())
{
// const cast is bad! but sometimes it is necessary. removing an observer does not really
// touch the internal state
NonConstNode->RemoveObserver(m_NodeModifiedObserverTags
.find(NonConstNode)->second);
NonConstNode->RemoveObserver(m_NodeDeleteObserverTags
.find(NonConstNode)->second);
NonConstNode->RemoveObserver(m_NodeInteractorChangedObserverTags
.find(NonConstNode)->second);
m_NodeModifiedObserverTags.erase(NonConstNode);
m_NodeDeleteObserverTags.erase(NonConstNode);
m_NodeInteractorChangedObserverTags.erase(NonConstNode);
}
}
mitk::TimeGeometry::Pointer mitk::DataStorage::ComputeBoundingGeometry3D( const SetOfObjects* input, const char* boolPropertyKey, mitk::BaseRenderer* renderer, const char* boolPropertyKey2) const
{
if (input == NULL)
throw std::invalid_argument("DataStorage: input is invalid");
BoundingBox::PointsContainer::Pointer pointscontainer=BoundingBox::PointsContainer::New();
BoundingBox::PointIdentifier pointid=0;
Point3D point;
Vector3D minSpacing;
minSpacing.Fill(ScalarTypeNumericTraits::max());
ScalarType stmin, stmax;
stmin= ScalarTypeNumericTraits::NonpositiveMin();
stmax= ScalarTypeNumericTraits::max();
ScalarType minimalIntervallSize = stmax;
ScalarType minimalTime = stmax;
ScalarType maximalTime = 0;
// Needed for check of zero bounding boxes
mitk::ScalarType nullpoint[]={0,0,0,0,0,0};
BoundingBox::BoundsArrayType itkBoundsZero(nullpoint);
for (SetOfObjects::ConstIterator it = input->Begin(); it != input->End(); ++it)
{
DataNode::Pointer node = it->Value();
if((node.IsNotNull()) && (node->GetData() != NULL) &&
(node->GetData()->IsEmpty()==false) &&
node->IsOn(boolPropertyKey, renderer) &&
node->IsOn(boolPropertyKey2, renderer)
)
{
const TimeGeometry* timeGeometry = node->GetData()->GetUpdatedTimeGeometry();
if (timeGeometry != NULL )
{
// bounding box (only if non-zero)
BoundingBox::BoundsArrayType itkBounds = timeGeometry->GetBoundingBoxInWorld()->GetBounds();
if (itkBounds == itkBoundsZero)
{
continue;
}
unsigned char i;
for(i=0; i<8; ++i)
{
point = timeGeometry->GetCornerPointInWorld(i);
if(point[0]*point[0]+point[1]*point[1]+point[2]*point[2] < large)
pointscontainer->InsertElement( pointid++, point);
else
{
itkGenericOutputMacro( << "Unrealistically distant corner point encountered. Ignored. Node: " << node );
}
}
try
{
// time bounds
// iterate over all time steps
// Attention: Objects with zero bounding box are not respected in time bound calculation
for (TimeStepType i=0; i<timeGeometry->CountTimeSteps(); i++)
{
Vector3D spacing = node->GetData()->GetGeometry(i)->GetSpacing();
for (int axis = 0; axis < 3; ++ axis)
{
if (spacing[axis] < minSpacing[axis]) minSpacing[axis] = spacing[axis];
}
- const TimeBounds & curTimeBounds = node->GetData()->GetGeometry(i)->GetTimeBounds();
+ const TimeBounds & curTimeBounds = node->GetData()->GetTimeGeometry()->GetTimeBounds(i);
// get the minimal time of all objects in the DataStorage
if ((curTimeBounds[0]<minimalTime)&&(curTimeBounds[0]>stmin))
{
minimalTime=curTimeBounds[0];
}
// get the maximal time of all objects in the DataStorage
if ((curTimeBounds[1]>maximalTime)&&(curTimeBounds[1]<stmax))
{
maximalTime = curTimeBounds[1];
}
// get the minimal TimeBound of all time steps of the current DataNode
if (curTimeBounds[1]-curTimeBounds[0]<minimalIntervallSize)
{
minimalIntervallSize = curTimeBounds[1]-curTimeBounds[0];
}
}
}
catch(itk::ExceptionObject e)
{
MITK_ERROR << e << std::endl;
}
}
}
}
BoundingBox::Pointer result = BoundingBox::New();
result->SetPoints(pointscontainer);
result->ComputeBoundingBox();
- // minimal time bounds of a single time step for all geometries
- TimeBounds minTimeBounds;
- minTimeBounds[0] = 0;
- minTimeBounds[1] = 1;
// compute the number of time steps
unsigned int numberOfTimeSteps = 1;
- if (maximalTime!=0) // make sure that there is at least one time sliced geometry in the data storage
+ if (maximalTime==0) // make sure that there is at least one time sliced geometry in the data storage
{
- minTimeBounds[0] = minimalTime;
- minTimeBounds[1] = minimalTime + minimalIntervallSize;
- numberOfTimeSteps = static_cast<unsigned int>((maximalTime-minimalTime)/minimalIntervallSize);
+ minimalTime = 0;
+ maximalTime = 1;
+ minimalIntervallSize = 1;
}
+ numberOfTimeSteps = static_cast<unsigned int>((maximalTime-minimalTime)/minimalIntervallSize);
TimeGeometry::Pointer timeGeometry = NULL;
if ( result->GetPoints()->Size()>0 )
{
// Initialize a geometry of a single time step
Geometry3D::Pointer geometry = Geometry3D::New();
geometry->Initialize();
// correct bounding-box (is now in mm, should be in index-coordinates)
// according to spacing
BoundingBox::BoundsArrayType bounds = result->GetBounds();
int i;
for(i = 0; i < 6; ++i)
{
bounds[i] /= minSpacing[i/2];
}
geometry->SetBounds(bounds);
geometry->SetSpacing(minSpacing);
- geometry->SetTimeBounds(minTimeBounds);
// Initialize the time sliced geometry
timeGeometry = ProportionalTimeGeometry::New();
dynamic_cast<ProportionalTimeGeometry*>(timeGeometry.GetPointer())->Initialize(geometry,numberOfTimeSteps);
+ dynamic_cast<ProportionalTimeGeometry*>(timeGeometry.GetPointer())->SetFirstTimePoint(minimalTime);
+ dynamic_cast<ProportionalTimeGeometry*>(timeGeometry.GetPointer())->SetStepDuration(minimalIntervallSize);
}
return timeGeometry;
}
mitk::TimeGeometry::Pointer mitk::DataStorage::ComputeBoundingGeometry3D( const char* boolPropertyKey, mitk::BaseRenderer* renderer, const char* boolPropertyKey2) const
{
return this->ComputeBoundingGeometry3D(this->GetAll(), boolPropertyKey, renderer, boolPropertyKey2);
}
mitk::TimeGeometry::Pointer mitk::DataStorage::ComputeVisibleBoundingGeometry3D( mitk::BaseRenderer* renderer, const char* boolPropertyKey )
{
return ComputeBoundingGeometry3D( "visible", renderer, boolPropertyKey );
}
mitk::BoundingBox::Pointer mitk::DataStorage::ComputeBoundingBox( const char* boolPropertyKey, mitk::BaseRenderer* renderer, const char* boolPropertyKey2)
{
BoundingBox::PointsContainer::Pointer pointscontainer=BoundingBox::PointsContainer::New();
BoundingBox::PointIdentifier pointid=0;
Point3D point;
// Needed for check of zero bounding boxes
mitk::ScalarType nullpoint[]={0,0,0,0,0,0};
BoundingBox::BoundsArrayType itkBoundsZero(nullpoint);
SetOfObjects::ConstPointer all = this->GetAll();
for (SetOfObjects::ConstIterator it = all->Begin(); it != all->End(); ++it)
{
DataNode::Pointer node = it->Value();
if((node.IsNotNull()) && (node->GetData() != NULL) &&
(node->GetData()->IsEmpty()==false) &&
node->IsOn(boolPropertyKey, renderer) &&
node->IsOn(boolPropertyKey2, renderer)
)
{
const TimeGeometry* geometry = node->GetData()->GetUpdatedTimeGeometry();
if (geometry != NULL )
{
// bounding box (only if non-zero)
BoundingBox::BoundsArrayType itkBounds = geometry->GetBoundingBoxInWorld()->GetBounds();
if (itkBounds == itkBoundsZero)
{
continue;
}
unsigned char i;
for(i=0; i<8; ++i)
{
point = geometry->GetCornerPointInWorld(i);
if(point[0]*point[0]+point[1]*point[1]+point[2]*point[2] < large)
pointscontainer->InsertElement( pointid++, point);
else
{
itkGenericOutputMacro( << "Unrealistically distant corner point encountered. Ignored. Node: " << node );
}
}
}
}
}
BoundingBox::Pointer result = BoundingBox::New();
result->SetPoints(pointscontainer);
result->ComputeBoundingBox();
return result;
}
mitk::TimeBounds mitk::DataStorage::ComputeTimeBounds( const char* boolPropertyKey, mitk::BaseRenderer* renderer, const char* boolPropertyKey2)
{
TimeBounds timeBounds;
ScalarType stmin, stmax, cur;
stmin= ScalarTypeNumericTraits::NonpositiveMin();
stmax= ScalarTypeNumericTraits::max();
timeBounds[0]=stmax; timeBounds[1]=stmin;
SetOfObjects::ConstPointer all = this->GetAll();
for (SetOfObjects::ConstIterator it = all->Begin(); it != all->End(); ++it)
{
DataNode::Pointer node = it->Value();
if((node.IsNotNull()) && (node->GetData() != NULL) &&
(node->GetData()->IsEmpty()==false) &&
node->IsOn(boolPropertyKey, renderer) &&
node->IsOn(boolPropertyKey2, renderer)
)
{
const TimeGeometry* geometry = node->GetData()->GetUpdatedTimeGeometry();
if (geometry != NULL )
{
const TimeBounds & curTimeBounds = geometry->GetTimeBounds();
cur=curTimeBounds[0];
//is it after -infinity, but before everything else that we found until now?
if((cur > stmin) && (cur < timeBounds[0]))
timeBounds[0] = cur;
cur=curTimeBounds[1];
//is it before infinity, but after everything else that we found until now?
if((cur < stmax) && (cur > timeBounds[1]))
timeBounds[1] = cur;
}
}
}
if(!(timeBounds[0] < stmax))
{
timeBounds[0] = stmin;
timeBounds[1] = stmax;
}
return timeBounds;
}
void mitk::DataStorage::BlockNodeModifiedEvents( bool block )
{
m_BlockNodeModifiedEvents = block;
}
diff --git a/Core/Code/DataManagement/mitkDisplayGeometry.cpp b/Core/Code/DataManagement/mitkDisplayGeometry.cpp
index 39fac88de3..da1dc11ebb 100644
--- a/Core/Code/DataManagement/mitkDisplayGeometry.cpp
+++ b/Core/Code/DataManagement/mitkDisplayGeometry.cpp
@@ -1,637 +1,613 @@
/*===================================================================
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 "mitkDisplayGeometry.h"
itk::LightObject::Pointer mitk::DisplayGeometry::InternalClone() const
{
-// itkExceptionMacro(<<"calling mitk::DisplayGeometry::Clone does not make much sense.");
+ // itkExceptionMacro(<<"calling mitk::DisplayGeometry::Clone does not make much sense.");
DisplayGeometry* returnValue = const_cast<DisplayGeometry *>(this);
return returnValue;
}
bool mitk::DisplayGeometry::IsValid() const
{
- return m_Valid && m_WorldGeometry.IsNotNull() && m_WorldGeometry->IsValid();
+ return m_WorldGeometry.IsNotNull() && m_WorldGeometry->IsValid();
}
unsigned long mitk::DisplayGeometry::GetMTime() const
{
- if((m_WorldGeometry.IsNotNull()) && (Geometry2D::GetMTime() < m_WorldGeometry->GetMTime()))
+ if((m_WorldGeometry.IsNotNull()) && (PlaneGeometry::GetMTime() < m_WorldGeometry->GetMTime()))
{
Modified();
}
- return Geometry2D::GetMTime();
-}
-
-const mitk::TimeBounds& mitk::DisplayGeometry::GetTimeBounds() const
-{
- if(m_WorldGeometry.IsNull())
- {
- return m_TimeBounds;
- }
-
- return m_WorldGeometry->GetTimeBounds();
+ return PlaneGeometry::GetMTime();
}
-
-
-
-
+//const mitk::TimeBounds& mitk::DisplayGeometry::GetTimeBounds() const
+//{
+// if(m_WorldGeometry.IsNull())
+// {
+// return m_TimeBounds;
+// }
+//
+// return m_WorldGeometry->GetTimeBounds();
+//}
// size definition methods
-void mitk::DisplayGeometry::SetWorldGeometry(const Geometry2D* aWorldGeometry)
+void mitk::DisplayGeometry::SetWorldGeometry(const PlaneGeometry* aWorldGeometry)
{
m_WorldGeometry = aWorldGeometry;
Modified();
}
bool mitk::DisplayGeometry::SetOriginInMM(const Vector2D& origin_mm)
{
m_OriginInMM = origin_mm;
WorldToDisplay(m_OriginInMM, m_OriginInDisplayUnits);
Modified();
return !this->RefitVisibleRect();
}
mitk::Vector2D mitk::DisplayGeometry::GetOriginInMM() const
{
return m_OriginInMM;
}
mitk::Vector2D mitk::DisplayGeometry::GetOriginInDisplayUnits() const
{
return m_OriginInDisplayUnits;
}
void mitk::DisplayGeometry::SetSizeInDisplayUnits(unsigned int width, unsigned int height, bool keepDisplayedRegion)
{
Vector2D oldSizeInMM( m_SizeInMM );
Point2D oldCenterInMM;
if(keepDisplayedRegion)
{
Point2D centerInDisplayUnits;
centerInDisplayUnits[0] = m_SizeInDisplayUnits[0]*0.5;
centerInDisplayUnits[1] = m_SizeInDisplayUnits[1]*0.5;
DisplayToWorld(centerInDisplayUnits, oldCenterInMM);
}
m_SizeInDisplayUnits[0]=width;
m_SizeInDisplayUnits[1]=height;
if(m_SizeInDisplayUnits[0] <= 0)
m_SizeInDisplayUnits[0] = 1;
if(m_SizeInDisplayUnits[1] <= 0)
m_SizeInDisplayUnits[1] = 1;
DisplayToWorld(m_SizeInDisplayUnits, m_SizeInMM);
if(keepDisplayedRegion)
{
Point2D positionOfOldCenterInCurrentDisplayUnits;
WorldToDisplay(oldCenterInMM, positionOfOldCenterInCurrentDisplayUnits);
Point2D currentNewCenterInDisplayUnits;
currentNewCenterInDisplayUnits[0] = m_SizeInDisplayUnits[0]*0.5;
currentNewCenterInDisplayUnits[1] = m_SizeInDisplayUnits[1]*0.5;
Vector2D shift;
shift=positionOfOldCenterInCurrentDisplayUnits.GetVectorFromOrigin()-currentNewCenterInDisplayUnits;
MoveBy(shift);
Zoom(m_SizeInMM.GetNorm()/oldSizeInMM.GetNorm(), currentNewCenterInDisplayUnits);
}
Modified();
}
mitk::Vector2D mitk::DisplayGeometry::GetSizeInDisplayUnits() const
{
return m_SizeInDisplayUnits;
}
mitk::Vector2D mitk::DisplayGeometry::GetSizeInMM() const
{
return m_SizeInMM;
}
unsigned int mitk::DisplayGeometry::GetDisplayWidth() const
{
assert(m_SizeInDisplayUnits[0] >= 0);
return (unsigned int)m_SizeInDisplayUnits[0];
}
unsigned int mitk::DisplayGeometry::GetDisplayHeight() const
{
assert(m_SizeInDisplayUnits[1] >= 0);
return (unsigned int)m_SizeInDisplayUnits[1];
}
-
-
-
-
// zooming, panning, restriction of both
void mitk::DisplayGeometry::SetConstrainZoomingAndPanning(bool constrain)
{
m_ConstrainZoomingAndPanning = constrain;
if (m_ConstrainZoomingAndPanning)
{
this->RefitVisibleRect();
}
}
bool mitk::DisplayGeometry::GetConstrainZommingAndPanning() const
{
return m_ConstrainZoomingAndPanning;
}
bool mitk::DisplayGeometry::SetScaleFactor(ScalarType mmPerDisplayUnit)
{
if(mmPerDisplayUnit<0.0001)
{
mmPerDisplayUnit=0.0001;
}
m_ScaleFactorMMPerDisplayUnit = mmPerDisplayUnit;
assert(m_ScaleFactorMMPerDisplayUnit < ScalarTypeNumericTraits::infinity());
DisplayToWorld(m_SizeInDisplayUnits, m_SizeInMM);
return !this->RefitVisibleRect();
}
mitk::ScalarType mitk::DisplayGeometry::GetScaleFactorMMPerDisplayUnit() const
{
return m_ScaleFactorMMPerDisplayUnit;
}
// Zooms with a factor (1.0=identity) around the specified center in display units
bool mitk::DisplayGeometry::Zoom(ScalarType factor, const Point2D& centerInDisplayUnits)
{
assert(factor > 0);
if ( SetScaleFactor(m_ScaleFactorMMPerDisplayUnit/factor) )
{
return SetOriginInMM(m_OriginInMM-centerInDisplayUnits.GetVectorFromOrigin()*(1-factor)*m_ScaleFactorMMPerDisplayUnit);
}
else
{
return false;
}
}
-
// Zooms with a factor (1.0=identity) around the specified center, but tries (if its within view contraints) to match the center in display units with the center in world coordinates.
bool mitk::DisplayGeometry::ZoomWithFixedWorldCoordinates(ScalarType factor, const Point2D& focusDisplayUnits, const Point2D& focusUnitsInMM )
{
assert(factor > 0);
SetScaleFactor(m_ScaleFactorMMPerDisplayUnit/factor);
SetOriginInMM(focusUnitsInMM.GetVectorFromOrigin()-focusDisplayUnits.GetVectorFromOrigin()*m_ScaleFactorMMPerDisplayUnit);
return true;
}
-
bool mitk::DisplayGeometry::MoveBy(const Vector2D& shiftInDisplayUnits)
{
SetOriginInMM(m_OriginInMM+shiftInDisplayUnits*m_ScaleFactorMMPerDisplayUnit);
Modified();
return !this->RefitVisibleRect();
}
void mitk::DisplayGeometry::Fit()
{
if((m_WorldGeometry.IsNull()) || (m_WorldGeometry->IsValid() == false)) return;
/// \FIXME: try to remove all the casts
int width=(int)m_SizeInDisplayUnits[0];
int height=(int)m_SizeInDisplayUnits[1];
ScalarType w = width;
ScalarType h = height;
- const ScalarType& widthInMM = m_WorldGeometry->GetParametricExtentInMM(0);
- const ScalarType& heightInMM = m_WorldGeometry->GetParametricExtentInMM(1);
+ const ScalarType& widthInMM = m_WorldGeometry->GetExtentInMM(0);
+ const ScalarType& heightInMM = m_WorldGeometry->GetExtentInMM(1);
ScalarType aspRatio=((ScalarType)widthInMM)/heightInMM;
ScalarType x = (ScalarType)w/widthInMM;
ScalarType y = (ScalarType)h/heightInMM;
if (x > y)
{
w = (int) (aspRatio*h);
}
else
{
h = (int) (w/aspRatio);
}
if(w>0)
{
SetScaleFactor(widthInMM/w);
}
Vector2D origin_display;
origin_display[0]=-(width-w)/2.0;
origin_display[1]=-(height-h)/2.0;
SetOriginInMM(origin_display*m_ScaleFactorMMPerDisplayUnit);
this->RefitVisibleRect();
Modified();
}
-
-
-
-
// conversion methods
void mitk::DisplayGeometry::DisplayToWorld(const Point2D &pt_display, Point2D &pt_mm) const
{
pt_mm[0]=m_ScaleFactorMMPerDisplayUnit*pt_display[0]+m_OriginInMM[0];
pt_mm[1]=m_ScaleFactorMMPerDisplayUnit*pt_display[1]+m_OriginInMM[1];
}
void mitk::DisplayGeometry::WorldToDisplay(const Point2D &pt_mm, Point2D &pt_display) const
{
pt_display[0]=(pt_mm[0]-m_OriginInMM[0])*(1.0/m_ScaleFactorMMPerDisplayUnit);
pt_display[1]=(pt_mm[1]-m_OriginInMM[1])*(1.0/m_ScaleFactorMMPerDisplayUnit);
}
void mitk::DisplayGeometry::DisplayToWorld(const Vector2D &vec_display, Vector2D &vec_mm) const
{
vec_mm=vec_display*m_ScaleFactorMMPerDisplayUnit;
}
void mitk::DisplayGeometry::WorldToDisplay(const Vector2D &vec_mm, Vector2D &vec_display) const
{
vec_display=vec_mm*(1.0/m_ScaleFactorMMPerDisplayUnit);
}
void mitk::DisplayGeometry::ULDisplayToMM(const Point2D &pt_ULdisplay, Point2D &pt_mm) const
{
ULDisplayToDisplay(pt_ULdisplay, pt_mm);
DisplayToWorld(pt_mm, pt_mm);
}
void mitk::DisplayGeometry::MMToULDisplay(const Point2D &pt_mm, Point2D &pt_ULdisplay) const
{
WorldToDisplay(pt_mm, pt_ULdisplay);
DisplayToULDisplay(pt_ULdisplay, pt_ULdisplay);
}
void mitk::DisplayGeometry::ULDisplayToMM(const Vector2D &vec_ULdisplay, Vector2D &vec_mm) const
{
ULDisplayToDisplay(vec_ULdisplay, vec_mm);
DisplayToWorld(vec_mm, vec_mm);
}
void mitk::DisplayGeometry::MMToULDisplay(const Vector2D &vec_mm, Vector2D &vec_ULdisplay) const
{
WorldToDisplay(vec_mm, vec_ULdisplay);
DisplayToULDisplay(vec_ULdisplay, vec_ULdisplay);
}
void mitk::DisplayGeometry::ULDisplayToDisplay(const Point2D &pt_ULdisplay, Point2D &pt_display) const
{
pt_display[0]=pt_ULdisplay[0];
pt_display[1]=GetDisplayHeight()-pt_ULdisplay[1];
}
void mitk::DisplayGeometry::DisplayToULDisplay(const Point2D &pt_display, Point2D &pt_ULdisplay) const
{
ULDisplayToDisplay(pt_display, pt_ULdisplay);
}
void mitk::DisplayGeometry::ULDisplayToDisplay(const Vector2D &vec_ULdisplay, Vector2D &vec_display) const
{
vec_display[0]= vec_ULdisplay[0];
vec_display[1]=-vec_ULdisplay[1];
}
void mitk::DisplayGeometry::DisplayToULDisplay(const Vector2D &vec_display, Vector2D &vec_ULdisplay) const
{
ULDisplayToDisplay(vec_display, vec_ULdisplay);
}
bool mitk::DisplayGeometry::Project(const Point3D &pt3d_mm, Point3D &projectedPt3d_mm) const
{
if(m_WorldGeometry.IsNotNull())
{
return m_WorldGeometry->Project(pt3d_mm, projectedPt3d_mm);
}
else
{
return false;
}
- }
+}
bool mitk::DisplayGeometry::Project(const Point3D & atPt3d_mm, const Vector3D &vec3d_mm, Vector3D &projectedVec3d_mm) const
{
if(m_WorldGeometry.IsNotNull())
{
return m_WorldGeometry->Project(atPt3d_mm, vec3d_mm, projectedVec3d_mm);
}
else
{
return false;
}
}
bool mitk::DisplayGeometry::Project(const Vector3D &vec3d_mm, Vector3D &projectedVec3d_mm) const
{
- if(m_WorldGeometry.IsNotNull())
- {
- return m_WorldGeometry->Project(vec3d_mm, projectedVec3d_mm);
- }
- else
- {
- return false;
- }
+ if(m_WorldGeometry.IsNotNull())
+ {
+ return m_WorldGeometry->Project(vec3d_mm, projectedVec3d_mm);
+ }
+ else
+ {
+ return false;
+ }
}
bool mitk::DisplayGeometry::Map(const Point3D &pt3d_mm, Point2D &pt2d_mm) const
{
if(m_WorldGeometry.IsNotNull())
{
return m_WorldGeometry->Map(pt3d_mm, pt2d_mm);
}
else
{
return false;
}
}
void mitk::DisplayGeometry::Map(const Point2D &pt2d_mm, Point3D &pt3d_mm) const
{
if(m_WorldGeometry.IsNull()) return;
m_WorldGeometry->Map(pt2d_mm, pt3d_mm);
}
bool mitk::DisplayGeometry::Map(const Point3D & atPt3d_mm, const Vector3D &vec3d_mm, Vector2D &vec2d_mm) const
{
if(m_WorldGeometry.IsNotNull())
{
return m_WorldGeometry->Map(atPt3d_mm, vec3d_mm, vec2d_mm);
}
else
{
return false;
}
}
void mitk::DisplayGeometry::Map(const Point2D & atPt2d_mm, const Vector2D &vec2d_mm, Vector3D &vec3d_mm) const
{
if(m_WorldGeometry.IsNull()) return;
m_WorldGeometry->Map(atPt2d_mm, vec2d_mm, vec3d_mm);
}
-
-
-
-
// protected methods
mitk::DisplayGeometry::DisplayGeometry()
-:m_ScaleFactorMMPerDisplayUnit(1.0)
-,m_WorldGeometry(NULL)
-,m_ConstrainZoomingAndPanning(true)
-,m_MaxWorldViewPercentage(1.0)
-,m_MinWorldViewPercentage(0.1)
+ :m_ScaleFactorMMPerDisplayUnit(1.0)
+ ,m_WorldGeometry(NULL)
+ ,m_ConstrainZoomingAndPanning(true)
+ ,m_MaxWorldViewPercentage(1.0)
+ ,m_MinWorldViewPercentage(0.1)
{
m_OriginInMM.Fill(0.0);
m_OriginInDisplayUnits.Fill(0.0);
m_SizeInMM.Fill(1.0);
m_SizeInDisplayUnits.Fill(10.0);
}
mitk::DisplayGeometry::~DisplayGeometry()
{
}
bool mitk::DisplayGeometry::RefitVisibleRect()
{
// do nothing if not asked to
if (!m_ConstrainZoomingAndPanning) return false;
// don't allow recursion (need to be fixed, singleton)
static bool inRecalculate = false;
if (inRecalculate) return false;
inRecalculate = true;
// rename some basic measures of the current viewport and world geometry (MM = milimeters Px = Pixels = display units)
float displayXMM = m_OriginInMM[0];
float displayYMM = m_OriginInMM[1];
float displayWidthPx = m_SizeInDisplayUnits[0];
float displayHeightPx = m_SizeInDisplayUnits[1];
float displayWidthMM = m_SizeInDisplayUnits[0] * m_ScaleFactorMMPerDisplayUnit;
float displayHeightMM = m_SizeInDisplayUnits[1] * m_ScaleFactorMMPerDisplayUnit;
- float worldWidthMM = m_WorldGeometry->GetParametricExtentInMM(0);
- float worldHeightMM = m_WorldGeometry->GetParametricExtentInMM(1);
+ float worldWidthMM = m_WorldGeometry->GetExtentInMM(0);
+ float worldHeightMM = m_WorldGeometry->GetExtentInMM(1);
// reserve variables for the correction logic to save a corrected origin and zoom factor
Vector2D newOrigin = m_OriginInMM;
bool correctPanning = false;
float newScaleFactor = m_ScaleFactorMMPerDisplayUnit;
bool correctZooming = false;
// start of the correction logic
// zoom to big means:
// at a given percentage of the world's width/height should be visible. Otherwise
// the whole screen could show only one pixel
//
// zoom to small means:
// zooming out should be limited at the point where the smaller of the world's sides is completely visible
bool zoomXtooSmall = displayWidthPx * m_ScaleFactorMMPerDisplayUnit > m_MaxWorldViewPercentage * worldWidthMM;
bool zoomXtooBig = displayWidthPx * m_ScaleFactorMMPerDisplayUnit < m_MinWorldViewPercentage * worldWidthMM;
bool zoomYtooSmall = displayHeightPx * m_ScaleFactorMMPerDisplayUnit > m_MaxWorldViewPercentage * worldHeightMM;
bool zoomYtooBig = displayHeightPx * m_ScaleFactorMMPerDisplayUnit < m_MinWorldViewPercentage * worldHeightMM;
// constrain zooming in both direction
if ( zoomXtooBig && zoomYtooBig)
{
double fx = worldWidthMM * m_MinWorldViewPercentage / displayWidthPx;
double fy = worldHeightMM * m_MinWorldViewPercentage / displayHeightPx;
newScaleFactor = fx < fy ? fx : fy;
correctZooming = true;
}
// constrain zooming in x direction
else if ( zoomXtooBig )
{
newScaleFactor = worldWidthMM * m_MinWorldViewPercentage / displayWidthPx;
correctZooming = true;
}
// constrain zooming in y direction
else if ( zoomYtooBig )
{
newScaleFactor = worldHeightMM * m_MinWorldViewPercentage / displayHeightPx;
correctZooming = true;
}
// constrain zooming out
// we stop zooming out at these situations:
//
// *** display
// --- image
//
// **********************
// * * x side maxed out
// * *
// *--------------------*
// *| |*
// *| |*
// *--------------------*
// * *
// * *
// * *
// **********************
//
// **********************
// * |------| * y side maxed out
// * | | *
// * | | *
// * | | *
// * | | *
// * | | *
// * | | *
// * | | *
// * |------| *
// **********************
//
// In both situations we center the not-maxed out direction
//
-if ( zoomXtooSmall && zoomYtooSmall )
- {
- // determine and set the bigger scale factor
- float fx = worldWidthMM * m_MaxWorldViewPercentage / displayWidthPx;
- float fy = worldHeightMM * m_MaxWorldViewPercentage / displayHeightPx;
- newScaleFactor = fx > fy ? fx : fy;
-
- correctZooming = true;
- }
+ if ( zoomXtooSmall && zoomYtooSmall )
+ {
+ // determine and set the bigger scale factor
+ float fx = worldWidthMM * m_MaxWorldViewPercentage / displayWidthPx;
+ float fy = worldHeightMM * m_MaxWorldViewPercentage / displayHeightPx;
+ newScaleFactor = fx > fy ? fx : fy;
+ correctZooming = true;
+ }
// actually execute correction
if (correctZooming)
{
SetScaleFactor(newScaleFactor);
}
displayWidthMM = m_SizeInDisplayUnits[0] * m_ScaleFactorMMPerDisplayUnit;
displayHeightMM = m_SizeInDisplayUnits[1] * m_ScaleFactorMMPerDisplayUnit;
// constrain panning
if(worldWidthMM<displayWidthMM)
{
// zoomed out too much in x (but tolerated because y is still ok)
// --> center x
newOrigin[0] = (worldWidthMM - displayWidthMM) / 2.0;
correctPanning = true;
}
else
{
// make sure left display border inside our world
if (displayXMM < 0)
{
newOrigin[0] = 0;
correctPanning = true;
}
// make sure right display border inside our world
else if (displayXMM + displayWidthMM > worldWidthMM)
{
newOrigin[0] = worldWidthMM - displayWidthMM;
correctPanning = true;
}
}
-
if (worldHeightMM<displayHeightMM)
{
// zoomed out too much in y (but tolerated because x is still ok)
// --> center y
newOrigin[1] = (worldHeightMM - displayHeightMM) / 2.0;
correctPanning = true;
}
else
{
// make sure top display border inside our world
if (displayYMM + displayHeightMM > worldHeightMM)
{
newOrigin[1] = worldHeightMM - displayHeightMM;
correctPanning = true;
}
- // make sure bottom display border inside our world
+ // make sure bottom display border inside our world
else
- if (displayYMM < 0)
- {
- newOrigin[1] = 0;
- correctPanning = true;
- }
-
+ if (displayYMM < 0)
+ {
+ newOrigin[1] = 0;
+ correctPanning = true;
+ }
}
- if (correctPanning)
+ if (correctPanning)
{
SetOriginInMM( newOrigin );
}
inRecalculate = false;
if ( correctPanning || correctZooming )
{
Modified();
}
// return true if any correction has been made
return correctPanning || correctZooming;
}
void mitk::DisplayGeometry::PrintSelf(std::ostream& os, itk::Indent indent) const
{
if(m_WorldGeometry.IsNull())
{
os << indent << " WorldGeometry: " << "NULL" << std::endl;
}
else
{
m_WorldGeometry->Print(os, indent);
os << indent << " OriginInMM: " << m_OriginInMM << std::endl;
os << indent << " OriginInDisplayUnits: " << m_OriginInDisplayUnits << std::endl;
os << indent << " SizeInMM: " << m_SizeInMM << std::endl;
os << indent << " SizeInDisplayUnits: " << m_SizeInDisplayUnits << std::endl;
os << indent << " ScaleFactorMMPerDisplayUni: " << m_ScaleFactorMMPerDisplayUnit << std::endl;
}
Superclass::PrintSelf(os,indent);
}
-
diff --git a/Core/Code/DataManagement/mitkDisplayGeometry.h b/Core/Code/DataManagement/mitkDisplayGeometry.h
index d463fa37e2..b05e6b61fd 100644
--- a/Core/Code/DataManagement/mitkDisplayGeometry.h
+++ b/Core/Code/DataManagement/mitkDisplayGeometry.h
@@ -1,241 +1,230 @@
/*===================================================================
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 mitkDisplayGeometry_h
#define mitkDisplayGeometry_h
-#include "mitkGeometry2D.h"
+#include "mitkPlaneGeometry.h"
namespace mitk
{
-
-/**
+ /**
\brief Describes the geometry on the display/screen for 2D display.
The main purpose of this class is to convert between display coordinates
(in display-units) and world coordinates (in mm).
DisplayGeometry depends on the size of the display area (widget width and
- height, m_SizeInDisplayUnits) and on a Geometry2D (m_WoldGeometry). It
+ height, m_SizeInDisplayUnits) and on a PlaneGeometry (m_WoldGeometry). It
represents a recangular view on this world-geometry. E.g., you can tell
the DisplayGeometry to fit the world-geometry in the display area by
calling Fit(). Provides methods for zooming and panning.
Zooming and panning can be restricted within reasonable bounds by setting
the ConstrainZoomingAndPanning flag. In these cases you can re-define what
bounds you accept as "reasonable" by calling
\warning \em Units refers to the units of the underlying world-geometry.
Take care, whether these are really the units you want to convert to.
E.g., when you want to convert a point \a pt_display (which is 2D) given
in display coordinates into a point in units of a BaseData-object @a datum
(the requested point is 3D!), use
\code
displaygeometry->DisplayToWorld(pt_display, pt2d_mm);
displaygeometry->Map(pt2d_mm, pt3d_mm);
datum->GetGeometry()->WorldToIndex(pt3d_mm, pt3d_datum_units);
\endcode
Even, if you want to convert the 2D point \a pt_display into a 2D point in
units on a certain 2D geometry \a certaingeometry, it is safer to use
\code
displaygeometry->DisplayToWorld(pt_display, pt_mm);
certaingeometry->WorldToIndex(pt_mm, pt_certain_geometry_units);
\endcode
unless you can be sure that the underlying geometry of \a displaygeometry
is really the \a certaingeometry.
\ingroup Geometry
-*/
-class MITK_CORE_EXPORT DisplayGeometry : public Geometry2D
-{
-
+ */
+ class MITK_CORE_EXPORT DisplayGeometry : public PlaneGeometry
+ {
public:
- mitkClassMacro(DisplayGeometry,Geometry2D);
+ mitkClassMacro(DisplayGeometry,PlaneGeometry);
/// Method for creation through the object factory.
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/// \brief duplicates the geometry, NOT useful for this sub-class
virtual itk::LightObject::Pointer InternalClone() const;
- virtual bool IsValid() const;
-
/// \return this objects modified time.
virtual unsigned long GetMTime() const;
- virtual const TimeBounds& GetTimeBounds() const;
-
-
+ //virtual const TimeBounds& GetTimeBounds() const;
// size definition methods
- virtual void SetWorldGeometry(const Geometry2D* aWorldGeometry);
- itkGetConstObjectMacro(WorldGeometry, Geometry2D);
+ virtual void SetWorldGeometry(const PlaneGeometry* aWorldGeometry);
+ itkGetConstObjectMacro(WorldGeometry, PlaneGeometry);
/// \return if new origin was within accepted limits
virtual bool SetOriginInMM(const Vector2D& origin_mm);
virtual Vector2D GetOriginInMM() const;
virtual Vector2D GetOriginInDisplayUnits() const;
/**
\brief Set the size of the display in display units.
This method must be called every time the display is resized (normally, the GUI-toolkit
informs about resizing).
\param keepDisplayedRegion: if \a true (the default), the displayed contents is zoomed/shrinked
so that the displayed region is (approximately) the same as before: The point at the center will
be kept at the center and the length of the diagonal of the displayed region \em in \em units
will also be kept.
When the aspect ration changes, the displayed region includes the old displayed region, but
cannot be exaclty the same.
*/
virtual void SetSizeInDisplayUnits(unsigned int width, unsigned int height, bool keepDisplayedRegion=true);
virtual Vector2D GetSizeInDisplayUnits() const;
virtual Vector2D GetSizeInMM() const;
unsigned int GetDisplayWidth() const;
unsigned int GetDisplayHeight() const;
-
-
-
// zooming, panning, restriction of both
virtual void SetConstrainZoomingAndPanning(bool constrain);
virtual bool GetConstrainZommingAndPanning() const;
/// what percentage of the world should be visible at maximum zoom out (default 1.0, i.e. 100% of width or height)
itkGetMacro(MaxWorldViewPercentage, float);
itkSetMacro(MaxWorldViewPercentage, float);
/// what percentage of the world should be visible at maximum zoom in (default 0.1, i.e. 10% of width or height)
itkGetMacro(MinWorldViewPercentage, float);
itkSetMacro(MinWorldViewPercentage, float);
virtual bool SetScaleFactor(ScalarType mmPerDisplayUnit);
ScalarType GetScaleFactorMMPerDisplayUnit() const;
/**
* \brief Zooms with a factor (1.0=identity) to/from the specified center in display units
* \return true if zoom request was within accepted limits
*/
virtual bool Zoom(ScalarType factor, const Point2D& centerInDisplayUnits);
/**
* \brief Zooms with a factor (1.0=identity) to/from the specified center, trying to preserve the center of zoom in world coordiantes
*
* Same zoom as mentioned above but tries (if it's within view contraints) to match the center in display units with the center in world coordinates.
*
* \return true if zoom request was within accepted limits
*/
virtual bool ZoomWithFixedWorldCoordinates(ScalarType factor, const Point2D& focusDisplayUnits, const Point2D& focusUnitsInMM );
// \return true if move request was within accepted limits
virtual bool MoveBy(const Vector2D& shiftInDisplayUnits);
// \brief align display with world, make world completely visible
virtual void Fit();
-
-
-
// conversion methods
virtual void DisplayToWorld(const Point2D &pt_display, Point2D &pt_mm) const;
virtual void WorldToDisplay(const Point2D &pt_mm, Point2D &pt_display) const;
virtual void DisplayToWorld(const Vector2D &vec_display, Vector2D &vec_mm) const;
virtual void WorldToDisplay(const Vector2D &vec_mm, Vector2D &vec_display) const;
virtual void ULDisplayToMM(const Point2D &pt_ULdisplay, Point2D &pt_mm) const;
virtual void MMToULDisplay(const Point2D &pt_mm, Point2D &pt_ULdisplay) const;
virtual void ULDisplayToMM(const Vector2D &vec_ULdisplay, Vector2D &vec_mm) const;
virtual void MMToULDisplay(const Vector2D &vec_mm, Vector2D &vec_ULdisplay) const;
virtual void ULDisplayToDisplay(const Point2D &pt_ULdisplay, Point2D &pt_display) const;
virtual void DisplayToULDisplay(const Point2D &pt_display, Point2D &pt_ULdisplay) const;
virtual void ULDisplayToDisplay(const Vector2D &vec_ULdisplay, Vector2D &vec_display) const;
virtual void DisplayToULDisplay(const Vector2D &vec_display, Vector2D &vec_ULdisplay) const;
/**
* \brief projects the given point onto current 2D world geometry plane
*/
virtual bool Project(const Point3D &pt3d_mm, Point3D &projectedPt3d_mm) const;
/**
* \brief projects the given vector onto current 2D world geometry plane.
* \warning DEPRECATED, please use Project(const Vector3D &vec3d_mm, Vector3D &projectedVec3d_mm) instead
*/
virtual bool Project(const Point3D & atPt3d_mm, const Vector3D &vec3d_mm, Vector3D &projectedVec3d_mm) const;
/**
* \brief projects the given vector onto current 2D world geometry plane
*/
virtual bool Project(const Vector3D &vec3d_mm, Vector3D &projectedVec3d_mm) const;
virtual bool Map(const Point3D &pt3d_mm, Point2D &pt2d_mm) const;
virtual void Map(const Point2D &pt2d_mm, Point3D &pt3d_mm) const;
virtual bool Map(const Point3D & atPt3d_mm, const Vector3D &vec3d_mm, Vector2D &vec2d_mm) const;
virtual void Map(const Point2D & atPt2d_mm, const Vector2D &vec2d_mm, Vector3D &vec3d_mm) const;
+ virtual bool IsValid() const;
+
+ virtual bool IsAbove( const Point3D &pt3d_mm , bool considerBoundingBox=false) const { return Superclass::IsAbove(pt3d_mm, true);};
+
protected:
DisplayGeometry();
virtual ~DisplayGeometry();
/**
\brief Called after zooming/panning to restrict these operations to sensible measures.
\return true if a correction in either zooming or panning was made
Enforces a couple of constraints on the relation of the current viewport and the current world geometry.
The basic logic in this lengthy method is:
<ol>
<li> Make display region big enough (in case of too large zoom factors)
<li> Make display region small enough (so that the image cannot be scaled into a single screen pixel
<li> Correct panning for each border (left, right, bottom, top)
</ol>
The little more complicated implementation is illustrated in the code itself.
*/
virtual bool RefitVisibleRect();
virtual void PrintSelf(std::ostream& os, itk::Indent indent) const;
Vector2D m_OriginInMM;
Vector2D m_OriginInDisplayUnits;
ScalarType m_ScaleFactorMMPerDisplayUnit;
Vector2D m_SizeInMM;
Vector2D m_SizeInDisplayUnits;
- Geometry2D::ConstPointer m_WorldGeometry;
+ PlaneGeometry::ConstPointer m_WorldGeometry;
bool m_ConstrainZoomingAndPanning;
float m_MaxWorldViewPercentage;
float m_MinWorldViewPercentage;
-};
-
+ };
} // namespace
#endif // include guard
-
diff --git a/Core/Code/DataManagement/mitkGeometry2D.cpp b/Core/Code/DataManagement/mitkGeometry2D.cpp
deleted file mode 100644
index 6f23c91710..0000000000
--- a/Core/Code/DataManagement/mitkGeometry2D.cpp
+++ /dev/null
@@ -1,284 +0,0 @@
-/*===================================================================
-
-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 "mitkGeometry2D.h"
-#include <vtkTransform.h>
-
-
-mitk::Geometry2D::Geometry2D()
- : m_ScaleFactorMMPerUnitX( 1.0 ),
- m_ScaleFactorMMPerUnitY( 1.0 ),
- m_ReferenceGeometry( NULL )
-{
-}
-
-mitk::Geometry2D::Geometry2D(const Geometry2D& other)
- : Geometry3D(other), m_ScaleFactorMMPerUnitX( other.m_ScaleFactorMMPerUnitX),
- m_ScaleFactorMMPerUnitY( other.m_ScaleFactorMMPerUnitY),
- m_ReferenceGeometry( other.m_ReferenceGeometry )
-{
-}
-
-
-
-mitk::Geometry2D::~Geometry2D()
-{
-}
-
-
-void
-mitk::Geometry2D::SetIndexToWorldTransform(
- mitk::AffineTransform3D* transform)
-{
- Superclass::SetIndexToWorldTransform(transform);
-
- m_ScaleFactorMMPerUnitX=GetExtentInMM(0)/GetExtent(0);
- m_ScaleFactorMMPerUnitY=GetExtentInMM(1)/GetExtent(1);
-
- assert(m_ScaleFactorMMPerUnitX<ScalarTypeNumericTraits::infinity());
- assert(m_ScaleFactorMMPerUnitY<ScalarTypeNumericTraits::infinity());
-}
-
-
-void
-mitk::Geometry2D::SetExtentInMM(int direction, ScalarType extentInMM)
-{
- Superclass::SetExtentInMM(direction, extentInMM);
-
- m_ScaleFactorMMPerUnitX=GetExtentInMM(0)/GetExtent(0);
- m_ScaleFactorMMPerUnitY=GetExtentInMM(1)/GetExtent(1);
-
- assert(m_ScaleFactorMMPerUnitX<ScalarTypeNumericTraits::infinity());
- assert(m_ScaleFactorMMPerUnitY<ScalarTypeNumericTraits::infinity());
-}
-
-
-bool
-mitk::Geometry2D::Map(
- const mitk::Point3D &pt3d_mm, mitk::Point2D &pt2d_mm) const
-{
- assert(m_BoundingBox.IsNotNull());
-
- Point3D pt3d_units;
- BackTransform(pt3d_mm, pt3d_units);
- pt2d_mm[0]=pt3d_units[0]*m_ScaleFactorMMPerUnitX;
- pt2d_mm[1]=pt3d_units[1]*m_ScaleFactorMMPerUnitY;
- pt3d_units[2]=0;
- return const_cast<BoundingBox*>(m_BoundingBox.GetPointer())->IsInside(pt3d_units);
-}
-
-
-void
-mitk::Geometry2D::Map(const mitk::Point2D &pt2d_mm, mitk::Point3D &pt3d_mm) const
-{
- Point3D pt3d_units;
- pt3d_units[0]=pt2d_mm[0]/m_ScaleFactorMMPerUnitX;
- pt3d_units[1]=pt2d_mm[1]/m_ScaleFactorMMPerUnitY;
- pt3d_units[2]=0;
- pt3d_mm = GetParametricTransform()->TransformPoint(pt3d_units);
-}
-
-
-void
-mitk::Geometry2D::IndexToWorld(
- const mitk::Point2D &/*pt_units*/, mitk::Point2D &/*pt_mm*/) const
-{
- itkExceptionMacro(<< "No general transform possible (only affine) ==> no general" \
- " IndexToWorld(const mitk::Point2D &pt_mm, mitk::Point2D &pt_units)" \
- " possible. Has to be implemented in sub-class.");
-}
-
-
-void
-mitk::Geometry2D::WorldToIndex(
- const mitk::Point2D &/*pt_mm*/, mitk::Point2D &/*pt_units*/) const
-{
- itkExceptionMacro(<< "No general back transform possible (only affine) ==> no general" \
- " WorldToIndex(const mitk::Point2D &pt_mm, mitk::Point2D &pt_units)" \
- " possible. Has to be implemented in sub-class.");
-}
-
-
-void
-mitk::Geometry2D::IndexToWorld(const mitk::Point2D &/*atPt2d_units*/,
- const mitk::Vector2D &/*vec_units*/, mitk::Vector2D &/*vec_mm*/) const
-{
- itkExceptionMacro(<< "No general transform possible (only affine) ==> no general" \
- " IndexToWorld(const mitk::Vector2D &vec_mm, mitk::Vector2D &vec_units)" \
- " possible. Has to be implemented in sub-class.");
-}
-
-
-void
-mitk::Geometry2D::WorldToIndex(const mitk::Point2D &/*atPt2d_mm*/,
- const mitk::Vector2D &/*vec_mm*/, mitk::Vector2D &/*vec_units*/) const
-{
- itkExceptionMacro(<< "No general back transform possible (only affine) ==> no general" \
- " WorldToIndex(const mitk::Vector2D &vec_mm, mitk::Vector2D &vec_units)" \
- " possible. Has to be implemented in sub-class.");
-}
-
-void
-mitk::Geometry2D::SetSizeInUnits(mitk::ScalarType width, mitk::ScalarType height)
-{
- ScalarType bounds[6]={0, width, 0, height, 0, 1};
- ScalarType extent, newextentInMM;
- if(GetExtent(0)>0)
- {
- extent = GetExtent(0);
- if(width>extent)
- newextentInMM = GetExtentInMM(0)/width*extent;
- else
- newextentInMM = GetExtentInMM(0)*extent/width;
- SetExtentInMM(0, newextentInMM);
- }
- if(GetExtent(1)>0)
- {
- extent = GetExtent(1);
- if(width>extent)
- newextentInMM = GetExtentInMM(1)/height*extent;
- else
- newextentInMM = GetExtentInMM(1)*extent/height;
- SetExtentInMM(1, newextentInMM);
- }
- SetBounds(bounds);
-}
-
-
-bool
-mitk::Geometry2D::Project(
- const mitk::Point3D &pt3d_mm, mitk::Point3D &projectedPt3d_mm) const
-{
- assert(m_BoundingBox.IsNotNull());
-
- Point3D pt3d_units;
- BackTransform(pt3d_mm, pt3d_units);
- pt3d_units[2] = 0;
- projectedPt3d_mm = GetParametricTransform()->TransformPoint(pt3d_units);
- return const_cast<BoundingBox*>(m_BoundingBox.GetPointer())->IsInside(pt3d_units);
-}
-
-bool
-mitk::Geometry2D::Project(const mitk::Vector3D &vec3d_mm, mitk::Vector3D &projectedVec3d_mm) const
-{
- assert(m_BoundingBox.IsNotNull());
-
- Vector3D vec3d_units;
- BackTransform(vec3d_mm, vec3d_units);
- vec3d_units[2] = 0;
- projectedVec3d_mm = GetParametricTransform()->TransformVector(vec3d_units);
- return true;
-}
-
-bool
-mitk::Geometry2D::Project(const mitk::Point3D & atPt3d_mm,
- const mitk::Vector3D &vec3d_mm, mitk::Vector3D &projectedVec3d_mm) const
-{
- MITK_WARN << "Deprecated function! Call Project(vec3D,vec3D) instead.";
- assert(m_BoundingBox.IsNotNull());
-
- Vector3D vec3d_units;
- BackTransform(atPt3d_mm, vec3d_mm, vec3d_units);
- vec3d_units[2] = 0;
- projectedVec3d_mm = GetParametricTransform()->TransformVector(vec3d_units);
-
- Point3D pt3d_units;
- BackTransform(atPt3d_mm, pt3d_units);
- return const_cast<BoundingBox*>(m_BoundingBox.GetPointer())->IsInside(pt3d_units);
-}
-
-
-bool
-mitk::Geometry2D::Map(const mitk::Point3D & atPt3d_mm,
- const mitk::Vector3D &vec3d_mm, mitk::Vector2D &vec2d_mm) const
-{
- Point2D pt2d_mm_start, pt2d_mm_end;
- Point3D pt3d_mm_end;
- bool inside=Map(atPt3d_mm, pt2d_mm_start);
- pt3d_mm_end = atPt3d_mm+vec3d_mm;
- inside&=Map(pt3d_mm_end, pt2d_mm_end);
- vec2d_mm=pt2d_mm_end-pt2d_mm_start;
- return inside;
-}
-
-
-void
-mitk::Geometry2D::Map(const mitk::Point2D &/*atPt2d_mm*/,
- const mitk::Vector2D &/*vec2d_mm*/, mitk::Vector3D &/*vec3d_mm*/) const
-{
- //@todo implement parallel to the other Map method!
- assert(false);
-}
-
-
-mitk::ScalarType
-mitk::Geometry2D::SignedDistance(const mitk::Point3D& pt3d_mm) const
-{
- Point3D projectedPoint;
- Project(pt3d_mm, projectedPoint);
- Vector3D direction = pt3d_mm-projectedPoint;
- ScalarType distance = direction.GetNorm();
-
- if(IsAbove(pt3d_mm) == false)
- distance*=-1.0;
-
- return distance;
-}
-
-bool
-mitk::Geometry2D::IsAbove(const mitk::Point3D& pt3d_mm) const
-{
- Point3D pt3d_units;
- Geometry3D::WorldToIndex(pt3d_mm, pt3d_units);
- return (pt3d_units[2] > m_BoundingBox->GetBounds()[4]);
-}
-
-itk::LightObject::Pointer
-mitk::Geometry2D::InternalClone() const
-{
- Self::Pointer newGeometry = new Geometry2D(*this);
- newGeometry->UnRegister();
- return newGeometry.GetPointer();
-}
-
-void
-mitk::Geometry2D::PrintSelf(std::ostream& os, itk::Indent indent) const
-{
- Superclass::PrintSelf(os,indent);
- os << indent << " ScaleFactorMMPerUnitX: "
- << m_ScaleFactorMMPerUnitX << std::endl;
- os << indent << " ScaleFactorMMPerUnitY: "
- << m_ScaleFactorMMPerUnitY << std::endl;
-}
-
-void
-mitk::Geometry2D::SetReferenceGeometry( mitk::Geometry3D *geometry )
-{
- m_ReferenceGeometry = geometry;
-}
-
-mitk::Geometry3D *
-mitk::Geometry2D::GetReferenceGeometry() const
-{
- return m_ReferenceGeometry;
-}
-
-bool
-mitk::Geometry2D::HasReferenceGeometry() const
-{
- return ( m_ReferenceGeometry != NULL );
-}
diff --git a/Core/Code/DataManagement/mitkGeometry2D.h b/Core/Code/DataManagement/mitkGeometry2D.h
deleted file mode 100644
index 4b5d912522..0000000000
--- a/Core/Code/DataManagement/mitkGeometry2D.h
+++ /dev/null
@@ -1,274 +0,0 @@
-/*===================================================================
-
-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 GEOMETRY2D_H_HEADER_INCLUDED_C1F4D8E0
-#define GEOMETRY2D_H_HEADER_INCLUDED_C1F4D8E0
-
-#include <MitkCoreExports.h>
-#include "mitkGeometry3D.h"
-
-namespace mitk {
-
-/**
- * \brief Describes the geometry of a two-dimensional object
- *
- * Describes a two-dimensional manifold, i.e., to put it simply,
- * an object that can be described using a 2D coordinate-system.
- *
- * Geometry2D can map points between 3D world coordinates
- * (in mm) and the described 2D coordinate-system (in mm) by first projecting
- * the 3D point onto the 2D manifold and then calculating the 2D-coordinates
- * (in mm). These 2D-mm-coordinates can be further converted into
- * 2D-unit-coordinates (e.g., pixels), giving a parameter representation of
- * the object with parameter values inside a rectangle
- * (e.g., [0,0]..[width, height]), which is the bounding box (bounding range
- * in z-direction always [0]..[1]).
- *
- * A Geometry2D describes the 2D representation within a 3D object and is
- * therefore itself a Geometry3D (derived from Geometry3D). For example,
- * a single CT-image (slice) is 2D in the sense that you can access the
- * pixels using 2D-coordinates, but is also 3D, as the pixels are really
- * voxels, thus have an extension (thickness) in the 3rd dimension.
- *
- * Most often, instances of Geometry2D will be used to descibe a plane,
- * which is represented by the sub-class PlaneGeometry, but curved
- * surfaces are also possible.
- *
- * Optionally, a reference Geometry3D can be specified, which usually would
- * be the geometry associated with the underlying dataset. This is currently
- * used for calculating the intersection of inclined / rotated planes
- * (represented as Geometry2D) with the bounding box of the associated
- * Geometry3D.
- *
- * \warning The Geometry2Ds are not necessarily up-to-date and not even
- * initialized. As described in the previous paragraph, one of the
- * Generate-/Copy-/UpdateOutputInformation methods have to initialize it.
- * mitk::BaseData::GetGeometry2D() makes sure, that the Geometry2D is
- * up-to-date before returning it (by setting the update extent appropriately
- * and calling UpdateOutputInformation).
- *
- * Rule: everything is in mm (or ms for temporal information) if not
- * stated otherwise.
- * \ingroup Geometry
- */
-class MITK_CORE_EXPORT Geometry2D : public mitk::Geometry3D
-{
-public:
- mitkClassMacro(Geometry2D, mitk::Geometry3D);
- itkFactorylessNewMacro(Self)
- itkCloneMacro(Self)
-
- /**
- * \brief Project a 3D point given in mm (\a pt3d_mm) onto the 2D
- * geometry. The result is a 2D point in mm (\a pt2d_mm).
- *
- * The result is a 2D point in mm (\a pt2d_mm) relative to the upper-left
- * corner of the geometry. To convert this point into units (e.g., pixels
- * in case of an image), use WorldToIndex.
- * \return true projection was possible
- * \sa Project(const mitk::Point3D &pt3d_mm, mitk::Point3D
- * &projectedPt3d_mm)
- */
- virtual bool Map(const mitk::Point3D &pt3d_mm, mitk::Point2D &pt2d_mm) const;
-
- /**
- * \brief Converts a 2D point given in mm (\a pt2d_mm) relative to the
- * upper-left corner of the geometry into the corresponding
- * world-coordinate (a 3D point in mm, \a pt3d_mm).
- *
- * To convert a 2D point given in units (e.g., pixels in case of an
- * image) into a 2D point given in mm (as required by this method), use
- * IndexToWorld.
- */
- virtual void Map(const mitk::Point2D &pt2d_mm, mitk::Point3D &pt3d_mm) const;
-
- /**
- * \brief Convert a 2D point given in units (e.g., pixels in case of an
- * image) into a 2D point given in mm
- */
- virtual void IndexToWorld(
- const mitk::Point2D &pt_units, mitk::Point2D &pt_mm) const;
-
- /**
- * \brief Convert a 2D point given in mm into a 2D point given in mm
- * (e.g., pixels in case of an image)
- */
- virtual void WorldToIndex(
- const mitk::Point2D &pt_mm, mitk::Point2D &pt_units) const;
-
- /**
- * \brief Convert a 2D vector given in units (e.g., pixels in case of an
- * image) into a 2D vector given in mm
- * \warning strange: in contrast to vtkTransform the class itk::Transform
- * does not have the parameter, \em where the vector that is to be
- * transformed is located. This method here should also need this
- * information for general transforms.
- */
- virtual void IndexToWorld(
- const mitk::Point2D &atPt2d_units, const mitk::Vector2D &vec_units,
- mitk::Vector2D &vec_mm) const;
-
- /**
- * \brief Convert a 2D vector given in mm into a 2D point vector in mm
- * (e.g., pixels in case of an image)
- * \warning strange: in contrast to vtkTransform the class itk::Transform
- * does not have the parameter, \em where the vector that is to be
- * transformed is located. This method here should also need this
- * information for general transforms.
- */
- virtual void WorldToIndex(
- const mitk::Point2D &atPt2d_mm, const mitk::Vector2D &vec_mm,
- mitk::Vector2D &vec_units) const;
-
- /**
- * \brief Set the width and height of this 2D-geometry in units by calling
- * SetBounds. This does \a not change the extent in mm!
- *
- * For an image, this is the number of pixels in x-/y-direction.
- * \note In contrast to calling SetBounds directly, this does \a not change
- * the extent in mm!
- */
- virtual void SetSizeInUnits(mitk::ScalarType width, mitk::ScalarType height);
-
- /**
- * \brief Project a 3D point given in mm (\a pt3d_mm) onto the 2D
- * geometry. The result is a 3D point in mm (\a projectedPt3d_mm).
- *
- * \return true projection was possible
- */
- virtual bool Project(const mitk::Point3D &pt3d_mm,
- mitk::Point3D &projectedPt3d_mm) const;
-
- /**
- * \brief Project a 3D vector given in mm (\a vec3d_mm) onto the 2D
- * geometry. The result is a 2D vector in mm (\a vec2d_mm).
- *
- * The result is a 2D vector in mm (\a vec2d_mm) relative to the
- * upper-left
- * corner of the geometry. To convert this point into units (e.g., pixels
- * in case of an image), use WorldToIndex.
- * \return true projection was possible
- * \sa Project(const mitk::Vector3D &vec3d_mm, mitk::Vector3D
- * &projectedVec3d_mm)
- */
- virtual bool Map(const mitk::Point3D & atPt3d_mm,
- const mitk::Vector3D &vec3d_mm, mitk::Vector2D &vec2d_mm) const;
-
- /**
- * \brief Converts a 2D vector given in mm (\a vec2d_mm) relative to the
- * upper-left corner of the geometry into the corresponding
- * world-coordinate (a 3D vector in mm, \a vec3d_mm).
- *
- * To convert a 2D vector given in units (e.g., pixels in case of an
- * image) into a 2D vector given in mm (as required by this method), use
- * IndexToWorld.
- */
- virtual void Map(const mitk::Point2D & atPt2d_mm,
- const mitk::Vector2D &vec2d_mm, mitk::Vector3D &vec3d_mm) const;
-
- /**
- * \brief Project a 3D vector given in mm (\a vec3d_mm) onto the 2D
- * geometry. The result is a 3D vector in mm (\a projectedVec3d_mm).
- *
- * DEPRECATED. Use Project(vector,vector) instead
- *
- * \return true projection was possible
- */
- virtual bool Project(const mitk::Point3D & atPt3d_mm,
- const mitk::Vector3D &vec3d_mm, mitk::Vector3D &projectedVec3d_mm) const;
-
- /**
- * \brief Project a 3D vector given in mm (\a vec3d_mm) onto the 2D
- * geometry. The result is a 3D vector in mm (\a projectedVec3d_mm).
- *
- * \return true projection was possible
- */
- virtual bool Project( const mitk::Vector3D &vec3d_mm, mitk::Vector3D &projectedVec3d_mm) const;
-
- /**
- * \brief Distance of the point from the geometry
- * (bounding-box \em not considered)
- *
- */
- inline ScalarType Distance(const Point3D& pt3d_mm) const
- {
- return fabs(SignedDistance(pt3d_mm));
- }
-
- /**
- * \brief Signed distance of the point from the geometry
- * (bounding-box \em not considered)
- *
- */
- virtual ScalarType SignedDistance(const Point3D& pt3d_mm) const;
-
- /**
- * \brief Test if the point is above the geometry
- * (bounding-box \em not considered)
- *
- */
- virtual bool IsAbove(const Point3D& pt3d_mm) const;
-
- virtual void SetIndexToWorldTransform(mitk::AffineTransform3D* transform);
-
- virtual void SetExtentInMM(int direction, ScalarType extentInMM);
-
- virtual itk::LightObject::Pointer InternalClone() const;
-
- /**
- * \brief Set the geometrical frame of reference in which this Geometry2D
- * is placed.
- *
- * This would usually be the Geometry3D of the underlying dataset, but
- * setting it is optional.
- */
- void SetReferenceGeometry( mitk::Geometry3D *geometry );
-
- /**
- * \brief Get the geometrical frame of reference for this Geometry2D.
- */
- Geometry3D *GetReferenceGeometry() const;
- bool HasReferenceGeometry() const;
-
-
-protected:
- Geometry2D();
-
- Geometry2D(const Geometry2D& other);
-
- virtual ~Geometry2D();
-
- virtual void PrintSelf(std::ostream& os, itk::Indent indent) const;
-
- /**
- * \brief factor to convert x-coordinates from mm to units and vice versa
- *
- */
- mutable mitk::ScalarType m_ScaleFactorMMPerUnitX;
-
- /**
- * \brief factor to convert y-coordinates from mm to units and vice versa
- *
- */
- mutable mitk::ScalarType m_ScaleFactorMMPerUnitY;
-
- mitk::Geometry3D *m_ReferenceGeometry;
-};
-
-} // namespace mitk
-
-#endif /* GEOMETRY2D_H_HEADER_INCLUDED_C1F4D8E0 */
diff --git a/Core/Code/DataManagement/mitkGeometry2DData.h b/Core/Code/DataManagement/mitkGeometry2DData.h
deleted file mode 100644
index ed1d5e7a17..0000000000
--- a/Core/Code/DataManagement/mitkGeometry2DData.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*===================================================================
-
-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 MITKGEOMETRY2DDATA_H_HEADER_INCLUDED_C19C01E2
-#define MITKGEOMETRY2DDATA_H_HEADER_INCLUDED_C19C01E2
-
-#include <MitkCoreExports.h>
-#include "mitkBaseData.h"
-#include "mitkGeometryData.h"
-#include "mitkGeometry2D.h"
-
-namespace mitk {
-
-//##Documentation
-//## @brief Data class containing Geometry2D objects
-//## @ingroup Geometry
-//##
-class MITK_CORE_EXPORT Geometry2DData : public GeometryData
-{
-public:
- mitkClassMacro(Geometry2DData, GeometryData);
-
- itkFactorylessNewMacro(Self)
- itkCloneMacro(Self)
-
- //##Documentation
- //## @brief Set the reference to a Geometry2D that is stored
- //## by the object
- //##
- //## @warning Accepts only instances of Geometry2D or sub-classes.
- virtual void SetGeometry(mitk::Geometry3D *geometry);
-
- //##Documentation
- //## @brief Set the reference to the Geometry2D that is stored
- //## by the object
- virtual void SetGeometry2D(mitk::Geometry2D* geometry2d);
- //##Documentation
- //## @brief Get the reference to the Geometry2D that is stored
- //## by the object
- virtual mitk::Geometry2D * GetGeometry2D() const
- {
- return static_cast<mitk::Geometry2D *>(GetGeometry());
- };
-
- virtual void UpdateOutputInformation();
-
- virtual void SetRequestedRegionToLargestPossibleRegion();
-
- virtual bool RequestedRegionIsOutsideOfTheBufferedRegion();
-
- virtual bool VerifyRequestedRegion();
-
- virtual void SetRequestedRegion( const itk::DataObject *data);
-
- virtual void CopyInformation(const itk::DataObject *data);
-
-protected:
- Geometry2DData();
-
- virtual ~Geometry2DData();
-};
-
-} // namespace mitk
-#endif /* MITKGEOMETRY2DDATA_H_HEADER_INCLUDED_C19C01E2 */
diff --git a/Core/Code/DataManagement/mitkGeometry3D.cpp b/Core/Code/DataManagement/mitkGeometry3D.cpp
index 70789582b1..50269ca660 100644
--- a/Core/Code/DataManagement/mitkGeometry3D.cpp
+++ b/Core/Code/DataManagement/mitkGeometry3D.cpp
@@ -1,978 +1,48 @@
/*===================================================================
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 <sstream>
#include <iomanip>
#include "mitkGeometry3D.h"
-#include "mitkMatrixConvert.h"
+
#include "mitkRotationOperation.h"
#include "mitkRestorePlanePositionOperation.h"
#include "mitkApplyTransformMatrixOperation.h"
#include "mitkPointOperation.h"
#include "mitkInteractionConst.h"
-
#include <vtkMatrixToLinearTransform.h>
#include <vtkMatrix4x4.h>
+#include "mitkMatrixConvert.h"
// Standard constructor for the New() macro. Sets the geometry to 3 dimensions
-mitk::Geometry3D::Geometry3D()
- : m_ParametricBoundingBox(NULL),
- m_ImageGeometry(false), m_Valid(true), m_FrameOfReferenceID(0), m_IndexToWorldTransformLastModified(0)
+mitk::Geometry3D::Geometry3D() : BaseGeometry()
{
- FillVector3D(m_FloatSpacing, 1,1,1);
- m_VtkMatrix = vtkMatrix4x4::New();
- m_VtkIndexToWorldTransform = vtkMatrixToLinearTransform::New();
- m_VtkIndexToWorldTransform->SetInput(m_VtkMatrix);
- Initialize();
}
-mitk::Geometry3D::Geometry3D(const Geometry3D& other) : Superclass(), mitk::OperationActor(), m_ParametricBoundingBox(other.m_ParametricBoundingBox),m_TimeBounds(other.m_TimeBounds),
- m_ImageGeometry(other.m_ImageGeometry), m_Valid(other.m_Valid), m_FrameOfReferenceID(other.m_FrameOfReferenceID), m_IndexToWorldTransformLastModified(other.m_IndexToWorldTransformLastModified), m_RotationQuaternion( other.m_RotationQuaternion ) , m_Origin(other.m_Origin)
+mitk::Geometry3D::Geometry3D(const Geometry3D& other) : BaseGeometry(other)
{
- // AffineGeometryFrame
- SetBounds(other.GetBounds());
- //SetIndexToObjectTransform(other.GetIndexToObjectTransform());
- //SetObjectToNodeTransform(other.GetObjectToNodeTransform());
- //SetIndexToWorldTransform(other.GetIndexToWorldTransform());
- // this is not used in AffineGeometryFrame of ITK, thus there are not Get and Set methods
- // m_IndexToNodeTransform = other.m_IndexToNodeTransform;
- // m_InvertedTransform = TransformType::New();
- // m_InvertedTransform = TransformType::New();
- // m_InvertedTransform->DeepCopy(other.m_InvertedTransform);
- m_VtkMatrix = vtkMatrix4x4::New();
- m_VtkMatrix->DeepCopy(other.m_VtkMatrix);
- if (other.m_ParametricBoundingBox.IsNotNull())
- {
- m_ParametricBoundingBox = other.m_ParametricBoundingBox->DeepCopy();
- }
- FillVector3D(m_FloatSpacing,other.m_FloatSpacing[0],other.m_FloatSpacing[1],other.m_FloatSpacing[2]);
- m_VtkIndexToWorldTransform = vtkMatrixToLinearTransform::New();
- m_VtkIndexToWorldTransform->DeepCopy(other.m_VtkIndexToWorldTransform);
- m_VtkIndexToWorldTransform->SetInput(m_VtkMatrix);
- other.InitializeGeometry(this);
}
mitk::Geometry3D::~Geometry3D()
{
- m_VtkMatrix->Delete();
- m_VtkIndexToWorldTransform->Delete();
-}
-
-
-static void CopySpacingFromTransform(mitk::AffineTransform3D* transform, mitk::Vector3D& spacing, float floatSpacing[3])
-{
- mitk::AffineTransform3D::MatrixType::InternalMatrixType vnlmatrix;
- vnlmatrix = transform->GetMatrix().GetVnlMatrix();
-
- spacing[0]=vnlmatrix.get_column(0).magnitude();
- spacing[1]=vnlmatrix.get_column(1).magnitude();
- spacing[2]=vnlmatrix.get_column(2).magnitude();
- floatSpacing[0]=spacing[0];
- floatSpacing[1]=spacing[1];
- floatSpacing[2]=spacing[2];
-}
-
-
-void mitk::Geometry3D::Initialize()
-{
- float b[6] = {0,1,0,1,0,1};
- SetFloatBounds(b);
-
- if(m_IndexToWorldTransform.IsNull())
- m_IndexToWorldTransform = TransformType::New();
- else
- m_IndexToWorldTransform->SetIdentity();
- CopySpacingFromTransform(m_IndexToWorldTransform, m_Spacing, m_FloatSpacing);
- vtk2itk(m_IndexToWorldTransform->GetOffset(), m_Origin);
-
- m_VtkMatrix->Identity();
-
- m_TimeBounds[0]=ScalarTypeNumericTraits::NonpositiveMin(); m_TimeBounds[1]=ScalarTypeNumericTraits::max();
-
- m_FrameOfReferenceID = 0;
-
- m_ImageGeometry = false;
-}
-
-void mitk::Geometry3D::TransferItkToVtkTransform()
-{
- // copy m_IndexToWorldTransform into m_VtkIndexToWorldTransform
- TransferItkTransformToVtkMatrix(m_IndexToWorldTransform.GetPointer(), m_VtkMatrix);
- m_VtkIndexToWorldTransform->Modified();
-}
-
-void mitk::Geometry3D::TransferVtkToItkTransform()
-{
- TransferVtkMatrixToItkTransform(m_VtkMatrix, m_IndexToWorldTransform.GetPointer());
- CopySpacingFromTransform(m_IndexToWorldTransform, m_Spacing, m_FloatSpacing);
- vtk2itk(m_IndexToWorldTransform->GetOffset(), m_Origin);
-}
-
-void mitk::Geometry3D::SetIndexToWorldTransformByVtkMatrix(vtkMatrix4x4* vtkmatrix)
-{
- m_VtkMatrix->DeepCopy(vtkmatrix);
- TransferVtkToItkTransform();
-}
-
-void mitk::Geometry3D::SetTimeBounds(const TimeBounds& timebounds)
-{
- if(m_TimeBounds != timebounds)
- {
- m_TimeBounds = timebounds;
- Modified();
- }
-}
-
-void mitk::Geometry3D::SetFloatBounds(const float bounds[6])
-{
- mitk::BoundingBox::BoundsArrayType b;
- const float *input = bounds;
- int i=0;
- for(mitk::BoundingBox::BoundsArrayType::Iterator it = b.Begin(); i < 6 ;++i) *it++ = (mitk::ScalarType)*input++;
- SetBounds(b);
-}
-
-void mitk::Geometry3D::SetFloatBounds(const double bounds[6])
-{
- mitk::BoundingBox::BoundsArrayType b;
- const double *input = bounds;
- int i=0;
- for(mitk::BoundingBox::BoundsArrayType::Iterator it = b.Begin(); i < 6 ;++i) *it++ = (mitk::ScalarType)*input++;
- SetBounds(b);
-}
-
-void mitk::Geometry3D::SetParametricBounds(const BoundingBox::BoundsArrayType& bounds)
-{
- m_ParametricBoundingBox = BoundingBoxType::New();
-
- BoundingBoxType::PointsContainer::Pointer pointscontainer =
- BoundingBoxType::PointsContainer::New();
- BoundingBoxType::PointType p;
- BoundingBoxType::PointIdentifier pointid;
-
- for(pointid=0; pointid<2;++pointid)
- {
- unsigned int i;
- for(i=0; i<NDimensions; ++i)
- {
- p[i] = bounds[2*i+pointid];
- }
- pointscontainer->InsertElement(pointid, p);
- }
-
- m_ParametricBoundingBox->SetPoints(pointscontainer);
- m_ParametricBoundingBox->ComputeBoundingBox();
- this->Modified();
-}
-
-void mitk::Geometry3D::WorldToIndex(const mitk::Point3D &pt_mm, mitk::Point3D &pt_units) const
-{
- BackTransform(pt_mm, pt_units);
-}
-
-void mitk::Geometry3D::IndexToWorld(const mitk::Point3D &pt_units, mitk::Point3D &pt_mm) const
-{
- pt_mm = m_IndexToWorldTransform->TransformPoint(pt_units);
-}
-
-void mitk::Geometry3D::WorldToIndex(const mitk::Point3D & /*atPt3d_mm*/, const mitk::Vector3D &vec_mm, mitk::Vector3D &vec_units) const
-{
- MITK_WARN<<"Warning! Call of the deprecated function Geometry3D::WorldToIndex(point, vec, vec). Use Geometry3D::WorldToIndex(vec, vec) instead!";
- //BackTransform(atPt3d_mm, vec_mm, vec_units);
- this->WorldToIndex(vec_mm, vec_units);
-}
-
-void mitk::Geometry3D::WorldToIndex( const mitk::Vector3D &vec_mm, mitk::Vector3D &vec_units) const
-{
- BackTransform( vec_mm, vec_units);
-}
-
-void mitk::Geometry3D::IndexToWorld(const mitk::Point3D &/*atPt3d_units*/, const mitk::Vector3D &vec_units, mitk::Vector3D &vec_mm) const
-{
- MITK_WARN<<"Warning! Call of the deprecated function Geometry3D::IndexToWorld(point, vec, vec). Use Geometry3D::IndexToWorld(vec, vec) instead!";
- //vec_mm = m_IndexToWorldTransform->TransformVector(vec_units);
- this->IndexToWorld(vec_units, vec_mm);
-}
-
-void mitk::Geometry3D::IndexToWorld(const mitk::Vector3D &vec_units, mitk::Vector3D &vec_mm) const
-{
- vec_mm = m_IndexToWorldTransform->TransformVector(vec_units);
-}
-
-void mitk::Geometry3D::SetIndexToWorldTransform(mitk::AffineTransform3D* transform)
-{
- if(m_IndexToWorldTransform.GetPointer() != transform)
- {
- m_IndexToWorldTransform = transform;
- CopySpacingFromTransform(m_IndexToWorldTransform, m_Spacing, m_FloatSpacing);
- vtk2itk(m_IndexToWorldTransform->GetOffset(), m_Origin);
- TransferItkToVtkTransform();
- Modified();
- }
}
itk::LightObject::Pointer mitk::Geometry3D::InternalClone() const
{
Self::Pointer newGeometry = new Self(*this);
newGeometry->UnRegister();
return newGeometry.GetPointer();
}
-/*
-void mitk::Geometry3D::InitializeGeometry(Geometry3D * newGeometry) const
-{
- Superclass::InitializeGeometry(newGeometry);
-
- newGeometry->SetTimeBounds(m_TimeBounds);
-
- //newGeometry->GetVtkTransform()->SetMatrix(m_VtkIndexToWorldTransform->GetMatrix()); IW
- //newGeometry->TransferVtkToItkTransform(); //MH
-
- newGeometry->SetFrameOfReferenceID(GetFrameOfReferenceID());
- newGeometry->m_ImageGeometry = m_ImageGeometry;
-}
-*/
-void mitk::Geometry3D::SetExtentInMM(int direction, ScalarType extentInMM)
-{
- ScalarType len = GetExtentInMM(direction);
- if(fabs(len - extentInMM)>=mitk::eps)
- {
- AffineTransform3D::MatrixType::InternalMatrixType vnlmatrix;
- vnlmatrix = m_IndexToWorldTransform->GetMatrix().GetVnlMatrix();
- if(len>extentInMM)
- vnlmatrix.set_column(direction, vnlmatrix.get_column(direction)/len*extentInMM);
- else
- vnlmatrix.set_column(direction, vnlmatrix.get_column(direction)*extentInMM/len);
- Matrix3D matrix;
- matrix = vnlmatrix;
- m_IndexToWorldTransform->SetMatrix(matrix);
- Modified();
- }
-}
-
-mitk::BoundingBox::Pointer mitk::Geometry3D::CalculateBoundingBoxRelativeToTransform(const mitk::AffineTransform3D* transform) const
-{
- mitk::BoundingBox::PointsContainer::Pointer pointscontainer=mitk::BoundingBox::PointsContainer::New();
-
- mitk::BoundingBox::PointIdentifier pointid=0;
-
- unsigned char i;
- if(transform!=NULL)
- {
- mitk::AffineTransform3D::Pointer inverse = mitk::AffineTransform3D::New();
- transform->GetInverse(inverse);
- for(i=0; i<8; ++i)
- pointscontainer->InsertElement( pointid++, inverse->TransformPoint( GetCornerPoint(i) ));
- }
- else
- {
- for(i=0; i<8; ++i)
- pointscontainer->InsertElement( pointid++, GetCornerPoint(i) );
- }
-
- mitk::BoundingBox::Pointer result = mitk::BoundingBox::New();
- result->SetPoints(pointscontainer);
- result->ComputeBoundingBox();
-
- return result;
-}
-
-#include <vtkTransform.h>
-void mitk::Geometry3D::ExecuteOperation(Operation* operation)
-{
- vtkTransform *vtktransform = vtkTransform::New();
- vtktransform->SetMatrix(m_VtkMatrix);
- switch (operation->GetOperationType())
- {
- case OpNOTHING:
- break;
- case OpMOVE:
- {
- mitk::PointOperation *pointOp = dynamic_cast<mitk::PointOperation *>(operation);
- if (pointOp == NULL)
- {
- //mitk::StatusBar::GetInstance()->DisplayText("received wrong type of operation!See mitkAffineInteractor.cpp", 10000);
- return;
- }
- mitk::Point3D newPos = pointOp->GetPoint();
- ScalarType data[3];
- vtktransform->GetPosition(data);
- vtktransform->PostMultiply();
- vtktransform->Translate(newPos[0], newPos[1], newPos[2]);
- vtktransform->PreMultiply();
- break;
- }
- case OpSCALE:
- {
- mitk::PointOperation *pointOp = dynamic_cast<mitk::PointOperation *>(operation);
- if (pointOp == NULL)
- {
- //mitk::StatusBar::GetInstance()->DisplayText("received wrong type of operation!See mitkAffineInteractor.cpp", 10000);
- return;
- }
- mitk::Point3D newScale = pointOp->GetPoint();
- ScalarType data[3];
- /* calculate new scale: newscale = oldscale * (oldscale + scaletoadd)/oldscale */
- data[0] = 1 + (newScale[0] / GetMatrixColumn(0).magnitude());
- data[1] = 1 + (newScale[1] / GetMatrixColumn(1).magnitude());
- data[2] = 1 + (newScale[2] / GetMatrixColumn(2).magnitude());
-
- mitk::Point3D center = const_cast<mitk::BoundingBox*>(m_BoundingBox.GetPointer())->GetCenter();
- ScalarType pos[3];
- vtktransform->GetPosition(pos);
- vtktransform->PostMultiply();
- vtktransform->Translate(-pos[0], -pos[1], -pos[2]);
- vtktransform->Translate(-center[0], -center[1], -center[2]);
- vtktransform->PreMultiply();
- vtktransform->Scale(data[0], data[1], data[2]);
- vtktransform->PostMultiply();
- vtktransform->Translate(+center[0], +center[1], +center[2]);
- vtktransform->Translate(pos[0], pos[1], pos[2]);
- vtktransform->PreMultiply();
- break;
- }
- case OpROTATE:
- {
- mitk::RotationOperation *rotateOp = dynamic_cast<mitk::RotationOperation *>(operation);
- if (rotateOp == NULL)
- {
- //mitk::StatusBar::GetInstance()->DisplayText("received wrong type of operation!See mitkAffineInteractor.cpp", 10000);
- return;
- }
- Vector3D rotationVector = rotateOp->GetVectorOfRotation();
- Point3D center = rotateOp->GetCenterOfRotation();
- ScalarType angle = rotateOp->GetAngleOfRotation();
- vtktransform->PostMultiply();
- vtktransform->Translate(-center[0], -center[1], -center[2]);
- vtktransform->RotateWXYZ(angle, rotationVector[0], rotationVector[1], rotationVector[2]);
- vtktransform->Translate(center[0], center[1], center[2]);
- vtktransform->PreMultiply();
- break;
- }
- case OpRESTOREPLANEPOSITION:
- {
- //Copy necessary to avoid vtk warning
- vtkMatrix4x4* matrix = vtkMatrix4x4::New();
- TransferItkTransformToVtkMatrix(dynamic_cast<mitk::RestorePlanePositionOperation*>(operation)->GetTransform().GetPointer(), matrix);
- vtktransform->SetMatrix(matrix);
- break;
- }
- case OpAPPLYTRANSFORMMATRIX:
- {
- ApplyTransformMatrixOperation *applyMatrixOp = dynamic_cast< ApplyTransformMatrixOperation* >( operation );
- vtktransform->SetMatrix(applyMatrixOp->GetMatrix());
- break;
- }
- default:
- vtktransform->Delete();
- return;
- }
- m_VtkMatrix->DeepCopy(vtktransform->GetMatrix());
- TransferVtkToItkTransform();
- Modified();
- vtktransform->Delete();
-}
-
-void mitk::Geometry3D::BackTransform(const mitk::Point3D &in, mitk::Point3D& out) const
-{
- ScalarType temp[3];
- unsigned int i, j;
- const TransformType::OffsetType& offset = m_IndexToWorldTransform->GetOffset();
-
- // Remove offset
- for (j = 0; j < 3; j++)
- {
- temp[j] = in[j] - offset[j];
- }
-
- // Get WorldToIndex transform
- if (m_IndexToWorldTransformLastModified != m_IndexToWorldTransform->GetMTime())
- {
- m_InvertedTransform = TransformType::New();
- if (!m_IndexToWorldTransform->GetInverse( m_InvertedTransform.GetPointer() ))
- {
- itkExceptionMacro( "Internal ITK matrix inversion error, cannot proceed." );
- }
- m_IndexToWorldTransformLastModified = m_IndexToWorldTransform->GetMTime();
- }
-
- // Check for valid matrix inversion
- const TransformType::MatrixType& inverse = m_InvertedTransform->GetMatrix();
- if(inverse.GetVnlMatrix().has_nans())
- {
- itkExceptionMacro( "Internal ITK matrix inversion error, cannot proceed. Matrix was: " << std::endl
- << m_IndexToWorldTransform->GetMatrix() << "Suggested inverted matrix is:" << std::endl
- << inverse );
- }
-
- // Transform point
- for (i = 0; i < 3; i++)
- {
- out[i] = 0.0;
- for (j = 0; j < 3; j++)
- {
- out[i] += inverse[i][j]*temp[j];
- }
- }
-}
-
-void mitk::Geometry3D::BackTransform(const mitk::Point3D &/*at*/, const mitk::Vector3D &in, mitk::Vector3D& out) const
-{
- MITK_INFO<<"Warning! Call of the deprecated function Geometry3D::BackTransform(point, vec, vec). Use Geometry3D::BackTransform(vec, vec) instead!";
- //// Get WorldToIndex transform
- //if (m_IndexToWorldTransformLastModified != m_IndexToWorldTransform->GetMTime())
- //{
- // m_InvertedTransform = TransformType::New();
- // if (!m_IndexToWorldTransform->GetInverse( m_InvertedTransform.GetPointer() ))
- // {
- // itkExceptionMacro( "Internal ITK matrix inversion error, cannot proceed." );
- // }
- // m_IndexToWorldTransformLastModified = m_IndexToWorldTransform->GetMTime();
- //}
-
- //// Check for valid matrix inversion
- //const TransformType::MatrixType& inverse = m_InvertedTransform->GetMatrix();
- //if(inverse.GetVnlMatrix().has_nans())
- //{
- // itkExceptionMacro( "Internal ITK matrix inversion error, cannot proceed. Matrix was: " << std::endl
- // << m_IndexToWorldTransform->GetMatrix() << "Suggested inverted matrix is:" << std::endl
- // << inverse );
- //}
-
- //// Transform vector
- //for (unsigned int i = 0; i < 3; i++)
- //{
- // out[i] = 0.0;
- // for (unsigned int j = 0; j < 3; j++)
- // {
- // out[i] += inverse[i][j]*in[j];
- // }
- //}
- this->BackTransform(in, out);
-}
-
-void mitk::Geometry3D::BackTransform(const mitk::Vector3D& in, mitk::Vector3D& out) const
-{
- // Get WorldToIndex transform
- if (m_IndexToWorldTransformLastModified != m_IndexToWorldTransform->GetMTime())
- {
- m_InvertedTransform = TransformType::New();
- if (!m_IndexToWorldTransform->GetInverse( m_InvertedTransform.GetPointer() ))
- {
- itkExceptionMacro( "Internal ITK matrix inversion error, cannot proceed." );
- }
- m_IndexToWorldTransformLastModified = m_IndexToWorldTransform->GetMTime();
- }
-
- // Check for valid matrix inversion
- const TransformType::MatrixType& inverse = m_InvertedTransform->GetMatrix();
- if(inverse.GetVnlMatrix().has_nans())
- {
- itkExceptionMacro( "Internal ITK matrix inversion error, cannot proceed. Matrix was: " << std::endl
- << m_IndexToWorldTransform->GetMatrix() << "Suggested inverted matrix is:" << std::endl
- << inverse );
- }
-
- // Transform vector
- for (unsigned int i = 0; i < 3; i++)
- {
- out[i] = 0.0;
- for (unsigned int j = 0; j < 3; j++)
- {
- out[i] += inverse[i][j]*in[j];
- }
- }
-}
-
-const float* mitk::Geometry3D::GetFloatSpacing() const
-{
- return m_FloatSpacing;
-}
-
-void mitk::Geometry3D::SetSpacing(const mitk::Vector3D& aSpacing)
-{
- if(mitk::Equal(m_Spacing, aSpacing) == false)
- {
- assert(aSpacing[0]>0 && aSpacing[1]>0 && aSpacing[2]>0);
-
- m_Spacing = aSpacing;
-
- AffineTransform3D::MatrixType::InternalMatrixType vnlmatrix;
-
- vnlmatrix = m_IndexToWorldTransform->GetMatrix().GetVnlMatrix();
-
- mitk::VnlVector col;
- col = vnlmatrix.get_column(0); col.normalize(); col*=aSpacing[0]; vnlmatrix.set_column(0, col);
- col = vnlmatrix.get_column(1); col.normalize(); col*=aSpacing[1]; vnlmatrix.set_column(1, col);
- col = vnlmatrix.get_column(2); col.normalize(); col*=aSpacing[2]; vnlmatrix.set_column(2, col);
-
- Matrix3D matrix;
- matrix = vnlmatrix;
-
- AffineTransform3D::Pointer transform = AffineTransform3D::New();
- transform->SetMatrix(matrix);
- transform->SetOffset(m_IndexToWorldTransform->GetOffset());
-
- SetIndexToWorldTransform(transform.GetPointer());
-
- itk2vtk(m_Spacing, m_FloatSpacing);
- }
-}
-
-void mitk::Geometry3D::SetOrigin(const Point3D & origin)
-{
- if(origin!=GetOrigin())
- {
- m_Origin = origin;
- m_IndexToWorldTransform->SetOffset(m_Origin.GetVectorFromOrigin());
- Modified();
- TransferItkToVtkTransform();
- }
-}
-
-void mitk::Geometry3D::Translate(const Vector3D & vector)
-{
- if((vector[0] != 0) || (vector[1] != 0) || (vector[2] != 0))
- {
- this->SetOrigin(m_Origin + vector);
-// m_IndexToWorldTransform->SetOffset(m_IndexToWorldTransform->GetOffset()+vector);
-// TransferItkToVtkTransform();
-// Modified();
- }
-}
-
-void mitk::Geometry3D::SetIdentity()
-{
- m_IndexToWorldTransform->SetIdentity();
- m_Origin.Fill(0);
- Modified();
- TransferItkToVtkTransform();
-}
-
-void mitk::Geometry3D::Compose( const mitk::Geometry3D::TransformType * other, bool pre )
-{
- m_IndexToWorldTransform->Compose(other, pre);
- CopySpacingFromTransform(m_IndexToWorldTransform, m_Spacing, m_FloatSpacing);
- vtk2itk(m_IndexToWorldTransform->GetOffset(), m_Origin);
- Modified();
- TransferItkToVtkTransform();
-}
-
-void mitk::Geometry3D::Compose( const vtkMatrix4x4 * vtkmatrix, bool pre )
-{
- mitk::Geometry3D::TransformType::Pointer itkTransform = mitk::Geometry3D::TransformType::New();
- TransferVtkMatrixToItkTransform(vtkmatrix, itkTransform.GetPointer());
- Compose(itkTransform, pre);
-}
-
-const std::string mitk::Geometry3D::GetTransformAsString( TransformType* transformType )
-{
- std::ostringstream out;
-
- out << '[';
-
- for( int i=0; i<3; ++i )
- {
- out << '[';
- for( int j=0; j<3; ++j )
- out << transformType->GetMatrix().GetVnlMatrix().get(i, j) << ' ';
- out << ']';
- }
-
- out << "][";
-
- for( int i=0; i<3; ++i )
- out << transformType->GetOffset()[i] << ' ';
-
- out << "]\0";
-
- return out.str();
-}
-
-void mitk::Geometry3D::PrintSelf(std::ostream& os, itk::Indent indent) const
-{
- os << indent << " IndexToWorldTransform: ";
- if(m_IndexToWorldTransform.IsNull())
- os << "NULL" << std::endl;
- else
- {
- // from itk::MatrixOffsetTransformBase
- unsigned int i, j;
- os << std::endl;
- os << indent << "Matrix: " << std::endl;
- for (i = 0; i < 3; i++)
- {
- os << indent.GetNextIndent();
- for (j = 0; j < 3; j++)
- {
- os << m_IndexToWorldTransform->GetMatrix()[i][j] << " ";
- }
- os << std::endl;
- }
-
- os << indent << "Offset: " << m_IndexToWorldTransform->GetOffset() << std::endl;
- os << indent << "Center: " << m_IndexToWorldTransform->GetCenter() << std::endl;
- os << indent << "Translation: " << m_IndexToWorldTransform->GetTranslation() << std::endl;
-
- os << indent << "Inverse: " << std::endl;
- for (i = 0; i < 3; i++)
- {
- os << indent.GetNextIndent();
- for (j = 0; j < 3; j++)
- {
- os << m_IndexToWorldTransform->GetInverseMatrix()[i][j] << " ";
- }
- os << std::endl;
- }
-
- // from itk::ScalableAffineTransform
- os << indent << "Scale : ";
- for (i = 0; i < 3; i++)
- {
- os << m_IndexToWorldTransform->GetScale()[i] << " ";
- }
- os << std::endl;
- }
-
- os << indent << " BoundingBox: ";
- if(m_BoundingBox.IsNull())
- os << "NULL" << std::endl;
- else
- {
- os << indent << "( ";
- for (unsigned int i=0; i<3; i++)
- {
- os << m_BoundingBox->GetBounds()[2*i] << "," << m_BoundingBox->GetBounds()[2*i+1] << " ";
- }
- os << " )" << std::endl;
- }
-
- os << indent << " Origin: " << m_Origin << std::endl;
- os << indent << " ImageGeometry: " << m_ImageGeometry << std::endl;
- os << indent << " Spacing: " << m_Spacing << std::endl;
- os << indent << " TimeBounds: " << m_TimeBounds << std::endl;
-}
-
-mitk::Point3D mitk::Geometry3D::GetCornerPoint(int id) const
-{
- assert(id >= 0);
- assert(m_BoundingBox.IsNotNull());
-
- BoundingBox::BoundsArrayType bounds = m_BoundingBox->GetBounds();
-
- Point3D cornerpoint;
- switch(id)
- {
- case 0: FillVector3D(cornerpoint, bounds[0],bounds[2],bounds[4]); break;
- case 1: FillVector3D(cornerpoint, bounds[0],bounds[2],bounds[5]); break;
- case 2: FillVector3D(cornerpoint, bounds[0],bounds[3],bounds[4]); break;
- case 3: FillVector3D(cornerpoint, bounds[0],bounds[3],bounds[5]); break;
- case 4: FillVector3D(cornerpoint, bounds[1],bounds[2],bounds[4]); break;
- case 5: FillVector3D(cornerpoint, bounds[1],bounds[2],bounds[5]); break;
- case 6: FillVector3D(cornerpoint, bounds[1],bounds[3],bounds[4]); break;
- case 7: FillVector3D(cornerpoint, bounds[1],bounds[3],bounds[5]); break;
- default:
- {
- itkExceptionMacro(<<"A cube only has 8 corners. These are labeled 0-7.");
- }
- }
- if(m_ImageGeometry)
- {
- // Here i have to adjust the 0.5 offset manually, because the cornerpoint is the corner of the
- // bounding box. The bounding box itself is no image, so it is corner-based
- FillVector3D(cornerpoint, cornerpoint[0]-0.5, cornerpoint[1]-0.5, cornerpoint[2]-0.5);
- }
- return m_IndexToWorldTransform->TransformPoint(cornerpoint);
-}
-
-mitk::Point3D mitk::Geometry3D::GetCornerPoint(bool xFront, bool yFront, bool zFront) const
-{
- assert(m_BoundingBox.IsNotNull());
- BoundingBox::BoundsArrayType bounds = m_BoundingBox->GetBounds();
-
- Point3D cornerpoint;
- cornerpoint[0] = (xFront ? bounds[0] : bounds[1]);
- cornerpoint[1] = (yFront ? bounds[2] : bounds[3]);
- cornerpoint[2] = (zFront ? bounds[4] : bounds[5]);
- if(m_ImageGeometry)
- {
- // Here i have to adjust the 0.5 offset manually, because the cornerpoint is the corner of the
- // bounding box. The bounding box itself is no image, so it is corner-based
- FillVector3D(cornerpoint, cornerpoint[0]-0.5, cornerpoint[1]-0.5, cornerpoint[2]-0.5);
- }
-
- return m_IndexToWorldTransform->TransformPoint(cornerpoint);
-}
-
-void
-mitk::Geometry3D::ResetSubTransforms()
-{
-}
-
-void
-mitk::Geometry3D::ChangeImageGeometryConsideringOriginOffset( const bool isAnImageGeometry )
-{
- // If Geometry is switched to ImageGeometry, you have to put an offset to the origin, because
- // imageGeometries origins are pixel-center-based
- // ... and remove the offset, if you switch an imageGeometry back to a normal geometry
- // For more information please see the Geometry documentation page
-
- if(m_ImageGeometry == isAnImageGeometry)
- return;
-
- const BoundingBox::BoundsArrayType& boundsarray =
- this->GetBoundingBox()->GetBounds();
-
- Point3D originIndex;
- FillVector3D(originIndex, boundsarray[0], boundsarray[2], boundsarray[4]);
-
- if(isAnImageGeometry == true)
- FillVector3D( originIndex,
- originIndex[0] + 0.5,
- originIndex[1] + 0.5,
- originIndex[2] + 0.5 );
- else
- FillVector3D( originIndex,
- originIndex[0] - 0.5,
- originIndex[1] - 0.5,
- originIndex[2] - 0.5 );
-
- Point3D originWorld;
-
- originWorld = GetIndexToWorldTransform()
- ->TransformPoint( originIndex );
- // instead could as well call IndexToWorld(originIndex,originWorld);
-
- SetOrigin(originWorld);
-
- this->SetImageGeometry(isAnImageGeometry);
-}
-
-bool mitk::Geometry3D::Is2DConvertable()
-{
- bool isConvertableWithoutLoss = true;
- do
- {
- if (this->GetSpacing()[2] != 1)
- {
- isConvertableWithoutLoss = false;
- break;
- }
- if (this->GetOrigin()[2] != 0)
- {
- isConvertableWithoutLoss = false;
- break;
- }
- mitk::Vector3D col0, col1, col2;
- col0.SetVnlVector(this->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(0));
- col1.SetVnlVector(this->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(1));
- col2.SetVnlVector(this->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(2));
-
- if ((col0[2] != 0) || (col1[2] != 0) || (col2[0] != 0) || (col2[1] != 0) || (col2[2] != 1))
- {
- isConvertableWithoutLoss = false;
- break;
- }
- } while (0);
-
- return isConvertableWithoutLoss;
-}
-
-bool mitk::Equal( const mitk::Geometry3D::BoundingBoxType *leftHandSide, const mitk::Geometry3D::BoundingBoxType *rightHandSide, ScalarType eps, bool verbose )
-{
- if(( leftHandSide == NULL) || ( rightHandSide == NULL ))
- {
- MITK_ERROR << "mitk::Equal( const mitk::Geometry3D::BoundingBoxType *leftHandSide, const mitk::Geometry3D::BoundingBoxType *rightHandSide, ScalarType eps, bool verbose ) does not with NULL pointer input.";
- return false;
- }
- return Equal( *leftHandSide, *rightHandSide, eps, verbose);
-}
-
-bool mitk::Equal( const mitk::Geometry3D::BoundingBoxType& leftHandSide, const mitk::Geometry3D::BoundingBoxType& rightHandSide, ScalarType eps, bool verbose )
-{
- bool result = true;
-
- Geometry3D::BoundsArrayType rightBounds = rightHandSide.GetBounds();
- Geometry3D::BoundsArrayType leftBounds = leftHandSide.GetBounds();
- Geometry3D::BoundsArrayType::Iterator itLeft = leftBounds.Begin();
- for( Geometry3D::BoundsArrayType::Iterator itRight = rightBounds.Begin(); itRight != rightBounds.End(); ++itRight)
- {
- if(( !mitk::Equal( *itLeft, *itRight, eps )) )
- {
- if(verbose)
- {
- MITK_INFO << "[( Geometry3D::BoundingBoxType )] bounds are not equal.";
- MITK_INFO << "rightHandSide is " << setprecision(12) << *itRight << " : leftHandSide is " << *itLeft << " and tolerance is " << eps;
- }
- result = false;
- }
- itLeft++;
- }
- return result;
-}
-
-bool mitk::Equal(const mitk::Geometry3D *leftHandSide, const mitk::Geometry3D *rightHandSide, ScalarType eps, bool verbose)
-{
- if(( leftHandSide == NULL) || ( rightHandSide == NULL ))
- {
- MITK_ERROR << "mitk::Equal(const mitk::Geometry3D *leftHandSide, const mitk::Geometry3D *rightHandSide, ScalarType eps, bool verbose) does not with NULL pointer input.";
- return false;
- }
- return Equal( *leftHandSide, *rightHandSide, eps, verbose);
-}
-
-bool mitk::Equal(const mitk::Geometry3D& leftHandSide, const mitk::Geometry3D& rightHandSide, ScalarType eps, bool verbose)
-{
- bool result = true;
-
- //Compare spacings
- if( !mitk::Equal( leftHandSide.GetSpacing(), rightHandSide.GetSpacing(), eps ) )
- {
- if(verbose)
- {
- MITK_INFO << "[( Geometry3D )] Spacing differs.";
- MITK_INFO << "rightHandSide is " << setprecision(12) << rightHandSide.GetSpacing() << " : leftHandSide is " << leftHandSide.GetSpacing() << " and tolerance is " << eps;
- }
- result = false;
- }
-
- //Compare Origins
- if( !mitk::Equal( leftHandSide.GetOrigin(), rightHandSide.GetOrigin(), eps ) )
- {
- if(verbose)
- {
- MITK_INFO << "[( Geometry3D )] Origin differs.";
- MITK_INFO << "rightHandSide is " << setprecision(12) << rightHandSide.GetOrigin() << " : leftHandSide is " << leftHandSide.GetOrigin() << " and tolerance is " << eps;
- }
- result = false;
- }
-
- //Compare Axis and Extents
- for( unsigned int i=0; i<3; ++i)
- {
- if( !mitk::Equal( leftHandSide.GetAxisVector(i), rightHandSide.GetAxisVector(i), eps))
- {
- if(verbose)
- {
- MITK_INFO << "[( Geometry3D )] AxisVector #" << i << " differ";
- MITK_INFO << "rightHandSide is " << setprecision(12) << rightHandSide.GetAxisVector(i) << " : leftHandSide is " << leftHandSide.GetAxisVector(i) << " and tolerance is " << eps;
- }
- result = false;
- }
-
- if( !mitk::Equal( leftHandSide.GetExtent(i), rightHandSide.GetExtent(i), eps) )
- {
- if(verbose)
- {
- MITK_INFO << "[( Geometry3D )] Extent #" << i << " differ";
- MITK_INFO << "rightHandSide is " << setprecision(12) << rightHandSide.GetExtent(i) << " : leftHandSide is " << leftHandSide.GetExtent(i) << " and tolerance is " << eps;
- }
- result = false;
- }
- }
-
- //Compare ImageGeometry Flag
- if( rightHandSide.GetImageGeometry() != leftHandSide.GetImageGeometry() )
- {
- if(verbose)
- {
- MITK_INFO << "[( Geometry3D )] GetImageGeometry is different.";
- MITK_INFO << "rightHandSide is " << rightHandSide.GetImageGeometry() << " : leftHandSide is " << leftHandSide.GetImageGeometry();
- }
- result = false;
- }
-
- //Compare BoundingBoxes
- if( !mitk::Equal( *leftHandSide.GetBoundingBox(), *rightHandSide.GetBoundingBox(), eps, verbose) )
- {
- result = false;
- }
-
- //Compare IndexToWorldTransform Matrix
- if( !mitk::Equal( *leftHandSide.GetIndexToWorldTransform(), *rightHandSide.GetIndexToWorldTransform(), eps, verbose) )
- {
- result = false;
- }
- return result;
-}
-
-bool mitk::Equal(const Geometry3D::TransformType *leftHandSide, const Geometry3D::TransformType *rightHandSide, ScalarType eps, bool verbose )
-{
- if(( leftHandSide == NULL) || ( rightHandSide == NULL ))
- {
- MITK_ERROR << "mitk::Equal(const Geometry3D::TransformType *leftHandSide, const Geometry3D::TransformType *rightHandSide, ScalarType eps, bool verbose ) does not with NULL pointer input.";
- return false;
- }
- return Equal( *leftHandSide, *rightHandSide, eps, verbose);
-}
-
-bool mitk::Equal(const Geometry3D::TransformType& leftHandSide, const Geometry3D::TransformType& rightHandSide, ScalarType eps, bool verbose )
-{
- //Compare IndexToWorldTransform Matrix
- if( !mitk::MatrixEqualElementWise( leftHandSide.GetMatrix(),
- rightHandSide.GetMatrix() ) )
- {
- if(verbose)
- {
- MITK_INFO << "[( Geometry3D::TransformType )] Index to World Transformation matrix differs.";
- MITK_INFO << "rightHandSide is " << setprecision(12) << rightHandSide.GetMatrix() << " : leftHandSide is " << leftHandSide.GetMatrix() << " and tolerance is " << eps;
- }
- return false;
- }
- return true;
-}
-
-/** Initialize the geometry */
-void
-mitk::Geometry3D::InitializeGeometry(Geometry3D* newGeometry) const
-{
- newGeometry->SetBounds(m_BoundingBox->GetBounds());
- // we have to create a new transform!!
-
- if(m_IndexToWorldTransform)
- {
- TransformType::Pointer indexToWorldTransform = TransformType::New();
- indexToWorldTransform->SetCenter( m_IndexToWorldTransform->GetCenter() );
- indexToWorldTransform->SetMatrix( m_IndexToWorldTransform->GetMatrix() );
- indexToWorldTransform->SetOffset( m_IndexToWorldTransform->GetOffset() );
- newGeometry->SetIndexToWorldTransform(indexToWorldTransform);
- }
-}
-
-/** Set the bounds */
-void mitk::Geometry3D::SetBounds(const BoundsArrayType& bounds)
-{
- m_BoundingBox = BoundingBoxType::New();
-
- BoundingBoxType::PointsContainer::Pointer pointscontainer =
- BoundingBoxType::PointsContainer::New();
- BoundingBoxType::PointType p;
- BoundingBoxType::PointIdentifier pointid;
-
- for(pointid=0; pointid<2;++pointid)
- {
- unsigned int i;
- for(i=0; i<NDimensions; ++i)
- {
- p[i] = bounds[2*i+pointid];
- }
- pointscontainer->InsertElement(pointid, p);
- }
-
- m_BoundingBox->SetPoints(pointscontainer);
- m_BoundingBox->ComputeBoundingBox();
- this->Modified();
-}
diff --git a/Core/Code/DataManagement/mitkGeometry3D.h b/Core/Code/DataManagement/mitkGeometry3D.h
index 0cfc5a2ac0..8d25585968 100644
--- a/Core/Code/DataManagement/mitkGeometry3D.h
+++ b/Core/Code/DataManagement/mitkGeometry3D.h
@@ -1,826 +1,72 @@
/*===================================================================
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 GEOMETRY3D_H_HEADER_INCLUDED_C1EBD0AD
#define GEOMETRY3D_H_HEADER_INCLUDED_C1EBD0AD
#include <MitkCoreExports.h>
#include <mitkCommon.h>
-#include "mitkVector.h"
-#include "mitkOperationActor.h"
-#include <itkIndex.h>
-#include <itkBoundingBox.h>
-#include <itkQuaternionRigidTransform.h>
-#include <itkAffineGeometryFrame.h>
#include "itkScalableAffineTransform.h"
-#include "itkBoundingBox.h"
+#include <itkIndex.h>
+
+#include "mitkBaseGeometry.h"
class vtkLinearTransform;
-class vtkMatrixToLinearTransform;
-class vtkMatrix4x4;
namespace mitk {
- //##Documentation
- //## @brief Standard 3D-BoundingBox typedef
- //##
- //## Standard 3D-BoundingBox typedef to get rid of template arguments (3D, type).
- typedef itk::BoundingBox<unsigned long, 3, ScalarType> BoundingBox;
-
- //##Documentation
- //## @brief Standard typedef for time-bounds
- typedef itk::FixedArray<ScalarType,2> TimeBounds;
- typedef itk::FixedArray<ScalarType, 3> FixedArrayType;
-
- typedef itk::AffineGeometryFrame<ScalarType, 3> AffineGeometryFrame3D;
-
- //##Documentation
- //## @brief Describes the geometry of a data object
- //##
- //## At least, it can return the bounding box of the data object.
- //##
- //## The class holds
- //## \li a bounding box which is axes-parallel in intrinsic coordinates
- //## (often integer indices of pixels), to be accessed by
- //## GetBoundingBox()
- //## \li a transform to convert intrinsic coordinates into a
- //## world-coordinate system with coordinates in millimeters
- //## and milliseconds (all are floating point values), to
- //## be accessed by GetIndexToWorldTransform()
- //## \li a life span, i.e. a bounding box in time in ms (with
- //## start and end time), to be accessed by GetTimeBounds().
- //## The default is minus infinity to plus infinity.
- //##
- //## Geometry3D and its sub-classes allow converting between
- //## intrinsic coordinates (called index or unit coordinates)
- //## and world-coordinates (called world or mm coordinates),
- //## e.g. WorldToIndex.
- //## In case you need integer index coordinates, provide an
- //## mitk::Index3D (or itk::Index) as target variable to
- //## WorldToIndex, otherwise you will get a continuous index
- //## (floating point values).
- //##
- //## An important sub-class is SlicedGeometry3D, which descibes
- //## data objects consisting of slices, e.g., objects of type Image.
- //## Conversions between world coordinates (in mm) and unit coordinates
- //## (e.g., pixels in the case of an Image) can be performed.
- //##
- //## For more information on related classes, see \ref Geometry.
- //##
- //## Geometry3D instances referring to an Image need a slightly
- //## different definition of corners, see SetImageGeometry. This
- //## is usualy automatically called by Image.
- //##
- //## Geometry3D have to be initialized in the method GenerateOutputInformation()
- //## of BaseProcess (or CopyInformation/ UpdateOutputInformation of BaseData,
- //## if possible, e.g., by analyzing pic tags in Image) subclasses. See also
- //## itk::ProcessObject::GenerateOutputInformation(),
- //## itk::DataObject::CopyInformation() and
- //## itk::DataObject::UpdateOutputInformation().
- //##
- //## Rule: everything is in mm (ms) if not stated otherwise.
- //## @ingroup Geometry
- class MITK_CORE_EXPORT Geometry3D : public itk::Object, public OperationActor
- {
- public:
- mitkClassMacro(Geometry3D, itk::Object);
-
- typedef itk::QuaternionRigidTransform< ScalarType > QuaternionTransformType;
- typedef QuaternionTransformType::VnlQuaternionType VnlQuaternionType;
-
- /** Method for creation through the object factory. */
- itkFactorylessNewMacro(Self)
- itkCloneMacro(Self)
-
- typedef itk::ScalableAffineTransform<ScalarType, 3> TransformType;
- typedef itk::BoundingBox<unsigned long, 3, ScalarType> BoundingBoxType;
- typedef BoundingBoxType::BoundsArrayType BoundsArrayType;
- typedef BoundingBoxType::Pointer BoundingBoxPointer;
-
- // a bit of a misuse, but we want only doxygen to see the following:
-#ifdef DOXYGEN_SKIP
- //##Documentation
- //## @brief Get the transformation used to convert from index
- //## to world coordinates
- itkGetObjectMacro(IndexToWorldTransform, AffineTransform3D);
-#endif
- //## @brief Set the transformation used to convert from index
- //## to world coordinates
- virtual void SetIndexToWorldTransform(mitk::AffineTransform3D* transform);
- //##Documentation
- //## @brief Convenience method for setting the ITK transform
- //## (m_IndexToWorldTransform) via an vtkMatrix4x4
- //## \sa SetIndexToWorldTransform
- virtual void SetIndexToWorldTransformByVtkMatrix(vtkMatrix4x4* vtkmatrix);
-
-#ifdef DOXYGEN_SKIP
- //##Documentation
- //## @brief Get bounding box (in index/unit coordinates)
- itkGetConstObjectMacro(BoundingBox, BoundingBoxType);
- //##Documentation
- //## @brief Get bounding box (in index/unit coordinates) as a BoundsArrayType
- const BoundsArrayType GetBounds() const
- {
- assert(m_BoundingBox.IsNotNull());
- return m_BoundingBox->GetBounds();
- }
-#endif
- //##Documentation
- //## \brief Set the bounding box (in index/unit coordinates)
- //##
- //## Only possible via the BoundsArray to make clear that a
- //## copy of the bounding-box is stored, not a reference to it.
- virtual void SetBounds(const BoundsArrayType& bounds);
- //##Documentation
- //## @brief Set the bounding box (in index/unit coordinates) via a float array
- virtual void SetFloatBounds(const float bounds[6]);
- //##Documentation
- //## @brief Set the bounding box (in index/unit coordinates) via a double array
- virtual void SetFloatBounds(const double bounds[6]);
-
- //##Documentation
- //## @brief When switching from an Image Geometry to a normal Geometry (and the other way around), you have to change the origin as well (See Geometry Documentation)! This function will change the "isImageGeometry" bool flag and changes the origin respectively.
- virtual void ChangeImageGeometryConsideringOriginOffset( const bool isAnImageGeometry );
-
- //##Documentation
- //## @brief Checks, if the given geometry can be converted to 2D without information loss
- //## e.g. when a 2D image is saved, the matrix is usually cropped to 2x2, and when you load it back to MITK
- //## it will be filled with standard values. This function checks, if information would be lost during this
- //## procedure
- virtual bool Is2DConvertable();
-
- //##Documentation
- //## @brief Get the time bounds (in ms)
- itkGetConstReferenceMacro(TimeBounds, TimeBounds);
- //##Documentation
- //## @brief Set the time bounds (in ms)
- virtual void SetTimeBounds(const TimeBounds& timebounds);
-
- //##Documentation
- //## @brief Get the position of the corner number \a id (in world coordinates)
- //##
- //## See SetImageGeometry for how a corner is defined on images.
- Point3D GetCornerPoint(int id) const;
-
- //##Documentation
- //## @brief Get the position of a corner (in world coordinates)
- //##
- //## See SetImageGeometry for how a corner is defined on images.
- Point3D GetCornerPoint(bool xFront=true, bool yFront=true, bool zFront=true) const;
-
- //##Documentation
- //## @brief Get vector along bounding-box in the specified @a direction in mm
- //##
- //## The length of the vector is the size of the bounding-box in the
- //## specified @a direction in mm
- //## \sa GetMatrixColumn
- Vector3D GetAxisVector(unsigned int direction) const
- {
- Vector3D frontToBack;
- frontToBack.SetVnlVector(m_IndexToWorldTransform->GetMatrix().GetVnlMatrix().get_column(direction));
- frontToBack *= GetExtent(direction);
- return frontToBack;
- }
-
- //##Documentation
- //## @brief Get the center of the bounding-box in mm
- //##
- Point3D GetCenter() const
- {
- assert(m_BoundingBox.IsNotNull());
- return m_IndexToWorldTransform->TransformPoint(m_BoundingBox->GetCenter());
- }
-
- //##Documentation
- //## @brief Get the squared length of the diagonal of the bounding-box in mm
- //##
- double GetDiagonalLength2() const
- {
- Vector3D diagonalvector = GetCornerPoint()-GetCornerPoint(false, false, false);
- return diagonalvector.GetSquaredNorm();
- }
-
- //##Documentation
- //## @brief Get the length of the diagonal of the bounding-box in mm
- //##
- double GetDiagonalLength() const
- {
- return sqrt(GetDiagonalLength2());
- }
-
- //##Documentation
- //## @brief Get a VnlVector along bounding-box in the specified
- //## @a direction, length is spacing
- //##
- //## \sa GetAxisVector
- VnlVector GetMatrixColumn(unsigned int direction) const
- {
- return m_IndexToWorldTransform->GetMatrix().GetVnlMatrix().get_column(direction);
- }
-
-#ifdef DOXYGEN_SKIP
- //##Documentation
- //## @brief Get the extent of the bounding box (in index/unit coordinates)
- //##
- //## To access the extent in mm use GetExtentInMM
- ScalarType GetExtent(unsigned int direction) const;
-#endif
-
- //##Documentation
- //## @brief Get the extent of the bounding-box in the specified @a direction in mm
- //##
- //## Equals length of GetAxisVector(direction).
- ScalarType GetExtentInMM(int direction) const
- {
- return m_IndexToWorldTransform->GetMatrix().GetVnlMatrix().get_column(direction).magnitude()*GetExtent(direction);
- }
-
- //##Documentation
- //## @brief Set the extent of the bounding-box in the specified @a direction in mm
- //##
- //## @note This changes the matrix in the transform, @a not the bounds, which are given in units!
- virtual void SetExtentInMM(int direction, ScalarType extentInMM);
-
- //##Documentation
- //## @brief Get the m_IndexToWorldTransform as a vtkLinearTransform
- vtkLinearTransform* GetVtkTransform() const
- {
- return (vtkLinearTransform*)m_VtkIndexToWorldTransform;
- }
-
- //##Documentation
- //## @brief Set the origin, i.e. the upper-left corner of the plane
- //##
- virtual void SetOrigin(const Point3D& origin);
-
- //##Documentation
- //## @brief Translate the origin by a vector
- //##
- virtual void Translate(const Vector3D& vector);
-
- //##Documentation
- //## @brief Set the transform to identity
- //##
- virtual void SetIdentity();
-
- //##Documentation
- //## @brief Compose new IndexToWorldTransform with a given transform.
- //##
- //## This method composes m_IndexToWorldTransform with another transform,
- //## modifying self to be the composition of self and other.
- //## If the argument pre is true, then other is precomposed with self;
- //## that is, the resulting transformation consists of first applying
- //## other to the source, followed by self. If pre is false or omitted,
- //## then other is post-composed with self; that is the resulting
- //## transformation consists of first applying self to the source,
- //## followed by other.
- virtual void Compose( const Geometry3D::TransformType * other, bool pre = 0 );
-
- //##Documentation
- //## @brief Compose new IndexToWorldTransform with a given vtkMatrix4x4.
- //##
- //## Converts the vtkMatrix4x4 into a itk-transform and calls the previous method.
- virtual void Compose( const vtkMatrix4x4 * vtkmatrix, bool pre = 0 );
-
- //##Documentation
- //## @brief Get the origin, e.g. the upper-left corner of the plane
- const Point3D& GetOrigin() const
- {
- return m_Origin;
- }
-
- //##Documentation
- //## @brief Get the origin as VnlVector
- //##
- //## \sa GetOrigin
- VnlVector GetOriginVnl() const
- {
- return const_cast<Self*>(this)->m_Origin.GetVnlVector();
- }
-
- //##Documentation
- //## @brief Convert world coordinates (in mm) of a \em point to (continuous!) index coordinates
- //## \warning If you need (discrete) integer index coordinates (e.g., for iterating easily over an image),
- //## use WorldToIndex(const mitk::Point3D& pt_mm, itk::Index<VIndexDimension> &index).
- //## For further information about coordinates types, please see the Geometry documentation
- void WorldToIndex(const mitk::Point3D& pt_mm, mitk::Point3D& pt_units) const;
-
- //##Documentation
- //## @brief Convert (continuous or discrete) index coordinates of a \em point to world coordinates (in mm)
- //## For further information about coordinates types, please see the Geometry documentation
- void IndexToWorld(const mitk::Point3D& pt_units, mitk::Point3D& pt_mm) const;
-
- //##Documentation
- //## @brief Convert (discrete) index coordinates of a \em point to world coordinates (in mm)
- //## For further information about coordinates types, please see the Geometry documentation
- template <unsigned int VIndexDimension>
- void IndexToWorld(const itk::Index<VIndexDimension> &index, mitk::Point3D& pt_mm ) const
- {
- mitk::Point3D pt_units;
- pt_units.Fill(0);
- int i, dim=index.GetIndexDimension();
- if(dim>3)
- {
- dim=3;
- }
- for(i=0;i<dim;++i)
- {
- pt_units[i] = index[i];
- }
-
- IndexToWorld(pt_units,pt_mm);
- }
-
- //##Documentation
- //## @brief Convert world coordinates (in mm) of a \em vector
- //## \a vec_mm to (continuous!) index coordinates.
- //## @deprecated First parameter (Point3D) is not used. If possible, please use void WorldToIndex(const mitk::Vector3D& vec_mm, mitk::Vector3D& vec_units) const.
- //## For further information about coordinates types, please see the Geometry documentation
- void WorldToIndex(const mitk::Point3D& atPt3d_mm, const mitk::Vector3D& vec_mm, mitk::Vector3D& vec_units) const;
-
- //##Documentation
- //## @brief Convert world coordinates (in mm) of a \em vector
- //## \a vec_mm to (continuous!) index coordinates.
- //## For further information about coordinates types, please see the Geometry documentation
- void WorldToIndex(const mitk::Vector3D& vec_mm, mitk::Vector3D& vec_units) const;
-
- //##Documentation
- //## @brief Convert (continuous or discrete) index coordinates of a \em vector
- //## \a vec_units to world coordinates (in mm)
- //## @deprecated First parameter (Point3D) is not used. If possible, please use void IndexToWorld(const mitk::Vector3D& vec_units, mitk::Vector3D& vec_mm) const.
- //## For further information about coordinates types, please see the Geometry documentation
- void IndexToWorld(const mitk::Point3D& atPt3d_units, const mitk::Vector3D& vec_units, mitk::Vector3D& vec_mm) const;
-
- //##Documentation
- //## @brief Convert (continuous or discrete) index coordinates of a \em vector
- //## \a vec_units to world coordinates (in mm)
- //## For further information about coordinates types, please see the Geometry documentation
- void IndexToWorld(const mitk::Vector3D& vec_units, mitk::Vector3D& vec_mm) const;
-
- //##Documentation
- //## @brief Convert world coordinates (in mm) of a \em point to (discrete!) index coordinates.
- //## This method rounds to integer indices!
- //## For further information about coordinates types, please see the Geometry documentation
- template <unsigned int VIndexDimension>
- void WorldToIndex(const mitk::Point3D& pt_mm, itk::Index<VIndexDimension> &index) const
- {
- typedef itk::Index<VIndexDimension> IndexType;
- mitk::Point3D pt_units;
- this->WorldToIndex(pt_mm, pt_units);
- int i, dim=index.GetIndexDimension();
- if(dim>3)
- {
- index.Fill(0);
- dim=3;
- }
- for(i=0;i<dim;++i){
- index[i]=itk::Math::RoundHalfIntegerUp<typename IndexType::IndexValueType>( pt_units[i] );
- }
- }
-
- //##Documentation
- //## @brief Deprecated for use with ITK version 3.10 or newer.
- //## Convert world coordinates (in mm) of a \em point to
- //## ITK physical coordinates (in mm, but without a possible rotation)
- //##
- //## This method is useful if you have want to access an mitk::Image
- //## via an itk::Image. ITK v3.8 and older did not support rotated (tilted)
- //## images, i.e., ITK images are always parallel to the coordinate axes.
- //## When accessing a (possibly rotated) mitk::Image via an itk::Image
- //## the rotational part of the transformation in the Geometry3D is
- //## simply discarded; in other word: only the origin and spacing is
- //## used by ITK, not the complete matrix available in MITK.
- //## With WorldToItkPhysicalPoint you can convert an MITK world
- //## coordinate (including the rotation) into a coordinate that
- //## can be used with the ITK image as a ITK physical coordinate
- //## (excluding the rotation).
- template<class TCoordRep>
- void WorldToItkPhysicalPoint(const mitk::Point3D& pt_mm,
- itk::Point<TCoordRep, 3>& itkPhysicalPoint) const
- {
- mitk::vtk2itk(pt_mm, itkPhysicalPoint);
- }
-
- //##Documentation
- //## @brief Deprecated for use with ITK version 3.10 or newer.
- //## Convert ITK physical coordinates of a \em point (in mm,
- //## but without a rotation) into MITK world coordinates (in mm)
- //##
- //## For more information, see WorldToItkPhysicalPoint.
- template<class TCoordRep>
- void ItkPhysicalPointToWorld(const itk::Point<TCoordRep, 3>& itkPhysicalPoint,
- mitk::Point3D& pt_mm) const
- {
- mitk::vtk2itk(itkPhysicalPoint, pt_mm);
- }
-
- //##Documentation
- //## @brief Initialize the Geometry3D
- virtual void Initialize();
-
- //##Documentation
- //## @brief Is this an ImageGeometry?
- //##
- //## For more information, see SetImageGeometry
- itkGetConstMacro(ImageGeometry, bool);
- //##Documentation
- //## @brief Define that this Geometry3D is refering to an Image
- //##
- //## A geometry referring to an Image needs a slightly different
- //## definition of the position of the corners (see GetCornerPoint).
- //## The position of a voxel is defined by the position of its center.
- //## If we would use the origin (position of the (center of) the first
- //## voxel) as a corner and display this point, it would seem to be
- //## \em not at the corner but a bit within the image. Even worse for
- //## the opposite corner of the image: here the corner would appear
- //## outside the image (by half of the voxel diameter). Thus, we have
- //## to correct for this and to be able to do that, we need to know
- //## that the Geometry3D is referring to an Image.
- itkSetMacro(ImageGeometry, bool);
- itkBooleanMacro(ImageGeometry);
-
- //##Documentation
- //## @brief Is this Geometry3D in a state that is valid?
- virtual bool IsValid() const
- {
- return m_Valid;
- }
-
- //##Documentation
- //## @brief Test whether the point \a p (world coordinates in mm) is
- //## inside the bounding box
- bool IsInside(const mitk::Point3D& p) const
- {
- mitk::Point3D index;
- WorldToIndex(p, index);
- return IsIndexInside(index);
- }
-
- //##Documentation
- //## @brief Test whether the point \a p ((continous!)index coordinates in units) is
- //## inside the bounding box
- bool IsIndexInside(const mitk::Point3D& index) const
- {
- bool inside = false;
- //if it is an image geometry, we need to convert the index to discrete values
- //this is done by applying the rounding function also used in WorldToIndex (see line 323)
- if (m_ImageGeometry)
- {
- mitk::Point3D discretIndex;
- discretIndex[0]=itk::Math::RoundHalfIntegerUp<mitk::ScalarType>( index[0] );
- discretIndex[1]=itk::Math::RoundHalfIntegerUp<mitk::ScalarType>( index[1] );
- discretIndex[2]=itk::Math::RoundHalfIntegerUp<mitk::ScalarType>( index[2] );
-
- inside = m_BoundingBox->IsInside(discretIndex);
- //we have to check if the index is at the upper border of each dimension,
- // because the boundingbox is not centerbased
- if (inside)
- {
- const BoundingBox::BoundsArrayType& bounds = m_BoundingBox->GetBounds();
- if((discretIndex[0] == bounds[1]) ||
- (discretIndex[1] == bounds[3]) ||
- (discretIndex[2] == bounds[5]))
- inside = false;
- }
- }
- else
- inside = m_BoundingBox->IsInside(index);
-
- return inside;
- }
-
- //##Documentation
- //## @brief Convenience method for working with ITK indices
- template <unsigned int VIndexDimension>
- bool IsIndexInside(const itk::Index<VIndexDimension> &index) const
- {
- int i, dim=index.GetIndexDimension();
- Point3D pt_index;
- pt_index.Fill(0);
- for ( i = 0; i < dim; ++i )
- {
- pt_index[i] = index[i];
- }
- return IsIndexInside(pt_index);
- }
-
- //##Documentation
- //## @brief Get the spacing (size of a pixel).
- //##
- itkGetConstReferenceMacro(Spacing, mitk::Vector3D);
-
- //##Documentation
- //## @brief Get the spacing as a float[3] array.
- const float* GetFloatSpacing() const;
-
- //##Documentation
- //## @brief Set the spacing (m_Spacing)
- virtual void SetSpacing(const mitk::Vector3D& aSpacing);
-
- //##Documentation
- //## @brief Get the DICOM FrameOfReferenceID referring to the
- //## used world coordinate system
- itkGetConstMacro(FrameOfReferenceID, unsigned int);
- //##Documentation
- //## @brief Set the DICOM FrameOfReferenceID referring to the
- //## used world coordinate system
- itkSetMacro(FrameOfReferenceID, unsigned int);
-
- //##Documentation
- //## @brief Copy the ITK transform
- //## (m_IndexToWorldTransform) to the VTK transform
- //## \sa SetIndexToWorldTransform
- void TransferItkToVtkTransform();
-
- //##Documentation
- //## @brief Copy the VTK transform
- //## to the ITK transform (m_IndexToWorldTransform)
- //## \sa SetIndexToWorldTransform
- void TransferVtkToItkTransform();
-
- //##Documentation
- //## @brief Get the parametric bounding-box
- //##
- //## See AbstractTransformGeometry for an example usage of this.
- itkGetConstObjectMacro(ParametricBoundingBox, BoundingBox);
- //##Documentation
- //## @brief Get the parametric bounds
- //##
- //## See AbstractTransformGeometry for an example usage of this.
- const BoundingBox::BoundsArrayType& GetParametricBounds() const
- {
- assert(m_ParametricBoundingBox.IsNotNull());
- return m_ParametricBoundingBox->GetBounds();
- }
-
- //##Documentation
- //## @brief Get the parametric extent
- //##
- //## See AbstractTransformGeometry for an example usage of this.
- mitk::ScalarType GetParametricExtent(int direction) const
- {
- if (direction < 0 || direction>=3)
- mitkThrow() << "Invalid direction. Must be between either 0, 1 or 2. ";
- assert(m_ParametricBoundingBox.IsNotNull());
-
- BoundingBoxType::BoundsArrayType bounds = m_ParametricBoundingBox->GetBounds();
- return bounds[direction*2+1]-bounds[direction*2];
- }
-
- //##Documentation
- //## @brief Get the parametric extent in mm
- //##
- //## See AbstractTransformGeometry for an example usage of this.
- virtual mitk::ScalarType GetParametricExtentInMM(int direction) const
- {
- return GetExtentInMM(direction);
- }
-
- //##Documentation
- //## @brief Get the parametric transform
- //##
- //## See AbstractTransformGeometry for an example usage of this.
- virtual const Transform3D* GetParametricTransform() const
- {
- return m_IndexToWorldTransform;
- }
-
- //##Documentation
- //## @brief Calculates a bounding-box around the geometry relative
- //## to a coordinate system defined by a transform
- //##
- mitk::BoundingBox::Pointer CalculateBoundingBoxRelativeToTransform(const mitk::AffineTransform3D* transform) const;
-
- //##Documentation
- //## @brief clones the geometry
- //##
- //## Overwrite in all sub-classes.
- //## Normally looks like:
- //## \code
- //## Self::Pointer newGeometry = new Self(*this);
- //## newGeometry->UnRegister();
- //## return newGeometry.GetPointer();
- //## \endcode
- virtual itk::LightObject::Pointer InternalClone() const;
-
- //##Documentation
- //##@brief executes affine operations (translate, rotate, scale)
- virtual void ExecuteOperation(Operation* operation);
-
- /** Set/Get the IndexToWorldTransform */
- itkGetConstObjectMacro(IndexToWorldTransform, AffineTransform3D);
- itkGetObjectMacro(IndexToWorldTransform, AffineTransform3D);
- /** Get the bounding box */
- itkGetConstObjectMacro(BoundingBox, BoundingBoxType);
-
- const BoundsArrayType GetBounds() const
- {
- assert(m_BoundingBox.IsNotNull());
- return m_BoundingBox->GetBounds();
- }
-
- /** Get the extent of the bounding box */
- ScalarType GetExtent(unsigned int direction) const
- {
- assert(m_BoundingBox.IsNotNull());
- if (direction>=NDimensions)
- mitkThrow() << "Direction is too big. This geometry is for 3D Data";
- BoundsArrayType bounds = m_BoundingBox->GetBounds();
- return bounds[direction*2+1]-bounds[direction*2];
- }
- protected:
- Geometry3D();
- Geometry3D(const Geometry3D& other);
-
- virtual void InitializeGeometry(Self * newGeometry) const;
-
- static const std::string GetTransformAsString( TransformType* transformType );
- static const unsigned int NDimensions = 3;
-
- virtual ~Geometry3D();
-
- virtual void PrintSelf(std::ostream& os, itk::Indent indent) const;
-
- virtual void BackTransform(const mitk::Point3D& in, mitk::Point3D& out) const;
- //##Documentation
- //## @brief Deprecated
- virtual void BackTransform(const mitk::Point3D& at, const mitk::Vector3D& in, mitk::Vector3D& out) const;
-
- //Without redundant parameter Point3D
- virtual void BackTransform(const mitk::Vector3D& in, mitk::Vector3D& out) const;
-
- //##Documentation
- //## @brief Set the parametric bounds
- //##
- //## Protected in this class, made public in some sub-classes, e.g.,
- //## ExternAbstractTransformGeometry.
- virtual void SetParametricBounds(const BoundingBox::BoundsArrayType& bounds);
-
- /** Resets sub-transforms that compose m_IndexToWorldTransform, by using
- * the current value of m_IndexToWorldTransform and setting the rotation
- * component to zero. */
- virtual void ResetSubTransforms();
-
- mutable mitk::BoundingBox::Pointer m_ParametricBoundingBox;
-
- mutable mitk::TimeBounds m_TimeBounds;
-
- vtkMatrix4x4* m_VtkMatrix;
-
- bool m_ImageGeometry;
-
- AffineTransform3D::Pointer m_IndexToWorldTransform;
- mutable BoundingBoxPointer m_BoundingBox;
-
- //##Documentation
- //## @brief Spacing of the data. Only significant if the geometry describes
- //## an Image (m_ImageGeometry==true).
- mitk::Vector3D m_Spacing;
-
- bool m_Valid;
-
- unsigned int m_FrameOfReferenceID;
-
- static const std::string INDEX_TO_OBJECT_TRANSFORM;
- static const std::string OBJECT_TO_NODE_TRANSFORM;
- static const std::string INDEX_TO_NODE_TRANSFORM;
- static const std::string INDEX_TO_WORLD_TRANSFORM;
-
- private:
- mutable TransformType::Pointer m_InvertedTransform;
- mutable unsigned long m_IndexToWorldTransformLastModified;
-
- VnlQuaternionType m_RotationQuaternion;
-
- float m_FloatSpacing[3];
- vtkMatrixToLinearTransform* m_VtkIndexToWorldTransform;
-
- //##Documentation
- //## @brief Origin, i.e. upper-left corner of the plane
- //##
- Point3D m_Origin;
- };
-
- //
- // Static compare functions mainly for testing
- //
- /**
- * @brief Equal A function comparing two geometries for beeing identical.
- * @warning This method is deprecated and will not be available in the future. Use the \a bool mitk::Equal(const mitk::mitk::Geometry3D& g1, const mitk::Geometry3D& g2) instead.
- *
- * @ingroup MITKTestingAPI
- *
- * The function compares the spacing, origin, axisvectors, extents, the matrix of the
- * IndexToWorldTransform (elementwise), the bounding (elementwise) and the ImageGeometry flag.
- *
- * The parameter eps is a tolarence value for all methods which are internally used for comparion.
- * If you want to use different tolarance values for different parts of the geometry, feel free to use
- * the other comparison methods and write your own implementation of Equal.
- * @param rightHandSide Compare this against leftHandSide.
- * @param leftHandSide Compare this against rightHandSide.
- * @param eps Tolarence for comparison. You can use mitk::eps in most cases.
- * @param verbose Flag indicating if the user wants detailed console output or not.
- * @return True, if all comparison are true. False in any other case.
- */
- DEPRECATED( MITK_CORE_EXPORT bool Equal(const mitk::Geometry3D* leftHandSide, const mitk::Geometry3D* rightHandSide, ScalarType eps, bool verbose));
-
- /**
- * @brief Equal A function comparing two geometries for beeing identical.
- *
- * @ingroup MITKTestingAPI
- *
- * The function compares the spacing, origin, axisvectors, extents, the matrix of the
- * IndexToWorldTransform (elementwise), the bounding (elementwise) and the ImageGeometry flag.
- *
- * The parameter eps is a tolarence value for all methods which are internally used for comparion.
- * If you want to use different tolarance values for different parts of the geometry, feel free to use
- * the other comparison methods and write your own implementation of Equal.
- * @param rightHandSide Compare this against leftHandSide.
- * @param leftHandSide Compare this against rightHandSide.
- * @param eps Tolarence for comparison. You can use mitk::eps in most cases.
- * @param verbose Flag indicating if the user wants detailed console output or not.
- * @return True, if all comparison are true. False in any other case.
- */
- MITK_CORE_EXPORT bool Equal(const mitk::Geometry3D& leftHandSide, const mitk::Geometry3D& rightHandSide, ScalarType eps, bool verbose);
-
- /**
- * @brief Equal A function comparing two transforms (TransformType) for beeing identical.
- * @warning This method is deprecated and will not be available in the future. Use the \a bool mitk::Equal(const mitk::mitk::Geometry3D::TransformType& t1, const mitk::Geometry3D::TransformType& t2) instead.
- *
- * @ingroup MITKTestingAPI
- *
- * The function compares the IndexToWorldTransform (elementwise).
- *
- * The parameter eps is a tolarence value for all methods which are internally used for comparion.
- * @param rightHandSide Compare this against leftHandSide.
- * @param leftHandSide Compare this against rightHandSide.
- * @param eps Tolarence for comparison. You can use mitk::eps in most cases.
- * @param verbose Flag indicating if the user wants detailed console output or not.
- * @return True, if all comparison are true. False in any other case.
- */
- DEPRECATED( MITK_CORE_EXPORT bool Equal(const mitk::Geometry3D::TransformType *leftHandSide, const mitk::Geometry3D::TransformType *rightHandSide, ScalarType eps, bool verbose));
-
- /**
- * @brief Equal A function comparing two transforms (TransformType) for beeing identical.
- *
- * @ingroup MITKTestingAPI
- *
- * The function compares the IndexToWorldTransform (elementwise).
- *
- * The parameter eps is a tolarence value for all methods which are internally used for comparion.
- * @param rightHandSide Compare this against leftHandSide.
- * @param leftHandSide Compare this against rightHandSide.
- * @param eps Tolarence for comparison. You can use mitk::eps in most cases.
- * @param verbose Flag indicating if the user wants detailed console output or not.
- * @return True, if all comparison are true. False in any other case.
- */
- MITK_CORE_EXPORT bool Equal(const mitk::Geometry3D::TransformType& leftHandSide, const mitk::Geometry3D::TransformType& rightHandSide, ScalarType eps, bool verbose);
-
- /**
- * @brief Equal A function comparing two bounding boxes (BoundingBoxType) for beeing identical.
- * @warning This method is deprecated and will not be available in the future. Use the \a bool mitk::Equal(const mitk::mitk::Geometry3D::BoundingBoxType& b1, const mitk::Geometry3D::BoundingBoxType& b2) instead.
- *
- * @ingroup MITKTestingAPI
- *
- * The function compares the bounds (elementwise).
- *
- * The parameter eps is a tolarence value for all methods which are internally used for comparion.
- * @param rightHandSide Compare this against leftHandSide.
- * @param leftHandSide Compare this against rightHandSide.
- * @param eps Tolarence for comparison. You can use mitk::eps in most cases.
- * @param verbose Flag indicating if the user wants detailed console output or not.
- * @return True, if all comparison are true. False in any other case.
- */
- DEPRECATED( MITK_CORE_EXPORT bool Equal( const mitk::Geometry3D::BoundingBoxType *leftHandSide, const mitk::Geometry3D::BoundingBoxType *rightHandSide, ScalarType eps, bool verbose));
-
- /**
- * @brief Equal A function comparing two bounding boxes (BoundingBoxType) for beeing identical.
- *
- * @ingroup MITKTestingAPI
- *
- * The function compares the bounds (elementwise).
- *
- * The parameter eps is a tolarence value for all methods which are internally used for comparion.
- * @param rightHandSide Compare this against leftHandSide.
- * @param leftHandSide Compare this against rightHandSide.
- * @param eps Tolarence for comparison. You can use mitk::eps in most cases.
- * @param verbose Flag indicating if the user wants detailed console output or not.
- * @return True, if all comparison are true. False in any other case.
- */
- MITK_CORE_EXPORT bool Equal( const mitk::Geometry3D::BoundingBoxType& leftHandSide, const mitk::Geometry3D::BoundingBoxType& rightHandSide, ScalarType eps, bool verbose);
+ //##Documentation
+ //## @brief Standard implementation of BaseGeometry.
+ //##
+ //## @ingroup Geometry
+ class MITK_CORE_EXPORT Geometry3D : public BaseGeometry
+ {
+ public:
+ mitkClassMacro(Geometry3D, mitk::BaseGeometry);
+
+ typedef itk::QuaternionRigidTransform< ScalarType > QuaternionTransformType;
+ typedef QuaternionTransformType::VnlQuaternionType VnlQuaternionType;
+
+ /** Method for creation through the object factory. */
+ itkFactorylessNewMacro(Self)
+ mitkNewMacro1Param(Self,Self);
+
+ itkCloneMacro(Self)
+ //itkGetConstReferenceMacro(TimeBounds, TimeBounds);
+
+ //virtual void SetTimeBounds(const TimeBounds& timebounds);
+
+ protected:
+ Geometry3D();
+ Geometry3D(const Geometry3D& other);
+
+ //##Documentation
+ //## @brief clones the geometry
+ //##
+ //## Overwrite in all sub-classes.
+ //## Normally looks like:
+ //## \code
+ //## Self::Pointer newGeometry = new Self(*this);
+ //## newGeometry->UnRegister();
+ //## return newGeometry.GetPointer();
+ //## \endcode
+ virtual itk::LightObject::Pointer InternalClone() const;
+
+ virtual ~Geometry3D();
+ };
} // namespace mitk
#endif /* GEOMETRY3D_H_HEADER_INCLUDED_C1EBD0AD */
diff --git a/Core/Code/DataManagement/mitkGeometryData.h b/Core/Code/DataManagement/mitkGeometryData.h
index 5dc905f072..0bb41c588f 100644
--- a/Core/Code/DataManagement/mitkGeometryData.h
+++ b/Core/Code/DataManagement/mitkGeometryData.h
@@ -1,58 +1,58 @@
/*===================================================================
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 MITKGEOMETRYDATA_H_HEADER_INCLUDED_C19C01E2
#define MITKGEOMETRYDATA_H_HEADER_INCLUDED_C19C01E2
#include "mitkBaseData.h"
namespace mitk {
//##Documentation
-//## @brief Data class only having a Geometry3D but not containing
+//## @brief Data class only having a BaseGeometry but not containing
//## any specific data.
//##
//## Only implements pipeline methods which are abstract in BaseData.
//## @ingroup Geometry
class MITK_CORE_EXPORT GeometryData : public BaseData
{
public:
mitkClassMacro(GeometryData, BaseData);
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
virtual void UpdateOutputInformation();
virtual void SetRequestedRegionToLargestPossibleRegion();
virtual bool RequestedRegionIsOutsideOfTheBufferedRegion();
virtual bool VerifyRequestedRegion();
virtual void SetRequestedRegion( const itk::DataObject *data);
virtual void CopyInformation(const itk::DataObject *data);
protected:
GeometryData();
virtual ~GeometryData();
};
} // namespace mitk
#endif /* MITKGEOMETRYDATA_H_HEADER_INCLUDED_C19C01E2 */
diff --git a/Core/Code/DataManagement/mitkITKImageImport.h b/Core/Code/DataManagement/mitkITKImageImport.h
index c6176af868..f9b3d7f9a5 100644
--- a/Core/Code/DataManagement/mitkITKImageImport.h
+++ b/Core/Code/DataManagement/mitkITKImageImport.h
@@ -1,195 +1,195 @@
/*===================================================================
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 MITKITKIMAGEIMPORT_H_HEADER_INCLUDED_C1E4861D
#define MITKITKIMAGEIMPORT_H_HEADER_INCLUDED_C1E4861D
#include <MitkCoreExports.h>
#include "mitkImageSource.h"
#include "itkImageToImageFilterDetail.h"
namespace mitk {
/**
* @brief Pipelined import of itk::Image
*
* The image data contained in the itk::Image is referenced,
* not copied.
* The easiest way of use is by the function
* mitk::ImportItkImage
* \code
* mitkImage = mitk::ImportItkImage(itkImage);
* \endcode
* \sa ImportItkImage
* @ingroup Adaptor
*/
template <class TInputImage>
class MITK_EXPORT ITKImageImport : public ImageSource
{
public:
mitkClassMacro(ITKImageImport,ImageSource)
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/// \brief The type of the input image.
typedef TInputImage InputImageType;
typedef typename InputImageType::Pointer InputImagePointer;
typedef typename InputImageType::ConstPointer InputImageConstPointer;
typedef typename InputImageType::RegionType InputImageRegionType;
typedef typename InputImageType::PixelType InputImagePixelType;
/** ImageDimension constants */
itkStaticConstMacro(InputImageDimension, unsigned int,
TInputImage::ImageDimension);
itkStaticConstMacro(RegionDimension, unsigned int,
mitk::SlicedData::RegionDimension);
/** \brief Set the input itk::Image of this image importer. */
InputImageType * GetInput(void);
/** \brief Set the input itk::Image of this image importer. */
void SetInput(const InputImageType*);
using itk::ProcessObject::SetInput;
/**
* \brief Set the Geometry of the result image (optional)
*
* The Geometry has to fit the dimension and size of
* the input image. The Geometry will be cloned, not
* referenced!
*
* Providing the Geometry is optional.
* The default behavior is to set the geometry by
* the itk::Image::GetDirection() information.
*/
- void SetGeometry(const Geometry3D* geometry);
+ void SetGeometry(const BaseGeometry* geometry);
protected:
ITKImageImport();
virtual ~ITKImageImport();
virtual void GenerateOutputInformation();
virtual void GenerateInputRequestedRegion();
virtual void GenerateData();
virtual void SetNthOutput(DataObjectPointerArraySizeType num, itk::DataObject *output);
/** Typedef for the region copier function object that converts an
* output region to an input region. */
typedef itk::ImageToImageFilterDetail::ImageRegionCopier<itkGetStaticConstMacro(InputImageDimension),
itkGetStaticConstMacro(RegionDimension)> OutputToInputRegionCopierType;
- Geometry3D::Pointer m_Geometry;
+ BaseGeometry::Pointer m_Geometry;
};
/**
* @brief Imports an itk::Image (with a specific type) as an mitk::Image.
* @ingroup Adaptor
*
* Instantiates instance of ITKImageImport.
* mitk::ITKImageImport does not cast pixel types etc., it just imports
* image data. If you get a compile error, try image.GetPointer().
*
* \param update: if \a true, fill mitk::Image, which will execute the
* up-stream pipeline connected to the input itk::Image. Otherwise you
* need to make sure that Update() is called on the mitk::Image before
* its data is being used, e.g., by connecting it to an mitk-pipeline
* and call Update of a downstream filter at some time.
* \sa itk::Image::CastToMitkImage
*/
template <typename ItkOutputImageType>
-Image::Pointer ImportItkImage(const itk::SmartPointer<ItkOutputImageType>& itkimage, const Geometry3D* geometry = NULL, bool update = true);
+Image::Pointer ImportItkImage(const itk::SmartPointer<ItkOutputImageType>& itkimage, const BaseGeometry* geometry = NULL, bool update = true);
/**
* @brief Imports an itk::Image (with a specific type) as an mitk::Image.
* @ingroup Adaptor
*
* Instantiates instance of ITKImageImport
* mitk::ITKImageImport does not cast pixel types etc., it just imports
* image data. If you get a compile error, try image.GetPointer().
*
* \param update: if \a true, fill mitk::Image, which will execute the
* up-stream pipeline connected to the input itk::Image. Otherwise you
* need to make sure that Update() is called on the mitk::Image before
* its data is being used, e.g., by connecting it to an mitk-pipeline
* and call Update of a downstream filter at some time.
*
*
* \note If the source (itk image) and the target (mitk image) do not share the same scope, the mitk::GrabItkImageMemory function
* has to be used instead. Otherwise the image memory managed by the itk image is lost at a scope level change. This affects especially the
* usage in combination with AccessByItk macros as in following example code
*
* \snippet Testing/mitkGrabItkImageMemoryTest.cpp OutOfScopeCall
*
* which calls an ITK-like filter
*
* \snippet Testing/mitkGrabItkImageMemoryTest.cpp ItkThresholdFilter
*
*
* \sa itk::Image::CastToMitkImage
* \sa GrabItkImageMemory
*/
template <typename ItkOutputImageType>
-Image::Pointer ImportItkImage(const ItkOutputImageType* itkimage, const Geometry3D* geometry = NULL, bool update = true);
+Image::Pointer ImportItkImage(const ItkOutputImageType* itkimage, const BaseGeometry* geometry = NULL, bool update = true);
/**
* @brief Grabs the memory of an itk::Image (with a specific type)
* and puts it into an mitk::Image.
* @ingroup Adaptor
*
* The memory is managed by the mitk::Image after calling this
* function. The itk::Image remains valid until the mitk::Image
* decides to free the memory.
* \param update: if \a true, fill mitk::Image, which will execute the
* up-stream pipeline connected to the input itk::Image. Otherwise you
* need to make sure that Update() is called on the mitk::Image before
* its data is being used, e.g., by connecting it to an mitk-pipeline
* and call Update of a downstream filter at some time.
* \sa ImportItkImage
*/
template <typename ItkOutputImageType>
-Image::Pointer GrabItkImageMemory(itk::SmartPointer<ItkOutputImageType>& itkimage, mitk::Image* mitkImage = NULL, const Geometry3D* geometry = NULL, bool update = true);
+Image::Pointer GrabItkImageMemory(itk::SmartPointer<ItkOutputImageType>& itkimage, mitk::Image* mitkImage = NULL, const BaseGeometry* geometry = NULL, bool update = true);
/**
* @brief Grabs the memory of an itk::Image (with a specific type)
* and puts it into an mitk::Image.
* @ingroup Adaptor
*
* The memory is managed by the mitk::Image after calling this
* function. The itk::Image remains valid until the mitk::Image
* decides to free the memory.
* \param update: if \a true, fill mitk::Image, which will execute the
* up-stream pipeline connected to the input itk::Image. Otherwise you
* need to make sure that Update() is called on the mitk::Image before
* its data is being used, e.g., by connecting it to an mitk-pipeline
* and call Update of a downstream filter at some time.
* \sa ImportItkImage
*/
template <typename ItkOutputImageType>
-Image::Pointer GrabItkImageMemory(ItkOutputImageType* itkimage, mitk::Image* mitkImage = NULL, const Geometry3D* geometry = NULL, bool update = true);
+Image::Pointer GrabItkImageMemory(ItkOutputImageType* itkimage, mitk::Image* mitkImage = NULL, const BaseGeometry* geometry = NULL, bool update = true);
} // namespace mitk
#ifndef MITK_MANUAL_INSTANTIATION
#include "mitkITKImageImport.txx"
#endif
#endif /* MITKITKIMAGEIMPORT_H_HEADER_INCLUDED_C1E4861D */
diff --git a/Core/Code/DataManagement/mitkITKImageImport.txx b/Core/Code/DataManagement/mitkITKImageImport.txx
index 4123b34f20..5d7867115f 100644
--- a/Core/Code/DataManagement/mitkITKImageImport.txx
+++ b/Core/Code/DataManagement/mitkITKImageImport.txx
@@ -1,177 +1,177 @@
/*===================================================================
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 __mitkITKImageImport_txx
#define __mitkITKImageImport_txx
#include "mitkITKImageImport.h"
template <class TInputImage>
mitk::ITKImageImport<TInputImage>::ITKImageImport()
{
}
template <class TInputImage>
mitk::ITKImageImport<TInputImage>::~ITKImageImport()
{
}
template <class TInputImage>
typename mitk::ITKImageImport<TInputImage>::InputImageType *
mitk::ITKImageImport<TInputImage>::GetInput(void)
{
return static_cast<TInputImage*>(
this->ProcessObject::GetInput(0));
}
template <class TInputImage>
void mitk::ITKImageImport<TInputImage>::SetInput(const InputImageType* input)
{
this->ProcessObject::SetNthInput(0, const_cast<TInputImage*>(input) );
}
template <class TInputImage>
-void mitk::ITKImageImport<TInputImage>::SetGeometry(const Geometry3D* geometry)
+void mitk::ITKImageImport<TInputImage>::SetGeometry(const BaseGeometry* geometry)
{
if(geometry != NULL)
{
- m_Geometry = static_cast<mitk::Geometry3D*>(geometry->Clone().GetPointer());
+ m_Geometry = static_cast<mitk::BaseGeometry*>(geometry->Clone().GetPointer());
}
else
{
m_Geometry = NULL;
}
Modified();
}
template <class TInputImage>
void mitk::ITKImageImport<TInputImage>::GenerateOutputInformation()
{
InputImageConstPointer input = this->GetInput();
mitk::Image::Pointer output = this->GetOutput();
itkDebugMacro(<<"GenerateOutputInformation()");
output->InitializeByItk(input.GetPointer());
if(m_Geometry.IsNotNull())
{
output->SetGeometry(m_Geometry);
}
}
template <class TInputImage>
void mitk::ITKImageImport<TInputImage>::GenerateData()
{
InputImageConstPointer input = this->GetInput();
mitk::Image::Pointer output = this->GetOutput();
output->SetImportChannel((void*)input->GetBufferPointer(), 0, mitk::Image::ReferenceMemory);
}
template <class TInputImage>
void mitk::ITKImageImport<TInputImage>::GenerateInputRequestedRegion()
{
Superclass::GenerateInputRequestedRegion();
// Input is an image, cast away the constness so we can set
// the requested region.
InputImagePointer input =
const_cast< TInputImage * > ( this->GetInput() );
// Use the function object RegionCopier to copy the output region
// to the input. The default region copier has default implementations
// to handle the cases where the input and output are the same
// dimension, the input a higher dimension than the output, and the
// input a lower dimension than the output.
InputImageRegionType inputRegion;
OutputToInputRegionCopierType regionCopier;
regionCopier(inputRegion, this->GetOutput()->GetRequestedRegion());
input->SetRequestedRegion( inputRegion );
}
template <class TInputImage>
void mitk::ITKImageImport<TInputImage>::SetNthOutput(DataObjectPointerArraySizeType idx, itk::DataObject *output)
{
if((output == NULL) && (idx == 0))
{
// we are disconnected from our output:
// copy buffer of input to output, because we
// cannot guarantee that the input (to which our
// output is refering) will stay alive.
InputImageConstPointer input = this->GetInput();
mitk::Image::Pointer currentOutput = this->GetOutput();
if(input.IsNotNull() && currentOutput.IsNotNull())
currentOutput->SetChannel(input->GetBufferPointer());
}
Superclass::SetNthOutput(idx, output);
}
template <typename ItkOutputImageType>
-mitk::Image::Pointer mitk::ImportItkImage(const itk::SmartPointer<ItkOutputImageType>& itkimage, const Geometry3D* geometry, bool update)
+mitk::Image::Pointer mitk::ImportItkImage(const itk::SmartPointer<ItkOutputImageType>& itkimage, const BaseGeometry* geometry, bool update)
{
typename mitk::ITKImageImport<ItkOutputImageType>::Pointer importer = mitk::ITKImageImport<ItkOutputImageType>::New();
importer->SetInput(itkimage);
importer->SetGeometry(geometry);
if(update)
importer->Update();
return importer->GetOutput();
}
template <typename ItkOutputImageType>
-mitk::Image::Pointer mitk::ImportItkImage(const ItkOutputImageType* itkimage, const Geometry3D* geometry, bool update)
+mitk::Image::Pointer mitk::ImportItkImage(const ItkOutputImageType* itkimage, const BaseGeometry* geometry, bool update)
{
typename mitk::ITKImageImport<ItkOutputImageType>::Pointer importer = mitk::ITKImageImport<ItkOutputImageType>::New();
importer->SetInput(itkimage);
importer->SetGeometry(geometry);
if(update)
importer->Update();
return importer->GetOutput();
}
template <typename ItkOutputImageType>
-mitk::Image::Pointer mitk::GrabItkImageMemory(itk::SmartPointer<ItkOutputImageType>& itkimage, mitk::Image* mitkImage, const Geometry3D* geometry, bool update)
+mitk::Image::Pointer mitk::GrabItkImageMemory(itk::SmartPointer<ItkOutputImageType>& itkimage, mitk::Image* mitkImage, const BaseGeometry* geometry, bool update)
{
return GrabItkImageMemory( itkimage.GetPointer(), mitkImage, geometry, update );
}
template <typename ItkOutputImageType>
-mitk::Image::Pointer mitk::GrabItkImageMemory(ItkOutputImageType* itkimage, mitk::Image* mitkImage, const Geometry3D* geometry, bool update)
+mitk::Image::Pointer mitk::GrabItkImageMemory(ItkOutputImageType* itkimage, mitk::Image* mitkImage, const BaseGeometry* geometry, bool update)
{
if(update)
itkimage->Update();
mitk::Image::Pointer resultImage;
if(mitkImage != NULL)
{
resultImage = mitkImage;
}
else
{
resultImage = mitk::Image::New();
}
resultImage->InitializeByItk( itkimage );
resultImage->SetImportVolume( itkimage->GetBufferPointer(), 0, 0,
Image::ManageMemory );
itkimage->GetPixelContainer()->ContainerManageMemoryOff();
if(geometry != NULL)
- resultImage->SetGeometry(static_cast<mitk::Geometry3D*>(geometry->Clone().GetPointer()));
+ resultImage->SetGeometry(static_cast<mitk::BaseGeometry*>(geometry->Clone().GetPointer()));
return resultImage;
}
#endif //__mitkITKImageImport_txx
diff --git a/Core/Code/DataManagement/mitkImage.cpp b/Core/Code/DataManagement/mitkImage.cpp
index bf86a0dad7..1c69b60898 100644
--- a/Core/Code/DataManagement/mitkImage.cpp
+++ b/Core/Code/DataManagement/mitkImage.cpp
@@ -1,1383 +1,1372 @@
/*===================================================================
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.
===================================================================*/
//MITK
#include "mitkImage.h"
#include "mitkImageStatisticsHolder.h"
#include "mitkPixelTypeMultiplex.h"
#include <mitkProportionalTimeGeometry.h>
#include "mitkCompareImageDataFilter.h"
//VTK
#include <vtkImageData.h>
//Other
#include <cmath>
#define FILL_C_ARRAY( _arr, _size, _value) for(unsigned int i=0u; i<_size; i++) \
{ _arr[i] = _value; }
mitk::Image::Image() :
m_Dimension(0), m_Dimensions(NULL), m_ImageDescriptor(NULL), m_OffsetTable(NULL), m_CompleteData(NULL),
m_ImageStatistics(NULL)
{
m_Dimensions = new unsigned int[MAX_IMAGE_DIMENSIONS];
FILL_C_ARRAY( m_Dimensions, MAX_IMAGE_DIMENSIONS, 0u);
m_Initialized = false;
}
mitk::Image::Image(const Image &other) : SlicedData(other), m_Dimension(0), m_Dimensions(NULL),
m_ImageDescriptor(NULL), m_OffsetTable(NULL), m_CompleteData(NULL), m_ImageStatistics(NULL)
{
m_Dimensions = new unsigned int[MAX_IMAGE_DIMENSIONS];
FILL_C_ARRAY( m_Dimensions, MAX_IMAGE_DIMENSIONS, 0u);
this->Initialize( other.GetPixelType(), other.GetDimension(), other.GetDimensions());
//Since the above called "Initialize" method doesn't take the geometry into account we need to set it
//here manually
TimeGeometry::Pointer cloned = other.GetTimeGeometry()->Clone();
this->SetTimeGeometry(cloned.GetPointer());
if (this->GetDimension() > 3)
{
const unsigned int time_steps = this->GetDimension(3);
for (unsigned int i = 0u; i < time_steps; ++i)
{
ImageDataItemPointer volume = const_cast<Image&>(other).GetVolumeData(i);
this->SetVolume(volume->GetData(), i);
}
}
else
{
ImageDataItemPointer volume = const_cast<Image&>(other).GetVolumeData(0);
this->SetVolume(volume->GetData(), 0);
}
}
mitk::Image::~Image()
{
Clear();
m_ReferenceCountLock.Lock();
m_ReferenceCount = 3;
m_ReferenceCountLock.Unlock();
m_ReferenceCountLock.Lock();
m_ReferenceCount = 0;
m_ReferenceCountLock.Unlock();
if(m_OffsetTable != NULL)
delete [] m_OffsetTable;
if(m_ImageStatistics != NULL)
delete m_ImageStatistics;
}
const mitk::PixelType mitk::Image::GetPixelType(int n) const
{
return this->m_ImageDescriptor->GetChannelTypeById(n);
}
unsigned int mitk::Image::GetDimension() const
{
return m_Dimension;
}
unsigned int mitk::Image::GetDimension(int i) const
{
if((i>=0) && (i<(int)m_Dimension))
return m_Dimensions[i];
return 1;
}
void* mitk::Image::GetData()
{
if(m_Initialized==false)
{
if(GetSource().IsNull())
return NULL;
if(GetSource()->Updating()==false)
GetSource()->UpdateOutputInformation();
}
m_CompleteData=GetChannelData();
// update channel's data
// if data was not available at creation point, the m_Data of channel descriptor is NULL
// if data present, it won't be overwritten
m_ImageDescriptor->GetChannelDescriptor(0).SetData(m_CompleteData->GetData());
return m_CompleteData->GetData();
}
template <class T>
void AccessPixel( const mitk::PixelType ptype, void* data, const unsigned int offset, double& value )
{
value = 0.0;
if( data == NULL ) return;
if(ptype.GetBpe() != 24)
{
value = (double) (((T*) data)[ offset ]);
}
else
{
const unsigned int rgboffset = 3 * offset;
double returnvalue = (((T*) data)[rgboffset ]);
returnvalue += (((T*) data)[rgboffset + 1]);
returnvalue += (((T*) data)[rgboffset + 2]);
value = returnvalue;
}
-
}
double mitk::Image::GetPixelValueByIndex(const mitk::Index3D &position, unsigned int timestep)
{
double value = 0;
if (this->GetTimeSteps() < timestep)
{
timestep = this->GetTimeSteps();
}
value = 0.0;
const unsigned int* imageDims = this->m_ImageDescriptor->GetDimensions();
const mitk::PixelType ptype = this->m_ImageDescriptor->GetChannelTypeById(0);
// Comparison ?>=0 not needed since all position[i] and timestep are unsigned int
// (position[0]>=0 && position[1] >=0 && position[2]>=0 && timestep>=0)
// bug-11978 : we still need to catch index with negative values
if ( position[0] < 0 ||
position[1] < 0 ||
position[2] < 0 )
{
MITK_WARN << "Given position ("<< position << ") is out of image range, returning 0." ;
}
// check if the given position is inside the index range of the image, the 3rd dimension needs to be compared only if the dimension is not 0
else if ( (unsigned int)position[0] >= imageDims[0] ||
(unsigned int)position[1] >= imageDims[1] ||
( imageDims[2] && (unsigned int)position[2] >= imageDims[2] ))
{
MITK_WARN << "Given position ("<< position << ") is out of image range, returning 0." ;
}
else
{
const unsigned int offset = position[0] + position[1]*imageDims[0] + position[2]*imageDims[0]*imageDims[1] + timestep*imageDims[0]*imageDims[1]*imageDims[2];
mitkPixelTypeMultiplex3( AccessPixel, ptype, this->GetData(), offset, value );
}
return value;
}
double mitk::Image::GetPixelValueByWorldCoordinate(const mitk::Point3D& position, unsigned int timestep)
{
double value = 0.0;
if (this->GetTimeSteps() < timestep)
{
timestep = this->GetTimeSteps();
}
Index3D itkIndex;
this->GetGeometry()->WorldToIndex(position, itkIndex);
value = this->GetPixelValueByIndex( itkIndex, timestep);
return value;
}
mitk::ImageVtkAccessor* mitk::Image::GetVtkImageData(int t, int n)
{
if(m_Initialized==false)
{
if(GetSource().IsNull())
return NULL;
if(GetSource()->Updating()==false)
GetSource()->UpdateOutputInformation();
}
ImageDataItemPointer volume=GetVolumeData(t, n);
if(volume.GetPointer()==NULL || volume->GetVtkImageData(this) == NULL)
return NULL;
SlicedGeometry3D* geom3d = GetSlicedGeometry(t);
- float *fspacing = const_cast<float *>(geom3d->GetFloatSpacing());
- double dspacing[3] = {fspacing[0],fspacing[1],fspacing[2]};
+ const mitk::Vector3D vspacing = (geom3d->GetSpacing());
+ double dspacing[3] = {vspacing[0],vspacing[1],vspacing[2]};
volume->GetVtkImageData(this)->SetSpacing( dspacing );
return volume->GetVtkImageData(this);
}
mitk::Image::ImageDataItemPointer mitk::Image::GetSliceData(int s, int t, int n, void *data, ImportMemoryManagementType importMemoryManagement)
{
if(IsValidSlice(s,t,n)==false) return NULL;
const size_t ptypeSize = this->m_ImageDescriptor->GetChannelTypeById(n).GetSize();
// slice directly available?
int pos=GetSliceIndex(s,t,n);
if(m_Slices[pos].GetPointer()!=NULL)
return m_Slices[pos];
// is slice available as part of a volume that is available?
ImageDataItemPointer sl, ch, vol;
vol=m_Volumes[GetVolumeIndex(t,n)];
if((vol.GetPointer()!=NULL) && (vol->IsComplete()))
{
sl=new ImageDataItem(*vol, m_ImageDescriptor, 2, data, importMemoryManagement == ManageMemory, ((size_t) s)*m_OffsetTable[2]*(ptypeSize));
sl->SetComplete(true);
return m_Slices[pos]=sl;
}
// is slice available as part of a channel that is available?
ch=m_Channels[n];
if((ch.GetPointer()!=NULL) && (ch->IsComplete()))
{
sl=new ImageDataItem(*ch, m_ImageDescriptor, 2, data, importMemoryManagement == ManageMemory, (((size_t) s)*m_OffsetTable[2]+((size_t) t)*m_OffsetTable[3])*(ptypeSize));
sl->SetComplete(true);
return m_Slices[pos]=sl;
}
// slice is unavailable. Can we calculate it?
if((GetSource().IsNotNull()) && (GetSource()->Updating()==false))
{
// ... wir mussen rechnen!!! ....
m_RequestedRegion.SetIndex(0, 0);
m_RequestedRegion.SetIndex(1, 0);
m_RequestedRegion.SetIndex(2, s);
m_RequestedRegion.SetIndex(3, t);
m_RequestedRegion.SetIndex(4, n);
m_RequestedRegion.SetSize(0, m_Dimensions[0]);
m_RequestedRegion.SetSize(1, m_Dimensions[1]);
m_RequestedRegion.SetSize(2, 1);
m_RequestedRegion.SetSize(3, 1);
m_RequestedRegion.SetSize(4, 1);
m_RequestedRegionInitialized=true;
GetSource()->Update();
if(IsSliceSet(s,t,n))
//yes: now we can call ourselves without the risk of a endless loop (see "if" above)
return GetSliceData(s,t,n,data,importMemoryManagement);
else
return NULL;
}
else
{
ImageDataItemPointer item = AllocateSliceData(s,t,n,data,importMemoryManagement);
item->SetComplete(true);
return item;
}
}
mitk::Image::ImageDataItemPointer mitk::Image::GetVolumeData(int t, int n, void *data, ImportMemoryManagementType importMemoryManagement)
{
if(IsValidVolume(t,n)==false) return NULL;
ImageDataItemPointer ch, vol;
// volume directly available?
int pos=GetVolumeIndex(t,n);
vol=m_Volumes[pos];
if((vol.GetPointer()!=NULL) && (vol->IsComplete()))
return vol;
const size_t ptypeSize = this->m_ImageDescriptor->GetChannelTypeById(n).GetSize();
// is volume available as part of a channel that is available?
ch=m_Channels[n];
if((ch.GetPointer()!=NULL) && (ch->IsComplete()))
{
vol=new ImageDataItem(*ch, m_ImageDescriptor, 3, data, importMemoryManagement == ManageMemory, (((size_t) t)*m_OffsetTable[3])*(ptypeSize));
vol->SetComplete(true);
return m_Volumes[pos]=vol;
}
// let's see if all slices of the volume are set, so that we can (could) combine them to a volume
bool complete=true;
unsigned int s;
for(s=0;s<m_Dimensions[2];++s)
{
if(m_Slices[GetSliceIndex(s,t,n)].GetPointer()==NULL)
{
complete=false;
break;
}
}
if(complete)
{
// if there is only single slice we do not need to combine anything
if(m_Dimensions[2]<=1)
{
ImageDataItemPointer sl;
sl=GetSliceData(0,t,n,data,importMemoryManagement);
vol=new ImageDataItem(*sl, m_ImageDescriptor, 3, data, importMemoryManagement == ManageMemory);
vol->SetComplete(true);
}
else
{
mitk::PixelType chPixelType = this->m_ImageDescriptor->GetChannelTypeById(n);
vol=m_Volumes[pos];
// ok, let's combine the slices!
if(vol.GetPointer()==NULL)
vol=new ImageDataItem( chPixelType, 3, m_Dimensions, NULL, true);
vol->SetComplete(true);
size_t size=m_OffsetTable[2]*(ptypeSize);
for(s=0;s<m_Dimensions[2];++s)
{
int posSl;
ImageDataItemPointer sl;
posSl=GetSliceIndex(s,t,n);
sl=m_Slices[posSl];
if(sl->GetParent()!=vol)
{
// copy data of slices in volume
size_t offset = ((size_t) s)*size;
std::memcpy(static_cast<char*>(vol->GetData())+offset, sl->GetData(), size);
// FIXME mitkIpPicDescriptor * pic = sl->GetPicDescriptor();
// replace old slice with reference to volume
sl=new ImageDataItem(*vol, m_ImageDescriptor, 2, data, importMemoryManagement == ManageMemory, ((size_t) s)*size);
sl->SetComplete(true);
//mitkIpFuncCopyTags(sl->GetPicDescriptor(), pic);
m_Slices[posSl]=sl;
}
}
//if(vol->GetPicDescriptor()->info->tags_head==NULL)
// mitkIpFuncCopyTags(vol->GetPicDescriptor(), m_Slices[GetSliceIndex(0,t,n)]->GetPicDescriptor());
}
return m_Volumes[pos]=vol;
}
// volume is unavailable. Can we calculate it?
if((GetSource().IsNotNull()) && (GetSource()->Updating()==false))
{
// ... wir muessen rechnen!!! ....
m_RequestedRegion.SetIndex(0, 0);
m_RequestedRegion.SetIndex(1, 0);
m_RequestedRegion.SetIndex(2, 0);
m_RequestedRegion.SetIndex(3, t);
m_RequestedRegion.SetIndex(4, n);
m_RequestedRegion.SetSize(0, m_Dimensions[0]);
m_RequestedRegion.SetSize(1, m_Dimensions[1]);
m_RequestedRegion.SetSize(2, m_Dimensions[2]);
m_RequestedRegion.SetSize(3, 1);
m_RequestedRegion.SetSize(4, 1);
m_RequestedRegionInitialized=true;
GetSource()->Update();
if(IsVolumeSet(t,n))
//yes: now we can call ourselves without the risk of a endless loop (see "if" above)
return GetVolumeData(t,n,data,importMemoryManagement);
else
return NULL;
}
else
{
ImageDataItemPointer item = AllocateVolumeData(t,n,data,importMemoryManagement);
item->SetComplete(true);
return item;
}
-
}
mitk::Image::ImageDataItemPointer mitk::Image::GetChannelData(int n, void *data, ImportMemoryManagementType importMemoryManagement)
{
if(IsValidChannel(n)==false) return NULL;
ImageDataItemPointer ch, vol;
ch=m_Channels[n];
if((ch.GetPointer()!=NULL) && (ch->IsComplete()))
return ch;
// let's see if all volumes are set, so that we can (could) combine them to a channel
if(IsChannelSet(n))
{
// if there is only one time frame we do not need to combine anything
if(m_Dimensions[3]<=1)
{
vol=GetVolumeData(0,n,data,importMemoryManagement);
ch=new ImageDataItem(*vol, m_ImageDescriptor, m_ImageDescriptor->GetNumberOfDimensions(), data, importMemoryManagement == ManageMemory);
ch->SetComplete(true);
}
else
{
const size_t ptypeSize = this->m_ImageDescriptor->GetChannelTypeById(n).GetSize();
ch=m_Channels[n];
// ok, let's combine the volumes!
if(ch.GetPointer()==NULL)
ch=new ImageDataItem(this->m_ImageDescriptor, NULL, true);
ch->SetComplete(true);
size_t size=m_OffsetTable[m_Dimension-1]*(ptypeSize);
unsigned int t;
ImageDataItemPointerArray::iterator slicesIt = m_Slices.begin()+n*m_Dimensions[2]*m_Dimensions[3];
for(t=0;t<m_Dimensions[3];++t)
{
int posVol;
ImageDataItemPointer vol;
posVol=GetVolumeIndex(t,n);
vol=GetVolumeData(t,n,data,importMemoryManagement);
if(vol->GetParent()!=ch)
{
// copy data of volume in channel
size_t offset = ((size_t) t)*m_OffsetTable[3]*(ptypeSize);
std::memcpy(static_cast<char*>(ch->GetData())+offset, vol->GetData(), size);
// REVEIW FIX mitkIpPicDescriptor * pic = vol->GetPicDescriptor();
// replace old volume with reference to channel
vol=new ImageDataItem(*ch, m_ImageDescriptor, 3, data, importMemoryManagement == ManageMemory, offset);
vol->SetComplete(true);
//mitkIpFuncCopyTags(vol->GetPicDescriptor(), pic);
m_Volumes[posVol]=vol;
// get rid of slices - they may point to old volume
ImageDataItemPointer dnull=NULL;
for(unsigned int i = 0; i < m_Dimensions[2]; ++i, ++slicesIt)
{
assert(slicesIt != m_Slices.end());
*slicesIt = dnull;
}
}
}
// REVIEW FIX
// if(ch->GetPicDescriptor()->info->tags_head==NULL)
// mitkIpFuncCopyTags(ch->GetPicDescriptor(), m_Volumes[GetVolumeIndex(0,n)]->GetPicDescriptor());
}
return m_Channels[n]=ch;
}
// channel is unavailable. Can we calculate it?
if((GetSource().IsNotNull()) && (GetSource()->Updating()==false))
{
// ... wir muessen rechnen!!! ....
m_RequestedRegion.SetIndex(0, 0);
m_RequestedRegion.SetIndex(1, 0);
m_RequestedRegion.SetIndex(2, 0);
m_RequestedRegion.SetIndex(3, 0);
m_RequestedRegion.SetIndex(4, n);
m_RequestedRegion.SetSize(0, m_Dimensions[0]);
m_RequestedRegion.SetSize(1, m_Dimensions[1]);
m_RequestedRegion.SetSize(2, m_Dimensions[2]);
m_RequestedRegion.SetSize(3, m_Dimensions[3]);
m_RequestedRegion.SetSize(4, 1);
m_RequestedRegionInitialized=true;
GetSource()->Update();
// did it work?
if(IsChannelSet(n))
//yes: now we can call ourselves without the risk of a endless loop (see "if" above)
return GetChannelData(n,data,importMemoryManagement);
else
return NULL;
}
else
{
ImageDataItemPointer item = AllocateChannelData(n,data,importMemoryManagement);
item->SetComplete(true);
return item;
}
}
bool mitk::Image::IsSliceSet(int s, int t, int n) const
{
if(IsValidSlice(s,t,n)==false) return false;
if(m_Slices[GetSliceIndex(s,t,n)].GetPointer()!=NULL)
return true;
ImageDataItemPointer ch, vol;
vol=m_Volumes[GetVolumeIndex(t,n)];
if((vol.GetPointer()!=NULL) && (vol->IsComplete()))
return true;
ch=m_Channels[n];
if((ch.GetPointer()!=NULL) && (ch->IsComplete()))
return true;
return false;
}
bool mitk::Image::IsVolumeSet(int t, int n) const
{
if(IsValidVolume(t,n)==false) return false;
ImageDataItemPointer ch, vol;
// volume directly available?
vol=m_Volumes[GetVolumeIndex(t,n)];
if((vol.GetPointer()!=NULL) && (vol->IsComplete()))
return true;
// is volume available as part of a channel that is available?
ch=m_Channels[n];
if((ch.GetPointer()!=NULL) && (ch->IsComplete()))
return true;
// let's see if all slices of the volume are set, so that we can (could) combine them to a volume
unsigned int s;
for(s=0;s<m_Dimensions[2];++s)
if(m_Slices[GetSliceIndex(s,t,n)].GetPointer()==NULL)
return false;
return true;
}
bool mitk::Image::IsChannelSet(int n) const
{
if(IsValidChannel(n)==false) return false;
ImageDataItemPointer ch, vol;
ch=m_Channels[n];
if((ch.GetPointer()!=NULL) && (ch->IsComplete()))
return true;
// let's see if all volumes are set, so that we can (could) combine them to a channel
unsigned int t;
for(t=0;t<m_Dimensions[3];++t)
if(IsVolumeSet(t,n)==false)
return false;
return true;
}
bool mitk::Image::SetSlice(const void *data, int s, int t, int n)
{
// const_cast is no risk for ImportMemoryManagementType == CopyMemory
return SetImportSlice(const_cast<void*>(data), s, t, n, CopyMemory);
}
bool mitk::Image::SetVolume(const void *data, int t, int n)
{
// const_cast is no risk for ImportMemoryManagementType == CopyMemory
return SetImportVolume(const_cast<void*>(data), t, n, CopyMemory);
}
bool mitk::Image::SetChannel(const void *data, int n)
{
// const_cast is no risk for ImportMemoryManagementType == CopyMemory
return SetImportChannel(const_cast<void*>(data), n, CopyMemory);
}
bool mitk::Image::SetImportSlice(void *data, int s, int t, int n, ImportMemoryManagementType importMemoryManagement)
{
if(IsValidSlice(s,t,n)==false) return false;
ImageDataItemPointer sl;
const size_t ptypeSize = this->m_ImageDescriptor->GetChannelTypeById(n).GetSize();
if(IsSliceSet(s,t,n))
{
sl=GetSliceData(s,t,n,data,importMemoryManagement);
if(sl->GetManageMemory()==false)
{
sl=AllocateSliceData(s,t,n,data,importMemoryManagement);
if(sl.GetPointer()==NULL) return false;
}
if ( sl->GetData() != data )
std::memcpy(sl->GetData(), data, m_OffsetTable[2]*(ptypeSize));
sl->Modified();
//we have changed the data: call Modified()!
Modified();
}
else
{
sl=AllocateSliceData(s,t,n,data,importMemoryManagement);
if(sl.GetPointer()==NULL) return false;
if ( sl->GetData() != data )
std::memcpy(sl->GetData(), data, m_OffsetTable[2]*(ptypeSize));
//we just added a missing slice, which is not regarded as modification.
//Therefore, we do not call Modified()!
}
return true;
}
bool mitk::Image::SetImportVolume(void *data, int t, int n, ImportMemoryManagementType importMemoryManagement)
{
if(IsValidVolume(t,n)==false) return false;
const size_t ptypeSize = this->m_ImageDescriptor->GetChannelTypeById(n).GetSize();
ImageDataItemPointer vol;
if(IsVolumeSet(t,n))
{
vol=GetVolumeData(t,n,data,importMemoryManagement);
if(vol->GetManageMemory()==false)
{
vol=AllocateVolumeData(t,n,data,importMemoryManagement);
if(vol.GetPointer()==NULL) return false;
}
if ( vol->GetData() != data )
std::memcpy(vol->GetData(), data, m_OffsetTable[3]*(ptypeSize));
vol->Modified();
vol->SetComplete(true);
//we have changed the data: call Modified()!
Modified();
}
else
{
vol=AllocateVolumeData(t,n,data,importMemoryManagement);
if(vol.GetPointer()==NULL) return false;
if ( vol->GetData() != data )
{
std::memcpy(vol->GetData(), data, m_OffsetTable[3]*(ptypeSize));
}
vol->SetComplete(true);
this->m_ImageDescriptor->GetChannelDescriptor(n).SetData( vol->GetData() );
//we just added a missing Volume, which is not regarded as modification.
//Therefore, we do not call Modified()!
}
return true;
}
bool mitk::Image::SetImportChannel(void *data, int n, ImportMemoryManagementType importMemoryManagement)
{
if(IsValidChannel(n)==false) return false;
// channel descriptor
const size_t ptypeSize = this->m_ImageDescriptor->GetChannelTypeById(n).GetSize();
ImageDataItemPointer ch;
if(IsChannelSet(n))
{
ch=GetChannelData(n,data,importMemoryManagement);
if(ch->GetManageMemory()==false)
{
ch=AllocateChannelData(n,data,importMemoryManagement);
if(ch.GetPointer()==NULL) return false;
}
if ( ch->GetData() != data )
std::memcpy(ch->GetData(), data, m_OffsetTable[4]*(ptypeSize));
ch->Modified();
ch->SetComplete(true);
//we have changed the data: call Modified()!
Modified();
}
else
{
ch=AllocateChannelData(n,data,importMemoryManagement);
if(ch.GetPointer()==NULL) return false;
if ( ch->GetData() != data )
std::memcpy(ch->GetData(), data, m_OffsetTable[4]*(ptypeSize));
ch->SetComplete(true);
this->m_ImageDescriptor->GetChannelDescriptor(n).SetData( ch->GetData() );
//we just added a missing Channel, which is not regarded as modification.
//Therefore, we do not call Modified()!
}
return true;
}
void mitk::Image::Initialize()
{
ImageDataItemPointerArray::iterator it, end;
for( it=m_Slices.begin(), end=m_Slices.end(); it!=end; ++it )
{
(*it)=NULL;
}
for( it=m_Volumes.begin(), end=m_Volumes.end(); it!=end; ++it )
{
(*it)=NULL;
}
for( it=m_Channels.begin(), end=m_Channels.end(); it!=end; ++it )
{
(*it)=NULL;
}
m_CompleteData = NULL;
if( m_ImageStatistics == NULL)
{
m_ImageStatistics = new mitk::ImageStatisticsHolder( this );
}
SetRequestedRegionToLargestPossibleRegion();
}
void mitk::Image::Initialize(const mitk::ImageDescriptor::Pointer inDesc)
{
// store the descriptor
this->m_ImageDescriptor = inDesc;
// initialize image
this->Initialize( inDesc->GetChannelDescriptor(0).GetPixelType(), inDesc->GetNumberOfDimensions(), inDesc->GetDimensions(), 1 );
}
void mitk::Image::Initialize(const mitk::PixelType& type, unsigned int dimension, const unsigned int *dimensions, unsigned int channels)
{
Clear();
m_Dimension=dimension;
if(!dimensions)
itkExceptionMacro(<< "invalid zero dimension image");
unsigned int i;
for(i=0;i<dimension;++i)
{
if(dimensions[i]<1)
itkExceptionMacro(<< "invalid dimension[" << i << "]: " << dimensions[i]);
}
// create new array since the old was deleted
m_Dimensions = new unsigned int[MAX_IMAGE_DIMENSIONS];
// initialize the first four dimensions to 1, the remaining 4 to 0
FILL_C_ARRAY(m_Dimensions, 4, 1u);
FILL_C_ARRAY((m_Dimensions+4), 4, 0u);
// copy in the passed dimension information
std::memcpy(m_Dimensions, dimensions, sizeof(unsigned int)*m_Dimension);
this->m_ImageDescriptor = mitk::ImageDescriptor::New();
this->m_ImageDescriptor->Initialize( this->m_Dimensions, this->m_Dimension );
for(i=0;i<4;++i)
{
m_LargestPossibleRegion.SetIndex(i, 0);
m_LargestPossibleRegion.SetSize (i, m_Dimensions[i]);
}
m_LargestPossibleRegion.SetIndex(i, 0);
m_LargestPossibleRegion.SetSize(i, channels);
if(m_LargestPossibleRegion.GetNumberOfPixels()==0)
{
delete [] m_Dimensions;
m_Dimensions = NULL;
return;
}
for( unsigned int i=0u; i<channels; i++)
{
this->m_ImageDescriptor->AddNewChannel( type );
}
PlaneGeometry::Pointer planegeometry = PlaneGeometry::New();
planegeometry->InitializeStandardPlane(m_Dimensions[0], m_Dimensions[1]);
SlicedGeometry3D::Pointer slicedGeometry = SlicedGeometry3D::New();
slicedGeometry->InitializeEvenlySpaced(planegeometry, m_Dimensions[2]);
- if(dimension>=4)
- {
- TimeBounds timebounds;
- timebounds[0] = 0.0;
- timebounds[1] = 1.0;
- slicedGeometry->SetTimeBounds(timebounds);
- }
-
ProportionalTimeGeometry::Pointer timeGeometry = ProportionalTimeGeometry::New();
timeGeometry->Initialize(slicedGeometry, m_Dimensions[3]);
for (TimeStepType step = 0; step < timeGeometry->CountTimeSteps(); ++step)
{
timeGeometry->GetGeometryForTimeStep(step)->ImageGeometryOn();
}
SetTimeGeometry(timeGeometry);
ImageDataItemPointer dnull=NULL;
m_Channels.assign(GetNumberOfChannels(), dnull);
m_Volumes.assign(GetNumberOfChannels()*m_Dimensions[3], dnull);
m_Slices.assign(GetNumberOfChannels()*m_Dimensions[3]*m_Dimensions[2], dnull);
ComputeOffsetTable();
Initialize();
m_Initialized = true;
}
-void mitk::Image::Initialize(const mitk::PixelType& type, const mitk::Geometry3D& geometry, unsigned int channels, int tDim )
+void mitk::Image::Initialize(const mitk::PixelType& type, const mitk::BaseGeometry& geometry, unsigned int channels, int tDim )
{
mitk::ProportionalTimeGeometry::Pointer timeGeometry = ProportionalTimeGeometry::New();
- Geometry3D::Pointer geometry3D = geometry.Clone();
- timeGeometry->Initialize(geometry3D.GetPointer(), tDim);
+ itk::LightObject::Pointer lopointer = geometry.Clone();
+ timeGeometry->Initialize(dynamic_cast<BaseGeometry*>(lopointer.GetPointer()), tDim);
this->Initialize(type, *timeGeometry, channels, tDim);
}
void mitk::Image::Initialize(const mitk::PixelType& type, const mitk::TimeGeometry& geometry, unsigned int channels, int tDim )
{
unsigned int dimensions[5];
dimensions[0] = (unsigned int)(geometry.GetGeometryForTimeStep(0)->GetExtent(0)+0.5);
dimensions[1] = (unsigned int)(geometry.GetGeometryForTimeStep(0)->GetExtent(1)+0.5);
dimensions[2] = (unsigned int)(geometry.GetGeometryForTimeStep(0)->GetExtent(2)+0.5);
dimensions[3] = (tDim > 0) ? tDim : geometry.CountTimeSteps();
dimensions[4] = 0;
unsigned int dimension = 2;
if ( dimensions[2] > 1 )
dimension = 3;
if ( dimensions[3] > 1 )
dimension = 4;
Initialize( type, dimension, dimensions, channels );
if (geometry.CountTimeSteps() > 1)
{
TimeGeometry::Pointer cloned = geometry.Clone();
SetTimeGeometry(cloned.GetPointer());
}
else
Superclass::SetGeometry(geometry.GetGeometryForTimeStep(0));
/* //Old //TODO_GOETZ Really necessary?
mitk::BoundingBox::BoundsArrayType bounds = geometry.GetBoundingBoxInWorld()->GetBounds();
if( (bounds[0] != 0.0) || (bounds[2] != 0.0) || (bounds[4] != 0.0) )
{
SlicedGeometry3D* slicedGeometry = GetSlicedGeometry(0);
mitk::Point3D origin; origin.Fill(0.0);
slicedGeometry->IndexToWorld(origin, origin);
bounds[1]-=bounds[0]; bounds[3]-=bounds[2]; bounds[5]-=bounds[4];
bounds[0] = 0.0; bounds[2] = 0.0; bounds[4] = 0.0;
this->m_ImageDescriptor->Initialize( this->m_Dimensions, this->m_Dimension );
slicedGeometry->SetBounds(bounds);
slicedGeometry->GetIndexToWorldTransform()->SetOffset(origin.GetVnlVector().data_block());
ProportionalTimeGeometry::Pointer timeGeometry = ProportionalTimeGeometry::New();
timeGeometry->Initialize(slicedGeometry, m_Dimensions[3]);
SetTimeGeometry(timeGeometry);
}*/
}
-void mitk::Image::Initialize(const mitk::PixelType& type, int sDim, const mitk::Geometry2D& geometry2d, bool flipped, unsigned int channels, int tDim )
+void mitk::Image::Initialize(const mitk::PixelType& type, int sDim, const mitk::PlaneGeometry& geometry2d, bool flipped, unsigned int channels, int tDim )
{
SlicedGeometry3D::Pointer slicedGeometry = SlicedGeometry3D::New();
- slicedGeometry->InitializeEvenlySpaced(static_cast<Geometry2D*>(geometry2d.Clone().GetPointer()), sDim, flipped);
+ slicedGeometry->InitializeEvenlySpaced(static_cast<PlaneGeometry*>(geometry2d.Clone().GetPointer()), sDim, flipped);
Initialize(type, *slicedGeometry, channels, tDim);
}
void mitk::Image::Initialize(const mitk::Image* image)
{
Initialize(image->GetPixelType(), *image->GetTimeGeometry());
}
void mitk::Image::Initialize(vtkImageData* vtkimagedata, int channels, int tDim, int sDim, int pDim)
{
if(vtkimagedata==NULL) return;
m_Dimension=vtkimagedata->GetDataDimension();
unsigned int i, *tmpDimensions=new unsigned int[m_Dimension>4?m_Dimension:4];
for(i=0;i<m_Dimension;++i) tmpDimensions[i]=vtkimagedata->GetDimensions()[i];
if(m_Dimension<4)
{
unsigned int *p;
for(i=0,p=tmpDimensions+m_Dimension;i<4-m_Dimension;++i, ++p)
*p=1;
}
if(pDim>=0)
{
tmpDimensions[1]=pDim;
if(m_Dimension < 2)
m_Dimension = 2;
}
if(sDim>=0)
{
tmpDimensions[2]=sDim;
if(m_Dimension < 3)
m_Dimension = 3;
}
if(tDim>=0)
{
tmpDimensions[3]=tDim;
if(m_Dimension < 4)
m_Dimension = 4;
}
switch ( vtkimagedata->GetScalarType() )
{
case VTK_BIT:
case VTK_CHAR:
//pixelType.Initialize(typeid(char), vtkimagedata->GetNumberOfScalarComponents());
Initialize(mitk::MakeScalarPixelType<char>(), m_Dimension, tmpDimensions, channels);
break;
case VTK_UNSIGNED_CHAR:
//pixelType.Initialize(typeid(unsigned char), vtkimagedata->GetNumberOfScalarComponents());
Initialize(mitk::MakeScalarPixelType<unsigned char>(), m_Dimension, tmpDimensions, channels);
break;
case VTK_SHORT:
//pixelType.Initialize(typeid(short), vtkimagedata->GetNumberOfScalarComponents());
Initialize(mitk::MakeScalarPixelType<short>(), m_Dimension, tmpDimensions, channels);
break;
case VTK_UNSIGNED_SHORT:
//pixelType.Initialize(typeid(unsigned short), vtkimagedata->GetNumberOfScalarComponents());
Initialize(mitk::MakeScalarPixelType<unsigned short>(), m_Dimension, tmpDimensions, channels);
break;
case VTK_INT:
//pixelType.Initialize(typeid(int), vtkimagedata->GetNumberOfScalarComponents());
Initialize(mitk::MakeScalarPixelType<int>(), m_Dimension, tmpDimensions, channels);
break;
case VTK_UNSIGNED_INT:
//pixelType.Initialize(typeid(unsigned int), vtkimagedata->GetNumberOfScalarComponents());
Initialize(mitk::MakeScalarPixelType<unsigned int>(), m_Dimension, tmpDimensions, channels);
break;
case VTK_LONG:
//pixelType.Initialize(typeid(long), vtkimagedata->GetNumberOfScalarComponents());
Initialize(mitk::MakeScalarPixelType<long>(), m_Dimension, tmpDimensions, channels);
break;
case VTK_UNSIGNED_LONG:
//pixelType.Initialize(typeid(unsigned long), vtkimagedata->GetNumberOfScalarComponents());
Initialize(mitk::MakeScalarPixelType<unsigned long>(), m_Dimension, tmpDimensions, channels);
break;
case VTK_FLOAT:
//pixelType.Initialize(typeid(float), vtkimagedata->GetNumberOfScalarComponents());
Initialize(mitk::MakeScalarPixelType<float>(), m_Dimension, tmpDimensions, channels);
break;
case VTK_DOUBLE:
//pixelType.Initialize(typeid(double), vtkimagedata->GetNumberOfScalarComponents());
Initialize(mitk::MakeScalarPixelType<double>(), m_Dimension, tmpDimensions, channels);
break;
default:
break;
}
/*
Initialize(pixelType,
m_Dimension,
tmpDimensions,
channels);
*/
const double *spacinglist = vtkimagedata->GetSpacing();
Vector3D spacing;
FillVector3D(spacing, spacinglist[0], 1.0, 1.0);
if(m_Dimension>=2)
spacing[1]=spacinglist[1];
if(m_Dimension>=3)
spacing[2]=spacinglist[2];
// access origin of vtkImage
Point3D origin;
double vtkorigin[3];
vtkimagedata->GetOrigin(vtkorigin);
FillVector3D(origin, vtkorigin[0], 0.0, 0.0);
if(m_Dimension>=2)
origin[1]=vtkorigin[1];
if(m_Dimension>=3)
origin[2]=vtkorigin[2];
SlicedGeometry3D* slicedGeometry = GetSlicedGeometry(0);
// re-initialize PlaneGeometry with origin and direction
- PlaneGeometry* planeGeometry = static_cast<PlaneGeometry*>(slicedGeometry->GetGeometry2D(0));
+ PlaneGeometry* planeGeometry = static_cast<PlaneGeometry*>(slicedGeometry->GetPlaneGeometry(0));
planeGeometry->SetOrigin(origin);
// re-initialize SlicedGeometry3D
slicedGeometry->SetOrigin(origin);
slicedGeometry->SetSpacing(spacing);
ProportionalTimeGeometry::Pointer timeGeometry = ProportionalTimeGeometry::New();
timeGeometry->Initialize(slicedGeometry, m_Dimensions[3]);
SetTimeGeometry(timeGeometry);
delete [] tmpDimensions;
}
bool mitk::Image::IsValidSlice(int s, int t, int n) const
{
if(m_Initialized)
return ((s>=0) && (s<(int)m_Dimensions[2]) && (t>=0) && (t< (int) m_Dimensions[3]) && (n>=0) && (n< (int)GetNumberOfChannels()));
else
return false;
}
bool mitk::Image::IsValidVolume(int t, int n) const
{
if(m_Initialized)
return IsValidSlice(0, t, n);
else
return false;
}
bool mitk::Image::IsValidChannel(int n) const
{
if(m_Initialized)
return IsValidSlice(0, 0, n);
else
return false;
}
void mitk::Image::ComputeOffsetTable()
{
if(m_OffsetTable!=NULL)
delete [] m_OffsetTable;
m_OffsetTable=new size_t[m_Dimension>4 ? m_Dimension+1 : 4+1];
unsigned int i;
size_t num=1;
m_OffsetTable[0] = 1;
for (i=0; i < m_Dimension; ++i)
{
num *= m_Dimensions[i];
m_OffsetTable[i+1] = num;
}
for (;i < 4; ++i)
m_OffsetTable[i+1] = num;
}
bool mitk::Image::IsValidTimeStep(int t) const
{
return ( ( m_Dimension >= 4 && t <= (int)m_Dimensions[3] && t > 0 ) || (t == 0) );
}
void mitk::Image::Expand(unsigned int timeSteps)
{
if(timeSteps < 1) itkExceptionMacro(<< "Invalid timestep in Image!");
Superclass::Expand(timeSteps);
}
int mitk::Image::GetSliceIndex(int s, int t, int n) const
{
if(IsValidSlice(s,t,n)==false) return false;
return ((size_t)s)+((size_t) t)*m_Dimensions[2]+((size_t) n)*m_Dimensions[3]*m_Dimensions[2]; //??
}
int mitk::Image::GetVolumeIndex(int t, int n) const
{
if(IsValidVolume(t,n)==false) return false;
return ((size_t)t)+((size_t) n)*m_Dimensions[3]; //??
}
mitk::Image::ImageDataItemPointer mitk::Image::AllocateSliceData(int s, int t, int n, void *data, ImportMemoryManagementType importMemoryManagement)
{
int pos;
pos=GetSliceIndex(s,t,n);
const size_t ptypeSize = this->m_ImageDescriptor->GetChannelTypeById(n).GetSize();
// is slice available as part of a volume that is available?
ImageDataItemPointer sl, ch, vol;
vol=m_Volumes[GetVolumeIndex(t,n)];
if(vol.GetPointer()!=NULL)
{
sl=new ImageDataItem(*vol, m_ImageDescriptor, 2, data, importMemoryManagement == ManageMemory, ((size_t) s)*m_OffsetTable[2]*(ptypeSize));
sl->SetComplete(true);
return m_Slices[pos]=sl;
}
// is slice available as part of a channel that is available?
ch=m_Channels[n];
if(ch.GetPointer()!=NULL)
{
sl=new ImageDataItem(*ch, m_ImageDescriptor, 2, data, importMemoryManagement == ManageMemory, (((size_t) s)*m_OffsetTable[2]+((size_t) t)*m_OffsetTable[3])*(ptypeSize));
sl->SetComplete(true);
return m_Slices[pos]=sl;
}
// allocate new volume (instead of a single slice to keep data together!)
m_Volumes[GetVolumeIndex(t,n)]=vol=AllocateVolumeData(t,n,NULL,importMemoryManagement);
sl=new ImageDataItem(*vol, m_ImageDescriptor, 2, data, importMemoryManagement == ManageMemory, ((size_t) s)*m_OffsetTable[2]*(ptypeSize));
sl->SetComplete(true);
return m_Slices[pos]=sl;
////ALTERNATIVE:
//// allocate new slice
//sl=new ImageDataItem(*m_PixelType, 2, m_Dimensions);
//m_Slices[pos]=sl;
//return vol;
}
mitk::Image::ImageDataItemPointer mitk::Image::AllocateVolumeData(int t, int n, void *data, ImportMemoryManagementType importMemoryManagement)
{
int pos;
pos=GetVolumeIndex(t,n);
const size_t ptypeSize = this->m_ImageDescriptor->GetChannelTypeById(n).GetSize();
// is volume available as part of a channel that is available?
ImageDataItemPointer ch, vol;
ch=m_Channels[n];
if(ch.GetPointer()!=NULL)
{
vol=new ImageDataItem(*ch, m_ImageDescriptor, 3, data,importMemoryManagement == ManageMemory, (((size_t) t)*m_OffsetTable[3])*(ptypeSize));
return m_Volumes[pos]=vol;
}
mitk::PixelType chPixelType = this->m_ImageDescriptor->GetChannelTypeById(n);
// allocate new volume
if(importMemoryManagement == CopyMemory)
{
vol=new ImageDataItem( chPixelType, 3, m_Dimensions, NULL, true);
if(data != NULL)
std::memcpy(vol->GetData(), data, m_OffsetTable[3]*(ptypeSize));
}
else
{
vol=new ImageDataItem( chPixelType, 3, m_Dimensions, data, importMemoryManagement == ManageMemory);
}
m_Volumes[pos]=vol;
return vol;
}
mitk::Image::ImageDataItemPointer mitk::Image::AllocateChannelData(int n, void *data, ImportMemoryManagementType importMemoryManagement)
{
ImageDataItemPointer ch;
// allocate new channel
if(importMemoryManagement == CopyMemory)
{
const size_t ptypeSize = this->m_ImageDescriptor->GetChannelTypeById(n).GetSize();
ch=new ImageDataItem(this->m_ImageDescriptor, NULL, true);
if(data != NULL)
std::memcpy(ch->GetData(), data, m_OffsetTable[4]*(ptypeSize));
}
else
{
ch=new ImageDataItem(this->m_ImageDescriptor, data, importMemoryManagement == ManageMemory);
}
m_Channels[n]=ch;
return ch;
}
unsigned int* mitk::Image::GetDimensions() const
{
return m_Dimensions;
}
void mitk::Image::Clear()
{
Superclass::Clear();
delete [] m_Dimensions;
m_Dimensions = NULL;
}
-void mitk::Image::SetGeometry(Geometry3D* aGeometry3D)
+void mitk::Image::SetGeometry(BaseGeometry* aGeometry3D)
{
// Please be aware of the 0.5 offset/pixel-center issue! See Geometry documentation for further information
if(aGeometry3D->GetImageGeometry()==false)
{
MITK_INFO << "WARNING: Applied a non-image geometry onto an image. Please be SURE that this geometry is pixel-center-based! If it is not, you need to call Geometry3D->ChangeImageGeometryConsideringOriginOffset(true) before calling image->setGeometry(..)\n";
}
Superclass::SetGeometry(aGeometry3D);
for (TimeStepType step = 0; step < GetTimeGeometry()->CountTimeSteps(); ++step)
GetTimeGeometry()->GetGeometryForTimeStep(step)->ImageGeometryOn();
}
void mitk::Image::PrintSelf(std::ostream& os, itk::Indent indent) const
{
unsigned char i;
if(m_Initialized)
{
os << indent << " Dimension: " << m_Dimension << std::endl;
os << indent << " Dimensions: ";
for(i=0; i < m_Dimension; ++i)
os << GetDimension(i) << " ";
os << std::endl;
for(unsigned int ch=0; ch < this->m_ImageDescriptor->GetNumberOfChannels(); ch++)
{
mitk::PixelType chPixelType = this->m_ImageDescriptor->GetChannelTypeById(ch);
os << indent << " Channel: " << this->m_ImageDescriptor->GetChannelName(ch) << std::endl;
os << indent << " PixelType: " << chPixelType.GetPixelTypeAsString() << std::endl;
os << indent << " BytesPerElement: " << chPixelType.GetSize() << std::endl;
os << indent << " ComponentType: " << chPixelType.GetComponentTypeAsString() << std::endl;
os << indent << " NumberOfComponents: " << chPixelType.GetNumberOfComponents() << std::endl;
os << indent << " BitsPerComponent: " << chPixelType.GetBitsPerComponent() << std::endl;
}
-
}
else
{
os << indent << " Image not initialized: m_Initialized: false" << std::endl;
}
Superclass::PrintSelf(os,indent);
}
bool mitk::Image::IsRotated() const
{
- const mitk::Geometry3D* geo = this->GetGeometry();
+ const mitk::BaseGeometry* geo = this->GetGeometry();
bool ret = false;
if(geo)
{
const vnl_matrix_fixed<ScalarType, 3, 3> & mx = geo->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix();
mitk::ScalarType ref = 0;
for(short k = 0; k < 3; ++k)
ref += mx[k][k];
ref/=1000; // Arbitrary value; if a non-diagonal (nd) element is bigger then this, matrix is considered nd.
for(short i = 0; i < 3; ++i)
{
for(short j = 0; j < 3; ++j)
{
if(i != j)
{
if(std::abs(mx[i][j]) > ref) // matrix is nd
ret = true;
}
}
}
}
return ret;
}
mitk::ScalarType mitk::Image::GetScalarValueMin(int t) const
{
return m_ImageStatistics->GetScalarValueMin(t);
}
//## \brief Get the maximum for scalar images
mitk::ScalarType mitk::Image::GetScalarValueMax(int t) const
{
return m_ImageStatistics->GetScalarValueMax(t);
}
//## \brief Get the second smallest value for scalar images
mitk::ScalarType mitk::Image::GetScalarValue2ndMin(int t) const
{
return m_ImageStatistics->GetScalarValue2ndMin(t);
}
mitk::ScalarType mitk::Image::GetScalarValueMinNoRecompute( unsigned int t ) const
{
return m_ImageStatistics->GetScalarValueMinNoRecompute(t);
}
mitk::ScalarType mitk::Image::GetScalarValue2ndMinNoRecompute( unsigned int t ) const
{
return m_ImageStatistics->GetScalarValue2ndMinNoRecompute(t);
}
mitk::ScalarType mitk::Image::GetScalarValue2ndMax(int t) const
{
return m_ImageStatistics->GetScalarValue2ndMax(t);
}
mitk::ScalarType mitk::Image::GetScalarValueMaxNoRecompute( unsigned int t) const
{
return m_ImageStatistics->GetScalarValueMaxNoRecompute(t);
}
mitk::ScalarType mitk::Image::GetScalarValue2ndMaxNoRecompute( unsigned int t ) const
{
return m_ImageStatistics->GetScalarValue2ndMaxNoRecompute(t);
}
mitk::ScalarType mitk::Image::GetCountOfMinValuedVoxels(int t ) const
{
return m_ImageStatistics->GetCountOfMinValuedVoxels(t);
}
mitk::ScalarType mitk::Image::GetCountOfMaxValuedVoxels(int t) const
{
return m_ImageStatistics->GetCountOfMaxValuedVoxels(t);
}
unsigned int mitk::Image::GetCountOfMaxValuedVoxelsNoRecompute( unsigned int t ) const
{
return m_ImageStatistics->GetCountOfMaxValuedVoxelsNoRecompute(t);
}
unsigned int mitk::Image::GetCountOfMinValuedVoxelsNoRecompute( unsigned int t ) const
{
return m_ImageStatistics->GetCountOfMinValuedVoxelsNoRecompute(t);
}
bool mitk::Equal(const mitk::Image* leftHandSide, const mitk::Image* rightHandSide, ScalarType eps, bool verbose)
{
if((leftHandSide == NULL) || (rightHandSide == NULL))
{
MITK_ERROR << "mitk::Equal(const mitk::Image* leftHandSide, const mitk::Image* rightHandSide, ScalarType eps, bool verbose) does not work with NULL pointer input.";
return false;
}
return mitk::Equal( *leftHandSide, *rightHandSide, eps, verbose);
}
bool mitk::Equal(const mitk::Image& leftHandSide, const mitk::Image& rightHandSide, ScalarType eps, bool verbose)
{
bool returnValue = true;
// Dimensionality
if( rightHandSide.GetDimension() != leftHandSide.GetDimension() )
{
if(verbose)
{
MITK_INFO << "[( Image )] Dimensionality differs.";
MITK_INFO << "leftHandSide is " << leftHandSide.GetDimension()
<< "rightHandSide is " << rightHandSide.GetDimension();
}
returnValue = false;
}
// Pair-wise dimension (size) comparison
unsigned int minDimensionality = std::min(rightHandSide.GetDimension(),leftHandSide.GetDimension());
for( unsigned int i=0; i< minDimensionality; ++i)
{
if( rightHandSide.GetDimension(i) != leftHandSide.GetDimension(i) )
{
returnValue = false;
if(verbose)
{
MITK_INFO << "[( Image )] dimension differs.";
MITK_INFO << "leftHandSide->GetDimension("<<i<<") is " << leftHandSide.GetDimension(i)
<< "rightHandSide->GetDimension("<<i<<") is " << rightHandSide.GetDimension(i);
}
}
}
// Pixeltype
mitk::PixelType pixelTypeRightHandSide = rightHandSide.GetPixelType();
mitk::PixelType pixelTypeLeftHandSide = leftHandSide.GetPixelType();
if( !( pixelTypeRightHandSide == pixelTypeLeftHandSide ) )
{
if(verbose)
{
MITK_INFO << "[( Image )] PixelType differs.";
MITK_INFO << "leftHandSide is " << pixelTypeLeftHandSide.GetTypeAsString()
<< "rightHandSide is " << pixelTypeRightHandSide.GetTypeAsString();
}
returnValue = false;
}
// Geometries
if( !mitk::Equal( leftHandSide.GetGeometry(),
rightHandSide.GetGeometry(), eps, verbose) )
{
if(verbose)
{
MITK_INFO << "[( Image )] Geometries differ.";
}
returnValue = false;
}
// Pixel values - default mode [ 0 threshold in difference ]
// compare only if all previous checks were successfull, otherwise the ITK filter will throw an exception
if( returnValue )
{
mitk::CompareImageDataFilter::Pointer compareFilter = mitk::CompareImageDataFilter::New();
compareFilter->SetInput(0, &rightHandSide);
compareFilter->SetInput(1, &leftHandSide);
compareFilter->SetTolerance(eps);
compareFilter->Update();
if(( !compareFilter->GetResult() ) )
{
returnValue = false;
if(verbose)
{
MITK_INFO << "[(Image)] Pixel values differ: ";
compareFilter->GetCompareResults().PrintSelf();
}
}
}
return returnValue;
}
diff --git a/Core/Code/DataManagement/mitkImage.h b/Core/Code/DataManagement/mitkImage.h
index 7ff5ab3a79..d35bf688b2 100644
--- a/Core/Code/DataManagement/mitkImage.h
+++ b/Core/Code/DataManagement/mitkImage.h
@@ -1,737 +1,737 @@
/*===================================================================
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 MITKIMAGE_H_HEADER_INCLUDED_C1C2FCD2
#define MITKIMAGE_H_HEADER_INCLUDED_C1C2FCD2
#include <MitkCoreExports.h>
#include "mitkSlicedData.h"
#include "mitkBaseData.h"
#include "mitkLevelWindow.h"
#include "mitkPlaneGeometry.h"
#include <mitkProportionalTimeGeometry.h>
#include "mitkImageDataItem.h"
#include "mitkImageDescriptor.h"
#include "mitkImageAccessorBase.h"
#include "mitkImageVtkAccessor.h"
//DEPRECATED
#include <mitkTimeSlicedGeometry.h>
#ifndef __itkHistogram_h
#include <itkHistogram.h>
#endif
class vtkImageData;
namespace mitk {
class SubImageSelector;
class ImageTimeSelector;
class ImageStatisticsHolder;
//##Documentation
//## @brief Image class for storing images
//##
//## Can be asked for header information, the data vector,
//## the mitkIpPicDescriptor struct or vtkImageData objects. If not the complete
//## data is required, the appropriate SubImageSelector class should be used
//## for access.
//## Image organizes sets of slices (s x 2D), volumes (t x 3D) and channels (n
//## x ND). Channels are for different kind of data, e.g., morphology in
//## channel 0, velocities in channel 1. All channels must have the same Geometry! In
//## particular, the dimensions of all channels are the same, only the pixel-type
//## may differ between channels.
//##
//## For importing ITK images use of mitk::ITKImageImport is recommended, see
//## \ref Adaptor.
//##
//## For ITK v3.8 and older: Converting coordinates from the ITK physical
//## coordinate system (which does not support rotated images) to the MITK world
-//## coordinate system should be performed via the Geometry3D of the Image, see
-//## Geometry3D::WorldToItkPhysicalPoint.
+//## coordinate system should be performed via the BaseGeometry of the Image, see
+//## BaseGeometry::WorldToItkPhysicalPoint.
//##
//## For more information, see \ref MitkImagePage .
//## @ingroup Data
class MITK_CORE_EXPORT Image : public SlicedData
{
friend class SubImageSelector;
friend class ImageAccessorBase;
friend class ImageVtkAccessor;
friend class ImageReadAccessor;
friend class ImageWriteAccessor;
public:
mitkClassMacro(Image, SlicedData);
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Smart Pointer type to a ImageDataItem. */
typedef itk::SmartPointer<ImageDataItem> ImageDataItemPointer;
typedef itk::Statistics::Histogram<double> HistogramType;
typedef mitk::ImageStatisticsHolder* StatisticsHolderPointer;
//## @param ImportMemoryManagementType This parameter is evaluated when setting new data to an image.
//## The different options are:
//## CopyMemory: Data to be set is copied and assigned to a new memory block. Data memory block will be freed on deletion of mitk::Image.
//## MamageMemory: Data to be set will be referenced, and Data memory block will be freed on deletion of mitk::Image.
//## Reference Memory: Data to be set will be referenced, but Data memory block will not be freed on deletion of mitk::Image.
//## DontManageMemory = ReferenceMemory.
enum ImportMemoryManagementType { CopyMemory, ManageMemory, ReferenceMemory, DontManageMemory = ReferenceMemory };
//##Documentation
//## @brief Vector container of SmartPointers to ImageDataItems;
//## Class is only for internal usage to allow convenient access to all slices over iterators;
//## See documentation of ImageDataItem for details.
typedef std::vector<ImageDataItemPointer> ImageDataItemPointerArray;
public:
//##Documentation
//## @brief Returns the PixelType of channel @a n.
const mitk::PixelType GetPixelType(int n = 0) const;
//##Documentation
//## @brief Get dimension of the image
//##
unsigned int GetDimension() const;
//##Documentation
//## @brief Get the size of dimension @a i (e.g., i=0 results in the number of pixels in x-direction).
//##
//## @sa GetDimensions()
unsigned int GetDimension(int i) const;
/** @brief Get the data vector of the complete image, i.e., of all channels linked together.
If you only want to access a slice, volume at a specific time or single channel
use one of the SubImageSelector classes.
\deprecatedSince{2012_09} Please use image accessors instead: See Doxygen/Related-Pages/Concepts/Image. This method can be replaced by ImageWriteAccessor::GetData() or ImageReadAccessor::GetData() */
DEPRECATED(virtual void* GetData());
public:
/** @brief Get the pixel value at one specific index position.
The pixel type is always being converted to double.
\deprecatedSince{2012_09} Please use image accessors instead: See Doxygen/Related-Pages/Concepts/Image. This method can be replaced by a method from ImagePixelWriteAccessor or ImagePixelReadAccessor */
DEPRECATED(double GetPixelValueByIndex(const mitk::Index3D& position, unsigned int timestep = 0));
/** @brief Get the pixel value at one specific world position.
The pixel type is always being converted to double.
\deprecatedSince{2012_09} Please use image accessors instead: See Doxygen/Related-Pages/Concepts/Image. This method can be replaced by a method from ImagePixelWriteAccessor or ImagePixelReadAccessor */
DEPRECATED(double GetPixelValueByWorldCoordinate(const mitk::Point3D& position, unsigned int timestep = 0));
//##Documentation
//## @brief Get a volume at a specific time @a t of channel @a n as a vtkImageData.
virtual ImageVtkAccessor* GetVtkImageData(int t = 0, int n = 0);
//##Documentation
//## @brief Get the complete image, i.e., all channels linked together, as a @a mitkIpPicDescriptor.
//##
//## If you only want to access a slice, volume at a specific time or single channel
//## use one of the SubImageSelector classes.
//virtual mitkIpPicDescriptor* GetPic();
//##Documentation
//## @brief Check whether slice @a s at time @a t in channel @a n is set
virtual bool IsSliceSet(int s = 0, int t = 0, int n = 0) const;
//##Documentation
//## @brief Check whether volume at time @a t in channel @a n is set
virtual bool IsVolumeSet(int t = 0, int n = 0) const;
//##Documentation
//## @brief Check whether the channel @a n is set
virtual bool IsChannelSet(int n = 0) const;
//##Documentation
//## @brief Set @a data as slice @a s at time @a t in channel @a n. It is in
//## the responsibility of the caller to ensure that the data vector @a data
//## is really a slice (at least is not smaller than a slice), since there is
//## no chance to check this.
//##
//## The data is copied to an array managed by the image. If the image shall
//## reference the data, use SetImportSlice with ImportMemoryManagementType
//## set to ReferenceMemory. For importing ITK images use of mitk::
//## ITKImageImport is recommended.
//## @sa SetPicSlice, SetImportSlice, SetImportVolume
virtual bool SetSlice(const void *data, int s = 0, int t = 0, int n = 0);
//##Documentation
//## @brief Set @a data as volume at time @a t in channel @a n. It is in
//## the responsibility of the caller to ensure that the data vector @a data
//## is really a volume (at least is not smaller than a volume), since there is
//## no chance to check this.
//##
//## The data is copied to an array managed by the image. If the image shall
//## reference the data, use SetImportVolume with ImportMemoryManagementType
//## set to ReferenceMemory. For importing ITK images use of mitk::
//## ITKImageImport is recommended.
//## @sa SetPicVolume, SetImportVolume
virtual bool SetVolume(const void *data, int t = 0, int n = 0);
//##Documentation
//## @brief Set @a data in channel @a n. It is in
//## the responsibility of the caller to ensure that the data vector @a data
//## is really a channel (at least is not smaller than a channel), since there is
//## no chance to check this.
//##
//## The data is copied to an array managed by the image. If the image shall
//## reference the data, use SetImportChannel with ImportMemoryManagementType
//## set to ReferenceMemory. For importing ITK images use of mitk::
//## ITKImageImport is recommended.
//## @sa SetPicChannel, SetImportChannel
virtual bool SetChannel(const void *data, int n = 0);
//##Documentation
//## @brief Set @a data as slice @a s at time @a t in channel @a n. It is in
//## the responsibility of the caller to ensure that the data vector @a data
//## is really a slice (at least is not smaller than a slice), since there is
//## no chance to check this.
//##
//## The data is managed according to the parameter \a importMemoryManagement.
//## @sa SetPicSlice
virtual bool SetImportSlice(void *data, int s = 0, int t = 0, int n = 0, ImportMemoryManagementType importMemoryManagement = CopyMemory );
//##Documentation
//## @brief Set @a data as volume at time @a t in channel @a n. It is in
//## the responsibility of the caller to ensure that the data vector @a data
//## is really a volume (at least is not smaller than a volume), since there is
//## no chance to check this.
//##
//## The data is managed according to the parameter \a importMemoryManagement.
//## @sa SetPicVolume
virtual bool SetImportVolume(void *data, int t = 0, int n = 0, ImportMemoryManagementType importMemoryManagement = CopyMemory );
//##Documentation
//## @brief Set @a data in channel @a n. It is in
//## the responsibility of the caller to ensure that the data vector @a data
//## is really a channel (at least is not smaller than a channel), since there is
//## no chance to check this.
//##
//## The data is managed according to the parameter \a importMemoryManagement.
//## @sa SetPicChannel
virtual bool SetImportChannel(void *data, int n = 0, ImportMemoryManagementType importMemoryManagement = CopyMemory );
//##Documentation
//## initialize new (or re-initialize) image information
//## @warning Initialize() by pic assumes a plane, evenly spaced geometry starting at (0,0,0).
virtual void Initialize(const mitk::PixelType& type, unsigned int dimension, const unsigned int *dimensions, unsigned int channels = 1);
//##Documentation
- //## initialize new (or re-initialize) image information by a Geometry3D
+ //## initialize new (or re-initialize) image information by a BaseGeometry
//##
//## @param tDim defines the number of time steps for which the Image should be initialized
- virtual void Initialize(const mitk::PixelType& type, const mitk::Geometry3D& geometry, unsigned int channels = 1, int tDim=1);
+ virtual void Initialize(const mitk::PixelType& type, const mitk::BaseGeometry& geometry, unsigned int channels = 1, int tDim=1);
/**
- * initialize new (or re-initialize) image information by a Geometry3D
+ * initialize new (or re-initialize) image information by a TimeGeometry
*
* @param tDim defines the number of time steps for which the Image should be initialized
* \deprecatedSince{2013_09} Please use TimeGeometry instead of TimeSlicedGeometry. For more information see http://www.mitk.org/Development/Refactoring%20of%20the%20Geometry%20Classes%20-%20Part%201
*/
DEPRECATED(virtual void Initialize(const mitk::PixelType& /*type*/, const mitk::TimeSlicedGeometry* /*geometry*/, unsigned int /*channels = 1*/, int /*tDim=1*/)){}
/**
* \brief Initialize new (or re-initialize) image information by a TimeGeometry
*
* \param tDim override time dimension if the value is bigger than 0 (Default -1)
*/
virtual void Initialize(const mitk::PixelType& type, const mitk::TimeGeometry& geometry, unsigned int channels = 1, int tDim=-1 );
//##Documentation
- //## initialize new (or re-initialize) image information by a Geometry2D and number of slices
+ //## initialize new (or re-initialize) image information by a PlaneGeometry and number of slices
//##
//## Initializes the bounding box according to the width/height of the
- //## Geometry2D and @a sDim via SlicedGeometry3D::InitializeEvenlySpaced.
- //## The spacing is calculated from the Geometry2D.
+ //## PlaneGeometry and @a sDim via SlicedGeometry3D::InitializeEvenlySpaced.
+ //## The spacing is calculated from the PlaneGeometry.
//## \sa SlicedGeometry3D::InitializeEvenlySpaced
- virtual void Initialize(const mitk::PixelType& type, int sDim, const mitk::Geometry2D& geometry2d, bool flipped = false, unsigned int channels = 1, int tDim=1);
+ virtual void Initialize(const mitk::PixelType& type, int sDim, const mitk::PlaneGeometry& geometry2d, bool flipped = false, unsigned int channels = 1, int tDim=1);
//##Documentation
//## initialize new (or re-initialize) image information by another
//## mitk-image.
//## Only the header is used, not the data vector!
//##
virtual void Initialize(const mitk::Image* image);
virtual void Initialize(const mitk::ImageDescriptor::Pointer inDesc);
//##Documentation
//## initialize new (or re-initialize) image information by @a pic.
- //## Dimensions and @a Geometry3D /@a Geometry2D are set according
+ //## Dimensions and @a Geometry3D /@a PlaneGeometry are set according
//## to the tags in @a pic.
//## Only the header is used, not the data vector! Use SetPicVolume(pic)
//## to set the data vector.
//##
//## @param tDim override time dimension (@a n[3]) in @a pic (if >0)
//## @param sDim override z-space dimension (@a n[2]) in @a pic (if >0)
//## @warning Initialize() by pic assumes a plane, evenly spaced geometry starting at (0,0,0).
//virtual void Initialize(const mitkIpPicDescriptor* pic, int channels = 1, int tDim = -1, int sDim = -1);
//##Documentation
//## initialize new (or re-initialize) image information by @a vtkimagedata,
//## a vtk-image.
//## Only the header is used, not the data vector! Use
//## SetVolume(vtkimage->GetScalarPointer()) to set the data vector.
//##
//## @param tDim override time dimension in @a vtkimagedata (if >0 and <)
//## @param sDim override z-space dimension in @a vtkimagedata (if >0 and <)
//## @param pDim override y-space dimension in @a vtkimagedata (if >0 and <)
virtual void Initialize(vtkImageData* vtkimagedata, int channels = 1, int tDim = -1, int sDim = -1, int pDim = -1);
//##Documentation
//## initialize new (or re-initialize) image information by @a itkimage,
//## a templated itk-image.
//## Only the header is used, not the data vector! Use
//## SetVolume(itkimage->GetBufferPointer()) to set the data vector.
//##
//## @param tDim override time dimension in @a itkimage (if >0 and <)
//## @param sDim override z-space dimension in @a itkimage (if >0 and <)
template <typename itkImageType> void InitializeByItk(const itkImageType* itkimage, int channels = 1, int tDim = -1, int sDim=-1)
{
if(itkimage==NULL) return;
MITK_DEBUG << "Initializing MITK image from ITK image.";
// build array with dimensions in each direction with at least 4 entries
m_Dimension=itkimage->GetImageDimension();
unsigned int i, *tmpDimensions=new unsigned int[m_Dimension>4?m_Dimension:4];
for(i=0;i<m_Dimension;++i)
tmpDimensions[i]=itkimage->GetLargestPossibleRegion().GetSize().GetSize()[i];
if(m_Dimension<4)
{
unsigned int *p;
for(i=0,p=tmpDimensions+m_Dimension;i<4-m_Dimension;++i, ++p)
*p=1;
}
// overwrite number of slices if sDim is set
if((m_Dimension>2) && (sDim>=0))
tmpDimensions[2]=sDim;
// overwrite number of time points if tDim is set
if((m_Dimension>3) && (tDim>=0))
tmpDimensions[3]=tDim;
// rough initialization of Image
// mitk::PixelType importType = ImportItkPixelType( itkimage::PixelType );
Initialize(MakePixelType<itkImageType>(),
m_Dimension,
tmpDimensions,
channels);
const typename itkImageType::SpacingType & itkspacing = itkimage->GetSpacing();
MITK_DEBUG << "ITK spacing " << itkspacing;
// access spacing of itk::Image
Vector3D spacing;
FillVector3D(spacing, itkspacing[0], 1.0, 1.0);
if(m_Dimension >= 2)
spacing[1]=itkspacing[1];
if(m_Dimension >= 3)
spacing[2]=itkspacing[2];
// access origin of itk::Image
Point3D origin;
const typename itkImageType::PointType & itkorigin = itkimage->GetOrigin();
MITK_DEBUG << "ITK origin " << itkorigin;
FillVector3D(origin, itkorigin[0], 0.0, 0.0);
if(m_Dimension>=2)
origin[1]=itkorigin[1];
if(m_Dimension>=3)
origin[2]=itkorigin[2];
// access direction of itk::Imagm_PixelType = new mitk::PixelType(type);e and include spacing
const typename itkImageType::DirectionType & itkdirection = itkimage->GetDirection();
MITK_DEBUG << "ITK direction " << itkdirection;
mitk::Matrix3D matrix;
matrix.SetIdentity();
unsigned int j, itkDimMax3 = (m_Dimension >= 3? 3 : m_Dimension);
// check if spacing has no zero entry and itkdirection has no zero columns
bool itkdirectionOk = true;
mitk::ScalarType columnSum;
for( j=0; j < itkDimMax3; ++j )
{
columnSum = 0.0;
for ( i=0; i < itkDimMax3; ++i)
{
columnSum += fabs(itkdirection[i][j]);
}
if(columnSum < mitk::eps)
{
itkdirectionOk = false;
}
if ( (spacing[j] < - mitk::eps) // (normally sized) negative value
&& (j==2) && (m_Dimensions[2] == 1) )
{
// Negative spacings can occur when reading single DICOM slices with ITK via GDCMIO
// In these cases spacing is not determind by ITK correctly (because it distinguishes correctly
// between slice thickness and inter slice distance -- slice distance is meaningless for
// single slices).
// I experienced that ITK produced something meaningful nonetheless because is is
// evaluating the tag "(0018,0088) Spacing between slices" as a fallback. This tag is not
// reliable (http://www.itk.org/pipermail/insight-users/2005-September/014711.html)
// but gives at least a hint.
// In real world cases I experienced that this tag contained the correct inter slice distance
// with a negative sign, so we just invert such negative spacings.
MITK_WARN << "Illegal value of itk::Image::GetSpacing()[" << j <<"]=" << spacing[j] << ". Using inverted value " << -spacing[j];
spacing[j] = -spacing[j];
}
else if (spacing[j] < mitk::eps) // value near zero
{
MITK_ERROR << "Illegal value of itk::Image::GetSpacing()[" << j <<"]=" << spacing[j] << ". Using 1.0 instead.";
spacing[j] = 1.0;
}
}
if(itkdirectionOk == false)
{
MITK_ERROR << "Illegal matrix returned by itk::Image::GetDirection():" << itkdirection << " Using identity instead.";
for ( i=0; i < itkDimMax3; ++i)
for( j=0; j < itkDimMax3; ++j )
if ( i == j )
matrix[i][j] = spacing[j];
else
matrix[i][j] = 0.0;
}
else
{
for ( i=0; i < itkDimMax3; ++i)
for( j=0; j < itkDimMax3; ++j )
matrix[i][j] = itkdirection[i][j]*spacing[j];
}
// re-initialize PlaneGeometry with origin and direction
- PlaneGeometry* planeGeometry = static_cast<PlaneGeometry*>(GetSlicedGeometry(0)->GetGeometry2D(0));
+ PlaneGeometry* planeGeometry = static_cast<PlaneGeometry*>(GetSlicedGeometry(0)->GetPlaneGeometry(0));
planeGeometry->SetOrigin(origin);
planeGeometry->GetIndexToWorldTransform()->SetMatrix(matrix);
// re-initialize SlicedGeometry3D
SlicedGeometry3D* slicedGeometry = GetSlicedGeometry(0);
slicedGeometry->InitializeEvenlySpaced(planeGeometry, m_Dimensions[2]);
slicedGeometry->SetSpacing(spacing);
// re-initialize TimeGeometry
ProportionalTimeGeometry::Pointer timeGeometry = ProportionalTimeGeometry::New();
timeGeometry->Initialize(slicedGeometry, m_Dimensions[3]);
SetTimeGeometry(timeGeometry);
// clean-up
delete [] tmpDimensions;
this->Initialize();
};
//##Documentation
//## @brief Check whether slice @a s at time @a t in channel @a n is valid, i.e.,
//## is (or can be) inside of the image
virtual bool IsValidSlice(int s = 0, int t = 0, int n = 0) const;
//##Documentation
//## @brief Check whether volume at time @a t in channel @a n is valid, i.e.,
//## is (or can be) inside of the image
virtual bool IsValidVolume(int t = 0, int n = 0) const;
//##Documentation
//## @brief Check whether the channel @a n is valid, i.e.,
//## is (or can be) inside of the image
virtual bool IsValidChannel(int n = 0) const;
//##Documentation
//## @brief Returns true if an image is rotated, i.e. its geometry's
//## transformation matrix has nonzero elements besides the diagonal.
//## Non-diagonal elements are checked if larger then 1/1000 of the matrix' trace.
bool IsRotated() const;
//##Documentation
//## @brief Get the sizes of all dimensions as an integer-array.
//##
//## @sa GetDimension(int i);
unsigned int* GetDimensions() const;
ImageDescriptor::Pointer GetImageDescriptor() const
{ return m_ImageDescriptor; }
ChannelDescriptor GetChannelDescriptor( int id = 0 ) const
{ return m_ImageDescriptor->GetChannelDescriptor(id); }
/** \brief Sets a geometry to an image.
*/
- virtual void SetGeometry(Geometry3D* aGeometry3D);
+ virtual void SetGeometry(BaseGeometry* aGeometry3D);
/**
* @warning for internal use only
*/
virtual ImageDataItemPointer GetSliceData(int s = 0, int t = 0, int n = 0, void *data = NULL, ImportMemoryManagementType importMemoryManagement = CopyMemory);
/**
* @warning for internal use only
*/
virtual ImageDataItemPointer GetVolumeData(int t = 0, int n = 0, void *data = NULL, ImportMemoryManagementType importMemoryManagement = CopyMemory);
/**
* @warning for internal use only
*/
virtual ImageDataItemPointer GetChannelData(int n = 0, void *data = NULL, ImportMemoryManagementType importMemoryManagement = CopyMemory);
/**
\brief (DEPRECATED) Get the minimum for scalar images
*/
DEPRECATED (ScalarType GetScalarValueMin(int t=0) const);
/**
\brief (DEPRECATED) Get the maximum for scalar images
\warning This method is deprecated and will not be available in the future. Use the \a GetStatistics instead
*/
DEPRECATED (ScalarType GetScalarValueMax(int t=0) const);
/**
\brief (DEPRECATED) Get the second smallest value for scalar images
\warning This method is deprecated and will not be available in the future. Use the \a GetStatistics instead
*/
DEPRECATED (ScalarType GetScalarValue2ndMin(int t=0) const);
/**
\brief (DEPRECATED) Get the smallest value for scalar images, but do not recompute it first
\warning This method is deprecated and will not be available in the future. Use the \a GetStatistics instead
*/
DEPRECATED (ScalarType GetScalarValueMinNoRecompute( unsigned int t = 0 ) const);
/**
\brief (DEPRECATED) Get the second smallest value for scalar images, but do not recompute it first
\warning This method is deprecated and will not be available in the future. Use the \a GetStatistics instead
*/
DEPRECATED (ScalarType GetScalarValue2ndMinNoRecompute( unsigned int t = 0 ) const);
/**
\brief (DEPRECATED) Get the second largest value for scalar images
\warning This method is deprecated and will not be available in the future. Use the \a GetStatistics instead
*/
DEPRECATED (ScalarType GetScalarValue2ndMax(int t=0) const);
/**
\brief (DEPRECATED) Get the largest value for scalar images, but do not recompute it first
\warning This method is deprecated and will not be available in the future. Use the \a GetStatistics instead
*/
DEPRECATED (ScalarType GetScalarValueMaxNoRecompute( unsigned int t = 0 ) const );
/**
\brief (DEPRECATED) Get the second largest value for scalar images, but do not recompute it first
\warning This method is deprecated and will not be available in the future. Use the \a GetStatistics instead
*/
DEPRECATED (ScalarType GetScalarValue2ndMaxNoRecompute( unsigned int t = 0 ) const);
/**
\brief (DEPRECATED) Get the count of voxels with the smallest scalar value in the dataset
\warning This method is deprecated and will not be available in the future. Use the \a GetStatistics instead
*/
DEPRECATED (ScalarType GetCountOfMinValuedVoxels(int t = 0) const);
/**
\brief (DEPRECATED) Get the count of voxels with the largest scalar value in the dataset
\warning This method is deprecated and will not be available in the future. Use the \a GetStatistics instead
*/
DEPRECATED (ScalarType GetCountOfMaxValuedVoxels(int t = 0) const);
/**
\brief (DEPRECATED) Get the count of voxels with the largest scalar value in the dataset
\warning This method is deprecated and will not be available in the future. Use the \a GetStatistics instead
*/
DEPRECATED (unsigned int GetCountOfMaxValuedVoxelsNoRecompute( unsigned int t = 0 ) const);
/**
\brief (DEPRECATED) Get the count of voxels with the smallest scalar value in the dataset
\warning This method is deprecated and will not be available in the future. Use the \a GetStatistics instead
*/
DEPRECATED (unsigned int GetCountOfMinValuedVoxelsNoRecompute( unsigned int t = 0 ) const);
/**
\brief Returns a pointer to the ImageStatisticsHolder object that holds all statistics information for the image.
All Get-methods for statistics properties formerly accessible directly from an Image object are now moved to the
new \a ImageStatisticsHolder object.
*/
StatisticsHolderPointer GetStatistics() const
{
return m_ImageStatistics;
}
protected:
mitkCloneMacro(Self);
int GetSliceIndex(int s = 0, int t = 0, int n = 0) const;
int GetVolumeIndex(int t = 0, int n = 0) const;
void ComputeOffsetTable();
virtual bool IsValidTimeStep(int t) const;
virtual void Expand( unsigned int timeSteps );
virtual ImageDataItemPointer AllocateSliceData(int s = 0, int t = 0, int n = 0, void *data = NULL, ImportMemoryManagementType importMemoryManagement = CopyMemory);
virtual ImageDataItemPointer AllocateVolumeData(int t = 0, int n = 0, void *data = NULL, ImportMemoryManagementType importMemoryManagement = CopyMemory);
virtual ImageDataItemPointer AllocateChannelData(int n = 0, void *data = NULL, ImportMemoryManagementType importMemoryManagement = CopyMemory);
Image();
Image(const Image &other);
virtual ~Image();
virtual void Clear();
//## @warning Has to be called by every Initialize method!
virtual void Initialize();
virtual void PrintSelf(std::ostream& os, itk::Indent indent) const;
mutable ImageDataItemPointerArray m_Channels;
mutable ImageDataItemPointerArray m_Volumes;
mutable ImageDataItemPointerArray m_Slices;
unsigned int m_Dimension;
unsigned int* m_Dimensions;
ImageDescriptor::Pointer m_ImageDescriptor;
size_t *m_OffsetTable;
ImageDataItemPointer m_CompleteData;
// Image statistics Holder replaces the former implementation directly inside this class
friend class ImageStatisticsHolder;
StatisticsHolderPointer m_ImageStatistics;
private:
/** Stores all existing ImageReadAccessors */
std::vector<ImageAccessorBase*> m_Readers;
/** Stores all existing ImageWriteAccessors */
std::vector<ImageAccessorBase*> m_Writers;
/** Stores all existing ImageVtkAccessors */
std::vector<ImageAccessorBase*> m_VtkReaders;
/** A mutex, which needs to be locked to manage m_Readers and m_Writers */
itk::SimpleFastMutexLock m_ReadWriteLock;
/** A mutex, which needs to be locked to manage m_VtkReaders */
itk::SimpleFastMutexLock m_VtkReadersLock;
};
/**
* @brief Equal A function comparing two images for beeing equal in meta- and imagedata
* @warning This method is deprecated and will not be available in the future. Use the \a bool mitk::Equal(const mitk::Image& i1, const mitk::Image& i2) instead.
*
* @ingroup MITKTestingAPI
*
* Following aspects are tested for equality:
* - dimension of the images
* - size of the images
* - pixel type
* - pixel values : pixel values are expected to be identical at each position ( for other options see mitk::CompareImageFilter )
*
* @param rightHandSide An image to be compared
* @param leftHandSide An image to be compared
* @param eps Tolarence for comparison. You can use mitk::eps in most cases.
* @param verbose Flag indicating if the user wants detailed console output or not.
* @return true, if all subsequent comparisons are true, false otherwise
*/
DEPRECATED (MITK_CORE_EXPORT bool Equal( const mitk::Image* leftHandSide, const mitk::Image* rightHandSide, ScalarType eps, bool verbose ));
/**
* @brief Equal A function comparing two images for beeing equal in meta- and imagedata
*
* @ingroup MITKTestingAPI
*
* Following aspects are tested for equality:
* - dimension of the images
* - size of the images
* - pixel type
* - pixel values : pixel values are expected to be identical at each position ( for other options see mitk::CompareImageFilter )
*
* @param rightHandSide An image to be compared
* @param leftHandSide An image to be compared
* @param eps Tolarence for comparison. You can use mitk::eps in most cases.
* @param verbose Flag indicating if the user wants detailed console output or not.
* @return true, if all subsequent comparisons are true, false otherwise
*/
MITK_CORE_EXPORT bool Equal( const mitk::Image& leftHandSide, const mitk::Image& rightHandSide, ScalarType eps, bool verbose );
//}
//##Documentation
//## @brief Cast an itk::Image (with a specific type) to an mitk::Image.
//##
//## CastToMitkImage does not cast pixel types etc., just image data
//## Needs "mitkImage.h" header included.
//## If you get a compile error, try image.GetPointer();
//## @ingroup Adaptor
//## \sa mitkITKImageImport
template <typename ItkOutputImageType>
void CastToMitkImage(const itk::SmartPointer<ItkOutputImageType>& itkimage, itk::SmartPointer<mitk::Image>& mitkoutputimage)
{
if(mitkoutputimage.IsNull())
{
mitkoutputimage = mitk::Image::New();
}
mitkoutputimage->InitializeByItk(itkimage.GetPointer());
mitkoutputimage->SetChannel(itkimage->GetBufferPointer());
}
//##Documentation
//## @brief Cast an itk::Image (with a specific type) to an mitk::Image.
//##
//## CastToMitkImage does not cast pixel types etc., just image data
//## Needs "mitkImage.h" header included.
//## If you get a compile error, try image.GetPointer();
//## @ingroup Adaptor
//## \sa mitkITKImageImport
template <typename ItkOutputImageType>
void CastToMitkImage(const ItkOutputImageType* itkimage, itk::SmartPointer<mitk::Image>& mitkoutputimage)
{
if(mitkoutputimage.IsNull())
{
mitkoutputimage = mitk::Image::New();
}
mitkoutputimage->InitializeByItk(itkimage);
mitkoutputimage->SetChannel(itkimage->GetBufferPointer());
}
} // namespace mitk
#endif /* MITKIMAGE_H_HEADER_INCLUDED_C1C2FCD2 */
diff --git a/Core/Code/DataManagement/mitkImagePixelAccessor.h b/Core/Code/DataManagement/mitkImagePixelAccessor.h
index 52895dc5bb..5bfea1638e 100644
--- a/Core/Code/DataManagement/mitkImagePixelAccessor.h
+++ b/Core/Code/DataManagement/mitkImagePixelAccessor.h
@@ -1,117 +1,117 @@
/*===================================================================
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 MITKIMAGEPIXELACCESSOR_H
#define MITKIMAGEPIXELACCESSOR_H
#include <algorithm>
#include <itkIndex.h>
#include <itkPoint.h>
#include <mitkCommon.h>
#include <itkSmartPointer.h>
#include "mitkImageAccessorBase.h"
#include "mitkImageDataItem.h"
#include "mitkPixelType.h"
#include "mitkImage.h"
namespace mitk {
class Image;
//##Documentation
//## @brief Provides templated image access for all inheriting classes
//## @tparam TPixel defines the PixelType
//## @tparam VDimension defines the dimension for accessing data
//## @ingroup Data
template <class TPixel, unsigned int VDimension = 3>
class ImagePixelAccessor
{
friend class Image;
public:
typedef itk::Index<VDimension> IndexType;
typedef ImagePixelAccessor<TPixel,VDimension> ImagePixelAccessorType;
/** Get Dimensions from ImageDataItem */
int GetDimension (int i) const {
return m_ImageDataItem->GetDimension(i);
}
protected:
/** \param ImageDataItem* specifies the allocated image part */
ImagePixelAccessor(mitk::Image::Pointer iP, mitk::ImageDataItem* iDI) :
m_ImageDataItem(iDI)
{
if(iDI == NULL)
m_ImageDataItem = iP->GetChannelData();
}
/** Destructor */
virtual ~ImagePixelAccessor()
{
}
protected:
// protected members
/** Holds the specified ImageDataItem */
ImageDataItem* m_ImageDataItem;
/** \brief Pointer to the used Geometry.
* Since Geometry can be different to the Image (if memory was forced to be coherent) it is necessary to store Geometry separately. */
- Geometry3D::Pointer m_Geometry;
+ BaseGeometry::Pointer m_Geometry;
/** \brief A Subregion defines an arbitrary area within the image.
* If no SubRegion is defined, the whole ImageDataItem or Image is regarded.
* A subregion (e.g. subvolume) can lead to non-coherent memory access where every dimension has a start- and end-offset.
*/
itk::ImageRegion<VDimension>* m_SubRegion;
/** \brief Stores all extended properties of an ImageAccessor.
* The different flags in mitk::ImageAccessorBase::Options can be unified by bitwise operations.
*/
int m_Options;
/** Get memory offset for a given image index */
unsigned int GetOffset(const IndexType & idx) const {
const unsigned int * imageDims = m_ImageDataItem->m_Dimensions;
unsigned int offset = 0;
switch(VDimension)
{
case 4:
offset += idx[3]*imageDims[0]*imageDims[1]*imageDims[2];
case 3:
offset += idx[2]*imageDims[0]*imageDims[1];
case 2:
offset += idx[0] + idx[1]*imageDims[0];
break;
}
return offset;
}
private:
};
}
#endif // MITKIMAGEACCESSOR_H
diff --git a/Core/Code/DataManagement/mitkLandmarkBasedCurvedGeometry.h b/Core/Code/DataManagement/mitkLandmarkBasedCurvedGeometry.h
deleted file mode 100644
index f7363d421f..0000000000
--- a/Core/Code/DataManagement/mitkLandmarkBasedCurvedGeometry.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*===================================================================
-
-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 MITKLANDMARKBASEDCURVEDGEOMETRY_H_HEADER_INCLUDED_C1C68A2C
-#define MITKLANDMARKBASEDCURVEDGEOMETRY_H_HEADER_INCLUDED_C1C68A2C
-
-#include "mitkAbstractTransformGeometry.h"
-#include "mitkPointSet.h"
-
-namespace mitk {
-
-//##Documentation
-//## @brief Superclass of AbstractTransformGeometry sub-classes defined
-//## by a set of landmarks.
-//##
-//## @ingroup Geometry
-class MITK_CORE_EXPORT LandmarkBasedCurvedGeometry : public AbstractTransformGeometry
-{
-public:
- mitkClassMacro(LandmarkBasedCurvedGeometry, AbstractTransformGeometry);
-
- //##Documentation
- //## @brief Set the landmarks through which the geometry shall pass
- itkSetConstObjectMacro(TargetLandmarks, mitk::PointSet::DataType::PointsContainer);
- //##Documentation
- //## @brief Get the landmarks through which the geometry shall pass
- itkGetConstObjectMacro(TargetLandmarks, mitk::PointSet::DataType::PointsContainer);
-
- virtual void ComputeGeometry() = 0;
-
- virtual itk::LightObject::Pointer InternalClone() const = 0;
-
-protected:
- LandmarkBasedCurvedGeometry();
-
- LandmarkBasedCurvedGeometry(const LandmarkBasedCurvedGeometry& other);
-
- virtual ~LandmarkBasedCurvedGeometry();
-
- mitk::PointSet::DataType::PointsContainer::ConstPointer m_TargetLandmarks;
-
-};
-
-} // namespace mitk
-
-#endif
diff --git a/Core/Code/DataManagement/mitkLandmarkProjector.h b/Core/Code/DataManagement/mitkLandmarkProjector.h
index fbb0be163f..0637a83da2 100644
--- a/Core/Code/DataManagement/mitkLandmarkProjector.h
+++ b/Core/Code/DataManagement/mitkLandmarkProjector.h
@@ -1,117 +1,117 @@
/*===================================================================
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 MITKLANDMARKPROJECTOR_H_HEADER_INCLUDED_C1C68A2C
#define MITKLANDMARKPROJECTOR_H_HEADER_INCLUDED_C1C68A2C
#include <MitkCoreExports.h>
#include "itkObject.h"
#include "mitkPlaneGeometry.h"
#include "mitkPointSet.h"
class vtkAbstractTransform;
namespace mitk {
//##Documentation
//## @brief Base-class of landmark-projectors, which project the target landmarks
//## to create source landmarks.
//##
//## @ingroup Geometry
class MITK_CORE_EXPORT LandmarkProjector : public itk::Object
{
public:
mitkClassMacro(LandmarkProjector, itk::Object);
//##Documentation
//## @brief Set the interpolating (world-space-to-world-space) transform,
//## which uses the landmarks.
//##
//## \sa GetCompleteAbstractTransform
virtual void SetInterpolatingAbstractTransform(vtkAbstractTransform* anInterpolatingAbstractTransform);
//##Documentation
//## @brief Get the interpolating (world-space-to-world-space) transform,
//## which uses the landmarks.
//##
//## \sa GetCompleteAbstractTransform
//## \sa ComputeCompleteAbstractTransform
itkGetConstMacro(InterpolatingAbstractTransform, vtkAbstractTransform*);
//##Documentation
//## @brief Set frame geometry within which the interpolation shall occur.
//##
//## Used as a hint, may be ignored depending on the concrete sub-classes.
- itkSetConstObjectMacro(FrameGeometry, mitk::Geometry3D);
+ itkSetConstObjectMacro(FrameGeometry, mitk::BaseGeometry);
//##Documentation
//## @brief Get frame geometry within which the interpolation shall occur.
//##
//## Used as a hint, may be ignored depending on the concrete sub-classes.
- itkGetConstObjectMacro(FrameGeometry, mitk::Geometry3D);
+ itkGetConstObjectMacro(FrameGeometry, mitk::BaseGeometry);
//##Documentation
//## @brief Get the parameter plane for use in AbstractTransformGeometry::SetPlane.
//##
itkGetConstObjectMacro(ParameterPlane, mitk::PlaneGeometry);
//##Documentation
//## @brief Get the projected landmarks.
//##
//## @note Valid only after calling ProjectLandmarks.
itkGetConstObjectMacro(ProjectedLandmarks, mitk::PointSet::DataType::PointsContainer);
//##Documentation
//## @brief Get the final target landmarks to use for the interpolating transform.
//##
//## @note Valid only after calling ProjectLandmarks.
itkGetConstObjectMacro(FinalTargetLandmarks, mitk::PointSet::DataType::PointsContainer);
//##Documentation
//## @brief Get the transform from parameter space to world space incorporating
//## the given interpolating transform, which uses the landmarks.
//##
//## \sa ComputeCompleteAbstractTransform
//## \sa SetInterpolatingAbstractTransform
virtual vtkAbstractTransform* GetCompleteAbstractTransform() const;
virtual void ProjectLandmarks(const mitk::PointSet::DataType::PointsContainer* targetLandmarks) = 0;
protected:
LandmarkProjector();
virtual ~LandmarkProjector();
//##Documentation
//## @brief Compute the transform from parameter space to world space incorporating
//## the given interpolating transform, which uses the landmarks.
//##
//## Called after a new interpolating transform is set via
//## SetInterpolatingAbstractTransform().
//## \sa SetInterpolatingAbstractTransform
//## \sa GetCompleteAbstractTransform
virtual void ComputeCompleteAbstractTransform() = 0;
vtkAbstractTransform* m_InterpolatingAbstractTransform;
vtkAbstractTransform* m_CompleteAbstractTransform;
- mitk::Geometry3D::ConstPointer m_FrameGeometry;
+ mitk::BaseGeometry::ConstPointer m_FrameGeometry;
mutable mitk::PlaneGeometry::ConstPointer m_ParameterPlane;
mitk::PointSet::DataType::PointsContainer::Pointer m_WritableFinalTargetLandmarks;
mitk::PointSet::DataType::PointsContainer::ConstPointer m_FinalTargetLandmarks;
mitk::PointSet::DataType::PointsContainer::Pointer m_ProjectedLandmarks;
};
} // namespace mitk
#endif /* MITKLANDMARKPROJECTOR_H_HEADER_INCLUDED_C1C68A2C */
diff --git a/Core/Code/DataManagement/mitkLandmarkProjectorBasedCurvedGeometry.cpp b/Core/Code/DataManagement/mitkLandmarkProjectorBasedCurvedGeometry.cpp
index c83f37ee82..9e8ac72940 100644
--- a/Core/Code/DataManagement/mitkLandmarkProjectorBasedCurvedGeometry.cpp
+++ b/Core/Code/DataManagement/mitkLandmarkProjectorBasedCurvedGeometry.cpp
@@ -1,82 +1,83 @@
/*===================================================================
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 "mitkLandmarkProjectorBasedCurvedGeometry.h"
#include <vtkAbstractTransform.h>
mitk::LandmarkProjectorBasedCurvedGeometry::LandmarkProjectorBasedCurvedGeometry()
- : m_LandmarkProjector(NULL), m_InterpolatingAbstractTransform(NULL)
+ : m_LandmarkProjector(NULL), m_InterpolatingAbstractTransform(NULL), m_TargetLandmarks(NULL)
{
}
mitk::LandmarkProjectorBasedCurvedGeometry::LandmarkProjectorBasedCurvedGeometry(const mitk::LandmarkProjectorBasedCurvedGeometry& other) : Superclass(other)
{
+ SetTargetLandmarks(other.m_TargetLandmarks);
this->SetLandmarkProjector(other.m_LandmarkProjector);
this->ComputeGeometry();
}
mitk::LandmarkProjectorBasedCurvedGeometry::~LandmarkProjectorBasedCurvedGeometry()
{
if(m_InterpolatingAbstractTransform!=NULL)
m_InterpolatingAbstractTransform->Delete();
}
void mitk::LandmarkProjectorBasedCurvedGeometry::SetLandmarkProjector(mitk::LandmarkProjector* aLandmarkProjector)
{
itkDebugMacro("setting LandmarkProjector to " << aLandmarkProjector );
if(m_LandmarkProjector != aLandmarkProjector)
{
m_LandmarkProjector = aLandmarkProjector;
if(m_LandmarkProjector.IsNotNull())
{
if(m_FrameGeometry.IsNotNull())
m_LandmarkProjector->SetFrameGeometry(m_FrameGeometry);
if(m_InterpolatingAbstractTransform == NULL)
{
itkWarningMacro(<<"m_InterpolatingAbstractTransform not set.");
}
m_LandmarkProjector->SetInterpolatingAbstractTransform(GetInterpolatingAbstractTransform());
SetVtkAbstractTransform(m_LandmarkProjector->GetCompleteAbstractTransform());
}
Modified();
}
}
-void mitk::LandmarkProjectorBasedCurvedGeometry::SetFrameGeometry(const mitk::Geometry3D* frameGeometry)
+void mitk::LandmarkProjectorBasedCurvedGeometry::SetFrameGeometry(const mitk::BaseGeometry* frameGeometry)
{
Superclass::SetFrameGeometry(frameGeometry);
if(m_LandmarkProjector.IsNotNull())
m_LandmarkProjector->SetFrameGeometry(frameGeometry);
}
void mitk::LandmarkProjectorBasedCurvedGeometry::ComputeGeometry()
{
if(m_LandmarkProjector.IsNull())
{
itkExceptionMacro(<< "m_LandmarkProjector is not set.");
}
m_LandmarkProjector->ProjectLandmarks(m_TargetLandmarks);
SetPlane(m_LandmarkProjector->GetParameterPlane());
}
itk::LightObject::Pointer mitk::LandmarkProjectorBasedCurvedGeometry::InternalClone() const
{
- mitk::Geometry3D::Pointer newGeometry = new LandmarkProjectorBasedCurvedGeometry(*this);
+ mitk::BaseGeometry::Pointer newGeometry = new LandmarkProjectorBasedCurvedGeometry(*this);
newGeometry->UnRegister();
return newGeometry.GetPointer();
}
diff --git a/Core/Code/DataManagement/mitkLandmarkProjectorBasedCurvedGeometry.h b/Core/Code/DataManagement/mitkLandmarkProjectorBasedCurvedGeometry.h
index b3b94d60c9..d2b5217475 100644
--- a/Core/Code/DataManagement/mitkLandmarkProjectorBasedCurvedGeometry.h
+++ b/Core/Code/DataManagement/mitkLandmarkProjectorBasedCurvedGeometry.h
@@ -1,61 +1,72 @@
/*===================================================================
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 MITKLANDMARKPROJECTORBASEDCURVEDGEOMETRY_H_HEADER_INCLUDED_C1C68A2C
#define MITKLANDMARKPROJECTORBASEDCURVEDGEOMETRY_H_HEADER_INCLUDED_C1C68A2C
-#include "mitkLandmarkBasedCurvedGeometry.h"
#include "mitkLandmarkProjector.h"
+#include "mitkAbstractTransformGeometry.h"
+#include "mitkPointSet.h"
+
namespace mitk {
//##Documentation
//## @brief Superclass of AbstractTransformGeometry sub-classes defined
//## by a set of landmarks.
//##
//## @ingroup Geometry
-class MITK_CORE_EXPORT LandmarkProjectorBasedCurvedGeometry : public LandmarkBasedCurvedGeometry
+class MITK_CORE_EXPORT LandmarkProjectorBasedCurvedGeometry : public AbstractTransformGeometry
{
public:
- mitkClassMacro(LandmarkProjectorBasedCurvedGeometry, LandmarkBasedCurvedGeometry);
+ mitkClassMacro(LandmarkProjectorBasedCurvedGeometry, AbstractTransformGeometry);
void SetLandmarkProjector(mitk::LandmarkProjector* aLandmarkProjector);
itkGetConstObjectMacro(LandmarkProjector, mitk::LandmarkProjector);
- virtual void SetFrameGeometry(const mitk::Geometry3D* frameGeometry);
+ virtual void SetFrameGeometry(const mitk::BaseGeometry* frameGeometry);
virtual void ComputeGeometry();
itkGetConstMacro(InterpolatingAbstractTransform, vtkAbstractTransform*);
itk::LightObject::Pointer InternalClone() const;
+ //##Documentation
+ //## @brief Set the landmarks through which the geometry shall pass
+ itkSetConstObjectMacro(TargetLandmarks, mitk::PointSet::DataType::PointsContainer);
+ //##Documentation
+ //## @brief Get the landmarks through which the geometry shall pass
+ itkGetConstObjectMacro(TargetLandmarks, mitk::PointSet::DataType::PointsContainer);
+
protected:
LandmarkProjectorBasedCurvedGeometry();
LandmarkProjectorBasedCurvedGeometry(const LandmarkProjectorBasedCurvedGeometry& other);
virtual ~LandmarkProjectorBasedCurvedGeometry();
mitk::LandmarkProjector::Pointer m_LandmarkProjector;
vtkAbstractTransform* m_InterpolatingAbstractTransform;
+
+ mitk::PointSet::DataType::PointsContainer::ConstPointer m_TargetLandmarks;
};
} // namespace mitk
#endif /* MITKLANDMARKPROJECTORBASEDCURVEDGEOMETRY_H_HEADER_INCLUDED_C1C68A2C */
diff --git a/Core/Code/DataManagement/mitkMatrixConvert.h b/Core/Code/DataManagement/mitkMatrixConvert.h
index e7ff867d3d..41410397f9 100644
--- a/Core/Code/DataManagement/mitkMatrixConvert.h
+++ b/Core/Code/DataManagement/mitkMatrixConvert.h
@@ -1,151 +1,151 @@
/*===================================================================
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 MITKMATRIXCONVERT_H_HEADER_INCLUDED_C1EBD0AD
#define MITKMATRIXCONVERT_H_HEADER_INCLUDED_C1EBD0AD
-#include "mitkGeometry3D.h"
+#include "mitkBaseGeometry.h"
#include "mitkItkMatrixHack.h"
#include <vtkMatrix4x4.h>
namespace mitk
{
template <class TTransformType>
void TransferVtkMatrixToItkTransform(const vtkMatrix4x4* vtkmatrix, TTransformType * itkTransform)
{
if(itkTransform==NULL)
return;
typename TTransformType::MatrixType::InternalMatrixType& vnlMatrix =
const_cast<typename TTransformType::MatrixType::InternalMatrixType&>(itkTransform->GetMatrix().GetVnlMatrix());
for ( int i=0; i < 3; ++i)
for( int j=0; j < 3; ++j )
vnlMatrix[i][j] = vtkmatrix->GetElement( i, j );
// *This* ensures m_MatrixMTime.Modified(), which is therewith not equal to
// m_InverseMatrixMTime, thus a new inverse will be calculated (when
// requested).
static_cast<mitk::ItkMatrixHack<TTransformType>*>(itkTransform)->MatrixChanged();
typename TTransformType::OffsetType offset;
offset[0] = vtkmatrix->GetElement( 0, 3 );
offset[1] = vtkmatrix->GetElement( 1, 3 );
offset[2] = vtkmatrix->GetElement( 2, 3 );
itkTransform->SetOffset( offset );
}
template <class TTransformType>
void TransferItkTransformToVtkMatrix(const TTransformType * itkTransform, vtkMatrix4x4* vtkmatrix)
{
int i,j;
for(i=0;i<3;++i)
for(j=0;j<3;++j)
vtkmatrix->SetElement(i, j, itkTransform->GetMatrix().GetVnlMatrix().get(i, j));
for(i=0;i<3;++i)
vtkmatrix->SetElement(i, 3, itkTransform->GetOffset()[i]);
for(i=0;i<3;++i)
vtkmatrix->SetElement(3, i, 0.0);
vtkmatrix->SetElement(3, 3, 1);
}
template <class TTransformType1, class TTransformType2>
void ConvertItkTransform(const TTransformType1* sourceTransform, TTransformType2* destTransform)
{
if((sourceTransform==NULL) || (destTransform==NULL))
return;
// transfer offset
const typename TTransformType1::OutputVectorType& sourceOffset =
sourceTransform->GetOffset();
typename TTransformType2::OutputVectorType offset;
offset[0] = sourceOffset[0]; offset[1] = sourceOffset[1]; offset[2] = sourceOffset[2];
destTransform->SetOffset( offset );
typename TTransformType1::MatrixType::InternalMatrixType& sourceVnlMatrix =
const_cast<typename TTransformType1::MatrixType::InternalMatrixType&>(sourceTransform->GetMatrix().GetVnlMatrix());
//transfer matrix
typename TTransformType2::MatrixType::InternalMatrixType& destVnlMatrix =
const_cast<typename TTransformType2::MatrixType::InternalMatrixType&>(destTransform->GetMatrix().GetVnlMatrix());
for ( int i=0; i < 3; ++i)
for( int j=0; j < 3; ++j )
destVnlMatrix[i][j] = sourceVnlMatrix[i][j];
// *This* ensures m_MatrixMTime.Modified(), which is therewith not equal to
// m_InverseMatrixMTime, thus a new inverse will be calculated (when
// requested).
static_cast<mitk::ItkMatrixHack<TTransformType2>*>(destTransform)->MatrixChanged();
}
template <class TMatrixType>
- void GetRotation(const mitk::Geometry3D * geometry, TMatrixType& itkmatrix)
+ void GetRotation(const mitk::BaseGeometry * geometry, TMatrixType& itkmatrix)
{
const mitk::Vector3D& spacing = geometry->GetSpacing();
- typename mitk::Geometry3D::TransformType::MatrixType::InternalMatrixType& geometryVnlMatrix =
- const_cast<typename mitk::Geometry3D::TransformType::MatrixType::InternalMatrixType&>(geometry->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix());
+ typename mitk::BaseGeometry::TransformType::MatrixType::InternalMatrixType& geometryVnlMatrix =
+ const_cast<typename mitk::BaseGeometry::TransformType::MatrixType::InternalMatrixType&>(geometry->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix());
typename TMatrixType::InternalMatrixType& outputVnlMatrix =
const_cast<typename TMatrixType::InternalMatrixType&>(itkmatrix.GetVnlMatrix());
for ( int i=0; i < 3; ++i)
for( int j=0; j < 3; ++j )
outputVnlMatrix [i][j] = geometryVnlMatrix [i][j] / spacing[j];
}
template <class TTransformType>
- void GetWorldToItkPhysicalTransform(const mitk::Geometry3D * geometry, TTransformType* itkTransform)
+ void GetWorldToItkPhysicalTransform(const mitk::BaseGeometry * geometry, TTransformType* itkTransform)
{
if(itkTransform==NULL)
return;
// get rotation matrix and offset from Geometry and transfer in TTransformType types
typename TTransformType::MatrixType rotationMatrix;
GetRotation(geometry, rotationMatrix);
const typename mitk::Geometry3D::TransformType::OffsetType& geometryOffset =
geometry->GetIndexToWorldTransform()->GetOffset();
vnl_vector<typename TTransformType::MatrixType::ValueType> vnlOffset(3);
vnlOffset[0] = geometryOffset[0]; vnlOffset[1] = geometryOffset[1]; vnlOffset[2] = geometryOffset[2];
// do calculations
typename TTransformType::MatrixType::InternalMatrixType inverseRotationVnlMatrix = rotationMatrix.GetTranspose();
vnlOffset -= inverseRotationVnlMatrix*vnlOffset;
typename TTransformType::OutputVectorType offset;//vnl_vector<TTransformType::MatrixType::ValueType> offset;
offset[0] = vnlOffset[0]; offset[1] = vnlOffset[1]; offset[2] = vnlOffset[2];
itkTransform->SetOffset( offset );
// copy in destination itkTransform
typename TTransformType::MatrixType::InternalMatrixType& destVnlMatrix =
const_cast<typename TTransformType::MatrixType::InternalMatrixType&>(itkTransform->GetMatrix().GetVnlMatrix());
for ( int i=0; i < 3; ++i)
for( int j=0; j < 3; ++j )
destVnlMatrix[i][j] = inverseRotationVnlMatrix[i][j];
// *This* ensures m_MatrixMTime.Modified(), which is therewith not equal to
// m_InverseMatrixMTime, thus a new inverse will be calculated (when
// requested).
static_cast<mitk::ItkMatrixHack<TTransformType>*>(itkTransform)->MatrixChanged();
}
}
#endif /* MITKMATRIXCONVERT_H_HEADER_INCLUDED_C1EBD0AD */
diff --git a/Core/Code/DataManagement/mitkLandmarkBasedCurvedGeometry.cpp b/Core/Code/DataManagement/mitkModifiedLock.cpp
similarity index 54%
rename from Core/Code/DataManagement/mitkLandmarkBasedCurvedGeometry.cpp
rename to Core/Code/DataManagement/mitkModifiedLock.cpp
index 9006e05040..dfc068756e 100644
--- a/Core/Code/DataManagement/mitkLandmarkBasedCurvedGeometry.cpp
+++ b/Core/Code/DataManagement/mitkModifiedLock.cpp
@@ -1,35 +1,32 @@
/*===================================================================
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 <mitkModifiedLock.h>
-#include "mitkLandmarkBasedCurvedGeometry.h"
-#include <vtkAbstractTransform.h>
-
-mitk::LandmarkBasedCurvedGeometry::LandmarkBasedCurvedGeometry()
- : m_TargetLandmarks(NULL)
-{
+mitk::ModifiedLock::ModifiedLock(BaseGeometry* baseGeo){
+ m_baseGeometry = baseGeo;
+ m_baseGeometry->m_ModifiedLockFlag = true;
+ m_baseGeometry->m_ModifiedCalledFlag = false;
}
-mitk::LandmarkBasedCurvedGeometry::LandmarkBasedCurvedGeometry(const LandmarkBasedCurvedGeometry& other)
- : Superclass(other)
-{
- SetTargetLandmarks(other.m_TargetLandmarks);
-}
+mitk::ModifiedLock::~ModifiedLock(){
+ m_baseGeometry->m_ModifiedLockFlag = false;
-mitk::LandmarkBasedCurvedGeometry::~LandmarkBasedCurvedGeometry()
-{
+ if(m_baseGeometry->m_ModifiedCalledFlag)
+ m_baseGeometry->Modified();
+ m_baseGeometry->m_ModifiedCalledFlag = false;
}
diff --git a/Core/Code/DataManagement/mitkModifiedLock.h b/Core/Code/DataManagement/mitkModifiedLock.h
new file mode 100644
index 0000000000..a5f77139e9
--- /dev/null
+++ b/Core/Code/DataManagement/mitkModifiedLock.h
@@ -0,0 +1,41 @@
+/*===================================================================
+
+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 ModifiedLock_H_HEADER_INCLUDED
+#define ModifiedLock_H_HEADER_INCLUDED
+
+#include <MitkCoreExports.h>
+#include <mitkBaseGeometry.h>
+namespace mitk {
+ //##Documentation
+ //## @brief ModifiedLock manages the calls of Modified() functions
+ //##
+ //## If an object of ModifiedLock is created, the ModifiedLockFlag in class
+ //## BaseGeometry is set to true. Therefore, all following calls of Modified()
+ //## will be collected and only be carried out at the end of the function / section,
+ //## when the deconstructor of the ModifiedLock object is called.
+ //##
+ class MITK_CORE_EXPORT ModifiedLock
+ {
+ public:
+ ModifiedLock();
+ ModifiedLock(BaseGeometry* baseGeo);
+ ~ModifiedLock();
+ private:
+ BaseGeometry* m_baseGeometry;
+ };
+}
+
+#endif //Header
diff --git a/Core/Code/DataManagement/mitkPlaneGeometry.cpp b/Core/Code/DataManagement/mitkPlaneGeometry.cpp
index 364fe98271..f2ff00020f 100644
--- a/Core/Code/DataManagement/mitkPlaneGeometry.cpp
+++ b/Core/Code/DataManagement/mitkPlaneGeometry.cpp
@@ -1,777 +1,916 @@
/*===================================================================
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 "mitkPlaneGeometry.h"
#include "mitkPlaneOperation.h"
#include "mitkInteractionConst.h"
#include "mitkLine.h"
#include <vtkTransform.h>
#include <vnl/vnl_cross.h>
-
namespace mitk
{
+ PlaneGeometry::PlaneGeometry()
+ : m_ScaleFactorMMPerUnitX( 1.0 ),
+ m_ScaleFactorMMPerUnitY( 1.0 ),
+ m_ReferenceGeometry( NULL )
+ {
+ Initialize();
+ }
-mitk::PlaneGeometry::PlaneGeometry()
-{
- Initialize();
-}
-
-
-mitk::PlaneGeometry::~PlaneGeometry()
-{
-}
-
-
-void
-PlaneGeometry::Initialize()
-{
- Superclass::Initialize();
-}
-
-
-void
-PlaneGeometry::EnsurePerpendicularNormal(mitk::AffineTransform3D *transform)
-{
- //ensure row(2) of transform to be perpendicular to plane, keep length.
- VnlVector normal = vnl_cross_3d(
- transform->GetMatrix().GetVnlMatrix().get_column(0),
- transform->GetMatrix().GetVnlMatrix().get_column(1) );
-
- normal.normalize();
- ScalarType len = transform->GetMatrix()
- .GetVnlMatrix().get_column(2).two_norm();
-
- if (len==0) len = 1;
- normal*=len;
- Matrix3D matrix = transform->GetMatrix();
- matrix.GetVnlMatrix().set_column(2, normal);
- transform->SetMatrix(matrix);
-}
-
-
-void
-PlaneGeometry::SetIndexToWorldTransform(mitk::AffineTransform3D *transform)
-{
- EnsurePerpendicularNormal(transform);
-
- Superclass::SetIndexToWorldTransform(transform);
-}
-
-
-void
-PlaneGeometry::SetBounds(const BoundingBox::BoundsArrayType &bounds)
-{
- //currently the unit rectangle must be starting at the origin [0,0]
- assert(bounds[0]==0);
- assert(bounds[2]==0);
- //the unit rectangle must be two-dimensional
- assert(bounds[1]>0);
- assert(bounds[3]>0);
+ PlaneGeometry::~PlaneGeometry()
+ {
+ }
- Superclass::SetBounds(bounds);
-}
+ PlaneGeometry::PlaneGeometry(const PlaneGeometry& other)
+ : Superclass(other), m_ScaleFactorMMPerUnitX( other.m_ScaleFactorMMPerUnitX),
+ m_ScaleFactorMMPerUnitY( other.m_ScaleFactorMMPerUnitY),
+ m_ReferenceGeometry( other.m_ReferenceGeometry )
+ {
+ }
+ void
+ PlaneGeometry::EnsurePerpendicularNormal(mitk::AffineTransform3D *transform)
+ {
+ //ensure row(2) of transform to be perpendicular to plane, keep length.
+ VnlVector normal = vnl_cross_3d(
+ transform->GetMatrix().GetVnlMatrix().get_column(0),
+ transform->GetMatrix().GetVnlMatrix().get_column(1) );
+
+ normal.normalize();
+ ScalarType len = transform->GetMatrix()
+ .GetVnlMatrix().get_column(2).two_norm();
+
+ if (len==0) len = 1;
+ normal*=len;
+ Matrix3D matrix = transform->GetMatrix();
+ matrix.GetVnlMatrix().set_column(2, normal);
+ transform->SetMatrix(matrix);
+ }
-void
-PlaneGeometry::IndexToWorld( const Point2D &pt_units, Point2D &pt_mm ) const
-{
- pt_mm[0]=m_ScaleFactorMMPerUnitX*pt_units[0];
- pt_mm[1]=m_ScaleFactorMMPerUnitY*pt_units[1];
-}
+ void
+ PlaneGeometry::PreSetIndexToWorldTransform(mitk::AffineTransform3D *transform)
+ {
+ EnsurePerpendicularNormal(transform);
+ }
+ void
+ PlaneGeometry::PreSetBounds(const BoundingBox::BoundsArrayType &bounds)
+ {
+ //currently the unit rectangle must be starting at the origin [0,0]
+ assert(bounds[0]==0);
+ assert(bounds[2]==0);
+ //the unit rectangle must be two-dimensional
+ assert(bounds[1]>0);
+ assert(bounds[3]>0);
+ }
-void PlaneGeometry::WorldToIndex( const Point2D &pt_mm, Point2D &pt_units ) const
-{
- pt_units[0]=pt_mm[0]*(1.0/m_ScaleFactorMMPerUnitX);
- pt_units[1]=pt_mm[1]*(1.0/m_ScaleFactorMMPerUnitY);
-}
+ void
+ PlaneGeometry::IndexToWorld( const Point2D &pt_units, Point2D &pt_mm ) const
+ {
+ pt_mm[0]=m_ScaleFactorMMPerUnitX*pt_units[0];
+ pt_mm[1]=m_ScaleFactorMMPerUnitY*pt_units[1];
+ }
-void PlaneGeometry::IndexToWorld( const Point2D & /*atPt2d_units*/,
- const Vector2D &vec_units, Vector2D &vec_mm) const
-{
- MITK_WARN<<"Warning! Call of the deprecated function PlaneGeometry::IndexToWorld(point, vec, vec). Use PlaneGeometry::IndexToWorld(vec, vec) instead!";
- this->IndexToWorld(vec_units, vec_mm);
-}
+ void PlaneGeometry::WorldToIndex( const Point2D &pt_mm, Point2D &pt_units ) const
+ {
+ pt_units[0]=pt_mm[0]*(1.0/m_ScaleFactorMMPerUnitX);
+ pt_units[1]=pt_mm[1]*(1.0/m_ScaleFactorMMPerUnitY);
+ }
-void PlaneGeometry::IndexToWorld(const Vector2D &vec_units, Vector2D &vec_mm) const
-{
- vec_mm[0] = m_ScaleFactorMMPerUnitX * vec_units[0];
- vec_mm[1] = m_ScaleFactorMMPerUnitY * vec_units[1];
-}
+ void PlaneGeometry::IndexToWorld( const Point2D & /*atPt2d_units*/,
+ const Vector2D &vec_units, Vector2D &vec_mm) const
+ {
+ MITK_WARN<<"Warning! Call of the deprecated function PlaneGeometry::IndexToWorld(point, vec, vec). Use PlaneGeometry::IndexToWorld(vec, vec) instead!";
+ this->IndexToWorld(vec_units, vec_mm);
+ }
-void
-PlaneGeometry::WorldToIndex( const Point2D & /*atPt2d_mm*/,
- const Vector2D &vec_mm, Vector2D &vec_units) const
-{
- MITK_WARN<<"Warning! Call of the deprecated function PlaneGeometry::WorldToIndex(point, vec, vec). Use PlaneGeometry::WorldToIndex(vec, vec) instead!";
- this->WorldToIndex(vec_mm, vec_units);
-}
+ void PlaneGeometry::IndexToWorld(const Vector2D &vec_units, Vector2D &vec_mm) const
+ {
+ vec_mm[0] = m_ScaleFactorMMPerUnitX * vec_units[0];
+ vec_mm[1] = m_ScaleFactorMMPerUnitY * vec_units[1];
+ }
-void
-PlaneGeometry::WorldToIndex( const Vector2D &vec_mm, Vector2D &vec_units) const
-{
- vec_units[0] = vec_mm[0] * ( 1.0 / m_ScaleFactorMMPerUnitX );
- vec_units[1] = vec_mm[1] * ( 1.0 / m_ScaleFactorMMPerUnitY );
-}
+ void
+ PlaneGeometry::WorldToIndex( const Point2D & /*atPt2d_mm*/,
+ const Vector2D &vec_mm, Vector2D &vec_units) const
+ {
+ MITK_WARN<<"Warning! Call of the deprecated function PlaneGeometry::WorldToIndex(point, vec, vec). Use PlaneGeometry::WorldToIndex(vec, vec) instead!";
+ this->WorldToIndex(vec_mm, vec_units);
+ }
+ void
+ PlaneGeometry::WorldToIndex( const Vector2D &vec_mm, Vector2D &vec_units) const
+ {
+ vec_units[0] = vec_mm[0] * ( 1.0 / m_ScaleFactorMMPerUnitX );
+ vec_units[1] = vec_mm[1] * ( 1.0 / m_ScaleFactorMMPerUnitY );
+ }
-void
-PlaneGeometry::InitializeStandardPlane( mitk::ScalarType width,
- ScalarType height, const Vector3D & spacing,
- PlaneGeometry::PlaneOrientation planeorientation,
- ScalarType zPosition, bool frontside, bool rotated )
-{
- AffineTransform3D::Pointer transform;
-
- transform = AffineTransform3D::New();
- AffineTransform3D::MatrixType matrix;
- AffineTransform3D::MatrixType::InternalMatrixType &vnlmatrix =
- matrix.GetVnlMatrix();
-
- vnlmatrix.set_identity();
- vnlmatrix(0,0) = spacing[0];
- vnlmatrix(1,1) = spacing[1];
- vnlmatrix(2,2) = spacing[2];
- transform->SetIdentity();
- transform->SetMatrix(matrix);
-
- InitializeStandardPlane(width, height, transform.GetPointer(),
- planeorientation, zPosition, frontside, rotated);
-}
-
-
-void
-PlaneGeometry::InitializeStandardPlane( mitk::ScalarType width,
- ScalarType height, const AffineTransform3D* transform,
- PlaneGeometry::PlaneOrientation planeorientation, ScalarType zPosition,
- bool frontside, bool rotated )
-{
- Superclass::Initialize();
+ void
+ PlaneGeometry::InitializeStandardPlane( mitk::ScalarType width,
+ ScalarType height, const Vector3D & spacing,
+ PlaneGeometry::PlaneOrientation planeorientation,
+ ScalarType zPosition, bool frontside, bool rotated )
+ {
+ AffineTransform3D::Pointer transform;
+
+ transform = AffineTransform3D::New();
+ AffineTransform3D::MatrixType matrix;
+ AffineTransform3D::MatrixType::InternalMatrixType &vnlmatrix =
+ matrix.GetVnlMatrix();
+
+ vnlmatrix.set_identity();
+ vnlmatrix(0,0) = spacing[0];
+ vnlmatrix(1,1) = spacing[1];
+ vnlmatrix(2,2) = spacing[2];
+ transform->SetIdentity();
+ transform->SetMatrix(matrix);
+
+ InitializeStandardPlane(width, height, transform.GetPointer(),
+ planeorientation, zPosition, frontside, rotated);
+ }
- //construct standard view
- Point3D origin;
- VnlVector rightDV(3), bottomDV(3);
- origin.Fill(0);
- int normalDirection;
- switch(planeorientation)
+ void
+ PlaneGeometry::InitializeStandardPlane( mitk::ScalarType width,
+ ScalarType height, const AffineTransform3D* transform,
+ PlaneGeometry::PlaneOrientation planeorientation, ScalarType zPosition,
+ bool frontside, bool rotated )
{
+ Superclass::Initialize();
+
+ //construct standard view
+ Point3D origin;
+ VnlVector rightDV(3), bottomDV(3);
+ origin.Fill(0);
+ int normalDirection;
+ switch(planeorientation)
+ {
case Axial:
if(frontside)
{
if(rotated==false)
{
FillVector3D(origin, 0, 0, zPosition);
FillVector3D(rightDV, 1, 0, 0);
FillVector3D(bottomDV, 0, 1, 0);
}
else
{
FillVector3D(origin, width, height, zPosition);
FillVector3D(rightDV, -1, 0, 0);
FillVector3D(bottomDV, 0, -1, 0);
}
}
else
{
if(rotated==false)
{
FillVector3D(origin, width, 0, zPosition);
FillVector3D(rightDV, -1, 0, 0);
FillVector3D(bottomDV, 0, 1, 0);
}
else
{
FillVector3D(origin, 0, height, zPosition);
FillVector3D(rightDV, 1, 0, 0);
FillVector3D(bottomDV, 0, -1, 0);
}
}
normalDirection = 2;
break;
case Frontal:
if(frontside)
{
if(rotated==false)
{
FillVector3D(origin, 0, zPosition, 0);
FillVector3D(rightDV, 1, 0, 0);
FillVector3D(bottomDV, 0, 0, 1);
}
else
{
FillVector3D(origin, width, zPosition, height);
FillVector3D(rightDV, -1, 0, 0);
FillVector3D(bottomDV, 0, 0, -1);
}
}
else
{
if(rotated==false)
{
FillVector3D(origin, width, zPosition, 0);
FillVector3D(rightDV, -1, 0, 0);
FillVector3D(bottomDV, 0, 0, 1);
}
else
{
FillVector3D(origin, 0, zPosition, height);
FillVector3D(rightDV, 1, 0, 0);
FillVector3D(bottomDV, 0, 0, -1);
}
}
normalDirection = 1;
break;
case Sagittal:
if(frontside)
{
if(rotated==false)
{
FillVector3D(origin, zPosition, 0, 0);
FillVector3D(rightDV, 0, 1, 0);
FillVector3D(bottomDV, 0, 0, 1);
}
else
{
FillVector3D(origin, zPosition, width, height);
FillVector3D(rightDV, 0, -1, 0);
FillVector3D(bottomDV, 0, 0, -1);
}
}
else
{
if(rotated==false)
{
FillVector3D(origin, zPosition, width, 0);
FillVector3D(rightDV, 0, -1, 0);
FillVector3D(bottomDV, 0, 0, 1);
}
else
{
FillVector3D(origin, zPosition, 0, height);
FillVector3D(rightDV, 0, 1, 0);
FillVector3D(bottomDV, 0, 0, -1);
}
}
normalDirection = 0;
break;
default:
itkExceptionMacro("unknown PlaneOrientation");
- }
- if ( transform != NULL )
- {
- origin = transform->TransformPoint( origin );
- rightDV = transform->TransformVector( rightDV );
- bottomDV = transform->TransformVector( bottomDV );
- }
+ }
+ if ( transform != NULL )
+ {
+ origin = transform->TransformPoint( origin );
+ rightDV = transform->TransformVector( rightDV );
+ bottomDV = transform->TransformVector( bottomDV );
+ }
- ScalarType bounds[6]= { 0, width, 0, height, 0, 1 };
- this->SetBounds( bounds );
+ ScalarType bounds[6]= { 0, width, 0, height, 0, 1 };
+ this->SetBounds( bounds );
- if ( transform == NULL )
- {
- this->SetMatrixByVectors( rightDV, bottomDV );
- }
- else
- {
- this->SetMatrixByVectors(
- rightDV, bottomDV,
- transform->GetMatrix().GetVnlMatrix()
+ if ( transform == NULL )
+ {
+ this->SetMatrixByVectors( rightDV, bottomDV );
+ }
+ else
+ {
+ this->SetMatrixByVectors(
+ rightDV, bottomDV,
+ transform->GetMatrix().GetVnlMatrix()
.get_column(normalDirection).magnitude()
- );
- }
-
- this->SetOrigin(origin);
-}
+ );
+ }
+ this->SetOrigin(origin);
+ }
-void
-PlaneGeometry::InitializeStandardPlane( const Geometry3D *geometry3D,
- PlaneOrientation planeorientation, ScalarType zPosition,
- bool frontside, bool rotated )
-{
- this->SetReferenceGeometry( const_cast< Geometry3D * >( geometry3D ) );
+ void
+ PlaneGeometry::InitializeStandardPlane( const BaseGeometry *geometry3D,
+ PlaneOrientation planeorientation, ScalarType zPosition,
+ bool frontside, bool rotated )
+ {
+ this->SetReferenceGeometry( const_cast< BaseGeometry * >( geometry3D ) );
- ScalarType width, height;
+ ScalarType width, height;
- const BoundingBox::BoundsArrayType& boundsarray =
- geometry3D->GetBoundingBox()->GetBounds();
+ const BoundingBox::BoundsArrayType& boundsarray =
+ geometry3D->GetBoundingBox()->GetBounds();
- Vector3D originVector;
- FillVector3D(originVector, boundsarray[0], boundsarray[2], boundsarray[4]);
+ Vector3D originVector;
+ FillVector3D(originVector, boundsarray[0], boundsarray[2], boundsarray[4]);
- if(geometry3D->GetImageGeometry())
- {
- FillVector3D( originVector,
- originVector[0] - 0.5,
- originVector[1] - 0.5,
- originVector[2] - 0.5 );
- }
- switch(planeorientation)
- {
+ if(geometry3D->GetImageGeometry())
+ {
+ FillVector3D( originVector,
+ originVector[0] - 0.5,
+ originVector[1] - 0.5,
+ originVector[2] - 0.5 );
+ }
+ switch(planeorientation)
+ {
case Axial:
width = geometry3D->GetExtent(0);
height = geometry3D->GetExtent(1);
break;
case Frontal:
width = geometry3D->GetExtent(0);
height = geometry3D->GetExtent(2);
break;
case Sagittal:
width = geometry3D->GetExtent(1);
height = geometry3D->GetExtent(2);
break;
default:
itkExceptionMacro("unknown PlaneOrientation");
- }
-
- InitializeStandardPlane( width, height,
- geometry3D->GetIndexToWorldTransform(),
- planeorientation, zPosition, frontside, rotated );
-
- ScalarType bounds[6]= { 0, width, 0, height, 0, 1 };
- this->SetBounds( bounds );
+ }
- Point3D origin;
- originVector = geometry3D->GetIndexToWorldTransform()
- ->TransformVector( originVector );
+ InitializeStandardPlane( width, height,
+ geometry3D->GetIndexToWorldTransform(),
+ planeorientation, zPosition, frontside, rotated );
- origin = GetOrigin() + originVector;
- SetOrigin(origin);
-}
+ ScalarType bounds[6]= { 0, width, 0, height, 0, 1 };
+ this->SetBounds( bounds );
+ Point3D origin;
+ originVector = geometry3D->GetIndexToWorldTransform()
+ ->TransformVector( originVector );
-void
-PlaneGeometry::InitializeStandardPlane( const Geometry3D *geometry3D,
- bool top, PlaneOrientation planeorientation, bool frontside, bool rotated )
-{
- ScalarType zPosition;
+ origin = GetOrigin() + originVector;
+ SetOrigin(origin);
+ }
- switch(planeorientation)
+ void
+ PlaneGeometry::InitializeStandardPlane( const BaseGeometry *geometry3D,
+ bool top, PlaneOrientation planeorientation, bool frontside, bool rotated )
{
+ ScalarType zPosition;
+
+ switch(planeorientation)
+ {
case Axial:
zPosition = (top ? 0.5 : geometry3D->GetExtent(2)-1+0.5);
break;
case Frontal:
zPosition = (top ? 0.5 : geometry3D->GetExtent(1)-1+0.5);
break;
case Sagittal:
zPosition = (top ? 0.5 : geometry3D->GetExtent(0)-1+0.5);
break;
default:
itkExceptionMacro("unknown PlaneOrientation");
+ }
+
+ InitializeStandardPlane( geometry3D, planeorientation,
+ zPosition, frontside, rotated );
}
- InitializeStandardPlane( geometry3D, planeorientation,
- zPosition, frontside, rotated );
-}
+ void
+ PlaneGeometry::InitializeStandardPlane( const Vector3D &rightVector,
+ const Vector3D &downVector, const Vector3D *spacing )
+ {
+ InitializeStandardPlane( rightVector.GetVnlVector(),
+ downVector.GetVnlVector(), spacing );
+ }
+ void
+ PlaneGeometry::InitializeStandardPlane( const VnlVector& rightVector,
+ const VnlVector &downVector, const Vector3D *spacing )
+ {
+ ScalarType width = rightVector.magnitude();
+ ScalarType height = downVector.magnitude();
-void
-PlaneGeometry::InitializeStandardPlane( const Vector3D &rightVector,
- const Vector3D &downVector, const Vector3D *spacing )
-{
- InitializeStandardPlane( rightVector.GetVnlVector(),
- downVector.GetVnlVector(), spacing );
-}
+ InitializeStandardPlane( width, height, rightVector, downVector, spacing );
+ }
+ void
+ PlaneGeometry::InitializeStandardPlane( mitk::ScalarType width,
+ ScalarType height, const Vector3D &rightVector, const Vector3D &downVector,
+ const Vector3D *spacing )
+ {
+ InitializeStandardPlane(
+ width, height,
+ rightVector.GetVnlVector(), downVector.GetVnlVector(),
+ spacing );
+ }
-void
-PlaneGeometry::InitializeStandardPlane( const VnlVector& rightVector,
- const VnlVector &downVector, const Vector3D *spacing )
-{
- ScalarType width = rightVector.magnitude();
- ScalarType height = downVector.magnitude();
+ void
+ PlaneGeometry::InitializeStandardPlane(
+ mitk::ScalarType width, ScalarType height,
+ const VnlVector &rightVector, const VnlVector &downVector,
+ const Vector3D *spacing )
+ {
+ assert(width > 0);
+ assert(height > 0);
- InitializeStandardPlane( width, height, rightVector, downVector, spacing );
-}
+ VnlVector rightDV = rightVector; rightDV.normalize();
+ VnlVector downDV = downVector; downDV.normalize();
+ VnlVector normal = vnl_cross_3d(rightVector, downVector);
+ normal.normalize();
+ if(spacing!=NULL)
+ {
+ rightDV *= (*spacing)[0];
+ downDV *= (*spacing)[1];
+ normal *= (*spacing)[2];
+ }
-void
-PlaneGeometry::InitializeStandardPlane( mitk::ScalarType width,
- ScalarType height, const Vector3D &rightVector, const Vector3D &downVector,
- const Vector3D *spacing )
-{
- InitializeStandardPlane(
- width, height,
- rightVector.GetVnlVector(), downVector.GetVnlVector(),
- spacing );
-}
-
-
-void
-PlaneGeometry::InitializeStandardPlane(
- mitk::ScalarType width, ScalarType height,
- const VnlVector &rightVector, const VnlVector &downVector,
- const Vector3D *spacing )
-{
- assert(width > 0);
- assert(height > 0);
+ AffineTransform3D::Pointer transform = AffineTransform3D::New();
+ Matrix3D matrix;
+ matrix.GetVnlMatrix().set_column(0, rightDV);
+ matrix.GetVnlMatrix().set_column(1, downDV);
+ matrix.GetVnlMatrix().set_column(2, normal);
+ transform->SetMatrix(matrix);
+ transform->SetOffset(this->GetIndexToWorldTransform()->GetOffset());
- VnlVector rightDV = rightVector; rightDV.normalize();
- VnlVector downDV = downVector; downDV.normalize();
- VnlVector normal = vnl_cross_3d(rightVector, downVector);
- normal.normalize();
+ ScalarType bounds[6] = { 0, width, 0, height, 0, 1 };
+ this->SetBounds( bounds );
- if(spacing!=NULL)
- {
- rightDV *= (*spacing)[0];
- downDV *= (*spacing)[1];
- normal *= (*spacing)[2];
+ this->SetIndexToWorldTransform( transform );
}
- AffineTransform3D::Pointer transform = AffineTransform3D::New();
- Matrix3D matrix;
- matrix.GetVnlMatrix().set_column(0, rightDV);
- matrix.GetVnlMatrix().set_column(1, downDV);
- matrix.GetVnlMatrix().set_column(2, normal);
- transform->SetMatrix(matrix);
- transform->SetOffset(m_IndexToWorldTransform->GetOffset());
-
- ScalarType bounds[6] = { 0, width, 0, height, 0, 1 };
- this->SetBounds( bounds );
+ void
+ PlaneGeometry::InitializePlane( const Point3D &origin,
+ const Vector3D &normal )
+ {
+ VnlVector rightVectorVnl(3), downVectorVnl;
- this->SetIndexToWorldTransform( transform );
-}
+ if( Equal( normal[1], 0.0f ) == false )
+ {
+ FillVector3D( rightVectorVnl, 1.0f, -normal[0]/normal[1], 0.0f );
+ rightVectorVnl.normalize();
+ }
+ else
+ {
+ FillVector3D( rightVectorVnl, 0.0f, 1.0f, 0.0f );
+ }
+ downVectorVnl = vnl_cross_3d( normal.GetVnlVector(), rightVectorVnl );
+ downVectorVnl.normalize();
+ InitializeStandardPlane( rightVectorVnl, downVectorVnl );
-void
-PlaneGeometry::InitializePlane( const Point3D &origin,
- const Vector3D &normal )
-{
- VnlVector rightVectorVnl(3), downVectorVnl;
+ SetOrigin(origin);
+ }
- if( Equal( normal[1], 0.0f ) == false )
+ void
+ PlaneGeometry::SetMatrixByVectors( const VnlVector &rightVector,
+ const VnlVector &downVector, ScalarType thickness )
{
- FillVector3D( rightVectorVnl, 1.0f, -normal[0]/normal[1], 0.0f );
- rightVectorVnl.normalize();
+ VnlVector normal = vnl_cross_3d(rightVector, downVector);
+ normal.normalize();
+ normal *= thickness;
+
+ AffineTransform3D::Pointer transform = AffineTransform3D::New();
+ Matrix3D matrix;
+ matrix.GetVnlMatrix().set_column(0, rightVector);
+ matrix.GetVnlMatrix().set_column(1, downVector);
+ matrix.GetVnlMatrix().set_column(2, normal);
+ transform->SetMatrix(matrix);
+ transform->SetOffset(this->GetIndexToWorldTransform()->GetOffset());
+ SetIndexToWorldTransform(transform);
}
- else
+
+ Vector3D
+ PlaneGeometry::GetNormal() const
{
- FillVector3D( rightVectorVnl, 0.0f, 1.0f, 0.0f );
+ Vector3D frontToBack;
+ frontToBack.SetVnlVector( this->GetIndexToWorldTransform()
+ ->GetMatrix().GetVnlMatrix().get_column(2) );
+
+ return frontToBack;
}
- downVectorVnl = vnl_cross_3d( normal.GetVnlVector(), rightVectorVnl );
- downVectorVnl.normalize();
- InitializeStandardPlane( rightVectorVnl, downVectorVnl );
+ VnlVector
+ PlaneGeometry::GetNormalVnl() const
+ {
+ return this->GetIndexToWorldTransform()
+ ->GetMatrix().GetVnlMatrix().get_column(2);
+ }
- SetOrigin(origin);
-}
+ ScalarType
+ PlaneGeometry::DistanceFromPlane( const Point3D &pt3d_mm ) const
+ {
+ return fabs(SignedDistance( pt3d_mm ));
+ }
+ ScalarType
+ PlaneGeometry::SignedDistance( const Point3D &pt3d_mm ) const
+ {
+ return SignedDistanceFromPlane(pt3d_mm);
+ }
-void
-PlaneGeometry::SetMatrixByVectors( const VnlVector &rightVector,
- const VnlVector &downVector, ScalarType thickness )
-{
- VnlVector normal = vnl_cross_3d(rightVector, downVector);
- normal.normalize();
- normal *= thickness;
-
- AffineTransform3D::Pointer transform = AffineTransform3D::New();
- Matrix3D matrix;
- matrix.GetVnlMatrix().set_column(0, rightVector);
- matrix.GetVnlMatrix().set_column(1, downVector);
- matrix.GetVnlMatrix().set_column(2, normal);
- transform->SetMatrix(matrix);
- transform->SetOffset(m_IndexToWorldTransform->GetOffset());
- SetIndexToWorldTransform(transform);
-}
-
-
-Vector3D
-PlaneGeometry::GetNormal() const
-{
- Vector3D frontToBack;
- frontToBack.SetVnlVector( m_IndexToWorldTransform
- ->GetMatrix().GetVnlMatrix().get_column(2) );
+ //Function from Geometry2D
+ // mitk::ScalarType
+ // PlaneGeometry::SignedDistance(const mitk::Point3D& pt3d_mm) const
+ //{
+ // Point3D projectedPoint;
+ // Project(pt3d_mm, projectedPoint);
+ // Vector3D direction = pt3d_mm-projectedPoint;
+ // ScalarType distance = direction.GetNorm();
- return frontToBack;
-}
+ // if(IsAbove(pt3d_mm) == false)
+ // distance*=-1.0;
+ // return distance;
+ //}
-VnlVector
-PlaneGeometry::GetNormalVnl() const
-{
- return m_IndexToWorldTransform
- ->GetMatrix().GetVnlMatrix().get_column(2);
-}
+ bool
+ PlaneGeometry::IsAbove( const Point3D &pt3d_mm , bool considerBoundingBox) const
+ {
+ if(considerBoundingBox)
+ {
+ Point3D pt3d_units;
+ BaseGeometry::WorldToIndex(pt3d_mm, pt3d_units);
+ return (pt3d_units[2] > this->GetBoundingBox()->GetBounds()[4]);
+ }
+ else
+ return SignedDistanceFromPlane(pt3d_mm) > 0;
+ }
+ bool
+ PlaneGeometry::IntersectionLine(
+ const PlaneGeometry* plane, Line3D& crossline ) const
+ {
+ Vector3D normal = this->GetNormal();
+ normal.Normalize();
-ScalarType
-PlaneGeometry::DistanceFromPlane( const Point3D &pt3d_mm ) const
-{
- return fabs(SignedDistance( pt3d_mm ));
-}
+ Vector3D planeNormal = plane->GetNormal();
+ planeNormal.Normalize();
+ Vector3D direction = itk::CrossProduct( normal, planeNormal );
-ScalarType
-PlaneGeometry::SignedDistance( const Point3D &pt3d_mm ) const
-{
- return SignedDistanceFromPlane(pt3d_mm);
-}
+ if ( direction.GetSquaredNorm() < eps )
+ return false;
+ crossline.SetDirection( direction );
-bool
-PlaneGeometry::IsAbove( const Point3D &pt3d_mm ) const
-{
- return SignedDistanceFromPlane(pt3d_mm) > 0;
-}
+ double N1dN2 = normal * planeNormal;
+ double determinant = 1.0 - N1dN2 * N1dN2;
+ Vector3D origin = this->GetOrigin().GetVectorFromOrigin();
+ Vector3D planeOrigin = plane->GetOrigin().GetVectorFromOrigin();
-bool
-PlaneGeometry::IntersectionLine(
- const PlaneGeometry* plane, Line3D& crossline ) const
-{
- Vector3D normal = this->GetNormal();
- normal.Normalize();
+ double d1 = normal * origin;
+ double d2 = planeNormal * planeOrigin;
- Vector3D planeNormal = plane->GetNormal();
- planeNormal.Normalize();
+ double c1 = ( d1 - d2 * N1dN2 ) / determinant;
+ double c2 = ( d2 - d1 * N1dN2 ) / determinant;
- Vector3D direction = itk::CrossProduct( normal, planeNormal );
+ Vector3D p = normal * c1 + planeNormal * c2;
+ crossline.GetPoint().GetVnlVector() = p.GetVnlVector();
- if ( direction.GetSquaredNorm() < eps )
- return false;
+ return true;
+ }
- crossline.SetDirection( direction );
+ unsigned int
+ PlaneGeometry::IntersectWithPlane2D(
+ const PlaneGeometry* plane, Point2D& lineFrom, Point2D &lineTo ) const
+ {
+ Line3D crossline;
+ if ( this->IntersectionLine( plane, crossline ) == false )
+ return 0;
- double N1dN2 = normal * planeNormal;
- double determinant = 1.0 - N1dN2 * N1dN2;
+ Point2D point2;
+ Vector2D direction2;
- Vector3D origin = this->GetOrigin().GetVectorFromOrigin();
- Vector3D planeOrigin = plane->GetOrigin().GetVectorFromOrigin();
+ this->Map( crossline.GetPoint(), point2 );
+ this->Map( crossline.GetPoint(), crossline.GetDirection(), direction2 );
- double d1 = normal * origin;
- double d2 = planeNormal * planeOrigin;
+ return
+ Line3D::RectangleLineIntersection(
+ 0, 0, GetExtentInMM(0), GetExtentInMM(1),
+ point2, direction2, lineFrom, lineTo );
+ }
- double c1 = ( d1 - d2 * N1dN2 ) / determinant;
- double c2 = ( d2 - d1 * N1dN2 ) / determinant;
+ double PlaneGeometry::Angle( const PlaneGeometry *plane ) const
+ {
+ return angle(plane->GetMatrixColumn(2), GetMatrixColumn(2));
+ }
- Vector3D p = normal * c1 + planeNormal * c2;
- crossline.GetPoint().GetVnlVector() = p.GetVnlVector();
+ double PlaneGeometry::Angle( const Line3D &line ) const
+ {
+ return vnl_math::pi_over_2
+ - angle( line.GetDirection().GetVnlVector(), GetMatrixColumn(2) );
+ }
- return true;
-}
+ bool PlaneGeometry::IntersectionPoint(
+ const Line3D &line, Point3D &intersectionPoint ) const
+ {
+ Vector3D planeNormal = this->GetNormal();
+ planeNormal.Normalize();
+ Vector3D lineDirection = line.GetDirection();
+ lineDirection.Normalize();
-unsigned int
-PlaneGeometry::IntersectWithPlane2D(
- const PlaneGeometry* plane, Point2D& lineFrom, Point2D &lineTo ) const
-{
- Line3D crossline;
- if ( this->IntersectionLine( plane, crossline ) == false )
- return 0;
+ double t = planeNormal * lineDirection;
+ if ( fabs( t ) < eps )
+ {
+ return false;
+ }
- Point2D point2;
- Vector2D direction2;
+ Vector3D diff;
+ diff = this->GetOrigin() - line.GetPoint();
+ t = ( planeNormal * diff ) / t;
- this->Map( crossline.GetPoint(), point2 );
- this->Map( crossline.GetPoint(), crossline.GetDirection(), direction2 );
+ intersectionPoint = line.GetPoint() + lineDirection * t;
+ return true;
+ }
- return
- Line3D::RectangleLineIntersection(
- 0, 0, GetExtentInMM(0), GetExtentInMM(1),
- point2, direction2, lineFrom, lineTo );
-}
+ bool
+ PlaneGeometry::IntersectionPointParam( const Line3D &line, double &t ) const
+ {
+ Vector3D planeNormal = this->GetNormal();
+ Vector3D lineDirection = line.GetDirection();
-double PlaneGeometry::Angle( const PlaneGeometry *plane ) const
-{
- return angle(plane->GetMatrixColumn(2), GetMatrixColumn(2));
-}
+ t = planeNormal * lineDirection;
+ if ( fabs( t ) < eps )
+ {
+ return false;
+ }
-double PlaneGeometry::Angle( const Line3D &line ) const
-{
- return vnl_math::pi_over_2
- - angle( line.GetDirection().GetVnlVector(), GetMatrixColumn(2) );
-}
+ Vector3D diff;
+ diff = this->GetOrigin() - line.GetPoint();
+ t = ( planeNormal * diff ) / t;
+ return true;
+ }
+ bool
+ PlaneGeometry::IsParallel( const PlaneGeometry *plane ) const
+ {
+ return ( (Angle(plane) < 10.0 * mitk::sqrteps ) || ( Angle(plane) > ( vnl_math::pi - 10.0 * sqrteps ) ) ) ;
+ }
-bool PlaneGeometry::IntersectionPoint(
- const Line3D &line, Point3D &intersectionPoint ) const
-{
- Vector3D planeNormal = this->GetNormal();
- planeNormal.Normalize();
+ bool
+ PlaneGeometry::IsOnPlane( const Point3D &point ) const
+ {
+ return Distance(point) < eps;
+ }
- Vector3D lineDirection = line.GetDirection();
- lineDirection.Normalize();
+ bool
+ PlaneGeometry::IsOnPlane( const Line3D &line ) const
+ {
+ return ( (Distance( line.GetPoint() ) < eps)
+ && (Distance( line.GetPoint2() ) < eps) );
+ }
- double t = planeNormal * lineDirection;
- if ( fabs( t ) < eps )
+ bool
+ PlaneGeometry::IsOnPlane( const PlaneGeometry *plane ) const
{
- return false;
+ return ( IsParallel( plane ) && (Distance( plane->GetOrigin() ) < eps) );
}
- Vector3D diff;
- diff = this->GetOrigin() - line.GetPoint();
- t = ( planeNormal * diff ) / t;
+ Point3D
+ PlaneGeometry::ProjectPointOntoPlane( const Point3D& pt ) const
+ {
+ ScalarType len = this->GetNormalVnl().two_norm();
+ return pt - this->GetNormal() * this->SignedDistanceFromPlane( pt ) / len;
+ }
- intersectionPoint = line.GetPoint() + lineDirection * t;
- return true;
-}
+ itk::LightObject::Pointer
+ PlaneGeometry::InternalClone() const
+ {
+ Self::Pointer newGeometry = new PlaneGeometry(*this);
+ newGeometry->UnRegister();
+ return newGeometry.GetPointer();
+ }
+ void
+ PlaneGeometry::ExecuteOperation( Operation *operation )
+ {
+ vtkTransform *transform = vtkTransform::New();
+ transform->SetMatrix( this->GetVtkMatrix());
-bool
-PlaneGeometry::IntersectionPointParam( const Line3D &line, double &t ) const
-{
- Vector3D planeNormal = this->GetNormal();
+ switch ( operation->GetOperationType() )
+ {
+ case OpORIENT:
+ {
+ mitk::PlaneOperation *planeOp = dynamic_cast< mitk::PlaneOperation * >( operation );
+ if ( planeOp == NULL )
+ {
+ return;
+ }
- Vector3D lineDirection = line.GetDirection();
+ Point3D center = planeOp->GetPoint();
- t = planeNormal * lineDirection;
+ Vector3D orientationVector = planeOp->GetNormal();
+ Vector3D defaultVector;
+ FillVector3D( defaultVector, 0.0, 0.0, 1.0 );
- if ( fabs( t ) < eps )
- {
- return false;
- }
+ Vector3D rotationAxis = itk::CrossProduct( orientationVector, defaultVector );
+ //double rotationAngle = acos( orientationVector[2] / orientationVector.GetNorm() );
- Vector3D diff;
- diff = this->GetOrigin() - line.GetPoint();
- t = ( planeNormal * diff ) / t;
- return true;
-}
+ double rotationAngle = atan2( (double) rotationAxis.GetNorm(), (double) (orientationVector * defaultVector) );
+ rotationAngle *= 180.0 / vnl_math::pi;
+ transform->PostMultiply();
+ transform->Identity();
+ transform->Translate( center[0], center[1], center[2] );
+ transform->RotateWXYZ( rotationAngle, rotationAxis[0], rotationAxis[1], rotationAxis[2] );
+ transform->Translate( -center[0], -center[1], -center[2] );
+ break;
+ }
+ case OpRESTOREPLANEPOSITION:
+ {
+ RestorePlanePositionOperation *op = dynamic_cast< mitk::RestorePlanePositionOperation* >(operation);
+ if(op == NULL)
+ {
+ return;
+ }
-bool
-PlaneGeometry::IsParallel( const PlaneGeometry *plane ) const
-{
- return ( (Angle(plane) < 10.0 * mitk::sqrteps ) || ( Angle(plane) > ( vnl_math::pi - 10.0 * sqrteps ) ) ) ;
-}
+ AffineTransform3D::Pointer transform2 = AffineTransform3D::New();
+ Matrix3D matrix;
+ matrix.GetVnlMatrix().set_column(0, op->GetTransform()->GetMatrix().GetVnlMatrix().get_column(0));
+ matrix.GetVnlMatrix().set_column(1, op->GetTransform()->GetMatrix().GetVnlMatrix().get_column(1));
+ matrix.GetVnlMatrix().set_column(2, op->GetTransform()->GetMatrix().GetVnlMatrix().get_column(2));
+ transform2->SetMatrix(matrix);
+ Vector3D offset = op->GetTransform()->GetOffset();
+ transform2->SetOffset(offset);
+
+ this->SetIndexToWorldTransform(transform2);
+ ScalarType bounds[6] = {0, op->GetWidth(), 0, op->GetHeight(), 0 ,1 };
+ this->SetBounds(bounds);
+ TransferItkToVtkTransform();
+ this->Modified();
+ transform->Delete();
+ return;
+ }
+ default:
+ Superclass::ExecuteOperation( operation );
+ transform->Delete();
+ return;
+ }
+ this->GetVtkMatrix()->DeepCopy(transform->GetMatrix());
+ this->TransferVtkToItkTransform();
+ this->Modified();
+ transform->Delete();
+ }
-bool
-PlaneGeometry::IsOnPlane( const Point3D &point ) const
-{
- return Distance(point) < eps;
-}
+ void PlaneGeometry::PrintSelf( std::ostream& os, itk::Indent indent ) const
+ {
+ Superclass::PrintSelf(os,indent);
+ os << indent << " ScaleFactorMMPerUnitX: "
+ << m_ScaleFactorMMPerUnitX << std::endl;
+ os << indent << " ScaleFactorMMPerUnitY: "
+ << m_ScaleFactorMMPerUnitY << std::endl;
+ os << indent << " Normal: " << GetNormal() << std::endl;
+ }
+ void PlaneGeometry::PostSetIndexToWorldTransform(
+ mitk::AffineTransform3D* transform)
+ {
+ m_ScaleFactorMMPerUnitX=GetExtentInMM(0)/GetExtent(0);
+ m_ScaleFactorMMPerUnitY=GetExtentInMM(1)/GetExtent(1);
-bool
-PlaneGeometry::IsOnPlane( const Line3D &line ) const
-{
- return ( (Distance( line.GetPoint() ) < eps)
- && (Distance( line.GetPoint2() ) < eps) );
-}
+ assert(m_ScaleFactorMMPerUnitX<ScalarTypeNumericTraits::infinity());
+ assert(m_ScaleFactorMMPerUnitY<ScalarTypeNumericTraits::infinity());
+ }
+ void
+ PlaneGeometry::PostSetExtentInMM(int direction, ScalarType extentInMM)
+ {
+ m_ScaleFactorMMPerUnitX=GetExtentInMM(0)/GetExtent(0);
+ m_ScaleFactorMMPerUnitY=GetExtentInMM(1)/GetExtent(1);
-bool
-PlaneGeometry::IsOnPlane( const PlaneGeometry *plane ) const
-{
- return ( IsParallel( plane ) && (Distance( plane->GetOrigin() ) < eps) );
-}
+ assert(m_ScaleFactorMMPerUnitX<ScalarTypeNumericTraits::infinity());
+ assert(m_ScaleFactorMMPerUnitY<ScalarTypeNumericTraits::infinity());
+ }
+ bool
+ PlaneGeometry::Map(
+ const mitk::Point3D &pt3d_mm, mitk::Point2D &pt2d_mm) const
+ {
+ assert(this->IsBoundingBoxNull()==false);
+
+ Point3D pt3d_units;
+ BackTransform(pt3d_mm, pt3d_units);
+ pt2d_mm[0]=pt3d_units[0]*m_ScaleFactorMMPerUnitX;
+ pt2d_mm[1]=pt3d_units[1]*m_ScaleFactorMMPerUnitY;
+ pt3d_units[2]=0;
+ return const_cast<BoundingBox*>(this->GetBoundingBox())->IsInside(pt3d_units);
+ }
-Point3D
-PlaneGeometry::ProjectPointOntoPlane( const Point3D& pt ) const
-{
- ScalarType len = this->GetNormalVnl().two_norm();
- return pt - this->GetNormal() * this->SignedDistanceFromPlane( pt ) / len;
-}
+ void
+ PlaneGeometry::Map(const mitk::Point2D &pt2d_mm, mitk::Point3D &pt3d_mm) const
+ {
+ Point3D pt3d_units;
+ pt3d_units[0]=pt2d_mm[0]/m_ScaleFactorMMPerUnitX;
+ pt3d_units[1]=pt2d_mm[1]/m_ScaleFactorMMPerUnitY;
+ pt3d_units[2]=0;
+ pt3d_mm = GetIndexToWorldTransform()->TransformPoint(pt3d_units);
+ }
+ void
+ PlaneGeometry::SetSizeInUnits(mitk::ScalarType width, mitk::ScalarType height)
+ {
+ ScalarType bounds[6]={0, width, 0, height, 0, 1};
+ ScalarType extent, newextentInMM;
+ if(GetExtent(0)>0)
+ {
+ extent = GetExtent(0);
+ if(width>extent)
+ newextentInMM = GetExtentInMM(0)/width*extent;
+ else
+ newextentInMM = GetExtentInMM(0)*extent/width;
+ SetExtentInMM(0, newextentInMM);
+ }
+ if(GetExtent(1)>0)
+ {
+ extent = GetExtent(1);
+ if(width>extent)
+ newextentInMM = GetExtentInMM(1)/height*extent;
+ else
+ newextentInMM = GetExtentInMM(1)*extent/height;
+ SetExtentInMM(1, newextentInMM);
+ }
+ SetBounds(bounds);
+ }
-itk::LightObject::Pointer
-PlaneGeometry::InternalClone() const
-{
- Self::Pointer newGeometry = new PlaneGeometry(*this);
- newGeometry->UnRegister();
- return newGeometry.GetPointer();
-}
+ bool
+ PlaneGeometry::Project(
+ const mitk::Point3D &pt3d_mm, mitk::Point3D &projectedPt3d_mm) const
+ {
+ assert(this->IsBoundingBoxNull()==false);
-void
-PlaneGeometry::ExecuteOperation( Operation *operation )
-{
- vtkTransform *transform = vtkTransform::New();
- transform->SetMatrix( m_VtkMatrix );
+ Point3D pt3d_units;
+ BackTransform(pt3d_mm, pt3d_units);
+ pt3d_units[2] = 0;
+ projectedPt3d_mm = GetIndexToWorldTransform()->TransformPoint(pt3d_units);
+ return const_cast<BoundingBox*>(this->GetBoundingBox())->IsInside(pt3d_units);
+ }
- switch ( operation->GetOperationType() )
+ bool
+ PlaneGeometry::Project(const mitk::Vector3D &vec3d_mm, mitk::Vector3D &projectedVec3d_mm) const
{
- case OpORIENT:
- {
- mitk::PlaneOperation *planeOp = dynamic_cast< mitk::PlaneOperation * >( operation );
- if ( planeOp == NULL )
- {
- return;
- }
+ assert(this->IsBoundingBoxNull()==false);
- Point3D center = planeOp->GetPoint();
-
- Vector3D orientationVector = planeOp->GetNormal();
- Vector3D defaultVector;
- FillVector3D( defaultVector, 0.0, 0.0, 1.0 );
+ Vector3D vec3d_units;
+ BackTransform(vec3d_mm, vec3d_units);
+ vec3d_units[2] = 0;
+ projectedVec3d_mm = GetIndexToWorldTransform()->TransformVector(vec3d_units);
+ return true;
+ }
- Vector3D rotationAxis = itk::CrossProduct( orientationVector, defaultVector );
- //double rotationAngle = acos( orientationVector[2] / orientationVector.GetNorm() );
+ bool
+ PlaneGeometry::Project(const mitk::Point3D & atPt3d_mm,
+ const mitk::Vector3D &vec3d_mm, mitk::Vector3D &projectedVec3d_mm) const
+ {
+ MITK_WARN << "Deprecated function! Call Project(vec3D,vec3D) instead.";
+ assert(this->IsBoundingBoxNull()==false);
- double rotationAngle = atan2( (double) rotationAxis.GetNorm(), (double) (orientationVector * defaultVector) );
- rotationAngle *= 180.0 / vnl_math::pi;
+ Vector3D vec3d_units;
+ BackTransform(atPt3d_mm, vec3d_mm, vec3d_units);
+ vec3d_units[2] = 0;
+ projectedVec3d_mm = GetIndexToWorldTransform()->TransformVector(vec3d_units);
- transform->PostMultiply();
- transform->Identity();
- transform->Translate( center[0], center[1], center[2] );
- transform->RotateWXYZ( rotationAngle, rotationAxis[0], rotationAxis[1], rotationAxis[2] );
- transform->Translate( -center[0], -center[1], -center[2] );
- break;
- }
- case OpRESTOREPLANEPOSITION:
- {
- RestorePlanePositionOperation *op = dynamic_cast< mitk::RestorePlanePositionOperation* >(operation);
- if(op == NULL)
- {
- return;
- }
+ Point3D pt3d_units;
+ BackTransform(atPt3d_mm, pt3d_units);
+ return const_cast<BoundingBox*>(this->GetBoundingBox())->IsInside(pt3d_units);
+ }
- AffineTransform3D::Pointer transform2 = AffineTransform3D::New();
- Matrix3D matrix;
- matrix.GetVnlMatrix().set_column(0, op->GetTransform()->GetMatrix().GetVnlMatrix().get_column(0));
- matrix.GetVnlMatrix().set_column(1, op->GetTransform()->GetMatrix().GetVnlMatrix().get_column(1));
- matrix.GetVnlMatrix().set_column(2, op->GetTransform()->GetMatrix().GetVnlMatrix().get_column(2));
- transform2->SetMatrix(matrix);
- Vector3D offset = op->GetTransform()->GetOffset();
- transform2->SetOffset(offset);
-
- this->SetIndexToWorldTransform(transform2);
- ScalarType bounds[6] = {0, op->GetWidth(), 0, op->GetHeight(), 0 ,1 };
- this->SetBounds(bounds);
- TransferItkToVtkTransform();
- this->Modified();
- transform->Delete();
- return;
+ bool
+ PlaneGeometry::Map(const mitk::Point3D & atPt3d_mm,
+ const mitk::Vector3D &vec3d_mm, mitk::Vector2D &vec2d_mm) const
+ {
+ Point2D pt2d_mm_start, pt2d_mm_end;
+ Point3D pt3d_mm_end;
+ bool inside=Map(atPt3d_mm, pt2d_mm_start);
+ pt3d_mm_end = atPt3d_mm+vec3d_mm;
+ inside&=Map(pt3d_mm_end, pt2d_mm_end);
+ vec2d_mm=pt2d_mm_end-pt2d_mm_start;
+ return inside;
+ }
- }
- default:
- Superclass::ExecuteOperation( operation );
- transform->Delete();
- return;
+ void
+ PlaneGeometry::Map(const mitk::Point2D &/*atPt2d_mm*/,
+ const mitk::Vector2D &/*vec2d_mm*/, mitk::Vector3D &/*vec3d_mm*/) const
+ {
+ //@todo implement parallel to the other Map method!
+ assert(false);
}
- m_VtkMatrix->DeepCopy(transform->GetMatrix());
- this->TransferVtkToItkTransform();
- this->Modified();
- transform->Delete();
-}
-void PlaneGeometry::PrintSelf( std::ostream& os, itk::Indent indent ) const
-{
- Superclass::PrintSelf(os,indent);
- os << indent << " Normal: " << GetNormal() << std::endl;
-}
+ void
+ PlaneGeometry::SetReferenceGeometry( mitk::BaseGeometry *geometry )
+ {
+ m_ReferenceGeometry = geometry;
+ }
+ mitk::BaseGeometry *
+ PlaneGeometry::GetReferenceGeometry() const
+ {
+ return m_ReferenceGeometry;
+ }
+
+ bool
+ PlaneGeometry::HasReferenceGeometry() const
+ {
+ return ( m_ReferenceGeometry != NULL );
+ }
} // namespace
diff --git a/Core/Code/DataManagement/mitkPlaneGeometry.h b/Core/Code/DataManagement/mitkPlaneGeometry.h
index ed8fd8d6e7..716d4abf82 100644
--- a/Core/Code/DataManagement/mitkPlaneGeometry.h
+++ b/Core/Code/DataManagement/mitkPlaneGeometry.h
@@ -1,428 +1,568 @@
/*===================================================================
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.
===================================================================*/
+/**
+* \brief Describes the geometry of a plane object
+*
+* Describes a two-dimensional manifold, i.e., to put it simply,
+* an object that can be described using a 2D coordinate-system.
+*
+* PlaneGeometry can map points between 3D world coordinates
+* (in mm) and the described 2D coordinate-system (in mm) by first projecting
+* the 3D point onto the 2D manifold and then calculating the 2D-coordinates
+* (in mm). These 2D-mm-coordinates can be further converted into
+* 2D-unit-coordinates (e.g., pixels), giving a parameter representation of
+* the object with parameter values inside a rectangle
+* (e.g., [0,0]..[width, height]), which is the bounding box (bounding range
+* in z-direction always [0]..[1]).
+*
+* A PlaneGeometry describes the 2D representation within a 3D object (derived from BaseGeometry). For example,
+* a single CT-image (slice) is 2D in the sense that you can access the
+* pixels using 2D-coordinates, but is also 3D, as the pixels are really
+* voxels, thus have an extension (thickness) in the 3rd dimension.
+*
+*
+* Optionally, a reference BaseGeometry can be specified, which usually would
+* be the geometry associated with the underlying dataset. This is currently
+* used for calculating the intersection of inclined / rotated planes
+* (represented as PlaneGeometry) with the bounding box of the associated
+* BaseGeometry.
+*
+* \warning The PlaneGeometry are not necessarily up-to-date and not even
+* initialized. As described in the previous paragraph, one of the
+* Generate-/Copy-/UpdateOutputInformation methods have to initialize it.
+* mitk::BaseData::GetPlaneGeometry() makes sure, that the PlaneGeometry is
+* up-to-date before returning it (by setting the update extent appropriately
+* and calling UpdateOutputInformation).
+*
+* Rule: everything is in mm (or ms for temporal information) if not
+* stated otherwise.
+* \ingroup Geometry
+*/
#ifndef PLANEGEOMETRY_H_HEADER_INCLUDED_C1C68A2C
#define PLANEGEOMETRY_H_HEADER_INCLUDED_C1C68A2C
#include <MitkCoreExports.h>
-#include "mitkGeometry2D.h"
+#include "mitkBaseGeometry.h"
#include "mitkRestorePlanePositionOperation.h"
#include <vnl/vnl_cross.h>
namespace mitk {
+ template < class TCoordRep, unsigned int NPointDimension > class Line;
+ typedef Line<ScalarType, 3> Line3D;
-template < class TCoordRep, unsigned int NPointDimension > class Line;
-typedef Line<ScalarType, 3> Line3D;
-
-
-
-/**
- * \brief Describes a two-dimensional, rectangular plane
- *
- * \ingroup Geometry
- */
-class MITK_CORE_EXPORT PlaneGeometry : public Geometry2D
-{
-public:
- mitkClassMacro(PlaneGeometry,Geometry2D);
-
- /** Method for creation through the object factory. */
- itkFactorylessNewMacro(Self)
- itkCloneMacro(Self)
-
- enum PlaneOrientation
- {
- Axial,
- Sagittal,
- Frontal
- };
-
- virtual void IndexToWorld(const Point2D &pt_units, Point2D &pt_mm) const;
-
- virtual void WorldToIndex(const Point2D &pt_mm, Point2D &pt_units) const;
-
-
- //##Documentation
- //## @brief Convert (continuous or discrete) index coordinates of a \em vector
- //## \a vec_units to world coordinates (in mm)
- //## @deprecated First parameter (Point2D) is not used. If possible, please use void IndexToWorld(const mitk::Vector2D& vec_units, mitk::Vector2D& vec_mm) const.
- //## For further information about coordinates types, please see the Geometry documentation
- virtual void IndexToWorld(const mitk::Point2D &atPt2d_untis, const mitk::Vector2D &vec_units, mitk::Vector2D &vec_mm) const;
-
- //##Documentation
- //## @brief Convert (continuous or discrete) index coordinates of a \em vector
- //## \a vec_units to world coordinates (in mm)
- //## For further information about coordinates types, please see the Geometry documentation
- virtual void IndexToWorld(const mitk::Vector2D &vec_units, mitk::Vector2D &vec_mm) const;
-
- //##Documentation
- //## @brief Convert world coordinates (in mm) of a \em vector
- //## \a vec_mm to (continuous!) index coordinates.
- //## @deprecated First parameter (Point2D) is not used. If possible, please use void WorldToIndex(const mitk::Vector2D& vec_mm, mitk::Vector2D& vec_units) const.
- //## For further information about coordinates types, please see the Geometry documentation
- virtual void WorldToIndex(const mitk::Point2D &atPt2d_mm, const mitk::Vector2D &vec_mm, mitk::Vector2D &vec_units) const;
-
- //##Documentation
- //## @brief Convert world coordinates (in mm) of a \em vector
- //## \a vec_mm to (continuous!) index coordinates.
- //## For further information about coordinates types, please see the Geometry documentation
- virtual void WorldToIndex(const mitk::Vector2D &vec_mm, mitk::Vector2D &vec_units) const;
-
-
- virtual void Initialize();
-
- /**
- * \brief Initialize a plane with orientation \a planeorientation
- * (default: axial) with respect to \a geometry3D (default: identity).
- * Spacing also taken from \a geometry3D.
- *
- * \warning A former version of this method created a geometry with unit
- * spacing. For unit spacing use
- *
- * \code
- * // for in-plane unit spacing:
- * thisgeometry->SetSizeInUnits(thisgeometry->GetExtentInMM(0),
- * thisgeometry->GetExtentInMM(1));
- * // additionally, for unit spacing in normal direction (former version
- * // did not do this):
- * thisgeometry->SetExtentInMM(2, 1.0);
- * \endcode
- */
- virtual void InitializeStandardPlane( const Geometry3D* geometry3D,
- PlaneOrientation planeorientation = Axial, ScalarType zPosition = 0,
- bool frontside=true, bool rotated=false );
-
-
- /**
- * \brief Initialize a plane with orientation \a planeorientation
- * (default: axial) with respect to \a geometry3D (default: identity).
- * Spacing also taken from \a geometry3D.
- *
- * \param top if \a true, create plane at top, otherwise at bottom
- * (for PlaneOrientation Axial, for other plane locations respectively)
- */
- virtual void InitializeStandardPlane( const Geometry3D* geometry3D, bool top,
- PlaneOrientation planeorientation = Axial,
- bool frontside=true, bool rotated=false );
-
-
- /**
- * \brief Initialize a plane with orientation \a planeorientation
- * (default: axial) with respect to \a transform (default: identity)
- * given width and height in units.
- *
- */
- virtual void InitializeStandardPlane( ScalarType width, ScalarType height,
- const AffineTransform3D* transform = NULL,
- PlaneOrientation planeorientation = Axial,
- ScalarType zPosition = 0, bool frontside=true, bool rotated=false );
-
-
- /**
- * \brief Initialize plane with orientation \a planeorientation
- * (default: axial) given width, height and spacing.
- *
- */
- virtual void InitializeStandardPlane( ScalarType width, ScalarType height,
- const Vector3D & spacing, PlaneOrientation planeorientation = Axial,
- ScalarType zPosition = 0, bool frontside = true, bool rotated = false );
-
- /**
- * \brief Initialize plane by width and height in pixels, right-/down-vector
- * (itk) to describe orientation in world-space (vectors will be normalized)
- * and spacing (default: 1.0 mm in all directions).
- *
- * The vectors are normalized and multiplied by the respective spacing before
- * they are set in the matrix.
- */
- virtual void InitializeStandardPlane( ScalarType width, ScalarType height,
- const Vector3D& rightVector, const Vector3D& downVector,
- const Vector3D *spacing = NULL );
-
-
- /**
- * \brief Initialize plane by width and height in pixels,
- * right-/down-vector (vnl) to describe orientation in world-space (vectors
- * will be normalized) and spacing (default: 1.0 mm in all directions).
- *
- * The vectors are normalized and multiplied by the respective spacing
- * before they are set in the matrix.
- */
- virtual void InitializeStandardPlane( ScalarType width, ScalarType height,
- const VnlVector& rightVector, const VnlVector& downVector,
- const Vector3D * spacing = NULL );
-
-
- /**
- * \brief Initialize plane by right-/down-vector (itk) and spacing
- * (default: 1.0 mm in all directions).
- *
- * The length of the right-/-down-vector is used as width/height in units,
- * respectively. Then, the vectors are normalized and multiplied by the
- * respective spacing before they are set in the matrix.
- */
- virtual void InitializeStandardPlane( const Vector3D& rightVector,
- const Vector3D& downVector, const Vector3D * spacing = NULL );
-
-
- /**
- * \brief Initialize plane by right-/down-vector (vnl) and spacing
- * (default: 1.0 mm in all directions).
- *
- * The length of the right-/-down-vector is used as width/height in units,
- * respectively. Then, the vectors are normalized and multiplied by the
- * respective spacing before they are set in the matrix.
- */
- virtual void InitializeStandardPlane( const VnlVector& rightVector,
- const VnlVector& downVector, const Vector3D * spacing = NULL );
+ class PlaneGeometry;
+ /** \deprecatedSince{2014_06} This class is deprecated. Please use PlaneGeometry instead. */
+ DEPRECATED( typedef PlaneGeometry Geometry2D);
/**
- * \brief Initialize plane by origin and normal (size is 1.0 mm in
- * all directions, direction of right-/down-vector valid but
- * undefined).
- *
- */
- virtual void InitializePlane( const Point3D& origin, const Vector3D& normal);
-
- /**
- * \brief Initialize plane by right-/down-vector.
- *
- * \warning The vectors are set into the matrix as they are,
- * \em without normalization!
- */
- void SetMatrixByVectors( const VnlVector& rightVector,
- const VnlVector& downVector, ScalarType thickness=1.0 );
-
-
- /**
- * \brief Change \a transform so that the third column of the
- * transform-martix is perpendicular to the first two columns
- *
- */
- static void EnsurePerpendicularNormal( AffineTransform3D* transform );
-
-
- /**
- * \brief Normal of the plane
- *
- */
- Vector3D GetNormal() const;
-
-
- /**
- * \brief Normal of the plane as VnlVector
- *
- */
- VnlVector GetNormalVnl() const;
-
-
- virtual ScalarType SignedDistance( const Point3D& pt3d_mm ) const;
-
-
- virtual bool IsAbove( const Point3D& pt3d_mm ) const;
-
-
- /**
- * \brief Distance of the point from the plane
- * (bounding-box \em not considered)
- *
- */
- ScalarType DistanceFromPlane( const Point3D& pt3d_mm ) const ;
-
-
- /**
- * \brief Signed distance of the point from the plane
- * (bounding-box \em not considered)
- *
- * > 0 : point is in the direction of the direction vector.
- */
- inline ScalarType SignedDistanceFromPlane( const Point3D& pt3d_mm ) const
+ * \brief Describes a two-dimensional, rectangular plane
+ *
+ * \ingroup Geometry
+ */
+ class MITK_CORE_EXPORT PlaneGeometry : public BaseGeometry
{
- ScalarType len = GetNormalVnl().two_norm();
-
- if( len == 0 )
- return 0;
+ public:
+ mitkClassMacro(PlaneGeometry,BaseGeometry);
- return (pt3d_mm-GetOrigin())*GetNormal() / len;
- }
+ /** Method for creation through the object factory. */
+ itkFactorylessNewMacro(Self)
+ itkCloneMacro(Self)
+ enum PlaneOrientation
+ {
+ Axial,
+ Sagittal,
+ Frontal
+ };
+
+ virtual void IndexToWorld(const Point2D &pt_units, Point2D &pt_mm) const;
+
+ virtual void WorldToIndex(const Point2D &pt_mm, Point2D &pt_units) const;
+
+ //##Documentation
+ //## @brief Convert (continuous or discrete) index coordinates of a \em vector
+ //## \a vec_units to world coordinates (in mm)
+ //## @deprecated First parameter (Point2D) is not used. If possible, please use void IndexToWorld(const mitk::Vector2D& vec_units, mitk::Vector2D& vec_mm) const.
+ //## For further information about coordinates types, please see the Geometry documentation
+ virtual void IndexToWorld(const mitk::Point2D &atPt2d_untis, const mitk::Vector2D &vec_units, mitk::Vector2D &vec_mm) const;
+
+ //##Documentation
+ //## @brief Convert (continuous or discrete) index coordinates of a \em vector
+ //## \a vec_units to world coordinates (in mm)
+ //## For further information about coordinates types, please see the Geometry documentation
+ virtual void IndexToWorld(const mitk::Vector2D &vec_units, mitk::Vector2D &vec_mm) const;
+
+ //##Documentation
+ //## @brief Convert world coordinates (in mm) of a \em vector
+ //## \a vec_mm to (continuous!) index coordinates.
+ //## @deprecated First parameter (Point2D) is not used. If possible, please use void WorldToIndex(const mitk::Vector2D& vec_mm, mitk::Vector2D& vec_units) const.
+ //## For further information about coordinates types, please see the Geometry documentation
+ virtual void WorldToIndex(const mitk::Point2D &atPt2d_mm, const mitk::Vector2D &vec_mm, mitk::Vector2D &vec_units) const;
+
+ //##Documentation
+ //## @brief Convert world coordinates (in mm) of a \em vector
+ //## \a vec_mm to (continuous!) index coordinates.
+ //## For further information about coordinates types, please see the Geometry documentation
+ virtual void WorldToIndex(const mitk::Vector2D &vec_mm, mitk::Vector2D &vec_units) const;
+
+ /**
+ * \brief Initialize a plane with orientation \a planeorientation
+ * (default: axial) with respect to \a BaseGeometry (default: identity).
+ * Spacing also taken from \a BaseGeometry.
+ *
+ * \warning A former version of this method created a geometry with unit
+ * spacing. For unit spacing use
+ *
+ * \code
+ * // for in-plane unit spacing:
+ * thisgeometry->SetSizeInUnits(thisgeometry->GetExtentInMM(0),
+ * thisgeometry->GetExtentInMM(1));
+ * // additionally, for unit spacing in normal direction (former version
+ * // did not do this):
+ * thisgeometry->SetExtentInMM(2, 1.0);
+ * \endcode
+ */
+ virtual void InitializeStandardPlane( const BaseGeometry* geometry3D,
+ PlaneOrientation planeorientation = Axial, ScalarType zPosition = 0,
+ bool frontside=true, bool rotated=false );
+
+ /**
+ * \brief Initialize a plane with orientation \a planeorientation
+ * (default: axial) with respect to \a BaseGeometry (default: identity).
+ * Spacing also taken from \a BaseGeometry.
+ *
+ * \param top if \a true, create plane at top, otherwise at bottom
+ * (for PlaneOrientation Axial, for other plane locations respectively)
+ */
+ virtual void InitializeStandardPlane( const BaseGeometry* geometry3D, bool top,
+ PlaneOrientation planeorientation = Axial,
+ bool frontside=true, bool rotated=false );
+
+ /**
+ * \brief Initialize a plane with orientation \a planeorientation
+ * (default: axial) with respect to \a transform (default: identity)
+ * given width and height in units.
+ *
+ */
+ virtual void InitializeStandardPlane( ScalarType width, ScalarType height,
+ const AffineTransform3D* transform = NULL,
+ PlaneOrientation planeorientation = Axial,
+ ScalarType zPosition = 0, bool frontside=true, bool rotated=false );
+
+ /**
+ * \brief Initialize plane with orientation \a planeorientation
+ * (default: axial) given width, height and spacing.
+ *
+ */
+ virtual void InitializeStandardPlane( ScalarType width, ScalarType height,
+ const Vector3D & spacing, PlaneOrientation planeorientation = Axial,
+ ScalarType zPosition = 0, bool frontside = true, bool rotated = false );
+
+ /**
+ * \brief Initialize plane by width and height in pixels, right-/down-vector
+ * (itk) to describe orientation in world-space (vectors will be normalized)
+ * and spacing (default: 1.0 mm in all directions).
+ *
+ * The vectors are normalized and multiplied by the respective spacing before
+ * they are set in the matrix.
+ */
+ virtual void InitializeStandardPlane( ScalarType width, ScalarType height,
+ const Vector3D& rightVector, const Vector3D& downVector,
+ const Vector3D *spacing = NULL );
+
+ /**
+ * \brief Initialize plane by width and height in pixels,
+ * right-/down-vector (vnl) to describe orientation in world-space (vectors
+ * will be normalized) and spacing (default: 1.0 mm in all directions).
+ *
+ * The vectors are normalized and multiplied by the respective spacing
+ * before they are set in the matrix.
+ */
+ virtual void InitializeStandardPlane( ScalarType width, ScalarType height,
+ const VnlVector& rightVector, const VnlVector& downVector,
+ const Vector3D * spacing = NULL );
+
+ /**
+ * \brief Initialize plane by right-/down-vector (itk) and spacing
+ * (default: 1.0 mm in all directions).
+ *
+ * The length of the right-/-down-vector is used as width/height in units,
+ * respectively. Then, the vectors are normalized and multiplied by the
+ * respective spacing before they are set in the matrix.
+ */
+ virtual void InitializeStandardPlane( const Vector3D& rightVector,
+ const Vector3D& downVector, const Vector3D * spacing = NULL );
+
+ /**
+ * \brief Initialize plane by right-/down-vector (vnl) and spacing
+ * (default: 1.0 mm in all directions).
+ *
+ * The length of the right-/-down-vector is used as width/height in units,
+ * respectively. Then, the vectors are normalized and multiplied by the
+ * respective spacing before they are set in the matrix.
+ */
+ virtual void InitializeStandardPlane( const VnlVector& rightVector,
+ const VnlVector& downVector, const Vector3D * spacing = NULL );
+
+ /**
+ * \brief Initialize plane by origin and normal (size is 1.0 mm in
+ * all directions, direction of right-/down-vector valid but
+ * undefined).
+ *
+ */
+ virtual void InitializePlane( const Point3D& origin, const Vector3D& normal);
+
+ /**
+ * \brief Initialize plane by right-/down-vector.
+ *
+ * \warning The vectors are set into the matrix as they are,
+ * \em without normalization!
+ */
+ void SetMatrixByVectors( const VnlVector& rightVector,
+ const VnlVector& downVector, ScalarType thickness=1.0 );
+
+ /**
+ * \brief Change \a transform so that the third column of the
+ * transform-martix is perpendicular to the first two columns
+ *
+ */
+ static void EnsurePerpendicularNormal( AffineTransform3D* transform );
+
+ /**
+ * \brief Normal of the plane
+ *
+ */
+ Vector3D GetNormal() const;
+
+ /**
+ * \brief Normal of the plane as VnlVector
+ *
+ */
+ VnlVector GetNormalVnl() const;
+
+ virtual ScalarType SignedDistance( const Point3D& pt3d_mm ) const;
+
+ /**
+ * \brief Calculates, whether a point is below or above the plane. There are two different
+ *calculation methods, with or without consideration of the bounding box.
+ */
+ virtual bool IsAbove( const Point3D& pt3d_mm , bool considerBoundingBox=false) const;
+
+ /**
+ * \brief Distance of the point from the plane
+ * (bounding-box \em not considered)
+ *
+ */
+ ScalarType DistanceFromPlane( const Point3D& pt3d_mm ) const ;
+
+ /**
+ * \brief Signed distance of the point from the plane
+ * (bounding-box \em not considered)
+ *
+ * > 0 : point is in the direction of the direction vector.
+ */
+ inline ScalarType SignedDistanceFromPlane( const Point3D& pt3d_mm ) const
+ {
+ ScalarType len = GetNormalVnl().two_norm();
- /**
- * \brief Distance of the plane from another plane
- * (bounding-box \em not considered)
- *
- * Result is 0 if planes are not parallel.
- */
- ScalarType DistanceFromPlane(const PlaneGeometry* plane) const
- {
- return fabs(SignedDistanceFromPlane(plane));
- }
+ if( len == 0 )
+ return 0;
+ return (pt3d_mm-GetOrigin())*GetNormal() / len;
+ }
- /**
- * \brief Signed distance of the plane from another plane
- * (bounding-box \em not considered)
- *
- * Result is 0 if planes are not parallel.
- */
- inline ScalarType SignedDistanceFromPlane( const PlaneGeometry *plane ) const
- {
- if(IsParallel(plane))
+ /**
+ * \brief Distance of the plane from another plane
+ * (bounding-box \em not considered)
+ *
+ * Result is 0 if planes are not parallel.
+ */
+ ScalarType DistanceFromPlane(const PlaneGeometry* plane) const
{
- return SignedDistance(plane->GetOrigin());
+ return fabs(SignedDistanceFromPlane(plane));
}
- return 0;
- }
-
-
- /**
- * \brief Calculate the intersecting line of two planes
- *
- * \return \a true planes are intersecting
- * \return \a false planes do not intersect
- */
- bool IntersectionLine( const PlaneGeometry *plane, Line3D &crossline ) const;
-
-
- /**
- * \brief Calculate two points where another plane intersects the border of this plane
- *
- * \return number of intersection points (0..2). First interection point (if existing)
- * is returned in \a lineFrom, second in \a lineTo.
- */
- unsigned int IntersectWithPlane2D(const PlaneGeometry *plane,
- Point2D &lineFrom, Point2D &lineTo ) const ;
-
-
- /**
- * \brief Calculate the angle between two planes
- *
- * \return angle in radiants
- */
- double Angle( const PlaneGeometry *plane ) const;
-
-
- /**
- * \brief Calculate the angle between the plane and a line
- *
- * \return angle in radiants
- */
- double Angle( const Line3D &line ) const;
-
-
- /**
- * \brief Calculate intersection point between the plane and a line
- *
- * \param intersectionPoint intersection point
- * \return \a true if \em unique intersection exists, i.e., if line
- * is \em not on or parallel to the plane
- */
- bool IntersectionPoint( const Line3D &line,
- Point3D &intersectionPoint ) const;
-
-
- /**
- * \brief Calculate line parameter of intersection point between the
- * plane and a line
- *
- * \param t parameter of line: intersection point is
- * line.GetPoint()+t*line.GetDirection()
- * \return \a true if \em unique intersection exists, i.e., if line
- * is \em not on or parallel to the plane
- */
- bool IntersectionPointParam( const Line3D &line, double &t ) const;
-
-
- /**
- * \brief Returns whether the plane is parallel to another plane
- *
- * @return true iff the normal vectors both point to the same or exactly oposit direction
- */
- bool IsParallel( const PlaneGeometry *plane ) const;
-
-
- /**
- * \brief Returns whether the point is on the plane
- * (bounding-box \em not considered)
- */
- bool IsOnPlane( const Point3D &point ) const;
-
-
- /**
- * \brief Returns whether the line is on the plane
- * (bounding-box \em not considered)
- */
- bool IsOnPlane( const Line3D &line ) const;
-
-
- /**
- * \brief Returns whether the plane is on the plane
- * (bounding-box \em not considered)
- *
- * @return true iff the normal vector of the planes point to the same or the exactly oposit direction and
- * the distance of the planes is < eps
- *
- */
- bool IsOnPlane( const PlaneGeometry *plane ) const;
+ /**
+ * \brief Signed distance of the plane from another plane
+ * (bounding-box \em not considered)
+ *
+ * Result is 0 if planes are not parallel.
+ */
+ inline ScalarType SignedDistanceFromPlane( const PlaneGeometry *plane ) const
+ {
+ if(IsParallel(plane))
+ {
+ return SignedDistance(plane->GetOrigin());
+ }
+ return 0;
+ }
- /**
- * \brief Returns the lot from the point to the plane
- */
- Point3D ProjectPointOntoPlane( const Point3D &pt ) const;
+ /**
+ * \brief Calculate the intersecting line of two planes
+ *
+ * \return \a true planes are intersecting
+ * \return \a false planes do not intersect
+ */
+ bool IntersectionLine( const PlaneGeometry *plane, Line3D &crossline ) const;
+
+ /**
+ * \brief Calculate two points where another plane intersects the border of this plane
+ *
+ * \return number of intersection points (0..2). First interection point (if existing)
+ * is returned in \a lineFrom, second in \a lineTo.
+ */
+ unsigned int IntersectWithPlane2D(const PlaneGeometry *plane,
+ Point2D &lineFrom, Point2D &lineTo ) const ;
+
+ /**
+ * \brief Calculate the angle between two planes
+ *
+ * \return angle in radiants
+ */
+ double Angle( const PlaneGeometry *plane ) const;
+
+ /**
+ * \brief Calculate the angle between the plane and a line
+ *
+ * \return angle in radiants
+ */
+ double Angle( const Line3D &line ) const;
+
+ /**
+ * \brief Calculate intersection point between the plane and a line
+ *
+ * \param intersectionPoint intersection point
+ * \return \a true if \em unique intersection exists, i.e., if line
+ * is \em not on or parallel to the plane
+ */
+ bool IntersectionPoint( const Line3D &line,
+ Point3D &intersectionPoint ) const;
+
+ /**
+ * \brief Calculate line parameter of intersection point between the
+ * plane and a line
+ *
+ * \param t parameter of line: intersection point is
+ * line.GetPoint()+t*line.GetDirection()
+ * \return \a true if \em unique intersection exists, i.e., if line
+ * is \em not on or parallel to the plane
+ */
+ bool IntersectionPointParam( const Line3D &line, double &t ) const;
+
+ /**
+ * \brief Returns whether the plane is parallel to another plane
+ *
+ * @return true iff the normal vectors both point to the same or exactly oposit direction
+ */
+ bool IsParallel( const PlaneGeometry *plane ) const;
+
+ /**
+ * \brief Returns whether the point is on the plane
+ * (bounding-box \em not considered)
+ */
+ bool IsOnPlane( const Point3D &point ) const;
+
+ /**
+ * \brief Returns whether the line is on the plane
+ * (bounding-box \em not considered)
+ */
+ bool IsOnPlane( const Line3D &line ) const;
+
+ /**
+ * \brief Returns whether the plane is on the plane
+ * (bounding-box \em not considered)
+ *
+ * @return true iff the normal vector of the planes point to the same or the exactly oposit direction and
+ * the distance of the planes is < eps
+ *
+ */
+ bool IsOnPlane( const PlaneGeometry *plane ) const;
+
+ /**
+ * \brief Returns the lot from the point to the plane
+ */
+ Point3D ProjectPointOntoPlane( const Point3D &pt ) const;
+
+ virtual itk::LightObject::Pointer InternalClone() const;
+
+ /** Implements operation to re-orient the plane */
+ virtual void ExecuteOperation( Operation *operation );
+
+ /**
+ * \brief Project a 3D point given in mm (\a pt3d_mm) onto the 2D
+ * geometry. The result is a 2D point in mm (\a pt2d_mm).
+ *
+ * The result is a 2D point in mm (\a pt2d_mm) relative to the upper-left
+ * corner of the geometry. To convert this point into units (e.g., pixels
+ * in case of an image), use WorldToIndex.
+ * \return true projection was possible
+ * \sa Project(const mitk::Point3D &pt3d_mm, mitk::Point3D
+ * &projectedPt3d_mm)
+ */
+ virtual bool Map(const mitk::Point3D &pt3d_mm, mitk::Point2D &pt2d_mm) const;
+
+ /**
+ * \brief Converts a 2D point given in mm (\a pt2d_mm) relative to the
+ * upper-left corner of the geometry into the corresponding
+ * world-coordinate (a 3D point in mm, \a pt3d_mm).
+ *
+ * To convert a 2D point given in units (e.g., pixels in case of an
+ * image) into a 2D point given in mm (as required by this method), use
+ * IndexToWorld.
+ */
+ virtual void Map(const mitk::Point2D &pt2d_mm, mitk::Point3D &pt3d_mm) const;
+
+ /**
+ * \brief Set the width and height of this 2D-geometry in units by calling
+ * SetBounds. This does \a not change the extent in mm!
+ *
+ * For an image, this is the number of pixels in x-/y-direction.
+ * \note In contrast to calling SetBounds directly, this does \a not change
+ * the extent in mm!
+ */
+ virtual void SetSizeInUnits(mitk::ScalarType width, mitk::ScalarType height);
+
+ /**
+ * \brief Project a 3D point given in mm (\a pt3d_mm) onto the 2D
+ * geometry. The result is a 3D point in mm (\a projectedPt3d_mm).
+ *
+ * \return true projection was possible
+ */
+ virtual bool Project(const mitk::Point3D &pt3d_mm,
+ mitk::Point3D &projectedPt3d_mm) const;
+
+ /**
+ * \brief Project a 3D vector given in mm (\a vec3d_mm) onto the 2D
+ * geometry. The result is a 2D vector in mm (\a vec2d_mm).
+ *
+ * The result is a 2D vector in mm (\a vec2d_mm) relative to the
+ * upper-left
+ * corner of the geometry. To convert this point into units (e.g., pixels
+ * in case of an image), use WorldToIndex.
+ * \return true projection was possible
+ * \sa Project(const mitk::Vector3D &vec3d_mm, mitk::Vector3D
+ * &projectedVec3d_mm)
+ */
+ virtual bool Map(const mitk::Point3D & atPt3d_mm,
+ const mitk::Vector3D &vec3d_mm, mitk::Vector2D &vec2d_mm) const;
+
+ /**
+ * \brief Converts a 2D vector given in mm (\a vec2d_mm) relative to the
+ * upper-left corner of the geometry into the corresponding
+ * world-coordinate (a 3D vector in mm, \a vec3d_mm).
+ *
+ * To convert a 2D vector given in units (e.g., pixels in case of an
+ * image) into a 2D vector given in mm (as required by this method), use
+ * IndexToWorld.
+ */
+ virtual void Map(const mitk::Point2D & atPt2d_mm,
+ const mitk::Vector2D &vec2d_mm, mitk::Vector3D &vec3d_mm) const;
+
+ /**
+ * \brief Project a 3D vector given in mm (\a vec3d_mm) onto the 2D
+ * geometry. The result is a 3D vector in mm (\a projectedVec3d_mm).
+ *
+ * DEPRECATED. Use Project(vector,vector) instead
+ *
+ * \return true projection was possible
+ */
+ virtual bool Project(const mitk::Point3D & atPt3d_mm,
+ const mitk::Vector3D &vec3d_mm, mitk::Vector3D &projectedVec3d_mm) const;
+
+ /**
+ * \brief Project a 3D vector given in mm (\a vec3d_mm) onto the 2D
+ * geometry. The result is a 3D vector in mm (\a projectedVec3d_mm).
+ *
+ * \return true projection was possible
+ */
+ virtual bool Project( const mitk::Vector3D &vec3d_mm, mitk::Vector3D &projectedVec3d_mm) const;
+
+ /**
+ * \brief Distance of the point from the geometry
+ * (bounding-box \em not considered)
+ *
+ */
+ inline ScalarType Distance(const Point3D& pt3d_mm) const
+ {
+ return fabs(SignedDistance(pt3d_mm));
+ }
+ /**
+ * \brief Set the geometrical frame of reference in which this PlaneGeometry
+ * is placed.
+ *
+ * This would usually be the BaseGeometry of the underlying dataset, but
+ * setting it is optional.
+ */
+ void SetReferenceGeometry( mitk::BaseGeometry *geometry );
- virtual void SetIndexToWorldTransform( AffineTransform3D *transform);
+ /**
+ * \brief Get the geometrical frame of reference for this PlaneGeometry.
+ */
+ BaseGeometry *GetReferenceGeometry() const;
+ bool HasReferenceGeometry() const;
+ protected:
+ PlaneGeometry();
- virtual void SetBounds( const BoundingBox::BoundsArrayType &bounds );
+ PlaneGeometry(const PlaneGeometry& other);
+ virtual ~PlaneGeometry();
- virtual itk::LightObject::Pointer InternalClone() const;
+ virtual void PrintSelf( std::ostream &os, itk::Indent indent ) const;
+ /**
+ * \brief factor to convert x-coordinates from mm to units and vice versa
+ *
+ */
+ mutable mitk::ScalarType m_ScaleFactorMMPerUnitX;
- /** Implements operation to re-orient the plane */
- virtual void ExecuteOperation( Operation *operation );
+ /**
+ * \brief factor to convert y-coordinates from mm to units and vice versa
+ *
+ */
+ mutable mitk::ScalarType m_ScaleFactorMMPerUnitY;
+ mitk::BaseGeometry *m_ReferenceGeometry;
-protected:
- PlaneGeometry();
+ private:
- virtual ~PlaneGeometry();
+ virtual void PreSetBounds( const BoundingBox::BoundsArrayType &bounds );
- virtual void PrintSelf( std::ostream &os, itk::Indent indent ) const;
+ virtual void PreSetIndexToWorldTransform( AffineTransform3D *transform);
-private:
- /**
- * \brief Compares plane with another plane: \a true if IsOnPlane
- * (bounding-box \em not considered)
- */
- virtual bool operator==( const PlaneGeometry * ) const { return false; };
+ virtual void PostSetExtentInMM(int direction, ScalarType extentInMM);
- /**
- * \brief Compares plane with another plane: \a false if IsOnPlane
- * (bounding-box \em not considered)
- */
- virtual bool operator!=( const PlaneGeometry * ) const { return false; };
+ virtual void PostSetIndexToWorldTransform(mitk::AffineTransform3D* transform);
-};
+ /**
+ * \brief Compares plane with another plane: \a true if IsOnPlane
+ * (bounding-box \em not considered)
+ */
+ virtual bool operator==( const PlaneGeometry * ) const { return false; };
+ /**
+ * \brief Compares plane with another plane: \a false if IsOnPlane
+ * (bounding-box \em not considered)
+ */
+ virtual bool operator!=( const PlaneGeometry * ) const { return false; };
+ };
} // namespace mitk
-
#endif /* PLANEGEOMETRY_H_HEADER_INCLUDED_C1C68A2C */
diff --git a/Core/Code/DataManagement/mitkGeometry2DData.cpp b/Core/Code/DataManagement/mitkPlaneGeometryData.cpp
similarity index 53%
rename from Core/Code/DataManagement/mitkGeometry2DData.cpp
rename to Core/Code/DataManagement/mitkPlaneGeometryData.cpp
index 3d87886121..a100f2b4c7 100644
--- a/Core/Code/DataManagement/mitkGeometry2DData.cpp
+++ b/Core/Code/DataManagement/mitkPlaneGeometryData.cpp
@@ -1,87 +1,87 @@
/*===================================================================
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 "mitkGeometry2DData.h"
+#include "mitkPlaneGeometryData.h"
#include "mitkBaseProcess.h"
#include <mitkProportionalTimeGeometry.h>
-mitk::Geometry2DData::Geometry2DData()
+mitk::PlaneGeometryData::PlaneGeometryData()
{
}
-mitk::Geometry2DData::~Geometry2DData()
+mitk::PlaneGeometryData::~PlaneGeometryData()
{
}
-void mitk::Geometry2DData::SetGeometry(mitk::Geometry3D *geometry)
+void mitk::PlaneGeometryData::SetGeometry(mitk::BaseGeometry *geometry)
{
if(geometry==NULL)
- SetGeometry2D(NULL);
+ SetPlaneGeometry(NULL);
else
{
- Geometry2D* geometry2d = dynamic_cast<Geometry2D*>(geometry);
+ PlaneGeometry* geometry2d = dynamic_cast<PlaneGeometry*>(geometry);
if(geometry2d==NULL)
- itkExceptionMacro(<<"Trying to set a geometry which is not a Geometry2D into Geometry2DData.");
- SetGeometry2D(geometry2d);
+ itkExceptionMacro(<<"Trying to set a geometry which is not a PlaneGeometry into PlaneGeometryData.");
+ SetPlaneGeometry(geometry2d);
}
}
-void mitk::Geometry2DData::SetGeometry2D(mitk::Geometry2D *geometry2d)
+void mitk::PlaneGeometryData::SetPlaneGeometry(mitk::PlaneGeometry *geometry2d)
{
if(geometry2d != NULL)
{
ProportionalTimeGeometry::Pointer timeGeometry = ProportionalTimeGeometry::New();
timeGeometry->Initialize(geometry2d, 1);
SetTimeGeometry(timeGeometry);
Modified();
}
else
Superclass::SetGeometry(geometry2d);
}
-void mitk::Geometry2DData::UpdateOutputInformation()
+void mitk::PlaneGeometryData::UpdateOutputInformation()
{
Superclass::UpdateOutputInformation();
}
-void mitk::Geometry2DData::SetRequestedRegionToLargestPossibleRegion()
+void mitk::PlaneGeometryData::SetRequestedRegionToLargestPossibleRegion()
{
}
-bool mitk::Geometry2DData::RequestedRegionIsOutsideOfTheBufferedRegion()
+bool mitk::PlaneGeometryData::RequestedRegionIsOutsideOfTheBufferedRegion()
{
- if(GetGeometry2D()==NULL) return true;
+ if(GetPlaneGeometry()==NULL) return true;
return false;
}
-bool mitk::Geometry2DData::VerifyRequestedRegion()
+bool mitk::PlaneGeometryData::VerifyRequestedRegion()
{
- if(GetGeometry2D()==NULL) return false;
+ if(GetPlaneGeometry()==NULL) return false;
return true;
}
-void mitk::Geometry2DData::SetRequestedRegion( const itk::DataObject *)
+void mitk::PlaneGeometryData::SetRequestedRegion( const itk::DataObject *)
{
}
-void mitk::Geometry2DData::CopyInformation(const itk::DataObject *)
+void mitk::PlaneGeometryData::CopyInformation(const itk::DataObject *)
{
}
diff --git a/Core/Code/DataManagement/mitkPlaneGeometryData.h b/Core/Code/DataManagement/mitkPlaneGeometryData.h
new file mode 100644
index 0000000000..4bccdd9fe9
--- /dev/null
+++ b/Core/Code/DataManagement/mitkPlaneGeometryData.h
@@ -0,0 +1,87 @@
+/*===================================================================
+
+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 MITKGEOMETRY2DDATA_H_HEADER_INCLUDED_C19C01E2
+#define MITKGEOMETRY2DDATA_H_HEADER_INCLUDED_C19C01E2
+
+#include <MitkCoreExports.h>
+#include "mitkBaseData.h"
+#include "mitkGeometryData.h"
+#include "mitkPlaneGeometry.h"
+
+namespace mitk {
+ class PlaneGeometryData;
+ /** \deprecatedSince{2014_06} This class is deprecated. Please use PlaneGeometryData instead. */
+ DEPRECATED( typedef PlaneGeometryData Geometry2DData);
+ //##Documentation
+ //## @brief Data class containing PlaneGeometry objects
+ //## @ingroup Geometry
+ //##
+ class MITK_CORE_EXPORT PlaneGeometryData : public GeometryData
+ {
+ public:
+ mitkClassMacro(PlaneGeometryData, GeometryData);
+
+ itkFactorylessNewMacro(Self)
+ itkCloneMacro(Self)
+
+ //##Documentation
+ //## @brief Set the reference to a PlaneGeometry that is stored
+ //## by the object
+ //##
+ //## @warning Accepts only instances of PlaneGeometry or sub-classes.
+ virtual void SetGeometry(mitk::BaseGeometry *geometry);
+
+ //##Documentation
+ //## @brief Set the reference to the PlaneGeometry that is stored
+ //## by the object
+ virtual void SetPlaneGeometry(mitk::PlaneGeometry* geometry2d);
+ /**
+ * \deprecatedSince{2014_06} Please use SetPlaneGeometry
+ */
+ DEPRECATED(void SetGeometry2D(PlaneGeometry* geo){SetPlaneGeometry(geo);};)
+
+ //##Documentation
+ //## @brief Get the reference to the PlaneGeometry that is stored
+ //## by the object
+ virtual mitk::PlaneGeometry * GetPlaneGeometry() const
+ {
+ return static_cast<mitk::PlaneGeometry *>(GetGeometry());
+ };
+ /**
+ * \deprecatedSince{2014_06} Please use GetPlaneGeometry
+ */
+ DEPRECATED(const PlaneGeometry* GetGeometry2D(){return GetPlaneGeometry();};)
+
+ virtual void UpdateOutputInformation();
+
+ virtual void SetRequestedRegionToLargestPossibleRegion();
+
+ virtual bool RequestedRegionIsOutsideOfTheBufferedRegion();
+
+ virtual bool VerifyRequestedRegion();
+
+ virtual void SetRequestedRegion( const itk::DataObject *data);
+
+ virtual void CopyInformation(const itk::DataObject *data);
+
+ protected:
+ PlaneGeometryData();
+
+ virtual ~PlaneGeometryData();
+ };
+} // namespace mitk
+#endif /* MITKGEOMETRY2DDATA_H_HEADER_INCLUDED_C19C01E2 */
diff --git a/Core/Code/DataManagement/mitkPlaneOrientationProperty.h b/Core/Code/DataManagement/mitkPlaneOrientationProperty.h
index 9496f984d9..76507ca0c0 100644
--- a/Core/Code/DataManagement/mitkPlaneOrientationProperty.h
+++ b/Core/Code/DataManagement/mitkPlaneOrientationProperty.h
@@ -1,131 +1,131 @@
/*===================================================================
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 MITK_PLANE_DECORATION_PROPERTY__H
#define MITK_PLANE_DECORATION_PROPERTY__H
#include "mitkEnumerationProperty.h"
namespace mitk
{
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable: 4522)
#endif
/**
* Property which controls whether 2D line representation of a PlaneGeometry
* should have small arrows at both ends to indicate the orientation of
* the plane, and whether the arrows should be oriented in the direction of
* the plane's normal or against it.
*
* Valid values of the enumeration property are
* - PLANE_DECORATION_NONE (no arrows)
* - PLANE_DECORATION_POSITIVE_ORIENTATION (arrows pointing upwards)
* - PLANE_DECORATION_NEGATIVE_ORIENTATION (arrows pointing downwards)
*
- * See also mitk::Geometry2DDataMapper2D::DrawOrientationArrow()
+ * See also mitk::PlaneGeometryDataMapper2D::DrawOrientationArrow()
*/
class MITK_CORE_EXPORT PlaneOrientationProperty : public EnumerationProperty
{
public:
mitkClassMacro( PlaneOrientationProperty, EnumerationProperty );
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
mitkNewMacro1Param(PlaneOrientationProperty, const IdType&);
mitkNewMacro1Param(PlaneOrientationProperty, const std::string&);
enum
{
PLANE_DECORATION_NONE,
PLANE_DECORATION_POSITIVE_ORIENTATION,
PLANE_DECORATION_NEGATIVE_ORIENTATION
};
/**
* Returns the state of plane decoration.
*/
virtual int GetPlaneDecoration();
/**
* Sets the decoration type to no decoration.
*/
virtual void SetPlaneDecorationToNone();
/**
* Sets the decoration type to arrows in positive plane direction.
*/
virtual void SetPlaneDecorationToPositiveOrientation();
/**
* Sets the decoration type to arrows in negative plane direction.
*/
virtual void SetPlaneDecorationToNegativeOrientation();
using BaseProperty::operator=;
protected:
/**
* Constructor. Sets the decoration type to none.
*/
PlaneOrientationProperty( );
/**
* Constructor. Sets the decoration type to the given value. If it is not
* valid, the interpolation is set to none
*/
PlaneOrientationProperty( const IdType &value );
/**
* Constructor. Sets the decoration type to the given value. If it is not
* valid, the representation is set to none
*/
PlaneOrientationProperty( const std::string &value );
/**
* this function is overridden as protected, so that the user may not add
* additional invalid types.
*/
virtual bool AddEnum( const std::string &name, const IdType &id );
/**
* Adds the standard enumeration types with corresponding strings.
*/
virtual void AddDecorationTypes();
private:
// purposely not implemented
PlaneOrientationProperty& operator=(const PlaneOrientationProperty&);
virtual itk::LightObject::Pointer InternalClone() const;
};
#ifdef _MSC_VER
# pragma warning(pop)
#endif
} // end of namespace mitk
#endif
diff --git a/Core/Code/DataManagement/mitkPointSet.cpp b/Core/Code/DataManagement/mitkPointSet.cpp
index 1040beae0f..e4dc354337 100755
--- a/Core/Code/DataManagement/mitkPointSet.cpp
+++ b/Core/Code/DataManagement/mitkPointSet.cpp
@@ -1,880 +1,880 @@
/*===================================================================
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 "mitkPointSet.h"
#include "mitkPointOperation.h"
#include "mitkInteractionConst.h"
#include <mitkVector.h>
#include <iomanip>
mitk::PointSet::PointSet()
{
this->InitializeEmpty();
}
mitk::PointSet::PointSet(const PointSet &other)
: BaseData(other)
, m_PointSetSeries(other.GetPointSetSeriesSize())
, m_CalculateBoundingBox(true)
{
// Copy points
for (std::size_t t = 0; t < m_PointSetSeries.size(); ++t)
{
m_PointSetSeries[t] = DataType::New();
DataType::Pointer otherPts = other.GetPointSet(t);
for (PointsConstIterator i = other.Begin(t);
i != other.End(t); ++i)
{
m_PointSetSeries[t]->SetPoint(i.Index(), i.Value());
PointDataType pointData;
if (otherPts->GetPointData(i.Index(), &pointData))
{
m_PointSetSeries[t]->SetPointData(i.Index(), pointData);
}
}
}
}
mitk::PointSet::~PointSet()
{
this->ClearData();
}
void mitk::PointSet::ClearData()
{
m_PointSetSeries.clear();
Superclass::ClearData();
}
void mitk::PointSet::InitializeEmpty()
{
m_PointSetSeries.resize( 1 );
m_PointSetSeries[0] = DataType::New();
PointDataContainer::Pointer pointData = PointDataContainer::New();
m_PointSetSeries[0]->SetPointData( pointData );
m_CalculateBoundingBox = false;
Superclass::InitializeTimeGeometry(1);
m_Initialized = true;
}
bool mitk::PointSet::IsEmptyTimeStep(unsigned int t) const
{
return IsInitialized() && (GetSize(t) == 0);
}
void mitk::PointSet::Expand( unsigned int timeSteps )
{
// Check if the vector is long enough to contain the new element
// at the given position. If not, expand it with sufficient pre-initialized
// elements.
//
// NOTE: This method will never REDUCE the vector size; it should only
// be used to make sure that the vector has enough elements to include the
// specified time step.
unsigned int oldSize = m_PointSetSeries.size();
if ( timeSteps > oldSize )
{
Superclass::Expand( timeSteps );
m_PointSetSeries.resize( timeSteps );
for ( unsigned int i = oldSize; i < timeSteps; ++i )
{
m_PointSetSeries[i] = DataType::New();
PointDataContainer::Pointer pointData = PointDataContainer::New();
m_PointSetSeries[i]->SetPointData( pointData );
}
//if the size changes, then compute the bounding box
m_CalculateBoundingBox = true;
this->InvokeEvent( PointSetExtendTimeRangeEvent() );
}
}
unsigned int mitk::PointSet::GetPointSetSeriesSize() const
{
return m_PointSetSeries.size();
}
int mitk::PointSet::GetSize( unsigned int t ) const
{
if ( t < m_PointSetSeries.size() )
{
return m_PointSetSeries[t]->GetNumberOfPoints();
}
else
{
return 0;
}
}
mitk::PointSet::DataType::Pointer mitk::PointSet::GetPointSet( int t ) const
{
if ( t < (int)m_PointSetSeries.size() )
{
return m_PointSetSeries[t];
}
else
{
return NULL;
}
}
mitk::PointSet::PointsIterator mitk::PointSet::Begin( int t )
{
if (t >= 0 && t < static_cast<int>(m_PointSetSeries.size()))
{
return m_PointSetSeries[t]->GetPoints()->Begin();
}
return PointsIterator();
}
mitk::PointSet::PointsConstIterator mitk::PointSet::Begin(int t) const
{
if (t >= 0 && t < static_cast<int>(m_PointSetSeries.size()))
{
return m_PointSetSeries[t]->GetPoints()->Begin();
}
return PointsConstIterator();
}
mitk::PointSet::PointsIterator mitk::PointSet::End( int t )
{
if (t >= 0 && t < static_cast<int>(m_PointSetSeries.size()))
{
return m_PointSetSeries[t]->GetPoints()->End();
}
return PointsIterator();
}
mitk::PointSet::PointsConstIterator mitk::PointSet::End(int t) const
{
if (t >= 0 && t < static_cast<int>(m_PointSetSeries.size()))
{
return m_PointSetSeries[t]->GetPoints()->End();
}
return PointsConstIterator();
}
int mitk::PointSet::SearchPoint( Point3D point, ScalarType distance, int t ) const
{
if ( t >= (int)m_PointSetSeries.size() )
{
return -1;
}
// Out is the point which is checked to be the searched point
PointType out;
out.Fill( 0 );
PointType indexPoint;
this->GetGeometry( t )->WorldToIndex(point, indexPoint);
// Searching the first point in the Set, that is +- distance far away fro
// the given point
unsigned int i;
PointsContainer::Iterator it, end;
end = m_PointSetSeries[t]->GetPoints()->End();
int bestIndex = -1;
distance = distance * distance;
// To correct errors from converting index to world and world to index
if (distance == 0.0)
{
distance = 0.000001;
}
ScalarType bestDist = distance;
ScalarType dist, tmp;
for ( it = m_PointSetSeries[t]->GetPoints()->Begin(), i = 0;
it != end;
++it, ++i )
{
bool ok = m_PointSetSeries[t]->GetPoints()
->GetElementIfIndexExists( it->Index(), &out );
if ( !ok )
{
return -1;
}
else if ( indexPoint == out ) //if totally equal
{
return it->Index();
}
//distance calculation
tmp = out[0] - indexPoint[0]; dist = tmp * tmp;
tmp = out[1] - indexPoint[1]; dist += tmp * tmp;
tmp = out[2] - indexPoint[2]; dist += tmp * tmp;
if ( dist < bestDist )
{
bestIndex = it->Index();
bestDist = dist;
}
}
return bestIndex;
}
mitk::PointSet::PointType
mitk::PointSet::GetPoint( PointIdentifier id, int t ) const
{
PointType out;
out.Fill(0);
if ( (unsigned int) t >= m_PointSetSeries.size() )
{
return out;
}
if ( m_PointSetSeries[t]->GetPoints()->IndexExists(id) )
{
m_PointSetSeries[t]->GetPoint( id, &out );
this->GetGeometry(t)->IndexToWorld( out, out );
return out;
}
else
{
return out;
}
}
bool
mitk::PointSet
::GetPointIfExists( PointIdentifier id, PointType* point, int t ) const
{
if ( (unsigned int) t >= m_PointSetSeries.size() )
{
return false;
}
if ( m_PointSetSeries[t]->GetPoints()->GetElementIfIndexExists(id, point) )
{
this->GetGeometry( t )->IndexToWorld( *point, *point );
return true;
}
else
{
return false;
}
}
void mitk::PointSet::SetPoint( PointIdentifier id, PointType point, int t )
{
// Adapt the size of the data vector if necessary
this->Expand( t+1 );
mitk::Point3D indexPoint;
this->GetGeometry( t )->WorldToIndex( point, indexPoint );
m_PointSetSeries[t]->SetPoint( id, indexPoint );
PointDataType defaultPointData;
defaultPointData.id = id;
defaultPointData.selected = false;
defaultPointData.pointSpec = mitk::PTUNDEFINED;
m_PointSetSeries[t]->SetPointData( id, defaultPointData );
//boundingbox has to be computed anyway
m_CalculateBoundingBox = true;
this->Modified();
}
void mitk::PointSet::SetPoint( PointIdentifier id, PointType point, PointSpecificationType spec, int t )
{
// Adapt the size of the data vector if necessary
this->Expand( t+1 );
mitk::Point3D indexPoint;
this->GetGeometry( t )->WorldToIndex( point, indexPoint );
m_PointSetSeries[t]->SetPoint( id, indexPoint );
PointDataType defaultPointData;
defaultPointData.id = id;
defaultPointData.selected = false;
defaultPointData.pointSpec = spec;
m_PointSetSeries[t]->SetPointData( id, defaultPointData );
//boundingbox has to be computed anyway
m_CalculateBoundingBox = true;
this->Modified();
}
void mitk::PointSet::InsertPoint( PointIdentifier id, PointType point, int t )
{
this->InsertPoint(id, point, mitk::PTUNDEFINED, t);
}
void mitk::PointSet::InsertPoint( PointIdentifier id, PointType point, PointSpecificationType spec, int t )
{
if ( (unsigned int) t < m_PointSetSeries.size() )
{
mitk::Point3D indexPoint;
- mitk::Geometry3D* tempGeometry = this->GetGeometry( t );
+ mitk::BaseGeometry* tempGeometry = this->GetGeometry( t );
if (tempGeometry == NULL)
{
MITK_INFO<< __FILE__ << ", l." << __LINE__ << ": GetGeometry of "<< t <<" returned NULL!" << std::endl;
return;
}
tempGeometry->WorldToIndex( point, indexPoint );
m_PointSetSeries[t]->GetPoints()->InsertElement( id, indexPoint );
PointDataType defaultPointData;
defaultPointData.id = id;
defaultPointData.selected = false;
defaultPointData.pointSpec = spec;
m_PointSetSeries[t]->GetPointData()->InsertElement(id, defaultPointData);
//boundingbox has to be computed anyway
m_CalculateBoundingBox = true;
this->Modified();
}
}
bool mitk::PointSet::SwapPointPosition( PointIdentifier id, bool moveUpwards, int t )
{
if(IndexExists(id, t) )
{
PointType point = GetPoint(id,t);
if(moveUpwards)
{//up
if(IndexExists(id-1,t))
{
InsertPoint(id, GetPoint(id - 1, t), t);
InsertPoint(id-1,point,t);
this->Modified();
return true;
}
}
else
{//down
if(IndexExists(id+1,t))
{
InsertPoint(id, GetPoint(id + 1, t), t);
InsertPoint(id+1,point,t);
this->Modified();
return true;
}
}
}
return false;
}
bool mitk::PointSet::IndexExists( int position, int t ) const
{
if ( (unsigned int) t < m_PointSetSeries.size() )
{
return m_PointSetSeries[t]->GetPoints()->IndexExists( position );
}
else
{
return false;
}
}
bool mitk::PointSet::GetSelectInfo( int position, int t ) const
{
if ( this->IndexExists( position, t ) )
{
PointDataType pointData = { 0, false, PTUNDEFINED };
m_PointSetSeries[t]->GetPointData( position, &pointData );
return pointData.selected;
}
else
{
return false;
}
}
void mitk::PointSet::SetSelectInfo( int position, bool selected, int t )
{
if ( this->IndexExists( position, t ) )
{
// timeStep to ms
TimePointType timeInMS = this->GetTimeGeometry()->TimeStepToTimePoint( t );
// point
Point3D point = this->GetPoint( position, t );
std::auto_ptr<PointOperation> op;
if (selected)
{
op.reset(new mitk::PointOperation(OpSELECTPOINT, timeInMS, point, position ));
}
else
{
op.reset(new mitk::PointOperation(OpDESELECTPOINT, timeInMS, point, position ));
}
this->ExecuteOperation( op.get() );
}
}
mitk::PointSpecificationType mitk::PointSet::GetSpecificationTypeInfo( int position, int t ) const
{
if ( this->IndexExists( position, t ) )
{
PointDataType pointData = { 0, false, PTUNDEFINED };
m_PointSetSeries[t]->GetPointData( position, &pointData );
return pointData.pointSpec;
}
else
{
return PTUNDEFINED;
}
}
int mitk::PointSet::GetNumberOfSelected( int t ) const
{
if ( (unsigned int) t >= m_PointSetSeries.size() )
{
return 0;
}
int numberOfSelected = 0;
PointDataIterator it;
for ( it = m_PointSetSeries[t]->GetPointData()->Begin();
it != m_PointSetSeries[t]->GetPointData()->End();
it++ )
{
if (it->Value().selected == true)
{
++numberOfSelected;
}
}
return numberOfSelected;
}
int mitk::PointSet::SearchSelectedPoint( int t ) const
{
if ( (unsigned int) t >= m_PointSetSeries.size() )
{
return -1;
}
PointDataIterator it;
for ( it = m_PointSetSeries[t]->GetPointData()->Begin();
it != m_PointSetSeries[t]->GetPointData()->End();
it++ )
{
if ( it->Value().selected == true )
{
return it->Index();
}
}
return -1;
}
void mitk::PointSet::ExecuteOperation( Operation* operation )
{
int timeStep = -1;
mitkCheckOperationTypeMacro(PointOperation, operation, pointOp);
if ( pointOp )
{
timeStep = this->GetTimeGeometry()->TimePointToTimeStep( pointOp->GetTimeInMS() );
}
if ( timeStep < 0 )
{
MITK_ERROR << "Time step (" << timeStep << ") outside of PointSet time bounds" << std::endl;
return;
}
switch (operation->GetOperationType())
{
case OpNOTHING:
break;
case OpINSERT://inserts the point at the given position and selects it.
{
int position = pointOp->GetIndex();
PointType pt;
pt.CastFrom(pointOp->GetPoint());
//transfer from world to index coordinates
- mitk::Geometry3D* geometry = this->GetGeometry( timeStep );
+ mitk::BaseGeometry* geometry = this->GetGeometry( timeStep );
if (geometry == NULL)
{
MITK_INFO<<"GetGeometry returned NULL!\n";
return;
}
geometry->WorldToIndex(pt, pt);
m_PointSetSeries[timeStep]->GetPoints()->InsertElement(position, pt);
PointDataType pointData =
{
static_cast<unsigned int>(pointOp->GetIndex()),
pointOp->GetSelected(),
pointOp->GetPointType()
};
m_PointSetSeries[timeStep]->GetPointData()
->InsertElement(position, pointData);
this->Modified();
//boundingbox has to be computed
m_CalculateBoundingBox = true;
this->InvokeEvent( PointSetAddEvent() );
this->OnPointSetChange();
}
break;
case OpMOVE://moves the point given by index
{
PointType pt;
pt.CastFrom(pointOp->GetPoint());
//transfer from world to index coordinates
this->GetGeometry( timeStep )->WorldToIndex(pt, pt);
// Copy new point into container
m_PointSetSeries[timeStep]->SetPoint(pointOp->GetIndex(), pt);
// Insert a default point data object to keep the containers in sync
// (if no point data object exists yet)
PointDataType pointData;
if ( !m_PointSetSeries[timeStep]->GetPointData( pointOp->GetIndex(), &pointData ) )
{
m_PointSetSeries[timeStep]->SetPointData( pointOp->GetIndex(), pointData );
}
this->OnPointSetChange();
this->Modified();
//boundingbox has to be computed anyway
m_CalculateBoundingBox = true;
this->InvokeEvent( PointSetMoveEvent() );
}
break;
case OpREMOVE://removes the point at given by position
{
m_PointSetSeries[timeStep]->GetPoints()->DeleteIndex((unsigned)pointOp->GetIndex());
m_PointSetSeries[timeStep]->GetPointData()->DeleteIndex((unsigned)pointOp->GetIndex());
this->OnPointSetChange();
this->Modified();
//boundingbox has to be computed anyway
m_CalculateBoundingBox = true;
this->InvokeEvent( PointSetRemoveEvent() );
}
break;
case OpSELECTPOINT://select the given point
{
PointDataType pointData = {0, false, PTUNDEFINED};
m_PointSetSeries[timeStep]->GetPointData(pointOp->GetIndex(), &pointData);
pointData.selected = true;
m_PointSetSeries[timeStep]->SetPointData(pointOp->GetIndex(), pointData);
this->Modified();
}
break;
case OpDESELECTPOINT://unselect the given point
{
PointDataType pointData = {0, false, PTUNDEFINED};
m_PointSetSeries[timeStep]->GetPointData(pointOp->GetIndex(), &pointData);
pointData.selected = false;
m_PointSetSeries[timeStep]->SetPointData(pointOp->GetIndex(), pointData);
this->Modified();
}
break;
case OpSETPOINTTYPE:
{
PointDataType pointData = {0, false, PTUNDEFINED};
m_PointSetSeries[timeStep]->GetPointData(pointOp->GetIndex(), &pointData);
pointData.pointSpec = pointOp->GetPointType();
m_PointSetSeries[timeStep]->SetPointData(pointOp->GetIndex(), pointData);
this->Modified();
}
break;
case OpMOVEPOINTUP: // swap content of point with ID pointOp->GetIndex() with the point preceding it in the container // move point position within the pointset
{
PointIdentifier currentID = pointOp->GetIndex();
/* search for point with this id and point that precedes this one in the data container */
PointsContainer::STLContainerType points = m_PointSetSeries[timeStep]->GetPoints()->CastToSTLContainer();
PointsContainer::STLContainerType::iterator it = points.find(currentID);
if (it == points.end()) // ID not found
break;
if (it == points.begin()) // we are at the first element, there is no previous element
break;
/* get and cache current point & pointdata and previous point & pointdata */
--it;
PointIdentifier prevID = it->first;
if (this->SwapPointContents(prevID, currentID, timeStep) == true)
this->Modified();
}
break;
case OpMOVEPOINTDOWN: // move point position within the pointset
{
PointIdentifier currentID = pointOp->GetIndex();
/* search for point with this id and point that succeeds this one in the data container */
PointsContainer::STLContainerType points = m_PointSetSeries[timeStep]->GetPoints()->CastToSTLContainer();
PointsContainer::STLContainerType::iterator it = points.find(currentID);
if (it == points.end()) // ID not found
break;
++it;
if (it == points.end()) // ID is already the last element, there is no succeeding element
break;
/* get and cache current point & pointdata and previous point & pointdata */
PointIdentifier nextID = it->first;
if (this->SwapPointContents(nextID, currentID, timeStep) == true)
this->Modified();
}
break;
default:
itkWarningMacro("mitkPointSet could not understrand the operation. Please check!");
break;
}
//to tell the mappers, that the data is modified and has to be updated
//only call modified if anything is done, so call in cases
//this->Modified();
mitk::OperationEndEvent endevent(operation);
((const itk::Object*)this)->InvokeEvent(endevent);
//*todo has to be done here, cause of update-pipeline not working yet
// As discussed lately, don't mess with the rendering from inside data structures
//mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void mitk::PointSet::UpdateOutputInformation()
{
if ( this->GetSource( ) )
{
this->GetSource( )->UpdateOutputInformation( );
}
//
// first make sure, that the associated time sliced geometry has
// the same number of geometry 3d's as PointSets are present
//
TimeGeometry* timeGeometry = GetTimeGeometry();
if ( timeGeometry->CountTimeSteps() != m_PointSetSeries.size() )
{
itkExceptionMacro(<<"timeGeometry->CountTimeSteps() != m_PointSetSeries.size() -- use Initialize(timeSteps) with correct number of timeSteps!");
}
// This is needed to detect zero objects
mitk::ScalarType nullpoint[]={0,0,0,0,0,0};
BoundingBox::BoundsArrayType itkBoundsNull(nullpoint);
//
// Iterate over the PointSets and update the Geometry
// information of each of the items.
//
if (m_CalculateBoundingBox)
{
for ( unsigned int i = 0 ; i < m_PointSetSeries.size() ; ++i )
{
const DataType::BoundingBoxType *bb = m_PointSetSeries[i]->GetBoundingBox();
BoundingBox::BoundsArrayType itkBounds = bb->GetBounds();
if ( m_PointSetSeries[i].IsNull() || (m_PointSetSeries[i]->GetNumberOfPoints() == 0)
|| (itkBounds == itkBoundsNull) )
{
itkBounds = itkBoundsNull;
continue;
}
// Ensure minimal bounds of 1.0 in each dimension
for ( unsigned int j = 0; j < 3; ++j )
{
if ( itkBounds[j*2+1] - itkBounds[j*2] < 1.0 )
{
BoundingBox::CoordRepType center =
(itkBounds[j*2] + itkBounds[j*2+1]) / 2.0;
itkBounds[j*2] = center - 0.5;
itkBounds[j*2+1] = center + 0.5;
}
}
this->GetGeometry(i)->SetBounds(itkBounds);
}
m_CalculateBoundingBox = false;
}
this->GetTimeGeometry()->Update();
}
void mitk::PointSet::SetRequestedRegionToLargestPossibleRegion()
{
}
bool mitk::PointSet::RequestedRegionIsOutsideOfTheBufferedRegion()
{
return false;
}
bool mitk::PointSet::VerifyRequestedRegion()
{
return true;
}
void mitk::PointSet::SetRequestedRegion(const DataObject * )
{
}
void mitk::PointSet::PrintSelf( std::ostream& os, itk::Indent indent ) const
{
Superclass::PrintSelf(os, indent);
os << indent << "Number timesteps: " << m_PointSetSeries.size() << "\n";
unsigned int i = 0;
for (PointSetSeries::const_iterator it = m_PointSetSeries.begin(); it != m_PointSetSeries.end(); ++it)
{
os << indent << "Timestep " << i++ << ": \n";
MeshType::Pointer ps = *it;
itk::Indent nextIndent = indent.GetNextIndent();
ps->Print(os, nextIndent);
MeshType::PointsContainer* points = ps->GetPoints();
MeshType::PointDataContainer* datas = ps->GetPointData();
MeshType::PointDataContainer::Iterator dataIterator = datas->Begin();
for (MeshType::PointsContainer::Iterator pointIterator = points->Begin();
pointIterator != points->End();
++pointIterator, ++dataIterator)
{
os << nextIndent << "Point " << pointIterator->Index() << ": [";
os << pointIterator->Value().GetElement(0);
for (unsigned int i = 1; i < PointType::GetPointDimension(); ++i)
{
os << ", " << pointIterator->Value().GetElement(i);
}
os << "]";
os << ", selected: " << dataIterator->Value().selected << ", point spec: " << dataIterator->Value().pointSpec << "\n";
}
}
}
bool mitk::PointSet::SwapPointContents(PointIdentifier id1, PointIdentifier id2, int timeStep)
{
/* search and cache contents */
PointType p1;
if (m_PointSetSeries[timeStep]->GetPoint(id1, &p1) == false)
return false;
PointDataType data1;
if (m_PointSetSeries[timeStep]->GetPointData(id1, &data1) == false)
return false;
PointType p2;
if (m_PointSetSeries[timeStep]->GetPoint(id2, &p2) == false)
return false;
PointDataType data2;
if (m_PointSetSeries[timeStep]->GetPointData(id2, &data2) == false)
return false;
/* now swap contents */
m_PointSetSeries[timeStep]->SetPoint(id1, p2);
m_PointSetSeries[timeStep]->SetPointData(id1, data2);
m_PointSetSeries[timeStep]->SetPoint(id2, p1);
m_PointSetSeries[timeStep]->SetPointData(id2, data1);
return true;
}
bool mitk::PointSet::PointDataType::operator ==(const mitk::PointSet::PointDataType &other) const
{
return id == other.id && selected == other.selected && pointSpec == other.pointSpec;
}
bool mitk::Equal( const mitk::PointSet* leftHandSide, const mitk::PointSet* rightHandSide, mitk::ScalarType eps, bool verbose )
{
if((leftHandSide == NULL) || (rightHandSide == NULL))
{
MITK_ERROR << "mitk::Equal( const mitk::PointSet* leftHandSide, const mitk::PointSet* rightHandSide, mitk::ScalarType eps, bool verbose ) does not work with NULL pointer input.";
return false;
}
return Equal( *leftHandSide, *rightHandSide, eps, verbose);
}
bool mitk::Equal( const mitk::PointSet& leftHandSide, const mitk::PointSet& rightHandSide, mitk::ScalarType eps, bool verbose )
{
bool result = true;
if( !mitk::Equal( *leftHandSide.GetGeometry(), *rightHandSide.GetGeometry(), eps, verbose) )
{
if(verbose)
MITK_INFO << "[( PointSet )] Geometries differ.";
result = false;
}
if ( leftHandSide.GetSize() != rightHandSide.GetSize())
{
if(verbose)
MITK_INFO << "[( PointSet )] Number of points differ.";
result = false;
}
else
{
//if the size is equal, we compare the point values
mitk::Point3D pointLeftHandSide;
mitk::Point3D pointRightHandSide;
int numberOfIncorrectPoints = 0;
//Iterate over both pointsets in order to compare all points pair-wise
mitk::PointSet::PointsConstIterator end = leftHandSide.End();
for( mitk::PointSet::PointsConstIterator pointSetIteratorLeft = leftHandSide.Begin(), pointSetIteratorRight = rightHandSide.Begin();
pointSetIteratorLeft != end; ++pointSetIteratorLeft, ++pointSetIteratorRight) //iterate simultaneously over both sets
{
pointLeftHandSide = pointSetIteratorLeft.Value();
pointRightHandSide = pointSetIteratorRight.Value();
if( !mitk::Equal( pointLeftHandSide, pointRightHandSide, eps, verbose ) )
{
if(verbose)
MITK_INFO << "[( PointSet )] Point values are different.";
result = false;
numberOfIncorrectPoints++;
}
}
if((numberOfIncorrectPoints > 0) && verbose)
{
MITK_INFO << numberOfIncorrectPoints <<" of a total of " << leftHandSide.GetSize() << " points are different.";
}
}
return result;
}
diff --git a/Core/Code/DataManagement/mitkProportionalTimeGeometry.cpp b/Core/Code/DataManagement/mitkProportionalTimeGeometry.cpp
index acb3327944..93ca960056 100644
--- a/Core/Code/DataManagement/mitkProportionalTimeGeometry.cpp
+++ b/Core/Code/DataManagement/mitkProportionalTimeGeometry.cpp
@@ -1,237 +1,265 @@
/*===================================================================
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 <mitkProportionalTimeGeometry.h>
#include <limits>
mitk::ProportionalTimeGeometry::ProportionalTimeGeometry() :
m_FirstTimePoint(0.0),
m_StepDuration(1.0)
{
}
mitk::ProportionalTimeGeometry::~ProportionalTimeGeometry()
{
}
void mitk::ProportionalTimeGeometry::Initialize()
{
m_FirstTimePoint = 0.0;
m_StepDuration = 1.0;
m_GeometryVector.resize(1);
}
mitk::TimeStepType mitk::ProportionalTimeGeometry::CountTimeSteps () const
{
return static_cast<TimeStepType>(m_GeometryVector.size() );
}
mitk::TimePointType mitk::ProportionalTimeGeometry::GetMinimumTimePoint () const
{
return m_FirstTimePoint;
}
mitk::TimePointType mitk::ProportionalTimeGeometry::GetMaximumTimePoint () const
{
TimePointType timePoint = m_FirstTimePoint + m_StepDuration * CountTimeSteps();
if (timePoint >std::numeric_limits<TimePointType>().max())
timePoint = std::numeric_limits<TimePointType>().max();
return timePoint;
}
mitk::TimeBounds mitk::ProportionalTimeGeometry::GetTimeBounds () const
{
TimeBounds bounds;
bounds[0] = this->GetMinimumTimePoint();
bounds[1] = this->GetMaximumTimePoint();
return bounds;
}
+mitk::TimePointType mitk::ProportionalTimeGeometry::GetMinimumTimePoint(TimeStepType step) const
+{
+ TimePointType timePoint;
+ if (step == 0)
+ {
+ timePoint = m_FirstTimePoint;
+ }
+ else
+ {
+ timePoint = m_FirstTimePoint + m_StepDuration * step;
+ }
+ if (timePoint >std::numeric_limits<TimePointType>().max())
+ timePoint = std::numeric_limits<TimePointType>().max();
+ return timePoint;
+}
+
+mitk::TimePointType mitk::ProportionalTimeGeometry::GetMaximumTimePoint(TimeStepType step) const
+{
+ TimePointType timePoint = m_FirstTimePoint + m_StepDuration * (step + 1);
+ if (timePoint >std::numeric_limits<TimePointType>().max())
+ timePoint = std::numeric_limits<TimePointType>().max();
+ return timePoint;
+}
+
+
+mitk::TimeBounds mitk::ProportionalTimeGeometry::GetTimeBounds(TimeStepType step) const
+{
+ TimeBounds bounds;
+ bounds[0] = this->GetMinimumTimePoint(step);
+ bounds[1] = this->GetMaximumTimePoint(step);
+ return bounds;
+}
+
bool mitk::ProportionalTimeGeometry::IsValidTimePoint (TimePointType timePoint) const
{
return this->GetMinimumTimePoint() <= timePoint && timePoint < this->GetMaximumTimePoint();
}
bool mitk::ProportionalTimeGeometry::IsValidTimeStep (TimeStepType timeStep) const
{
return timeStep < this->CountTimeSteps();
}
mitk::TimePointType mitk::ProportionalTimeGeometry::TimeStepToTimePoint( TimeStepType timeStep) const
{
if (m_FirstTimePoint <= itk::NumericTraits<TimePointType>::NonpositiveMin() ||
m_FirstTimePoint >= itk::NumericTraits<TimePointType>::max() ||
m_StepDuration <= itk::NumericTraits<TimePointType>::min() ||
m_StepDuration >= itk::NumericTraits<TimePointType>::max())
{
return static_cast<TimePointType>(timeStep);
}
return m_FirstTimePoint + timeStep * m_StepDuration;
}
mitk::TimeStepType mitk::ProportionalTimeGeometry::TimePointToTimeStep( TimePointType timePoint) const
{
if (m_FirstTimePoint <= timePoint)
return static_cast<TimeStepType>((timePoint -m_FirstTimePoint) / m_StepDuration);
else
return 0;
}
-mitk::Geometry3D::Pointer mitk::ProportionalTimeGeometry::GetGeometryForTimeStep( TimeStepType timeStep) const
+mitk::BaseGeometry::Pointer mitk::ProportionalTimeGeometry::GetGeometryForTimeStep( TimeStepType timeStep) const
{
if (IsValidTimeStep(timeStep))
{
- return dynamic_cast<Geometry3D*>(m_GeometryVector[timeStep].GetPointer());
+ return dynamic_cast<BaseGeometry*>(m_GeometryVector[timeStep].GetPointer());
}
else
{
return 0;
}
}
-mitk::Geometry3D::Pointer mitk::ProportionalTimeGeometry::GetGeometryForTimePoint(TimePointType timePoint) const
+mitk::BaseGeometry::Pointer mitk::ProportionalTimeGeometry::GetGeometryForTimePoint(TimePointType timePoint) const
{
if (this->IsValidTimePoint(timePoint))
{
TimeStepType timeStep = this->TimePointToTimeStep(timePoint);
return this->GetGeometryForTimeStep(timeStep);
}
else
{
return 0;
}
}
-mitk::Geometry3D::Pointer mitk::ProportionalTimeGeometry::GetGeometryCloneForTimeStep( TimeStepType timeStep) const
+mitk::BaseGeometry::Pointer mitk::ProportionalTimeGeometry::GetGeometryCloneForTimeStep( TimeStepType timeStep) const
{
if (timeStep > m_GeometryVector.size())
return 0;
- return m_GeometryVector[timeStep]->Clone();
+ itk::LightObject::Pointer lopointer = m_GeometryVector[timeStep]->Clone();
+ return dynamic_cast<BaseGeometry*>(lopointer.GetPointer());
}
bool mitk::ProportionalTimeGeometry::IsValid() const
{
bool isValid = true;
isValid &= m_GeometryVector.size() > 0;
isValid &= m_StepDuration > 0;
return isValid;
}
void mitk::ProportionalTimeGeometry::ClearAllGeometries()
{
m_GeometryVector.clear();
}
void mitk::ProportionalTimeGeometry::ReserveSpaceForGeometries(TimeStepType numberOfGeometries)
{
m_GeometryVector.reserve(numberOfGeometries);
}
void mitk::ProportionalTimeGeometry::Expand(mitk::TimeStepType size)
{
m_GeometryVector.reserve(size);
while (m_GeometryVector.size() < size)
{
- m_GeometryVector.push_back(Geometry3D::New());
+ Geometry3D::Pointer geo3D = Geometry3D::New();
+ m_GeometryVector.push_back(dynamic_cast<BaseGeometry*>(geo3D.GetPointer()));
}
}
-void mitk::ProportionalTimeGeometry::SetTimeStepGeometry(Geometry3D* geometry, TimeStepType timeStep)
+void mitk::ProportionalTimeGeometry::SetTimeStepGeometry(BaseGeometry* geometry, TimeStepType timeStep)
{
assert(timeStep<=m_GeometryVector.size());
if (timeStep == m_GeometryVector.size())
m_GeometryVector.push_back(geometry);
m_GeometryVector[timeStep] = geometry;
}
itk::LightObject::Pointer mitk::ProportionalTimeGeometry::InternalClone() const
{
itk::LightObject::Pointer parent = Superclass::InternalClone();
ProportionalTimeGeometry::Pointer newTimeGeometry =
dynamic_cast<ProportionalTimeGeometry * > (parent.GetPointer());
newTimeGeometry->m_FirstTimePoint = this->m_FirstTimePoint;
newTimeGeometry->m_StepDuration = this->m_StepDuration;
newTimeGeometry->m_GeometryVector.clear();
newTimeGeometry->Expand(this->CountTimeSteps());
for (TimeStepType i =0; i < CountTimeSteps(); ++i)
{
- Geometry3D::Pointer tempGeometry = GetGeometryForTimeStep(i)->Clone();
+ itk::LightObject::Pointer lopointer=GetGeometryForTimeStep(i)->Clone();
+ BaseGeometry::Pointer tempGeometry = dynamic_cast<BaseGeometry*>(lopointer.GetPointer());
newTimeGeometry->SetTimeStepGeometry(tempGeometry.GetPointer(),i);
}
return parent;
}
-void mitk::ProportionalTimeGeometry::Initialize (Geometry3D* geometry, TimeStepType timeSteps)
+void mitk::ProportionalTimeGeometry::Initialize (BaseGeometry* geometry, TimeStepType timeSteps)
{
timeSteps = (timeSteps > 0) ? timeSteps : 1;
- m_FirstTimePoint = geometry->GetTimeBounds()[0];
- m_StepDuration = geometry->GetTimeBounds()[1] - geometry->GetTimeBounds()[0];
+ m_FirstTimePoint = 0.0;
+ m_StepDuration = 1.0;
+ if (timeSteps < 2)
+ {
+ m_FirstTimePoint = -std::numeric_limits<double>::max();
+ m_StepDuration = std::numeric_limits<mitk::TimePointType>().infinity();
+ }
+
this->ReserveSpaceForGeometries(timeSteps);
try{
for (TimeStepType currentStep = 0; currentStep < timeSteps; ++currentStep)
{
- mitk::TimeBounds timeBounds;
- if (timeSteps > 1)
- {
- timeBounds[0] = m_FirstTimePoint + currentStep * m_StepDuration;
- timeBounds[1] = m_FirstTimePoint + (currentStep+1) * m_StepDuration;
- }
- else
- {
- timeBounds = geometry->GetTimeBounds();
- }
-
- Geometry3D::Pointer clonedGeometry = geometry->Clone();
+ itk::LightObject::Pointer lopointer=geometry->Clone();
+ BaseGeometry::Pointer clonedGeometry = dynamic_cast<BaseGeometry*>(lopointer.GetPointer());
this->SetTimeStepGeometry(clonedGeometry.GetPointer(), currentStep);
- GetGeometryForTimeStep(currentStep)->SetTimeBounds(timeBounds);
}
}
catch (...)
{
MITK_INFO << "Cloning of geometry produced an error!";
}
Update();
}
void mitk::ProportionalTimeGeometry::Initialize (TimeStepType timeSteps)
{
- mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New();
+ mitk::Geometry3D::Pointer geo3D = Geometry3D::New();
+ mitk::BaseGeometry::Pointer geometry = dynamic_cast<BaseGeometry*>(geo3D.GetPointer());
geometry->Initialize();
- if ( timeSteps > 1 )
- {
- mitk::ScalarType timeBounds[] = {0.0, 1.0};
- geometry->SetTimeBounds( timeBounds );
- }
this->Initialize(geometry.GetPointer(), timeSteps);
}
void mitk::ProportionalTimeGeometry::PrintSelf(std::ostream& os, itk::Indent indent) const
{
os << indent << " TimeSteps: " << this->CountTimeSteps() << std::endl;
os << indent << " FirstTimePoint: " << this->GetFirstTimePoint() << std::endl;
os << indent << " StepDuration: " << this->GetStepDuration() << " ms" << std::endl;
+ os << indent << " Time Bounds: " << this->GetTimeBounds()[0] << " - " << this->GetTimeBounds()[1] << std::endl;
os << std::endl;
os << indent << " GetGeometryForTimeStep(0): ";
if(GetGeometryForTimeStep(0).IsNull())
os << "NULL" << std::endl;
else
GetGeometryForTimeStep(0)->Print(os, indent);
}
diff --git a/Core/Code/DataManagement/mitkProportionalTimeGeometry.h b/Core/Code/DataManagement/mitkProportionalTimeGeometry.h
index 1a4c77d8bd..1fb7478c55 100644
--- a/Core/Code/DataManagement/mitkProportionalTimeGeometry.h
+++ b/Core/Code/DataManagement/mitkProportionalTimeGeometry.h
@@ -1,207 +1,225 @@
/*===================================================================
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 ProportionalTimeGeometry_h
#define ProportionalTimeGeometry_h
//MITK
#include <mitkTimeGeometry.h>
+#include <mitkGeometry3D.h>
#include <mitkCommon.h>
#include <MitkCoreExports.h>
namespace mitk {
-
/**
* \brief Organizes geometries over proportional time steps
*
* For this TimeGeometry implementation it is assumed that
* the durations of the time steps are equidistant, e.g.
* the durations of the time steps in one ProportionalTimeGeometry
* are the same. The geometries of the time steps are independent,
* and not linked to each other. Since the timeBounds of the
* geometries are different for each time step it is not possible
* to set the same geometry to different time steps. Instead
* copies should be used.
*
* \addtogroup geometry
*/
class MITK_CORE_EXPORT ProportionalTimeGeometry : public TimeGeometry
{
public:
mitkClassMacro(ProportionalTimeGeometry, TimeGeometry);
ProportionalTimeGeometry();
typedef ProportionalTimeGeometry self;
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/**
* \brief Returns the number of time steps.
*
* Returns the number of time steps for which
* geometries are saved. The number of time steps
* is also the upper bound of the time steps. The
* minimum time steps is always 0.
*/
virtual TimeStepType CountTimeSteps() const;
/**
* \brief Returns the first time point for which the object is valid.
*
* Returns the first valid time point for this geometry. If only one
* time steps available it usually goes from -max to +max. The time point
* is given in ms.
*/
virtual TimePointType GetMinimumTimePoint () const;
/**
* \brief Returns the last time point for which the object is valid
*
* Gives the last time point for which a valid geometrie is saved in
* this time geometry. The time point is given in ms.
*/
virtual TimePointType GetMaximumTimePoint () const;
+ /**
+ * \brief Returns the first time point for which the object is valid.
+ *
+ * Returns the first valid time point for the given TimeStep. The time point
+ * is given in ms.
+ */
+ virtual TimePointType GetMinimumTimePoint(TimeStepType step) const;
+ /**
+ * \brief Returns the last time point for which the object is valid
+ *
+ * Gives the last time point for the Geometry specified by the given TimeStep. The time point is given in ms.
+ */
+ virtual TimePointType GetMaximumTimePoint(TimeStepType step) const;
+
/**
* \brief Get the time bounds (in ms)
*/
virtual TimeBounds GetTimeBounds( ) const;
+
+ /**
+ * \brief Get the time bounds for the given TimeStep (in ms)
+ */
+ virtual TimeBounds GetTimeBounds(TimeStepType step) const;
+
/**
* \brief Tests if a given time point is covered by this object
*
* Returns true if a geometry can be returned for the given time
* point and falls if not. The time point must be given in ms.
*/
virtual bool IsValidTimePoint (TimePointType timePoint) const;
/**
* \brief Test for the given time step if a geometry is availible
*
* Returns true if a geometry is defined for the given time step.
* Otherwise false is returned.
* The time step is defined as positiv number.
*/
virtual bool IsValidTimeStep (TimeStepType timeStep) const;
/**
* \brief Converts a time step to a time point
*
* Converts a time step to a time point in a way that
* the new time point indicates the same geometry as the time step.
* If the original time steps does not point to a valid geometry,
* a time point is calculated that also does not point to a valid
* geometry, but no exception is raised.
*/
virtual TimePointType TimeStepToTimePoint (TimeStepType timeStep) const;
/**
* \brief Converts a time point to the corresponding time step
*
* Converts a time point to a time step in a way that
* the new time step indicates the same geometry as the time point.
* If a negativ invalid time point is given always time step 0 is
* returned. If an positiv invalid time step is given an invalid
* time step will be returned.
*/
virtual TimeStepType TimePointToTimeStep (TimePointType timePoint) const;
/**
* \brief Returns the geometry which corresponds to the given time step
*
* Returns a clone of the geometry which defines the given time step. If
* the given time step is invalid an null-pointer is returned.
*/
- virtual Geometry3D::Pointer GetGeometryCloneForTimeStep( TimeStepType timeStep) const;
+ virtual BaseGeometry::Pointer GetGeometryCloneForTimeStep( TimeStepType timeStep) const;
/**
* \brief Returns the geometry which corresponds to the given time point
*
* Returns the geometry which defines the given time point. If
* the given time point is invalid an null-pointer is returned.
*
* If the returned geometry is changed this will affect the saved
* geometry.
*/
- virtual Geometry3D::Pointer GetGeometryForTimePoint ( TimePointType timePoint) const;
+ virtual BaseGeometry::Pointer GetGeometryForTimePoint ( TimePointType timePoint) const;
/**
* \brief Returns the geometry which corresponds to the given time step
*
* Returns the geometry which defines the given time step. If
* the given time step is invalid an null-pointer is returned.
*
* If the returned geometry is changed this will affect the saved
* geometry.
*/
- virtual Geometry3D::Pointer GetGeometryForTimeStep ( TimeStepType timeStep) const;
+ virtual BaseGeometry::Pointer GetGeometryForTimeStep ( TimeStepType timeStep) const;
/**
* \brief Tests if all necessary informations are set and the object is valid
*/
virtual bool IsValid () const;
/**
* \brief Initilizes a new object with one time steps which contains an empty geometry.
*/
virtual void Initialize();
/**
* \brief Expands the time geometry to the given number of time steps.
*
* Initializes the new time steps with empty geometries.
* Shrinking is not supported.
*/
virtual void Expand(TimeStepType size);
/**
* \brief Sets the geometry for the given time step
*
* This method does not afflict other time steps, since the geometry for
* each time step is saved individually.
*/
- virtual void SetTimeStepGeometry(Geometry3D* geometry, TimeStepType timeStep);
+ virtual void SetTimeStepGeometry(BaseGeometry* geometry, TimeStepType timeStep);
/**
* \brief Makes a deep copy of the current object
*/
virtual itk::LightObject::Pointer InternalClone () const;
itkGetConstMacro(FirstTimePoint, TimePointType);
itkSetMacro(FirstTimePoint, TimePointType);
itkGetConstMacro(StepDuration, TimePointType);
itkSetMacro(StepDuration, TimePointType);
// void SetGeometryForTimeStep(TimeStepType timeStep, BaseGeometry& geometry);
void ClearAllGeometries ();
// void AddGeometry(BaseGeometry geometry);
void ReserveSpaceForGeometries (TimeStepType numberOfGeometries);
/**
* \brief Initializes the TimeGeometry with equally time Step geometries
*
* Saves a copy for each time step.
*/
- void Initialize (Geometry3D* geometry, TimeStepType timeSteps);
+ void Initialize (BaseGeometry* geometry, TimeStepType timeSteps);
/**
- * \brief Initialize the TimeGeometry with empty Geometry3D
+ * \brief Initialize the TimeGeometry with empty BaseGeometry
*/
void Initialize (TimeStepType timeSteps);
virtual void PrintSelf(std::ostream& os, itk::Indent indent) const;
protected:
virtual ~ProportionalTimeGeometry();
- std::vector<Geometry3D::Pointer> m_GeometryVector;
+ std::vector<BaseGeometry::Pointer> m_GeometryVector;
TimePointType m_FirstTimePoint;
TimePointType m_StepDuration;
-
}; // end class ProportialTimeGeometry
-
} // end namespace MITK
#endif // ProportionalTimeGeometry_h
diff --git a/Core/Code/DataManagement/mitkSlicedData.cpp b/Core/Code/DataManagement/mitkSlicedData.cpp
index 73548a368a..2f9121153c 100644
--- a/Core/Code/DataManagement/mitkSlicedData.cpp
+++ b/Core/Code/DataManagement/mitkSlicedData.cpp
@@ -1,359 +1,359 @@
/*===================================================================
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 "mitkSlicedData.h"
#include "mitkBaseProcess.h"
#include <mitkProportionalTimeGeometry.h>
mitk::SlicedData::SlicedData() : m_UseLargestPossibleRegion(false)
{
unsigned int i;
for(i=0;i<4;++i)
{
m_LargestPossibleRegion.SetIndex(i, 0);
m_LargestPossibleRegion.SetSize (i, 1);
}
}
mitk::SlicedData::SlicedData( const SlicedData &other ): BaseData(other),
m_LargestPossibleRegion(other.m_LargestPossibleRegion),
m_RequestedRegion(other.m_RequestedRegion),
m_BufferedRegion(other.m_BufferedRegion),
m_UseLargestPossibleRegion(other.m_UseLargestPossibleRegion)
{
}
mitk::SlicedData::~SlicedData()
{
}
void mitk::SlicedData::UpdateOutputInformation()
{
Superclass::UpdateOutputInformation();
if (this->GetSource().IsNull())
// If we don't have a source, then let's make our Image
// span our buffer
{
m_UseLargestPossibleRegion = true;
}
// Now we should know what our largest possible region is. If our
// requested region was not set yet, (or has been set to something
// invalid - with no data in it ) then set it to the largest possible
// region.
if ( ! m_RequestedRegionInitialized)
{
this->SetRequestedRegionToLargestPossibleRegion();
m_RequestedRegionInitialized = true;
}
m_LastRequestedRegionWasOutsideOfTheBufferedRegion = 0;
}
void mitk::SlicedData::PrepareForNewData()
{
if ( GetUpdateMTime() < GetPipelineMTime() || GetDataReleased() )
{
ReleaseData();
}
}
void mitk::SlicedData::SetRequestedRegionToLargestPossibleRegion()
{
m_UseLargestPossibleRegion = true;
if(GetGeometry()==NULL)
return;
unsigned int i;
const RegionType::IndexType & index = GetLargestPossibleRegion().GetIndex();
const RegionType::SizeType & size = GetLargestPossibleRegion().GetSize();
for(i=0;i<RegionDimension;++i)
{
m_RequestedRegion.SetIndex(i, index[i]);
m_RequestedRegion.SetSize(i, size[i]);
}
}
bool mitk::SlicedData::RequestedRegionIsOutsideOfTheBufferedRegion()
{
// Is the requested region within the currently buffered data?
// SlicedData and subclasses store entire volumes or slices. The
// methods IsVolumeSet() and IsSliceSet are provided to check,
// a volume or slice, respectively, is available. Thus, these
// methods used here.
const IndexType &requestedRegionIndex = m_RequestedRegion.GetIndex();
const SizeType& requestedRegionSize = m_RequestedRegion.GetSize();
const SizeType& largestPossibleRegionSize
= GetLargestPossibleRegion().GetSize();
// are whole channels requested?
int c, cEnd;
c=requestedRegionIndex[4];
cEnd=c+static_cast<long>(requestedRegionSize[4]);
if(requestedRegionSize[3] == largestPossibleRegionSize[3])
{
for (; c< cEnd; ++c)
if(IsChannelSet(c)==false) return true;
return false;
}
// are whole volumes requested?
int t, tEnd;
t=requestedRegionIndex[3];
tEnd=t+static_cast<long>(requestedRegionSize[3]);
if(requestedRegionSize[2] == largestPossibleRegionSize[2])
{
for (; c< cEnd; ++c)
for (; t< tEnd; ++t)
if(IsVolumeSet(t, c)==false) return true;
return false;
}
// ok, only slices are requested. Check if they are available.
int s, sEnd;
s=requestedRegionIndex[2];
sEnd=s+static_cast<long>(requestedRegionSize[2]);
for (; c< cEnd; ++c)
for (; t< tEnd; ++t)
for (; s< sEnd; ++s)
if(IsSliceSet(s, t, c)==false) return true;
return false;
}
bool mitk::SlicedData::VerifyRequestedRegion()
{
if(GetTimeGeometry() == NULL) return false;
unsigned int i;
// Is the requested region within the LargestPossibleRegion?
// Note that the test is indeed against the largest possible region
// rather than the buffered region; see DataObject::VerifyRequestedRegion.
const IndexType &requestedRegionIndex = m_RequestedRegion.GetIndex();
const IndexType &largestPossibleRegionIndex
= GetLargestPossibleRegion().GetIndex();
const SizeType& requestedRegionSize = m_RequestedRegion.GetSize();
const SizeType& largestPossibleRegionSize
= GetLargestPossibleRegion().GetSize();
for (i=0; i< RegionDimension; ++i)
{
if ( (requestedRegionIndex[i] < largestPossibleRegionIndex[i]) ||
((requestedRegionIndex[i] + static_cast<long>(requestedRegionSize[i]))
> (largestPossibleRegionIndex[i]+static_cast<long>(largestPossibleRegionSize[i]))))
{
return false;
}
}
return true;
}
void mitk::SlicedData::SetRequestedRegion( const itk::DataObject *data)
{
m_UseLargestPossibleRegion=false;
const mitk::SlicedData *slicedData = dynamic_cast<const mitk::SlicedData*>(data);
if (slicedData)
{
m_RequestedRegion = slicedData->GetRequestedRegion();
m_RequestedRegionInitialized = true;
}
else
{
// pointer could not be cast back down
itkExceptionMacro( << "mitk::SlicedData::SetRequestedRegion(DataObject*) cannot cast " << typeid(data).name() << " to " << typeid(SlicedData*).name() );
}
}
void mitk::SlicedData::SetRequestedRegion(SlicedData::RegionType *region)
{
m_UseLargestPossibleRegion=false;
if(region!=NULL)
{
m_RequestedRegion = *region;
m_RequestedRegionInitialized = true;
}
else
{
// pointer could not be cast back down
itkExceptionMacro( << "mitk::SlicedData::SetRequestedRegion(SlicedData::RegionType*) cannot cast " << typeid(region).name() << " to " << typeid(SlicedData*).name() );
}
}
void mitk::SlicedData::SetLargestPossibleRegion(SlicedData::RegionType *region)
{
if(region!=NULL)
{
m_LargestPossibleRegion = *region;
m_UseLargestPossibleRegion=true;
}
else
{
// pointer could not be cast back down
itkExceptionMacro( << "mitk::SlicedData::SetLargestPossibleRegion(SlicedData::RegionType*) cannot cast " << typeid(region).name() << " to " << typeid(SlicedData*).name() );
}
}
void mitk::SlicedData::CopyInformation(const itk::DataObject *data)
{
// Standard call to the superclass' method
Superclass::CopyInformation(data);
const mitk::SlicedData *slicedData;
slicedData = dynamic_cast<const mitk::SlicedData*>(data);
if (slicedData)
{
m_LargestPossibleRegion = slicedData->GetLargestPossibleRegion();
}
else
{
// pointer could not be cast back down
itkExceptionMacro( << "mitk::SlicedData::CopyInformation(const DataObject *data) cannot cast " << typeid(data).name() << " to " << typeid(SlicedData*).name() );
}
}
-//const mitk::Geometry2D* mitk::SlicedData::GetGeometry2D(int s, int t) const
+//const mitk::PlaneGeometry* mitk::SlicedData::GetPlaneGeometry(int s, int t) const
//{
// const_cast<SlicedData*>(this)->SetRequestedRegionToLargestPossibleRegion();
//
// const_cast<SlicedData*>(this)->UpdateOutputInformation();
//
-// return GetSlicedGeometry(t)->GetGeometry2D(s);
+// return GetSlicedGeometry(t)->GetPlaneGeometry(s);
//}
//
mitk::SlicedGeometry3D* mitk::SlicedData::GetSlicedGeometry(unsigned int t) const
{
if (GetTimeGeometry() == NULL)
return NULL;
return dynamic_cast<SlicedGeometry3D*>(GetTimeGeometry()->GetGeometryForTimeStep(t).GetPointer());
}
const mitk::SlicedGeometry3D* mitk::SlicedData::GetUpdatedSlicedGeometry(unsigned int t)
{
SetRequestedRegionToLargestPossibleRegion();
UpdateOutputInformation();
return GetSlicedGeometry(t);
}
-void mitk::SlicedData::SetGeometry(Geometry3D* aGeometry3D)
+void mitk::SlicedData::SetGeometry(BaseGeometry* aGeometry3D)
{
if(aGeometry3D!=NULL)
{
ProportionalTimeGeometry::Pointer timeGeometry = ProportionalTimeGeometry::New();
SlicedGeometry3D::Pointer slicedGeometry = dynamic_cast<SlicedGeometry3D*>(aGeometry3D);
if(slicedGeometry.IsNull())
{
- Geometry2D* geometry2d = dynamic_cast<Geometry2D*>(aGeometry3D);
+ PlaneGeometry* geometry2d = dynamic_cast<PlaneGeometry*>(aGeometry3D);
if(geometry2d!=NULL)
{
- if((GetSlicedGeometry()->GetGeometry2D(0)==geometry2d) && (GetSlicedGeometry()->GetSlices()==1))
+ if((GetSlicedGeometry()->GetPlaneGeometry(0)==geometry2d) && (GetSlicedGeometry()->GetSlices()==1))
return;
slicedGeometry = SlicedGeometry3D::New();
slicedGeometry->InitializeEvenlySpaced(geometry2d, 1);
}
else
{
slicedGeometry = SlicedGeometry3D::New();
PlaneGeometry::Pointer planeGeometry = PlaneGeometry::New();
planeGeometry->InitializeStandardPlane(aGeometry3D);
slicedGeometry->InitializeEvenlySpaced(planeGeometry, (unsigned int)(aGeometry3D->GetExtent(2)));
}
}
assert(slicedGeometry.IsNotNull());
timeGeometry->Initialize(slicedGeometry, 1);
Superclass::SetTimeGeometry(timeGeometry);
}
else
{
if(GetGeometry()==NULL)
return;
Superclass::SetGeometry(NULL);
}
}
void mitk::SlicedData::SetSpacing(const ScalarType aSpacing[3])
{
this->SetSpacing((mitk::Vector3D)aSpacing);
}
void mitk::SlicedData::SetOrigin(const mitk::Point3D& origin)
{
TimeGeometry* timeGeometry = GetTimeGeometry();
assert(timeGeometry!=NULL);
mitk::SlicedGeometry3D* slicedGeometry;
unsigned int steps = timeGeometry->CountTimeSteps();
for(unsigned int timestep = 0; timestep < steps; ++timestep)
{
slicedGeometry = GetSlicedGeometry(timestep);
if(slicedGeometry != NULL)
{
slicedGeometry->SetOrigin(origin);
if(slicedGeometry->GetEvenlySpaced())
{
- mitk::Geometry2D* geometry2D = slicedGeometry->GetGeometry2D(0);
+ mitk::PlaneGeometry* geometry2D = slicedGeometry->GetPlaneGeometry(0);
geometry2D->SetOrigin(origin);
slicedGeometry->InitializeEvenlySpaced(geometry2D, slicedGeometry->GetSlices());
}
}
//ProportionalTimeGeometry* timeGeometry = dynamic_cast<ProportionalTimeGeometry *>(GetTimeGeometry());
//if(timeGeometry != NULL)
//{
// timeGeometry->Initialize(slicedGeometry, steps);
// break;
//}
}
}
void mitk::SlicedData::SetSpacing(mitk::Vector3D aSpacing)
{
TimeGeometry* timeGeometry = GetTimeGeometry();
assert(timeGeometry!=NULL);
mitk::SlicedGeometry3D* slicedGeometry;
unsigned int steps = timeGeometry->CountTimeSteps();
for(unsigned int timestep = 0; timestep < steps; ++timestep)
{
slicedGeometry = GetSlicedGeometry(timestep);
if(slicedGeometry != NULL)
{
slicedGeometry->SetSpacing(aSpacing);
}
}
timeGeometry->Update();
}
diff --git a/Core/Code/DataManagement/mitkSlicedData.h b/Core/Code/DataManagement/mitkSlicedData.h
index 4530570c31..fa57bfd326 100644
--- a/Core/Code/DataManagement/mitkSlicedData.h
+++ b/Core/Code/DataManagement/mitkSlicedData.h
@@ -1,227 +1,227 @@
/*===================================================================
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 SLICEDDATA_H_HEADER_INCLUDED
#define SLICEDDATA_H_HEADER_INCLUDED
#include <MitkCoreExports.h>
#include "mitkBaseData.h"
#include "mitkSlicedGeometry3D.h"
#include "itkIndex.h"
#include "itkOffset.h"
#include "itkSize.h"
#include "itkImageRegion.h"
namespace mitk {
class SlicedGeometry3D;
//##Documentation
//## @brief Super class of data objects consisting of slices
//##
//## Super class of data objects consisting of slices, e.g., images or a stack
-//## of contours. (GetGeometry will return a Geometry3D containing Geometry2D
+//## of contours. (GetGeometry will return a BaseGeometry containing PlaneGeometry
//## objects).
//##
//## SlicedData-objects have geometries of type SlicedGeometry3D or sub-classes.
//## @ingroup Data
class MITK_CORE_EXPORT SlicedData : public BaseData
{
public:
mitkClassMacro(SlicedData, BaseData);
itkStaticConstMacro(RegionDimension, unsigned int, 5);
/** Region typedef support. A region is used to specify a subset of a @a SlicedData. */
typedef itk::ImageRegion<RegionDimension> RegionType;
/** Index typedef support. An index is used to access pixel values. */
typedef itk::Index<RegionDimension> IndexType;
typedef IndexType::IndexValueType IndexValueType;
/** Offset typedef support. An offset represent relative position
* between indices. */
typedef itk::Offset<RegionDimension> OffsetType;
typedef OffsetType::OffsetValueType OffsetValueType;
/** Size typedef support. A size is used to define region bounds. */
typedef itk::Size<RegionDimension> SizeType;
typedef SizeType::SizeValueType SizeValueType;
//##Documentation
//## Update the information for this DataObject so that it can be used as
//## an output of a ProcessObject. This method is used in the pipeline
//## mechanism to propagate information and initialize the meta data
//## associated with a itk::DataObject. Any implementation of this method
//## in a derived class of itk::DataObject is assumed to call its source's
//## ProcessObject::UpdateOutputInformation() which determines modified
//## times, LargestPossibleRegions, and any extra meta data like spacing,
//## origin, etc.
virtual void UpdateOutputInformation();
virtual void PrepareForNewData();
//##Documentation
//## Set the RequestedRegion to the LargestPossibleRegion. This forces a
//## filter to produce all of the output in one execution (i.e. not
//## streaming) on the next call to Update().
virtual void SetRequestedRegionToLargestPossibleRegion();
//##Documentation
//## Determine whether the RequestedRegion is outside of the
//## BufferedRegion. This method returns true if the RequestedRegion is
//## outside the BufferedRegion (true if at least one pixel is outside).
//## This is used by the pipeline mechanism to determine whether a filter
//## needs to re-execute in order to satisfy the current request. If the
//## current RequestedRegion is already inside the BufferedRegion from the
//## previous execution (and the current filter is up to date), then a
//## given filter does not need to re-execute
virtual bool RequestedRegionIsOutsideOfTheBufferedRegion();
//##Documentation
//## @brief Verify that the RequestedRegion is within the
//## LargestPossibleRegion.
//##
//## Verify that the RequestedRegion is within the LargestPossibleRegion.
//## If the RequestedRegion is not within the LargestPossibleRegion,
//## then the filter cannot possibly satisfy the request. This method
//## returns true if the request can be satisfied (even if it will be
//## necessary to process the entire LargestPossibleRegion) and
//## returns false otherwise. This method is used by
//## PropagateRequestedRegion(). PropagateRequestedRegion() throws a
//## InvalidRequestedRegionError exception if the requested region is
//## not within the LargestPossibleRegion.
virtual bool VerifyRequestedRegion();
//##Documentation
//## Set the requested region from this data object to match the requested
//## region of the data object passed in as a parameter. This method is
//## implemented in the concrete subclasses of DataObject.
virtual void SetRequestedRegion( const itk::DataObject *data);
//##Documentation
//## Set the requested region from this data object to match the requested
//## region of the data object passed in as a parameter. This method is
//## implemented in the concrete subclasses of DataObject.
virtual void SetRequestedRegion(SlicedData::RegionType *region);
/*! Documentation
\brief Sets the largest possible region.
The largest possible region is the entire region occupied by the data object.
Note that the largest possible region should always be bigger then the requested region
of a certain operation.*/
void SetLargestPossibleRegion(SlicedData::RegionType *region);
const RegionType& GetLargestPossibleRegion() const
{
return m_LargestPossibleRegion;
}
//##Documentation
//## Get the region object that defines the size and starting index
//## for the region of the image requested (i.e., the region of the
//## image to be operated on by a filter).
virtual const RegionType& GetRequestedRegion() const
{
return m_RequestedRegion;
}
virtual bool IsSliceSet(int s = 0, int t = 0, int n = 0) const = 0;
virtual bool IsVolumeSet(int t = 0, int n = 0) const = 0;
virtual bool IsChannelSet(int n = 0) const = 0;
virtual void CopyInformation(const itk::DataObject *data);
//##Documentation
//## @brief Get the number of channels
unsigned int GetNumberOfChannels() const
{
return m_LargestPossibleRegion.GetSize(4);
}
////##Documentation
- ////## @brief Return the Geometry2D of the slice (@a s, @a t).
+ ////## @brief Return the PlaneGeometry of the slice (@a s, @a t).
////##
- ////## The method does not simply call GetGeometry()->GetGeometry2D(). Before doing this, it
- ////## makes sure that the Geometry2D is up-to-date before returning it (by
+ ////## The method does not simply call GetGeometry()->GetPlaneGeometry(). Before doing this, it
+ ////## makes sure that the PlaneGeometry is up-to-date before returning it (by
////## setting the update extent appropriately and calling
////## UpdateOutputInformation).
////##
- ////## @warning GetGeometry2D not yet completely implemented.
+ ////## @warning GetPlaneGeometry not yet completely implemented.
////## @todo Appropriate setting of the update extent is missing.
- //virtual const mitk::Geometry2D* GetGeometry2D(int s, int t=0) const;
+ //virtual const mitk::PlaneGeometry* GetPlaneGeometry(int s, int t=0) const;
//##Documentation
//## @brief Convenience access method for the geometry, which is of type SlicedGeometry3D (or a sub-class of it).
//##
//## @em No update will be called. Normally used in GenerateOutputInformation of
//## subclasses of BaseProcess.
SlicedGeometry3D* GetSlicedGeometry(unsigned int t=0) const;
//##Documentation
//## @brief Convenience access method for the geometry, which is of type SlicedGeometry3D (or a sub-class of it).
//##
//## The method does not simply return the value of the m_Geometry3D member.
- //## Before doing this, it makes sure that the Geometry3D is up-to-date before
+ //## Before doing this, it makes sure that the BaseGeometry is up-to-date before
//## returning it (by setting the update extent appropriately and calling
//## UpdateOutputInformation).
//##
//## @warning GetGeometry not yet completely implemented.
//## @todo Appropriate setting of the update extent is missing.
const SlicedGeometry3D* GetUpdatedSlicedGeometry(unsigned int t=0);
//##Documentation
- //## @brief Set the Geometry3D of the data, which will be referenced (not copied!). It
+ //## @brief Set the BaseGeometry of the data, which will be referenced (not copied!). It
//## has to be a sub-class of SlicedGeometry3D.
//##
//## @warning This method will normally be called internally by the sub-class of SlicedData
//## during initialization.
- virtual void SetGeometry(Geometry3D* aGeometry3D);
+ virtual void SetGeometry(BaseGeometry* aGeometry3D);
//##Documentation
//## @brief Convenience method for setting the origin of
//## the SlicedGeometry3D instances of all time steps
//##
//## In case the SlicedGeometry3D is evenly spaced,
//## the origin of the first slice is set to \a origin.
//## \sa mitk::BaseData::SetOrigin
virtual void SetOrigin(const Point3D& origin);
//##Documentation
//## @brief Convenience method for setting the spacing of
//## the SlicedGeometry3D instances of all time steps
virtual void SetSpacing(const ScalarType aSpacing[]);
//##Documentation
//## @brief Convenience method for setting the spacing of
//## the SlicedGeometry3D instances of all time steps
virtual void SetSpacing(mitk::Vector3D aSpacing);
protected:
SlicedData();
SlicedData(const SlicedData &other);
virtual ~SlicedData();
RegionType m_LargestPossibleRegion;
RegionType m_RequestedRegion;
RegionType m_BufferedRegion;
bool m_UseLargestPossibleRegion;
};
} // namespace mitk
#endif /* SLICEDDATA_H_HEADER_INCLUDED */
diff --git a/Core/Code/DataManagement/mitkSlicedGeometry3D.cpp b/Core/Code/DataManagement/mitkSlicedGeometry3D.cpp
index e63b6ea31a..1f223b2437 100644
--- a/Core/Code/DataManagement/mitkSlicedGeometry3D.cpp
+++ b/Core/Code/DataManagement/mitkSlicedGeometry3D.cpp
@@ -1,1055 +1,1035 @@
/*===================================================================
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 "mitkSlicedGeometry3D.h"
#include "mitkPlaneGeometry.h"
#include "mitkRotationOperation.h"
#include "mitkPlaneOperation.h"
#include "mitkRestorePlanePositionOperation.h"
#include "mitkApplyTransformMatrixOperation.h"
#include "mitkInteractionConst.h"
#include "mitkSliceNavigationController.h"
const mitk::ScalarType PI = 3.14159265359;
mitk::SlicedGeometry3D::SlicedGeometry3D()
-: m_EvenlySpaced( true ),
+ : m_EvenlySpaced( true ),
m_Slices( 0 ),
m_ReferenceGeometry( NULL ),
m_SliceNavigationController( NULL )
{
- m_DirectionVector.Fill(0);
+ m_DirectionVector.Fill(0);
this->InitializeSlicedGeometry( m_Slices );
}
mitk::SlicedGeometry3D::SlicedGeometry3D(const SlicedGeometry3D& other)
-: Superclass(other),
+ : Superclass(other),
m_EvenlySpaced( other.m_EvenlySpaced ),
m_Slices( other.m_Slices ),
m_ReferenceGeometry( other.m_ReferenceGeometry ),
m_SliceNavigationController( other.m_SliceNavigationController )
{
- m_DirectionVector.Fill(0);
+ m_DirectionVector.Fill(0);
SetSpacing( other.GetSpacing() );
SetDirectionVector( other.GetDirectionVector() );
if ( m_EvenlySpaced )
{
- Geometry2D::Pointer geometry = other.m_Geometry2Ds[0]->Clone();
- Geometry2D* geometry2D = dynamic_cast<Geometry2D*>(geometry.GetPointer());
+ PlaneGeometry::Pointer geometry = other.m_PlaneGeometries[0]->Clone();
+ PlaneGeometry* geometry2D = dynamic_cast<PlaneGeometry*>(geometry.GetPointer());
assert(geometry2D!=NULL);
- SetGeometry2D(geometry2D, 0);
+ SetPlaneGeometry(geometry2D, 0);
}
else
{
unsigned int s;
for ( s = 0; s < other.m_Slices; ++s )
{
- if ( other.m_Geometry2Ds[s].IsNull() )
+ if ( other.m_PlaneGeometries[s].IsNull() )
{
assert(other.m_EvenlySpaced);
- m_Geometry2Ds[s] = NULL;
+ m_PlaneGeometries[s] = NULL;
}
else
{
- Geometry2D* geometry2D = other.m_Geometry2Ds[s]->Clone();
+ PlaneGeometry* geometry2D = other.m_PlaneGeometries[s]->Clone();
assert(geometry2D!=NULL);
- SetGeometry2D(geometry2D, s);
+ SetPlaneGeometry(geometry2D, s);
}
}
}
}
mitk::SlicedGeometry3D::~SlicedGeometry3D()
{
}
-
-mitk::Geometry2D *
-mitk::SlicedGeometry3D::GetGeometry2D( int s ) const
+mitk::PlaneGeometry *
+ mitk::SlicedGeometry3D::GetPlaneGeometry( int s ) const
{
- mitk::Geometry2D::Pointer geometry2D = NULL;
+ mitk::PlaneGeometry::Pointer geometry2D = NULL;
if ( this->IsValidSlice(s) )
{
- geometry2D = m_Geometry2Ds[s];
+ geometry2D = m_PlaneGeometries[s];
- // If (a) m_EvenlySpaced==true, (b) we don't have a Geometry2D stored
+ // If (a) m_EvenlySpaced==true, (b) we don't have a PlaneGeometry stored
// for the requested slice, and (c) the first slice (s=0)
// is a PlaneGeometry instance, then we calculate the geometry of the
// requested as the plane of the first slice shifted by m_Spacing[2]*s
// in the direction of m_DirectionVector.
if ( (m_EvenlySpaced) && (geometry2D.IsNull()) )
{
PlaneGeometry *firstSlice = dynamic_cast< PlaneGeometry * > (
- m_Geometry2Ds[0].GetPointer() );
+ m_PlaneGeometries[0].GetPointer() );
if ( firstSlice != NULL )
{
if ( (m_DirectionVector[0] == 0.0)
&& (m_DirectionVector[1] == 0.0)
&& (m_DirectionVector[2] == 0.0) )
{
m_DirectionVector = firstSlice->GetNormal();
m_DirectionVector.Normalize();
}
Vector3D direction;
- direction = m_DirectionVector * m_Spacing[2];
+ direction = m_DirectionVector * this->GetSpacing()[2];
mitk::PlaneGeometry::Pointer requestedslice;
requestedslice = static_cast< mitk::PlaneGeometry * >(
firstSlice->Clone().GetPointer() );
requestedslice->SetOrigin(
requestedslice->GetOrigin() + direction * s );
geometry2D = requestedslice;
- m_Geometry2Ds[s] = geometry2D;
+ m_PlaneGeometries[s] = geometry2D;
}
}
return geometry2D;
}
else
{
return NULL;
}
}
const mitk::BoundingBox *
-mitk::SlicedGeometry3D::GetBoundingBox() const
+ mitk::SlicedGeometry3D::GetBoundingBox() const
{
- assert(m_BoundingBox.IsNotNull());
- return m_BoundingBox.GetPointer();
+ assert(this->IsBoundingBoxNull()==false);
+ return Superclass::GetBoundingBox();
}
-
bool
-mitk::SlicedGeometry3D::SetGeometry2D( mitk::Geometry2D *geometry2D, int s )
+ mitk::SlicedGeometry3D::SetPlaneGeometry( mitk::PlaneGeometry *geometry2D, int s )
{
if ( this->IsValidSlice(s) )
{
- m_Geometry2Ds[s] = geometry2D;
- m_Geometry2Ds[s]->SetReferenceGeometry( m_ReferenceGeometry );
+ m_PlaneGeometries[s] = geometry2D;
+ m_PlaneGeometries[s]->SetReferenceGeometry( m_ReferenceGeometry );
return true;
}
return false;
}
-
void
-mitk::SlicedGeometry3D::InitializeSlicedGeometry( unsigned int slices )
+ mitk::SlicedGeometry3D::InitializeSlicedGeometry( unsigned int slices )
{
Superclass::Initialize();
m_Slices = slices;
- Geometry2D::Pointer gnull = NULL;
- m_Geometry2Ds.assign( m_Slices, gnull );
+ PlaneGeometry::Pointer gnull = NULL;
+ m_PlaneGeometries.assign( m_Slices, gnull );
Vector3D spacing;
spacing.Fill( 1.0 );
this->SetSpacing( spacing );
m_DirectionVector.Fill( 0 );
}
-
void
-mitk::SlicedGeometry3D::InitializeEvenlySpaced(
- mitk::Geometry2D* geometry2D, unsigned int slices, bool flipped )
+ mitk::SlicedGeometry3D::InitializeEvenlySpaced(
+ mitk::PlaneGeometry* geometry2D, unsigned int slices, bool flipped )
{
assert( geometry2D != NULL );
this->InitializeEvenlySpaced(
geometry2D, geometry2D->GetExtentInMM(2)/geometry2D->GetExtent(2),
slices, flipped );
}
-
void
-mitk::SlicedGeometry3D::InitializeEvenlySpaced(
- mitk::Geometry2D* geometry2D, mitk::ScalarType zSpacing,
+ mitk::SlicedGeometry3D::InitializeEvenlySpaced(
+ mitk::PlaneGeometry* geometry2D, mitk::ScalarType zSpacing,
unsigned int slices, bool flipped )
{
assert( geometry2D != NULL );
assert( geometry2D->GetExtent(0) > 0 );
assert( geometry2D->GetExtent(1) > 0 );
geometry2D->Register();
Superclass::Initialize();
m_Slices = slices;
BoundingBox::BoundsArrayType bounds = geometry2D->GetBounds();
bounds[4] = 0;
bounds[5] = slices;
// clear and reserve
- Geometry2D::Pointer gnull = NULL;
- m_Geometry2Ds.assign( m_Slices, gnull );
+ PlaneGeometry::Pointer gnull = NULL;
+ m_PlaneGeometries.assign( m_Slices, gnull );
Vector3D directionVector = geometry2D->GetAxisVector(2);
directionVector.Normalize();
directionVector *= zSpacing;
if ( flipped == false )
{
// Normally we should use the following four lines to create a copy of
// the transform contrained in geometry2D, because it may not be changed
// by us. But we know that SetSpacing creates a new transform without
// changing the old (coming from geometry2D), so we can use the fifth
// line instead. We check this at (**).
//
// AffineTransform3D::Pointer transform = AffineTransform3D::New();
// transform->SetMatrix(geometry2D->GetIndexToWorldTransform()->GetMatrix());
// transform->SetOffset(geometry2D->GetIndexToWorldTransform()->GetOffset());
// SetIndexToWorldTransform(transform);
- m_IndexToWorldTransform = const_cast< AffineTransform3D * >(
- geometry2D->GetIndexToWorldTransform() );
+ this->SetIndexToWorldTransform( const_cast< AffineTransform3D * >(
+ geometry2D->GetIndexToWorldTransform() ));
}
else
{
directionVector *= -1.0;
- m_IndexToWorldTransform = AffineTransform3D::New();
- m_IndexToWorldTransform->SetMatrix(
+ this->SetIndexToWorldTransform( AffineTransform3D::New());
+ this->GetIndexToWorldTransform()->SetMatrix(
geometry2D->GetIndexToWorldTransform()->GetMatrix() );
AffineTransform3D::OutputVectorType scaleVector;
FillVector3D(scaleVector, 1.0, 1.0, -1.0);
- m_IndexToWorldTransform->Scale(scaleVector, true);
- m_IndexToWorldTransform->SetOffset(
+ this->GetIndexToWorldTransform()->Scale(scaleVector, true);
+ this->GetIndexToWorldTransform()->SetOffset(
geometry2D->GetIndexToWorldTransform()->GetOffset() );
}
mitk::Vector3D spacing;
FillVector3D( spacing,
geometry2D->GetExtentInMM(0) / bounds[1],
geometry2D->GetExtentInMM(1) / bounds[3],
zSpacing );
- // Ensure that spacing differs from m_Spacing to make SetSpacing change the
- // matrix.
- m_Spacing[2] = zSpacing - 1;
-
this->SetDirectionVector( directionVector );
this->SetBounds( bounds );
- this->SetGeometry2D( geometry2D, 0 );
- this->SetSpacing( spacing );
+ this->SetPlaneGeometry( geometry2D, 0 );
+ this->SetSpacing( spacing ,true);
this->SetEvenlySpaced();
- this->SetTimeBounds( geometry2D->GetTimeBounds() );
- assert(m_IndexToWorldTransform.GetPointer()
- != geometry2D->GetIndexToWorldTransform()); // (**) see above.
+ //this->SetTimeBounds( geometry2D->GetTimeBounds() );
+
+ assert(this->GetIndexToWorldTransform()
+ != geometry2D->GetIndexToWorldTransform()); // (**) see above.
this->SetFrameOfReferenceID( geometry2D->GetFrameOfReferenceID() );
this->SetImageGeometry( geometry2D->GetImageGeometry() );
geometry2D->UnRegister();
}
-
void
-mitk::SlicedGeometry3D::InitializePlanes(
- const mitk::Geometry3D *geometry3D,
+ mitk::SlicedGeometry3D::InitializePlanes(
+ const mitk::BaseGeometry *geometry3D,
mitk::PlaneGeometry::PlaneOrientation planeorientation,
bool top, bool frontside, bool rotated )
{
- m_ReferenceGeometry = const_cast< Geometry3D * >( geometry3D );
+ m_ReferenceGeometry = const_cast< BaseGeometry * >( geometry3D );
PlaneGeometry::Pointer planeGeometry = mitk::PlaneGeometry::New();
planeGeometry->InitializeStandardPlane(
geometry3D, top, planeorientation, frontside, rotated );
ScalarType viewSpacing = 1;
unsigned int slices = 1;
switch ( planeorientation )
{
- case PlaneGeometry::Axial:
- viewSpacing = geometry3D->GetSpacing()[2];
- slices = (unsigned int) geometry3D->GetExtent( 2 );
- break;
-
- case PlaneGeometry::Frontal:
- viewSpacing = geometry3D->GetSpacing()[1];
- slices = (unsigned int) geometry3D->GetExtent( 1 );
- break;
-
- case PlaneGeometry::Sagittal:
- viewSpacing = geometry3D->GetSpacing()[0];
- slices = (unsigned int) geometry3D->GetExtent( 0 );
- break;
-
- default:
- itkExceptionMacro("unknown PlaneOrientation");
+ case PlaneGeometry::Axial:
+ viewSpacing = geometry3D->GetSpacing()[2];
+ slices = (unsigned int) geometry3D->GetExtent( 2 );
+ break;
+
+ case PlaneGeometry::Frontal:
+ viewSpacing = geometry3D->GetSpacing()[1];
+ slices = (unsigned int) geometry3D->GetExtent( 1 );
+ break;
+
+ case PlaneGeometry::Sagittal:
+ viewSpacing = geometry3D->GetSpacing()[0];
+ slices = (unsigned int) geometry3D->GetExtent( 0 );
+ break;
+
+ default:
+ itkExceptionMacro("unknown PlaneOrientation");
}
mitk::Vector3D normal = this->AdjustNormal( planeGeometry->GetNormal() );
-
ScalarType directedExtent =
- std::abs( m_ReferenceGeometry->GetExtentInMM( 0 ) * normal[0] )
+ std::abs( m_ReferenceGeometry->GetExtentInMM( 0 ) * normal[0] )
+ std::abs( m_ReferenceGeometry->GetExtentInMM( 1 ) * normal[1] )
+ std::abs( m_ReferenceGeometry->GetExtentInMM( 2 ) * normal[2] );
if ( directedExtent >= viewSpacing )
{
slices = static_cast< int >(directedExtent / viewSpacing + 0.5);
}
else
{
slices = 1;
}
bool flipped = (top == false);
if ( frontside == false )
{
flipped = !flipped;
}
if ( planeorientation == PlaneGeometry::Frontal )
{
flipped = !flipped;
}
this->InitializeEvenlySpaced( planeGeometry, viewSpacing, slices, flipped );
}
-
void
-mitk::SlicedGeometry3D
-::ReinitializePlanes( const Point3D &center, const Point3D &referencePoint )
+ mitk::SlicedGeometry3D
+ ::ReinitializePlanes( const Point3D &center, const Point3D &referencePoint )
{
// Need a reference frame to align the rotated planes
if ( !m_ReferenceGeometry )
{
return;
}
// Get first plane of plane stack
PlaneGeometry *firstPlane =
- dynamic_cast< PlaneGeometry * >( m_Geometry2Ds[0].GetPointer() );
+ dynamic_cast< PlaneGeometry * >( m_PlaneGeometries[0].GetPointer() );
// If plane stack is empty, exit
if ( firstPlane == NULL )
{
return;
}
// Calculate the "directed" spacing when taking the plane (defined by its axes
// vectors and normal) as the reference coordinate frame.
//
// This is done by calculating the radius of the ellipsoid defined by the
// original volume spacing axes, in the direction of the respective axis of the
// reference frame.
mitk::Vector3D axis0 = firstPlane->GetAxisVector(0);
mitk::Vector3D axis1 = firstPlane->GetAxisVector(1);
mitk::Vector3D normal = firstPlane->GetNormal();
normal.Normalize();
Vector3D spacing;
spacing[0] = this->CalculateSpacing( axis0 );
spacing[1] = this->CalculateSpacing( axis1 );
spacing[2] = this->CalculateSpacing( normal );
Superclass::SetSpacing( spacing );
-
// Now we need to calculate the number of slices in the plane's normal
// direction, so that the entire volume is covered. This is done by first
// calculating the dot product between the volume diagonal (the maximum
// distance inside the volume) and the normal, and dividing this value by
// the directed spacing calculated above.
ScalarType directedExtent =
- std::abs( m_ReferenceGeometry->GetExtentInMM( 0 ) * normal[0] )
+ std::abs( m_ReferenceGeometry->GetExtentInMM( 0 ) * normal[0] )
+ std::abs( m_ReferenceGeometry->GetExtentInMM( 1 ) * normal[1] )
+ std::abs( m_ReferenceGeometry->GetExtentInMM( 2 ) * normal[2] );
if ( directedExtent >= spacing[2] )
{
m_Slices = static_cast< unsigned int >(directedExtent / spacing[2] + 0.5);
}
else
{
m_Slices = 1;
}
// The origin of our "first plane" needs to be adapted to this new extent.
// To achieve this, we first calculate the current distance to the volume's
// center, and then shift the origin in the direction of the normal by the
// difference between this distance and half of the new extent.
double centerOfRotationDistance =
firstPlane->SignedDistanceFromPlane( center );
if ( centerOfRotationDistance > 0 )
{
firstPlane->SetOrigin( firstPlane->GetOrigin()
+ normal * (centerOfRotationDistance - directedExtent / 2.0)
- );
+ );
m_DirectionVector = normal;
}
else
{
firstPlane->SetOrigin( firstPlane->GetOrigin()
+ normal * (directedExtent / 2.0 + centerOfRotationDistance)
- );
+ );
m_DirectionVector = -normal;
}
// Now we adjust this distance according with respect to the given reference
// point: we need to make sure that the point is touched by one slice of the
// new slice stack.
double referencePointDistance =
firstPlane->SignedDistanceFromPlane( referencePoint );
int referencePointSlice = static_cast< int >(
referencePointDistance / spacing[2]);
double alignmentValue =
referencePointDistance / spacing[2] - referencePointSlice;
firstPlane->SetOrigin(
firstPlane->GetOrigin() + normal * alignmentValue * spacing[2] );
-
// Finally, we can clear the previous geometry stack and initialize it with
// our re-initialized "first plane".
- m_Geometry2Ds.assign( m_Slices, Geometry2D::Pointer( NULL ) );
+ m_PlaneGeometries.assign( m_Slices, PlaneGeometry::Pointer( NULL ) );
if ( m_Slices > 0 )
{
- m_Geometry2Ds[0] = firstPlane;
+ m_PlaneGeometries[0] = firstPlane;
}
// Reinitialize SNC with new number of slices
m_SliceNavigationController->GetSlice()->SetSteps( m_Slices );
this->Modified();
}
-
double
-mitk::SlicedGeometry3D::CalculateSpacing( const mitk::Vector3D &d ) const
+ mitk::SlicedGeometry3D::CalculateSpacing( const mitk::Vector3D &d ) const
{
- // Need the spacing of the underlying dataset / geometry
- if ( !m_ReferenceGeometry )
- {
- return 1.0;
- }
-
- const mitk::Vector3D &spacing = m_ReferenceGeometry->GetSpacing();
- return SlicedGeometry3D::CalculateSpacing( spacing, d );
+ // Need the spacing of the underlying dataset / geometry
+ if ( !m_ReferenceGeometry )
+ {
+ return 1.0;
+ }
+
+ const mitk::Vector3D &spacing = m_ReferenceGeometry->GetSpacing();
+ return SlicedGeometry3D::CalculateSpacing( spacing, d );
}
double mitk::SlicedGeometry3D::CalculateSpacing( const mitk::Vector3D spacing, const mitk::Vector3D &d )
{
// 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)
//
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 );
}
mitk::Vector3D
-mitk::SlicedGeometry3D::AdjustNormal( const mitk::Vector3D &normal ) const
+ mitk::SlicedGeometry3D::AdjustNormal( const mitk::Vector3D &normal ) const
{
TransformType::Pointer inverse = TransformType::New();
m_ReferenceGeometry->GetIndexToWorldTransform()->GetInverse( inverse );
Vector3D transformedNormal = inverse->TransformVector( normal );
transformedNormal.Normalize();
return transformedNormal;
}
-
void
-mitk::SlicedGeometry3D::SetImageGeometry( const bool isAnImageGeometry )
+ mitk::SlicedGeometry3D::SetImageGeometry( const bool isAnImageGeometry )
{
Superclass::SetImageGeometry( isAnImageGeometry );
- mitk::Geometry3D* geometry;
+ mitk::BaseGeometry* geometry;
unsigned int s;
for ( s = 0; s < m_Slices; ++s )
{
- geometry = m_Geometry2Ds[s];
+ geometry = m_PlaneGeometries[s];
if ( geometry!=NULL )
{
geometry->SetImageGeometry( isAnImageGeometry );
}
}
}
void
-mitk::SlicedGeometry3D::ChangeImageGeometryConsideringOriginOffset( const bool isAnImageGeometry )
+ mitk::SlicedGeometry3D::ChangeImageGeometryConsideringOriginOffset( const bool isAnImageGeometry )
{
- mitk::Geometry3D* geometry;
+ mitk::BaseGeometry* geometry;
unsigned int s;
for ( s = 0; s < m_Slices; ++s )
{
- geometry = m_Geometry2Ds[s];
+ geometry = m_PlaneGeometries[s];
if ( geometry!=NULL )
{
geometry->ChangeImageGeometryConsideringOriginOffset( isAnImageGeometry );
}
}
Superclass::ChangeImageGeometryConsideringOriginOffset( isAnImageGeometry );
}
-
bool
-mitk::SlicedGeometry3D::IsValidSlice( int s ) const
+ mitk::SlicedGeometry3D::IsValidSlice( int s ) const
{
return ((s >= 0) && (s < (int)m_Slices));
}
void
-mitk::SlicedGeometry3D::SetReferenceGeometry( Geometry3D *referenceGeometry )
+ mitk::SlicedGeometry3D::SetReferenceGeometry( BaseGeometry *referenceGeometry )
{
m_ReferenceGeometry = referenceGeometry;
- std::vector<Geometry2D::Pointer>::iterator it;
+ std::vector<PlaneGeometry::Pointer>::iterator it;
- for ( it = m_Geometry2Ds.begin(); it != m_Geometry2Ds.end(); ++it )
+ for ( it = m_PlaneGeometries.begin(); it != m_PlaneGeometries.end(); ++it )
{
(*it)->SetReferenceGeometry( referenceGeometry );
}
}
void
-mitk::SlicedGeometry3D::SetSpacing( const mitk::Vector3D &aSpacing )
+ mitk::SlicedGeometry3D::PreSetSpacing( const mitk::Vector3D &aSpacing )
{
bool hasEvenlySpacedPlaneGeometry = false;
mitk::Point3D origin;
mitk::Vector3D rightDV, bottomDV;
BoundingBox::BoundsArrayType bounds;
assert(aSpacing[0]>0 && aSpacing[1]>0 && aSpacing[2]>0);
- // In case of evenly-spaced data: re-initialize instances of Geometry2D,
+ // In case of evenly-spaced data: re-initialize instances of PlaneGeometry,
// since the spacing influences them
- if ((m_EvenlySpaced) && (m_Geometry2Ds.size() > 0))
+ if ((m_EvenlySpaced) && (m_PlaneGeometries.size() > 0))
{
- mitk::Geometry2D::ConstPointer firstGeometry =
- m_Geometry2Ds[0].GetPointer();
+ mitk::PlaneGeometry::ConstPointer firstGeometry =
+ m_PlaneGeometries[0].GetPointer();
const PlaneGeometry *planeGeometry =
dynamic_cast< const PlaneGeometry * >( firstGeometry.GetPointer() );
if (planeGeometry != NULL )
{
this->WorldToIndex( planeGeometry->GetOrigin(), origin );
this->WorldToIndex( planeGeometry->GetAxisVector(0), rightDV );
this->WorldToIndex( planeGeometry->GetAxisVector(1), bottomDV );
bounds = planeGeometry->GetBounds();
hasEvenlySpacedPlaneGeometry = true;
}
}
- Superclass::SetSpacing(aSpacing);
+ _SetSpacing(aSpacing);
- mitk::Geometry2D::Pointer firstGeometry;
+ mitk::PlaneGeometry::Pointer firstGeometry;
- // In case of evenly-spaced data: re-initialize instances of Geometry2D,
+ // In case of evenly-spaced data: re-initialize instances of PlaneGeometry,
// since the spacing influences them
if ( hasEvenlySpacedPlaneGeometry )
{
//create planeGeometry according to new spacing
this->IndexToWorld( origin, origin );
this->IndexToWorld( rightDV, rightDV );
this->IndexToWorld( bottomDV, bottomDV );
mitk::PlaneGeometry::Pointer planeGeometry = mitk::PlaneGeometry::New();
planeGeometry->SetImageGeometry( this->GetImageGeometry() );
planeGeometry->SetReferenceGeometry( m_ReferenceGeometry );
+
+ //Store spacing, as Initialize... needs a pointer
+ mitk::Vector3D lokalSpacing = this->GetSpacing();
planeGeometry->InitializeStandardPlane(
- rightDV.GetVnlVector(), bottomDV.GetVnlVector(), &m_Spacing );
+ rightDV.GetVnlVector(), bottomDV.GetVnlVector(), &lokalSpacing );
planeGeometry->SetOrigin(origin);
planeGeometry->SetBounds(bounds);
firstGeometry = planeGeometry;
}
- else if ( (m_EvenlySpaced) && (m_Geometry2Ds.size() > 0) )
+ else if ( (m_EvenlySpaced) && (m_PlaneGeometries.size() > 0) )
{
- firstGeometry = m_Geometry2Ds[0].GetPointer();
+ firstGeometry = m_PlaneGeometries[0].GetPointer();
}
//clear and reserve
- Geometry2D::Pointer gnull=NULL;
- m_Geometry2Ds.assign(m_Slices, gnull);
+ PlaneGeometry::Pointer gnull=NULL;
+ m_PlaneGeometries.assign(m_Slices, gnull);
if ( m_Slices > 0 )
{
- m_Geometry2Ds[0] = firstGeometry;
+ m_PlaneGeometries[0] = firstGeometry;
}
this->Modified();
}
-
void
-mitk::SlicedGeometry3D
-::SetSliceNavigationController( SliceNavigationController *snc )
+ mitk::SlicedGeometry3D
+ ::SetSliceNavigationController( SliceNavigationController *snc )
{
m_SliceNavigationController = snc;
}
-
mitk::SliceNavigationController *
-mitk::SlicedGeometry3D::GetSliceNavigationController()
+ mitk::SlicedGeometry3D::GetSliceNavigationController()
{
return m_SliceNavigationController;
}
void
-mitk::SlicedGeometry3D::SetEvenlySpaced(bool on)
+ mitk::SlicedGeometry3D::SetEvenlySpaced(bool on)
{
if(m_EvenlySpaced!=on)
{
m_EvenlySpaced=on;
this->Modified();
}
}
-
void
-mitk::SlicedGeometry3D
-::SetDirectionVector( const mitk::Vector3D& directionVector )
+ mitk::SlicedGeometry3D
+ ::SetDirectionVector( const mitk::Vector3D& directionVector )
{
- Vector3D newDir = directionVector;
- newDir.Normalize();
- if ( newDir != m_DirectionVector )
+ Vector3D newDir = directionVector;
+ newDir.Normalize();
+ if ( newDir != m_DirectionVector )
{
- m_DirectionVector = newDir;
+ m_DirectionVector = newDir;
this->Modified();
}
}
-
-void
-mitk::SlicedGeometry3D::SetTimeBounds( const mitk::TimeBounds& timebounds )
-{
- Superclass::SetTimeBounds( timebounds );
-
- unsigned int s;
- for ( s = 0; s < m_Slices; ++s )
- {
- if(m_Geometry2Ds[s].IsNotNull())
- {
- m_Geometry2Ds[s]->SetTimeBounds( timebounds );
- }
- }
- m_TimeBounds = timebounds;
-}
-
+//void
+//mitk::SlicedGeometry3D::SetTimeBounds( const mitk::TimeBounds& timebounds )
+//{
+// Superclass::SetTimeBounds( timebounds );
+//
+// unsigned int s;
+// for ( s = 0; s < m_Slices; ++s )
+// {
+// if(m_Geometry2Ds[s].IsNotNull())
+// {
+// m_Geometry2Ds[s]->SetTimeBounds( timebounds );
+// }
+// }
+// m_TimeBounds = timebounds;
+//}
itk::LightObject::Pointer
-mitk::SlicedGeometry3D::InternalClone() const
+ mitk::SlicedGeometry3D::InternalClone() const
{
Self::Pointer newGeometry = new SlicedGeometry3D(*this);
newGeometry->UnRegister();
return newGeometry.GetPointer();
}
void
-mitk::SlicedGeometry3D::PrintSelf( std::ostream& os, itk::Indent indent ) const
+ mitk::SlicedGeometry3D::PrintSelf( std::ostream& os, itk::Indent indent ) const
{
Superclass::PrintSelf(os,indent);
os << indent << " EvenlySpaced: " << m_EvenlySpaced << std::endl;
if ( m_EvenlySpaced )
{
os << indent << " DirectionVector: " << m_DirectionVector << std::endl;
}
os << indent << " Slices: " << m_Slices << std::endl;
os << std::endl;
- os << indent << " GetGeometry2D(0): ";
- if ( this->GetGeometry2D(0) == NULL )
+ os << indent << " GetPlaneGeometry(0): ";
+ if ( this->GetPlaneGeometry(0) == NULL )
{
os << "NULL" << std::endl;
}
else
{
- this->GetGeometry2D(0)->Print(os, indent);
+ this->GetPlaneGeometry(0)->Print(os, indent);
}
}
void
-mitk::SlicedGeometry3D::ExecuteOperation(Operation* operation)
+ mitk::SlicedGeometry3D::ExecuteOperation(Operation* operation)
{
switch ( operation->GetOperationType() )
{
case OpNOTHING:
break;
case OpROTATE:
if ( m_EvenlySpaced )
{
// Need a reference frame to align the rotation
if ( m_ReferenceGeometry )
{
// Clear all generated geometries and then rotate only the first slice.
// The other slices will be re-generated on demand
// Save first slice
- Geometry2D::Pointer geometry2D = m_Geometry2Ds[0];
+ PlaneGeometry::Pointer geometry2D = m_PlaneGeometries[0];
RotationOperation *rotOp = dynamic_cast< RotationOperation * >( operation );
// Generate a RotationOperation using the dataset center instead of
// the supplied rotation center. This is necessary so that the rotated
// zero-plane does not shift away. The supplied center is instead used
// to adjust the slice stack afterwards.
Point3D center = m_ReferenceGeometry->GetCenter();
RotationOperation centeredRotation(
rotOp->GetOperationType(),
center,
rotOp->GetVectorOfRotation(),
rotOp->GetAngleOfRotation()
- );
+ );
// Rotate first slice
geometry2D->ExecuteOperation( &centeredRotation );
// Clear the slice stack and adjust it according to the center of
// the dataset and the supplied rotation center (see documentation of
// ReinitializePlanes)
this->ReinitializePlanes( center, rotOp->GetCenterOfRotation() );
geometry2D->SetSpacing(this->GetSpacing());
if ( m_SliceNavigationController )
{
m_SliceNavigationController->SelectSliceByPoint(
rotOp->GetCenterOfRotation() );
m_SliceNavigationController->AdjustSliceStepperRange();
}
- Geometry3D::ExecuteOperation( &centeredRotation );
+ BaseGeometry::ExecuteOperation( &centeredRotation );
}
else
{
// we also have to consider the case, that there is no reference geometry available.
- if ( m_Geometry2Ds.size() > 0 )
+ if ( m_PlaneGeometries.size() > 0 )
{
- // Reach through to all slices in my container
- for (std::vector<Geometry2D::Pointer>::iterator iter = m_Geometry2Ds.begin();
- iter != m_Geometry2Ds.end();
- ++iter)
- {
- // Test for empty slices, which can happen if evenly spaced geometry
- if ((*iter).IsNotNull())
- {
- (*iter)->ExecuteOperation(operation);
- }
- }
+ // Reach through to all slices in my container
+ for (std::vector<PlaneGeometry::Pointer>::iterator iter = m_PlaneGeometries.begin();
+ iter != m_PlaneGeometries.end();
+ ++iter)
+ {
+ // Test for empty slices, which can happen if evenly spaced geometry
+ if ((*iter).IsNotNull())
+ {
+ (*iter)->ExecuteOperation(operation);
+ }
+ }
// rotate overall geometry
RotationOperation *rotOp = dynamic_cast< RotationOperation * >( operation );
- Geometry3D::ExecuteOperation( rotOp);
+ BaseGeometry::ExecuteOperation( rotOp);
}
-
}
}
else
{
// Reach through to all slices
- for (std::vector<Geometry2D::Pointer>::iterator iter = m_Geometry2Ds.begin();
- iter != m_Geometry2Ds.end();
- ++iter)
+ for (std::vector<PlaneGeometry::Pointer>::iterator iter = m_PlaneGeometries.begin();
+ iter != m_PlaneGeometries.end();
+ ++iter)
{
(*iter)->ExecuteOperation(operation);
}
}
break;
case OpORIENT:
if ( m_EvenlySpaced )
{
- // get operation data
+ // get operation data
PlaneOperation *planeOp = dynamic_cast< PlaneOperation * >( operation );
// Get first slice
- Geometry2D::Pointer geometry2D = m_Geometry2Ds[0];
+ PlaneGeometry::Pointer geometry2D = m_PlaneGeometries[0];
PlaneGeometry *planeGeometry = dynamic_cast< PlaneGeometry * >(
geometry2D.GetPointer() );
// Need a PlaneGeometry, a PlaneOperation and a reference frame to
// carry out the re-orientation. If not all avaialble, stop here
if ( !m_ReferenceGeometry || !planeGeometry || !planeOp )
{
- break;
+ break;
}
// General Behavior:
// Clear all generated geometries and then rotate only the first slice.
// The other slices will be re-generated on demand
//
// 1st Step: Reorient Normal Vector of first plane
//
Point3D center = planeOp->GetPoint(); //m_ReferenceGeometry->GetCenter();
mitk::Vector3D currentNormal = planeGeometry->GetNormal();
mitk::Vector3D newNormal;
if (planeOp->AreAxisDefined())
{
- // If planeOp was defined by one centerpoint and two axis vectors
- newNormal = CrossProduct(planeOp->GetAxisVec0(), planeOp->GetAxisVec1());
+ // If planeOp was defined by one centerpoint and two axis vectors
+ newNormal = CrossProduct(planeOp->GetAxisVec0(), planeOp->GetAxisVec1());
}
else
{
- // If planeOp was defined by one centerpoint and one normal vector
- newNormal = planeOp->GetNormal();
+ // If planeOp was defined by one centerpoint and one normal vector
+ newNormal = planeOp->GetNormal();
}
// Get Rotation axis und angle
currentNormal.Normalize();
newNormal.Normalize();
ScalarType rotationAngle = angle(currentNormal.GetVnlVector(),newNormal.GetVnlVector());
rotationAngle *= 180.0 / vnl_math::pi; // from rad to deg
Vector3D rotationAxis = itk::CrossProduct( currentNormal, newNormal );
if (std::abs(rotationAngle-180) < mitk::eps )
{
- // current Normal and desired normal are not linear independent!!(e.g 1,0,0 and -1,0,0).
- // Rotation Axis should be ANY vector that is 90� to current Normal
- mitk::Vector3D helpNormal;
- helpNormal = currentNormal;
- helpNormal[0] += 1;
- helpNormal[1] -= 1;
- helpNormal[2] += 1;
- helpNormal.Normalize();
- rotationAxis = itk::CrossProduct( helpNormal, currentNormal );
+ // current Normal and desired normal are not linear independent!!(e.g 1,0,0 and -1,0,0).
+ // Rotation Axis should be ANY vector that is 90� to current Normal
+ mitk::Vector3D helpNormal;
+ helpNormal = currentNormal;
+ helpNormal[0] += 1;
+ helpNormal[1] -= 1;
+ helpNormal[2] += 1;
+ helpNormal.Normalize();
+ rotationAxis = itk::CrossProduct( helpNormal, currentNormal );
}
RotationOperation centeredRotation(
- mitk::OpROTATE,
- center,
- rotationAxis,
- rotationAngle
- );
+ mitk::OpROTATE,
+ center,
+ rotationAxis,
+ rotationAngle
+ );
// Rotate first slice
geometry2D->ExecuteOperation( &centeredRotation );
// Reinitialize planes and select slice, if my rotations are all done.
if (!planeOp->AreAxisDefined())
{
- // Clear the slice stack and adjust it according to the center of
- // rotation and plane position (see documentation of ReinitializePlanes)
- this->ReinitializePlanes( center, planeOp->GetPoint() );
-
- if ( m_SliceNavigationController )
- {
- m_SliceNavigationController->SelectSliceByPoint( planeOp->GetPoint() );
- m_SliceNavigationController->AdjustSliceStepperRange();
- }
+ // Clear the slice stack and adjust it according to the center of
+ // rotation and plane position (see documentation of ReinitializePlanes)
+ this->ReinitializePlanes( center, planeOp->GetPoint() );
+
+ if ( m_SliceNavigationController )
+ {
+ m_SliceNavigationController->SelectSliceByPoint( planeOp->GetPoint() );
+ m_SliceNavigationController->AdjustSliceStepperRange();
+ }
}
// Also apply rotation on the slicedGeometry - Geometry3D (Bounding geometry)
- Geometry3D::ExecuteOperation( &centeredRotation );
+ BaseGeometry::ExecuteOperation( &centeredRotation );
//
// 2nd step. If axis vectors were defined, rotate the plane around its normal to fit these
//
if (planeOp->AreAxisDefined())
{
- mitk::Vector3D vecAxixNew = planeOp->GetAxisVec0();
- vecAxixNew.Normalize();
- mitk::Vector3D VecAxisCurr = geometry2D->GetAxisVector(0);
- VecAxisCurr.Normalize();
-
- ScalarType rotationAngle = angle(VecAxisCurr.GetVnlVector(),vecAxixNew.GetVnlVector());
- rotationAngle = rotationAngle * 180 / PI; // Rad to Deg
-
- // we rotate around the normal of the plane, but we do not know, if we need to rotate clockwise
- // or anti-clockwise. So we rotate around the crossproduct of old and new Axisvector.
- // Since both axis vectors lie in the plane, the crossproduct is the planes normal or the negative planes normal
-
- rotationAxis = itk::CrossProduct( VecAxisCurr, vecAxixNew );
- if (std::abs(rotationAngle-180) < mitk::eps )
- {
- // current axisVec and desired axisVec are not linear independent!!(e.g 1,0,0 and -1,0,0).
- // Rotation Axis can be just plane Normal. (have to rotate by 180�)
- rotationAxis = newNormal;
- }
-
- // Perfom Rotation
- mitk::RotationOperation op(mitk::OpROTATE, center, rotationAxis, rotationAngle);
- geometry2D->ExecuteOperation( &op );
-
- // Apply changes on first slice to whole slice stack
- this->ReinitializePlanes( center, planeOp->GetPoint() );
-
- if ( m_SliceNavigationController )
- {
- m_SliceNavigationController->SelectSliceByPoint( planeOp->GetPoint() );
- m_SliceNavigationController->AdjustSliceStepperRange();
- }
-
- // Also apply rotation on the slicedGeometry - Geometry3D (Bounding geometry)
- Geometry3D::ExecuteOperation( &op );
+ mitk::Vector3D vecAxixNew = planeOp->GetAxisVec0();
+ vecAxixNew.Normalize();
+ mitk::Vector3D VecAxisCurr = geometry2D->GetAxisVector(0);
+ VecAxisCurr.Normalize();
+
+ ScalarType rotationAngle = angle(VecAxisCurr.GetVnlVector(),vecAxixNew.GetVnlVector());
+ rotationAngle = rotationAngle * 180 / PI; // Rad to Deg
+
+ // we rotate around the normal of the plane, but we do not know, if we need to rotate clockwise
+ // or anti-clockwise. So we rotate around the crossproduct of old and new Axisvector.
+ // Since both axis vectors lie in the plane, the crossproduct is the planes normal or the negative planes normal
+
+ rotationAxis = itk::CrossProduct( VecAxisCurr, vecAxixNew );
+ if (std::abs(rotationAngle-180) < mitk::eps )
+ {
+ // current axisVec and desired axisVec are not linear independent!!(e.g 1,0,0 and -1,0,0).
+ // Rotation Axis can be just plane Normal. (have to rotate by 180�)
+ rotationAxis = newNormal;
+ }
+
+ // Perfom Rotation
+ mitk::RotationOperation op(mitk::OpROTATE, center, rotationAxis, rotationAngle);
+ geometry2D->ExecuteOperation( &op );
+
+ // Apply changes on first slice to whole slice stack
+ this->ReinitializePlanes( center, planeOp->GetPoint() );
+
+ if ( m_SliceNavigationController )
+ {
+ m_SliceNavigationController->SelectSliceByPoint( planeOp->GetPoint() );
+ m_SliceNavigationController->AdjustSliceStepperRange();
+ }
+
+ // Also apply rotation on the slicedGeometry - Geometry3D (Bounding geometry)
+ BaseGeometry::ExecuteOperation( &op );
}
}
else
{
// Reach through to all slices
- for (std::vector<Geometry2D::Pointer>::iterator iter = m_Geometry2Ds.begin();
- iter != m_Geometry2Ds.end();
- ++iter)
+ for (std::vector<PlaneGeometry::Pointer>::iterator iter = m_PlaneGeometries.begin();
+ iter != m_PlaneGeometries.end();
+ ++iter)
{
(*iter)->ExecuteOperation(operation);
}
}
break;
case OpRESTOREPLANEPOSITION:
if ( m_EvenlySpaced )
{
// Save first slice
- Geometry2D::Pointer geometry2D = m_Geometry2Ds[0];
+ PlaneGeometry::Pointer geometry2D = m_PlaneGeometries[0];
PlaneGeometry* planeGeometry = dynamic_cast< PlaneGeometry * >(
geometry2D.GetPointer() );
RestorePlanePositionOperation *restorePlaneOp = dynamic_cast< RestorePlanePositionOperation* >( operation );
// Need a PlaneGeometry, a PlaneOperation and a reference frame to
// carry out the re-orientation
if ( m_ReferenceGeometry && planeGeometry && restorePlaneOp )
{
// Clear all generated geometries and then rotate only the first slice.
// The other slices will be re-generated on demand
// Rotate first slice
geometry2D->ExecuteOperation( restorePlaneOp );
m_DirectionVector = restorePlaneOp->GetDirectionVector();
double centerOfRotationDistance =
planeGeometry->SignedDistanceFromPlane( m_ReferenceGeometry->GetCenter() );
if ( centerOfRotationDistance > 0 )
{
m_DirectionVector = m_DirectionVector;
}
else
{
m_DirectionVector = -m_DirectionVector;
}
Vector3D spacing = restorePlaneOp->GetSpacing();
Superclass::SetSpacing( spacing );
// /*Now we need to calculate the number of slices in the plane's normal
// direction, so that the entire volume is covered. This is done by first
// calculating the dot product between the volume diagonal (the maximum
// distance inside the volume) and the normal, and dividing this value by
// the directed spacing calculated above.*/
ScalarType directedExtent =
std::abs( m_ReferenceGeometry->GetExtentInMM( 0 ) * m_DirectionVector[0] )
+ std::abs( m_ReferenceGeometry->GetExtentInMM( 1 ) * m_DirectionVector[1] )
+ std::abs( m_ReferenceGeometry->GetExtentInMM( 2 ) * m_DirectionVector[2] );
if ( directedExtent >= spacing[2] )
{
m_Slices = static_cast< unsigned int >(directedExtent / spacing[2] + 0.5);
}
else
{
m_Slices = 1;
}
- m_Geometry2Ds.assign( m_Slices, Geometry2D::Pointer( NULL ) );
+ m_PlaneGeometries.assign( m_Slices, PlaneGeometry::Pointer( NULL ) );
- if ( m_Slices > 0 )
- {
- m_Geometry2Ds[0] = geometry2D;
- }
+ if ( m_Slices > 0 )
+ {
+ m_PlaneGeometries[0] = geometry2D;
+ }
m_SliceNavigationController->GetSlice()->SetSteps( m_Slices );
this->Modified();
//End Reinitialization
if ( m_SliceNavigationController )
{
m_SliceNavigationController->GetSlice()->SetPos( restorePlaneOp->GetPos() );
m_SliceNavigationController->AdjustSliceStepperRange();
}
- Geometry3D::ExecuteOperation(restorePlaneOp);
+ BaseGeometry::ExecuteOperation(restorePlaneOp);
}
}
else
{
// Reach through to all slices
- for (std::vector<Geometry2D::Pointer>::iterator iter = m_Geometry2Ds.begin();
- iter != m_Geometry2Ds.end();
- ++iter)
+ for (std::vector<PlaneGeometry::Pointer>::iterator iter = m_PlaneGeometries.begin();
+ iter != m_PlaneGeometries.end();
+ ++iter)
{
(*iter)->ExecuteOperation(operation);
}
}
break;
case OpAPPLYTRANSFORMMATRIX:
// Clear all generated geometries and then transform only the first slice.
// The other slices will be re-generated on demand
// Save first slice
- Geometry2D::Pointer geometry2D = m_Geometry2Ds[0];
+ PlaneGeometry::Pointer geometry2D = m_PlaneGeometries[0];
ApplyTransformMatrixOperation *applyMatrixOp = dynamic_cast< ApplyTransformMatrixOperation* >( operation );
// Apply transformation to first plane
geometry2D->ExecuteOperation( applyMatrixOp );
// Generate a ApplyTransformMatrixOperation using the dataset center instead of
// the supplied rotation center. The supplied center is instead used to adjust the
// slice stack afterwards (see OpROTATE).
Point3D center = m_ReferenceGeometry->GetCenter();
// Clear the slice stack and adjust it according to the center of
// the dataset and the supplied rotation center (see documentation of
// ReinitializePlanes)
this->ReinitializePlanes( center, applyMatrixOp->GetReferencePoint() );
- Geometry3D::ExecuteOperation( applyMatrixOp );
+ BaseGeometry::ExecuteOperation( applyMatrixOp );
break;
}
this->Modified();
}
-
diff --git a/Core/Code/DataManagement/mitkSlicedGeometry3D.h b/Core/Code/DataManagement/mitkSlicedGeometry3D.h
index 34c4810e80..029392ef81 100644
--- a/Core/Code/DataManagement/mitkSlicedGeometry3D.h
+++ b/Core/Code/DataManagement/mitkSlicedGeometry3D.h
@@ -1,325 +1,321 @@
/*===================================================================
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 MITKSLICEDGEOMETRY3D_H_HEADER_INCLUDED_C1EBD0AD
#define MITKSLICEDGEOMETRY3D_H_HEADER_INCLUDED_C1EBD0AD
-#include "mitkGeometry3D.h"
+#include "mitkBaseGeometry.h"
#include "mitkPlaneGeometry.h"
namespace mitk {
-
-class SliceNavigationController;
-class NavigationController;
-
-/** \brief Describes the geometry of a data object consisting of slices.
- *
- * A Geometry2D can be requested for each slice. In the case of
- * \em evenly-spaced, \em plane geometries (m_EvenlySpaced==true),
- * only the 2D-geometry of the first slice has to be set (to an instance of
- * PlaneGeometry). The 2D geometries of the other slices are calculated
- * by shifting the first slice in the direction m_DirectionVector by
- * m_Spacing.z * sliceNumber. The m_Spacing member (which is only
- * relevant in the case m_EvenlySpaced==true) descibes the size of a voxel
- * (in mm), i.e., m_Spacing.x is the voxel width in the x-direction of the
- * plane. It is derived from the reference geometry of this SlicedGeometry3D,
- * which usually would be the global geometry describing how datasets are to
- * be resliced.
- *
- * By default, slices are oriented in the direction of one of the main axes
- * (x, y, z). However, by means of rotation, it is possible to realign the
- * slices in any possible direction. In case of an inclined plane, the spacing
- * is derived as a product of the (regular) geometry spacing and the direction
- * vector of the plane.
- *
- * SlicedGeometry3D and the associated Geometry2Ds have to be initialized in
- * the method GenerateOutputInformation() of BaseProcess (or CopyInformation /
- * UpdateOutputInformation of BaseData, if possible, e.g., by analyzing pic
- * tags in Image) subclasses. See also
- *
- * \sa itk::ProcessObject::GenerateOutputInformation(),
- * \sa itk::DataObject::CopyInformation() and
- * \a itk::DataObject::UpdateOutputInformation().
- *
- * Rule: everything is in mm (or ms for temporal information) if not
- * stated otherwise.
- *
- * \warning The hull (i.e., transform, bounding-box and
- * time-bounds) is only guaranteed to be up-to-date after calling
- * UpdateInformation().
- *
- * \ingroup Geometry
- */
-class MITK_CORE_EXPORT SlicedGeometry3D : public mitk::Geometry3D
-{
-public:
- mitkClassMacro(SlicedGeometry3D, Geometry3D);
-
- /** Method for creation through the object factory. */
- itkFactorylessNewMacro(Self)
- itkCloneMacro(Self)
-
- /**
- * \brief Returns the Geometry2D of the slice (\a s).
- *
- * If (a) m_EvenlySpaced==true, (b) we don't have a Geometry2D stored
- * for the requested slice, and (c) the first slice (s=0)
- * is a PlaneGeometry instance, then we calculate the geometry of the
- * requested as the plane of the first slice shifted by m_Spacing[3]*s
- * in the direction of m_DirectionVector.
- *
- * \warning The Geometry2Ds are not necessarily up-to-date and not even
- * initialized.
- *
- * The Geometry2Ds have to be initialized in the method
- * GenerateOutputInformation() of BaseProcess (or CopyInformation /
- * UpdateOutputInformation of BaseData, if possible, e.g., by analyzing
- * pic tags in Image) subclasses. See also
- *
- * \sa itk::ProcessObject::GenerateOutputInformation(),
- * \sa itk::DataObject::CopyInformation() and
- * \sa itk::DataObject::UpdateOutputInformation().
- */
- virtual mitk::Geometry2D* GetGeometry2D( int s ) const;
-
-
- /**
- * \brief Set Geometry2D of slice \a s.
- */
- virtual bool SetGeometry2D( mitk::Geometry2D *geometry2D, int s );
-
- //##Documentation
- //## @brief When switching from an Image Geometry to a normal Geometry (and the other way around), you have to change the origin as well (See Geometry Documentation)! This function will change the "isImageGeometry" bool flag and changes the origin respectively.
- virtual void ChangeImageGeometryConsideringOriginOffset( const bool isAnImageGeometry );
-
- virtual void SetTimeBounds( const mitk::TimeBounds& timebounds );
-
-
- virtual const mitk::BoundingBox* GetBoundingBox() const;
-
- /**
- * \brief Get the number of slices
- */
- itkGetConstMacro( Slices, unsigned int );
-
-
- /**
- * \brief Check whether a slice exists
- */
- virtual bool IsValidSlice( int s = 0 ) const;
-
- virtual void SetReferenceGeometry( Geometry3D *referenceGeometry );
-
- /**
- * \brief Set the spacing (m_Spacing), in direction of the plane normal.
- *
- * INTERNAL METHOD.
- */
- virtual void SetSpacing( const mitk::Vector3D &aSpacing );
-
- /**
- * \brief Set the SliceNavigationController corresponding to this sliced
- * geometry.
- *
- * The SNC needs to be informed when the number of slices in the geometry
- * changes, which can occur whenthe slices are re-oriented by rotation.
- */
- virtual void SetSliceNavigationController(
- mitk::SliceNavigationController *snc );
- mitk::SliceNavigationController *GetSliceNavigationController();
-
- /**
- * \brief Set/Get whether the SlicedGeometry3D is evenly-spaced
- * (m_EvenlySpaced)
- *
- * If (a) m_EvenlySpaced==true, (b) we don't have a Geometry2D stored for
- * the requested slice, and (c) the first slice (s=0) is a PlaneGeometry
- * instance, then we calculate the geometry of the requested as the plane
- * of the first slice shifted by m_Spacing.z * s in the direction of
- * m_DirectionVector.
- *
- * \sa GetGeometry2D
- */
- itkGetConstMacro(EvenlySpaced, bool);
-
- virtual void SetEvenlySpaced(bool on = true);
-
- /**
- * \brief Set/Get the vector between slices for the evenly-spaced case
- * (m_EvenlySpaced==true).
- *
- * If the direction-vector is (0,0,0) (the default) and the first
- * 2D geometry is a PlaneGeometry, then the direction-vector will be
- * calculated from the plane normal.
- *
- * \sa m_DirectionVector
- */
- virtual void SetDirectionVector(const mitk::Vector3D& directionVector);
- itkGetConstMacro(DirectionVector, const mitk::Vector3D&);
-
- virtual itk::LightObject::Pointer InternalClone() const;
-
- static const std::string SLICES;
- const static std::string DIRECTION_VECTOR;
- const static std::string EVENLY_SPACED;
-
- /**
- * \brief Tell this instance how many Geometry2Ds it shall manage. Bounding
- * box and the Geometry2Ds must be set additionally by calling the respective
- * methods!
- *
- * \warning Bounding box and the 2D-geometries must be set additionally: use
- * SetBounds(), SetGeometry().
- */
- virtual void InitializeSlicedGeometry( unsigned int slices );
-
- /**
- * \brief Completely initialize this instance as evenly-spaced with slices
- * parallel to the provided Geometry2D that is used as the first slice and
- * for spacing calculation.
- *
- * Initializes the bounding box according to the width/height of the
- * Geometry2D and \a slices. The spacing is calculated from the Geometry2D.
- */
- virtual void InitializeEvenlySpaced( mitk::Geometry2D *geometry2D,
- unsigned int slices, bool flipped=false );
-
- /**
- * \brief Completely initialize this instance as evenly-spaced with slices
- * parallel to the provided Geometry2D that is used as the first slice and
- * for spacing calculation (except z-spacing).
- *
- * Initializes the bounding box according to the width/height of the
- * Geometry2D and \a slices. The x-/y-spacing is calculated from the
- * Geometry2D.
- */
- virtual void InitializeEvenlySpaced( mitk::Geometry2D *geometry2D,
- mitk::ScalarType zSpacing, unsigned int slices, bool flipped=false );
-
- /**
- * \brief Completely initialize this instance as evenly-spaced plane slices
- * parallel to a side of the provided Geometry3D and using its spacing
- * information.
- *
- * Initializes the bounding box according to the width/height of the
- * Geometry3D and the number of slices according to
- * Geometry3D::GetExtent(2).
- *
- * \param planeorientation side parallel to which the slices will be oriented
- * \param top if \a true, create plane at top, otherwise at bottom
- * (for PlaneOrientation Axial, for other plane locations respectively)
- * \param frontside defines the side of the plane (the definition of
- * front/back is somewhat arbitrary)
- *
- * \param rotate rotates the plane by 180 degree around its normal (the
- * definition of rotated vs not rotated is somewhat arbitrary)
- */
- virtual void InitializePlanes( const mitk::Geometry3D *geometry3D,
- mitk::PlaneGeometry::PlaneOrientation planeorientation, bool top=true,
- bool frontside=true, bool rotated=false );
-
-
- virtual void SetImageGeometry(const bool isAnImageGeometry);
-
- virtual void ExecuteOperation(Operation* operation);
-
- static double CalculateSpacing( const mitk::Vector3D spacing, const mitk::Vector3D &d );
-
-protected:
- SlicedGeometry3D();
-
- SlicedGeometry3D(const SlicedGeometry3D& other);
-
- virtual ~SlicedGeometry3D();
-
-
- /**
- * Reinitialize plane stack after rotation. More precisely, the first plane
- * of the stack needs to spatially aligned, in two respects:
- *
- * 1. Re-alignment with respect to the dataset center; this is necessary
- * since the distance from the first plane to the center could otherwise
- * continuously decrease or increase.
- * 2. Re-alignment with respect to a given reference point; the reference
- * point is a location which the user wants to be exactly touched by one
- * plane of the plane stack. The first plane is minimally shifted to
- * ensure this touching. Usually, the reference point would be the
- * point around which the geometry is rotated.
- */
- virtual void ReinitializePlanes( const Point3D &center,
- const Point3D &referencePoint );
-
-
- ScalarType GetLargestExtent( const Geometry3D *geometry );
-
- void PrintSelf(std::ostream& os, itk::Indent indent) const;
-
- /** Calculate "directed spacing", i.e. the spacing in directions
- * non-orthogonal to the coordinate axes. This is done via the
- * ellipsoid equation.
- */
- double CalculateSpacing( const mitk::Vector3D &direction ) const;
-
-
-
- /** The extent of the slice stack, i.e. the number of slices, depends on the
- * plane normal. For rotated geometries, the geometry's transform needs to
- * be accounted in this calculation.
- */
- mitk::Vector3D AdjustNormal( const mitk::Vector3D &normal ) const;
-
-
- /**
- * Container for the 2D-geometries contained within this SliceGeometry3D.
- */
- mutable std::vector<Geometry2D::Pointer> m_Geometry2Ds;
-
-
- /**
- * If (a) m_EvenlySpaced==true, (b) we don't have a Geometry2D stored
- * for the requested slice, and (c) the first slice (s=0)
- * is a PlaneGeometry instance, then we calculate the geometry of the
- * requested as the plane of the first slice shifted by m_Spacing.z*s
- * in the direction of m_DirectionVector.
- *
- * \sa GetGeometry2D
- */
- bool m_EvenlySpaced;
-
- /**
- * Vector between slices for the evenly-spaced case (m_EvenlySpaced==true).
- * If the direction-vector is (0,0,0) (the default) and the first
- * 2D geometry is a PlaneGeometry, then the direction-vector will be
- * calculated from the plane normal.
- */
- mutable mitk::Vector3D m_DirectionVector;
-
- /** Number of slices this SliceGeometry3D is descibing. */
- unsigned int m_Slices;
-
- /** Underlying Geometry3D for this SlicedGeometry */
- mitk::Geometry3D *m_ReferenceGeometry;
-
- /** SNC correcsponding to this geometry; used to reflect changes in the
- * number of slices due to rotation. */
- //mitk::NavigationController *m_NavigationController;
- mitk::SliceNavigationController *m_SliceNavigationController;
-};
-
+ class SliceNavigationController;
+ class NavigationController;
+
+ /** \brief Describes the geometry of a data object consisting of slices.
+ *
+ * A PlaneGeometry can be requested for each slice. In the case of
+ * \em evenly-spaced, \em plane geometries (m_EvenlySpaced==true),
+ * only the 2D-geometry of the first slice has to be set (to an instance of
+ * PlaneGeometry). The 2D geometries of the other slices are calculated
+ * by shifting the first slice in the direction m_DirectionVector by
+ * m_Spacing.z * sliceNumber. The m_Spacing member (which is only
+ * relevant in the case m_EvenlySpaced==true) descibes the size of a voxel
+ * (in mm), i.e., m_Spacing.x is the voxel width in the x-direction of the
+ * plane. It is derived from the reference geometry of this SlicedGeometry3D,
+ * which usually would be the global geometry describing how datasets are to
+ * be resliced.
+ *
+ * By default, slices are oriented in the direction of one of the main axes
+ * (x, y, z). However, by means of rotation, it is possible to realign the
+ * slices in any possible direction. In case of an inclined plane, the spacing
+ * is derived as a product of the (regular) geometry spacing and the direction
+ * vector of the plane.
+ *
+ * SlicedGeometry3D and the associated PlaneGeometries have to be initialized in
+ * the method GenerateOutputInformation() of BaseProcess (or CopyInformation /
+ * UpdateOutputInformation of BaseData, if possible, e.g., by analyzing pic
+ * tags in Image) subclasses. See also
+ *
+ * \sa itk::ProcessObject::GenerateOutputInformation(),
+ * \sa itk::DataObject::CopyInformation() and
+ * \a itk::DataObject::UpdateOutputInformation().
+ *
+ * Rule: everything is in mm (or ms for temporal information) if not
+ * stated otherwise.
+ *
+ * \warning The hull (i.e., transform, bounding-box and
+ * time-bounds) is only guaranteed to be up-to-date after calling
+ * UpdateInformation().
+ *
+ * \ingroup Geometry
+ */
+ class MITK_CORE_EXPORT SlicedGeometry3D : public mitk::BaseGeometry
+ {
+ public:
+ mitkClassMacro(SlicedGeometry3D, BaseGeometry);
+
+ /** Method for creation through the object factory. */
+ itkFactorylessNewMacro(Self)
+ itkCloneMacro(Self)
+
+ /**
+ * \brief Returns the PlaneGeometry of the slice (\a s).
+ *
+ * If (a) m_EvenlySpaced==true, (b) we don't have a PlaneGeometry stored
+ * for the requested slice, and (c) the first slice (s=0)
+ * is a PlaneGeometry instance, then we calculate the geometry of the
+ * requested as the plane of the first slice shifted by m_Spacing[3]*s
+ * in the direction of m_DirectionVector.
+ *
+ * \warning The PlaneGeometries are not necessarily up-to-date and not even
+ * initialized.
+ *
+ * The PlaneGeometries have to be initialized in the method
+ * GenerateOutputInformation() of BaseProcess (or CopyInformation /
+ * UpdateOutputInformation of BaseData, if possible, e.g., by analyzing
+ * pic tags in Image) subclasses. See also
+ *
+ * \sa itk::ProcessObject::GenerateOutputInformation(),
+ * \sa itk::DataObject::CopyInformation() and
+ * \sa itk::DataObject::UpdateOutputInformation().
+ */
+ virtual mitk::PlaneGeometry* GetPlaneGeometry( int s ) const;
+ /**
+ * \deprecatedSince{2014_06} Please use GetPlaneGeometry
+ */
+ DEPRECATED(const PlaneGeometry* GetGeometry2D(int s){return GetPlaneGeometry(s);};)
+
+ /**
+ * \brief Set PlaneGeometry of slice \a s.
+ */
+ virtual bool SetPlaneGeometry( mitk::PlaneGeometry *geometry2D, int s );
+ /**
+ * \deprecatedSince{2014_06} Please use SetPlaneGeometry
+ */
+ DEPRECATED(void SetGeometry2D(PlaneGeometry* geo, int s){SetPlaneGeometry(geo, s);};)
+
+ //##Documentation
+ //## @brief When switching from an Image Geometry to a normal Geometry (and the other way around), you have to change the origin as well (See Geometry Documentation)! This function will change the "isImageGeometry" bool flag and changes the origin respectively.
+ virtual void ChangeImageGeometryConsideringOriginOffset( const bool isAnImageGeometry );
+
+ //virtual void SetTimeBounds( const mitk::TimeBounds& timebounds );
+ virtual const mitk::BoundingBox* GetBoundingBox() const;
+
+ /**
+ * \brief Get the number of slices
+ */
+ itkGetConstMacro( Slices, unsigned int );
+
+ /**
+ * \brief Check whether a slice exists
+ */
+ virtual bool IsValidSlice( int s = 0 ) const;
+
+ virtual void SetReferenceGeometry( BaseGeometry *referenceGeometry );
+
+ /**
+ * \brief Set the SliceNavigationController corresponding to this sliced
+ * geometry.
+ *
+ * The SNC needs to be informed when the number of slices in the geometry
+ * changes, which can occur whenthe slices are re-oriented by rotation.
+ */
+ virtual void SetSliceNavigationController(
+ mitk::SliceNavigationController *snc );
+ mitk::SliceNavigationController *GetSliceNavigationController();
+
+ /**
+ * \brief Set/Get whether the SlicedGeometry3D is evenly-spaced
+ * (m_EvenlySpaced)
+ *
+ * If (a) m_EvenlySpaced==true, (b) we don't have a PlaneGeometry stored for
+ * the requested slice, and (c) the first slice (s=0) is a PlaneGeometry
+ * instance, then we calculate the geometry of the requested as the plane
+ * of the first slice shifted by m_Spacing.z * s in the direction of
+ * m_DirectionVector.
+ *
+ * \sa GetPlaneGeometry
+ */
+ itkGetConstMacro(EvenlySpaced, bool);
+
+ virtual void SetEvenlySpaced(bool on = true);
+
+ /**
+ * \brief Set/Get the vector between slices for the evenly-spaced case
+ * (m_EvenlySpaced==true).
+ *
+ * If the direction-vector is (0,0,0) (the default) and the first
+ * 2D geometry is a PlaneGeometry, then the direction-vector will be
+ * calculated from the plane normal.
+ *
+ * \sa m_DirectionVector
+ */
+ virtual void SetDirectionVector(const mitk::Vector3D& directionVector);
+ itkGetConstMacro(DirectionVector, const mitk::Vector3D&);
+
+ virtual itk::LightObject::Pointer InternalClone() const;
+
+ static const std::string SLICES;
+ const static std::string DIRECTION_VECTOR;
+ const static std::string EVENLY_SPACED;
+
+ /**
+ * \brief Tell this instance how many PlaneGeometries it shall manage. Bounding
+ * box and the PlaneGeometries must be set additionally by calling the respective
+ * methods!
+ *
+ * \warning Bounding box and the 2D-geometries must be set additionally: use
+ * SetBounds(), SetGeometry().
+ */
+ virtual void InitializeSlicedGeometry( unsigned int slices );
+
+ /**
+ * \brief Completely initialize this instance as evenly-spaced with slices
+ * parallel to the provided PlaneGeometry that is used as the first slice and
+ * for spacing calculation.
+ *
+ * Initializes the bounding box according to the width/height of the
+ * PlaneGeometry and \a slices. The spacing is calculated from the PlaneGeometry.
+ */
+ virtual void InitializeEvenlySpaced( mitk::PlaneGeometry *geometry2D,
+ unsigned int slices, bool flipped=false );
+
+ /**
+ * \brief Completely initialize this instance as evenly-spaced with slices
+ * parallel to the provided PlaneGeometry that is used as the first slice and
+ * for spacing calculation (except z-spacing).
+ *
+ * Initializes the bounding box according to the width/height of the
+ * PlaneGeometry and \a slices. The x-/y-spacing is calculated from the
+ * PlaneGeometry.
+ */
+ virtual void InitializeEvenlySpaced( mitk::PlaneGeometry *geometry2D,
+ mitk::ScalarType zSpacing, unsigned int slices, bool flipped=false );
+
+ /**
+ * \brief Completely initialize this instance as evenly-spaced plane slices
+ * parallel to a side of the provided BaseGeometry and using its spacing
+ * information.
+ *
+ * Initializes the bounding box according to the width/height of the
+ * BaseGeometry and the number of slices according to
+ * BaseGeometry::GetExtent(2).
+ *
+ * \param planeorientation side parallel to which the slices will be oriented
+ * \param top if \a true, create plane at top, otherwise at bottom
+ * (for PlaneOrientation Axial, for other plane locations respectively)
+ * \param frontside defines the side of the plane (the definition of
+ * front/back is somewhat arbitrary)
+ *
+ * \param rotate rotates the plane by 180 degree around its normal (the
+ * definition of rotated vs not rotated is somewhat arbitrary)
+ */
+ virtual void InitializePlanes( const mitk::BaseGeometry *geometry3D,
+ mitk::PlaneGeometry::PlaneOrientation planeorientation, bool top=true,
+ bool frontside=true, bool rotated=false );
+
+ virtual void SetImageGeometry(const bool isAnImageGeometry);
+
+ virtual void ExecuteOperation(Operation* operation);
+
+ static double CalculateSpacing( const mitk::Vector3D spacing, const mitk::Vector3D &d );
+
+ protected:
+ SlicedGeometry3D();
+
+ SlicedGeometry3D(const SlicedGeometry3D& other);
+
+ virtual ~SlicedGeometry3D();
+
+ /**
+ * Reinitialize plane stack after rotation. More precisely, the first plane
+ * of the stack needs to spatially aligned, in two respects:
+ *
+ * 1. Re-alignment with respect to the dataset center; this is necessary
+ * since the distance from the first plane to the center could otherwise
+ * continuously decrease or increase.
+ * 2. Re-alignment with respect to a given reference point; the reference
+ * point is a location which the user wants to be exactly touched by one
+ * plane of the plane stack. The first plane is minimally shifted to
+ * ensure this touching. Usually, the reference point would be the
+ * point around which the geometry is rotated.
+ */
+ virtual void ReinitializePlanes( const Point3D &center,
+ const Point3D &referencePoint );
+
+ ScalarType GetLargestExtent( const BaseGeometry *geometry );
+
+ void PrintSelf(std::ostream& os, itk::Indent indent) const;
+
+ /** Calculate "directed spacing", i.e. the spacing in directions
+ * non-orthogonal to the coordinate axes. This is done via the
+ * ellipsoid equation.
+ */
+ double CalculateSpacing( const mitk::Vector3D &direction ) const;
+
+ /** The extent of the slice stack, i.e. the number of slices, depends on the
+ * plane normal. For rotated geometries, the geometry's transform needs to
+ * be accounted in this calculation.
+ */
+ mitk::Vector3D AdjustNormal( const mitk::Vector3D &normal ) const;
+
+ /**
+ * Container for the 2D-geometries contained within this SliceGeometry3D.
+ */
+ mutable std::vector<PlaneGeometry::Pointer> m_PlaneGeometries;
+
+ /**
+ * If (a) m_EvenlySpaced==true, (b) we don't have a PlaneGeometry stored
+ * for the requested slice, and (c) the first slice (s=0)
+ * is a PlaneGeometry instance, then we calculate the geometry of the
+ * requested as the plane of the first slice shifted by m_Spacing.z*s
+ * in the direction of m_DirectionVector.
+ *
+ * \sa GetPlaneGeometry
+ */
+ bool m_EvenlySpaced;
+
+ /**
+ * Vector between slices for the evenly-spaced case (m_EvenlySpaced==true).
+ * If the direction-vector is (0,0,0) (the default) and the first
+ * 2D geometry is a PlaneGeometry, then the direction-vector will be
+ * calculated from the plane normal.
+ */
+ mutable mitk::Vector3D m_DirectionVector;
+
+ /** Number of slices this SliceGeometry3D is descibing. */
+ unsigned int m_Slices;
+
+ /** Underlying BaseGeometry for this SlicedGeometry */
+ mitk::BaseGeometry *m_ReferenceGeometry;
+
+ /** SNC correcsponding to this geometry; used to reflect changes in the
+ * number of slices due to rotation. */
+ //mitk::NavigationController *m_NavigationController;
+ mitk::SliceNavigationController *m_SliceNavigationController;
+ private:
+
+ virtual void PreSetBounds(const BoundsArrayType& bounds){};
+
+ /**
+ * \brief Set the spacing (m_Spacing), in direction of the plane normal.
+ *
+ */
+ virtual void PreSetSpacing( const mitk::Vector3D &aSpacing );
+ };
} // namespace mitk
#endif /* MITKSLICEDGEOMETRY3D_H_HEADER_INCLUDED_C1EBD0AD */
diff --git a/Core/Code/DataManagement/mitkSurface.cpp b/Core/Code/DataManagement/mitkSurface.cpp
index 87d8b21755..27a0341c17 100644
--- a/Core/Code/DataManagement/mitkSurface.cpp
+++ b/Core/Code/DataManagement/mitkSurface.cpp
@@ -1,530 +1,530 @@
/*===================================================================
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 "mitkSurface.h"
#include "mitkInteractionConst.h"
#include "mitkSurfaceOperation.h"
#include <algorithm>
#include <vtkPolyData.h>
static vtkPolyData* DeepCopy(vtkPolyData* other)
{
if (other == NULL)
return NULL;
vtkPolyData* copy = vtkPolyData::New();
copy->DeepCopy(other);
return copy;
}
static void Delete(vtkPolyData* polyData)
{
if (polyData != NULL)
polyData->Delete();
}
static void Update(vtkPolyData* /*polyData*/)
{
// if (polyData != NULL)
// polyData->Update(); //VTK6_TODO vtk pipeline
}
mitk::Surface::Surface()
: m_CalculateBoundingBox(false)
{
this->InitializeEmpty();
}
mitk::Surface::Surface(const mitk::Surface& other)
: BaseData(other),
m_LargestPossibleRegion(other.m_LargestPossibleRegion),
m_RequestedRegion(other.m_RequestedRegion),
m_CalculateBoundingBox(other.m_CalculateBoundingBox)
{
if(!other.m_PolyDatas.empty())
{
m_PolyDatas.resize(other.m_PolyDatas.size());
std::transform(other.m_PolyDatas.begin(), other.m_PolyDatas.end(), m_PolyDatas.begin(), DeepCopy);
}
else
{
this->InitializeEmpty();
}
}
void mitk::Surface::Swap(mitk::Surface& other)
{
std::swap(m_PolyDatas, other.m_PolyDatas);
std::swap(m_LargestPossibleRegion, other.m_LargestPossibleRegion);
std::swap(m_RequestedRegion, other.m_RequestedRegion);
std::swap(m_CalculateBoundingBox, other.m_CalculateBoundingBox);
}
mitk::Surface& mitk::Surface::operator=(Surface other)
{
this->Swap(other);
return *this;
}
mitk::Surface::~Surface()
{
this->ClearData();
}
void mitk::Surface::ClearData()
{
using ::Delete;
std::for_each(m_PolyDatas.begin(), m_PolyDatas.end(), Delete);
m_PolyDatas.clear();
Superclass::ClearData();
}
const mitk::Surface::RegionType& mitk::Surface::GetLargestPossibleRegion() const
{
m_LargestPossibleRegion.SetIndex(3, 0);
m_LargestPossibleRegion.SetSize(3, GetTimeGeometry()->CountTimeSteps());
return m_LargestPossibleRegion;
}
const mitk::Surface::RegionType& mitk::Surface::GetRequestedRegion() const
{
return m_RequestedRegion;
}
void mitk::Surface::InitializeEmpty()
{
if (!m_PolyDatas.empty())
this->ClearData();
Superclass::InitializeTimeGeometry();
m_PolyDatas.push_back(NULL);
m_Initialized = true;
}
void mitk::Surface::SetVtkPolyData(vtkPolyData* polyData, unsigned int t)
{
this->Expand(t + 1);
if (m_PolyDatas[t] != NULL)
{
if (m_PolyDatas[t] == polyData)
return;
m_PolyDatas[t]->Delete();
}
m_PolyDatas[t] = polyData;
if(polyData != NULL)
polyData->Register(NULL);
m_CalculateBoundingBox = true;
this->Modified();
this->UpdateOutputInformation();
}
bool mitk::Surface::IsEmptyTimeStep(unsigned int t) const
{
if(!IsInitialized())
return false;
vtkPolyData* polyData = const_cast<Surface*>(this)->GetVtkPolyData(t);
return polyData == NULL || (
polyData->GetNumberOfLines() == 0 &&
polyData->GetNumberOfPolys() == 0 &&
polyData->GetNumberOfStrips() == 0 &&
polyData->GetNumberOfVerts() == 0
);
}
vtkPolyData* mitk::Surface::GetVtkPolyData(unsigned int t)
{
if (t < m_PolyDatas.size())
{
if(m_PolyDatas[t] == NULL && this->GetSource().IsNotNull())
{
RegionType requestedRegion;
requestedRegion.SetIndex(3, t);
requestedRegion.SetSize(3, 1);
this->SetRequestedRegion(&requestedRegion);
this->GetSource()->Update();
}
return m_PolyDatas[t];
}
return NULL;
}
void mitk::Surface::UpdateOutputInformation()
{
if (this->GetSource().IsNotNull())
this->GetSource()->UpdateOutputInformation();
if (m_CalculateBoundingBox == true && !m_PolyDatas.empty())
this->CalculateBoundingBox();
else
this->GetTimeGeometry()->Update();
}
void mitk::Surface::CalculateBoundingBox()
{
TimeGeometry* timeGeometry = this->GetTimeGeometry();
if (timeGeometry->CountTimeSteps() != m_PolyDatas.size())
mitkThrow() << "Number of geometry time steps is inconsistent with number of poly data pointers.";
for (unsigned int i = 0; i < m_PolyDatas.size(); ++i)
{
vtkPolyData* polyData = m_PolyDatas[i];
double bounds[6] = {0};
if (polyData != NULL && polyData->GetNumberOfPoints() > 0)
{
// polyData->Update(); //VTK6_TODO vtk pipeline
polyData->ComputeBounds();
polyData->GetBounds(bounds);
}
- Geometry3D::Pointer geometry = timeGeometry->GetGeometryForTimeStep(i);
+ BaseGeometry::Pointer geometry = timeGeometry->GetGeometryForTimeStep(i);
if (geometry.IsNull())
mitkThrow() << "Time-sliced geometry is invalid (equals NULL).";
geometry->SetFloatBounds(bounds);
}
timeGeometry->Update();
m_CalculateBoundingBox = false;
}
void mitk::Surface::SetRequestedRegionToLargestPossibleRegion()
{
m_RequestedRegion = GetLargestPossibleRegion();
}
bool mitk::Surface::RequestedRegionIsOutsideOfTheBufferedRegion()
{
RegionType::IndexValueType end = m_RequestedRegion.GetIndex(3) + m_RequestedRegion.GetSize(3);
if(static_cast<RegionType::IndexValueType>(m_PolyDatas.size()) < end)
return true;
for(RegionType::IndexValueType t = m_RequestedRegion.GetIndex(3); t < end; ++t)
{
if(m_PolyDatas[t] == NULL)
return true;
}
return false;
}
bool mitk::Surface::VerifyRequestedRegion()
{
if(m_RequestedRegion.GetIndex(3) >= 0 && m_RequestedRegion.GetIndex(3) + m_RequestedRegion.GetSize(3) <= m_PolyDatas.size())
return true;
return false;
}
void mitk::Surface::SetRequestedRegion(const itk::DataObject* data )
{
const mitk::Surface *surface = dynamic_cast<const mitk::Surface*>(data);
if (surface != NULL)
m_RequestedRegion = surface->GetRequestedRegion();
else
mitkThrow() << "Data object used to get requested region is not a mitk::Surface.";
}
void mitk::Surface::SetRequestedRegion(Surface::RegionType* region)
{
if (region == NULL)
mitkThrow() << "Requested region is invalid (equals NULL)";
m_RequestedRegion = *region;
}
void mitk::Surface::CopyInformation(const itk::DataObject* data)
{
Superclass::CopyInformation(data);
const mitk::Surface* surface = dynamic_cast<const mitk::Surface*>(data);
if (surface == NULL)
mitkThrow() << "Data object used to get largest possible region is not a mitk::Surface.";
m_LargestPossibleRegion = surface->GetLargestPossibleRegion();
}
void mitk::Surface::Update()
{
using ::Update;
if (this->GetSource().IsNull())
std::for_each(m_PolyDatas.begin(), m_PolyDatas.end(), Update);
Superclass::Update();
}
void mitk::Surface::Expand(unsigned int timeSteps)
{
if (timeSteps > m_PolyDatas.size())
{
Superclass::Expand(timeSteps);
m_PolyDatas.resize(timeSteps);
m_CalculateBoundingBox = true;
}
}
void mitk::Surface::ExecuteOperation(Operation* operation)
{
switch (operation->GetOperationType())
{
case OpSURFACECHANGED:
{
mitk::SurfaceOperation* surfaceOperation = dynamic_cast<mitk::SurfaceOperation*>(operation);
if(surfaceOperation == NULL)
break;
unsigned int timeStep = surfaceOperation->GetTimeStep();
if(m_PolyDatas[timeStep] != NULL)
{
vtkPolyData* updatedPolyData = surfaceOperation->GetVtkPolyData();
if(updatedPolyData != NULL)
{
this->SetVtkPolyData(updatedPolyData, timeStep);
this->CalculateBoundingBox();
this->Modified();
}
}
break;
}
default:
return;
}
}
unsigned int mitk::Surface::GetSizeOfPolyDataSeries() const
{
return m_PolyDatas.size();
}
void mitk::Surface::Graft(const DataObject* data)
{
const Surface* surface = dynamic_cast<const Surface*>(data);
if(surface == NULL)
mitkThrow() << "Data object used to graft surface is not a mitk::Surface.";
this->CopyInformation(data);
m_PolyDatas.clear();
for (unsigned int i = 0; i < surface->GetSizeOfPolyDataSeries(); ++i)
{
m_PolyDatas.push_back(vtkPolyData::New());
m_PolyDatas.back()->DeepCopy(const_cast<mitk::Surface*>(surface)->GetVtkPolyData(i));
}
}
void mitk::Surface::PrintSelf(std::ostream& os, itk::Indent indent) const
{
Superclass::PrintSelf(os, indent);
os << indent << "\nNumber PolyDatas: " << m_PolyDatas.size() << "\n";
unsigned int count = 0;
for (std::vector<vtkPolyData*>::const_iterator it = m_PolyDatas.begin(); it != m_PolyDatas.end(); ++it)
{
os << "\n";
if(*it != NULL)
{
os << indent << "PolyData at time step " << count << ":\n";
os << indent << "Number of cells: " << (*it)->GetNumberOfCells() << "\n";
os << indent << "Number of points: " << (*it)->GetNumberOfPoints() << "\n\n";
os << indent << "VTKPolyData:\n";
(*it)->Print(os);
}
else
{
os << indent << "Empty PolyData at time step " << count << "\n";
}
++count;
}
}
bool mitk::Equal( vtkPolyData* leftHandSide, vtkPolyData* rightHandSide, mitk::ScalarType eps, bool verbose )
{
if(( leftHandSide == NULL ) || ( rightHandSide == NULL ))
{
MITK_ERROR << "mitk::Equal( vtkPolyData* leftHandSide, vtkPolyData* rightHandSide, mitk::ScalarType eps, bool verbose ) does not work for NULL pointer input.";
return false;
}
return Equal( *leftHandSide, *rightHandSide, eps, verbose);
}
bool mitk::Equal( vtkPolyData& leftHandSide, vtkPolyData& rightHandSide, mitk::ScalarType eps, bool verbose )
{
bool noDifferenceFound = true;
if( ! mitk::Equal( leftHandSide.GetNumberOfCells(), rightHandSide.GetNumberOfCells(), eps, verbose ) )
{
if(verbose)
MITK_INFO << "[Equal( vtkPolyData*, vtkPolyData* )] Number of cells not equal";
noDifferenceFound = false;
}
if( ! mitk::Equal( leftHandSide.GetNumberOfVerts(), rightHandSide.GetNumberOfVerts(), eps, verbose ))
{
if(verbose)
MITK_INFO << "[Equal( vtkPolyData*, vtkPolyData* )] Number of vertices not equal";
noDifferenceFound = false;
}
if( ! mitk::Equal( leftHandSide.GetNumberOfLines(), rightHandSide.GetNumberOfLines(), eps, verbose ) )
{
if(verbose)
MITK_INFO << "[Equal( vtkPolyData*, vtkPolyData* )] Number of lines not equal";
noDifferenceFound = false;
}
if( ! mitk::Equal( leftHandSide.GetNumberOfPolys(), rightHandSide.GetNumberOfPolys(), eps, verbose ) )
{
if(verbose)
MITK_INFO << "[Equal( vtkPolyData*, vtkPolyData* )] Number of polys not equal";
noDifferenceFound = false;
}
if( ! mitk::Equal( leftHandSide.GetNumberOfStrips(), rightHandSide.GetNumberOfStrips(), eps, verbose ) )
{
if(verbose)
MITK_INFO << "[Equal( vtkPolyData*, vtkPolyData* )] Number of strips not equal";
noDifferenceFound = false;
}
{
unsigned int numberOfPointsRight = rightHandSide.GetPoints()->GetNumberOfPoints();
unsigned int numberOfPointsLeft = leftHandSide.GetPoints()->GetNumberOfPoints();
if(! mitk::Equal( numberOfPointsLeft, numberOfPointsRight, eps, verbose ))
{
if(verbose)
MITK_INFO << "[Equal( vtkPolyData*, vtkPolyData* )] Number of points not equal";
noDifferenceFound = false;
}
else
{
for( unsigned int i( 0 ); i < numberOfPointsRight; i++ )
{
bool pointFound = false;
double pointOne[3];
rightHandSide.GetPoints()->GetPoint(i, pointOne);
for( unsigned int j( 0 ); j < numberOfPointsLeft; j++ )
{
double pointTwo[3];
leftHandSide.GetPoints()->GetPoint(j, pointTwo);
double x = pointOne[0] - pointTwo[0];
double y = pointOne[1] - pointTwo[1];
double z = pointOne[2] - pointTwo[2];
double distance = x*x + y*y + z*z;
if( distance < eps )
{
pointFound = true;
break;
}
}
if( !pointFound )
{
if(verbose)
{
MITK_INFO << "[Equal( vtkPolyData*, vtkPolyData* )] Right hand side point with id " << i << " and coordinates ( "
<< std::setprecision(12)
<< pointOne[0] << " ; " << pointOne[1] << " ; " << pointOne[2]
<< " ) could not be found in left hand side with epsilon " << eps << ".";
}
noDifferenceFound = false;
break;
}
}
}
}
return noDifferenceFound;
}
bool mitk::Equal( mitk::Surface* leftHandSide, mitk::Surface* rightHandSide, mitk::ScalarType eps, bool verbose )
{
if(( leftHandSide == NULL ) || ( rightHandSide == NULL ))
{
MITK_ERROR << "mitk::Equal( mitk::Surface* leftHandSide, mitk::Surface* rightHandSide, mitk::ScalarType eps, bool verbose ) does not work with NULL pointer input.";
return false;
}
return Equal( *leftHandSide, *rightHandSide, eps, verbose);
}
bool mitk::Equal( mitk::Surface& leftHandSide, mitk::Surface& rightHandSide, mitk::ScalarType eps, bool verbose )
{
bool noDifferenceFound = true;
if( ! mitk::Equal( leftHandSide.GetSizeOfPolyDataSeries(), rightHandSide.GetSizeOfPolyDataSeries(), eps, verbose ) )
{
if(verbose)
MITK_INFO << "[Equal( mitk::surface&, mitk::surface& )] Size of PolyData series not equal.";
return false;
}
// No mitk::Equal for TimeGeometry implemented.
//if( ! mitk::Equal( leftHandSide->GetTimeGeometry(), rightHandSide->GetTimeGeometry(), eps, verbose ) )
//{
// if(verbose)
// MITK_INFO << "[Equal( mitk::surface&, mitk::surface& )] Time sliced geometries not equal";
// noDifferenceFound = false;
//}
for( unsigned int i( 0 ); i < rightHandSide.GetSizeOfPolyDataSeries(); i++ )
{
if( ! mitk::Equal( *leftHandSide.GetVtkPolyData( i ), *rightHandSide.GetVtkPolyData( i ), eps, verbose ) )
{
if(verbose)
MITK_INFO << "[Equal( mitk::surface&, mitk::surface& )] Poly datas not equal.";
noDifferenceFound = false;
}
}
return noDifferenceFound;
}
diff --git a/Core/Code/DataManagement/mitkThinPlateSplineCurvedGeometry.cpp b/Core/Code/DataManagement/mitkThinPlateSplineCurvedGeometry.cpp
index 43cdba71e9..562f2d6745 100644
--- a/Core/Code/DataManagement/mitkThinPlateSplineCurvedGeometry.cpp
+++ b/Core/Code/DataManagement/mitkThinPlateSplineCurvedGeometry.cpp
@@ -1,102 +1,100 @@
/*===================================================================
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 "mitkThinPlateSplineCurvedGeometry.h"
#include <vtkThinPlateSplineTransform.h>
#include <vtkPoints.h>
mitk::ThinPlateSplineCurvedGeometry::ThinPlateSplineCurvedGeometry()
{
m_InterpolatingAbstractTransform = m_ThinPlateSplineTransform = vtkThinPlateSplineTransform::New();
m_VtkTargetLandmarks = vtkPoints::New();
m_VtkProjectedLandmarks = vtkPoints::New();
m_ThinPlateSplineTransform->SetInverseIterations(5000);
}
mitk::ThinPlateSplineCurvedGeometry::ThinPlateSplineCurvedGeometry(const ThinPlateSplineCurvedGeometry& other ) : Superclass(other)
{
this->SetSigma(other.GetSigma());
}
mitk::ThinPlateSplineCurvedGeometry::~ThinPlateSplineCurvedGeometry()
{
// don't need to delete m_ThinPlateSplineTransform, because it is
// the same as m_InterpolatingAbstractTransform, which will be deleted
// by the superclass.
if(m_VtkTargetLandmarks!=NULL)
m_VtkTargetLandmarks->Delete();
if(m_VtkProjectedLandmarks!=NULL)
m_VtkProjectedLandmarks->Delete();
}
bool mitk::ThinPlateSplineCurvedGeometry::IsValid() const
{
return m_TargetLandmarks.IsNotNull() && (m_TargetLandmarks->Size() >= 3) && m_LandmarkProjector.IsNotNull();
}
void mitk::ThinPlateSplineCurvedGeometry::SetSigma(double sigma)
{
m_ThinPlateSplineTransform->SetSigma(sigma);
}
double mitk::ThinPlateSplineCurvedGeometry::GetSigma() const
{
return m_ThinPlateSplineTransform->GetSigma();
-
}
void mitk::ThinPlateSplineCurvedGeometry::ComputeGeometry()
{
Superclass::ComputeGeometry();
const mitk::PointSet::DataType::PointsContainer *finalTargetLandmarks, *projectedTargetLandmarks;
finalTargetLandmarks = m_LandmarkProjector->GetFinalTargetLandmarks();
projectedTargetLandmarks = m_LandmarkProjector->GetProjectedLandmarks();
mitk::PointSet::DataType::PointsContainer::ConstIterator targetIt, projectedIt;
targetIt = finalTargetLandmarks->Begin();
projectedIt = projectedTargetLandmarks->Begin();
//initialize Thin-Plate-Spline
m_VtkTargetLandmarks->Reset();
m_VtkProjectedLandmarks->Reset();
vtkIdType id;
int size=finalTargetLandmarks->Size();
for(id=0; id < size; ++id, ++targetIt, ++projectedIt)
{
const mitk::PointSet::PointType& target = targetIt->Value();
m_VtkTargetLandmarks->InsertPoint(id, target[0], target[1], target[2]);
const mitk::PointSet::PointType& projected = projectedIt->Value();
m_VtkProjectedLandmarks->InsertPoint(id, projected[0], projected[1], projected[2]);
}
m_VtkTargetLandmarks->Modified();
m_VtkProjectedLandmarks->Modified();
m_ThinPlateSplineTransform->SetSourceLandmarks(m_VtkProjectedLandmarks);
m_ThinPlateSplineTransform->SetTargetLandmarks(m_VtkTargetLandmarks);
}
itk::LightObject::Pointer mitk::ThinPlateSplineCurvedGeometry::InternalClone() const
{
- mitk::Geometry3D::Pointer newGeometry = new Self(*this);
+ mitk::BaseGeometry::Pointer newGeometry = new Self(*this);
newGeometry->UnRegister();
return newGeometry.GetPointer();
}
diff --git a/Core/Code/DataManagement/mitkThinPlateSplineCurvedGeometry.h b/Core/Code/DataManagement/mitkThinPlateSplineCurvedGeometry.h
index d7fed98109..98ab9b8489 100644
--- a/Core/Code/DataManagement/mitkThinPlateSplineCurvedGeometry.h
+++ b/Core/Code/DataManagement/mitkThinPlateSplineCurvedGeometry.h
@@ -1,69 +1,65 @@
/*===================================================================
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 MITKTHINPLATESPLINECURVEDGEOMETRY_H_HEADER_INCLUDED_C1C68A2C
#define MITKTHINPLATESPLINECURVEDGEOMETRY_H_HEADER_INCLUDED_C1C68A2C
#include "mitkLandmarkProjectorBasedCurvedGeometry.h"
class vtkPoints;
class vtkThinPlateSplineTransform;
namespace mitk {
-
-//##Documentation
-//## @brief Thin-plate-spline-based landmark-based curved geometry
-//##
-//## @ingroup Geometry
-class MITK_CORE_EXPORT ThinPlateSplineCurvedGeometry : public LandmarkProjectorBasedCurvedGeometry
-{
-public:
+ //##Documentation
+ //## @brief Thin-plate-spline-based landmark-based curved geometry
+ //##
+ //## @ingroup Geometry
+ class MITK_CORE_EXPORT ThinPlateSplineCurvedGeometry : public LandmarkProjectorBasedCurvedGeometry
+ {
+ public:
mitkClassMacro(ThinPlateSplineCurvedGeometry, LandmarkProjectorBasedCurvedGeometry);
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
virtual void ComputeGeometry();
virtual itk::LightObject::Pointer InternalClone() const;
vtkThinPlateSplineTransform* GetThinPlateSplineTransform() const
{
return m_ThinPlateSplineTransform;
}
virtual void SetSigma(double sigma);
virtual double GetSigma() const;
virtual bool IsValid() const;
-protected:
+ protected:
ThinPlateSplineCurvedGeometry();
ThinPlateSplineCurvedGeometry(const ThinPlateSplineCurvedGeometry& other );
virtual ~ThinPlateSplineCurvedGeometry();
vtkThinPlateSplineTransform* m_ThinPlateSplineTransform;
vtkPoints* m_VtkTargetLandmarks;
vtkPoints* m_VtkProjectedLandmarks;
-
-};
-
+ };
} // namespace mitk
#endif /* MITKTHINPLATESPLINECURVEDGEOMETRY_H_HEADER_INCLUDED_C1C68A2C */
diff --git a/Core/Code/DataManagement/mitkTimeGeometry.h b/Core/Code/DataManagement/mitkTimeGeometry.h
index e95a584fd9..375dbb543b 100644
--- a/Core/Code/DataManagement/mitkTimeGeometry.h
+++ b/Core/Code/DataManagement/mitkTimeGeometry.h
@@ -1,288 +1,305 @@
/*===================================================================
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 TimeGeometry_h
#define TimeGeometry_h
//ITK
#include <itkObject.h>
//MITK
#include <mitkCommon.h>
#include <MitkCoreExports.h>
#include "mitkOperationActor.h"
-#include <mitkGeometry3D.h>
+#include <mitkBaseGeometry.h>
namespace mitk {
-
/**
* \deprecatedSince{2013_09} GlobalInteraction is deprecated. It is replaced by mitk::Dispatcher.
* Please use the new implementation described in \see DataInteractionPage .
*/
typedef mitk::ScalarType TimePointType;
typedef std::size_t TimeStepType;
/**
* \brief Manages the geometries of a data object for each time step
*
* This class is an abstract class. The concrete implementation
* depends on the way the different time steps are managed.
*
* The time is defined either by a time step or a time point. Time steps
* are non-negativ integers starting from 0. A time point is is a ScalarType value
* which gives the passed time since start in ms. Be aware that the starting
* point is not fixed so it is possible that the same time point defines two
* different time depending on the start time of the used time geometry.
*
* \addtogroup geometry
*/
class MITK_CORE_EXPORT TimeGeometry : public itk::Object, public OperationActor
{
protected:
TimeGeometry();
virtual ~TimeGeometry();
/**
* \brief Contains a bounding box which includes all time steps
*/
BoundingBox::Pointer m_BoundingBox;
/**
* \brief Makes a deep copy of the current object
*/
virtual LightObject::Pointer InternalClone() const;
public:
mitkClassMacro(TimeGeometry, itk::Object)
itkCloneMacro(Self)
itkCreateAnotherMacro(Self)
+
/**
* \brief Returns the number of time steps.
*
* Returns the number of time steps for which
* geometries are saved. The number of time steps
* is also the upper bound of the time steps. The
* minimum time steps is always 0.
*/
virtual TimeStepType CountTimeSteps() const = 0;
/**
* \brief Returns the first time point for which the object is valid.
*
* Returns the first valid time point for this geometry. If only one
* time steps available it usually goes from -max to +max. The time point
* is given in ms.
*/
- virtual TimePointType GetMinimumTimePoint () const = 0;
+ virtual TimePointType GetMinimumTimePoint() const = 0;
/**
* \brief Returns the last time point for which the object is valid
*
* Gives the last time point for which a valid geometrie is saved in
* this time geometry. The time point is given in ms.
*/
- virtual TimePointType GetMaximumTimePoint () const = 0;
+ virtual TimePointType GetMaximumTimePoint() const = 0;
+
+ /**
+ * \brief Returns the first time point for which the object is valid.
+ *
+ * Returns the first valid time point for the given TimeStep. The time point
+ * is given in ms.
+ */
+ virtual TimePointType GetMinimumTimePoint(TimeStepType step) const = 0;
+ /**
+ * \brief Returns the last time point for which the object is valid
+ *
+ * Gives the last time point for the Geometry specified by the given TimeStep. The time point is given in ms.
+ */
+ virtual TimePointType GetMaximumTimePoint(TimeStepType step) const = 0;
/**
* \brief Get the time bounds (in ms)
*/
- virtual TimeBounds GetTimeBounds( ) const = 0;
+ virtual TimeBounds GetTimeBounds() const = 0;
+
+ /**
+ * \brief Get the time bounds for the given TimeStep (in ms)
+ */
+ virtual TimeBounds GetTimeBounds(TimeStepType step) const = 0;
/**
* \brief Tests if a given time point is covered by this object
*
* Returns true if a geometry can be returned for the given time
* point and falls if not. The time point must be given in ms.
*/
virtual bool IsValidTimePoint (TimePointType timePoint) const = 0;
/**
* \brief Test for the given time step if a geometry is availible
*
* Returns true if a geometry is defined for the given time step.
* Otherwise false is returned.
* The time step is defined as positiv number.
*/
virtual bool IsValidTimeStep (TimeStepType timeStep) const = 0;
/**
* \brief Converts a time step to a time point
*
* Converts a time step to a time point in a way that
* the new time point indicates the same geometry as the time step.
* If the original time steps does not point to a valid geometry,
* a time point is calculated that also does not point to a valid
* geometry, but no exception is raised.
*/
virtual TimePointType TimeStepToTimePoint (TimeStepType timeStep) const = 0;
/**
* \brief Converts a time point to the corresponding time step
*
* Converts a time point to a time step in a way that
* the new time step indicates the same geometry as the time point.
* If a negativ invalid time point is given always time step 0 is
* returned. If an positiv invalid time step is given an invalid
* time step will be returned.
*/
virtual TimeStepType TimePointToTimeStep (TimePointType timePoint) const = 0;
/**
* \brief Returns the geometry of a specific time point
*
* Returns the geometry which defines the given time point. If
* the given time point is invalid an null-pointer is returned.
*
* The pointer to the returned geometry may point to the saved
* geometry but this is not necessarily the case. So a change to
* the returned geometry may or may not afflict the geometry for the
* time point or all time points depending on the used implementation
* of TimeGeometry.
*/
- virtual Geometry3D::Pointer GetGeometryForTimePoint ( TimePointType timePoint) const = 0;
+ virtual BaseGeometry::Pointer GetGeometryForTimePoint ( TimePointType timePoint) const = 0;
/**
* \brief Returns the geometry which corresponds to the given time step
*
* Returns the geometry which defines the given time step. If
* the given time step is invalid an null-pointer is returned.
*
* The pointer to the returned geometry may point to the saved
* geometry but this is not necessarily the case. So a change to
* the returned geometry may or may not afflict the geometry for the
* time step or all time steps depending on the used implementation
* of TimeGeometry.
*/
- virtual Geometry3D::Pointer GetGeometryForTimeStep ( TimeStepType timeStep) const = 0;
+ virtual BaseGeometry::Pointer GetGeometryForTimeStep ( TimeStepType timeStep) const = 0;
/**
* \brief Returns a clone of the geometry of a specific time point
*
* If an invalid time step is given (e.g. no geometry is defined for this time step)
* a null-pointer will be returned.
*/
- virtual Geometry3D::Pointer GetGeometryCloneForTimeStep( TimeStepType timeStep) const = 0;
+ virtual BaseGeometry::Pointer GetGeometryCloneForTimeStep( TimeStepType timeStep) const = 0;
/**
* \brief Sets the geometry for a given time step
*
* Sets the geometry for the given time steps. This may also afflects other
* time steps, depending on the implementation of TimeGeometry.
*/
- virtual void SetTimeStepGeometry(Geometry3D* geometry, TimeStepType timeStep) = 0;
+ virtual void SetTimeStepGeometry(BaseGeometry* geometry, TimeStepType timeStep) = 0;
/**
* \brief Expands to the given number of time steps
*
* Expands to the given number of time steps. Each new created time
* step is filled with an empty geometry.
* Shrinking is not supported!
*/
virtual void Expand(TimeStepType size) = 0;
/**
* \brief Tests if all necessary informations are set and the object is valid
*/
virtual bool IsValid () const = 0;
/**
* \brief Get the position of the corner number \a id (in world coordinates)
*
* See SetImageGeometry for how a corner is defined on images.
*/
Point3D GetCornerPointInWorld(int id) const;
/**
* \brief Get the position of a corner (in world coordinates)
*
* See SetImageGeometry for how a corner is defined on images.
*/
Point3D GetCornerPointInWorld(bool xFront=true, bool yFront=true, bool zFront=true) const;
/**
* \brief Get the center of the bounding-box in mm
*/
Point3D GetCenterInWorld() const;
/**
* \brief Get the squared length of the diagonal of the bounding-box in mm
*/
double GetDiagonalLength2InWorld() const;
/**
* \brief Get the length of the diagonal of the bounding-box in mm
*/
double GetDiagonalLengthInWorld() const;
/**
* \brief Test whether the point \a p (world coordinates in mm) is inside the bounding box
*/
bool IsWorldPointInside(const mitk::Point3D& p) const;
/**
* \brief Updates the bounding box to cover the area used in all time steps
*
* The bounding box is updated by this method. The new bounding box
* covers an area which includes all bounding boxes during
* all times steps.
*/
void UpdateBoundingBox();
/**
* \brief Returns a bounding box that covers all time steps
*/
BoundingBox* GetBoundingBoxInWorld() const
{
return m_BoundingBox;
}
/**
* \brief Returns the world bounds of the object that cover all time steps
*/
BoundingBox::BoundsArrayType GetBoundsInWorld() const
{
return m_BoundingBox->GetBounds();
}
/**
* \brief Returns the Extend of the bounding in the given direction
*/
ScalarType GetExtentInWorld (unsigned int direction) const;
/**
* \brief Initializes the TimeGeometry
*/
virtual void Initialize();
/**
* \brief Updates the geometry
*/
void Update();
/**
* \brief Updates everything except the Bounding box
*
* This class should be overwritten by child classes.
* The method is called when Update() is required.
*/
virtual void UpdateWithoutBoundingBox()
{};
/**
* \brief Executes the given operation on all time steps
*/
virtual void ExecuteOperation(Operation *op);
virtual void PrintSelf(std::ostream& os, itk::Indent indent) const;
-
}; // end class TimeGeometry
-
} // end namespace MITK
#endif // TimeGeometry_h
diff --git a/Core/Code/IO/mitkImageWriter.cpp b/Core/Code/IO/mitkImageWriter.cpp
index e6e5a66c15..a4ce6ab7df 100644
--- a/Core/Code/IO/mitkImageWriter.cpp
+++ b/Core/Code/IO/mitkImageWriter.cpp
@@ -1,490 +1,490 @@
/*===================================================================
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 "mitkImageWriter.h"
#include "mitkItkPictureWrite.h"
#include "mitkImage.h"
#include "mitkImageTimeSelector.h"
#include "mitkImageAccessByItk.h"
#include "mitkImageReadAccessor.h"
#include <itkImageIOBase.h>
#include <itkImageIOFactory.h>
mitk::ImageWriter::ImageWriter()
{
this->SetNumberOfRequiredInputs( 1 );
m_MimeType = "";
SetDefaultExtension();
}
mitk::ImageWriter::~ImageWriter()
{
}
void mitk::ImageWriter::SetFileName(const char* fileName)
{
if ( fileName && ( fileName == this->m_FileName ) )
{
return;
}
if ( fileName )
{
this->m_FileName = fileName;
this->m_FileNameWithoutExtension = this->m_FileName;
this->m_Extension.clear();
std::size_t pos = this->m_FileName.find_last_of("/\\");
if (pos != std::string::npos)
{
std::size_t ppos = this->m_FileName.find_first_of('.', pos);
if (ppos != std::string::npos)
{
this->m_FileNameWithoutExtension = this->m_FileName.substr(0, ppos);
this->m_Extension = this->m_FileName.substr(ppos);
}
}
}
else
{
this->m_FileName.clear();
this->m_FileNameWithoutExtension.clear();
this->m_Extension.clear();
}
this->Modified();
}
void mitk::ImageWriter::SetFileName(const std::string & fileName)
{
this->SetFileName( fileName.c_str() );
}
void mitk::ImageWriter::SetExtension(const char* extension)
{
if ( extension && ( extension == this->m_Extension ) )
{
return;
}
if ( extension )
{
this->m_Extension = extension;
this->m_FileName = this->m_FileNameWithoutExtension + this->m_Extension;
}
else
{
this->m_Extension.clear();
this->m_FileName = this->m_FileNameWithoutExtension;
}
this->Modified();
}
void mitk::ImageWriter::SetExtension(const std::string & extension)
{
this->SetFileName( extension.c_str() );
}
void mitk::ImageWriter::SetDefaultExtension()
{
this->m_Extension = ".mhd";
this->m_FileName = this->m_FileNameWithoutExtension + this->m_Extension;
this->Modified();
}
#include <vtkConfigure.h>
#include <vtkImageData.h>
#include <vtkXMLImageDataWriter.h>
static void writeVti(const char * filename, mitk::Image* image, int t=0)
{
vtkXMLImageDataWriter * vtkwriter = vtkXMLImageDataWriter::New();
vtkwriter->SetFileName( filename );
vtkwriter->SetInputData(image->GetVtkImageData(t));
vtkwriter->Write();
vtkwriter->Delete();
}
#include <itkRGBAPixel.h>
void mitk::ImageWriter::WriteByITK(mitk::Image* image, const std::string& fileName)
{
MITK_INFO << "Writing image: " << fileName << std::endl;
// Pictures and picture series like .png are written via a different mechanism then volume images.
// So, they are still multiplexed and thus not support vector images.
if (fileName.find(".png") != std::string::npos || fileName.find(".tif") != std::string::npos || fileName.find(".jpg") != std::string::npos || fileName.find(".bmp") != std::string::npos)
{
try
{
// switch processing of single/multi-component images
if( image->GetPixelType(0).GetNumberOfComponents() == 1)
{
AccessByItk_1( image, _mitkItkPictureWrite, fileName );
}
else
{
AccessFixedPixelTypeByItk_1( image, _mitkItkPictureWriteComposite, MITK_ACCESSBYITK_PIXEL_TYPES_SEQ MITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES_SEQ , fileName);
}
}
catch(itk::ExceptionObject &e)
{
std::cerr << "Caught " << e.what() << std::endl;
}
catch(std::exception &e)
{
std::cerr << "Caught std::exception " << e.what() << std::endl;
}
return;
}
// Implementation of writer using itkImageIO directly. This skips the use
// of templated itkImageFileWriter, which saves the multiplexing on MITK side.
unsigned int dimension = image->GetDimension();
unsigned int* dimensions = image->GetDimensions();
mitk::PixelType pixelType = image->GetPixelType();
mitk::Vector3D mitkSpacing = image->GetGeometry()->GetSpacing();
mitk::Point3D mitkOrigin = image->GetGeometry()->GetOrigin();
// Due to templating in itk, we are forced to save a 4D spacing and 4D Origin, though they are not supported in MITK
itk::Vector<double, 4u> spacing4D;
spacing4D[0] = mitkSpacing[0];
spacing4D[1] = mitkSpacing[1];
spacing4D[2] = mitkSpacing[2];
spacing4D[3] = 1; // There is no support for a 4D spacing. However, we should have an valid value here
itk::Vector<double, 4u> origin4D;
origin4D[0] = mitkOrigin[0];
origin4D[1] = mitkOrigin[1];
origin4D[2] = mitkOrigin[2];
origin4D[3] = 0; // There is no support for a 4D origin. However, we should have an valid value here
itk::ImageIOBase::Pointer imageIO = itk::ImageIOFactory::CreateImageIO( fileName.c_str(),
itk::ImageIOFactory::WriteMode );
if(imageIO.IsNull())
{
itkExceptionMacro(<< "Error: Could not create itkImageIO via factory for file " << fileName);
}
// Set the necessary information for imageIO
imageIO->SetNumberOfDimensions(dimension);
imageIO->SetPixelType( pixelType.GetPixelType() );
imageIO->SetComponentType( pixelType.GetComponentType() < PixelComponentUserType ?
static_cast<itk::ImageIOBase::IOComponentType>(pixelType.GetComponentType()) :
itk::ImageIOBase::UNKNOWNCOMPONENTTYPE);
imageIO->SetNumberOfComponents( pixelType.GetNumberOfComponents() );
itk::ImageIORegion ioRegion( dimension );
for(unsigned int i=0; i<dimension; i++)
{
imageIO->SetDimensions(i,dimensions[i]);
imageIO->SetSpacing(i,spacing4D[i]);
imageIO->SetOrigin(i,origin4D[i]);
mitk::Vector3D mitkDirection;
mitkDirection.SetVnlVector(image->GetGeometry()->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(i));
itk::Vector<double, 4u> direction4D;
direction4D[0] = mitkDirection[0];
direction4D[1] = mitkDirection[1];
direction4D[2] = mitkDirection[2];
// MITK only supports a 3x3 direction matrix. Due to templating in itk, however, we must
// save a 4x4 matrix for 4D images. in this case, add an homogneous component to the matrix.
if (i == 3)
direction4D[3] = 1; // homogenous component
else
direction4D[3] = 0;
vnl_vector< double > axisDirection(dimension);
for(unsigned int j=0; j<dimension; j++)
{
axisDirection[j] = direction4D[j]/spacing4D[i];
}
imageIO->SetDirection( i, axisDirection );
ioRegion.SetSize(i, image->GetLargestPossibleRegion().GetSize(i) );
ioRegion.SetIndex(i, image->GetLargestPossibleRegion().GetIndex(i) );
}
//use compression if available
imageIO->UseCompressionOn();
imageIO->SetIORegion(ioRegion);
imageIO->SetFileName(fileName);
ImageReadAccessor imageAccess(image);
imageIO->Write(imageAccess.GetData());
}
void mitk::ImageWriter::GenerateData()
{
const std::string& locale = "C";
const std::string& currLocale = setlocale( LC_ALL, NULL );
if ( locale.compare(currLocale)!=0 )
{
try
{
setlocale(LC_ALL, locale.c_str());
}
catch(...)
{
MITK_INFO << "Could not set locale " << locale;
}
}
if ( m_FileName == "" )
{
itkWarningMacro( << "Sorry, filename has not been set!" );
return ;
}
FILE* tempFile = fopen(m_FileName.c_str(),"w");
if (tempFile==NULL)
{
itkExceptionMacro(<<"File location not writeable");
return;
}
fclose(tempFile);
remove(m_FileName.c_str());
// Creating clone of input image, since i might change the geometry
mitk::Image::Pointer input = const_cast<mitk::Image*>(this->GetInput())->Clone();
// Check if geometry information will be lost
if (input->GetDimension() == 2)
{
if (!input->GetGeometry()->Is2DConvertable())
{
MITK_WARN << "Saving a 2D image with 3D geometry information. Geometry information will be lost! You might consider using Convert2Dto3DImageFilter before saving.";
// set matrix to identity
mitk::AffineTransform3D::Pointer affTrans = mitk::AffineTransform3D::New();
affTrans->SetIdentity();
mitk::Vector3D spacing = input->GetGeometry()->GetSpacing();
mitk::Point3D origin = input->GetGeometry()->GetOrigin();
input->GetGeometry()->SetIndexToWorldTransform(affTrans);
input->GetGeometry()->SetSpacing(spacing);
input->GetGeometry()->SetOrigin(origin);
}
}
bool vti = (m_Extension.find(".vti") != std::string::npos);
// If the extension is NOT .pic and NOT .nrrd and NOT .nii and NOT .nii.gz the following block is entered
if ( m_Extension.find(".pic") == std::string::npos
&& m_Extension.find(".nrrd") == std::string::npos
&& m_Extension.find(".nii") == std::string::npos
&& m_Extension.find(".nii.gz") == std::string::npos
)
{
if(input->GetDimension() > 3)
{
int t, timesteps;
timesteps = input->GetDimension(3);
ImageTimeSelector::Pointer timeSelector = ImageTimeSelector::New();
timeSelector->SetInput(input);
mitk::Image::Pointer image = timeSelector->GetOutput();
for(t = 0; t < timesteps; ++t)
{
std::ostringstream filename;
timeSelector->SetTimeNr(t);
timeSelector->Update();
if(input->GetTimeGeometry()->IsValidTimeStep(t))
{
- const mitk::TimeBounds& timebounds = input->GetTimeGeometry()->GetGeometryForTimeStep(t)->GetTimeBounds();
+ const mitk::TimeBounds& timebounds = input->GetTimeGeometry()->GetTimeBounds(t);
filename << m_FileNameWithoutExtension << "_S" << std::setprecision(0) << timebounds[0] << "_E" << std::setprecision(0) << timebounds[1] << "_T" << t << m_Extension;
}
else
{
itkWarningMacro(<<"Error on write: TimeGeometry invalid of image " << filename.str() << ".");
filename << m_FileNameWithoutExtension << "_T" << t << m_Extension;
}
if ( vti )
{
writeVti(filename.str().c_str(), input, t);
}
else
{
WriteByITK(image, filename.str());
}
}
}
else if ( vti )
{
writeVti(m_FileName.c_str(), input);
}
else
{
WriteByITK(input, m_FileName);
}
}
else
{
// use the PicFileWriter for the .pic data type
if( m_Extension.find(".pic") != std::string::npos )
{
/* PicFileWriter::Pointer picWriter = PicFileWriter::New();
size_t found;
found = m_FileName.find( m_Extension ); // !!! HAS to be at the very end of the filename (not somewhere in the middle)
if( m_FileName.length() > 3 && found != m_FileName.length() - 4 )
{
//if Extension not in Filename
std::ostringstream filename;
filename << m_FileName.c_str() << m_Extension;
picWriter->SetFileName( filename.str().c_str() );
}
else
{
picWriter->SetFileName( m_FileName.c_str() );
}
picWriter->SetInputImage( input );
picWriter->Write();
*/ }
// use the ITK .nrrd Image writer
if( m_Extension.find(".nrrd") != std::string::npos
|| m_Extension.find(".nii") != std::string::npos
|| m_Extension.find(".nii.gz") != std::string::npos
)
{
WriteByITK(input, this->m_FileName);
}
}
m_MimeType = "application/MITK.Pic";
try
{
setlocale(LC_ALL, currLocale.c_str());
}
catch(...)
{
MITK_INFO << "Could not reset locale " << currLocale;
}
}
bool mitk::ImageWriter::CanWriteDataType( DataNode* input )
{
if ( input )
{
return this->CanWriteBaseDataType(input->GetData());
}
return false;
}
void mitk::ImageWriter::SetInput( DataNode* input )
{
if( input && CanWriteDataType( input ) )
this->ProcessObject::SetNthInput( 0, dynamic_cast<mitk::Image*>( input->GetData() ) );
}
std::string mitk::ImageWriter::GetWritenMIMEType()
{
return m_MimeType;
}
std::vector<std::string> mitk::ImageWriter::GetPossibleFileExtensions()
{
std::vector<std::string> possibleFileExtensions;
possibleFileExtensions.push_back(".pic");
possibleFileExtensions.push_back(".pic.gz");
possibleFileExtensions.push_back(".bmp");
possibleFileExtensions.push_back(".dcm");
possibleFileExtensions.push_back(".DCM");
possibleFileExtensions.push_back(".dicom");
possibleFileExtensions.push_back(".DICOM");
possibleFileExtensions.push_back(".gipl");
possibleFileExtensions.push_back(".gipl.gz");
possibleFileExtensions.push_back(".mha");
possibleFileExtensions.push_back(".nii");
possibleFileExtensions.push_back(".nii.gz");
possibleFileExtensions.push_back(".nrrd");
possibleFileExtensions.push_back(".nhdr");
possibleFileExtensions.push_back(".png");
possibleFileExtensions.push_back(".PNG");
possibleFileExtensions.push_back(".spr");
possibleFileExtensions.push_back(".mhd");
possibleFileExtensions.push_back(".vtk");
possibleFileExtensions.push_back(".vti");
possibleFileExtensions.push_back(".hdr");
possibleFileExtensions.push_back(".img");
possibleFileExtensions.push_back(".img.gz");
possibleFileExtensions.push_back(".png");
possibleFileExtensions.push_back(".tif");
possibleFileExtensions.push_back(".jpg");
return possibleFileExtensions;
}
std::string mitk::ImageWriter::GetFileExtension()
{
return m_Extension;
}
void mitk::ImageWriter::SetInput( mitk::Image* image )
{
this->ProcessObject::SetNthInput( 0, image );
}
const mitk::Image* mitk::ImageWriter::GetInput()
{
if ( this->GetNumberOfInputs() < 1 )
{
return NULL;
}
else
{
return static_cast< const mitk::Image * >( this->ProcessObject::GetInput( 0 ) );
}
}
const char* mitk::ImageWriter::GetDefaultFilename()
{
return "Image.nrrd";
}
const char* mitk::ImageWriter::GetFileDialogPattern()
{
return
"Nearly Raw Raster Data (*.nrrd);;"
"NIfTI format (*.nii *.nii.gz);;"
"VTK Image Data Files (*.vti);;"
"NRRD with detached header (*.nhdr);;"
"Analyze Format (*.hdr);;"
"MetaImage (*.mhd);;"
"Sets of 2D slices (*.png *.tiff *.jpg *.jpeg *.bmp);;"
"DICOM (*.dcm *.DCM *.dicom *.DICOM);;"
"UMDS GIPL Format Files (*.gipl *.gipl.gz)";
}
const char *mitk::ImageWriter::GetDefaultExtension()
{
return ".nrrd";
}
bool mitk::ImageWriter::CanWriteBaseDataType(BaseData::Pointer data)
{
return dynamic_cast<mitk::Image*>( data.GetPointer() );
}
void mitk::ImageWriter::DoWrite(BaseData::Pointer data)
{
if (this->CanWriteBaseDataType(data))
{
this->SetInput(dynamic_cast<mitk::Image *>(data.GetPointer()));
this->Update();
}
}
\ No newline at end of file
diff --git a/Core/Code/IO/mitkItkImageFileReader.cpp b/Core/Code/IO/mitkItkImageFileReader.cpp
index 776a82e753..475610eaf1 100644
--- a/Core/Code/IO/mitkItkImageFileReader.cpp
+++ b/Core/Code/IO/mitkItkImageFileReader.cpp
@@ -1,211 +1,211 @@
/*===================================================================
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 "mitkItkImageFileReader.h"
#include "mitkConfig.h"
#include "mitkException.h"
#include <mitkProportionalTimeGeometry.h>
#include <itkImageFileReader.h>
#include <itksys/SystemTools.hxx>
#include <itksys/Directory.hxx>
#include <itkImage.h>
//#include <itkImageSeriesReader.h>
#include <itkImageFileReader.h>
#include <itkImageIOFactory.h>
#include <itkImageIORegion.h>
//#include <itkImageSeriesReader.h>
//#include <itkDICOMImageIO2.h>
//#include <itkDICOMSeriesFileNames.h>
//#include <itkGDCMImageIO.h>
//#include <itkGDCMSeriesFileNames.h>
//#include <itkNumericSeriesFileNames.h>
void mitk::ItkImageFileReader::GenerateData()
{
const std::string& locale = "C";
const std::string& currLocale = setlocale( LC_ALL, NULL );
if ( locale.compare(currLocale)!=0 )
{
try
{
setlocale(LC_ALL, locale.c_str());
}
catch(...)
{
MITK_INFO("mitkItkImageFileReader") << "Could not set locale " << locale;
}
}
mitk::Image::Pointer image = this->GetOutput();
const unsigned int MINDIM = 2;
const unsigned int MAXDIM = 4;
MITK_INFO("mitkItkImageFileReader") << "loading " << m_FileName << " via itk::ImageIOFactory... " << std::endl;
// Check to see if we can read the file given the name or prefix
if ( m_FileName == "" )
{
mitkThrow() << "Empty filename in mitk::ItkImageFileReader ";
return ;
}
itk::ImageIOBase::Pointer imageIO = itk::ImageIOFactory::CreateImageIO( m_FileName.c_str(), itk::ImageIOFactory::ReadMode );
if ( imageIO.IsNull() )
{
//itkWarningMacro( << "File Type not supported!" );
mitkThrow() << "Could not create itk::ImageIOBase object for filename " << m_FileName;
return ;
}
// Got to allocate space for the image. Determine the characteristics of
// the image.
imageIO->SetFileName( m_FileName.c_str() );
imageIO->ReadImageInformation();
unsigned int ndim = imageIO->GetNumberOfDimensions();
if ( ndim < MINDIM || ndim > MAXDIM )
{
itkWarningMacro( << "Sorry, only dimensions 2, 3 and 4 are supported. The given file has " << ndim << " dimensions! Reading as 4D." );
ndim = MAXDIM;
}
itk::ImageIORegion ioRegion( ndim );
itk::ImageIORegion::SizeType ioSize = ioRegion.GetSize();
itk::ImageIORegion::IndexType ioStart = ioRegion.GetIndex();
unsigned int dimensions[ MAXDIM ];
dimensions[ 0 ] = 0;
dimensions[ 1 ] = 0;
dimensions[ 2 ] = 0;
dimensions[ 3 ] = 0;
ScalarType spacing[ MAXDIM ];
spacing[ 0 ] = 1.0f;
spacing[ 1 ] = 1.0f;
spacing[ 2 ] = 1.0f;
spacing[ 3 ] = 1.0f;
Point3D origin;
origin.Fill(0);
unsigned int i;
for ( i = 0; i < ndim ; ++i )
{
ioStart[ i ] = 0;
ioSize[ i ] = imageIO->GetDimensions( i );
if(i<MAXDIM)
{
dimensions[ i ] = imageIO->GetDimensions( i );
spacing[ i ] = imageIO->GetSpacing( i );
if(spacing[ i ] <= 0)
spacing[ i ] = 1.0f;
}
if(i<3)
{
origin[ i ] = imageIO->GetOrigin( i );
}
}
ioRegion.SetSize( ioSize );
ioRegion.SetIndex( ioStart );
MITK_INFO("mitkItkImageFileReader") << "ioRegion: " << ioRegion << std::endl;
imageIO->SetIORegion( ioRegion );
void* buffer = new unsigned char[imageIO->GetImageSizeInBytes()];
imageIO->Read( buffer );
image->Initialize( MakePixelType(imageIO), ndim, dimensions );
image->SetImportChannel( buffer, 0, Image::ManageMemory );
// access direction of itk::Image and include spacing
mitk::Matrix3D matrix;
matrix.SetIdentity();
unsigned int j, itkDimMax3 = (ndim >= 3? 3 : ndim);
for ( i=0; i < itkDimMax3; ++i)
for( j=0; j < itkDimMax3; ++j )
matrix[i][j] = imageIO->GetDirection(j)[i];
// re-initialize PlaneGeometry with origin and direction
- PlaneGeometry* planeGeometry = static_cast<PlaneGeometry*>(image->GetSlicedGeometry(0)->GetGeometry2D(0));
+ PlaneGeometry* planeGeometry = static_cast<PlaneGeometry*>(image->GetSlicedGeometry(0)->GetPlaneGeometry(0));
planeGeometry->SetOrigin(origin);
planeGeometry->GetIndexToWorldTransform()->SetMatrix(matrix);
// re-initialize SlicedGeometry3D
SlicedGeometry3D* slicedGeometry = image->GetSlicedGeometry(0);
slicedGeometry->InitializeEvenlySpaced(planeGeometry, image->GetDimension(2));
slicedGeometry->SetSpacing(spacing);
MITK_INFO("mitkItkImageFileReader") << slicedGeometry->GetCornerPoint(false,false,false);
MITK_INFO("mitkItkImageFileReader") << slicedGeometry->GetCornerPoint(true,true,true);
// re-initialize TimeGeometry
ProportionalTimeGeometry::Pointer timeGeometry = ProportionalTimeGeometry::New();
timeGeometry->Initialize(slicedGeometry, image->GetDimension(3));
image->SetTimeGeometry(timeGeometry);
buffer = NULL;
MITK_INFO("mitkItkImageFileReader") << "number of image components: "<< image->GetPixelType().GetNumberOfComponents() << std::endl;
// mitk::DataNode::Pointer node = this->GetOutput();
// node->SetData( image );
// add level-window property
//if ( image->GetPixelType().GetNumberOfComponents() == 1 )
//{
// SetDefaultImageProperties( node );
//}
MITK_INFO("mitkItkImageFileReader") << "...finished!" << std::endl;
try
{
setlocale(LC_ALL, currLocale.c_str());
}
catch(...)
{
MITK_INFO("mitkItkImageFileReader") << "Could not reset locale " << currLocale;
}
}
bool mitk::ItkImageFileReader::CanReadFile(const std::string filename, const std::string filePrefix, const std::string filePattern)
{
// First check the extension
if( filename == "" )
return false;
// check if image is serie
if( filePattern != "" && filePrefix != "" )
return false;
itk::ImageIOBase::Pointer imageIO = itk::ImageIOFactory::CreateImageIO( filename.c_str(), itk::ImageIOFactory::ReadMode );
if ( imageIO.IsNull() )
return false;
return true;
}
mitk::ItkImageFileReader::ItkImageFileReader()
: m_FileName(""), m_FilePrefix(""), m_FilePattern("")
{
}
mitk::ItkImageFileReader::~ItkImageFileReader()
{
}
diff --git a/Core/Code/IO/mitkSurfaceVtkWriter.txx b/Core/Code/IO/mitkSurfaceVtkWriter.txx
index 9fc7fe2c25..8705d8dbdc 100644
--- a/Core/Code/IO/mitkSurfaceVtkWriter.txx
+++ b/Core/Code/IO/mitkSurfaceVtkWriter.txx
@@ -1,174 +1,173 @@
/*===================================================================
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 "mitkSurfaceVtkWriter.h"
#include <vtkConfigure.h>
#include <vtkPolyData.h>
#include <vtkLinearTransform.h>
#include <vtkTransformPolyDataFilter.h>
#include <vtkErrorCode.h>
#include <sstream>
#include <sys/stat.h>
#include <sys/types.h>
#include <stdio.h>
template <class VTKWRITER>
mitk::SurfaceVtkWriter<VTKWRITER>::SurfaceVtkWriter()
: m_WriterWriteHasReturnValue( false )
{
this->SetNumberOfRequiredInputs( 1 );
m_VtkWriter = vtkSmartPointer<VtkWriterType>::New();
//enable to write ascii-formatted-file
//m_VtkWriter->SetFileTypeToASCII();
SetDefaultExtension(); // and information about the Writer's Write() method
}
template <class VTKWRITER>
mitk::SurfaceVtkWriter<VTKWRITER>::~SurfaceVtkWriter()
{
}
template <class VTKWRITER>
void mitk::SurfaceVtkWriter<VTKWRITER>::SetDefaultExtension()
{
m_Extension = ".vtk";
}
template<class VTKWRITER>
void mitk::SurfaceVtkWriter<VTKWRITER>::ExecuteWrite( VtkWriterType* vtkWriter )
{
if ( vtkWriter->Write() == 0 || vtkWriter->GetErrorCode() != 0 )
{
itkExceptionMacro(<<"Error during surface writing: " << vtkErrorCode::GetStringFromErrorCode(vtkWriter->GetErrorCode()) );
}
}
template <class VTKWRITER>
void mitk::SurfaceVtkWriter<VTKWRITER>::GenerateData()
{
if ( m_FileName == "" )
{
itkWarningMacro( << "Sorry, filename has not been set!" );
return ;
}
mitk::Surface::Pointer input = const_cast<mitk::Surface*>(this->GetInput());
vtkSmartPointer<vtkTransformPolyDataFilter> transformPolyData = vtkSmartPointer<vtkTransformPolyDataFilter>::New();
vtkPolyData * polyData;
- Geometry3D* geometry;
+ BaseGeometry* geometry;
unsigned int t, timesteps = input->GetTimeGeometry()->CountTimeSteps();
for(t = 0; t < timesteps; ++t)
{
// surfaces do not have to exist in all timeteps; therefor, only write valid surfaces
if( input->GetVtkPolyData(t) == NULL ) continue;
std::ostringstream filename;
filename.imbue(::std::locale::classic());
geometry = input->GetGeometry(t);
if ( timesteps > 1 )
{
if(input->GetTimeGeometry()->IsValidTimeStep(t))
{
- const TimeBounds& timebounds = geometry->GetTimeBounds();
+ const TimeBounds& timebounds = input->GetTimeGeometry()->GetTimeBounds(t);
filename << m_FileName.c_str() << "_S" << std::setprecision(0) << timebounds[0] << "_E" << std::setprecision(0) << timebounds[1] << "_T" << t << m_Extension;
}
else
{
itkWarningMacro(<<"Error on write: TimeGeometry invalid of surface " << filename.str() << ".");
filename << m_FileName.c_str() << "_T" << t << m_Extension;
}
m_VtkWriter->SetFileName(filename.str().c_str());
}
else
m_VtkWriter->SetFileName(m_FileName.c_str());
- geometry->TransferItkToVtkTransform();
transformPolyData->SetInputData(input->GetVtkPolyData(t));
transformPolyData->SetTransform(geometry->GetVtkTransform());
transformPolyData->UpdateWholeExtent();
polyData = transformPolyData->GetOutput();
m_VtkWriter->SetInputData(polyData);
ExecuteWrite( m_VtkWriter );
}
m_MimeType = "application/MITK.Surface";
}
template <class VTKWRITER>
void mitk::SurfaceVtkWriter<VTKWRITER>::SetInput( mitk::Surface* surface )
{
this->ProcessObject::SetNthInput( 0, surface );
}
template <class VTKWRITER>
const mitk::Surface* mitk::SurfaceVtkWriter<VTKWRITER>::GetInput()
{
if ( this->GetNumberOfInputs() < 1 )
{
return NULL;
}
else
{
return static_cast< const Surface * >( this->ProcessObject::GetInput( 0 ) );
}
}
template <class VTKWRITER>
bool mitk::SurfaceVtkWriter<VTKWRITER>::CanWriteDataType( DataNode* input )
{
if ( input )
{
BaseData* data = input->GetData();
if ( data )
{
Surface::Pointer surface = dynamic_cast<Surface*>( data );
if( surface.IsNotNull() )
{
SetDefaultExtension();
return true;
}
}
}
return false;
}
template <class VTKWRITER>
void mitk::SurfaceVtkWriter<VTKWRITER>::SetInput( DataNode* input )
{
if( input && CanWriteDataType( input ) )
SetInput( dynamic_cast<Surface*>( input->GetData() ) );
}
template <class VTKWRITER>
std::string mitk::SurfaceVtkWriter<VTKWRITER>::GetWritenMIMEType()
{
return m_MimeType;
}
template <class VTKWRITER>
std::string mitk::SurfaceVtkWriter<VTKWRITER>::GetFileExtension()
{
return m_Extension;
}
diff --git a/Core/Code/Interactions/mitkAffineInteractor.cpp b/Core/Code/Interactions/mitkAffineInteractor.cpp
index f15650f790..24a9f30704 100755
--- a/Core/Code/Interactions/mitkAffineInteractor.cpp
+++ b/Core/Code/Interactions/mitkAffineInteractor.cpp
@@ -1,382 +1,382 @@
/*===================================================================
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 "mitkAffineInteractor.h"
#include "mitkInteractionConst.h"
#include "mitkDataNode.h"
#include "mitkGeometry3D.h"
#include "mitkRotationOperation.h"
#include "mitkPointOperation.h"
#include "mitkPositionEvent.h"
#include "mitkStateEvent.h"
#include "mitkOperationEvent.h"
#include "mitkUndoController.h"
#include "mitkDisplayPositionEvent.h"
#include "vtkTransform.h"
#include "mitkVtkPropRenderer.h"
#include "mitkProperties.h"
#include <itkBoundingBox.h>
#include <itkFixedArray.h>
#include "mitkAction.h"
//#include "mitkBoundingObject.h"
#include "mitkRenderingManager.h"
#include <math.h>
#include <vtkWorldPointPicker.h>
#include <vtkPicker.h>
#include "mitkGlobalInteraction.h"
#include "mitkFocusManager.h"
#include "mitkEventMapper.h"
#include "vtkProp3D.h"
#include "mitkVtkInteractorCameraController.h"
#include <vtkInteractorObserver.h>
#include "vtkRenderer.h"
#include "vtkCamera.h"
#include <vtkInteractorObserver.h>
#include <iostream>
mitk::AffineInteractor::AffineInteractor(const char * type, DataNode* dataNode)
: Interactor(type, dataNode)
{
}
bool mitk::AffineInteractor::ExecuteAction(Action* action, mitk::StateEvent const* stateEvent)
{
bool ok = false;
TimeGeometry* inputTimeGeometry = GetData()->GetTimeGeometry();
if (inputTimeGeometry == NULL)
return false;
- Geometry3D* geometry = inputTimeGeometry->GetGeometryForTimeStep(m_TimeStep);
+ BaseGeometry* geometry = inputTimeGeometry->GetGeometryForTimeStep(m_TimeStep);
mitk::DisplayPositionEvent const *event = dynamic_cast <const mitk::DisplayPositionEvent *> (stateEvent->GetEvent());
switch (action->GetActionId())
{
case AcCHECKELEMENT:
{
mitk::Point3D worldPoint = event->GetWorldPosition();
/* now we have a worldpoint. check if it is inside our object and select/deselect it accordingly */
mitk::BoolProperty::Pointer selected;
mitk::ColorProperty::Pointer color;
std::auto_ptr<StateEvent> newStateEvent;
selected = dynamic_cast<mitk::BoolProperty*>(m_DataNode->GetProperty("selected"));
if ( selected.IsNull() ) {
selected = mitk::BoolProperty::New();
m_DataNode->GetPropertyList()->SetProperty("selected", selected);
}
color = dynamic_cast<mitk::ColorProperty*>(m_DataNode->GetProperty("color"));
if ( color.IsNull() ) {
color = mitk::ColorProperty::New();
m_DataNode->GetPropertyList()->SetProperty("color", color);
}
if (this->CheckSelected(worldPoint, m_TimeStep))
{
newStateEvent.reset(new mitk::StateEvent(EIDYES, stateEvent->GetEvent()));
selected->SetValue(true);
color->SetColor(1.0, 1.0, 0.0);
}
else
{
newStateEvent.reset(new mitk::StateEvent(EIDNO, stateEvent->GetEvent()));
selected = mitk::BoolProperty::New(false);
color->SetColor(0.0, 0.0, 1.0);
/*
mitk::BoundingObject* b = dynamic_cast<mitk::BoundingObject*>(m_DataNode->GetData());
if(b != NULL)
{
color = (b->GetPositive())? mitk::ColorProperty::New(0.0, 0.0, 1.0) : mitk::ColorProperty::New(1.0, 0.0, 0.0); // if deselected, a boundingobject is colored according to its positive/negative state
}
else
color = mitk::ColorProperty::New(1.0, 1.0, 1.0); // if deselcted and no bounding object, color is white
*/
}
/* write new state (selected/not selected) to the property */
this->HandleEvent( newStateEvent.get() );
ok = true;
break;
}
case AcADD:
{
mitk::Point3D worldPoint = event->GetWorldPosition();
std::auto_ptr<StateEvent> newStateEvent;
if (this->CheckSelected(worldPoint, m_TimeStep))
{
newStateEvent.reset(new mitk::StateEvent(EIDYES, event));
m_DataNode->GetPropertyList()->SetProperty("selected", mitk::BoolProperty::New(true)); // TODO: Generate an Select Operation and send it to the undo controller ?
}
else // if not selected, do nothing (don't deselect)
{
newStateEvent.reset(new mitk::StateEvent(EIDNO, event));
}
//call HandleEvent to leave the guard-state
this->HandleEvent( newStateEvent.get() );
ok = true;
break;
}
case AcTRANSLATESTART:
case AcROTATESTART:
case AcSCALESTART:
{
m_LastMousePosition = event->GetWorldPosition();
ok = true;
break;
}
case AcTRANSLATE:
{
mitk::Point3D newPosition;
newPosition = event->GetWorldPosition();
newPosition -= m_LastMousePosition.GetVectorFromOrigin(); // compute difference between actual and last mouse position
m_LastMousePosition = event->GetWorldPosition(); // save current mouse position as last position
/* create operation with position difference */
mitk::PointOperation* doOp = new mitk::PointOperation(OpMOVE, newPosition, 0); // Index is not used here
if (m_UndoEnabled) //write to UndoMechanism
{
mitk::Point3D oldPosition=geometry->GetCornerPoint(0);
PointOperation* undoOp = new mitk::PointOperation(OpMOVE, oldPosition, 0);
OperationEvent *operationEvent = new OperationEvent(geometry, doOp, undoOp);
m_UndoController->SetOperationEvent(operationEvent);
}
/* execute the Operation */
geometry->ExecuteOperation(doOp);
if (!m_UndoEnabled)
delete doOp;
ok = true;
break;
}
case AcTRANSLATEEND:
{
m_UndoController->SetOperationEvent(new UndoStackItem("Move object"));
m_DataNode->InvokeEvent(TranslateEvent());
break;
}
case AcROTATE:
{
mitk::Point3D p = event->GetWorldPosition();
mitk::Vector3D newPosition = p.GetVectorFromOrigin();
mitk::Point3D dataPosition = geometry->GetCenter();
newPosition = newPosition - dataPosition.GetVectorFromOrigin(); // calculate vector from center of the data object to the current mouse position
mitk::Vector3D startPosition = m_LastMousePosition.GetVectorFromOrigin() - dataPosition.GetVectorFromOrigin(); // calculate vector from center of the data object to the last mouse position
/* calculate rotation axis (by calculating the cross produkt of the vectors) */
mitk::Vector3D rotationaxis;
rotationaxis[0] = startPosition[1] * newPosition[2] - startPosition[2] * newPosition[1];
rotationaxis[1] = startPosition[2] * newPosition[0] - startPosition[0] * newPosition[2];
rotationaxis[2] = startPosition[0] * newPosition[1] - startPosition[1] * newPosition[0];
/* calculate rotation angle in degrees */
mitk::ScalarType angle = atan2((mitk::ScalarType)rotationaxis.GetNorm(), (mitk::ScalarType) (newPosition * startPosition)) * (180/vnl_math::pi);
m_LastMousePosition = p; // save current mouse position as last mouse position
/* create operation with center of rotation, angle and axis and send it to the geometry and Undo controller */
mitk::RotationOperation* doOp = new mitk::RotationOperation(OpROTATE, dataPosition, rotationaxis, angle);
if (m_UndoEnabled) //write to UndoMechanism
{
RotationOperation* undoOp = new mitk::RotationOperation(OpROTATE, dataPosition, rotationaxis, -angle);
OperationEvent *operationEvent = new OperationEvent(geometry, doOp, undoOp);
m_UndoController->SetOperationEvent(operationEvent);
}
/* execute the Operation */
geometry->ExecuteOperation(doOp);
if(!m_UndoEnabled)
delete doOp;
ok = true;
break;
}
case AcROTATEEND:
{
m_UndoController->SetOperationEvent(new UndoStackItem("Rotate object"));
m_DataNode->InvokeEvent(RotateEvent());
break;
}
case AcSCALE:
{
mitk::Point3D p = event->GetWorldPosition();
mitk::Vector3D v = p - m_LastMousePosition;
/* calculate scale changes */
mitk::Point3D newScale;
newScale[0] = (geometry->GetAxisVector(0) * v) / geometry->GetExtentInMM(0); // Scalarprodukt of normalized Axis
newScale[1] = (geometry->GetAxisVector(1) * v) / geometry->GetExtentInMM(1); // and direction vector of mouse movement
newScale[2] = (geometry->GetAxisVector(2) * v) / geometry->GetExtentInMM(2); // is the length of the movement vectors
// projection onto the axis
/* convert movement to local object coordinate system and mirror it to the positive quadrant */
Vector3D start;
Vector3D end;
mitk::ScalarType convert[3];
itk2vtk(m_LastMousePosition, convert);
geometry->GetVtkTransform()->GetInverse()->TransformPoint(convert, convert); // transform start point to local object coordinates
start[0] = fabs(convert[0]); start[1] = fabs(convert[1]); start[2] = fabs(convert[2]); // mirror it to the positive quadrant
itk2vtk(p, convert);
geometry->GetVtkTransform()->GetInverse()->TransformPoint(convert, convert); // transform end point to local object coordinates
end[0] = fabs(convert[0]); end[1] = fabs(convert[1]); end[2] = fabs(convert[2]); // mirror it to the positive quadrant
/* check if mouse movement is towards or away from the objects axes and adjust scale factors accordingly */
Vector3D vLocal = start - end;
newScale[0] = (vLocal[0] > 0.0) ? -fabs(newScale[0]) : +fabs(newScale[0]);
newScale[1] = (vLocal[1] > 0.0) ? -fabs(newScale[1]) : +fabs(newScale[1]);
newScale[2] = (vLocal[2] > 0.0) ? -fabs(newScale[2]) : +fabs(newScale[2]);
m_LastMousePosition = p; // update lastPosition for next mouse move
/* generate Operation and send it to the receiving geometry */
PointOperation* doOp = new mitk::PointOperation(OpSCALE, newScale, 0); // Index is not used here
if (m_UndoEnabled) //write to UndoMechanism
{
mitk::Point3D oldScaleData;
oldScaleData[0] = -newScale[0];
oldScaleData[1] = -newScale[1];
oldScaleData[2] = -newScale[2];
PointOperation* undoOp = new mitk::PointOperation(OpSCALE, oldScaleData, 0);
OperationEvent *operationEvent = new OperationEvent(geometry, doOp, undoOp);
m_UndoController->SetOperationEvent(operationEvent);
}
/* execute the Operation */
geometry->ExecuteOperation(doOp);
if(!m_UndoEnabled)
delete doOp;
/* Update Volume Property with new value */
/*
mitk::BoundingObject* b = dynamic_cast<mitk::BoundingObject*>(m_DataNode->GetData());
if (b != NULL)
{
m_DataNode->GetPropertyList()->SetProperty("volume", FloatProperty::New(b->GetVolume()));
//MITK_INFO << "Volume of Boundingobject is " << b->GetVolume()/1000.0 << " ml" << std::endl;
}
*/
ok = true;
break;
}
case AcSCALEEND:
{
m_UndoController->SetOperationEvent(new UndoStackItem("Scale object"));
m_DataNode->InvokeEvent(ScaleEvent());
break;
}
default:
ok = Superclass::ExecuteAction(action, stateEvent);//, objectEventId, groupEventId);
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
return ok;
}
bool mitk::AffineInteractor::CheckSelected(const mitk::Point3D& worldPoint, int timestep )
{
bool selected = false;
if (m_DataNode->GetBoolProperty("selected", selected) == false) // if property does not exist
m_DataNode->SetProperty("selected", mitk::BoolProperty::New(false)); // create it
// check if mouseclick has hit the object
/*
mitk::BoundingObject::Pointer boundingObject = dynamic_cast<mitk::BoundingObject*>(m_DataNode->GetData());
if(boundingObject.IsNotNull()) // if it is a bounding object, use its inside function for exact hit calculation
{
selected = boundingObject->IsInside(worldPoint); // check if point is inside the object
}
else // use the data objects bounding box to determine if hit
*/
{
GetData()->GetTimeGeometry()->Update();
- const Geometry3D* geometry = GetData()->GetGeometry( timestep );
+ const BaseGeometry* geometry = GetData()->GetGeometry( timestep );
selected = geometry->IsInside(worldPoint);
}
return selected;
}
bool mitk::AffineInteractor::ConvertDisplayEventToWorldPosition(mitk::DisplayPositionEvent const* displayEvent, mitk::Point3D& worldPoint)
{
mitk::Point2D displayPoint = displayEvent->GetDisplayPosition();
/* Copied from vtk Sphere widget */
double focalPoint[4], position[4];
double z;
FocusManager::FocusElement* fe = mitk::GlobalInteraction::GetInstance()->GetFocus();
mitk::VtkPropRenderer* glRenderer = dynamic_cast<mitk::VtkPropRenderer*>( fe );
if ( glRenderer == NULL )
{
return false;
}
vtkRenderer *renderer = glRenderer->GetVtkRenderer();
vtkCamera *camera = renderer->GetActiveCamera();
if ( !camera )
{
return false;
}
// Compute the two points defining the motion vector
camera->GetFocalPoint(focalPoint);
//this->ComputeWorldToDisplay(focalPoint[0], focalPoint[1], focalPoint[2], focalPoint);
renderer->SetWorldPoint(focalPoint[0], focalPoint[1], focalPoint[2], 1.0);
renderer->WorldToDisplay();
renderer->GetDisplayPoint(focalPoint);
z = focalPoint[2];
// this->ComputeDisplayToWorld(displayPoint.x, displayPoint.y, z, position);
renderer->SetDisplayPoint(displayPoint[0], displayPoint[1], z);
renderer->DisplayToWorld();
renderer->GetWorldPoint(position);
if (position[3])
{
worldPoint[0] = position[0] / position[3];
worldPoint[1] = position[1] / position[3];
worldPoint[2] = position[2] / position[3];
position[3] = 1.0;
}
else
{
worldPoint[0] = position[0];
worldPoint[1] = position[1];
worldPoint[2] = position[2];
}
return true;
}
float mitk::AffineInteractor::CanHandleEvent( StateEvent const* stateEvent ) const
{
float jd = 0.0f;
if ( stateEvent->GetEvent()->GetSender()->GetMapperID() == mitk::BaseRenderer::Standard3D )
{
MITK_DEBUG << "Sorry, mitkAffineInteractor does not support interaction in a 3D view at the moment.";
return jd;
}
return Superclass::CanHandleEvent( stateEvent );
}
diff --git a/Core/Code/Interactions/mitkCoordinateSupplier.cpp b/Core/Code/Interactions/mitkCoordinateSupplier.cpp
index 3055f0dae4..551ac8eadc 100755
--- a/Core/Code/Interactions/mitkCoordinateSupplier.cpp
+++ b/Core/Code/Interactions/mitkCoordinateSupplier.cpp
@@ -1,169 +1,166 @@
/*===================================================================
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 "mitkDisplayCoordinateOperation.h"
//has to be on top, otherwise compiler error!
#include "mitkCoordinateSupplier.h"
#include "mitkOperation.h"
#include "mitkOperationActor.h"
#include "mitkPointOperation.h"
#include "mitkPositionEvent.h"
#include "mitkStateEvent.h"
#include "mitkUndoController.h"
//and not here!
#include <string>
#include "mitkInteractionConst.h"
#include "mitkAction.h"
mitk::CoordinateSupplier::CoordinateSupplier(const char * type, mitk::OperationActor* operationActor)
: mitk::StateMachine(type), m_Destination(operationActor)
{
m_CurrentPoint.Fill(0);
}
mitk::CoordinateSupplier::~CoordinateSupplier()
{
-
}
bool mitk::CoordinateSupplier::ExecuteAction(Action* action, mitk::StateEvent const* stateEvent)
{
bool ok = false;
const PositionEvent* posEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent());
PointOperation* doOp=NULL;
if(posEvent!=NULL)
{
ScalarType timeInMS = 0;
if(stateEvent->GetEvent()->GetSender()!=NULL)
{
- const Geometry2D* worldGeometry = stateEvent->GetEvent()->GetSender()->GetCurrentWorldGeometry2D();
- assert( worldGeometry != NULL );
- timeInMS = worldGeometry->GetTimeBounds()[ 0 ];
+ timeInMS = stateEvent->GetEvent()->GetSender()->GetTime();
}
else
{
itkWarningMacro(<<"StateEvent::GetSender()==NULL - setting timeInMS to 0");
}
switch (action->GetActionId())
{
case AcNEWPOINT:
{
if (m_Destination == NULL)
return false;
m_OldPoint = posEvent->GetWorldPosition();
doOp = new mitk::PointOperation(OpADD, timeInMS, m_OldPoint, 0);
//Undo
if (m_UndoEnabled)
{
PointOperation* undoOp = new PointOperation(OpDELETE, m_OldPoint, 0);
OperationEvent *operationEvent = new OperationEvent( m_Destination, doOp, undoOp );
m_UndoController->SetOperationEvent(operationEvent);
}
//execute the Operation
m_Destination->ExecuteOperation(doOp);
if (!m_UndoEnabled)
delete doOp;
ok = true;
break;
}
case AcINITMOVEMENT:
{
if (m_Destination == NULL)
return false;
//move the point to the coordinate //not used, cause same to MovePoint... check xml-file
mitk::Point3D movePoint = posEvent->GetWorldPosition();
mitk::PointOperation doPointOp(OpMOVE, timeInMS, movePoint, 0);
//execute the Operation
m_Destination->ExecuteOperation(&doPointOp);
ok = true;
break;
}
case AcMOVEPOINT:
case AcMOVE:
{
mitk::Point3D movePoint = posEvent->GetWorldPosition();
m_CurrentPoint = movePoint;
if (m_Destination == NULL)
return false;
mitk::PointOperation doPointOp(OpMOVE, timeInMS, movePoint, 0);
//execute the Operation
m_Destination->ExecuteOperation(&doPointOp);
ok = true;
break;
}
case AcFINISHMOVEMENT:
{
if (m_Destination == NULL)
return false;
/*finishes a Movement from the coordinate supplier:
gets the lastpoint from the undolist and writes an undo-operation so
that the movement of the coordinatesupplier is undoable.*/
mitk::Point3D movePoint = posEvent->GetWorldPosition();
mitk::Point3D oldMovePoint; oldMovePoint.Fill(0);
doOp = new mitk::PointOperation(OpMOVE, timeInMS, movePoint, 0);
PointOperation finishOp(OpTERMINATE, movePoint, 0);
if (m_UndoEnabled )
{
//get the last Position from the UndoList
OperationEvent *lastOperationEvent = m_UndoController->GetLastOfType(m_Destination, OpMOVE);
if (lastOperationEvent != NULL)
{
PointOperation* lastOp = dynamic_cast<PointOperation *>(lastOperationEvent->GetOperation());
if (lastOp != NULL)
{
oldMovePoint = lastOp->GetPoint();
}
}
PointOperation* undoOp = new PointOperation(OpMOVE, timeInMS, oldMovePoint, 0, "Move slices");
OperationEvent *operationEvent = new OperationEvent(m_Destination, doOp, undoOp, "Move slices");
m_UndoController->SetOperationEvent(operationEvent);
}
//execute the Operation
m_Destination->ExecuteOperation(doOp);
if (!m_UndoEnabled)
delete doOp;
m_Destination->ExecuteOperation(&finishOp);
ok = true;
break;
}
default:
ok = false;
break;
}
return ok;
}
const mitk::DisplayPositionEvent* displPosEvent = dynamic_cast<const mitk::DisplayPositionEvent *>(stateEvent->GetEvent());
if(displPosEvent!=NULL)
{
return true;
}
return false;
}
diff --git a/Core/Code/Interactions/mitkInteractor.cpp b/Core/Code/Interactions/mitkInteractor.cpp
index f9b27c0f76..8bc4b95c12 100755
--- a/Core/Code/Interactions/mitkInteractor.cpp
+++ b/Core/Code/Interactions/mitkInteractor.cpp
@@ -1,301 +1,301 @@
/*===================================================================
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 "mitkInteractor.h"
#include <mitkDataNode.h>
#include <mitkDisplayPositionEvent.h>
#include <mitkPositionEvent.h>
#include <mitkGeometry3D.h>
#include <mitkAction.h>
#include <mitkOperationEvent.h>
#include <mitkStateEvent.h>
#include <mitkState.h>
#include <mitkUndoController.h>
//#include <mitkStatusBar.h>
#include <vtkCamera.h>
#include <vtkRenderer.h>
#include "mitkInteractionConst.h"
#include <vtkLinearTransform.h>
#include <itkVector.h>
#include <mitkModeOperation.h>
#include "mitkGlobalInteraction.h"
const std::string mitk::Interactor::XML_NODE_NAME = "interactor";
mitk::Interactor::Interactor(const char * type, DataNode* dataNode)
: StateMachine(type),
m_DataNode(dataNode),
m_Mode(SMDESELECTED)
{
if (m_DataNode != NULL)
m_DataNode->SetInteractor(this);
// handle these actions in those Methods
CONNECT_ACTION( AcMODEDESELECT, OnModeDeselect );
CONNECT_ACTION( AcMODESELECT, OnModeSelect );
CONNECT_ACTION( AcMODESUBSELECT, OnModeSubSelect );
}
mitk::BaseData* mitk::Interactor::GetData() const
{
if (m_DataNode != NULL)
return m_DataNode->GetData();
else
return NULL;
}
mitk::Interactor::SMMode mitk::Interactor::GetMode() const
{
return m_Mode;
}
bool mitk::Interactor::IsNotSelected() const
{
return (m_Mode==SMDESELECTED);
}
bool mitk::Interactor::IsSelected() const
{
return (m_Mode!=SMDESELECTED);
}
void mitk::Interactor::CreateModeOperation(ModeType mode)
{
ModeOperation* doOp = new ModeOperation(OpMODECHANGE, mode);
if (m_UndoEnabled)
{
ModeOperation* undoOp = new ModeOperation(OpMODECHANGE, this->GetMode());
OperationEvent *operationEvent = new OperationEvent(this, doOp, undoOp);
m_UndoController->SetOperationEvent(operationEvent);
}
this->ExecuteOperation(doOp);
if (!m_UndoEnabled)
delete doOp;
}
bool mitk::Interactor::OnModeDeselect(Action* /*action*/, StateEvent const*)
{
GlobalInteraction* global = GlobalInteraction::GetInstance();
if (global == NULL)
itkWarningMacro("Message from Interactor.cpp: GlobalInteraction == NULL! Check use of Interactor!");
if( this->GetMode() != SMDESELECTED)
{
this->CreateModeOperation(SMDESELECTED);
global->RemoveFromSelectedInteractors(this);
}
return true;
}
bool mitk::Interactor::OnModeSelect(Action* /*action*/, StateEvent const*)
{
GlobalInteraction* global = GlobalInteraction::GetInstance();
if (global == NULL)
itkWarningMacro("Message from Interactor.cpp: GlobalInteraction == NULL! Check use of Interactor!");
if( this->GetMode() != SMSELECTED)
{
this->CreateModeOperation(SMSELECTED);
global->AddToSelectedInteractors(this);
}
return true;
}
bool mitk::Interactor::OnModeSubSelect(Action* /*action*/, StateEvent const*)
{
//StatusBar::GetInstance()->DisplayText("Error! in XML-Interaction: an simple Interactor can not set in sub selected", 1102);
return false;
}
float mitk::Interactor::CanHandleEvent(StateEvent const* stateEvent) const
{
//return value for boundingbox
float returnvalueBB = 0.0,
//return value for a existing transition
returnvalueTransition = 0.0,
//return value for an existing key transition
returnvalueKey = 0.0;
//if it is a key event that can be handled in the current state
DisplayPositionEvent const *disPosEvent = dynamic_cast <const DisplayPositionEvent *> (stateEvent->GetEvent());
//Key event handling:
if (disPosEvent == NULL)
{
//check, if the current state has a transition waiting for that key event.
if (this->GetCurrentState()->GetTransition(stateEvent->GetId())!=NULL)
{
returnvalueKey = 0.5;
}
}
//Mouse event handling:
//on MouseMove do nothing! reimplement if needed differently
if (stateEvent->GetEvent()->GetType() == Type_MouseMove)
{
return 0;
}
//if the event can be understood and if there is a transition waiting for that event
if (this->GetCurrentState()->GetTransition(stateEvent->GetId())!=NULL)
{
returnvalueTransition = 0.5;//it can be understood
}
//compute the center of the data taken care of if != NULL
if (GetData() != NULL)
{
DisplayPositionEvent const *event = dynamic_cast <const DisplayPositionEvent *> (stateEvent->GetEvent());
if (event != NULL)
{
//transforming the world position to local coordinate system
Point3D point;
GetData()->GetTimeGeometry()->Update();
TimeStepType timeStep = stateEvent->GetEvent()->GetSender()->GetTimeStep();
GetData()->GetGeometry(timeStep)->WorldToIndex(event->GetWorldPosition(), point);
const BoundingBox *bBox = GetData()->GetGeometry(timeStep)->GetBoundingBox();
if (bBox == NULL)
return 0;
//distance between center and point
BoundingBox::PointType center = bBox->GetCenter();
returnvalueBB = point.EuclideanDistanceTo(center);
// now check if object bounding box has a non-zero size
float bBoxSize = bBox->GetMaximum().EuclideanDistanceTo(bBox->GetMinimum() );
if( bBoxSize < 0.00001 ) return 0; // bounding box too small?
//now compared to size of bounding box to get value between 0 and 1;
returnvalueBB = returnvalueBB/bBoxSize;
//safety: if by now return value is not in [0,1], then return 0!
if (returnvalueBB>1 || returnvalueBB<0)
returnvalueBB = 0;
// A return value of 1 is good, 0 is bad -> reverse value
returnvalueBB = 1 - returnvalueBB;
//check if the given position lies inside the data object
if (bBox->IsInside(point))
{
//mapped between 0.5 and 1
returnvalueBB = 0.5 + (returnvalueBB/ 2);
}
else
{
//set it in range between 0 and 0.5
returnvalueBB = returnvalueBB / 2;
}
}
}
//else
// itkWarningMacro("Data of Interactor is NULL! Please check setup of Interactors!");
return std::max(returnvalueBB, std::max(returnvalueKey, returnvalueTransition));
}
void mitk::Interactor::ExecuteOperation(Operation* operation)
{
switch (operation->GetOperationType())
{
case OpMODECHANGE:
{
ModeOperation *modeOp = dynamic_cast<ModeOperation*>(operation);
if (modeOp)
{
m_Mode = modeOp->GetMode();
}
}
break;
default:
Superclass::ExecuteOperation(operation);
}
}
const std::string& mitk::Interactor::GetXMLNodeName() const
{
return XML_NODE_NAME;
}
void mitk::Interactor::SetDataNode( DataNode* dataNode )
{
m_DataNode = dataNode;
//check for the number of time steps and initialize the vector of CurrentStatePointer accordingly
if (m_DataNode != NULL)
{
mitk::BaseData* data = dataNode->GetData();
if (data != NULL)
{
unsigned int timeSteps = data->GetTimeSteps();
//expand the list of StartStates according to the number of timesteps in data
if (timeSteps > 1)
this->InitializeStartStates(timeSteps);
}
}
}
void mitk::Interactor::UpdateTimeStep(unsigned int timeStep)
{
//check if the vector of StartStates contains enough pointers to use timeStep
if (timeStep >= 1)
{
// Make sure that the data (if time-resolved) has enough entries;
// if not, create the required extra ones (empty)
if (m_DataNode!= NULL)
if (m_DataNode->GetData()!= NULL)
m_DataNode->GetData()->Expand(timeStep+1); //+1 becuase the vector starts with 0 and the timesteps with 1
//now check for this object
this->ExpandStartStateVector(timeStep+1); //nothing is changed if the number of timesteps in data equals the number of startstates held in statemachine
}
//set the time to the given time
Superclass::UpdateTimeStep(timeStep);
//time has to be up-to-date
//check and throw an exception if not so
if (timeStep != m_TimeStep)
itkExceptionMacro(<<"Time is invalid. Take care of synchonization!");
}
bool mitk::Interactor::HandleEvent(StateEvent const* stateEvent)
{
//update the Time and then call Superclass
if (stateEvent != NULL)
{
mitk::Event const* event = stateEvent->GetEvent();
if (event != NULL)
{
mitk::BaseRenderer* sender = event->GetSender();
if (sender != NULL)
{
- //Get the TimeStep according to CurrentWorldGeometry2D
+ //Get the TimeStep according to CurrentWorldPlaneGeometry
unsigned int currentTimeStep = sender->GetTimeStep();
if (currentTimeStep != m_TimeStep)
this->UpdateTimeStep(currentTimeStep);
}
}
}
return Superclass::HandleEvent(stateEvent);
}
diff --git a/Core/Code/Interactions/mitkMoveBaseDataInteractor.cpp b/Core/Code/Interactions/mitkMoveBaseDataInteractor.cpp
index b3fa20353f..bca46309b9 100644
--- a/Core/Code/Interactions/mitkMoveBaseDataInteractor.cpp
+++ b/Core/Code/Interactions/mitkMoveBaseDataInteractor.cpp
@@ -1,189 +1,189 @@
/*===================================================================
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 "mitkMoveBaseDataInteractor.h"
#include "mitkInteractionConst.h"
#include <mitkDataNode.h>
#include "mitkDisplayPositionEvent.h"
#include "mitkStateEvent.h"
#include "mitkProperties.h"
//for an temporary update
#include "mitkRenderingManager.h"
//## Default Constructor
mitk::MoveBaseDataInteractor
::MoveBaseDataInteractor(const char * type, DataNode* dataNode)
:Interactor(type, dataNode)
{
//define the colors for selected/deselected state
m_DataNode->AddProperty( "MovingInteractor.SelectedColor", ColorProperty::New(0.0,1.0,0.0) );
m_DataNode->AddProperty( "MovingInteractor.DeselectedColor", ColorProperty::New(0.0,0.0,1.0) );
//save the previous color of the node, in order to restore it after the interactor is destroyed
mitk::ColorProperty::Pointer priorColor = dynamic_cast<mitk::ColorProperty*>(m_DataNode->GetProperty("color"));
if ( priorColor.IsNotNull() )
{
mitk::ColorProperty::Pointer tmpCopyOfPriorColor = mitk::ColorProperty::New();
tmpCopyOfPriorColor->SetColor( priorColor->GetColor() );
m_DataNode->AddProperty( "MovingInteractor.PriorColor", tmpCopyOfPriorColor );
}
}
mitk::MoveBaseDataInteractor::~MoveBaseDataInteractor()
{
mitk::ColorProperty::Pointer color = dynamic_cast<mitk::ColorProperty*>(m_DataNode->GetProperty("MovingInteractor.PriorColor"));
if ( color.IsNotNull() )
{
m_DataNode->GetPropertyList()->SetProperty("color", color);
}
m_DataNode->GetPropertyList()->DeleteProperty("MovingInteractor.SelectedColor");
m_DataNode->GetPropertyList()->DeleteProperty("MovingInteractor.DeselectedColor");
m_DataNode->GetPropertyList()->DeleteProperty("MovingInteractor.PriorColor");
//update rendering
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
bool mitk::MoveBaseDataInteractor::ExecuteAction( Action* action, mitk::StateEvent const* stateEvent )
{
bool ok = false;
/*Each case must watch the type of the event!*/
switch (action->GetActionId())
{
case AcDONOTHING:
ok = true;
break;
case AcCHECKELEMENT:
/*
* picking: Answer the question if the given position within stateEvent is close enough to select an object
* send yes if close enough and no if not picked
*/
{
mitk::DisplayPositionEvent const *posEvent = dynamic_cast <const mitk::DisplayPositionEvent *> (stateEvent->GetEvent());
if (posEvent == NULL)
{
MITK_WARN<<"Wrong usage of mitkMoveBaseDataInteractor! Aborting interaction!\n";
return false;
}
mitk::Point3D worldPoint = posEvent->GetWorldPosition();
/* now we have a worldpoint. check if it is inside our object and select/deselect it accordingly */
std::auto_ptr<StateEvent> newStateEvent;
- const Geometry3D* geometry = GetData()->GetUpdatedTimeGeometry()->GetGeometryForTimeStep( m_TimeStep );
+ const BaseGeometry* geometry = GetData()->GetUpdatedTimeGeometry()->GetGeometryForTimeStep( m_TimeStep );
if (geometry->IsInside(worldPoint))
newStateEvent.reset(new mitk::StateEvent(EIDYES, stateEvent->GetEvent()));
else
newStateEvent.reset(new mitk::StateEvent(EIDNO, stateEvent->GetEvent()));
/* write new state (selected/not selected) to the property */
this->HandleEvent( newStateEvent.get() );
ok = true;
break;
}
case AcSELECT:
// select the data
{
mitk::BoolProperty::Pointer selected = dynamic_cast<mitk::BoolProperty*>(m_DataNode->GetProperty("selected"));
if ( selected.IsNull() )
{
selected = mitk::BoolProperty::New();
m_DataNode->GetPropertyList()->SetProperty("selected", selected);
}
mitk::ColorProperty::Pointer selectedColor = dynamic_cast<mitk::ColorProperty*>(m_DataNode->GetProperty("MovingInteractor.SelectedColor"));
if ( selectedColor.IsNotNull() )
{
m_DataNode->GetPropertyList()->SetProperty("color", selectedColor);
}
selected->SetValue(true);
//update rendering
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
ok = true;
break;
}
case AcDESELECT:
//deselect the data
{
mitk::BoolProperty::Pointer selected = dynamic_cast<mitk::BoolProperty*>(m_DataNode->GetProperty("selected"));
if ( selected.IsNull() )
{
selected = mitk::BoolProperty::New();
m_DataNode->GetPropertyList()->SetProperty("selected", selected);
}
mitk::ColorProperty::Pointer deselectedColor =
dynamic_cast<mitk::ColorProperty*>(m_DataNode->GetProperty("MovingInteractor.DeselectedColor"));
if ( deselectedColor.IsNotNull() )
{
m_DataNode->GetPropertyList()->SetProperty("color", deselectedColor);
}
selected = mitk::BoolProperty::New(false);
//update rendering
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
ok = true;
break;
}
case AcMOVE:
{
//modify Geometry from data as given in parameters or in event
mitk::IntProperty* xP = dynamic_cast<mitk::IntProperty*>(action->GetProperty("DIRECTION_X"));
mitk::IntProperty* yP = dynamic_cast<mitk::IntProperty*>(action->GetProperty("DIRECTION_Y"));
mitk::IntProperty* zP = dynamic_cast<mitk::IntProperty*>(action->GetProperty("DIRECTION_Z"));
if (xP == NULL || yP == NULL || zP == NULL)
{
MITK_WARN<<"No properties returned\n!";
return false;
}
mitk::Vector3D movementVector;
movementVector.SetElement(0, (float) xP->GetValue());
movementVector.SetElement(1, (float) yP->GetValue());
movementVector.SetElement(2, (float) zP->GetValue());
- Geometry3D* geometry = m_DataNode->GetData()->GetUpdatedTimeGeometry()->GetGeometryForTimeStep( m_TimeStep );
+ BaseGeometry* geometry = m_DataNode->GetData()->GetUpdatedTimeGeometry()->GetGeometryForTimeStep( m_TimeStep );
geometry->Translate(movementVector);
// indicate modification of data tree node
m_DataNode->Modified();
//update rendering
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
ok = true;
break;
}
default:
return Superclass::ExecuteAction( action, stateEvent );
}
return ok;
}
/**
\example mitkMoveBaseDataInteractor.cpp
* This is an example of how to implement a new Interactor.
* See more details about this example in tutorial Step10.
*/
diff --git a/Core/Code/Rendering/mitkBaseRenderer.cpp b/Core/Code/Rendering/mitkBaseRenderer.cpp
index f2418cb26f..1d7454239f 100644
--- a/Core/Code/Rendering/mitkBaseRenderer.cpp
+++ b/Core/Code/Rendering/mitkBaseRenderer.cpp
@@ -1,876 +1,876 @@
/*===================================================================
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 "mitkBaseRenderer.h"
#include "mitkMapper.h"
#include "mitkResliceMethodProperty.h"
#include "mitkKeyEvent.h"
// Geometries
#include "mitkPlaneGeometry.h"
#include "mitkSlicedGeometry3D.h"
// Controllers
#include "mitkCameraController.h"
#include "mitkSliceNavigationController.h"
#include "mitkCameraRotationController.h"
#include "mitkVtkInteractorCameraController.h"
#ifdef MITK_USE_TD_MOUSE
#include "mitkTDMouseVtkCameraController.h"
#else
#include "mitkCameraController.h"
#endif
#include "mitkVtkLayerController.h"
// Events // TODO: INTERACTION_LEGACY
#include "mitkEventMapper.h"
#include "mitkGlobalInteraction.h"
#include "mitkPositionEvent.h"
#include "mitkDisplayPositionEvent.h"
#include "mitkProperties.h"
#include "mitkWeakPointerProperty.h"
#include "mitkInteractionConst.h"
#include "mitkOverlayManager.h"
// VTK
#include <vtkLinearTransform.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkCamera.h>
#include <vtkProperty.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
mitk::BaseRenderer::BaseRendererMapType mitk::BaseRenderer::baseRendererMap;
mitk::BaseRenderer* mitk::BaseRenderer::GetInstance(vtkRenderWindow * renWin)
{
for (BaseRendererMapType::iterator mapit = baseRendererMap.begin(); mapit != baseRendererMap.end(); mapit++)
{
if ((*mapit).first == renWin)
return (*mapit).second;
}
return NULL;
}
void mitk::BaseRenderer::AddInstance(vtkRenderWindow* renWin, BaseRenderer* baseRenderer)
{
if (renWin == NULL || baseRenderer == NULL)
return;
// ensure that no BaseRenderer is managed twice
mitk::BaseRenderer::RemoveInstance(renWin);
baseRendererMap.insert(BaseRendererMapType::value_type(renWin, baseRenderer));
}
void mitk::BaseRenderer::RemoveInstance(vtkRenderWindow* renWin)
{
BaseRendererMapType::iterator mapit = baseRendererMap.find(renWin);
if (mapit != baseRendererMap.end())
baseRendererMap.erase(mapit);
}
mitk::BaseRenderer* mitk::BaseRenderer::GetByName(const std::string& name)
{
for (BaseRendererMapType::iterator mapit = baseRendererMap.begin(); mapit != baseRendererMap.end(); mapit++)
{
if ((*mapit).second->m_Name == name)
return (*mapit).second;
}
return NULL;
}
vtkRenderWindow* mitk::BaseRenderer::GetRenderWindowByName(const std::string& name)
{
for (BaseRendererMapType::iterator mapit = baseRendererMap.begin(); mapit != baseRendererMap.end(); mapit++)
{
if ((*mapit).second->m_Name == name)
return (*mapit).first;
}
return NULL;
}
mitk::BaseRenderer::BaseRenderer(const char* name, vtkRenderWindow * renWin, mitk::RenderingManager* rm,RenderingMode::Type renderingMode) :
m_RenderWindow(NULL), m_VtkRenderer(NULL), m_MapperID(defaultMapper), m_DataStorage(NULL), m_RenderingManager(rm), m_LastUpdateTime(0), m_CameraController(
NULL), m_SliceNavigationController(NULL), m_CameraRotationController(NULL), /*m_Size(),*/
- m_Focused(false), m_WorldGeometry(NULL), m_WorldTimeGeometry(NULL), m_CurrentWorldGeometry(NULL), m_CurrentWorldGeometry2D(NULL), m_DisplayGeometry(
- NULL), m_Slice(0), m_TimeStep(), m_CurrentWorldGeometry2DUpdateTime(), m_DisplayGeometryUpdateTime(), m_TimeStepUpdateTime(), m_WorldGeometryData(
- NULL), m_DisplayGeometryData(NULL), m_CurrentWorldGeometry2DData(NULL), m_WorldGeometryNode(NULL), m_DisplayGeometryNode(NULL), m_CurrentWorldGeometry2DNode(
- NULL), m_DisplayGeometryTransformTime(0), m_CurrentWorldGeometry2DTransformTime(0), m_Name(name), /*m_Bounds(),*/m_EmptyWorldGeometry(
+ m_Focused(false), m_WorldGeometry(NULL), m_WorldTimeGeometry(NULL), m_CurrentWorldGeometry(NULL), m_CurrentWorldPlaneGeometry(NULL), m_DisplayGeometry(
+ NULL), m_Slice(0), m_TimeStep(), m_CurrentWorldPlaneGeometryUpdateTime(), m_DisplayGeometryUpdateTime(), m_TimeStepUpdateTime(), m_WorldGeometryData(
+ NULL), m_DisplayGeometryData(NULL), m_CurrentWorldPlaneGeometryData(NULL), m_WorldGeometryNode(NULL), m_DisplayGeometryNode(NULL), m_CurrentWorldPlaneGeometryNode(
+ NULL), m_DisplayGeometryTransformTime(0), m_CurrentWorldPlaneGeometryTransformTime(0), m_Name(name), /*m_Bounds(),*/m_EmptyWorldGeometry(
true), m_NumberOfVisibleLODEnabledMappers(0)
{
m_Bounds[0] = 0;
m_Bounds[1] = 0;
m_Bounds[2] = 0;
m_Bounds[3] = 0;
m_Bounds[4] = 0;
m_Bounds[5] = 0;
if (name != NULL)
{
m_Name = name;
}
else
{
m_Name = "unnamed renderer";
itkWarningMacro(<< "Created unnamed renderer. Bad for serialization. Please choose a name.");
}
if (renWin != NULL)
{
m_RenderWindow = renWin;
m_RenderWindow->Register(NULL);
}
else
{
itkWarningMacro(<< "Created mitkBaseRenderer without vtkRenderWindow present.");
}
m_Size[0] = 0;
m_Size[1] = 0;
//instances.insert( this );
//adding this BaseRenderer to the List of all BaseRenderer
// TODO: INTERACTION_LEGACY
m_RenderingManager->GetGlobalInteraction()->AddFocusElement(this);
m_BindDispatcherInteractor = new mitk::BindDispatcherInteractor( GetName() );
WeakPointerProperty::Pointer rendererProp = WeakPointerProperty::New((itk::Object*) this);
- m_CurrentWorldGeometry2D = mitk::PlaneGeometry::New();
+ m_CurrentWorldPlaneGeometry = mitk::PlaneGeometry::New();
- m_CurrentWorldGeometry2DData = mitk::Geometry2DData::New();
- m_CurrentWorldGeometry2DData->SetGeometry2D(m_CurrentWorldGeometry2D);
- m_CurrentWorldGeometry2DNode = mitk::DataNode::New();
- m_CurrentWorldGeometry2DNode->SetData(m_CurrentWorldGeometry2DData);
- m_CurrentWorldGeometry2DNode->GetPropertyList()->SetProperty("renderer", rendererProp);
- m_CurrentWorldGeometry2DNode->GetPropertyList()->SetProperty("layer", IntProperty::New(1000));
+ m_CurrentWorldPlaneGeometryData = mitk::PlaneGeometryData::New();
+ m_CurrentWorldPlaneGeometryData->SetPlaneGeometry(m_CurrentWorldPlaneGeometry);
+ m_CurrentWorldPlaneGeometryNode = mitk::DataNode::New();
+ m_CurrentWorldPlaneGeometryNode->SetData(m_CurrentWorldPlaneGeometryData);
+ m_CurrentWorldPlaneGeometryNode->GetPropertyList()->SetProperty("renderer", rendererProp);
+ m_CurrentWorldPlaneGeometryNode->GetPropertyList()->SetProperty("layer", IntProperty::New(1000));
- m_CurrentWorldGeometry2DNode->SetProperty("reslice.thickslices", mitk::ResliceMethodProperty::New());
- m_CurrentWorldGeometry2DNode->SetProperty("reslice.thickslices.num", mitk::IntProperty::New(1));
+ m_CurrentWorldPlaneGeometryNode->SetProperty("reslice.thickslices", mitk::ResliceMethodProperty::New());
+ m_CurrentWorldPlaneGeometryNode->SetProperty("reslice.thickslices.num", mitk::IntProperty::New(1));
- m_CurrentWorldGeometry2DTransformTime = m_CurrentWorldGeometry2DNode->GetVtkTransform()->GetMTime();
+ m_CurrentWorldPlaneGeometryTransformTime = m_CurrentWorldPlaneGeometryNode->GetVtkTransform()->GetMTime();
m_DisplayGeometry = mitk::DisplayGeometry::New();
- m_DisplayGeometry->SetWorldGeometry(m_CurrentWorldGeometry2D);
- m_DisplayGeometryData = mitk::Geometry2DData::New();
- m_DisplayGeometryData->SetGeometry2D(m_DisplayGeometry);
+ m_DisplayGeometry->SetWorldGeometry(m_CurrentWorldPlaneGeometry);
+ m_DisplayGeometryData = mitk::PlaneGeometryData::New();
+ m_DisplayGeometryData->SetPlaneGeometry(m_DisplayGeometry);
m_DisplayGeometryNode = mitk::DataNode::New();
m_DisplayGeometryNode->SetData(m_DisplayGeometryData);
m_DisplayGeometryNode->GetPropertyList()->SetProperty("renderer", rendererProp);
m_DisplayGeometryTransformTime = m_DisplayGeometryNode->GetVtkTransform()->GetMTime();
mitk::SliceNavigationController::Pointer sliceNavigationController = mitk::SliceNavigationController::New("navigation");
sliceNavigationController->SetRenderer(this);
sliceNavigationController->ConnectGeometrySliceEvent(this);
sliceNavigationController->ConnectGeometryUpdateEvent(this);
sliceNavigationController->ConnectGeometryTimeEvent(this, false);
m_SliceNavigationController = sliceNavigationController;
m_CameraRotationController = mitk::CameraRotationController::New();
m_CameraRotationController->SetRenderWindow(m_RenderWindow);
m_CameraRotationController->AcquireCamera();
//if TD Mouse Interaction is activated, then call TDMouseVtkCameraController instead of VtkInteractorCameraController
#ifdef MITK_USE_TD_MOUSE
m_CameraController = mitk::TDMouseVtkCameraController::New();
#else
m_CameraController = mitk::CameraController::New(NULL);
#endif
m_VtkRenderer = vtkRenderer::New();
if( renderingMode == RenderingMode::DepthPeeling )
{
m_VtkRenderer->SetUseDepthPeeling(1);
m_VtkRenderer->SetMaximumNumberOfPeels(8);
m_VtkRenderer->SetOcclusionRatio(0.0);
}
if (mitk::VtkLayerController::GetInstance(m_RenderWindow) == NULL)
{
mitk::VtkLayerController::AddInstance(m_RenderWindow, m_VtkRenderer);
mitk::VtkLayerController::GetInstance(m_RenderWindow)->InsertSceneRenderer(m_VtkRenderer);
}
else
mitk::VtkLayerController::GetInstance(m_RenderWindow)->InsertSceneRenderer(m_VtkRenderer);
}
mitk::BaseRenderer::~BaseRenderer()
{
if (m_OverlayManager.IsNotNull())
{
m_OverlayManager->RemoveBaseRenderer(this);
}
if (m_VtkRenderer != NULL)
{
m_VtkRenderer->Delete();
m_VtkRenderer = NULL;
}
if (m_CameraController.IsNotNull())
m_CameraController->SetRenderer(NULL);
m_RenderingManager->GetGlobalInteraction()->RemoveFocusElement(this);
mitk::VtkLayerController::RemoveInstance(m_RenderWindow);
RemoveAllLocalStorages();
m_DataStorage = NULL;
if (m_BindDispatcherInteractor != NULL)
{
delete m_BindDispatcherInteractor;
}
if (m_RenderWindow != NULL)
{
m_RenderWindow->Delete();
m_RenderWindow = NULL;
}
}
void mitk::BaseRenderer::RemoveAllLocalStorages()
{
this->InvokeEvent(mitk::BaseRenderer::RendererResetEvent());
std::list<mitk::BaseLocalStorageHandler*>::iterator it;
for (it = m_RegisteredLocalStorageHandlers.begin(); it != m_RegisteredLocalStorageHandlers.end(); it++)
(*it)->ClearLocalStorage(this, false);
m_RegisteredLocalStorageHandlers.clear();
}
void mitk::BaseRenderer::RegisterLocalStorageHandler(mitk::BaseLocalStorageHandler *lsh)
{
m_RegisteredLocalStorageHandlers.push_back(lsh);
}
mitk::Dispatcher::Pointer mitk::BaseRenderer::GetDispatcher() const
{
return m_BindDispatcherInteractor->GetDispatcher();
}
mitk::Point3D mitk::BaseRenderer::Map2DRendererPositionTo3DWorldPosition(const Point2D& mousePosition) const
{
Point2D p_mm;
Point3D position;
if (m_MapperID == 1)
{
GetDisplayGeometry()->DisplayToWorld(mousePosition, p_mm);
GetDisplayGeometry()->Map(p_mm, position);
}
else if (m_MapperID == 2)
{
PickWorldPoint(mousePosition, position);
}
return position;
}
void mitk::BaseRenderer::UnregisterLocalStorageHandler(mitk::BaseLocalStorageHandler *lsh)
{
m_RegisteredLocalStorageHandlers.remove(lsh);
}
void mitk::BaseRenderer::SetDataStorage(DataStorage* storage)
{
if (storage != NULL)
{
m_DataStorage = storage;
m_BindDispatcherInteractor->SetDataStorage(m_DataStorage);
this->Modified();
}
}
const mitk::BaseRenderer::MapperSlotId mitk::BaseRenderer::defaultMapper = 1;
void mitk::BaseRenderer::Paint()
{
}
void mitk::BaseRenderer::Initialize()
{
}
void mitk::BaseRenderer::Resize(int w, int h)
{
m_Size[0] = w;
m_Size[1] = h;
if (m_CameraController)
m_CameraController->Resize(w, h); //(formerly problematic on windows: vtkSizeBug)
GetDisplayGeometry()->SetSizeInDisplayUnits(w, h);
}
void mitk::BaseRenderer::InitRenderer(vtkRenderWindow* renderwindow)
{
if (m_RenderWindow != NULL)
{
m_RenderWindow->Delete();
}
m_RenderWindow = renderwindow;
if (m_RenderWindow != NULL)
{
m_RenderWindow->Register(NULL);
}
RemoveAllLocalStorages();
if (m_CameraController.IsNotNull())
{
m_CameraController->SetRenderer(this);
}
}
void mitk::BaseRenderer::InitSize(int w, int h)
{
m_Size[0] = w;
m_Size[1] = h;
GetDisplayGeometry()->SetSizeInDisplayUnits(w, h, false);
GetDisplayGeometry()->Fit();
}
void mitk::BaseRenderer::SetSlice(unsigned int slice)
{
if (m_Slice != slice)
{
m_Slice = slice;
if (m_WorldTimeGeometry.IsNotNull())
{
SlicedGeometry3D* slicedWorldGeometry = dynamic_cast<SlicedGeometry3D*>(m_WorldTimeGeometry->GetGeometryForTimeStep(m_TimeStep).GetPointer());
if (slicedWorldGeometry != NULL)
{
if (m_Slice >= slicedWorldGeometry->GetSlices())
m_Slice = slicedWorldGeometry->GetSlices() - 1;
- SetCurrentWorldGeometry2D(slicedWorldGeometry->GetGeometry2D(m_Slice));
+ SetCurrentWorldPlaneGeometry(slicedWorldGeometry->GetPlaneGeometry(m_Slice));
SetCurrentWorldGeometry(slicedWorldGeometry);
}
}
else
Modified();
}
}
void mitk::BaseRenderer::SetOverlayManager(itk::SmartPointer<OverlayManager> overlayManager)
{
if(overlayManager.IsNull())
return;
if(this->m_OverlayManager.IsNotNull())
{
if(this->m_OverlayManager.GetPointer() == overlayManager.GetPointer())
{
return;
}
else
{
this->m_OverlayManager->RemoveBaseRenderer(this);
}
}
this->m_OverlayManager = overlayManager;
this->m_OverlayManager->AddBaseRenderer(this); //TODO
}
itk::SmartPointer<mitk::OverlayManager> mitk::BaseRenderer::GetOverlayManager()
{
if(this->m_OverlayManager.IsNull())
{
m_OverlayManager = mitk::OverlayManager::New();
m_OverlayManager->AddBaseRenderer(this);
}
return this->m_OverlayManager;
}
void mitk::BaseRenderer::SetTimeStep(unsigned int timeStep)
{
if (m_TimeStep != timeStep)
{
m_TimeStep = timeStep;
m_TimeStepUpdateTime.Modified();
if (m_WorldTimeGeometry.IsNotNull())
{
if (m_TimeStep >= m_WorldTimeGeometry->CountTimeSteps())
m_TimeStep = m_WorldTimeGeometry->CountTimeSteps() - 1;
SlicedGeometry3D* slicedWorldGeometry = dynamic_cast<SlicedGeometry3D*>(m_WorldTimeGeometry->GetGeometryForTimeStep(m_TimeStep).GetPointer());
if (slicedWorldGeometry != NULL)
{
- SetCurrentWorldGeometry2D(slicedWorldGeometry->GetGeometry2D(m_Slice));
+ SetCurrentWorldPlaneGeometry(slicedWorldGeometry->GetPlaneGeometry(m_Slice));
SetCurrentWorldGeometry(slicedWorldGeometry);
}
}
else
Modified();
}
}
int mitk::BaseRenderer::GetTimeStep(const mitk::BaseData* data) const
{
if ((data == NULL) || (data->IsInitialized() == false))
{
return -1;
}
return data->GetTimeGeometry()->TimePointToTimeStep(GetTime());
}
mitk::ScalarType mitk::BaseRenderer::GetTime() const
{
if (m_WorldTimeGeometry.IsNull())
{
return 0;
}
else
{
ScalarType timeInMS = m_WorldTimeGeometry->TimeStepToTimePoint(GetTimeStep());
if (timeInMS == ScalarTypeNumericTraits::NonpositiveMin())
return 0;
else
return timeInMS;
}
}
void mitk::BaseRenderer::SetWorldTimeGeometry(mitk::TimeGeometry* geometry)
{
assert(geometry != NULL);
itkDebugMacro("setting WorldTimeGeometry to " << geometry);
if (m_WorldTimeGeometry != geometry)
{
if (geometry->GetBoundingBoxInWorld()->GetDiagonalLength2() == 0)
return;
m_WorldTimeGeometry = geometry;
itkDebugMacro("setting WorldTimeGeometry to " << m_WorldTimeGeometry);
if (m_TimeStep >= m_WorldTimeGeometry->CountTimeSteps())
m_TimeStep = m_WorldTimeGeometry->CountTimeSteps() - 1;
- Geometry3D* geometry3d;
+ BaseGeometry* geometry3d;
geometry3d = m_WorldTimeGeometry->GetGeometryForTimeStep(m_TimeStep);
SetWorldGeometry3D(geometry3d);
}
}
-void mitk::BaseRenderer::SetWorldGeometry3D(mitk::Geometry3D* geometry)
+void mitk::BaseRenderer::SetWorldGeometry3D(mitk::BaseGeometry* geometry)
{
itkDebugMacro("setting WorldGeometry3D to " << geometry);
if (m_WorldGeometry != geometry)
{
if (geometry->GetBoundingBox()->GetDiagonalLength2() == 0)
return;
m_WorldGeometry = geometry;
SlicedGeometry3D* slicedWorldGeometry;
slicedWorldGeometry = dynamic_cast<SlicedGeometry3D*>(geometry);
- Geometry2D::Pointer geometry2d;
+ PlaneGeometry::Pointer geometry2d;
if (slicedWorldGeometry != NULL)
{
if (m_Slice >= slicedWorldGeometry->GetSlices() && (m_Slice != 0))
m_Slice = slicedWorldGeometry->GetSlices() - 1;
- geometry2d = slicedWorldGeometry->GetGeometry2D(m_Slice);
+ geometry2d = slicedWorldGeometry->GetPlaneGeometry(m_Slice);
if (geometry2d.IsNull())
{
PlaneGeometry::Pointer plane = mitk::PlaneGeometry::New();
plane->InitializeStandardPlane(slicedWorldGeometry);
geometry2d = plane;
}
SetCurrentWorldGeometry(slicedWorldGeometry);
}
else
{
- geometry2d = dynamic_cast<Geometry2D*>(geometry);
+ geometry2d = dynamic_cast<PlaneGeometry*>(geometry);
if (geometry2d.IsNull())
{
PlaneGeometry::Pointer plane = PlaneGeometry::New();
plane->InitializeStandardPlane(geometry);
geometry2d = plane;
}
SetCurrentWorldGeometry(geometry);
}
- SetCurrentWorldGeometry2D(geometry2d); // calls Modified()
+ SetCurrentWorldPlaneGeometry(geometry2d); // calls Modified()
}
- if (m_CurrentWorldGeometry2D.IsNull())
- itkWarningMacro("m_CurrentWorldGeometry2D is NULL");
+ if (m_CurrentWorldPlaneGeometry.IsNull())
+ itkWarningMacro("m_CurrentWorldPlaneGeometry is NULL");
}
void mitk::BaseRenderer::SetDisplayGeometry(mitk::DisplayGeometry* geometry2d)
{
itkDebugMacro("setting DisplayGeometry to " << geometry2d);
if (m_DisplayGeometry != geometry2d)
{
m_DisplayGeometry = geometry2d;
- m_DisplayGeometryData->SetGeometry2D(m_DisplayGeometry);
+ m_DisplayGeometryData->SetPlaneGeometry(m_DisplayGeometry);
m_DisplayGeometryUpdateTime.Modified();
Modified();
}
}
-void mitk::BaseRenderer::SetCurrentWorldGeometry2D(mitk::Geometry2D* geometry2d)
+void mitk::BaseRenderer::SetCurrentWorldPlaneGeometry(mitk::PlaneGeometry* geometry2d)
{
- if (m_CurrentWorldGeometry2D != geometry2d)
+ if (m_CurrentWorldPlaneGeometry != geometry2d)
{
- m_CurrentWorldGeometry2D = geometry2d;
- m_CurrentWorldGeometry2DData->SetGeometry2D(m_CurrentWorldGeometry2D);
- m_DisplayGeometry->SetWorldGeometry(m_CurrentWorldGeometry2D);
- m_CurrentWorldGeometry2DUpdateTime.Modified();
+ m_CurrentWorldPlaneGeometry = geometry2d;
+ m_CurrentWorldPlaneGeometryData->SetPlaneGeometry(m_CurrentWorldPlaneGeometry);
+ m_DisplayGeometry->SetWorldGeometry(m_CurrentWorldPlaneGeometry);
+ m_CurrentWorldPlaneGeometryUpdateTime.Modified();
Modified();
}
}
void mitk::BaseRenderer::SendUpdateSlice()
{
m_DisplayGeometryUpdateTime.Modified();
- m_CurrentWorldGeometry2DUpdateTime.Modified();
+ m_CurrentWorldPlaneGeometryUpdateTime.Modified();
}
-void mitk::BaseRenderer::SetCurrentWorldGeometry(mitk::Geometry3D* geometry)
+void mitk::BaseRenderer::SetCurrentWorldGeometry(mitk::BaseGeometry* geometry)
{
m_CurrentWorldGeometry = geometry;
if (geometry == NULL)
{
m_Bounds[0] = 0;
m_Bounds[1] = 0;
m_Bounds[2] = 0;
m_Bounds[3] = 0;
m_Bounds[4] = 0;
m_Bounds[5] = 0;
m_EmptyWorldGeometry = true;
return;
}
BoundingBox::Pointer boundingBox = m_CurrentWorldGeometry->CalculateBoundingBoxRelativeToTransform(NULL);
const BoundingBox::BoundsArrayType& worldBounds = boundingBox->GetBounds();
m_Bounds[0] = worldBounds[0];
m_Bounds[1] = worldBounds[1];
m_Bounds[2] = worldBounds[2];
m_Bounds[3] = worldBounds[3];
m_Bounds[4] = worldBounds[4];
m_Bounds[5] = worldBounds[5];
if (boundingBox->GetDiagonalLength2() <= mitk::eps)
m_EmptyWorldGeometry = true;
else
m_EmptyWorldGeometry = false;
}
void mitk::BaseRenderer::UpdateOverlays()
{
if(m_OverlayManager.IsNotNull())
{
m_OverlayManager->UpdateOverlays(this);
}
}
void mitk::BaseRenderer::SetGeometry(const itk::EventObject & geometrySendEvent)
{
const SliceNavigationController::GeometrySendEvent* sendEvent =
dynamic_cast<const SliceNavigationController::GeometrySendEvent *>(&geometrySendEvent);
assert(sendEvent!=NULL);
SetWorldTimeGeometry(sendEvent->GetTimeGeometry());
}
void mitk::BaseRenderer::UpdateGeometry(const itk::EventObject & geometryUpdateEvent)
{
const SliceNavigationController::GeometryUpdateEvent* updateEvent =
dynamic_cast<const SliceNavigationController::GeometryUpdateEvent*>(&geometryUpdateEvent);
if (updateEvent == NULL)
return;
if (m_CurrentWorldGeometry.IsNotNull())
{
SlicedGeometry3D* slicedWorldGeometry = dynamic_cast<SlicedGeometry3D*>(m_CurrentWorldGeometry.GetPointer());
if (slicedWorldGeometry)
{
- Geometry2D* geometry2D = slicedWorldGeometry->GetGeometry2D(m_Slice);
+ PlaneGeometry* geometry2D = slicedWorldGeometry->GetPlaneGeometry(m_Slice);
- SetCurrentWorldGeometry2D(geometry2D); // calls Modified()
+ SetCurrentWorldPlaneGeometry(geometry2D); // calls Modified()
}
}
}
void mitk::BaseRenderer::SetGeometrySlice(const itk::EventObject & geometrySliceEvent)
{
const SliceNavigationController::GeometrySliceEvent* sliceEvent =
dynamic_cast<const SliceNavigationController::GeometrySliceEvent *>(&geometrySliceEvent);
assert(sliceEvent!=NULL);
SetSlice(sliceEvent->GetPos());
}
void mitk::BaseRenderer::SetGeometryTime(const itk::EventObject & geometryTimeEvent)
{
const SliceNavigationController::GeometryTimeEvent * timeEvent =
dynamic_cast<const SliceNavigationController::GeometryTimeEvent *>(&geometryTimeEvent);
assert(timeEvent!=NULL);
SetTimeStep(timeEvent->GetPos());
}
const double* mitk::BaseRenderer::GetBounds() const
{
return m_Bounds;
}
void mitk::BaseRenderer::MousePressEvent(mitk::MouseEvent *me)
{
//set the Focus on the renderer
/*bool success =*/m_RenderingManager->GetGlobalInteraction()->SetFocus(this);
/*
if (! success)
mitk::StatusBar::GetInstance()->DisplayText("Warning! from mitkBaseRenderer.cpp: Couldn't focus this BaseRenderer!");
*/
//if (m_CameraController)
//{
// if(me->GetButtonState()!=512) // provisorisch: Ctrl nicht durchlassen. Bald wird aus m_CameraController eine StateMachine
// m_CameraController->MousePressEvent(me);
//}
if (m_MapperID == 1)
{
Point2D p(me->GetDisplayPosition());
Point2D p_mm;
Point3D position;
GetDisplayGeometry()->ULDisplayToDisplay(p, p);
GetDisplayGeometry()->DisplayToWorld(p, p_mm);
GetDisplayGeometry()->Map(p_mm, position);
mitk::PositionEvent event(this, me->GetType(), me->GetButton(), me->GetButtonState(), mitk::Key_unknown, p, position);
mitk::EventMapper::MapEvent(&event, m_RenderingManager->GetGlobalInteraction());
}
else if (m_MapperID > 1) //==2 for 3D and ==5 for stencil
{
Point2D p(me->GetDisplayPosition());
GetDisplayGeometry()->ULDisplayToDisplay(p, p);
me->SetDisplayPosition(p);
mitk::EventMapper::MapEvent(me, m_RenderingManager->GetGlobalInteraction());
}
}
void mitk::BaseRenderer::MouseReleaseEvent(mitk::MouseEvent *me)
{
//if (m_CameraController)
//{
// if(me->GetButtonState()!=512) // provisorisch: Ctrl nicht durchlassen. Bald wird aus m_CameraController eine StateMachine
// m_CameraController->MouseReleaseEvent(me);
//}
if (m_MapperID == 1)
{
Point2D p(me->GetDisplayPosition());
Point2D p_mm;
Point3D position;
GetDisplayGeometry()->ULDisplayToDisplay(p, p);
GetDisplayGeometry()->DisplayToWorld(p, p_mm);
GetDisplayGeometry()->Map(p_mm, position);
mitk::PositionEvent event(this, me->GetType(), me->GetButton(), me->GetButtonState(), mitk::Key_unknown, p, position);
mitk::EventMapper::MapEvent(&event, m_RenderingManager->GetGlobalInteraction());
}
else if (m_MapperID == 2)
{
Point2D p(me->GetDisplayPosition());
GetDisplayGeometry()->ULDisplayToDisplay(p, p);
me->SetDisplayPosition(p);
mitk::EventMapper::MapEvent(me, m_RenderingManager->GetGlobalInteraction());
}
}
void mitk::BaseRenderer::MouseMoveEvent(mitk::MouseEvent *me)
{
//if (m_CameraController)
//{
// if((me->GetButtonState()<=512) || (me->GetButtonState()>=516))// provisorisch: Ctrl nicht durchlassen. Bald wird aus m_CameraController eine StateMachine
// m_CameraController->MouseMoveEvent(me);
//}
if (m_MapperID == 1)
{
Point2D p(me->GetDisplayPosition());
Point2D p_mm;
Point3D position;
GetDisplayGeometry()->ULDisplayToDisplay(p, p);
GetDisplayGeometry()->DisplayToWorld(p, p_mm);
GetDisplayGeometry()->Map(p_mm, position);
mitk::PositionEvent event(this, me->GetType(), me->GetButton(), me->GetButtonState(), mitk::Key_unknown, p, position);
mitk::EventMapper::MapEvent(&event, m_RenderingManager->GetGlobalInteraction());
}
else if (m_MapperID == 2)
{
Point2D p(me->GetDisplayPosition());
GetDisplayGeometry()->ULDisplayToDisplay(p, p);
me->SetDisplayPosition(p);
mitk::EventMapper::MapEvent(me, m_RenderingManager->GetGlobalInteraction());
}
}
void mitk::BaseRenderer::PickWorldPoint(const mitk::Point2D& displayPoint, mitk::Point3D& worldPoint) const
{
mitk::Point2D worldPoint2D;
GetDisplayGeometry()->DisplayToWorld(displayPoint, worldPoint2D);
GetDisplayGeometry()->Map(worldPoint2D, worldPoint);
}
void mitk::BaseRenderer::WheelEvent(mitk::WheelEvent * we)
{
if (m_MapperID == 1)
{
Point2D p(we->GetDisplayPosition());
Point2D p_mm;
Point3D position;
GetDisplayGeometry()->ULDisplayToDisplay(p, p);
GetDisplayGeometry()->DisplayToWorld(p, p_mm);
GetDisplayGeometry()->Map(p_mm, position);
mitk::PositionEvent event(this, we->GetType(), we->GetButton(), we->GetButtonState(), mitk::Key_unknown, p, position);
mitk::EventMapper::MapEvent(we, m_RenderingManager->GetGlobalInteraction());
mitk::EventMapper::MapEvent(&event, m_RenderingManager->GetGlobalInteraction());
}
else if (m_MapperID == 2)
{
Point2D p(we->GetDisplayPosition());
GetDisplayGeometry()->ULDisplayToDisplay(p, p);
we->SetDisplayPosition(p);
mitk::EventMapper::MapEvent(we, m_RenderingManager->GetGlobalInteraction());
}
}
void mitk::BaseRenderer::KeyPressEvent(mitk::KeyEvent *ke)
{
if (m_MapperID == 1)
{
Point2D p(ke->GetDisplayPosition());
Point2D p_mm;
Point3D position;
GetDisplayGeometry()->ULDisplayToDisplay(p, p);
GetDisplayGeometry()->DisplayToWorld(p, p_mm);
GetDisplayGeometry()->Map(p_mm, position);
mitk::KeyEvent event(this, ke->GetType(), ke->GetButton(), ke->GetButtonState(), ke->GetKey(), ke->GetText(), p);
mitk::EventMapper::MapEvent(&event, m_RenderingManager->GetGlobalInteraction());
}
else if (m_MapperID == 2)
{
Point2D p(ke->GetDisplayPosition());
GetDisplayGeometry()->ULDisplayToDisplay(p, p);
ke->SetDisplayPosition(p);
mitk::EventMapper::MapEvent(ke, m_RenderingManager->GetGlobalInteraction());
}
}
void mitk::BaseRenderer::DrawOverlayMouse(mitk::Point2D& itkNotUsed(p2d))
{
MITK_INFO<<"BaseRenderer::DrawOverlayMouse()- should be inconcret implementation OpenGLRenderer."<<std::endl;
}
void mitk::BaseRenderer::RequestUpdate()
{
m_RenderingManager->RequestUpdate(this->m_RenderWindow);
}
void mitk::BaseRenderer::ForceImmediateUpdate()
{
m_RenderingManager->ForceImmediateUpdate(this->m_RenderWindow);
}
unsigned int mitk::BaseRenderer::GetNumberOfVisibleLODEnabledMappers() const
{
return m_NumberOfVisibleLODEnabledMappers;
}
mitk::RenderingManager* mitk::BaseRenderer::GetRenderingManager() const
{
return m_RenderingManager.GetPointer();
}
/*!
Sets the new Navigation controller
*/
void mitk::BaseRenderer::SetSliceNavigationController(mitk::SliceNavigationController *SlicenavigationController)
{
if (SlicenavigationController == NULL)
return;
//disconnect old from globalinteraction
m_RenderingManager->GetGlobalInteraction()->RemoveListener(SlicenavigationController);
//copy worldgeometry
SlicenavigationController->SetInputWorldTimeGeometry(SlicenavigationController->GetCreatedWorldGeometry());
SlicenavigationController->Update();
//set new
m_SliceNavigationController = SlicenavigationController;
m_SliceNavigationController->SetRenderer(this);
if (m_SliceNavigationController.IsNotNull())
{
m_SliceNavigationController->ConnectGeometrySliceEvent(this);
m_SliceNavigationController->ConnectGeometryUpdateEvent(this);
m_SliceNavigationController->ConnectGeometryTimeEvent(this, false);
}
}
/*!
Sets the new camera controller and deletes the vtkRenderWindowInteractor in case of the VTKInteractorCameraController
*/
void mitk::BaseRenderer::SetCameraController(CameraController* cameraController)
{
mitk::VtkInteractorCameraController::Pointer vtkInteractorCameraController =
dynamic_cast<mitk::VtkInteractorCameraController*>(cameraController);
if (vtkInteractorCameraController.IsNotNull())
MITK_INFO<<"!!!WARNING!!!: RenderWindow interaction events are no longer handled via CameraController (See Bug #954)."<<std::endl;
m_CameraController->SetRenderer(NULL);
m_CameraController = NULL;
m_CameraController = cameraController;
m_CameraController->SetRenderer(this);
}
void mitk::BaseRenderer::PrintSelf(std::ostream& os, itk::Indent indent) const
{
os << indent << " MapperID: " << m_MapperID << std::endl;
os << indent << " Slice: " << m_Slice << std::endl;
os << indent << " TimeStep: " << m_TimeStep << std::endl;
os << indent << " WorldGeometry: ";
if (m_WorldGeometry.IsNull())
os << "NULL" << std::endl;
else
m_WorldGeometry->Print(os, indent);
- os << indent << " CurrentWorldGeometry2D: ";
- if (m_CurrentWorldGeometry2D.IsNull())
+ os << indent << " CurrentWorldPlaneGeometry: ";
+ if (m_CurrentWorldPlaneGeometry.IsNull())
os << "NULL" << std::endl;
else
- m_CurrentWorldGeometry2D->Print(os, indent);
+ m_CurrentWorldPlaneGeometry->Print(os, indent);
- os << indent << " CurrentWorldGeometry2DUpdateTime: " << m_CurrentWorldGeometry2DUpdateTime << std::endl;
- os << indent << " CurrentWorldGeometry2DTransformTime: " << m_CurrentWorldGeometry2DTransformTime << std::endl;
+ os << indent << " CurrentWorldPlaneGeometryUpdateTime: " << m_CurrentWorldPlaneGeometryUpdateTime << std::endl;
+ os << indent << " CurrentWorldPlaneGeometryTransformTime: " << m_CurrentWorldPlaneGeometryTransformTime << std::endl;
os << indent << " DisplayGeometry: ";
if (m_DisplayGeometry.IsNull())
os << "NULL" << std::endl;
else
m_DisplayGeometry->Print(os, indent);
os << indent << " DisplayGeometryTransformTime: " << m_DisplayGeometryTransformTime << std::endl;
Superclass::PrintSelf(os, indent);
}
diff --git a/Core/Code/Rendering/mitkBaseRenderer.h b/Core/Code/Rendering/mitkBaseRenderer.h
index df60f34502..3febb2aad0 100644
--- a/Core/Code/Rendering/mitkBaseRenderer.h
+++ b/Core/Code/Rendering/mitkBaseRenderer.h
@@ -1,646 +1,663 @@
/*===================================================================
- The Medical Imaging Interaction Toolkit (MITK)
+The Medical Imaging Interaction Toolkit (MITK)
- Copyright (c) German Cancer Research Center,
- Division of Medical and Biological Informatics.
- All rights reserved.
+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.
+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.
+See LICENSE.txt or http://www.mitk.org for details.
- ===================================================================*/
+===================================================================*/
#ifndef BASERENDERER_H_HEADER_INCLUDED_C1CCA0F4
#define BASERENDERER_H_HEADER_INCLUDED_C1CCA0F4
#include "mitkDataStorage.h"
-#include "mitkGeometry2D.h"
+#include "mitkPlaneGeometry.h"
#include "mitkTimeGeometry.h"
#include "mitkDisplayGeometry.h"
-#include "mitkGeometry2DData.h"
+#include "mitkPlaneGeometryData.h"
#include "mitkCameraController.h"
#include "mitkDisplayPositionEvent.h"
#include "mitkWheelEvent.h"
//#include "mitkMapper.h"
#include "mitkSliceNavigationController.h"
#include "mitkCameraController.h"
#include "mitkCameraRotationController.h"
#include "mitkBindDispatcherInteractor.h"
#include "mitkDispatcher.h"
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <map>
#include <set>
// DEPRECATED
#include <mitkTimeSlicedGeometry.h>
namespace mitk
{
class NavigationController;
class SliceNavigationController;
class CameraRotationController;
class CameraController;
class DataStorage;
class Mapper;
class BaseLocalStorageHandler;
class OverlayManager;
-//##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
+ //##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:
/** \brief This rendering mode enumeration is specified at various constructors
* of the Renderer and RenderWindow classes, which autoconfigures the
* respective VTK objects. This has to be done at construction time because later
* configuring turns out to be not working on most platforms.
*/
struct RenderingMode
{
enum Type {
Standard = 0, // no multi-sampling, no depth-peeling
MultiSampling, // multi-sampling (antialiasing), no depth-peeling
DepthPeeling // no multi-sampling, depth-peeling is on (order-independant transparency)
};
};
typedef std::map<vtkRenderWindow*, BaseRenderer*> 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,RenderingMode::Type mode = RenderingMode::Standard);
//##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 Returns the Dispatcher which handles Events for this BaseRenderer
Dispatcher::Pointer GetDispatcher() const;
//##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
+ //## Depending of the type of the passed BaseGeometry more or less information can be extracted:
+ //## \li if it is a PlaneGeometry (which is a sub-class of BaseGeometry), m_CurrentWorldPlaneGeometry is
//## also set to point to it. m_WorldTimeGeometry is set to NULL.
//## \li if it is a TimeGeometry, m_WorldTimeGeometry is also set to point to it.
- //## If m_WorldTimeGeometry contains instances of SlicedGeometry3D, m_CurrentWorldGeometry2D is set to
+ //## If m_WorldTimeGeometry contains instances of SlicedGeometry3D, m_CurrentWorldPlaneGeometry 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_WorldTimeGeometry 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.
+ //## a PlaneGeometry describing the top of the bounding-box of the BaseGeometry is set as the
+ //## m_CurrentWorldPlaneGeometry.
+ //## \li otherwise a PlaneGeometry describing the top of the bounding-box of the BaseGeometry
+ //## is set as the m_CurrentWorldPlaneGeometry. m_WorldTimeGeometry is set to NULL.
+ //## @todo add calculation of PlaneGeometry describing the top of the bounding-box of the BaseGeometry
+ //## when the passed BaseGeometry is not sliced.
//## \sa m_WorldGeometry
//## \sa m_WorldTimeGeometry
- //## \sa m_CurrentWorldGeometry2D
- virtual void SetWorldGeometry3D(Geometry3D* geometry);
+ //## \sa m_CurrentWorldPlaneGeometry
+ virtual void SetWorldGeometry3D(BaseGeometry* geometry);
virtual void SetWorldTimeGeometry(mitk::TimeGeometry* geometry);
/**
* \deprecatedSince{2013_09} Please use TimeGeometry instead of TimeSlicedGeometry. For more information see http://www.mitk.org/Development/Refactoring%20of%20the%20Geometry%20Classes%20-%20Part%201
*/
DEPRECATED(void SetWorldGeometry3D(TimeSlicedGeometry* geometry));
- itkGetConstObjectMacro(WorldGeometry, Geometry3D)
- itkGetObjectMacro(WorldGeometry, Geometry3D)
- itkGetConstObjectMacro(WorldTimeGeometry, TimeGeometry)
- itkGetObjectMacro(WorldTimeGeometry, TimeGeometry)
-
- //##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()
+ itkGetConstObjectMacro(WorldGeometry, BaseGeometry)
+ itkGetObjectMacro(WorldGeometry, BaseGeometry)
+ itkGetConstObjectMacro(WorldTimeGeometry, TimeGeometry)
+ itkGetObjectMacro(WorldTimeGeometry, TimeGeometry)
+
+ //##Documentation
+ //## @brief Get the current 3D-worldgeometry (m_CurrentWorldGeometry) used for 3D-rendering
+ itkGetConstObjectMacro(CurrentWorldGeometry, BaseGeometry)
+
+ //##Documentation
+ //## @brief Get the current 2D-worldgeometry (m_CurrentWorldPlaneGeometry) used for 2D-rendering
+ itkGetConstObjectMacro(CurrentWorldPlaneGeometry, PlaneGeometry)
+ /**
+ * \deprecatedSince{2014_06} Please use GetCurrentWorldPlaneGeometry
+ */
+ DEPRECATED(const PlaneGeometry* GetCurrentWorldGeometry2D(){return GetCurrentWorldPlaneGeometry();};)
+
+ //##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
+ //## The DisplayGeometry describes which part of the PlaneGeometry m_CurrentWorldPlaneGeometry
//## is displayed.
virtual void SetDisplayGeometry(DisplayGeometry* geometry2d);
itkGetConstObjectMacro(DisplayGeometry, DisplayGeometry)
- itkGetObjectMacro(DisplayGeometry, DisplayGeometry)
+ itkGetObjectMacro(DisplayGeometry, DisplayGeometry)
- //##Documentation
- //## @brief Set/Get m_Slice which defines together with m_TimeStep the 2D geometry
- //## stored in m_WorldTimeGeometry used as m_CurrentWorldGeometry2D
- //##
- //## \sa m_Slice
- virtual void SetSlice(unsigned int slice);
+ //##Documentation
+ //## @brief Set/Get m_Slice which defines together with m_TimeStep the 2D geometry
+ //## stored in m_WorldTimeGeometry used as m_CurrentWorldPlaneGeometry
+ //##
+ //## \sa m_Slice
+ virtual void SetSlice(unsigned int slice);
//##Documentation
//## @brief Sets an OverlayManager which is used to add various Overlays to this
//## renderer. If an OverlayManager was already set it will be overwritten.
void SetOverlayManager(itk::SmartPointer<OverlayManager> overlayManager);
//##Documentation
//## @brief Get the OverlayManager registered with this renderer
//## if none was set, it will be created at this point.
itk::SmartPointer<OverlayManager> GetOverlayManager();
itkGetConstMacro(Slice, unsigned int)
- //##Documentation
- //## @brief Set/Get m_TimeStep which defines together with m_Slice the 2D geometry
- //## stored in m_WorldTimeGeometry used as m_CurrentWorldGeometry2D
- //##
- //## \sa m_TimeStep
- virtual void SetTimeStep(unsigned int timeStep);
+ //##Documentation
+ //## @brief Set/Get m_TimeStep which defines together with m_Slice the 2D geometry
+ //## stored in m_WorldTimeGeometry used as m_CurrentWorldPlaneGeometry
+ //##
+ //## \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-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()
+ itkGetObjectMacro(DisplayGeometryData, PlaneGeometryData)
+ //##Documentation
+ //## @brief Get a data object containing the WorldGeometry (for 2D rendering)
+ itkGetObjectMacro(WorldGeometryData, PlaneGeometryData)
+
+ //##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_CurrentWorldPlaneGeometry (for 2D rendering)
+ itkGetObjectMacro(CurrentWorldPlaneGeometryNode, DataNode)
+ /**
+ * \deprecatedSince{2014_06} Please use GetCurrentWorldPlaneGeometryNode
+ */
+ DEPRECATED(DataNode* GetCurrentWorldGeometry2DNode(){return GetCurrentWorldPlaneGeometryNode();};)
+
+ //##Documentation
+ //## @brief Sets timestamp of CurrentWorldPlaneGeometry and DisplayGeometry and forces so reslicing in that renderwindow
+ void SendUpdateSlice();
+
+ //##Documentation
+ //## @brief Get timestamp of last call of SetCurrentWorldPlaneGeometry
+ unsigned long GetCurrentWorldPlaneGeometryUpdateTime()
{
- return m_CurrentWorldGeometry2DUpdateTime;
+ return m_CurrentWorldPlaneGeometryUpdateTime;
}
- //##Documentation
- //## @brief Get timestamp of last call of SetDisplayGeometry
- unsigned long GetDisplayGeometryUpdateTime()
+ /**
+ * \deprecatedSince{2014_06} Please use GetCurrentWorldPlaneGeometryUpdateTime
+ */
+ DEPRECATED(unsigned long GetCurrentWorldGeometry2DUpdateTime(){return GetCurrentWorldPlaneGeometryUpdateTime();};)
+
+ //##Documentation
+ //## @brief Get timestamp of last call of SetDisplayGeometry
+ unsigned long GetDisplayGeometryUpdateTime()
{
- return m_CurrentWorldGeometry2DUpdateTime;
+ return m_CurrentWorldPlaneGeometryUpdateTime;
}
//##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 */
+ * 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)
+ itkGetConstMacro(MapperID, MapperSlotId)
- //##Documentation
- //## @brief Set the MapperSlotId to use.
- itkSetMacro(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 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)
- itkGetMacro(Size, int*)
+ itkGetMacro(Size, int*)
- void SetSliceNavigationController(SliceNavigationController* SlicenavigationController);
+ void SetSliceNavigationController(SliceNavigationController* SlicenavigationController);
void SetCameraController(CameraController* cameraController);
itkGetObjectMacro(CameraController, CameraController)
- itkGetObjectMacro(SliceNavigationController, SliceNavigationController)
- itkGetObjectMacro(CameraRotationController, CameraRotationController)
+ itkGetObjectMacro(SliceNavigationController, SliceNavigationController)
+ itkGetObjectMacro(CameraRotationController, CameraRotationController)
- itkGetMacro(EmptyWorldGeometry, bool)
+ 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 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 */
+ * 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
- */
+ * \brief Getter for the RenderingManager that handles this instance of BaseRenderer
+ */
virtual mitk::RenderingManager* GetRenderingManager() const;
/**
- * \brief Provides (1) world coordinates for a given mouse position and (2)
- * translates mousePosition to Display coordinates
- */
+ * \brief Provides (1) world coordinates for a given mouse position and (2)
+ * translates mousePosition to Display coordinates
+ */
virtual Point3D Map2DRendererPositionTo3DWorldPosition(const Point2D& mousePosition) const;
/**
* \deprecatedSince{2014_03} Please use Map2DRendererPositionTo3DWorldPosition(const Point2D& mousePosition) const
*/
DEPRECATED(Point3D Map2DRendererPositionTo3DWorldPosition(Point2D* mousePosition) 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);
+ //## @brief Sets m_CurrentWorldPlaneGeometry
+ virtual void SetCurrentWorldPlaneGeometry(PlaneGeometry* geometry2d);
+ /**
+ * \deprecatedSince{2014_06} Please use SetCurrentWorldPlaneGeometry
+ */
+ DEPRECATED(void SetCurrentWorldGeometry2D(PlaneGeometry* geometry2d){SetCurrentWorldPlaneGeometry(geometry2d);};)
- //##Documentation
- //## @brief Sets m_CurrentWorldGeometry
- virtual void SetCurrentWorldGeometry(Geometry3D* geometry);
+ //##Documentation
+ //## @brief Sets m_CurrentWorldGeometry
+ virtual void SetCurrentWorldGeometry(BaseGeometry* geometry);
//##Documentation
//## @brief This method is called during the rendering process to update or render the Overlays
//## which are stored in the OverlayManager
void UpdateOverlays();
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;
+ BaseGeometry::Pointer m_WorldGeometry;
itk::SmartPointer<OverlayManager> m_OverlayManager;
//##Documentation
- //## m_WorldTimeGeometry is set by SetWorldGeometry if the passed Geometry3D is a
+ //## m_WorldTimeGeometry is set by SetWorldGeometry if the passed BaseGeometry is a
//## TimeGeometry (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_WorldTimeGeometry (if available)
- //## is used as m_CurrentWorldGeometry2D.
- //## \sa m_CurrentWorldGeometry2D
+ //## is used as m_CurrentWorldPlaneGeometry.
+ //## \sa m_CurrentWorldPlaneGeometry
TimeGeometry::Pointer m_WorldTimeGeometry;
//##Documentation
//## Pointer to the current 3D-worldgeometry.
- Geometry3D::Pointer m_CurrentWorldGeometry;
+ BaseGeometry::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;
+ PlaneGeometry::Pointer m_CurrentWorldPlaneGeometry;
//##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_WorldTimeGeometry
- //## is used as m_CurrentWorldGeometry2D: m_WorldTimeGeometry->GetGeometry2D(m_Slice, m_TimeStep).
+ //## is used as m_CurrentWorldPlaneGeometry: m_WorldTimeGeometry->GetPlaneGeometry(m_Slice, m_TimeStep).
//## \sa m_WorldTimeGeometry
unsigned int m_Slice;
//##Documentation
//## Defines together with m_TimeStep which 2D geometry stored in m_WorldTimeGeometry
- //## is used as m_CurrentWorldGeometry2D: m_WorldTimeGeometry->GetGeometry2D(m_Slice, m_TimeStep).
+ //## is used as m_CurrentWorldPlaneGeometry: m_WorldTimeGeometry->GetPlaneGeometry(m_Slice, m_TimeStep).
//## \sa m_WorldTimeGeometry
unsigned int m_TimeStep;
//##Documentation
//## @brief timestamp of last call of SetWorldGeometry
- itk::TimeStamp m_CurrentWorldGeometry2DUpdateTime;
+ itk::TimeStamp m_CurrentWorldPlaneGeometryUpdateTime;
//##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;
//##Documentation
//## @brief Helper class which establishes connection between Interactors and Dispatcher via a common DataStorage.
BindDispatcherInteractor* m_BindDispatcherInteractor;
protected:
virtual void PrintSelf(std::ostream& os, itk::Indent indent) const;
//##Documentation
//## Data object containing the m_WorldGeometry defined above.
- Geometry2DData::Pointer m_WorldGeometryData;
+ PlaneGeometryData::Pointer m_WorldGeometryData;
//##Documentation
//## Data object containing the m_DisplayGeometry defined above.
- Geometry2DData::Pointer m_DisplayGeometryData;
+ PlaneGeometryData::Pointer m_DisplayGeometryData;
//##Documentation
- //## Data object containing the m_CurrentWorldGeometry2D defined above.
- Geometry2DData::Pointer m_CurrentWorldGeometry2DData;
+ //## Data object containing the m_CurrentWorldPlaneGeometry defined above.
+ PlaneGeometryData::Pointer m_CurrentWorldPlaneGeometryData;
//##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;
+ //## DataNode objects containing the m_CurrentWorldPlaneGeometryData defined above.
+ DataNode::Pointer m_CurrentWorldPlaneGeometryNode;
//##Documentation
//## @brief test only
unsigned long m_DisplayGeometryTransformTime;
//##Documentation
//## @brief test only
- unsigned long m_CurrentWorldGeometry2DTransformTime;
+ unsigned long m_CurrentWorldPlaneGeometryTransformTime;
std::string m_Name;
double m_Bounds[6];
bool m_EmptyWorldGeometry;
typedef std::set<Mapper *> LODEnabledMappersType;
/** Number of mappers which are visible and have level-of-detail
- * rendering enabled */
+ * rendering enabled */
unsigned int m_NumberOfVisibleLODEnabledMappers;
// Local Storage Handling for mappers
protected:
std::list<mitk::BaseLocalStorageHandler*> m_RegisteredLocalStorageHandlers;
public:
void RemoveAllLocalStorages();
void RegisterLocalStorageHandler(mitk::BaseLocalStorageHandler *lsh);
void UnregisterLocalStorageHandler(mitk::BaseLocalStorageHandler *lsh);
};
} // namespace mitk
#endif /* BASERENDERER_H_HEADER_INCLUDED_C1CCA0F4 */
\ No newline at end of file
diff --git a/Core/Code/Rendering/mitkGeometry2DDataMapper2D.h b/Core/Code/Rendering/mitkGeometry2DDataMapper2D.h
deleted file mode 100644
index 38d3e314a2..0000000000
--- a/Core/Code/Rendering/mitkGeometry2DDataMapper2D.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/*===================================================================
-
-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 MITKGEOMETRY2DDATAMAPPER2D_H_HEADER_INCLUDED_C19C0BFB
-#define MITKGEOMETRY2DDATAMAPPER2D_H_HEADER_INCLUDED_C19C0BFB
-
-#include <MitkCoreExports.h>
-#include "mitkGLMapper.h"
-#include "mitkSurfaceGLMapper2D.h"
-#include "mitkDataStorage.h"
-#include "mitkDataNode.h"
-#include "mitkWeakPointer.h"
-#include "mitkLine.h"
-
-namespace mitk {
-
-class BaseRenderer;
-
-/**
- * \brief OpenGL-based mapper to display a Geometry2D in a 2D window
- *
- * Currently implemented for mapping on PlaneGeometry.
- * The result is normally a line. An important usage of this class is to show
- * the orientation of the slices displayed in other 2D windows.
- *
- *
- * Properties that can be set and influence the Geometry2DDataMapper2D are:
- *
- * - \b "PlaneOrientationProperty": (PlaneOrientationProperty)
-
-
- * \todo implement for AbstractTransformGeometry.
- * \ingroup Mapper
- */
-class MITK_CORE_EXPORT Geometry2DDataMapper2D : public GLMapper
-{
-
-public:
- mitkClassMacro(Geometry2DDataMapper2D, GLMapper);
-
- itkFactorylessNewMacro(Self)
- itkCloneMacro(Self)
-
- /**
- * \brief Get the Geometry2DData to map
- */
- const Geometry2DData *GetInput();
-
- virtual void Paint( BaseRenderer *renderer );
-
- virtual void SetDatastorageAndGeometryBaseNode(mitk::DataStorage::Pointer ds, mitk::DataNode::Pointer parent);
-
- /** Applies properties specific to this mapper */
- virtual void ApplyAllProperties( BaseRenderer *renderer );
-
- LocalStorageHandler<BaseLocalStorage> m_LSH;
-
-protected:
- Geometry2DDataMapper2D();
-
- virtual ~Geometry2DDataMapper2D();
-
- virtual void GenerateDataForRenderer(mitk::BaseRenderer* renderer);
- /**
- * \brief Returns the thick slice mode for the given datanode.
- *
- * This method returns the value of the 'reslice.thickslices' property for
- * the given datanode.
- * '0': thick slice mode disabled
- * '1': thick slice mode enabled
- *
- * The variable 'thickSlicesNum' contains the value of the 'reslice.thickslices.num'
- * property that defines how many slices are shown at once.
- */
- int DetermineThickSliceMode( DataNode * dn, int &thickSlicesNum );
-
- /**
- * \brief Determines the cross position of two lines and stores them as parametric coordinates
- *
- * This method determines the parametric position at which a line 'otherLine' crosses another line
- * 'mainLine'. The result is stored in 'crossPositions'.
- */
- void DetermineParametricCrossPositions( Line<ScalarType,2> &mainLine, Line<ScalarType,2> &otherLine, std::vector<ScalarType> &crossPositions );
-
- void DrawLine( BaseRenderer * renderer, ScalarType lengthInDisplayUnits,
- Line< ScalarType, 2 > &line, std::vector< ScalarType > &gapPositions,
- const PlaneGeometry * inputPlaneGeometry, bool drawDashed,
- ScalarType gapSizeInPixel
- );
-
-
- void DrawOrientationArrow( Point2D &outerPoint, Point2D &innerPoint,
- const PlaneGeometry *planeGeometry,
- const PlaneGeometry *rendererPlaneGeometry,
- const DisplayGeometry *displayGeometry,
- bool positiveOrientation = true );
-
- SurfaceGLMapper2D::Pointer m_SurfaceMapper;
-
- mitk::WeakPointer<mitk::DataStorage> m_DataStorage; ///< DataStorage that will be searched for sub nodes
- DataNode::Pointer m_ParentNode; ///< parent node that will be used to search for sub nodes
-
- typedef std::vector<DataNode*> NodesVectorType;
- NodesVectorType m_OtherGeometry2Ds;
-
- bool m_RenderOrientationArrows;
- bool m_ArrowOrientationPositive;
-};
-} // namespace mitk
-#endif /* MITKGEOMETRY2DDATAMAPPER2D_H_HEADER_INCLUDED_C19C0BFB */
diff --git a/Core/Code/Rendering/mitkGeometry2DDataVtkMapper3D.h b/Core/Code/Rendering/mitkGeometry2DDataVtkMapper3D.h
deleted file mode 100644
index d556213a74..0000000000
--- a/Core/Code/Rendering/mitkGeometry2DDataVtkMapper3D.h
+++ /dev/null
@@ -1,212 +0,0 @@
-/*===================================================================
-
-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 MITKGEOMETRY2DDATAVTKMAPPER3D_H_HEADER_INCLUDED_C196C71F
-#define MITKGEOMETRY2DDATAVTKMAPPER3D_H_HEADER_INCLUDED_C196C71F
-
-#include <MitkCoreExports.h>
-#include "mitkVtkMapper.h"
-#include "mitkDataStorage.h"
-#include "mitkGeometry2DDataToSurfaceFilter.h"
-#include "mitkWeakPointer.h"
-
-#include <vtkSystemIncludes.h>
-#include <vtkCleanPolyData.h>
-
-class vtkActor;
-class vtkPolyDataMapper;
-class vtkAssembly;
-class vtkFeatureEdges;
-class vtkTubeFilter;
-class vtkTransformPolyDataFilter;
-class vtkHedgeHog;
-
-namespace mitk {
-
-class Geometry2DData;
-class BaseRenderer;
-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 "draw edges": (Bool) Toggle display of the tubed frame
- * - \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 VtkMapper
-{
-public:
- mitkClassMacro(Geometry2DDataVtkMapper3D, VtkMapper);
-
- itkFactorylessNewMacro(Self)
- itkCloneMacro(Self)
-
- /**
- * 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 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<mitk::DataStorage> m_DataStorage;
-
- 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< ImageVtkMapper2D *, ActorInfo > ActorList;
- ActorList m_ImageActors;
-
- // 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/mitkImageVtkMapper2D.cpp b/Core/Code/Rendering/mitkImageVtkMapper2D.cpp
index 1ad19b7fe9..9db61c7bd3 100644
--- a/Core/Code/Rendering/mitkImageVtkMapper2D.cpp
+++ b/Core/Code/Rendering/mitkImageVtkMapper2D.cpp
@@ -1,1073 +1,1073 @@
/*===================================================================
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.
===================================================================*/
//MITK
#include <mitkAbstractTransformGeometry.h>
#include <mitkDataNode.h>
#include <mitkDataNodeFactory.h>
#include <mitkImageSliceSelector.h>
#include <mitkLevelWindowProperty.h>
#include <mitkLookupTableProperty.h>
#include <mitkPlaneGeometry.h>
#include <mitkProperties.h>
#include <mitkResliceMethodProperty.h>
#include <mitkVtkResliceInterpolationProperty.h>
#include <mitkPixelType.h>
//#include <mitkTransferFunction.h>
#include <mitkTransferFunctionProperty.h>
#include "mitkImageStatisticsHolder.h"
#include "mitkPlaneClipping.h"
//MITK Rendering
#include "mitkImageVtkMapper2D.h"
#include "vtkMitkThickSlicesFilter.h"
#include "vtkMitkLevelWindowFilter.h"
#include "vtkNeverTranslucentTexture.h"
//VTK
#include <vtkProperty.h>
#include <vtkTransform.h>
#include <vtkMatrix4x4.h>
#include <vtkLookupTable.h>
#include <vtkImageData.h>
#include <vtkPoints.h>
#include <vtkGeneralTransform.h>
#include <vtkImageExtractComponents.h>
#include <vtkImageReslice.h>
#include <vtkImageChangeInformation.h>
#include <vtkPlaneSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkCellArray.h>
#include <vtkCamera.h>
#include <vtkColorTransferFunction.h>
//ITK
#include <itkRGBAPixel.h>
#include <mitkRenderingModeProperty.h>
mitk::ImageVtkMapper2D::ImageVtkMapper2D()
{
}
mitk::ImageVtkMapper2D::~ImageVtkMapper2D()
{
- //The 3D RW Mapper (Geometry2DDataVtkMapper3D) is listening to this event,
+ //The 3D RW Mapper (PlaneGeometryDataVtkMapper3D) 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, double planeBounds[6])
{
LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);
float depth = this->CalculateLayerDepth(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.
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 (axial, 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 * >( GetDataNode()->GetData() );
}
vtkProp* mitk::ImageVtkMapper2D::GetVtkProp(mitk::BaseRenderer* renderer)
{
//return the actor corresponding to the renderer
return m_LSH.GetLocalStorage(renderer)->m_Actors;
}
void mitk::ImageVtkMapper2D::GenerateDataForRenderer( mitk::BaseRenderer *renderer )
{
LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);
mitk::Image *input = const_cast< mitk::Image * >( this->GetInput() );
mitk::DataNode* datanode = this->GetDataNode();
if ( input == NULL || input->IsInitialized() == false )
{
return;
}
//check if there is a valid worldGeometry
- const Geometry2D *worldGeometry = renderer->GetCurrentWorldGeometry2D();
+ const PlaneGeometry *worldGeometry = renderer->GetCurrentWorldPlaneGeometry();
if( ( worldGeometry == NULL ) || ( !worldGeometry->IsValid() ) || ( !worldGeometry->HasReferenceGeometry() ))
{
return;
}
input->Update();
// early out if there is no intersection of the current rendering geometry
// and the geometry of the image that is to be rendered.
if ( !RenderingGeometryIntersectsImage( worldGeometry, input->GetSlicedGeometry() ) )
{
// set image to NULL, to clear the texture in 3D, because
// the latest image is used there if the plane is out of the geometry
// see bug-13275
localStorage->m_ReslicedImage = NULL;
localStorage->m_Mapper->SetInputData( localStorage->m_EmptyPolyData );
return;
}
//set main input for ExtractSliceFilter
localStorage->m_Reslicer->SetInput(input);
localStorage->m_Reslicer->SetWorldGeometry(worldGeometry);
localStorage->m_Reslicer->SetTimeStep( this->GetTimestep() );
//set the transformation of the image to adapt reslice axis
localStorage->m_Reslicer->SetResliceTransformByGeometry( input->GetTimeGeometry()->GetGeometryForTimeStep( this->GetTimestep() ) );
//is the geometry of the slice based on the input image or the worldgeometry?
bool inPlaneResampleExtentByGeometry = false;
datanode->GetBoolProperty("in plane resample extent by geometry", inPlaneResampleExtentByGeometry, renderer);
localStorage->m_Reslicer->SetInPlaneResampleExtentByGeometry(inPlaneResampleExtentByGeometry);
// 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;
datanode->GetProperty(
resliceInterpolationProperty, "reslice interpolation" );
int interpolationMode = VTK_RESLICE_NEAREST;
if ( resliceInterpolationProperty != NULL )
{
interpolationMode = resliceInterpolationProperty->GetInterpolation();
}
switch ( interpolationMode )
{
case VTK_RESLICE_NEAREST:
localStorage->m_Reslicer->SetInterpolationMode(ExtractSliceFilter::RESLICE_NEAREST);
break;
case VTK_RESLICE_LINEAR:
localStorage->m_Reslicer->SetInterpolationMode(ExtractSliceFilter::RESLICE_LINEAR);
break;
case VTK_RESLICE_CUBIC:
localStorage->m_Reslicer->SetInterpolationMode(ExtractSliceFilter::RESLICE_CUBIC);
break;
}
}
else
{
localStorage->m_Reslicer->SetInterpolationMode(ExtractSliceFilter::RESLICE_NEAREST);
}
//set the vtk output property to true, makes sure that no unneeded mitk image convertion
//is done.
localStorage->m_Reslicer->SetVtkOutputRequest(true);
//Thickslicing
int thickSlicesMode = 0;
int thickSlicesNum = 1;
// Thick slices parameters
if( input->GetPixelType().GetNumberOfComponents() == 1 ) // for now only single component are allowed
{
- DataNode *dn=renderer->GetCurrentWorldGeometry2DNode();
+ DataNode *dn=renderer->GetCurrentWorldPlaneGeometryNode();
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";
}
}
const PlaneGeometry *planeGeometry = dynamic_cast< const PlaneGeometry * >( worldGeometry );
if(thickSlicesMode > 0)
{
double dataZSpacing = 1.0;
Vector3D normInIndex, normal;
if ( planeGeometry != NULL ){
normal = planeGeometry->GetNormal();
}else{
const mitk::AbstractTransformGeometry* abstractGeometry = dynamic_cast< const AbstractTransformGeometry * >(worldGeometry);
if(abstractGeometry != NULL)
normal = abstractGeometry->GetPlane()->GetNormal();
else
return; //no fitting geometry set
}
normal.Normalize();
input->GetTimeGeometry()->GetGeometryForTimeStep( this->GetTimestep() )->WorldToIndex( normal, normInIndex );
dataZSpacing = 1.0 / normInIndex.GetNorm();
localStorage->m_Reslicer->SetOutputDimensionality( 3 );
localStorage->m_Reslicer->SetOutputSpacingZDirection(dataZSpacing);
localStorage->m_Reslicer->SetOutputExtentZDirection( -thickSlicesNum, 0+thickSlicesNum );
// 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.
localStorage->m_TSFilter->SetThickSliceMode( thickSlicesMode-1 );
localStorage->m_TSFilter->SetInputData( localStorage->m_Reslicer->GetVtkOutput() );
//vtkFilter=>mitkFilter=>vtkFilter update mechanism will fail without calling manually
localStorage->m_Reslicer->Modified();
localStorage->m_Reslicer->Update();
localStorage->m_TSFilter->Modified();
localStorage->m_TSFilter->Update();
localStorage->m_ReslicedImage = localStorage->m_TSFilter->GetOutput();
}
else
{
//this is needed when thick mode was enable bevore. These variable have to be reset to default values
localStorage->m_Reslicer->SetOutputDimensionality( 2 );
localStorage->m_Reslicer->SetOutputSpacingZDirection(1.0);
localStorage->m_Reslicer->SetOutputExtentZDirection( 0, 0 );
localStorage->m_Reslicer->Modified();
//start the pipeline with updating the largest possible, needed if the geometry of the input has changed
localStorage->m_Reslicer->UpdateLargestPossibleRegion();
localStorage->m_ReslicedImage = localStorage->m_Reslicer->GetVtkOutput();
}
// Bounds information for reslicing (only reuqired if reference geometry
// is present)
//this used for generating a vtkPLaneSource with the right size
double sliceBounds[6];
for ( int i = 0; i < 6; ++i )
{
sliceBounds[i] = 0.0;
}
localStorage->m_Reslicer->GetClippedPlaneBounds(sliceBounds);
//get the spacing of the slice
localStorage->m_mmPerPixel = localStorage->m_Reslicer->GetOutputSpacing();
// calculate minimum bounding rect of IMAGE in texture
{
double textureClippingBounds[6];
for ( int i = 0; i < 6; ++i )
{
textureClippingBounds[i] = 0.0;
}
// 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.
mitk::PlaneClipping::CalculateClippedPlaneBounds( input->GetGeometry(), planeGeometry, textureClippingBounds );
textureClippingBounds[0] = static_cast< int >( textureClippingBounds[0] / localStorage->m_mmPerPixel[0] + 0.5 );
textureClippingBounds[1] = static_cast< int >( textureClippingBounds[1] / localStorage->m_mmPerPixel[0] + 0.5 );
textureClippingBounds[2] = static_cast< int >( textureClippingBounds[2] / localStorage->m_mmPerPixel[1] + 0.5 );
textureClippingBounds[3] = static_cast< int >( textureClippingBounds[3] / localStorage->m_mmPerPixel[1] + 0.5 );
//clipping bounds for cutting the image
localStorage->m_LevelWindowFilter->SetClippingBounds(textureClippingBounds);
}
//get the number of scalar components to distinguish between different image types
int numberOfComponents = localStorage->m_ReslicedImage->GetNumberOfScalarComponents();
//get the binary property
bool binary = false;
bool binaryOutline = false;
datanode->GetBoolProperty( "binary", binary, renderer );
if(binary) //binary image
{
datanode->GetBoolProperty( "outline binary", binaryOutline, renderer );
if(binaryOutline) //contour rendering
{
if ( input->GetPixelType().GetBpe() <= 8 )
{
//generate contours/outlines
localStorage->m_OutlinePolyData = CreateOutlinePolyData(renderer);
float binaryOutlineWidth(1.0);
if ( datanode->GetFloatProperty( "outline width", binaryOutlineWidth, renderer ) )
{
if ( localStorage->m_Actors->GetNumberOfPaths() > 1 )
{
float binaryOutlineShadowWidth(1.5);
datanode->GetFloatProperty( "outline shadow width", binaryOutlineShadowWidth, renderer );
dynamic_cast<vtkActor*>(localStorage->m_Actors->GetParts()->GetItemAsObject(0))
->GetProperty()->SetLineWidth( binaryOutlineWidth * binaryOutlineShadowWidth );
}
localStorage->m_Actor->GetProperty()->SetLineWidth( binaryOutlineWidth );
}
}
else
{
binaryOutline = false;
this->ApplyLookuptable(renderer);
MITK_WARN << "Type of all binary images should be (un)signed char. Outline does not work on other pixel types!";
}
}
else //standard binary image
{
if(numberOfComponents != 1)
{
MITK_ERROR << "Rendering Error: Binary Images with more then 1 component are not supported!";
}
}
}
this->ApplyOpacity( renderer );
this->ApplyRenderingMode(renderer);
// do not use a VTK lookup table (we do that ourselves in m_LevelWindowFilter)
localStorage->m_Texture->MapColorScalarsThroughLookupTableOff();
int displayedComponent = 0;
if (datanode->GetIntProperty("Image.Displayed Component", displayedComponent, renderer) && numberOfComponents > 1)
{
localStorage->m_VectorComponentExtractor->SetComponents(displayedComponent);
localStorage->m_VectorComponentExtractor->SetInputData(localStorage->m_ReslicedImage);
localStorage->m_LevelWindowFilter->SetInputConnection(localStorage->m_VectorComponentExtractor->GetOutputPort(0));
}
else
{
//connect the input with the levelwindow filter
localStorage->m_LevelWindowFilter->SetInputData(localStorage->m_ReslicedImage);
}
// check for texture interpolation property
bool textureInterpolation = false;
GetDataNode()->GetBoolProperty( "texture interpolation", textureInterpolation, renderer );
//set the interpolation modus according to the property
localStorage->m_Texture->SetInterpolate(textureInterpolation);
// connect the texture with the output of the levelwindow filter
localStorage->m_Texture->SetInputConnection(localStorage->m_LevelWindowFilter->GetOutputPort());
this->TransformActor( renderer );
vtkActor* contourShadowActor = dynamic_cast<vtkActor*> (localStorage->m_Actors->GetParts()->GetItemAsObject(0));
if(binary && binaryOutline) //connect the mapper with the polyData which contains the lines
{
//We need the contour for the binary outline property as actor
localStorage->m_Mapper->SetInputData(localStorage->m_OutlinePolyData);
localStorage->m_Actor->SetTexture(NULL); //no texture for contours
bool binaryOutlineShadow( false );
datanode->GetBoolProperty( "outline binary shadow", binaryOutlineShadow, renderer );
if ( binaryOutlineShadow )
contourShadowActor->SetVisibility( true );
else
contourShadowActor->SetVisibility( false );
}
else
{ //Connect the mapper with the input texture. This is the standard case.
//setup the textured plane
this->GeneratePlane( renderer, sliceBounds );
//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);
contourShadowActor->SetVisibility( false );
}
// We have been modified => save this for next Update()
localStorage->m_LastUpdateTime.Modified();
}
void mitk::ImageVtkMapper2D::ApplyLevelWindow(mitk::BaseRenderer *renderer)
{
LocalStorage *localStorage = this->GetLocalStorage( renderer );
LevelWindow levelWindow;
this->GetDataNode()->GetLevelWindow( levelWindow, renderer, "levelwindow" );
localStorage->m_LevelWindowFilter->GetLookupTable()->SetRange( levelWindow.GetLowerWindowBound(), levelWindow.GetUpperWindowBound() );
mitk::LevelWindow opacLevelWindow;
if( this->GetDataNode()->GetLevelWindow( opacLevelWindow, renderer, "opaclevelwindow" ) )
{
//pass the opaque level window to the filter
localStorage->m_LevelWindowFilter->SetMinOpacity(opacLevelWindow.GetLowerWindowBound());
localStorage->m_LevelWindowFilter->SetMaxOpacity(opacLevelWindow.GetUpperWindowBound());
}
else
{
//no opaque level window
localStorage->m_LevelWindowFilter->SetMinOpacity(0.0);
localStorage->m_LevelWindowFilter->SetMaxOpacity(255.0);
}
}
void mitk::ImageVtkMapper2D::ApplyColor( mitk::BaseRenderer* renderer )
{
LocalStorage *localStorage = this->GetLocalStorage( renderer );
float rgb[3]= { 1.0f, 1.0f, 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<mitk::ColorProperty*>(GetDataNode()->GetProperty
("binaryimage.hoveringcolor", renderer));
if(colorprop.IsNotNull())
{
memcpy(rgb, colorprop->GetColor().GetDataPointer(), 3*sizeof(float));
}
else
{
GetDataNode()->GetColor( rgb, renderer, "color" );
}
}
if(selected)
{
mitk::ColorProperty::Pointer colorprop = dynamic_cast<mitk::ColorProperty*>(GetDataNode()->GetProperty
("binaryimage.selectedcolor", renderer));
if(colorprop.IsNotNull()) {
memcpy(rgb, colorprop->GetColor().GetDataPointer(), 3*sizeof(float));
}
else
{
GetDataNode()->GetColor(rgb, renderer, "color");
}
}
if(!hover && !selected)
{
GetDataNode()->GetColor( rgb, renderer, "color" );
}
double rgbConv[3] = {(double)rgb[0], (double)rgb[1], (double)rgb[2]}; //conversion to double for VTK
dynamic_cast<vtkActor*> (localStorage->m_Actors->GetParts()->GetItemAsObject(0))->GetProperty()->SetColor(rgbConv);
localStorage->m_Actor->GetProperty()->SetColor(rgbConv);
if ( localStorage->m_Actors->GetParts()->GetNumberOfItems() > 1 )
{
float rgb[3]= { 1.0f, 1.0f, 1.0f };
mitk::ColorProperty::Pointer colorprop = dynamic_cast<mitk::ColorProperty*>(GetDataNode()->GetProperty
("outline binary shadow color", renderer));
if(colorprop.IsNotNull())
{
memcpy(rgb, colorprop->GetColor().GetDataPointer(), 3*sizeof(float));
}
double rgbConv[3] = {(double)rgb[0], (double)rgb[1], (double)rgb[2]}; //conversion to double for VTK
dynamic_cast<vtkActor*>( localStorage->m_Actors->GetParts()->GetItemAsObject(0) )->GetProperty()->SetColor(rgbConv);
}
}
void mitk::ImageVtkMapper2D::ApplyOpacity( mitk::BaseRenderer* renderer )
{
LocalStorage* localStorage = this->GetLocalStorage( renderer );
float opacity = 1.0f;
// check for opacity prop and use it for rendering if it exists
GetDataNode()->GetOpacity( opacity, renderer, "opacity" );
//set the opacity according to the properties
localStorage->m_Actor->GetProperty()->SetOpacity(opacity);
if ( localStorage->m_Actors->GetParts()->GetNumberOfItems() > 1 )
{
dynamic_cast<vtkActor*>( localStorage->m_Actors->GetParts()->GetItemAsObject(0) )->GetProperty()->SetOpacity(opacity);
}
}
void mitk::ImageVtkMapper2D::ApplyRenderingMode( mitk::BaseRenderer* renderer )
{
LocalStorage* localStorage = m_LSH.GetLocalStorage(renderer);
bool binary = false;
this->GetDataNode()->GetBoolProperty( "binary", binary, renderer );
if(binary) // is it a binary image?
{
//for binary images, we always use our default LuT and map every value to (0,1)
//the opacity of 0 will always be 0.0. We never a apply a LuT/TfF nor a level window.
localStorage->m_LevelWindowFilter->SetLookupTable(localStorage->m_BinaryLookupTable);
}
else
{
//all other image types can make use of the rendering mode
int renderingMode = mitk::RenderingModeProperty::LOOKUPTABLE_LEVELWINDOW_COLOR;
mitk::RenderingModeProperty::Pointer mode = dynamic_cast<mitk::RenderingModeProperty*>(this->GetDataNode()->GetProperty( "Image Rendering.Mode", renderer ));
if(mode.IsNotNull())
{
renderingMode = mode->GetRenderingMode();
}
switch(renderingMode)
{
case mitk::RenderingModeProperty::LOOKUPTABLE_LEVELWINDOW_COLOR:
MITK_DEBUG << "'Image Rendering.Mode' = LevelWindow_LookupTable_Color";
this->ApplyLookuptable( renderer );
this->ApplyLevelWindow( renderer );
break;
case mitk::RenderingModeProperty::COLORTRANSFERFUNCTION_LEVELWINDOW_COLOR:
MITK_DEBUG << "'Image Rendering.Mode' = LevelWindow_ColorTransferFunction_Color";
this->ApplyColorTransferFunction( renderer );
this->ApplyLevelWindow( renderer );
break;
case mitk::RenderingModeProperty::LOOKUPTABLE_COLOR:
MITK_DEBUG << "'Image Rendering.Mode' = LookupTable_Color";
this->ApplyLookuptable( renderer );
break;
case mitk::RenderingModeProperty::COLORTRANSFERFUNCTION_COLOR:
MITK_DEBUG << "'Image Rendering.Mode' = ColorTransferFunction_Color";
this->ApplyColorTransferFunction( renderer );
break;
default:
MITK_ERROR << "No valid 'Image Rendering.Mode' set. Using LOOKUPTABLE_LEVELWINDOW_COLOR instead.";
this->ApplyLookuptable( renderer );
this->ApplyLevelWindow( renderer );
break;
}
}
//we apply color for all images (including binaries).
this->ApplyColor( renderer );
}
void mitk::ImageVtkMapper2D::ApplyLookuptable( mitk::BaseRenderer* renderer )
{
LocalStorage* localStorage = m_LSH.GetLocalStorage(renderer);
vtkLookupTable* usedLookupTable = localStorage->m_ColorLookupTable;
// If lookup table or transferfunction use is requested...
mitk::LookupTableProperty::Pointer lookupTableProp = dynamic_cast<mitk::LookupTableProperty*>(this->GetDataNode()->GetProperty("LookupTable"));
if( lookupTableProp.IsNotNull() ) // is a lookuptable set?
{
usedLookupTable = lookupTableProp->GetLookupTable()->GetVtkLookupTable();
}
else
{
//"Image Rendering.Mode was set to use a lookup table but there is no property 'LookupTable'.
//A default (rainbow) lookup table will be used.
//Here have to do nothing. Warning for the user has been removed, due to unwanted console output
//in every interation of the rendering.
}
localStorage->m_LevelWindowFilter->SetLookupTable(usedLookupTable);
}
void mitk::ImageVtkMapper2D::ApplyColorTransferFunction(mitk::BaseRenderer *renderer)
{
mitk::TransferFunctionProperty::Pointer transferFunctionProp = dynamic_cast<mitk::TransferFunctionProperty*>(this->GetDataNode()->GetProperty("Image Rendering.Transfer Function",renderer ));
if( transferFunctionProp.IsNull() )
{
MITK_ERROR << "'Image Rendering.Mode'' was set to use a color transfer function but there is no property 'Image Rendering.Transfer Function'. Nothing will be done.";
return;
}
LocalStorage* localStorage = m_LSH.GetLocalStorage(renderer);
//pass the transfer function to our level window filter
localStorage->m_LevelWindowFilter->SetLookupTable(transferFunctionProp->GetValue()->GetColorTransferFunction());
}
void mitk::ImageVtkMapper2D::Update(mitk::BaseRenderer* renderer)
{
bool visible = true;
GetDataNode()->GetVisibility(visible, renderer, "visible");
if ( !visible )
{
return;
}
mitk::Image* data = const_cast<mitk::Image *>( 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 TimeGeometry *dataTimeGeometry = data->GetTimeGeometry();
if ( ( dataTimeGeometry == NULL )
|| ( dataTimeGeometry->CountTimeSteps() == 0 )
|| ( !dataTimeGeometry->IsValidTimeStep( 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 < renderer->GetCurrentWorldPlaneGeometryUpdateTime()) //was the geometry modified?
+ || (localStorage->m_LastUpdateTime < renderer->GetCurrentWorldPlaneGeometry()->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<mitk::Image*>(node->GetData());
// Properties common for both images and segmentations
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 );
node->AddProperty( "outline binary shadow", mitk::BoolProperty::New( false ), renderer, overwrite );
node->AddProperty( "outline binary shadow color", ColorProperty::New(0.0,0.0,0.0), renderer, overwrite );
node->AddProperty( "outline shadow width", mitk::FloatProperty::New( 1.5 ), 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 ) );
mitk::RenderingModeProperty::Pointer renderingModeProperty = mitk::RenderingModeProperty::New();
node->AddProperty( "Image Rendering.Mode", renderingModeProperty);
// Set default grayscale look-up table
mitk::LookupTable::Pointer mitkLut = mitk::LookupTable::New();
mitkLut->SetType(mitk::LookupTable::GRAYSCALE);
mitk::LookupTableProperty::Pointer mitkLutProp = mitk::LookupTableProperty::New();
mitkLutProp->SetLookupTable(mitkLut);
node->SetProperty("LookupTable", mitkLutProp);
std::string photometricInterpretation; // DICOM tag telling us how pixel values should be displayed
if ( node->GetStringProperty( "dicom.pixel.PhotometricInterpretation", photometricInterpretation ) )
{
// modality provided by DICOM or other reader
if ( photometricInterpretation.find("MONOCHROME1") != std::string::npos ) // meaning: display MINIMUM pixels as WHITE
{
// Set inverse grayscale look-up table
mitkLut->SetType(mitk::LookupTable::INVERSE_GRAYSCALE);
mitkLutProp->SetLookupTable(mitkLut);
node->SetProperty("LookupTable", mitkLutProp);
}
// Otherwise do nothing - the default grayscale look-up table has already been set
}
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->GetStatistics()->GetScalarValueMin();
maxValue = centralSliceImage->GetStatistics()->GetScalarValueMax();
min2ndValue = centralSliceImage->GetStatistics()->GetScalarValue2ndMin();
max2ndValue = centralSliceImage->GetStatistics()->GetScalarValue2ndMax();
}
if ((maxValue == min2ndValue && minValue == max2ndValue) || minValue == maxValue)
{
// centralSlice is strange, lets look at all data
minValue = image->GetStatistics()->GetScalarValueMin();
maxValue = image->GetStatistics()->GetScalarValueMaxNoRecompute();
min2ndValue = image->GetStatistics()->GetScalarValue2ndMinNoRecompute();
max2ndValue = image->GetStatistics()->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);
std::string className = image->GetNameOfClass();
if (className != "TensorImage" && className != "QBallImage")
{
PixelType pixelType = image->GetPixelType();
size_t numComponents = pixelType.GetNumberOfComponents();
if ((pixelType.GetPixelTypeAsString() == "vector" && numComponents > 1) || numComponents == 2 || numComponents > 4)
node->AddProperty("Image.Displayed Component", mitk::IntProperty::New(0), renderer, overwrite);
}
}
if(image.IsNotNull() && image->IsInitialized())
{
if((overwrite) || (node->GetProperty("levelwindow", renderer)==NULL))
{
/* initialize level/window from DICOM tags */
std::string sLevel;
std::string sWindow;
if ( image->GetPropertyList()->GetStringProperty( "dicom.voilut.WindowCenter", sLevel )
&& image->GetPropertyList()->GetStringProperty( "dicom.voilut.WindowWidth", sWindow ) )
{
float level = atof( sLevel.c_str() );
float window = atof( sWindow.c_str() );
mitk::LevelWindow contrast;
std::string sSmallestPixelValueInSeries;
std::string sLargestPixelValueInSeries;
if ( image->GetPropertyList()->GetStringProperty( "dicom.series.SmallestPixelValueInSeries", sSmallestPixelValueInSeries )
&& image->GetPropertyList()->GetStringProperty( "dicom.series.LargestPixelValueInSeries", sLargestPixelValueInSeries ) )
{
float smallestPixelValueInSeries = atof( sSmallestPixelValueInSeries.c_str() );
float largestPixelValueInSeries = atof( sLargestPixelValueInSeries.c_str() );
contrast.SetRangeMinMax( smallestPixelValueInSeries-1, largestPixelValueInSeries+1 ); // why not a little buffer?
// might remedy some l/w widget challenges
}
else
{
contrast.SetAuto( static_cast<mitk::Image*>(node->GetData()), false, true ); // we need this as a fallback
}
contrast.SetLevelWindow( level, window, true );
node->SetProperty( "levelwindow", LevelWindowProperty::New( contrast ), renderer );
}
}
if(((overwrite) || (node->GetProperty("opaclevelwindow", renderer)==NULL))
&& (image->GetPixelType().GetPixelType() == itk::ImageIOBase::RGBA)
&& (image->GetPixelType().GetComponentType() == itk::ImageIOBase::UCHAR) )
{
mitk::LevelWindow opaclevwin;
opaclevwin.SetRangeMinMax(0,255);
opaclevwin.SetWindowBounds(0,255);
mitk::LevelWindowProperty::Pointer prop = mitk::LevelWindowProperty::New(opaclevwin);
node->SetProperty( "opaclevelwindow", prop, renderer );
}
}
Superclass::SetDefaultProperties(node, renderer, overwrite);
}
mitk::ImageVtkMapper2D::LocalStorage* mitk::ImageVtkMapper2D::GetLocalStorage(mitk::BaseRenderer* renderer)
{
return m_LSH.GetLocalStorage(renderer);
}
vtkSmartPointer<vtkPolyData> mitk::ImageVtkMapper2D::CreateOutlinePolyData(mitk::BaseRenderer* renderer ){
LocalStorage* localStorage = this->GetLocalStorage(renderer);
//get the min and max index values of each direction
int* extent = localStorage->m_ReslicedImage->GetExtent();
int xMin = extent[0];
int xMax = extent[1];
int yMin = extent[2];
int yMax = extent[3];
int* dims = localStorage->m_ReslicedImage->GetDimensions(); //dimensions of the image
int line = dims[0]; //how many pixels per line?
int x = xMin; //pixel index x
int y = yMin; //pixel index y
char* currentPixel;
//get the depth for each contour
float depth = CalculateLayerDepth(renderer);
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New(); //the points to draw
vtkSmartPointer<vtkCellArray> lines = vtkSmartPointer<vtkCellArray>::New(); //the lines to connect the points
// We take the pointer to the first pixel of the image
currentPixel = static_cast<char*>(localStorage->m_ReslicedImage->GetScalarPointer() );
while (y <= yMax)
{
//if the current pixel value is set to something
if ((currentPixel) && (*currentPixel != 0))
{
//check in which direction a line is necessary
//a line is added if the neighbor of the current pixel has the value 0
//and if the pixel is located at the edge of the image
//if vvvvv not the first line vvvvv
if (y > yMin && *(currentPixel-line) == 0)
{ //x direction - bottom edge of the pixel
//add the 2 points
vtkIdType p1 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth);
vtkIdType p2 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth);
//add the line between both points
lines->InsertNextCell(2);
lines->InsertCellPoint(p1);
lines->InsertCellPoint(p2);
}
//if vvvvv not the last line vvvvv
if (y < yMax && *(currentPixel+line) == 0)
{ //x direction - top edge of the pixel
vtkIdType p1 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth);
vtkIdType p2 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth);
lines->InsertNextCell(2);
lines->InsertCellPoint(p1);
lines->InsertCellPoint(p2);
}
//if vvvvv not the first pixel vvvvv
if ( (x > xMin || y > yMin) && *(currentPixel-1) == 0)
{ //y direction - left edge of the pixel
vtkIdType p1 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth);
vtkIdType p2 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth);
lines->InsertNextCell(2);
lines->InsertCellPoint(p1);
lines->InsertCellPoint(p2);
}
//if vvvvv not the last pixel vvvvv
if ( (y < yMax || (x < xMax) ) && *(currentPixel+1) == 0)
{ //y direction - right edge of the pixel
vtkIdType p1 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth);
vtkIdType p2 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth);
lines->InsertNextCell(2);
lines->InsertCellPoint(p1);
lines->InsertCellPoint(p2);
}
/* now consider pixels at the edge of the image */
//if vvvvv left edge of image vvvvv
if (x == xMin)
{ //draw left edge of the pixel
vtkIdType p1 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth);
vtkIdType p2 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth);
lines->InsertNextCell(2);
lines->InsertCellPoint(p1);
lines->InsertCellPoint(p2);
}
//if vvvvv right edge of image vvvvv
if (x == xMax)
{ //draw right edge of the pixel
vtkIdType p1 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth);
vtkIdType p2 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth);
lines->InsertNextCell(2);
lines->InsertCellPoint(p1);
lines->InsertCellPoint(p2);
}
//if vvvvv bottom edge of image vvvvv
if (y == yMin)
{ //draw bottom edge of the pixel
vtkIdType p1 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth);
vtkIdType p2 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth);
lines->InsertNextCell(2);
lines->InsertCellPoint(p1);
lines->InsertCellPoint(p2);
}
//if vvvvv top edge of image vvvvv
if (y == yMax)
{ //draw top edge of the pixel
vtkIdType p1 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth);
vtkIdType p2 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth);
lines->InsertNextCell(2);
lines->InsertCellPoint(p1);
lines->InsertCellPoint(p2);
}
}//end if currentpixel is set
x++;
if (x > xMax)
{ //reached end of line
x = xMin;
y++;
}
// Increase the pointer-position to the next pixel.
// This is safe, as the while-loop and the x-reset logic above makes
// sure we do not exceed the bounds of the image
currentPixel++;
}//end of while
// Create a polydata to store everything in
vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New();
// Add the points to the dataset
polyData->SetPoints(points);
// Add the lines to the dataset
polyData->SetLines(lines);
return polyData;
}
void mitk::ImageVtkMapper2D::TransformActor(mitk::BaseRenderer* renderer)
{
LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);
//get the transformation matrix of the reslicer in order to render the slice as axial, coronal or saggital
vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
vtkSmartPointer<vtkMatrix4x4> matrix = localStorage->m_Reslicer->GetResliceAxes();
trans->SetMatrix(matrix);
//transform the plane/contour (the actual actor) to the corresponding view (axial, coronal or saggital)
localStorage->m_Actor->SetUserTransform(trans);
//transform the origin to center based coordinates, because MITK is center based.
localStorage->m_Actor->SetPosition( -0.5*localStorage->m_mmPerPixel[0], -0.5*localStorage->m_mmPerPixel[1], 0.0);
if ( localStorage->m_Actors->GetNumberOfPaths() > 1 )
{
vtkActor* secondaryActor = dynamic_cast<vtkActor*>( localStorage->m_Actors->GetParts()->GetItemAsObject(0) );
secondaryActor->SetUserTransform(trans);
secondaryActor->SetPosition( -0.5*localStorage->m_mmPerPixel[0], -0.5*localStorage->m_mmPerPixel[1], 0.0);
}
}
-bool mitk::ImageVtkMapper2D::RenderingGeometryIntersectsImage( const Geometry2D* renderingGeometry, SlicedGeometry3D* imageGeometry )
+bool mitk::ImageVtkMapper2D::RenderingGeometryIntersectsImage( const PlaneGeometry* renderingGeometry, SlicedGeometry3D* imageGeometry )
{
// if either one of the two geometries is NULL we return true
// for safety reasons
if ( renderingGeometry == NULL || imageGeometry == NULL )
return true;
// get the distance for the first cornerpoint
ScalarType initialDistance = renderingGeometry->SignedDistance( imageGeometry->GetCornerPoint( 0 ) );
for( int i=1; i<8; i++ )
{
mitk::Point3D cornerPoint = imageGeometry->GetCornerPoint( i );
// get the distance to the other cornerpoints
ScalarType distance = renderingGeometry->SignedDistance( cornerPoint );
// if it has not the same signing as the distance of the first point
if ( initialDistance * distance < 0 )
{
// we have an intersection and return true
return true;
}
}
// all distances have the same sign, no intersection and we return false
return false;
}
mitk::ImageVtkMapper2D::LocalStorage::~LocalStorage()
{
}
mitk::ImageVtkMapper2D::LocalStorage::LocalStorage()
: m_VectorComponentExtractor(vtkSmartPointer<vtkImageExtractComponents>::New())
{
m_LevelWindowFilter = vtkSmartPointer<vtkMitkLevelWindowFilter>::New();
//Do as much actions as possible in here to avoid double executions.
m_Plane = vtkSmartPointer<vtkPlaneSource>::New();
m_Texture = vtkSmartPointer<vtkNeverTranslucentTexture>::New().GetPointer();
m_DefaultLookupTable = vtkSmartPointer<vtkLookupTable>::New();
m_BinaryLookupTable = vtkSmartPointer<vtkLookupTable>::New();
m_ColorLookupTable = vtkSmartPointer<vtkLookupTable>::New();
m_Mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
m_Actor = vtkSmartPointer<vtkActor>::New();
m_Actors = vtkSmartPointer<vtkPropAssembly>::New();
m_Reslicer = mitk::ExtractSliceFilter::New();
m_TSFilter = vtkSmartPointer<vtkMitkThickSlicesFilter>::New();
m_OutlinePolyData = vtkSmartPointer<vtkPolyData>::New();
m_ReslicedImage = vtkSmartPointer<vtkImageData>::New();
m_EmptyPolyData = vtkSmartPointer<vtkPolyData>::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();
mitk::LookupTable::Pointer mitkLUT = mitk::LookupTable::New();
//built a default lookuptable
mitkLUT->SetType(mitk::LookupTable::GRAYSCALE);
m_DefaultLookupTable = mitkLUT->GetVtkLookupTable();
mitkLUT->SetType(mitk::LookupTable::LEGACY_BINARY);
m_BinaryLookupTable = mitkLUT->GetVtkLookupTable();
mitkLUT->SetType(mitk::LookupTable::LEGACY_RAINBOW_COLOR);
m_ColorLookupTable = mitkLUT->GetVtkLookupTable();
//do not repeat the texture (the image)
m_Texture->RepeatOff();
//set the mapper for the actor
m_Actor->SetMapper( m_Mapper );
vtkSmartPointer<vtkActor> outlineShadowActor = vtkSmartPointer<vtkActor>::New();
outlineShadowActor->SetMapper( m_Mapper );
m_Actors->AddPart( outlineShadowActor );
m_Actors->AddPart( m_Actor );
}
diff --git a/Core/Code/Rendering/mitkImageVtkMapper2D.h b/Core/Code/Rendering/mitkImageVtkMapper2D.h
index 1409106e72..8ba9e8b2a7 100644
--- a/Core/Code/Rendering/mitkImageVtkMapper2D.h
+++ b/Core/Code/Rendering/mitkImageVtkMapper2D.h
@@ -1,307 +1,307 @@
/*===================================================================
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 MITKIMAGEVTKMAPPER2D_H_HEADER_INCLUDED_C10E906E
#define MITKIMAGEVTKMAPPER2D_H_HEADER_INCLUDED_C10E906E
//MITK
#include <mitkCommon.h>
//MITK Rendering
#include "mitkBaseRenderer.h"
#include "mitkVtkMapper.h"
#include "mitkExtractSliceFilter.h"
//VTK
#include <vtkSmartPointer.h>
#include <vtkPropAssembly.h>
class vtkActor;
class vtkPolyDataMapper;
class vtkPlaneSource;
class vtkImageData;
class vtkLookupTable;
class vtkImageExtractComponents;
class vtkImageReslice;
class vtkImageChangeInformation;
class vtkPoints;
class vtkMitkThickSlicesFilter;
class vtkPolyData;
class vtkMitkApplyLevelWindowToRGBFilter;
class vtkMitkLevelWindowFilter;
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 put into a vtkMitkLevelWindowFilter
* and the scalar levelwindow, opacity levelwindow and optional clipping to
* local image bounds are applied
*
* Next, the output of the vtkMitkLevelWindowFilter 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 "LookupTable": (mitkLookupTableProperty) If this property is set,
* the default lookuptable will be ignored and the "LookupTable" value
* will be used instead.
* - \b "Image Rendering.Mode": This property decides which mode is used to render images. (E.g. if a lookup table or a transferfunction is applied). Detailed documentation about the modes can be found here: \link mitk::RenderingerModeProperty \endlink
* - \b "Image Rendering.Transfer Function": (mitkTransferFunctionProperty) If this
* property is set, a color transferfunction will be used to color the image.
* - \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 "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)
* - \b "Image Rendering.Transfer Function": Default color transfer function for CTs
* - \b "LookupTable": Rainbow color.
* 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 VtkMapper
{
public:
/** Standard class typedefs. */
mitkClassMacro( ImageVtkMapper2D,VtkMapper );
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(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);
//### 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<vtkActor> m_Actor;
vtkSmartPointer<vtkPropAssembly> m_Actors;
/** \brief Mapper of a 2D render window. */
vtkSmartPointer<vtkPolyDataMapper> m_Mapper;
vtkSmartPointer<vtkImageExtractComponents> m_VectorComponentExtractor;
/** \brief Current slice of a 2D render window.*/
vtkSmartPointer<vtkImageData> m_ReslicedImage;
/** \brief Empty vtkPolyData that is set when rendering geometry does not
* intersect the image geometry.
* \warning This member variable is set to NULL,
* if no image geometry is inside the plane geometry
* of the respective render window. Any user of this
* slice has to check whether it is set to NULL!
*/
vtkSmartPointer<vtkPolyData> m_EmptyPolyData;
/** \brief Plane on which the slice is rendered as texture. */
vtkSmartPointer<vtkPlaneSource> m_Plane;
/** \brief The texture which is used to render the current slice. */
vtkSmartPointer<vtkTexture> m_Texture;
/** \brief The lookuptables for colors and level window */
vtkSmartPointer<vtkLookupTable> m_DefaultLookupTable;
vtkSmartPointer<vtkLookupTable> m_BinaryLookupTable;
vtkSmartPointer<vtkLookupTable> m_ColorLookupTable;
/** \brief The actual reslicer (one per renderer) */
mitk::ExtractSliceFilter::Pointer m_Reslicer;
/** \brief Filter for thick slices */
vtkSmartPointer<vtkMitkThickSlicesFilter> m_TSFilter;
/** \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<vtkPolyData> m_OutlinePolyData;
/** \brief Timestamp of last update of stored data. */
itk::TimeStamp m_LastUpdateTime;
/** \brief mmPerPixel relation between pixel and mm. (World spacing).*/
mitk::ScalarType* m_mmPerPixel;
/** \brief This filter is used to apply the level window to Grayvalue and RBG(A) images. */
vtkSmartPointer<vtkMitkLevelWindowFilter> m_LevelWindowFilter;
/** \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::LocalStorageHandler<LocalStorage> m_LSH;
/** \brief Get the LocalStorage corresponding to the current renderer. */
LocalStorage* GetLocalStorage(mitk::BaseRenderer* renderer);
/** \brief Set the default properties for general image rendering. */
static void SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer = NULL, bool overwrite = false);
/** \brief This method switches between different rendering modes (e.g. use a lookup table or a transfer function).
* Detailed documentation about the modes can be found here: \link mitk::RenderingerModeProperty \endlink
*/
void ApplyRenderingMode(mitk::BaseRenderer *renderer);
protected:
/** \brief Transforms the actor to the actual position in 3D.
* \param renderer The current renderer corresponding to the render window.
*/
void TransformActor(mitk::BaseRenderer* renderer);
/** \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, double planeBounds[6]);
/** \brief Generates a vtkPolyData object containing the outline of a given binary slice.
\param renderer: Pointer to the renderer containing the needed information
\note This code is based on code from the iil library.
*/
vtkSmartPointer<vtkPolyData> CreateOutlinePolyData(mitk::BaseRenderer* renderer);
/** 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 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);
/** \brief This method applies (or modifies) the lookuptable for all types of images.
* \warning To use the lookup table, the property 'Lookup Table' must be set and a 'Image Rendering.Mode'
* which uses the lookup table must be set.
*/
void ApplyLookuptable(mitk::BaseRenderer* renderer);
/** \brief This method applies a color transfer function.
* Internally, a vtkColorTransferFunction is used. This is usefull for coloring continous
* images (e.g. float)
* \warning To use the color transfer function, the property 'Image Rendering.Transfer Function' must be set and a 'Image Rendering.Mode' which uses the color transfer function must be set.
*/
void ApplyColorTransferFunction(mitk::BaseRenderer* renderer);
/**
* @brief ApplyLevelWindow Apply the level window for the given renderer.
* \warning To use the level window, the property 'LevelWindow' must be set and a 'Image Rendering.Mode' which uses the level window must be set.
* @param renderer Level window for which renderer?
*/
void ApplyLevelWindow(mitk::BaseRenderer* renderer);
/** \brief Set the color of the image/polydata */
void ApplyColor( mitk::BaseRenderer* renderer );
/** \brief Set the opacity of the actor. */
void ApplyOpacity( mitk::BaseRenderer* renderer );
/**
* \brief Calculates whether the given rendering geometry intersects the
* given SlicedGeometry3D.
*
- * This method checks if the given Geometry2D intersects the given
- * SlicedGeometry3D. It calculates the distance of the Geometry2D to all
+ * This method checks if the given PlaneGeometry intersects the given
+ * SlicedGeometry3D. It calculates the distance of the PlaneGeometry to all
* 8 cornerpoints of the SlicedGeometry3D. If all distances have the same
* sign (all positive or all negative) there is no intersection.
* If the distances have different sign, there is an intersection.
**/
- bool RenderingGeometryIntersectsImage( const Geometry2D* renderingGeometry, SlicedGeometry3D* imageGeometry );
+ bool RenderingGeometryIntersectsImage( const PlaneGeometry* renderingGeometry, SlicedGeometry3D* imageGeometry );
};
} // namespace mitk
#endif /* MITKIMAGEVTKMAPPER2D_H_HEADER_INCLUDED_C10E906E */
diff --git a/Core/Code/Rendering/mitkGeometry2DDataMapper2D.cpp b/Core/Code/Rendering/mitkPlaneGeometryDataMapper2D.cpp
similarity index 87%
rename from Core/Code/Rendering/mitkGeometry2DDataMapper2D.cpp
rename to Core/Code/Rendering/mitkPlaneGeometryDataMapper2D.cpp
index 0b48d9c60d..93e077ba05 100644
--- a/Core/Code/Rendering/mitkGeometry2DDataMapper2D.cpp
+++ b/Core/Code/Rendering/mitkPlaneGeometryDataMapper2D.cpp
@@ -1,671 +1,671 @@
/*===================================================================
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 "mitkPlaneGeometryDataMapper2D.h"
#include "mitkBaseRenderer.h"
#include "mitkPlaneGeometry.h"
#include "mitkColorProperty.h"
#include "mitkProperties.h"
#include "mitkSmartPointerProperty.h"
#include "mitkPlaneOrientationProperty.h"
-#include "mitkGeometry2DDataToSurfaceFilter.h"
+#include "mitkPlaneGeometryDataToSurfaceFilter.h"
#include "mitkSurfaceGLMapper2D.h"
#include "mitkLine.h"
#include "mitkNodePredicateDataType.h"
#include "mitkSlicedGeometry3D.h"
#include "mitkResliceMethodProperty.h"
-mitk::Geometry2DDataMapper2D::Geometry2DDataMapper2D()
+mitk::PlaneGeometryDataMapper2D::PlaneGeometryDataMapper2D()
: m_SurfaceMapper( NULL ), m_DataStorage(NULL), m_ParentNode(NULL),
- m_OtherGeometry2Ds(), m_RenderOrientationArrows( false ),
+ m_OtherPlaneGeometries(), m_RenderOrientationArrows( false ),
m_ArrowOrientationPositive( true )
{
}
-mitk::Geometry2DDataMapper2D::~Geometry2DDataMapper2D()
+mitk::PlaneGeometryDataMapper2D::~PlaneGeometryDataMapper2D()
{
}
-const mitk::Geometry2DData* mitk::Geometry2DDataMapper2D::GetInput(void)
+const mitk::PlaneGeometryData* mitk::PlaneGeometryDataMapper2D::GetInput(void)
{
- return static_cast<const Geometry2DData * > ( GetDataNode()->GetData() );
+ return static_cast<const PlaneGeometryData * > ( GetDataNode()->GetData() );
}
-void mitk::Geometry2DDataMapper2D::GenerateDataForRenderer(mitk::BaseRenderer* renderer)
+void mitk::PlaneGeometryDataMapper2D::GenerateDataForRenderer(mitk::BaseRenderer* renderer)
{
BaseLocalStorage *ls = m_LSH.GetLocalStorage(renderer);
if(!ls->IsGenerateDataRequired(renderer,this,GetDataNode()))
return;
ls->UpdateGenerateDataTime();
- // collect all Geometry2DDatas accessible from the DataStorage
- m_OtherGeometry2Ds.clear();
+ // collect all PlaneGeometryDatas accessible from the DataStorage
+ m_OtherPlaneGeometries.clear();
if (m_DataStorage.IsNull())
return;
- mitk::NodePredicateDataType::Pointer p = mitk::NodePredicateDataType::New("Geometry2DData");
+ mitk::NodePredicateDataType::Pointer p = mitk::NodePredicateDataType::New("PlaneGeometryData");
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<Geometry2DData*>(data);
+ PlaneGeometryData* geometry2dData = dynamic_cast<PlaneGeometryData*>(data);
if(geometry2dData == NULL)
continue;
- PlaneGeometry* planegeometry = dynamic_cast<PlaneGeometry*>(geometry2dData->GetGeometry2D());
+ PlaneGeometry* planegeometry = dynamic_cast<PlaneGeometry*>(geometry2dData->GetPlaneGeometry());
if (planegeometry != NULL)
- m_OtherGeometry2Ds.push_back(it->Value());
+ m_OtherPlaneGeometries.push_back(it->Value());
}
}
-void mitk::Geometry2DDataMapper2D::Paint(BaseRenderer *renderer)
+void mitk::PlaneGeometryDataMapper2D::Paint(BaseRenderer *renderer)
{
bool visible = true;
GetDataNode()->GetVisibility(visible, renderer, "visible");
if(!visible) return;
- Geometry2DData::Pointer input = const_cast< Geometry2DData * >(this->GetInput());
+ PlaneGeometryData::Pointer input = const_cast< PlaneGeometryData * >(this->GetInput());
// intersecting with ourself?
- if ( input.IsNull() || (this->GetInput()->GetGeometry2D() ==
- renderer->GetCurrentWorldGeometry2D()) )
+ if ( input.IsNull() || (this->GetInput()->GetPlaneGeometry() ==
+ renderer->GetCurrentWorldPlaneGeometry()) )
{
return; // do nothing!
}
const PlaneGeometry *inputPlaneGeometry =
- dynamic_cast< const PlaneGeometry * >( input->GetGeometry2D() );
+ dynamic_cast< const PlaneGeometry * >( input->GetPlaneGeometry() );
const PlaneGeometry *worldPlaneGeometry =
dynamic_cast< const PlaneGeometry* >(
- renderer->GetCurrentWorldGeometry2D() );
+ renderer->GetCurrentWorldPlaneGeometry() );
if ( worldPlaneGeometry && inputPlaneGeometry
&& inputPlaneGeometry->GetReferenceGeometry() )
{
DisplayGeometry *displayGeometry = renderer->GetDisplayGeometry();
assert( displayGeometry );
- const Geometry3D *referenceGeometry =
+ const BaseGeometry *referenceGeometry =
inputPlaneGeometry->GetReferenceGeometry();
// calculate intersection of the plane data with the border of the
// world geometry rectangle
Point2D lineFrom, lineTo;
const Geometry3D::TransformType *transform = dynamic_cast< const Geometry3D::TransformType * >(
referenceGeometry->GetIndexToWorldTransform() );
Geometry3D::TransformType::Pointer inverseTransform = Geometry3D::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.reserve( m_OtherPlaneGeometries.size() + 2 );
mainLineParams.push_back( 0.0 );
mainLineParams.push_back( 1.0 );
- primaryHelperLineParams.reserve( m_OtherGeometry2Ds.size() + 2 );
+ primaryHelperLineParams.reserve( m_OtherPlaneGeometries.size() + 2 );
primaryHelperLineParams.push_back( 0.0 );
primaryHelperLineParams.push_back( 1.0 );
- secondaryHelperLineParams.reserve( m_OtherGeometry2Ds.size() + 2 );
+ secondaryHelperLineParams.reserve( m_OtherPlaneGeometries.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();
+ NodesVectorType::iterator otherPlanesIt = m_OtherPlaneGeometries.begin();
+ NodesVectorType::iterator otherPlanesEnd = m_OtherPlaneGeometries.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() );
+ static_cast< PlaneGeometryData * >(
+ (*otherPlanesIt)->GetData() )->GetPlaneGeometry() );
// 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();
+ otherPlanesIt = m_OtherPlaneGeometries.begin();
while ( otherPlanesIt != otherPlanesEnd )
{
PlaneGeometry *otherPlane = static_cast< PlaneGeometry * >(
- static_cast< Geometry2DData * >(
- (*otherPlanesIt)->GetData() )->GetGeometry2D() );
+ static_cast< PlaneGeometryData * >(
+ (*otherPlanesIt)->GetData() )->GetPlaneGeometry() );
// 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;
+ PlaneGeometryDataToSurfaceFilter::Pointer surfaceCreator;
SmartPointerProperty::Pointer surfacecreatorprop;
surfacecreatorprop = dynamic_cast< SmartPointerProperty * >(
GetDataNode()->GetProperty(
"surfacegeometry", renderer));
if( (surfacecreatorprop.IsNull()) ||
(surfacecreatorprop->GetSmartPointer().IsNull()) ||
- ((surfaceCreator = dynamic_cast< Geometry2DDataToSurfaceFilter * >(
+ ((surfaceCreator = dynamic_cast< PlaneGeometryDataToSurfaceFilter * >(
surfacecreatorprop->GetSmartPointer().GetPointer())).IsNull())
)
{
- surfaceCreator = Geometry2DDataToSurfaceFilter::New();
+ surfaceCreator = PlaneGeometryDataToSurfaceFilter::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() )
+ // Clip the PlaneGeometry with the reference geometry bounds (if available)
+ if ( input->GetPlaneGeometry()->HasReferenceGeometry() )
{
surfaceCreator->SetBoundingBox(
- input->GetGeometry2D()->GetReferenceGeometry()->GetBoundingBox()
+ input->GetPlaneGeometry()->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
+ // Calculate the surface of the PlaneGeometry
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,
+void mitk::PlaneGeometryDataMapper2D::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::ApplyAllProperties( BaseRenderer *renderer )
+void mitk::PlaneGeometryDataMapper2D::ApplyAllProperties( BaseRenderer *renderer )
{
Superclass::ApplyColorAndOpacityProperties(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 )
+void mitk::PlaneGeometryDataMapper2D::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,
+void mitk::PlaneGeometryDataMapper2D::DrawLine( BaseRenderer* renderer,
ScalarType lengthInDisplayUnits,
Line<ScalarType,2> &line,
std::vector<ScalarType> &gapPositions,
const PlaneGeometry* inputPlaneGeometry,
bool drawDashed,
ScalarType gapSizeInPixel
)
{
DisplayGeometry *displayGeometry = renderer->GetDisplayGeometry();
const PlaneGeometry *worldPlaneGeometry =
- dynamic_cast< const PlaneGeometry* >( renderer->GetCurrentWorldGeometry2D() );
+ dynamic_cast< const PlaneGeometry* >( renderer->GetCurrentWorldPlaneGeometry() );
// Apply color and opacity read from the PropertyList.
this->ApplyAllProperties( 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 mitk::PlaneGeometryDataMapper2D::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,
+void mitk::PlaneGeometryDataMapper2D::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/mitkPlaneGeometryDataMapper2D.h b/Core/Code/Rendering/mitkPlaneGeometryDataMapper2D.h
new file mode 100644
index 0000000000..3b9a6fdf2e
--- /dev/null
+++ b/Core/Code/Rendering/mitkPlaneGeometryDataMapper2D.h
@@ -0,0 +1,122 @@
+/*===================================================================
+
+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 MITKGEOMETRY2DDATAMAPPER2D_H_HEADER_INCLUDED_C19C0BFB
+#define MITKGEOMETRY2DDATAMAPPER2D_H_HEADER_INCLUDED_C19C0BFB
+
+#include <MitkCoreExports.h>
+#include "mitkGLMapper.h"
+#include "mitkSurfaceGLMapper2D.h"
+#include "mitkDataStorage.h"
+#include "mitkDataNode.h"
+#include "mitkWeakPointer.h"
+#include "mitkLine.h"
+
+namespace mitk {
+ class BaseRenderer;
+ class PlaneGeometryDataMapper2D;
+ /** \deprecatedSince{2014_06} This class is deprecated. Please use PlaneGeometryDataMapper2D instead. */
+ DEPRECATED( typedef PlaneGeometryDataMapper2D Geometry2DDataMapper2D);
+
+ /**
+ * \brief OpenGL-based mapper to display a PlaneGeometry in a 2D window
+ *
+ * Currently implemented for mapping on PlaneGeometry.
+ * The result is normally a line. An important usage of this class is to show
+ * the orientation of the slices displayed in other 2D windows.
+ *
+ *
+ * Properties that can be set and influence the PlaneGeometryDataMapper2D are:
+ *
+ * - \b "PlaneOrientationProperty": (PlaneOrientationProperty)
+
+ * \todo implement for AbstractTransformGeometry.
+ * \ingroup Mapper
+ */
+ class MITK_CORE_EXPORT PlaneGeometryDataMapper2D : public GLMapper
+ {
+ public:
+ mitkClassMacro(PlaneGeometryDataMapper2D, GLMapper);
+
+ itkFactorylessNewMacro(Self)
+ itkCloneMacro(Self)
+
+ /**
+ * \brief Get the PlaneGeometryData to map
+ */
+ const PlaneGeometryData *GetInput();
+
+ virtual void Paint( BaseRenderer *renderer );
+
+ virtual void SetDatastorageAndGeometryBaseNode(mitk::DataStorage::Pointer ds, mitk::DataNode::Pointer parent);
+
+ /** Applies properties specific to this mapper */
+ virtual void ApplyAllProperties( BaseRenderer *renderer );
+
+ LocalStorageHandler<BaseLocalStorage> m_LSH;
+
+ protected:
+ PlaneGeometryDataMapper2D();
+
+ virtual ~PlaneGeometryDataMapper2D();
+
+ virtual void GenerateDataForRenderer(mitk::BaseRenderer* renderer);
+ /**
+ * \brief Returns the thick slice mode for the given datanode.
+ *
+ * This method returns the value of the 'reslice.thickslices' property for
+ * the given datanode.
+ * '0': thick slice mode disabled
+ * '1': thick slice mode enabled
+ *
+ * The variable 'thickSlicesNum' contains the value of the 'reslice.thickslices.num'
+ * property that defines how many slices are shown at once.
+ */
+ int DetermineThickSliceMode( DataNode * dn, int &thickSlicesNum );
+
+ /**
+ * \brief Determines the cross position of two lines and stores them as parametric coordinates
+ *
+ * This method determines the parametric position at which a line 'otherLine' crosses another line
+ * 'mainLine'. The result is stored in 'crossPositions'.
+ */
+ void DetermineParametricCrossPositions( Line<ScalarType,2> &mainLine, Line<ScalarType,2> &otherLine, std::vector<ScalarType> &crossPositions );
+
+ void DrawLine( BaseRenderer * renderer, ScalarType lengthInDisplayUnits,
+ Line< ScalarType, 2 > &line, std::vector< ScalarType > &gapPositions,
+ const PlaneGeometry * inputPlaneGeometry, bool drawDashed,
+ ScalarType gapSizeInPixel
+ );
+
+ void DrawOrientationArrow( Point2D &outerPoint, Point2D &innerPoint,
+ const PlaneGeometry *planeGeometry,
+ const PlaneGeometry *rendererPlaneGeometry,
+ const DisplayGeometry *displayGeometry,
+ bool positiveOrientation = true );
+
+ SurfaceGLMapper2D::Pointer m_SurfaceMapper;
+
+ mitk::WeakPointer<mitk::DataStorage> m_DataStorage; ///< DataStorage that will be searched for sub nodes
+ DataNode::Pointer m_ParentNode; ///< parent node that will be used to search for sub nodes
+
+ typedef std::vector<DataNode*> NodesVectorType;
+ NodesVectorType m_OtherPlaneGeometries;
+
+ bool m_RenderOrientationArrows;
+ bool m_ArrowOrientationPositive;
+ };
+} // namespace mitk
+#endif /* MITKGEOMETRY2DDATAMAPPER2D_H_HEADER_INCLUDED_C19C0BFB */
diff --git a/Core/Code/Rendering/mitkGeometry2DDataVtkMapper3D.cpp b/Core/Code/Rendering/mitkPlaneGeometryDataVtkMapper3D.cpp
similarity index 92%
rename from Core/Code/Rendering/mitkGeometry2DDataVtkMapper3D.cpp
rename to Core/Code/Rendering/mitkPlaneGeometryDataVtkMapper3D.cpp
index fa355c8e25..ac402e7b3e 100644
--- a/Core/Code/Rendering/mitkGeometry2DDataVtkMapper3D.cpp
+++ b/Core/Code/Rendering/mitkPlaneGeometryDataVtkMapper3D.cpp
@@ -1,587 +1,587 @@
/*===================================================================
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 "mitkGeometry2DDataVtkMapper3D.h"
+#include "mitkPlaneGeometryDataVtkMapper3D.h"
#include "mitkImageVtkMapper2D.h"
#include "mitkSmartPointerProperty.h"
#include "mitkSurface.h"
#include "mitkVtkRepresentationProperty.h"
#include "mitkWeakPointerProperty.h"
#include "mitkNodePredicateDataType.h"
#include "mitkNodePredicateOr.h"
#include "vtkNeverTranslucentTexture.h"
#include "vtkMitkLevelWindowFilter.h"
#include <vtkAssembly.h>
#include <vtkDataSetMapper.h>
#include <vtkFeatureEdges.h>
#include <vtkHedgeHog.h>
#include <vtkImageData.h>
#include <vtkLinearTransform.h>
#include <vtkPolyData.h>
#include <vtkPolyDataMapper.h>
#include <vtkProp3DCollection.h>
#include <vtkProperty.h>
#include <vtkTransformPolyDataFilter.h>
#include <vtkTubeFilter.h>
namespace mitk
{
- Geometry2DDataVtkMapper3D::Geometry2DDataVtkMapper3D()
+ PlaneGeometryDataVtkMapper3D::PlaneGeometryDataVtkMapper3D()
: m_NormalsActorAdded(false),
m_DataStorage(NULL)
{
m_EdgeTuber = vtkTubeFilter::New();
m_EdgeMapper = vtkPolyDataMapper::New();
- m_SurfaceCreator = Geometry2DDataToSurfaceFilter::New();
+ m_SurfaceCreator = PlaneGeometryDataToSurfaceFilter::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->SetInputData( emptyPolyData );
emptyPolyData->Delete();
m_Edges->SetInputConnection(m_Cleaner->GetOutputPort());
m_EdgeTransformer->SetInputConnection( m_Edges->GetOutputPort() );
m_EdgeTuber->SetInputConnection( m_EdgeTransformer->GetOutputPort() );
m_EdgeTuber->SetVaryRadiusToVaryRadiusOff();
m_EdgeTuber->SetNumberOfSides( 12 );
m_EdgeTuber->CappingOn();
m_EdgeMapper->SetInputConnection( m_EdgeTuber->GetOutputPort() );
m_EdgeMapper->ScalarVisibilityOff();
m_BackgroundMapper->SetInputData(emptyPolyData);
m_BackgroundMapper->Update();
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( 0.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->SetInputConnection( m_FrontHedgeHog->GetOutputPort());
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_ImageMapperDeletedCommand = MemberCommandType::New();
m_ImageMapperDeletedCommand->SetCallbackFunction(
- this, &Geometry2DDataVtkMapper3D::ImageMapperDeletedCallback );
+ this, &PlaneGeometryDataVtkMapper3D::ImageMapperDeletedCallback );
}
- Geometry2DDataVtkMapper3D::~Geometry2DDataVtkMapper3D()
+ PlaneGeometryDataVtkMapper3D::~PlaneGeometryDataVtkMapper3D()
{
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_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();
m_DataStorage = NULL;
}
- vtkProp* Geometry2DDataVtkMapper3D::GetVtkProp(mitk::BaseRenderer * /*renderer*/)
+ vtkProp* PlaneGeometryDataVtkMapper3D::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*/)
+ void PlaneGeometryDataVtkMapper3D::UpdateVtkTransform(mitk::BaseRenderer * /*renderer*/)
{
m_ImageAssembly->SetUserTransform(
this->GetDataNode()->GetVtkTransform(this->GetTimestep()) );
}
- const Geometry2DData* Geometry2DDataVtkMapper3D::GetInput()
+ const PlaneGeometryData* PlaneGeometryDataVtkMapper3D::GetInput()
{
- return static_cast<const Geometry2DData * > ( GetDataNode()->GetData() );
+ return static_cast<const PlaneGeometryData * > ( GetDataNode()->GetData() );
}
- void Geometry2DDataVtkMapper3D::SetDataStorageForTexture(mitk::DataStorage* storage)
+ void PlaneGeometryDataVtkMapper3D::SetDataStorageForTexture(mitk::DataStorage* storage)
{
if(storage != NULL && m_DataStorage != storage )
{
m_DataStorage = storage;
this->Modified();
}
}
- void Geometry2DDataVtkMapper3D::ImageMapperDeletedCallback(
+ void PlaneGeometryDataVtkMapper3D::ImageMapperDeletedCallback(
itk::Object *caller, const itk::EventObject& /*event*/ )
{
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 );
}
}
}
- void Geometry2DDataVtkMapper3D::GenerateDataForRenderer(BaseRenderer* renderer)
+ void PlaneGeometryDataVtkMapper3D::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();
bool visible = true;
GetDataNode()->GetVisibility(visible, renderer, "visible");
if ( !visible )
{
// 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();
bool drawEdges = true;
this->GetDataNode()->GetBoolProperty("draw edges", drawEdges, renderer);
m_EdgeActor->SetVisibility(drawEdges);
- Geometry2DData::Pointer input = const_cast< Geometry2DData * >(this->GetInput());
+ PlaneGeometryData::Pointer input = const_cast< PlaneGeometryData * >(this->GetInput());
- if (input.IsNotNull() && (input->GetGeometry2D() != NULL))
+ if (input.IsNotNull() && (input->GetPlaneGeometry() != NULL))
{
SmartPointerProperty::Pointer surfacecreatorprop;
surfacecreatorprop = dynamic_cast< SmartPointerProperty * >(GetDataNode()->GetProperty("surfacegeometry", renderer));
if ( (surfacecreatorprop.IsNull())
|| (surfacecreatorprop->GetSmartPointer().IsNull())
- || ((m_SurfaceCreator = dynamic_cast<Geometry2DDataToSurfaceFilter*>
+ || ((m_SurfaceCreator = dynamic_cast<PlaneGeometryDataToSurfaceFilter*>
(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() )
+ // Clip the PlaneGeometry with the reference geometry bounds (if available)
+ if ( input->GetPlaneGeometry()->HasReferenceGeometry() )
{
- Geometry3D *referenceGeometry =
- input->GetGeometry2D()->GetReferenceGeometry();
+ BaseGeometry *referenceGeometry =
+ input->GetPlaneGeometry()->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
+ // Calculate the surface of the PlaneGeometry
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->SetInputData( surface->GetVtkPolyData() );
m_NormalsTransformer->SetTransform(node->GetVtkTransform(this->GetTimestep()) );
m_FrontHedgeHog->SetInputConnection(m_NormalsTransformer->GetOutputPort() );
m_FrontHedgeHog->SetVectorModeToUseNormal();
m_FrontHedgeHog->SetScaleFactor( invertNormals ? 1.0 : -1.0 );
m_FrontHedgeHog->Update();
m_FrontNormalsActor->GetProperty()->SetColor( frontColor[0], frontColor[1], frontColor[2] );
m_BackHedgeHog->SetInputConnection( m_NormalsTransformer->GetOutputPort() );
m_BackHedgeHog->SetVectorModeToUseNormal();
m_BackHedgeHog->SetScaleFactor( invertNormals ? -1.0 : 1.0 );
m_BackHedgeHog->Update();
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->SetInputData( surface->GetVtkPolyData() );
m_ImageAssembly->AddPart( m_BackgroundActor );
LayerSortedActorList layerSortedActors;
// Traverse the data tree to find nodes resliced by ImageMapperGL2D
//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->SetInputData(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<ColorProperty*>(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,
+ void PlaneGeometryDataVtkMapper3D::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
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<ImageVtkMapper2D* >( 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());
// Retrieve and update image to be mapped
const ImageVtkMapper2D::LocalStorage* localStorage = imageMapper->GetLocalStorage(planeRenderer);
if ( planeRenderer.IsNotNull() )
{
// perform update of imagemapper if needed (maybe the respective 2D renderwindow is not rendered/update before)
imageMapper->Update(planeRenderer);
// If it has not been initialized already in a previous pass,
// generate an actor and a texture object to
// render the image associated with the ImageVtkMapper2D.
vtkActor *imageActor;
vtkDataSetMapper *dataSetMapper = NULL;
vtkTexture *texture;
if ( m_ImageActors.count( imageMapper ) == 0 )
{
dataSetMapper = vtkDataSetMapper::New();
//Enable rendering without copying the image.
dataSetMapper->ImmediateModeRenderingOn();
texture = vtkNeverTranslucentTexture::New();
texture->RepeatOff();
imageActor = vtkActor::New();
imageActor->SetMapper( dataSetMapper );
imageActor->SetTexture( texture );
imageActor->GetProperty()->SetOpacity(0.999); // HACK! otherwise VTK wouldn't recognize this as translucent surface (if LUT values map to alpha < 255
// improvement: apply "opacity" property onle HERE and also in 2D image mapper. DO NOT change LUT to achieve translucent images (see method ChangeOpacity in image mapper 2D)
// Make imageActor the sole owner of the mapper and texture
// objects
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();
}
// 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->SetInputData( surface->GetVtkPolyData() );
}
dataSetMapper->Update();
//Check if the m_ReslicedImage is NULL.
//This is the case when no image geometry is met by
//the reslicer. In that case, the texture has to be
//empty (black) and we don't have to do anything.
//See fixed bug #13275
if(localStorage->m_ReslicedImage != NULL)
{
texture->SetInputConnection(localStorage->m_LevelWindowFilter->GetOutputPort());
// do not use a VTK lookup table (we do that ourselves in m_LevelWindowFilter)
texture->MapColorScalarsThroughLookupTableOff();
//re-use properties from the 2D image mapper
imageActor->SetProperty( localStorage->m_Actor->GetProperty() );
imageActor->GetProperty()->SetAmbient(0.5);
// 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)
+ void PlaneGeometryDataVtkMapper3D::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)
+ PlaneGeometryDataVtkMapper3D::ActorInfo::ActorInfo() : m_Actor(NULL), m_Sender(NULL), m_ObserverID(0)
{
}
- Geometry2DDataVtkMapper3D::ActorInfo::~ActorInfo()
+ PlaneGeometryDataVtkMapper3D::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/mitkPlaneGeometryDataVtkMapper3D.h b/Core/Code/Rendering/mitkPlaneGeometryDataVtkMapper3D.h
new file mode 100644
index 0000000000..e762146dea
--- /dev/null
+++ b/Core/Code/Rendering/mitkPlaneGeometryDataVtkMapper3D.h
@@ -0,0 +1,214 @@
+/*===================================================================
+
+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 MITKGEOMETRY2DDATAVTKMAPPER3D_H_HEADER_INCLUDED_C196C71F
+#define MITKGEOMETRY2DDATAVTKMAPPER3D_H_HEADER_INCLUDED_C196C71F
+
+#include <MitkCoreExports.h>
+#include "mitkVtkMapper.h"
+#include "mitkDataStorage.h"
+#include "mitkPlaneGeometryDataToSurfaceFilter.h"
+#include "mitkWeakPointer.h"
+
+#include <vtkSystemIncludes.h>
+#include <vtkCleanPolyData.h>
+
+class vtkActor;
+class vtkPolyDataMapper;
+class vtkAssembly;
+class vtkFeatureEdges;
+class vtkTubeFilter;
+class vtkTransformPolyDataFilter;
+class vtkHedgeHog;
+
+namespace mitk {
+ class PlaneGeometryData;
+ class BaseRenderer;
+ class ImageVtkMapper2D;
+ class DataStorage;
+
+ class PlaneGeometryDataVtkMapper3D;
+ /** \deprecatedSince{2014_06} This class is deprecated. Please use PlaneGeometryDataVTKMapper3D instead. */
+ DEPRECATED( typedef PlaneGeometryDataVtkMapper3D Geometry2DDataVtkMapper3D);
+
+ /**
+ * \brief Vtk-based mapper to display a PlaneGeometry in a 3D window
+ * \ingroup Mapper
+ *
+ * Uses a PlaneGeometryDataToSurfaceFilter object to create a vtkPolyData representation of a given PlaneGeometry instance.
+ * PlaneGeometry 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 "draw edges": (Bool) Toggle display of the tubed frame
+ * - \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 mitkPlaneGeometryDataVtkMapper3D.png "Internal filter pipeline"
+ *
+ */
+ class MITK_CORE_EXPORT PlaneGeometryDataVtkMapper3D : public VtkMapper
+ {
+ public:
+ mitkClassMacro(PlaneGeometryDataVtkMapper3D, VtkMapper);
+
+ itkFactorylessNewMacro(Self)
+ itkCloneMacro(Self)
+
+ /**
+ * 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 PlaneGeometryData to map
+ */
+ virtual const PlaneGeometryData *GetInput();
+
+ /**
+ * \brief All images found when traversing the (sub-) tree starting at
+ * \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;
+
+ PlaneGeometryDataVtkMapper3D();
+
+ virtual ~PlaneGeometryDataVtkMapper3D();
+
+ 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;
+
+ PlaneGeometryDataToSurfaceFilter::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<mitk::DataStorage> m_DataStorage;
+
+ 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< ImageVtkMapper2D *, ActorInfo > ActorList;
+ ActorList m_ImageActors;
+
+ // responsiblity to remove the observer upon its destruction
+ typedef itk::MemberCommand< PlaneGeometryDataVtkMapper3D > MemberCommandType;
+ MemberCommandType::Pointer m_ImageMapperDeletedCommand;
+ };
+} // namespace mitk
+#endif /* MITKGEOMETRY2DDATAVTKMAPPER3D_H_HEADER_INCLUDED_C196C71F */
diff --git a/Core/Code/Rendering/mitkPointSetGLMapper2D.cpp b/Core/Code/Rendering/mitkPointSetGLMapper2D.cpp
index 66b91d9360..968099664a 100644
--- a/Core/Code/Rendering/mitkPointSetGLMapper2D.cpp
+++ b/Core/Code/Rendering/mitkPointSetGLMapper2D.cpp
@@ -1,524 +1,521 @@
/*===================================================================
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 "mitkPointSetGLMapper2D.h"
#include "mitkPointSet.h"
#include "mitkPlaneGeometry.h"
#include "mitkColorProperty.h"
#include "mitkProperties.h"
#include "vtkLinearTransform.h"
#include "mitkStringProperty.h"
#include "mitkPointSet.h"
#include "mitkVtkPropRenderer.h"
#include "mitkGL.h"
//const float selectedColor[]={1.0,0.0,0.6}; //for selected!
mitk::PointSetGLMapper2D::PointSetGLMapper2D()
: m_Polygon(false),
m_ShowPoints(true),
m_ShowDistances(false),
m_DistancesDecimalDigits(1),
m_ShowAngles(false),
m_ShowDistantLines(true),
m_LineWidth(1)
{
}
mitk::PointSetGLMapper2D::~PointSetGLMapper2D()
{
}
const mitk::PointSet *mitk::PointSetGLMapper2D::GetInput(void)
{
return static_cast<const mitk::PointSet * > ( GetDataNode()->GetData() );
}
void mitk::PointSetGLMapper2D::ApplyAllProperties(mitk::BaseRenderer* renderer)
{
GLMapper::ApplyColorAndOpacityProperties( renderer );
const mitk::DataNode* node=GetDataNode();
if( node == NULL )
return;
node->GetBoolProperty("show contour", m_Polygon);
node->GetBoolProperty("close contour", m_PolygonClosed);
node->GetBoolProperty("show points", m_ShowPoints);
node->GetBoolProperty("show distances", m_ShowDistances);
node->GetIntProperty("distance decimal digits", m_DistancesDecimalDigits);
node->GetBoolProperty("show angles", m_ShowAngles);
node->GetBoolProperty("show distant lines", m_ShowDistantLines);
node->GetIntProperty("line width", m_LineWidth);
node->GetIntProperty("point line width", m_PointLineWidth);
node->GetIntProperty("point 2D size", m_Point2DSize);
}
static bool makePerpendicularVector2D(const mitk::Vector2D& in, mitk::Vector2D& out)
{
if((fabs(in[0])>0) && ( (fabs(in[0])>fabs(in[1])) || (in[1] == 0) ) )
{
out[0]=-in[1]/in[0];
out[1]=1;
out.Normalize();
return true;
}
else
if(fabs(in[1])>0)
{
out[0]=1;
out[1]=-in[0]/in[1];
out.Normalize();
return true;
}
else
return false;
}
void mitk::PointSetGLMapper2D::Paint( mitk::BaseRenderer *renderer )
{
-
const mitk::DataNode* node=GetDataNode();
if( node == NULL )
return;
const int text2dDistance = 10;
bool visible = true;
GetDataNode()->GetVisibility(visible, renderer, "visible");
if ( !visible) return;
// @FIXME: Logik fuer update
bool updateNeccesary=true;
if (updateNeccesary)
{
// ok, das ist aus GenerateData kopiert
mitk::PointSet::Pointer input = const_cast<mitk::PointSet*>(this->GetInput());
// Get the TimeGeometry of the input object
const TimeGeometry* inputTimeGeometry = input->GetTimeGeometry();
if (( inputTimeGeometry == NULL ) || ( inputTimeGeometry->CountTimeSteps() == 0 ) )
{
return;
}
//
// get the world time
//
- const Geometry2D* worldGeometry = renderer->GetCurrentWorldGeometry2D();
- assert( worldGeometry != NULL );
- ScalarType time = worldGeometry->GetTimeBounds()[ 0 ];
+ ScalarType time = renderer->GetTime();
//
// convert the world time in time steps of the input object
//
int timeStep=0;
if ( time > ScalarTypeNumericTraits::NonpositiveMin() )
timeStep = inputTimeGeometry->TimePointToTimeStep( time );
if ( inputTimeGeometry->IsValidTimeStep( timeStep ) == false )
{
return;
}
mitk::PointSet::DataType::Pointer itkPointSet = input->GetPointSet( timeStep );
if ( itkPointSet.GetPointer() == NULL)
{
return;
}
mitk::DisplayGeometry::Pointer displayGeometry = renderer->GetDisplayGeometry();
assert(displayGeometry.IsNotNull());
//apply color and opacity read from the PropertyList
this->ApplyAllProperties(renderer);
vtkLinearTransform* transform = GetDataNode()->GetVtkTransform();
//List of the Points
PointSet::DataType::PointsContainerConstIterator it, end;
it = itkPointSet->GetPoints()->Begin();
end = itkPointSet->GetPoints()->End();
//iterator on the additional data of each point
PointSet::DataType::PointDataContainerIterator selIt, selEnd;
bool pointDataBroken = (itkPointSet->GetPointData()->Size() != itkPointSet->GetPoints()->Size());
selIt = itkPointSet->GetPointData()->Begin();
selEnd = itkPointSet->GetPointData()->End();
int counter = 0;
//for writing text
int j = 0;
//for switching back to old color after using selected color
float recallColor[4];
glGetFloatv(GL_CURRENT_COLOR,recallColor);
//get the properties for coloring the points
float unselectedColor[4] = {1.0, 1.0, 0.0, 1.0};//yellow
//check if there is an unselected property
if (dynamic_cast<mitk::ColorProperty*>(node->GetPropertyList(renderer)->GetProperty("unselectedcolor")) != NULL)
{
mitk::Color tmpColor = dynamic_cast<mitk::ColorProperty *>(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("unselectedcolor"))->GetValue();
unselectedColor[0] = tmpColor[0];
unselectedColor[1] = tmpColor[1];
unselectedColor[2] = tmpColor[2];
unselectedColor[3] = 1.0f; //!!define a new ColorProp to be able to pass alpha value
}
else if (dynamic_cast<mitk::ColorProperty*>(node->GetPropertyList(NULL)->GetProperty("unselectedcolor")) != NULL)
{
mitk::Color tmpColor = dynamic_cast<mitk::ColorProperty *>(this->GetDataNode()->GetPropertyList(NULL)->GetProperty("unselectedcolor"))->GetValue();
unselectedColor[0] = tmpColor[0];
unselectedColor[1] = tmpColor[1];
unselectedColor[2] = tmpColor[2];
unselectedColor[3] = 1.0f; //!!define a new ColorProp to be able to pass alpha value
}
else
{
//get the color from the dataNode
node->GetColor(unselectedColor, NULL);
}
//get selected property
float selectedColor[4] = {1.0, 0.0, 0.6, 1.0};
if (dynamic_cast<mitk::ColorProperty*>(node->GetPropertyList(renderer)->GetProperty("selectedcolor")) != NULL)
{
mitk::Color tmpColor = dynamic_cast<mitk::ColorProperty *>(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("selectedcolor"))->GetValue();
selectedColor[0] = tmpColor[0];
selectedColor[1] = tmpColor[1];
selectedColor[2] = tmpColor[2];
selectedColor[3] = 1.0f;
}
else if (dynamic_cast<mitk::ColorProperty*>(node->GetPropertyList(NULL)->GetProperty("selectedcolor")) != NULL)
{
mitk::Color tmpColor = dynamic_cast<mitk::ColorProperty *>(this->GetDataNode()->GetPropertyList(NULL)->GetProperty("selectedcolor"))->GetValue();
selectedColor[0] = tmpColor[0];
selectedColor[1] = tmpColor[1];
selectedColor[2] = tmpColor[2];
selectedColor[3] = 1.0f;
}
//check if there is an pointLineWidth property
if (dynamic_cast<mitk::IntProperty*>(node->GetPropertyList(renderer)->GetProperty("point line width")) != NULL)
{
m_PointLineWidth = dynamic_cast<mitk::IntProperty *>(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("point line width"))->GetValue();
}
else if (dynamic_cast<mitk::IntProperty*>(node->GetPropertyList(NULL)->GetProperty("point line width")) != NULL)
{
m_PointLineWidth = dynamic_cast<mitk::IntProperty *>(this->GetDataNode()->GetPropertyList(NULL)->GetProperty("point line width"))->GetValue();
}
//check if there is an point 2D size property
if (dynamic_cast<mitk::IntProperty*>(node->GetPropertyList(renderer)->GetProperty("point 2D size")) != NULL)
{
m_Point2DSize = dynamic_cast<mitk::IntProperty *>(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("point 2D size"))->GetValue();
}
else if (dynamic_cast<mitk::IntProperty*>(node->GetPropertyList(NULL)->GetProperty("point 2D size")) != NULL)
{
m_Point2DSize = dynamic_cast<mitk::IntProperty *>(this->GetDataNode()->GetPropertyList(NULL)->GetProperty("point 2D size"))->GetValue();
}
Point3D p; // currently visited point
Point3D lastP; // last visited point
Vector3D vec; // p - lastP
Vector3D lastVec; // lastP - point before lastP
vec.Fill(0);
mitk::Point3D projected_p; // p projected on viewplane
Point2D pt2d; // projected_p in display coordinates
Point2D lastPt2d; // last projected_p in display coordinates
Point2D preLastPt2d;// projected_p in display coordinates before lastPt2d
Point2D lastPt2DInPointSet; // The last point in the pointset in display coordinates
mitk::PointSet::DataType::PointType plob;
plob.Fill(0);
itkPointSet->GetPoint( itkPointSet->GetNumberOfPoints()-1, &plob);
//map lastPt2DInPointSet to display coordinates
float vtkp[3];
itk2vtk(plob, vtkp);
transform->TransformPoint(vtkp, vtkp);
vtk2itk(vtkp,p);
displayGeometry->Project(p, projected_p);
displayGeometry->Map(projected_p, lastPt2DInPointSet);
displayGeometry->WorldToDisplay(lastPt2DInPointSet, lastPt2DInPointSet);
while(it!=end) // iterate over all points
{
lastP = p; // valid only for counter > 0
lastVec = vec; // valid only for counter > 1
preLastPt2d = lastPt2d; // valid only for counter > 1
lastPt2d = pt2d; // valid only for counter > 0
itk2vtk(it->Value(), vtkp);
transform->TransformPoint(vtkp, vtkp);
vtk2itk(vtkp,p);
vec = p-lastP; // valid only for counter > 0
displayGeometry->Project(p, projected_p);
Vector3D diff=p-projected_p;
ScalarType scalardiff = diff.GetSquaredNorm();
//MouseOrientation
bool isInputDevice=false;
bool isRendererSlice = scalardiff < 0.00001; //cause roundoff error
if(this->GetDataNode()->GetBoolProperty("inputdevice",isInputDevice) && isInputDevice && !isRendererSlice )
{
displayGeometry->Map(projected_p, pt2d);
displayGeometry->WorldToDisplay(pt2d, pt2d);
//Point size depending of distance to slice
/*float p_size = (1/scalardiff)*10*m_Point2DSize;
if(p_size < m_Point2DSize * 0.6 )
p_size = m_Point2DSize * 0.6 ;
else if ( p_size > m_Point2DSize )
p_size = m_Point2DSize;*/
float p_size = (1/scalardiff)*100.0;
if(p_size < 6.0 )
p_size = 6.0 ;
else if ( p_size > 10.0 )
p_size = 10.0;
//draw Point
float opacity = (p_size<8)?0.3:1.0;//don't get the opacity from the node? Feature not a bug! Otehrwise the 2D cross is hardly seen.
glColor4f(unselectedColor[0],unselectedColor[1],unselectedColor[2],opacity);
glPointSize(p_size);
//glShadeModel(GL_FLAT);
glBegin (GL_POINTS);
glVertex2dv(&pt2d[0]);
glEnd ();
}
//for point set
if(!isInputDevice && ( (scalardiff<4.0) || (m_Polygon)))
{
Point2D tmp;
displayGeometry->Map(projected_p, pt2d);
displayGeometry->WorldToDisplay(pt2d, pt2d);
Vector2D horz,vert;
horz[0]=(float)m_Point2DSize-scalardiff*2; horz[1]=0;
vert[0]=0; vert[1]=(float)m_Point2DSize-scalardiff*2;
// now paint text if available
if (dynamic_cast<mitk::StringProperty *>(this->GetDataNode()
->GetProperty("label")) != NULL)
{
const char * pointLabel = dynamic_cast<mitk::StringProperty *>(
this->GetDataNode()->GetProperty("label"))->GetValue();
std::string l = pointLabel;
if (input->GetSize()>1)
{
// char buffer[20];
// sprintf(buffer,"%d",it->Index());
std::stringstream ss;
ss << it->Index();
l.append(ss.str());
}
if (unselectedColor != NULL)
{
mitk::VtkPropRenderer* OpenGLrenderer = dynamic_cast<mitk::VtkPropRenderer*>( renderer );
float rgb[3];//yellow
rgb[0] = unselectedColor[0]; rgb[1] = unselectedColor[1]; rgb[2] = unselectedColor[2];
OpenGLrenderer->WriteSimpleText(l, pt2d[0] + text2dDistance, pt2d[1] + text2dDistance,rgb[0], rgb[1],rgb[2]);
}
else
{
mitk::VtkPropRenderer* OpenGLrenderer = dynamic_cast<mitk::VtkPropRenderer*>( renderer );
OpenGLrenderer->WriteSimpleText(l, pt2d[0] + text2dDistance, pt2d[1] + text2dDistance,0.0,1.0,0.0);
}
}
if((m_ShowPoints) && (scalardiff<4.0))
{
//check if the point is to be marked as selected
if(selIt != selEnd || pointDataBroken)
{
bool addAsSelected = false;
if (pointDataBroken)
addAsSelected = false;
else if (selIt->Value().selected)
addAsSelected = true;
else
addAsSelected = false;
if (addAsSelected)
{
horz[0]=(float)m_Point2DSize;
vert[1]=(float)m_Point2DSize;
glColor3f(selectedColor[0],selectedColor[1],selectedColor[2]);
glLineWidth(m_PointLineWidth);
//a diamond around the point with the selected color
glBegin (GL_LINE_LOOP);
tmp=pt2d-horz; glVertex2dv(&tmp[0]);
tmp=pt2d+vert; glVertex2dv(&tmp[0]);
tmp=pt2d+horz; glVertex2dv(&tmp[0]);
tmp=pt2d-vert; glVertex2dv(&tmp[0]);
glEnd ();
glLineWidth(1);
//the actual point in the specified color to see the usual color of the point
glColor3f(unselectedColor[0],unselectedColor[1],unselectedColor[2]);
glPointSize(1);
glBegin (GL_POINTS);
tmp=pt2d; glVertex2dv(&tmp[0]);
glEnd ();
}
else //if not selected
{
glColor3f(unselectedColor[0],unselectedColor[1],unselectedColor[2]);
glLineWidth(m_PointLineWidth);
//drawing crosses
glBegin (GL_LINES);
tmp=pt2d-horz; glVertex2dv(&tmp[0]);
tmp=pt2d+horz; glVertex2dv(&tmp[0]);
tmp=pt2d-vert; glVertex2dv(&tmp[0]);
tmp=pt2d+vert; glVertex2dv(&tmp[0]);
glEnd ();
glLineWidth(1);
}
}
}
bool drawLinesEtc = true;
if (!m_ShowDistantLines && counter > 0) // check, whether this line should be drawn
{
ScalarType currentDistance = displayGeometry->GetWorldGeometry()->SignedDistance(p);
ScalarType lastDistance = displayGeometry->GetWorldGeometry()->SignedDistance(lastP);
if ( currentDistance * lastDistance > 0.5 ) // points on same side of plane
drawLinesEtc = false;
}
// draw a line
if ((m_Polygon && counter>0 && drawLinesEtc) ||
(m_Polygon && m_PolygonClosed && drawLinesEtc))
{
if ((counter == 0) && ( m_PolygonClosed))
{
lastPt2d = lastPt2DInPointSet;
}
//get contour color property
float contourColor[4] = {unselectedColor[0], unselectedColor[1], unselectedColor[2], unselectedColor[3]};//so if no property set, then use unselected color
if (dynamic_cast<mitk::ColorProperty*>(node->GetPropertyList(renderer)->GetProperty("contourcolor")) != NULL)
{
mitk::Color tmpColor = dynamic_cast<mitk::ColorProperty *>(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("contourcolor"))->GetValue();
contourColor[0] = tmpColor[0];
contourColor[1] = tmpColor[1];
contourColor[2] = tmpColor[2];
contourColor[3] = 1.0f;
}
else if (dynamic_cast<mitk::ColorProperty*>(node->GetPropertyList(NULL)->GetProperty("contourcolor")) != NULL)
{
mitk::Color tmpColor = dynamic_cast<mitk::ColorProperty *>(this->GetDataNode()->GetPropertyList(NULL)->GetProperty("contourcolor"))->GetValue();
contourColor[0] = tmpColor[0];
contourColor[1] = tmpColor[1];
contourColor[2] = tmpColor[2];
contourColor[3] = 1.0f;
}
//set this color
glColor3f(contourColor[0],contourColor[1],contourColor[2]);
glLineWidth( m_LineWidth );
glBegin (GL_LINES);
glVertex2dv(&pt2d[0]);
glVertex2dv(&lastPt2d[0]);
glEnd ();
glLineWidth(1.0);
if(m_ShowDistances) // calculate and print a distance
{
std::stringstream buffer;
float distance = vec.GetNorm();
buffer<<std::fixed <<std::setprecision(m_DistancesDecimalDigits)<<distance<<" mm";
Vector2D vec2d = pt2d-lastPt2d;
makePerpendicularVector2D(vec2d, vec2d);
Vector2D pos2d = (lastPt2d.GetVectorFromOrigin()+pt2d)*0.5+vec2d*text2dDistance;
mitk::VtkPropRenderer* OpenGLrenderer = dynamic_cast<mitk::VtkPropRenderer*>( renderer );
OpenGLrenderer->WriteSimpleText(buffer.str(), pos2d[0], pos2d[1]);
//this->WriteTextXY(pos2d[0], pos2d[1], buffer.str(),renderer);
}
if(m_ShowAngles && counter > 1 ) // calculate and print the angle btw. two lines
{
std::stringstream buffer;
//buffer << angle(vec.Get_vnl_vector(), -lastVec.Get_vnl_vector())*180/vnl_math::pi << "�";
buffer << angle(vec.GetVnlVector(), -lastVec.GetVnlVector())*180/vnl_math::pi << (char)176;
Vector2D vec2d = pt2d-lastPt2d;
vec2d.Normalize();
Vector2D lastVec2d = lastPt2d-preLastPt2d;
lastVec2d.Normalize();
vec2d=vec2d-lastVec2d;
vec2d.Normalize();
Vector2D pos2d = lastPt2d.GetVectorFromOrigin()+vec2d*text2dDistance*text2dDistance;
mitk::VtkPropRenderer* OpenGLrenderer = dynamic_cast<mitk::VtkPropRenderer*>( renderer );
OpenGLrenderer->WriteSimpleText(buffer.str(), pos2d[0], pos2d[1]);
//this->WriteTextXY(pos2d[0], pos2d[1], buffer.str(),renderer);
}
}
counter++;
}
++it;
if(selIt != selEnd && !pointDataBroken)
++selIt;
j++;
}
//recall the color to the same color before this drawing
glColor3f(recallColor[0],recallColor[1],recallColor[2]);
}
}
void mitk::PointSetGLMapper2D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite)
{
node->AddProperty( "line width", mitk::IntProperty::New(2), renderer, overwrite ); // width of the line from one point to another
node->AddProperty( "point line width", mitk::IntProperty::New(1), renderer, overwrite ); //width of the cross marking a point
node->AddProperty( "point 2D size", mitk::IntProperty::New(8), renderer, overwrite ); // length of the cross marking a point // length of an edge of the box marking a point
node->AddProperty( "show contour", mitk::BoolProperty::New(false), renderer, overwrite ); // contour of the line between points
node->AddProperty( "close contour", mitk::BoolProperty::New(false), renderer, overwrite );
node->AddProperty( "show points", mitk::BoolProperty::New(true), renderer, overwrite ); //show or hide points
node->AddProperty( "show distances", mitk::BoolProperty::New(false), renderer, overwrite ); //show or hide distance measure (not always available)
node->AddProperty( "distance decimal digits", mitk::IntProperty::New(2), renderer, overwrite ); //set the number of decimal digits to be shown
node->AddProperty( "show angles", mitk::BoolProperty::New(false), renderer, overwrite ); //show or hide angle measurement (not always available)
node->AddProperty( "show distant lines", mitk::BoolProperty::New(false), renderer, overwrite ); //show the line between to points from a distant view (equals "always on top" option)
node->AddProperty( "layer", mitk::IntProperty::New(1), renderer, overwrite ); // default to draw pointset above images (they have a default layer of 0)
Superclass::SetDefaultProperties(node, renderer, overwrite);
}
diff --git a/Core/Code/Rendering/mitkPointSetVtkMapper2D.cpp b/Core/Code/Rendering/mitkPointSetVtkMapper2D.cpp
index 04d52709ef..c414dcc3d5 100644
--- a/Core/Code/Rendering/mitkPointSetVtkMapper2D.cpp
+++ b/Core/Code/Rendering/mitkPointSetVtkMapper2D.cpp
@@ -1,717 +1,717 @@
/*===================================================================
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 "mitkPointSetVtkMapper2D.h"
//mitk includes
#include "mitkDataNode.h"
#include "mitkProperties.h"
#include "mitkVtkPropRenderer.h"
#include "mitkPointSet.h"
#include "mitkPlaneGeometry.h"
//vtk includes
#include <vtkActor.h>
#include <vtkPropAssembly.h>
#include <vtkPolyDataMapper.h>
#include <vtkTransform.h>
#include <vtkGlyph3D.h>
#include <vtkTransformFilter.h>
#include <vtkLine.h>
#include <vtkGlyphSource2D.h>
#include <vtkFloatArray.h>
#include <vtkPointData.h>
#include <vtkTextActor.h>
#include <vtkTextProperty.h>
#include <vtkCellArray.h>
#include <stdlib.h>
// constructor LocalStorage
mitk::PointSetVtkMapper2D::LocalStorage::LocalStorage()
{
// points
m_UnselectedPoints = vtkSmartPointer<vtkPoints>::New();
m_SelectedPoints = vtkSmartPointer<vtkPoints>::New();
m_ContourPoints = vtkSmartPointer<vtkPoints>::New();
// scales
m_UnselectedScales = vtkSmartPointer<vtkFloatArray>::New();
m_SelectedScales = vtkSmartPointer<vtkFloatArray>::New();
// distances
m_DistancesBetweenPoints = vtkSmartPointer<vtkFloatArray>::New();
// lines
m_ContourLines = vtkSmartPointer<vtkCellArray>::New();
// glyph source (provides the different shapes)
m_UnselectedGlyphSource2D = vtkSmartPointer<vtkGlyphSource2D>::New();
m_SelectedGlyphSource2D = vtkSmartPointer<vtkGlyphSource2D>::New();
// glyphs
m_UnselectedGlyph3D = vtkSmartPointer<vtkGlyph3D>::New();
m_SelectedGlyph3D = vtkSmartPointer<vtkGlyph3D>::New();
// polydata
m_VtkUnselectedPointListPolyData = vtkSmartPointer<vtkPolyData>::New();
m_VtkSelectedPointListPolyData = vtkSmartPointer <vtkPolyData>::New();
m_VtkContourPolyData = vtkSmartPointer<vtkPolyData>::New();
// actors
m_UnselectedActor = vtkSmartPointer <vtkActor>::New();
m_SelectedActor = vtkSmartPointer <vtkActor>::New();
m_ContourActor = vtkSmartPointer <vtkActor>::New();
// mappers
m_VtkUnselectedPolyDataMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
m_VtkSelectedPolyDataMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
m_VtkContourPolyDataMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
// propassembly
m_PropAssembly = vtkSmartPointer <vtkPropAssembly>::New();
}
// destructor LocalStorage
mitk::PointSetVtkMapper2D::LocalStorage::~LocalStorage()
{
}
// input for this mapper ( = point set)
const mitk::PointSet* mitk::PointSetVtkMapper2D::GetInput() const
{
return static_cast<const mitk::PointSet * > ( GetDataNode()->GetData() );
}
// constructor PointSetVtkMapper2D
mitk::PointSetVtkMapper2D::PointSetVtkMapper2D()
: m_ShowContour(false),
m_CloseContour(false),
m_ShowPoints(true),
m_ShowDistances(false),
m_DistancesDecimalDigits(1),
m_ShowAngles(false),
m_ShowDistantLines(false),
m_LineWidth(1),
m_PointLineWidth(1),
m_Point2DSize(6),
m_IDShapeProperty(mitk::PointSetShapeProperty::CROSS),
m_FillShape(false),
m_DistanceToPlane(4.0f)
{
}
// destructor
mitk::PointSetVtkMapper2D::~PointSetVtkMapper2D()
{
}
// reset mapper so that nothing is displayed e.g. toggle visiblity of the propassembly
void mitk::PointSetVtkMapper2D::ResetMapper( BaseRenderer* renderer )
{
LocalStorage *ls = m_LSH.GetLocalStorage(renderer);
ls->m_PropAssembly->VisibilityOff();
}
// returns propassembly
vtkProp* mitk::PointSetVtkMapper2D::GetVtkProp(mitk::BaseRenderer * renderer)
{
LocalStorage *ls = m_LSH.GetLocalStorage(renderer);
return ls->m_PropAssembly;
}
static bool makePerpendicularVector2D(const mitk::Vector2D& in, mitk::Vector2D& out)
{
// The dot product of orthogonal vectors is zero.
// In two dimensions the slopes of perpendicular lines are negative reciprocals.
if((fabs(in[0])>0) && ( (fabs(in[0])>fabs(in[1])) || (in[1] == 0) ) )
{
// negative reciprocal
out[0]=-in[1]/in[0];
out[1]=1;
out.Normalize();
return true;
}
else
if(fabs(in[1])>0)
{
out[0]=1;
// negative reciprocal
out[1]=-in[0]/in[1];
out.Normalize();
return true;
}
else
return false;
}
void mitk::PointSetVtkMapper2D::CreateVTKRenderObjects(mitk::BaseRenderer* renderer)
{
LocalStorage *ls = m_LSH.GetLocalStorage(renderer);
unsigned i = 0;
// The vtk text actors need to be removed manually from the propassembly
// since the same vtk text actors are not overwriten within this function,
// but new actors are added to the propassembly each time this function is executed.
// Thus, the actors from the last call must be removed in the beginning.
for(i=0; i< ls->m_VtkTextLabelActors.size(); i++)
{
if(ls->m_PropAssembly->GetParts()->IsItemPresent(ls->m_VtkTextLabelActors.at(i)))
ls->m_PropAssembly->RemovePart(ls->m_VtkTextLabelActors.at(i));
}
for(i=0; i< ls->m_VtkTextDistanceActors.size(); i++)
{
if(ls->m_PropAssembly->GetParts()->IsItemPresent(ls->m_VtkTextDistanceActors.at(i)))
ls->m_PropAssembly->RemovePart(ls->m_VtkTextDistanceActors.at(i));
}
for(i=0; i< ls->m_VtkTextAngleActors.size(); i++)
{
if(ls->m_PropAssembly->GetParts()->IsItemPresent(ls->m_VtkTextAngleActors.at(i)))
ls->m_PropAssembly->RemovePart(ls->m_VtkTextAngleActors.at(i));
}
// initialize polydata here, otherwise we have update problems when
// executing this function again
ls->m_VtkUnselectedPointListPolyData = vtkSmartPointer<vtkPolyData>::New();
ls->m_VtkSelectedPointListPolyData = vtkSmartPointer <vtkPolyData>::New();
ls->m_VtkContourPolyData = vtkSmartPointer<vtkPolyData>::New();
// get input point set and update the PointSet
mitk::PointSet::Pointer input = const_cast<mitk::PointSet*>(this->GetInput());
// only update the input data, if the property tells us to
bool update = true;
this->GetDataNode()->GetBoolProperty("updateDataOnRender", update);
if (update == true)
input->Update();
int timestep = this->GetTimestep();
mitk::PointSet::DataType::Pointer itkPointSet = input->GetPointSet( timestep );
if ( itkPointSet.GetPointer() == NULL)
{
ls->m_PropAssembly->VisibilityOff();
return;
}
//iterator for point set
mitk::PointSet::PointsContainer::Iterator pointsIter = itkPointSet->GetPoints()->Begin();
// PointDataContainer has additional information to each point, e.g. whether
// it is selected or not
mitk::PointSet::PointDataContainer::Iterator pointDataIter;
pointDataIter = itkPointSet->GetPointData()->Begin();
//check if the list for the PointDataContainer is the same size as the PointsContainer.
//If not, then the points were inserted manually and can not be visualized according to the PointData (selected/unselected)
bool pointDataBroken = (itkPointSet->GetPointData()->Size() != itkPointSet->GetPoints()->Size());
if( itkPointSet->GetPointData()->size() == 0 || pointDataBroken)
{
ls->m_PropAssembly->VisibilityOff();
return;
}
ls->m_PropAssembly->VisibilityOn();
// empty point sets, cellarrays, scalars
ls->m_UnselectedPoints->Reset();
ls->m_SelectedPoints->Reset();
ls->m_ContourPoints->Reset();
ls->m_ContourLines->Reset();
ls->m_UnselectedScales->Reset();
ls->m_SelectedScales->Reset();
ls->m_DistancesBetweenPoints->Reset();
ls->m_VtkTextLabelActors.clear();
ls->m_VtkTextDistanceActors.clear();
ls->m_VtkTextAngleActors.clear();
ls->m_UnselectedScales->SetNumberOfComponents(3);
ls->m_SelectedScales->SetNumberOfComponents(3);
int NumberContourPoints = 0;
bool pointsOnSameSideOfPlane = false;
const int text2dDistance = 10;
// initialize points with a random start value
// current point in point set
itk::Point<ScalarType> point = pointsIter->Value();
mitk::Point3D p = point; // currently visited point
mitk::Point3D lastP = point; // last visited point (predecessor in point set of "point")
mitk::Vector3D vec; // p - lastP
mitk::Vector3D lastVec; // lastP - point before lastP
vec.Fill(0);
lastVec.Fill(0);
mitk::Point3D projected_p = point; // p projected on viewplane
mitk::Point2D pt2d;
pt2d[0] = point[0]; // projected_p in display coordinates
pt2d[1] = point[1];
mitk::Point2D lastPt2d = pt2d; // last projected_p in display coordinates (predecessor in point set of "pt2d")
mitk::Point2D preLastPt2d = pt2d ; // projected_p in display coordinates before lastPt2
mitk::DisplayGeometry::Pointer displayGeometry = renderer->GetDisplayGeometry();
- const mitk::Geometry2D* geo2D = renderer->GetCurrentWorldGeometry2D();
+ const mitk::PlaneGeometry* geo2D = renderer->GetCurrentWorldPlaneGeometry();
vtkLinearTransform* dataNodeTransform = input->GetGeometry()->GetVtkTransform();
int count = 0;
for (pointsIter=itkPointSet->GetPoints()->Begin();
pointsIter!=itkPointSet->GetPoints()->End();
pointsIter++)
{
lastP = p; // valid for number of points count > 0
preLastPt2d = lastPt2d; // valid only for count > 1
lastPt2d = pt2d; // valid for number of points count > 0
lastVec = vec; // valid only for counter > 1
// get current point in point set
point = pointsIter->Value();
// transform point
{
float vtkp[3];
itk2vtk(point, vtkp);
dataNodeTransform->TransformPoint(vtkp, vtkp);
vtk2itk(vtkp,point);
}
p[0] = point[0];
p[1] = point[1];
p[2] = point[2];
displayGeometry->Project(p, projected_p);
displayGeometry->Map(projected_p, pt2d);
displayGeometry->WorldToDisplay(pt2d, pt2d);
vec = p-lastP; // valid only for counter > 0
// compute distance to current plane
float diff = geo2D->Distance(point);
diff = diff * diff;
// draw markers on slices a certain distance away from the points true location according to the tolerance threshold (m_DistanceToPlane)
if(diff < m_DistanceToPlane)
{
// is point selected or not?
if (pointDataIter->Value().selected)
{
ls->m_SelectedPoints->InsertNextPoint(point[0],point[1],point[2]);
// point is scaled according to its distance to the plane
ls->m_SelectedScales->InsertNextTuple3(m_Point2DSize - (2*diff),0,0);
}
else
{
ls->m_UnselectedPoints->InsertNextPoint(point[0],point[1],point[2]);
// point is scaled according to its distance to the plane
ls->m_UnselectedScales->InsertNextTuple3(m_Point2DSize - (2*diff),0,0);
}
//---- LABEL -----//
// paint label for each point if available
if (dynamic_cast<mitk::StringProperty *>(this->GetDataNode()->GetProperty("label")) != NULL)
{
const char * pointLabel = dynamic_cast<mitk::StringProperty *>(
this->GetDataNode()->GetProperty("label"))->GetValue();
std::string l = pointLabel;
if (input->GetSize()>1)
{
std::stringstream ss;
ss << pointsIter->Index();
l.append(ss.str());
}
ls->m_VtkTextActor = vtkSmartPointer<vtkTextActor>::New();
ls->m_VtkTextActor->SetPosition(pt2d[0] + text2dDistance, pt2d[1] + text2dDistance);
ls->m_VtkTextActor->SetInput(l.c_str());
ls->m_VtkTextActor->GetTextProperty()->SetOpacity( 100 );
float unselectedColor[4];
//check if there is a color property
GetDataNode()->GetColor(unselectedColor);
if (unselectedColor != NULL)
ls->m_VtkTextActor->GetTextProperty()->SetColor(unselectedColor[0], unselectedColor[1], unselectedColor[2]);
else
ls->m_VtkTextActor->GetTextProperty()->SetColor(0.0f, 1.0f, 0.0f);
ls->m_VtkTextLabelActors.push_back(ls->m_VtkTextActor);
}
}
// draw contour, distance text and angle text in render window
// lines between points, which intersect the current plane, are drawn
if( m_ShowContour && count > 0 )
{
ScalarType distance = displayGeometry->GetWorldGeometry()->SignedDistance(point);
ScalarType lastDistance = displayGeometry->GetWorldGeometry()->SignedDistance(lastP);
pointsOnSameSideOfPlane = (distance * lastDistance) > 0.5;
// Points must be on different side of plane in order to draw a contour.
// If "show distant lines" is enabled this condition is disregarded.
if ( !pointsOnSameSideOfPlane || m_ShowDistantLines)
{
vtkSmartPointer<vtkLine> line = vtkSmartPointer<vtkLine>::New();
ls->m_ContourPoints->InsertNextPoint(lastP[0],lastP[1],lastP[2]);
line->GetPointIds()->SetId(0, NumberContourPoints);
NumberContourPoints++;
ls->m_ContourPoints->InsertNextPoint(point[0], point[1], point[2]);
line->GetPointIds()->SetId(1, NumberContourPoints);
NumberContourPoints++;
ls->m_ContourLines->InsertNextCell(line);
if(m_ShowDistances) // calculate and print distance between adjacent points
{
float distancePoints = point.EuclideanDistanceTo(lastP);
std::stringstream buffer;
buffer<<std::fixed <<std::setprecision(m_DistancesDecimalDigits)<<distancePoints<<" mm";
// compute desired display position of text
Vector2D vec2d = pt2d-lastPt2d;
makePerpendicularVector2D(vec2d, vec2d); // text is rendered within text2dDistance perpendicular to current line
Vector2D pos2d = (lastPt2d.GetVectorFromOrigin() + pt2d ) * 0.5 + vec2d * text2dDistance;
ls->m_VtkTextActor = vtkSmartPointer<vtkTextActor>::New();
ls->m_VtkTextActor->SetPosition(pos2d[0],pos2d[1]);
ls->m_VtkTextActor->SetInput(buffer.str().c_str());
ls->m_VtkTextActor->GetTextProperty()->SetColor(0.0, 1.0, 0.0);
ls->m_VtkTextDistanceActors.push_back(ls->m_VtkTextActor);
}
if(m_ShowAngles && count > 1) // calculate and print angle between connected lines
{
std::stringstream buffer;
//(char) 176 is the degree sign
buffer << angle(vec.GetVnlVector(), -lastVec.GetVnlVector())*180/vnl_math::pi << (char)176;
//compute desired display position of text
Vector2D vec2d = pt2d-lastPt2d; // first arm enclosing the angle
vec2d.Normalize();
Vector2D lastVec2d = lastPt2d-preLastPt2d; // second arm enclosing the angle
lastVec2d.Normalize();
vec2d=vec2d-lastVec2d; // vector connecting both arms
vec2d.Normalize();
// middle between two vectors that enclose the angle
Vector2D pos2d = lastPt2d.GetVectorFromOrigin() + vec2d * text2dDistance * text2dDistance;
ls->m_VtkTextActor = vtkSmartPointer<vtkTextActor>::New();
ls->m_VtkTextActor->SetPosition(pos2d[0],pos2d[1]);
ls->m_VtkTextActor->SetInput(buffer.str().c_str());
ls->m_VtkTextActor->GetTextProperty()->SetColor(0.0, 1.0, 0.0);
ls->m_VtkTextAngleActors.push_back(ls->m_VtkTextActor);
}
}
}
if(pointDataIter != itkPointSet->GetPointData()->End())
{
pointDataIter++;
count++;
}
}
// add each single text actor to the assembly
for(i=0; i< ls->m_VtkTextLabelActors.size(); i++)
{
ls->m_PropAssembly->AddPart(ls->m_VtkTextLabelActors.at(i));
}
for(i=0; i< ls->m_VtkTextDistanceActors.size(); i++)
{
ls->m_PropAssembly->AddPart(ls->m_VtkTextDistanceActors.at(i));
}
for(i=0; i< ls->m_VtkTextAngleActors.size(); i++)
{
ls->m_PropAssembly->AddPart(ls->m_VtkTextAngleActors.at(i));
}
//---- CONTOUR -----//
//create lines between the points which intersect the plane
if (m_ShowContour)
{
// draw line between first and last point which is rendered
if(m_CloseContour && NumberContourPoints > 1){
vtkSmartPointer<vtkLine> closingLine = vtkSmartPointer<vtkLine>::New();
closingLine->GetPointIds()->SetId(0, 0); // index of first point
closingLine->GetPointIds()->SetId(1, NumberContourPoints-1); // index of last point
ls->m_ContourLines->InsertNextCell(closingLine);
}
ls->m_VtkContourPolyData->SetPoints(ls->m_ContourPoints);
ls->m_VtkContourPolyData->SetLines(ls->m_ContourLines);
ls->m_VtkContourPolyDataMapper->SetInputData(ls->m_VtkContourPolyData);
ls->m_ContourActor->SetMapper(ls->m_VtkContourPolyDataMapper);
ls->m_ContourActor->GetProperty()->SetLineWidth(m_LineWidth);
ls->m_PropAssembly->AddPart(ls->m_ContourActor);
}
// the point set must be transformed in order to obtain the appropriate glyph orientation
// according to the current view
vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New();
vtkSmartPointer<vtkMatrix4x4> a,b = vtkSmartPointer<vtkMatrix4x4>::New();
a = geo2D->GetVtkTransform()->GetMatrix();
b->DeepCopy( a );
// delete transformation from matrix, only take orientation
b->SetElement(3,3,1);
b->SetElement(2,3,0);
b->SetElement(1,3,0);
b->SetElement(0,3,0);
b->SetElement(3,2,0);
b->SetElement(3,1,0);
b->SetElement(3,0,0);
transform->SetMatrix( b );
//---- UNSELECTED POINTS -----//
// apply properties to glyph
ls->m_UnselectedGlyphSource2D->SetGlyphType(m_IDShapeProperty);
if(m_FillShape)
ls->m_UnselectedGlyphSource2D->FilledOn();
else
ls->m_UnselectedGlyphSource2D->FilledOff();
// apply transform
vtkSmartPointer<vtkTransformFilter> transformFilterU = vtkSmartPointer<vtkTransformFilter>::New();
transformFilterU->SetInputConnection(ls->m_UnselectedGlyphSource2D->GetOutputPort());
transformFilterU->SetTransform(transform);
ls->m_VtkUnselectedPointListPolyData->SetPoints(ls->m_UnselectedPoints);
ls->m_VtkUnselectedPointListPolyData->GetPointData()->SetVectors(ls->m_UnselectedScales);
// apply transform of current plane to glyphs
ls->m_UnselectedGlyph3D->SetSourceConnection(transformFilterU->GetOutputPort());
ls->m_UnselectedGlyph3D->SetInputData(ls->m_VtkUnselectedPointListPolyData);
ls->m_UnselectedGlyph3D->SetScaleModeToScaleByVector();
ls->m_UnselectedGlyph3D->SetVectorModeToUseVector();
ls->m_VtkUnselectedPolyDataMapper->SetInputConnection(ls->m_UnselectedGlyph3D->GetOutputPort());
ls->m_UnselectedActor->SetMapper(ls->m_VtkUnselectedPolyDataMapper);
ls->m_UnselectedActor->GetProperty()->SetLineWidth(m_PointLineWidth);
ls->m_PropAssembly->AddPart(ls->m_UnselectedActor);
//---- SELECTED POINTS -----//
ls->m_SelectedGlyphSource2D->SetGlyphTypeToDiamond();
ls->m_SelectedGlyphSource2D->CrossOn();
ls->m_SelectedGlyphSource2D->FilledOff();
// apply transform
vtkSmartPointer<vtkTransformFilter> transformFilterS = vtkSmartPointer<vtkTransformFilter>::New();
transformFilterS->SetInputConnection(ls->m_SelectedGlyphSource2D->GetOutputPort());
transformFilterS->SetTransform(transform);
ls->m_VtkSelectedPointListPolyData->SetPoints(ls->m_SelectedPoints);
ls->m_VtkSelectedPointListPolyData->GetPointData()->SetVectors(ls->m_SelectedScales);
// apply transform of current plane to glyphs
ls->m_SelectedGlyph3D->SetSourceConnection(transformFilterS->GetOutputPort());
ls->m_SelectedGlyph3D->SetInputData(ls->m_VtkSelectedPointListPolyData);
ls->m_SelectedGlyph3D->SetScaleModeToScaleByVector();
ls->m_SelectedGlyph3D->SetVectorModeToUseVector();
ls->m_VtkSelectedPolyDataMapper->SetInputConnection(ls->m_SelectedGlyph3D->GetOutputPort());
ls->m_SelectedActor->SetMapper(ls->m_VtkSelectedPolyDataMapper);
ls->m_SelectedActor->GetProperty()->SetLineWidth(m_PointLineWidth);
ls->m_PropAssembly->AddPart(ls->m_SelectedActor);
}
void mitk::PointSetVtkMapper2D::GenerateDataForRenderer( mitk::BaseRenderer *renderer )
{
const mitk::DataNode* node = GetDataNode();
if( node == NULL )
return;
LocalStorage *ls = m_LSH.GetLocalStorage(renderer);
// check whether the input data has been changed
bool needGenerateData = ls->IsGenerateDataRequired( renderer, this, GetDataNode() );
// toggle visibility
bool visible = true;
node->GetVisibility(visible, renderer, "visible");
if(!visible)
{
ls->m_UnselectedActor->VisibilityOff();
ls->m_SelectedActor->VisibilityOff();
ls->m_ContourActor->VisibilityOff();
ls->m_PropAssembly->VisibilityOff();
return;
}else{
ls->m_PropAssembly->VisibilityOn();
}
node->GetBoolProperty("show contour", m_ShowContour, renderer);
node->GetBoolProperty("close contour", m_CloseContour, renderer);
node->GetBoolProperty("show points", m_ShowPoints, renderer);
node->GetBoolProperty("show distances", m_ShowDistances, renderer);
node->GetIntProperty("distance decimal digits", m_DistancesDecimalDigits, renderer);
node->GetBoolProperty("show angles", m_ShowAngles, renderer);
node->GetBoolProperty("show distant lines", m_ShowDistantLines, renderer);
node->GetIntProperty("line width", m_LineWidth, renderer);
node->GetIntProperty("point line width", m_PointLineWidth, renderer);
node->GetIntProperty("point 2D size", m_Point2DSize, renderer);
node->GetBoolProperty("Pointset.2D.fill shape", m_FillShape, renderer);
node->GetFloatProperty("Pointset.2D.distance to plane", m_DistanceToPlane, renderer );
mitk::PointSetShapeProperty::Pointer shape = dynamic_cast<mitk::PointSetShapeProperty*>(this->GetDataNode()->GetProperty( "Pointset.2D.shape", renderer ));
if(shape.IsNotNull())
{
m_IDShapeProperty = shape->GetPointSetShape();
}
//check for color props and use it for rendering of selected/unselected points and contour
//due to different params in VTK (double/float) we have to convert
float unselectedColor[4];
double selectedColor[4]={1.0f,0.0f,0.0f,1.0f}; //red
double contourColor[4]={1.0f,0.0f,0.0f,1.0f}; //red
float opacity = 1.0;
GetDataNode()->GetOpacity(opacity, renderer);
// apply color and opacity
if(m_ShowPoints)
{
ls->m_UnselectedActor->VisibilityOn();
ls->m_SelectedActor->VisibilityOn();
//check if there is a color property
GetDataNode()->GetColor(unselectedColor);
//get selected color property
if (dynamic_cast<mitk::ColorProperty*>(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("selectedcolor")) != NULL)
{
mitk::Color tmpColor = dynamic_cast<mitk::ColorProperty *>(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("selectedcolor"))->GetValue();
selectedColor[0] = tmpColor[0];
selectedColor[1] = tmpColor[1];
selectedColor[2] = tmpColor[2];
selectedColor[3] = 1.0f; // alpha value
}
else if (dynamic_cast<mitk::ColorProperty*>(this->GetDataNode()->GetPropertyList(NULL)->GetProperty("selectedcolor")) != NULL)
{
mitk::Color tmpColor = dynamic_cast<mitk::ColorProperty *>(this->GetDataNode()->GetPropertyList(NULL)->GetProperty("selectedcolor"))->GetValue();
selectedColor[0] = tmpColor[0];
selectedColor[1] = tmpColor[1];
selectedColor[2] = tmpColor[2];
selectedColor[3] = 1.0f; // alpha value
}
ls->m_SelectedActor->GetProperty()->SetColor(selectedColor);
ls->m_SelectedActor->GetProperty()->SetOpacity(opacity);
ls->m_UnselectedActor->GetProperty()->SetColor(unselectedColor[0],unselectedColor[1],unselectedColor[2]);
ls->m_UnselectedActor->GetProperty()->SetOpacity(opacity);
}
else
{
ls->m_UnselectedActor->VisibilityOff();
ls-> m_SelectedActor->VisibilityOff();
}
if (m_ShowContour)
{
ls->m_ContourActor->VisibilityOn();
//get contour color property
if (dynamic_cast<mitk::ColorProperty*>(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("contourcolor")) != NULL)
{
mitk::Color tmpColor = dynamic_cast<mitk::ColorProperty *>(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("contourcolor"))->GetValue();
contourColor[0] = tmpColor[0];
contourColor[1] = tmpColor[1];
contourColor[2] = tmpColor[2];
contourColor[3] = 1.0f;
}
else if (dynamic_cast<mitk::ColorProperty*>(this->GetDataNode()->GetPropertyList(NULL)->GetProperty("contourcolor")) != NULL)
{
mitk::Color tmpColor = dynamic_cast<mitk::ColorProperty *>(this->GetDataNode()->GetPropertyList(NULL)->GetProperty("contourcolor"))->GetValue();
contourColor[0] = tmpColor[0];
contourColor[1] = tmpColor[1];
contourColor[2] = tmpColor[2];
contourColor[3] = 1.0f;
}
ls->m_ContourActor->GetProperty()->SetColor(contourColor);
ls->m_ContourActor->GetProperty()->SetOpacity(opacity);
}
else
{
ls->m_ContourActor->VisibilityOff();
}
if(needGenerateData)
{
// create new vtk render objects (e.g. a circle for a point)
this->CreateVTKRenderObjects(renderer);
}
}
void mitk::PointSetVtkMapper2D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite)
{
node->AddProperty( "line width", mitk::IntProperty::New(2), renderer, overwrite );
node->AddProperty( "point line width", mitk::IntProperty::New(1), renderer, overwrite );
node->AddProperty( "point 2D size", mitk::IntProperty::New(6), renderer, overwrite );
node->AddProperty( "show contour", mitk::BoolProperty::New(false), renderer, overwrite );
node->AddProperty( "close contour", mitk::BoolProperty::New(false), renderer, overwrite );
node->AddProperty( "show points", mitk::BoolProperty::New(true), renderer, overwrite );
node->AddProperty( "show distances", mitk::BoolProperty::New(false), renderer, overwrite );
node->AddProperty( "distance decimal digits", mitk::IntProperty::New(2), renderer, overwrite );
node->AddProperty( "show angles", mitk::BoolProperty::New(false), renderer, overwrite );
node->AddProperty( "show distant lines", mitk::BoolProperty::New(false), renderer, overwrite );
node->AddProperty( "layer", mitk::IntProperty::New(1), renderer, overwrite );
node->AddProperty( "Pointset.2D.fill shape", mitk::BoolProperty::New(false), renderer, overwrite); // fill or do not fill the glyph shape
mitk::PointSetShapeProperty::Pointer pointsetShapeProperty = mitk::PointSetShapeProperty::New();
node->AddProperty( "Pointset.2D.shape", pointsetShapeProperty, renderer, overwrite);
node->AddProperty( "Pointset.2D.distance to plane", mitk::FloatProperty::New(4.0f), renderer, overwrite ); //show the point at a certain distance above/below the 2D imaging plane.
Superclass::SetDefaultProperties(node, renderer, overwrite);
}
diff --git a/Core/Code/Rendering/mitkSurfaceGLMapper2D.cpp b/Core/Code/Rendering/mitkSurfaceGLMapper2D.cpp
index de23b26633..bac6ecca0c 100644
--- a/Core/Code/Rendering/mitkSurfaceGLMapper2D.cpp
+++ b/Core/Code/Rendering/mitkSurfaceGLMapper2D.cpp
@@ -1,544 +1,538 @@
/*===================================================================
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 "mitkSurfaceGLMapper2D.h"
#include "mitkBaseRenderer.h"
#include "mitkPlaneGeometry.h"
#include "mitkSurface.h"
#include "mitkColorProperty.h"
#include "mitkProperties.h"
#include "mitkVtkScalarModeProperty.h"
#include "mitkAbstractTransformGeometry.h"
#include "mitkLookupTableProperty.h"
#include <vtkPolyData.h>
#include <vtkPlane.h>
#include <vtkCutter.h>
#include <vtkPoints.h>
#include <vtkCellArray.h>
#include <vtkLookupTable.h>
#include <vtkPointData.h>
#include <vtkCellData.h>
#include <vtkDataArray.h>
#include <vtkLinearTransform.h>
#include <vtkAbstractMapper.h>
#include <vtkPKdTree.h>
#include <vtkStripper.h>
mitk::SurfaceGLMapper2D::SurfaceGLMapper2D()
: m_Plane( vtkPlane::New() ),
m_Cutter( vtkCutter::New() ),
m_LUT( vtkLookupTable::New() ),
m_PointLocator( vtkPKdTree::New() ),
m_Stripper( vtkStripper::New() ),
m_DrawNormals(false),
m_FrontNormalLengthInPixels(10.0),
m_BackNormalLengthInPixels(10.0)
{
// default for normals on front side = green
m_FrontSideColor[0] = 0.0;
m_FrontSideColor[1] = 1.0;
m_FrontSideColor[2] = 0.0;
m_FrontSideColor[3] = 1.0;
// default for normals on back side = red
m_BackSideColor[0] = 1.0;
m_BackSideColor[1] = 0.0;
m_BackSideColor[2] = 0.0;
m_BackSideColor[3] = 1.0;
// default for line color = yellow
m_LineColor[0] = 1.0;
m_LineColor[1] = 1.0;
m_LineColor[2] = 0.0;
m_LineColor[3] = 1.0;
m_Cutter->SetCutFunction(m_Plane);
m_Cutter->GenerateValues(1,0,1);
m_LUT->SetTableRange(0,255);
m_LUT->SetNumberOfColors(255);
m_LUT->SetRampToLinear();
m_LUT->Build();
}
mitk::SurfaceGLMapper2D::~SurfaceGLMapper2D()
{
m_Plane->Delete();
m_Cutter->Delete();
m_LUT->Delete();
m_PointLocator->Delete();
m_Stripper->Delete();
}
const mitk::Surface *mitk::SurfaceGLMapper2D::GetInput(void)
{
if(m_Surface.IsNotNull())
return m_Surface;
return static_cast<const Surface * > ( GetDataNode()->GetData() );
}
void mitk::SurfaceGLMapper2D::SetDataNode( mitk::DataNode* node )
{
Superclass::SetDataNode( node );
bool useCellData;
if (dynamic_cast<BoolProperty *>(node->GetProperty("deprecated useCellDataForColouring")) == NULL)
useCellData = false;
else
useCellData = dynamic_cast<BoolProperty *>(node->GetProperty("deprecated useCellDataForColouring"))->GetValue();
if (!useCellData)
{
// search min/max point scalars over all time steps
double dataRange[2] = {0,0};
double range[2];
Surface::Pointer input = const_cast< Surface* >(dynamic_cast<const Surface*>( this->GetDataNode()->GetData() ));
if(input.IsNull()) return;
const TimeGeometry::Pointer inputTimeGeometry = input->GetTimeGeometry();
if(( inputTimeGeometry.IsNull() ) || ( inputTimeGeometry->CountTimeSteps() == 0 ) ) return;
for (unsigned int timestep=0; timestep<inputTimeGeometry->CountTimeSteps(); timestep++)
{
vtkPolyData * vtkpolydata = input->GetVtkPolyData( timestep );
if((vtkpolydata==NULL) || (vtkpolydata->GetNumberOfPoints() < 1 )) continue;
vtkDataArray *vpointscalars = vtkpolydata->GetPointData()->GetScalars();
if (vpointscalars) {
vpointscalars->GetRange( range, 0 );
if (dataRange[0]==0 && dataRange[1]==0) {
dataRange[0] = range[0];
dataRange[1] = range[1];
}
else {
if (range[0] < dataRange[0]) dataRange[0] = range[0];
if (range[1] > dataRange[1]) dataRange[1] = range[1];
}
}
}
if (dataRange[1] - dataRange[0] > 0) {
m_LUT->SetTableRange( dataRange );
m_LUT->Build();
}
}
}
void mitk::SurfaceGLMapper2D::Paint(mitk::BaseRenderer * renderer)
{
bool visible = true;
GetDataNode()->GetVisibility(visible, renderer, "visible");
if(!visible) return;
Surface::Pointer input = const_cast<Surface*>(this->GetInput());
if(input.IsNull())
return;
//
// get the TimeGeometry of the input object
//
const TimeGeometry* inputTimeGeometry = input->GetTimeGeometry();
if(( inputTimeGeometry == NULL ) || ( inputTimeGeometry->CountTimeSteps() == 0 ) )
return;
if (dynamic_cast<IntProperty *>(this->GetDataNode()->GetProperty("line width")) == NULL)
m_LineWidth = 1;
else
m_LineWidth = dynamic_cast<IntProperty *>(this->GetDataNode()->GetProperty("line width"))->GetValue();
//
// get the world time
//
- Geometry2D::ConstPointer worldGeometry = renderer->GetCurrentWorldGeometry2D();
- assert( worldGeometry.IsNotNull() );
-
- ScalarType time = worldGeometry->GetTimeBounds()[ 0 ];
+ ScalarType time =renderer->GetTime();
int timestep=0;
if( time > ScalarTypeNumericTraits::NonpositiveMin() )
timestep = inputTimeGeometry->TimePointToTimeStep( time );
// int timestep = this->GetTimestep();
if( inputTimeGeometry->IsValidTimeStep( timestep ) == false )
return;
vtkPolyData * vtkpolydata = input->GetVtkPolyData( timestep );
if((vtkpolydata==NULL) || (vtkpolydata->GetNumberOfPoints() < 1 ))
return;
- PlaneGeometry::ConstPointer worldPlaneGeometry = dynamic_cast<const PlaneGeometry*>(worldGeometry.GetPointer());
-
//apply color and opacity read from the PropertyList
this->ApplyAllProperties(renderer);
if (m_DrawNormals)
{
m_PointLocator->SetDataSet( vtkpolydata );
m_PointLocator->BuildLocatorFromPoints( vtkpolydata->GetPoints() );
}
if(vtkpolydata!=NULL)
{
Point3D point;
Vector3D normal;
//Check if Lookup-Table is already given, else use standard one.
double* scalarLimits = m_LUT->GetTableRange();
double scalarsMin = scalarLimits[0], scalarsMax = scalarLimits[1];
vtkLookupTable *lut;
LookupTableProperty::Pointer lookupTableProp;
this->GetDataNode()->GetProperty(lookupTableProp, "LookupTable", renderer);
if (lookupTableProp.IsNotNull() )
{
lut = lookupTableProp->GetLookupTable()->GetVtkLookupTable();
if (dynamic_cast<FloatProperty *>(this->GetDataNode()->GetProperty("ScalarsRangeMinimum")) != NULL)
scalarsMin = dynamic_cast<FloatProperty*>(this->GetDataNode()->GetProperty("ScalarsRangeMinimum"))->GetValue();
if (dynamic_cast<FloatProperty *>(this->GetDataNode()->GetProperty("ScalarsRangeMaximum")) != NULL)
scalarsMax = dynamic_cast<FloatProperty*>(this->GetDataNode()->GetProperty("ScalarsRangeMaximum"))->GetValue();
// check if the scalar range has been changed, e.g. manually, for the data tree node, and rebuild the LUT if necessary.
double* oldRange = lut->GetTableRange();
if( oldRange[0] != scalarsMin || oldRange[1] != scalarsMax )
{
lut->SetTableRange(scalarsMin, scalarsMax);
lut->Build();
}
}
else
{
lut = m_LUT;
}
vtkLinearTransform * vtktransform = GetDataNode()->GetVtkTransform(timestep);
- if(worldPlaneGeometry.IsNotNull())
+ Geometry2D::ConstPointer worldGeometry = renderer->GetCurrentWorldGeometry2D();
+ assert( worldGeometry.IsNotNull() );
+ if (worldGeometry.IsNotNull())
{
// set up vtkPlane according to worldGeometry
- point=worldPlaneGeometry->GetOrigin();
- normal=worldPlaneGeometry->GetNormal(); normal.Normalize();
+ point=worldGeometry->GetOrigin();
+ normal=worldGeometry->GetNormal(); normal.Normalize();
m_Plane->SetTransform((vtkAbstractTransform*)NULL);
}
else
{
- AbstractTransformGeometry::ConstPointer worldAbstractGeometry = dynamic_cast<const AbstractTransformGeometry*>(renderer->GetCurrentWorldGeometry2D());
+ AbstractTransformGeometry::ConstPointer worldAbstractGeometry = dynamic_cast<const AbstractTransformGeometry*>(renderer->GetCurrentWorldPlaneGeometry());
if(worldAbstractGeometry.IsNotNull())
{
AbstractTransformGeometry::ConstPointer surfaceAbstractGeometry = dynamic_cast<const AbstractTransformGeometry*>(input->GetTimeGeometry()->GetGeometryForTimeStep(0).GetPointer());
if(surfaceAbstractGeometry.IsNotNull()) //@todo substitude by operator== after implementation, see bug id 28
{
PaintCells(renderer, vtkpolydata, worldGeometry, renderer->GetDisplayGeometry(), vtktransform, lut);
return;
}
else
{
//@FIXME: does not work correctly. Does m_Plane->SetTransform really transforms a "flat plane" into a "curved plane"?
return;
// set up vtkPlane according to worldGeometry
point=const_cast<BoundingBox*>(worldAbstractGeometry->GetParametricBoundingBox())->GetMinimum();
FillVector3D(normal, 0, 0, 1);
m_Plane->SetTransform(worldAbstractGeometry->GetVtkAbstractTransform()->GetInverse());
}
}
else
return;
}
double vp[3], vnormal[3];
vnl2vtk(point.GetVnlVector(), vp);
vnl2vtk(normal.GetVnlVector(), vnormal);
//normally, we would need to transform the surface and cut the transformed surface with the cutter.
//This might be quite slow. Thus, the idea is, to perform an inverse transform of the plane instead.
//@todo It probably does not work for scaling operations yet:scaling operations have to be
//dealed with after the cut is performed by scaling the contour.
vtkLinearTransform * inversetransform = vtktransform->GetLinearInverse();
inversetransform->TransformPoint(vp, vp);
inversetransform->TransformNormalAtPoint(vp, vnormal, vnormal);
m_Plane->SetOrigin(vp);
m_Plane->SetNormal(vnormal);
//set data into cutter
m_Cutter->SetInputData(vtkpolydata);
m_Cutter->Update();
// m_Cutter->GenerateCutScalarsOff();
// m_Cutter->SetSortByToSortByCell();
if (m_DrawNormals)
{
m_Stripper->SetInputData( m_Cutter->GetOutput() );
// calculate the cut
m_Stripper->Update();
PaintCells(renderer, m_Stripper->GetOutput(), worldGeometry, renderer->GetDisplayGeometry(), vtktransform, lut, vtkpolydata);
}
else
{
PaintCells(renderer, m_Cutter->GetOutput(), worldGeometry, renderer->GetDisplayGeometry(), vtktransform, lut, vtkpolydata);
}
}
}
void mitk::SurfaceGLMapper2D::PaintCells(mitk::BaseRenderer* renderer, vtkPolyData* contour,
- const Geometry2D* worldGeometry,
+ const PlaneGeometry* worldGeometry,
const DisplayGeometry* displayGeometry,
vtkLinearTransform * vtktransform,
vtkLookupTable *lut,
vtkPolyData* original3DObject)
{
// deprecated settings
bool usePointData = false;
bool useCellData = false;
this->GetDataNode()->GetBoolProperty("deprecated useCellDataForColouring", useCellData);
bool scalarVisibility = false;
this->GetDataNode()->GetBoolProperty("scalar visibility", scalarVisibility);
if(scalarVisibility)
{
VtkScalarModeProperty* scalarMode;
if(this->GetDataNode()->GetProperty(scalarMode, "scalar mode", renderer))
{
if( (scalarMode->GetVtkScalarMode() == VTK_SCALAR_MODE_USE_POINT_DATA) ||
(scalarMode->GetVtkScalarMode() == VTK_SCALAR_MODE_DEFAULT) )
{
usePointData = true;
}
if(scalarMode->GetVtkScalarMode() == VTK_SCALAR_MODE_USE_CELL_DATA)
{
useCellData = true;
}
}
else
{
usePointData = true;
}
}
vtkPoints *vpoints = contour->GetPoints();
vtkDataArray *vpointscalars = contour->GetPointData()->GetScalars();
vtkCellArray *vlines = contour->GetLines();
vtkDataArray* vcellscalars = contour->GetCellData()->GetScalars();
Point3D p; Point2D p2d, last;
int i, j;
int numberOfLines = vlines->GetNumberOfCells();
glLineWidth( m_LineWidth );
glBegin (GL_LINES);
glColor4fv(m_LineColor);
double distanceSinceLastNormal(0.0);
vlines->InitTraversal();
for(i=0;i<numberOfLines;++i)
{
vtkIdType *cell(NULL);
vtkIdType cellSize(0);
double vp[3];
vlines->GetNextCell(cellSize, cell);
vpoints->GetPoint(cell[0], vp);
//take transformation via vtktransform into account
vtktransform->TransformPoint(vp, vp);
vtk2itk(vp, p);
//convert 3D point (in mm) to 2D point on slice (also in mm)
worldGeometry->Map(p, p2d);
//convert point (until now mm and in world coordinates) to display coordinates (units )
displayGeometry->WorldToDisplay(p2d, p2d);
last=p2d;
for(j=1; j<cellSize; ++j)
{
vpoints->GetPoint(cell[j], vp);
Point3D originalPoint;
vtk2itk(vp, originalPoint);
//take transformation via vtktransform into account
vtktransform->TransformPoint(vp, vp);
vtk2itk(vp, p);
//convert 3D point (in mm) to 2D point on slice (also in mm)
worldGeometry->Map(p, p2d);
//convert point (until now mm and in world coordinates) to display coordinates (units )
displayGeometry->WorldToDisplay(p2d, p2d);
double color[3];
if (useCellData && vcellscalars != NULL )
{
// color each cell according to cell data
lut->GetColor( vcellscalars->GetComponent(i,0),color);
glColor3f(color[0],color[1],color[2]);
glVertex2f(last[0], last[1]);
glVertex2f(p2d[0], p2d[1]);
}
else if (usePointData && vpointscalars != NULL )
{
lut->GetColor( vpointscalars->GetComponent(cell[j-1],0),color);
glColor3f(color[0],color[1],color[2]);
glVertex2f(last[0], last[1]);
lut->GetColor( vpointscalars->GetComponent(cell[j],0),color);
glColor3f(color[0],color[1],color[2]);
glVertex2f(p2d[0], p2d[1]);
}
else
{
glVertex2f(last[0], last[1]);
glVertex2f(p2d[0], p2d[1]);
// draw normals ?
if (m_DrawNormals && original3DObject)
{
distanceSinceLastNormal += sqrt((p2d[0]-last[0])*(p2d[0]-last[0]) + (p2d[1]-last[1])*(p2d[1]-last[1]));
if (distanceSinceLastNormal >= 5.0)
{
distanceSinceLastNormal = 0.0;
vtkPointData* pointData = original3DObject->GetPointData();
if (!pointData) break;
vtkDataArray* normalsArray = pointData->GetNormals();
if (!normalsArray) break;
// find 3D point closest to the currently drawn point
double distance(0.0);
vtkIdType closestPointId = m_PointLocator->FindClosestPoint(originalPoint[0], originalPoint[1], originalPoint[2], distance);
if (closestPointId >= 0)
{
// find normal of 3D object at this 3D point
double* normal = normalsArray->GetTuple3(closestPointId);
double transformedNormal[3];
vtktransform->TransformNormal(normal, transformedNormal);
Vector3D normalITK;
vtk2itk(transformedNormal, normalITK);
normalITK.Normalize();
// calculate a point (point from the cut 3D object) + (normal vector of closest point)
Point3D tip3D = p + normalITK;
// map this point into our 2D coordinate system
Point2D tip2D;
worldGeometry->Map(tip3D, tip2D);
displayGeometry->WorldToDisplay(tip2D, tip2D);
// calculate 2D vector from point to point+normal, normalize it to standard length
Vector2D tipVectorGLFront = tip2D - p2d;
tipVectorGLFront.Normalize();
tipVectorGLFront *= m_FrontNormalLengthInPixels;
Vector2D tipVectorGLBack = p2d - tip2D;
tipVectorGLBack.Normalize();
tipVectorGLBack *= m_BackNormalLengthInPixels;
Point2D tipPoint2D = p2d + tipVectorGLFront;
Point2D backTipPoint2D = p2d + tipVectorGLBack;
// draw normalized mapped normal vector
glColor4f(m_BackSideColor[0], m_BackSideColor[1], m_BackSideColor[2], m_BackSideColor[3]); // red backside
glVertex2f(p2d[0], p2d[1]);
glVertex2f(tipPoint2D[0], tipPoint2D[1]);
glColor4f(m_FrontSideColor[0], m_FrontSideColor[1], m_FrontSideColor[2], m_FrontSideColor[3]); // green backside
glVertex2f(p2d[0], p2d[1]);
glVertex2f(backTipPoint2D[0], backTipPoint2D[1]);
glColor4fv(m_LineColor); // back to line color
}
}
}
}
last=p2d;
}
}
glEnd();
glLineWidth(1.0);
}
void mitk::SurfaceGLMapper2D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite)
{
node->AddProperty( "line width", IntProperty::New(2), renderer, overwrite );
node->AddProperty( "scalar mode", VtkScalarModeProperty::New(), renderer, overwrite );
node->AddProperty( "draw normals 2D", BoolProperty::New(false), renderer, overwrite );
node->AddProperty( "invert normals", BoolProperty::New(false), renderer, overwrite );
node->AddProperty( "front color", ColorProperty::New(0.0, 1.0, 0.0), renderer, overwrite );
node->AddProperty( "back color", ColorProperty::New(1.0, 0.0, 0.0), renderer, overwrite );
node->AddProperty( "front normal lenth (px)", FloatProperty::New(10.0), renderer, overwrite );
node->AddProperty( "back normal lenth (px)", FloatProperty::New(10.0), renderer, overwrite );
node->AddProperty( "layer", mitk::IntProperty::New(100), renderer, overwrite);
Superclass::SetDefaultProperties(node, renderer, overwrite);
}
void mitk::SurfaceGLMapper2D::ApplyAllProperties(mitk::BaseRenderer* renderer)
{
ApplyColorAndOpacityProperties(renderer);
DataNode * node = GetDataNode();
if(node == NULL)
{
return;
}
node->GetBoolProperty("draw normals 2D", m_DrawNormals, renderer);
// check for color and opacity properties, use it for rendering if they exists
node->GetColor(m_LineColor, renderer, "color");
node->GetOpacity(m_LineColor[3], renderer, "opacity");
bool invertNormals(false);
node->GetBoolProperty("invert normals", invertNormals, renderer);
if (!invertNormals)
{
node->GetColor(m_FrontSideColor, renderer, "front color");
node->GetOpacity(m_FrontSideColor[3], renderer, "opacity");
node->GetColor(m_BackSideColor, renderer, "back color");
node->GetOpacity(m_BackSideColor[3], renderer, "opacity");
node->GetFloatProperty( "front normal lenth (px)", m_FrontNormalLengthInPixels, renderer );
node->GetFloatProperty( "back normal lenth (px)", m_BackNormalLengthInPixels, renderer );
-
}
else
{
node->GetColor(m_FrontSideColor, renderer, "back color");
node->GetOpacity(m_FrontSideColor[3], renderer, "opacity");
node->GetColor(m_BackSideColor, renderer, "front color");
node->GetOpacity(m_BackSideColor[3], renderer, "opacity");
node->GetFloatProperty( "back normal lenth (px)", m_FrontNormalLengthInPixels, renderer );
node->GetFloatProperty( "front normal lenth (px)", m_BackNormalLengthInPixels, renderer );
-
}
}
-
diff --git a/Core/Code/Rendering/mitkSurfaceGLMapper2D.h b/Core/Code/Rendering/mitkSurfaceGLMapper2D.h
index 77b7766371..310409b441 100644
--- a/Core/Code/Rendering/mitkSurfaceGLMapper2D.h
+++ b/Core/Code/Rendering/mitkSurfaceGLMapper2D.h
@@ -1,156 +1,156 @@
/*===================================================================
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 MITKSURFACEDATAMAPPER2D_H_HEADER_INCLUDED_C10EB2E8
#define MITKSURFACEDATAMAPPER2D_H_HEADER_INCLUDED_C10EB2E8
#include <MitkCoreExports.h>
#include "mitkGLMapper.h"
#include "mitkSurface.h"
class vtkCutter;
class vtkPlane;
class vtkLookupTable;
class vtkLinearTransform;
class vtkPKdTree;
class vtkStripper;
namespace mitk {
class BaseRenderer;
-class Geometry2D;
+class PlaneGeometry;
class DisplayGeometry;
/**
* @brief OpenGL-based mapper to display a Surface in a 2D window.
*
* Displays a 2D cut through a Surface object (vtkPolyData). This
* is basically done in two steps:
*
* 1. Cut a slice out of a (input) vtkPolyData object. The slice may be a flat plane (PlaneGeometry)
* or a curved plane (ThinPlateSplineCurvedGeometry). The actual cutting is done by a vtkCutter.
* The result of cutting is a (3D) vtkPolyData object, which contains only points and lines
* describing the cut.
*
* 2. Paint the cut out slice by means of OpenGL. To do this, all lines of the cut object are traversed.
* For each line segment, both end points are transformed from 3D into the 2D system of the associated
* renderer and then drawn by OpenGL.
*
* There is a mode to display normals of the input surface object (see properties below). If this mode
* is on, then the drawing of the 2D cut is slightly more complicated. For each line segment of the cut,
* we take the end point (p2d) of this line and search the input vtkPolyData object for the closest point to p2d (p3D-input).
* We then read out the surface normal for p3D-input. We map this normal into our 2D coordinate system and
* then draw a line from p2d to (p2d+mapped normal). This drawing of surface normals will only work if the
* input vtkPolyData actually HAS normals. If you have a vtkPolyData without normals, use the vtkPolyDataNormals
* filter to generate normals.
*
* Properties that influence rendering are:
*
* - \b "color": (ColorProperty) Color of surface object
* - \b "line width": (IntProperty) Width in pixels of the lines drawn.
* - \b "scalar visibility": (BoolProperty) Whether point/cell data values (from vtkPolyData) should be used to influence colors
* - \b "scalar mode": (BoolProperty) If "scalar visibility" is on, whether to use point data or cell data for coloring.
* - \b "LookupTable": (LookupTableProperty) A lookup table to translate point/cell data values (from vtkPolyData) to colors
* - \b "ScalarsRangeMinimum": (FloatProperty) Range of the lookup table
* - \b "ScalarsRangeMaximum": (FloatProperty) Range of the lookup table
* - \b "draw normals 2D": (BoolProperty) If true, normals are drawn (if present in vtkPolyData)
* - \b "invert normals": (BoolProperty) Inverts front/back for display.
* - \b "front color": (ColorProperty) Color for normals display on front side of the plane
* - \b "front normal length (px)": (FloatProperty) Length of the front side normals in pixels.
* - \b "back color": (ColorProperty) Color for normals display on back side of the plane
* - \b "back normal length (px)": (FloatProperty) Length of the back side normals in pixels.
*
*/
class MITK_CORE_EXPORT SurfaceGLMapper2D : public GLMapper
{
public:
mitkClassMacro(SurfaceGLMapper2D, GLMapper);
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
const Surface* GetInput(void);
virtual void Paint(BaseRenderer* renderer);
/**
* @brief The Surface to map can be explicitly set by this method.
*
* If it is set, it is used instead of the data stored in the DataNode.
* This enables to use the mapper also internally from other mappers.
*/
itkSetConstObjectMacro(Surface, Surface);
/**
* @brief Get the Surface set explicitly.
*
* @return NULL is returned if no Surface is set to be used instead of DataNode::GetData().
* @sa SetSurface
*/
itkGetConstObjectMacro(Surface, Surface);
/**
*\brief Overwritten to initialize lookup table for point scalar data
*/
void SetDataNode( DataNode* node );
/**
* \brief Generate OpenGL primitives for the VTK contour held in contour.
*/
void PaintCells(BaseRenderer* renderer, vtkPolyData* contour,
- const Geometry2D* worldGeometry,
+ const PlaneGeometry* worldGeometry,
const DisplayGeometry* displayGeometry,
vtkLinearTransform* vtktransform,
vtkLookupTable* lut = NULL,
vtkPolyData* original3DObject = NULL);
static void SetDefaultProperties(DataNode* node, BaseRenderer* renderer = NULL, bool overwrite = false);
virtual void ApplyAllProperties(BaseRenderer* renderer);
protected:
SurfaceGLMapper2D();
virtual ~SurfaceGLMapper2D();
vtkPlane* m_Plane;
vtkCutter* m_Cutter;
Surface::ConstPointer m_Surface;
vtkLookupTable* m_LUT;
int m_LineWidth;
vtkPKdTree* m_PointLocator;
vtkStripper* m_Stripper;
bool m_DrawNormals;
float m_FrontSideColor[4];
float m_BackSideColor[4];
float m_LineColor[4];
float m_FrontNormalLengthInPixels;
float m_BackNormalLengthInPixels;
};
} // namespace mitk
#endif /* MITKSURFACEDATAMAPPER2D_H_HEADER_INCLUDED_C10EB2E8 */
diff --git a/Core/Code/Rendering/mitkVolumeDataVtkMapper3D.cpp b/Core/Code/Rendering/mitkVolumeDataVtkMapper3D.cpp
index 52f8065424..1ad7e45e0a 100644
--- a/Core/Code/Rendering/mitkVolumeDataVtkMapper3D.cpp
+++ b/Core/Code/Rendering/mitkVolumeDataVtkMapper3D.cpp
@@ -1,706 +1,706 @@
/*===================================================================
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 "mitkVolumeDataVtkMapper3D.h"
#include "mitkDataNode.h"
#include "mitkProperties.h"
#include "mitkLevelWindow.h"
#include "mitkColorProperty.h"
#include "mitkLevelWindowProperty.h"
#include "mitkLookupTableProperty.h"
#include "mitkTransferFunctionProperty.h"
#include "mitkTransferFunctionInitializer.h"
#include "mitkColorProperty.h"
#include "mitkVtkPropRenderer.h"
#include "mitkRenderingManager.h"
#include <vtkActor.h>
#include <vtkProperty.h>
#include <vtkVolumeRayCastMapper.h>
#include <vtkVolumeTextureMapper2D.h>
#include <vtkVolume.h>
#include <vtkVolumeProperty.h>
#include <vtkColorTransferFunction.h>
#include <vtkPiecewiseFunction.h>
#include <vtkVolumeRayCastCompositeFunction.h>
#include <vtkVolumeRayCastMIPFunction.h>
#include <vtkFiniteDifferenceGradientEstimator.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkImageShiftScale.h>
#include <vtkImageChangeInformation.h>
#include <vtkImageWriter.h>
#include <vtkImageData.h>
#include <vtkLODProp3D.h>
#include <vtkImageResample.h>
#include <vtkPlane.h>
#include <vtkImplicitPlaneWidget.h>
#include <vtkAssembly.h>
#include <vtkCubeSource.h>
#include <vtkPolyDataMapper.h>
#include "mitkVtkVolumeRenderingProperty.h"
#include <itkMultiThreader.h>
const mitk::Image* mitk::VolumeDataVtkMapper3D::GetInput()
{
return static_cast<const mitk::Image*> ( GetDataNode()->GetData() );
}
mitk::VolumeDataVtkMapper3D::VolumeDataVtkMapper3D()
: m_Mask( NULL )
{
m_PlaneSet = false;
m_ClippingPlane = vtkPlane::New();
m_PlaneWidget = vtkImplicitPlaneWidget::New();
/*
m_T2DMapper = vtkVolumeTextureMapper2D::New();
m_T2DMapper->SetMaximumNumberOfPlanes( 100 );
*/
m_HiResMapper = vtkVolumeRayCastMapper::New();
m_HiResMapper->SetSampleDistance(1.0); // 4 rays for every pixel
m_HiResMapper->IntermixIntersectingGeometryOn();
m_HiResMapper->SetNumberOfThreads( itk::MultiThreader::GetGlobalDefaultNumberOfThreads() );
/*
vtkVolumeRayCastCompositeFunction* compositeFunction = vtkVolumeRayCastCompositeFunction::New();
compositeFunction->SetCompositeMethodToClassifyFirst();
m_HiResMapper->SetVolumeRayCastFunction(compositeFunction);
compositeFunction->Delete();
vtkVolumeRayCastMIPFunction* mipFunction = vtkVolumeRayCastMIPFunction::New();
m_HiResMapper->SetVolumeRayCastFunction(mipFunction);
mipFunction->Delete();
*/
vtkFiniteDifferenceGradientEstimator* gradientEstimator =
vtkFiniteDifferenceGradientEstimator::New();
m_HiResMapper->SetGradientEstimator(gradientEstimator);
gradientEstimator->Delete();
m_VolumePropertyLow = vtkVolumeProperty::New();
m_VolumePropertyMed = vtkVolumeProperty::New();
m_VolumePropertyHigh = vtkVolumeProperty::New();
m_VolumeLOD = vtkLODProp3D::New();
m_VolumeLOD->VisibilityOff();
m_HiResID = m_VolumeLOD->AddLOD(m_HiResMapper,m_VolumePropertyHigh,0.0); // RayCast
// m_LowResID = m_VolumeLOD->AddLOD(m_T2DMapper,m_VolumePropertyLow,0.0); // TextureMapper2D
m_MedResID = m_VolumeLOD->AddLOD(m_HiResMapper,m_VolumePropertyMed,0.0); // RayCast
m_Resampler = vtkImageResample::New();
m_Resampler->SetAxisMagnificationFactor(0,0.25);
m_Resampler->SetAxisMagnificationFactor(1,0.25);
m_Resampler->SetAxisMagnificationFactor(2,0.25);
// For abort rendering mechanism
m_VolumeLOD->AutomaticLODSelectionOff();
m_BoundingBox = vtkCubeSource::New();
m_BoundingBox->SetXLength( 0.0 );
m_BoundingBox->SetYLength( 0.0 );
m_BoundingBox->SetZLength( 0.0 );
m_BoundingBoxMapper = vtkPolyDataMapper::New();
m_BoundingBoxMapper->SetInputConnection( m_BoundingBox->GetOutputPort() );
m_BoundingBoxActor = vtkActor::New();
m_BoundingBoxActor->SetMapper( m_BoundingBoxMapper );
m_BoundingBoxActor->GetProperty()->SetColor( 1.0, 1.0, 1.0 );
m_BoundingBoxActor->GetProperty()->SetRepresentationToWireframe();
// BoundingBox rendering is not working due to problem with assembly
// transformation; see bug #454
// If commenting in the following, do not forget to comment in the
// m_Prop3DAssembly->Delete() line in the destructor.
//m_Prop3DAssembly = vtkAssembly::New();
//m_Prop3DAssembly->AddPart( m_VolumeLOD );
//m_Prop3DAssembly->AddPart( m_BoundingBoxActor );
//m_Prop3D = m_Prop3DAssembly;
m_ImageCast = vtkImageShiftScale::New();
m_ImageCast->SetOutputScalarTypeToUnsignedShort();
m_ImageCast->ClampOverflowOn();
m_UnitSpacingImageFilter = vtkImageChangeInformation::New();
m_UnitSpacingImageFilter->SetInputConnection(m_ImageCast->GetOutputPort());
m_UnitSpacingImageFilter->SetOutputSpacing( 1.0, 1.0, 1.0 );
m_ImageMaskFilter = vtkImageMask::New();
m_ImageMaskFilter->SetMaskedOutputValue(0xffff);
this->m_Resampler->SetInputConnection( this->m_UnitSpacingImageFilter->GetOutputPort() );
this->m_HiResMapper->SetInputConnection( this->m_UnitSpacingImageFilter->GetOutputPort() );
// m_T2DMapper->SetInput(m_Resampler->GetOutput());
this->CreateDefaultTransferFunctions();
}
vtkProp *mitk::VolumeDataVtkMapper3D::GetVtkProp(mitk::BaseRenderer * /*renderer*/)
{
return m_VolumeLOD;
}
mitk::VolumeDataVtkMapper3D::~VolumeDataVtkMapper3D()
{
m_UnitSpacingImageFilter->Delete();
m_ImageCast->Delete();
// m_T2DMapper->Delete();
m_HiResMapper->Delete();
m_Resampler->Delete();
m_VolumePropertyLow->Delete();
m_VolumePropertyMed->Delete();
m_VolumePropertyHigh->Delete();
m_VolumeLOD->Delete();
m_ClippingPlane->Delete();
m_PlaneWidget->Delete();
// m_Prop3DAssembly->Delete();
m_BoundingBox->Delete();
m_BoundingBoxMapper->Delete();
m_BoundingBoxActor->Delete();
m_ImageMaskFilter->Delete();
m_DefaultColorTransferFunction->Delete();
m_DefaultOpacityTransferFunction->Delete();
m_DefaultGradientTransferFunction->Delete();
if (m_Mask)
{
m_Mask->Delete();
}
}
void mitk::VolumeDataVtkMapper3D::GenerateDataForRenderer( mitk::BaseRenderer *renderer )
{
SetVtkMapperImmediateModeRendering(m_BoundingBoxMapper);
mitk::Image *input = const_cast< mitk::Image * >( this->GetInput() );
if ( !input || !input->IsInitialized() )
return;
vtkRenderWindow* renderWindow = renderer->GetRenderWindow();
bool volumeRenderingEnabled = true;
bool visible = true;
GetDataNode()->GetVisibility(visible, renderer, "visible");
if ( !visible ||
this->GetDataNode() == NULL ||
dynamic_cast<mitk::BoolProperty*>(GetDataNode()->GetProperty("volumerendering",renderer))==NULL ||
dynamic_cast<mitk::BoolProperty*>(GetDataNode()->GetProperty("volumerendering",renderer))->GetValue() == false
)
{
volumeRenderingEnabled = false;
// Check if a bounding box should be displayed around the dataset
// (even if volume rendering is disabled)
bool hasBoundingBox = false;
this->GetDataNode()->GetBoolProperty( "bounding box", hasBoundingBox );
if ( !hasBoundingBox )
{
m_BoundingBoxActor->VisibilityOff();
}
else
{
m_BoundingBoxActor->VisibilityOn();
const BoundingBox::BoundsArrayType &bounds =
input->GetTimeGeometry()->GetBoundsInWorld();
m_BoundingBox->SetBounds(
bounds[0], bounds[1],
bounds[2], bounds[3],
bounds[4], bounds[5] );
ColorProperty *colorProperty;
if ( this->GetDataNode()->GetProperty(
colorProperty, "color" ) )
{
const mitk::Color &color = colorProperty->GetColor();
m_BoundingBoxActor->GetProperty()->SetColor(
color[0], color[1], color[2] );
}
else
{
m_BoundingBoxActor->GetProperty()->SetColor(
1.0, 1.0, 1.0 );
}
}
}
// Don't do anything if VR is disabled
if ( !volumeRenderingEnabled )
{
m_VolumeLOD->VisibilityOff();
return;
}
else
{
mitk::VtkVolumeRenderingProperty* vrp=dynamic_cast<mitk::VtkVolumeRenderingProperty*>(GetDataNode()->GetProperty("volumerendering configuration",renderer));
if(vrp)
{
int renderingValue = vrp->GetValueAsId();
switch(renderingValue)
{
case VTK_VOLUME_RAY_CAST_MIP_FUNCTION:
{
vtkVolumeRayCastMIPFunction* mipFunction = vtkVolumeRayCastMIPFunction::New();
m_HiResMapper->SetVolumeRayCastFunction(mipFunction);
mipFunction->Delete();
MITK_INFO <<"in switch" <<std::endl;
break;
}
case VTK_RAY_CAST_COMPOSITE_FUNCTION:
{
vtkVolumeRayCastCompositeFunction* compositeFunction = vtkVolumeRayCastCompositeFunction::New();
compositeFunction->SetCompositeMethodToClassifyFirst();
m_HiResMapper->SetVolumeRayCastFunction(compositeFunction);
compositeFunction->Delete();
break;
}
default:
MITK_ERROR <<"Warning: invalid volume rendering option. " << std::endl;
}
}
m_VolumeLOD->VisibilityOn();
}
this->SetPreferences();
/*
switch ( mitk::RenderingManager::GetInstance()->GetNextLOD( renderer ) )
{
case 0:
m_VolumeLOD->SetSelectedLODID(m_MedResID); m_LowResID );
break;
default:
case 1:
m_VolumeLOD->SetSelectedLODID( m_HiResID );
break;
}
*/
m_VolumeLOD->SetSelectedLODID( m_HiResID );
assert(input->GetTimeGeometry());
- const Geometry3D* worldgeometry = renderer->GetCurrentWorldGeometry();
+ const BaseGeometry* worldgeometry = renderer->GetCurrentWorldGeometry();
if(worldgeometry==NULL)
{
GetDataNode()->SetProperty("volumerendering",mitk::BoolProperty::New(false));
return;
}
vtkImageData *inputData = input->GetVtkImageData( this->GetTimestep() );
if(inputData==NULL)
return;
m_ImageCast->SetInputData( inputData );
//If mask exists, process mask before resampling.
if (this->m_Mask)
{
this->m_UnitSpacingImageFilter->Update();
this->m_ImageMaskFilter->SetImageInputData(this->m_UnitSpacingImageFilter->GetOutput());
this->m_Resampler->SetInputConnection(this->m_ImageMaskFilter->GetOutputPort());
this->m_HiResMapper->SetInputConnection(this->m_ImageMaskFilter->GetOutputPort());
}
else
{
this->m_Resampler->SetInputConnection(this->m_UnitSpacingImageFilter->GetOutputPort());
this->m_HiResMapper->SetInputConnection(this->m_UnitSpacingImageFilter->GetOutputPort());
}
this->UpdateTransferFunctions( renderer );
vtkRenderWindowInteractor *interactor = renderWindow->GetInteractor();
float frameRate;
if( this->GetDataNode()->GetFloatProperty( "framerate", frameRate ) && frameRate > 0 && frameRate <= 60)
{
interactor->SetDesiredUpdateRate( frameRate );
interactor->SetStillUpdateRate( frameRate );
}
else if( frameRate > 60 )
{
this->GetDataNode()->SetProperty( "framerate",mitk::FloatProperty::New(60));
interactor->SetDesiredUpdateRate( 60 );
interactor->SetStillUpdateRate( 60 );
}
else
{
this->GetDataNode()->SetProperty( "framerate",mitk::FloatProperty::New(0.00001));
interactor->SetDesiredUpdateRate( 0.00001 );
interactor->SetStillUpdateRate( 0.00001 );
}
if ( m_RenderWindowInitialized.find( renderWindow ) == m_RenderWindowInitialized.end() )
{
m_RenderWindowInitialized.insert( renderWindow );
// mitk::RenderingManager::GetInstance()->SetNextLOD( 0, renderer );
mitk::RenderingManager::GetInstance()->SetShading( true, 0 );
mitk::RenderingManager::GetInstance()->SetShading( true, 1 );
//mitk::RenderingManager::GetInstance()->SetShading( true, 2 );
mitk::RenderingManager::GetInstance()->SetShadingValues(
m_VolumePropertyHigh->GetAmbient(),
m_VolumePropertyHigh->GetDiffuse(),
m_VolumePropertyHigh->GetSpecular(),
m_VolumePropertyHigh->GetSpecularPower());
mitk::RenderingManager::GetInstance()->SetClippingPlaneStatus(false);
}
this->SetClippingPlane( interactor );
}
void mitk::VolumeDataVtkMapper3D::CreateDefaultTransferFunctions()
{
m_DefaultOpacityTransferFunction = vtkPiecewiseFunction::New();
m_DefaultOpacityTransferFunction->AddPoint( 0.0, 0.0 );
m_DefaultOpacityTransferFunction->AddPoint( 255.0, 0.8 );
m_DefaultOpacityTransferFunction->ClampingOn();
m_DefaultGradientTransferFunction = vtkPiecewiseFunction::New();
m_DefaultGradientTransferFunction->AddPoint( 0.0, 0.0 );
m_DefaultGradientTransferFunction->AddPoint( 255.0, 0.8 );
m_DefaultGradientTransferFunction->ClampingOn();
m_DefaultColorTransferFunction = vtkColorTransferFunction::New();
m_DefaultColorTransferFunction->AddRGBPoint( 0.0, 0.0, 0.0, 0.0 );
m_DefaultColorTransferFunction->AddRGBPoint( 127.5, 1, 1, 0.0 );
m_DefaultColorTransferFunction->AddRGBPoint( 255.0, 0.8, 0.2, 0 );
m_DefaultColorTransferFunction->ClampingOn();
}
void mitk::VolumeDataVtkMapper3D::UpdateTransferFunctions( mitk::BaseRenderer *renderer )
{
vtkSmartPointer<vtkPiecewiseFunction> opacityTransferFunction;
vtkSmartPointer<vtkPiecewiseFunction> gradientTransferFunction;
vtkSmartPointer<vtkColorTransferFunction> colorTransferFunction;
mitk::LookupTableProperty::Pointer lookupTableProp;
lookupTableProp = dynamic_cast<mitk::LookupTableProperty*>(this->GetDataNode()->GetProperty("LookupTable"));
mitk::TransferFunctionProperty::Pointer transferFunctionProp = dynamic_cast<mitk::TransferFunctionProperty*>(this->GetDataNode()->GetProperty("TransferFunction"));
if ( transferFunctionProp.IsNotNull() ) {
opacityTransferFunction = transferFunctionProp->GetValue()->GetScalarOpacityFunction();
gradientTransferFunction = transferFunctionProp->GetValue()->GetGradientOpacityFunction();
colorTransferFunction = transferFunctionProp->GetValue()->GetColorTransferFunction();
}
else if (lookupTableProp.IsNotNull() )
{
opacityTransferFunction = lookupTableProp->GetLookupTable()->CreateOpacityTransferFunction();
opacityTransferFunction->ClampingOn();
gradientTransferFunction = lookupTableProp->GetLookupTable()->CreateGradientTransferFunction();
gradientTransferFunction->ClampingOn();
colorTransferFunction = lookupTableProp->GetLookupTable()->CreateColorTransferFunction();
colorTransferFunction->ClampingOn();
}
else
{
opacityTransferFunction = m_DefaultOpacityTransferFunction;
gradientTransferFunction = m_DefaultGradientTransferFunction;
colorTransferFunction = m_DefaultColorTransferFunction;
float rgb[3]={1.0f,1.0f,1.0f};
// check for color prop and use it for rendering if it exists
if(GetDataNode()->GetColor(rgb, renderer, "color"))
{
colorTransferFunction->AddRGBPoint( 0.0, 0.0, 0.0, 0.0 );
colorTransferFunction->AddRGBPoint( 127.5, rgb[0], rgb[1], rgb[2] );
colorTransferFunction->AddRGBPoint( 255.0, rgb[0], rgb[1], rgb[2] );
}
}
if (this->m_Mask)
{
opacityTransferFunction->AddPoint(0xffff, 0.0);
}
m_VolumePropertyLow->SetColor( colorTransferFunction );
m_VolumePropertyLow->SetScalarOpacity( opacityTransferFunction );
m_VolumePropertyLow->SetGradientOpacity( gradientTransferFunction );
m_VolumePropertyLow->SetInterpolationTypeToNearest();
m_VolumePropertyMed->SetColor( colorTransferFunction );
m_VolumePropertyMed->SetScalarOpacity( opacityTransferFunction );
m_VolumePropertyMed->SetGradientOpacity( gradientTransferFunction );
m_VolumePropertyMed->SetInterpolationTypeToNearest();
m_VolumePropertyHigh->SetColor( colorTransferFunction );
m_VolumePropertyHigh->SetScalarOpacity( opacityTransferFunction );
m_VolumePropertyHigh->SetGradientOpacity( gradientTransferFunction );
m_VolumePropertyHigh->SetInterpolationTypeToLinear();
}
/* Shading enabled / disabled */
void mitk::VolumeDataVtkMapper3D::SetPreferences()
{
//LOD 0
/*if(mitk::RenderingManager::GetInstance()->GetShading(0))
{
m_VolumePropertyLow->ShadeOn();
m_VolumePropertyLow->SetAmbient(mitk::RenderingManager::GetInstance()->GetShadingValues()[0]);
m_VolumePropertyLow->SetDiffuse(mitk::RenderingManager::GetInstance()->GetShadingValues()[1]);
m_VolumePropertyLow->SetSpecular(mitk::RenderingManager::GetInstance()->GetShadingValues()[2]);
m_VolumePropertyLow->SetSpecularPower(mitk::RenderingManager::GetInstance()->GetShadingValues()[3]);
}
else*/
{
m_VolumePropertyLow->ShadeOff();
}
//LOD 1
/*if(mitk::RenderingManager::GetInstance()->GetShading(1))
{
m_VolumePropertyMed->ShadeOn();
m_VolumePropertyMed->SetAmbient(mitk::RenderingManager::GetInstance()->GetShadingValues()[0]);
m_VolumePropertyMed->SetDiffuse(mitk::RenderingManager::GetInstance()->GetShadingValues()[1]);
m_VolumePropertyMed->SetSpecular(mitk::RenderingManager::GetInstance()->GetShadingValues()[2]);
m_VolumePropertyMed->SetSpecularPower(mitk::RenderingManager::GetInstance()->GetShadingValues()[3]);
}
else*/
{
m_VolumePropertyMed->ShadeOff();
}
//LOD 2
/*
if(mitk::RenderingManager::GetInstance()->GetShading(2))
{
m_VolumePropertyHigh->ShadeOn();
//Shading Properties
m_VolumePropertyHigh->SetAmbient(mitk::RenderingManager::GetInstance()->GetShadingValues()[0]);
m_VolumePropertyHigh->SetDiffuse(mitk::RenderingManager::GetInstance()->GetShadingValues()[1]);
m_VolumePropertyHigh->SetSpecular(mitk::RenderingManager::GetInstance()->GetShadingValues()[2]);
m_VolumePropertyHigh->SetSpecularPower(mitk::RenderingManager::GetInstance()->GetShadingValues()[3]);
}
else
{
m_VolumePropertyHigh->ShadeOff();
}
*/
}
/* Adds A Clipping Plane to the Mapper */
void mitk::VolumeDataVtkMapper3D::SetClippingPlane(vtkRenderWindowInteractor* interactor)
{
if(mitk::RenderingManager::GetInstance()->GetClippingPlaneStatus()) //if clipping plane is enabled
{
if(!m_PlaneSet)
{
m_PlaneWidget->SetInteractor(interactor);
m_PlaneWidget->SetPlaceFactor(1.0);
m_PlaneWidget->SetInputData(m_UnitSpacingImageFilter->GetOutput());
m_PlaneWidget->OutlineTranslationOff(); //disables scaling of the bounding box
m_PlaneWidget->ScaleEnabledOff(); //disables scaling of the bounding box
m_PlaneWidget->DrawPlaneOff(); //clipping plane is transparent
mitk::Image* input = const_cast<mitk::Image *>(this->GetInput());
/*places the widget within the specified bounds*/
m_PlaneWidget->PlaceWidget(
input->GetGeometry()->GetOrigin()[0],(input->GetGeometry()->GetOrigin()[0])+(input->GetDimension(0))*(input->GetVtkImageData()->GetSpacing()[0]), input->GetGeometry()->GetOrigin()[1],(input->GetGeometry()->GetOrigin()[1])+(input->GetDimension(1))*(input->GetVtkImageData()->GetSpacing()[1]), input->GetGeometry()->GetOrigin()[2],(input->GetGeometry()->GetOrigin()[2])+(input->GetDimension(2))*(input->GetVtkImageData()->GetSpacing()[2]));
// m_T2DMapper->AddClippingPlane(m_ClippingPlane);
m_HiResMapper->AddClippingPlane(m_ClippingPlane);
}
m_PlaneWidget->GetPlane(m_ClippingPlane);
m_PlaneSet = true;
}
else //if clippingplane is disabled
{
if(m_PlaneSet) //if plane exists
{
DelClippingPlane();
}
}
}
/* Removes the clipping plane */
void mitk::VolumeDataVtkMapper3D::DelClippingPlane()
{
// m_T2DMapper->RemoveAllClippingPlanes();
m_HiResMapper->RemoveAllClippingPlanes();
m_PlaneSet = false;
}
void mitk::VolumeDataVtkMapper3D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite)
{
node->AddProperty( "volumerendering", mitk::BoolProperty::New( false ), renderer, overwrite );
node->AddProperty( "volumerendering configuration", mitk::VtkVolumeRenderingProperty::New( 1 ), renderer, overwrite );
node->AddProperty( "binary", mitk::BoolProperty::New( false ), renderer, overwrite );
mitk::Image::Pointer image = dynamic_cast<mitk::Image*>(node->GetData());
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 );
levWinProp->SetLevelWindow( levelwindow );
node->SetProperty( "levelwindow", levWinProp, renderer );
}
//This mapper used to set a default lut "LookupTable" for images. However, this will
//overwrite the default lut of the 2D image mapper. Thus, this property here is renamed.
/*
if((overwrite) || (node->GetProperty("Volume.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( "Volume.LookupTable", mitkLutProp );
}*/
if((overwrite) || (node->GetProperty("TransferFunction", renderer)==NULL))
{
// add a default transfer function
mitk::TransferFunction::Pointer tf = mitk::TransferFunction::New();
mitk::TransferFunctionInitializer::Pointer tfInit = mitk::TransferFunctionInitializer::New(tf);
tfInit->SetTransferFunctionMode(0);
node->SetProperty ( "TransferFunction", mitk::TransferFunctionProperty::New ( tf.GetPointer() ) );
}
}
Superclass::SetDefaultProperties(node, renderer, overwrite);
}
bool mitk::VolumeDataVtkMapper3D::IsLODEnabled( mitk::BaseRenderer * /*renderer*/ ) const
{
return false;
// Volume mapper is LOD enabled if volumerendering is enabled
/*
return
dynamic_cast<mitk::BoolProperty*>(GetDataNode()->GetProperty("volumerendering",renderer)) != NULL &&
dynamic_cast<mitk::BoolProperty*>(GetDataNode()->GetProperty("volumerendering",renderer))->GetValue() == true;
*/
}
void mitk::VolumeDataVtkMapper3D::EnableMask()
{
if (!this->m_Mask)
{
const Image *orig_image = this->GetInput();
unsigned int *dimensions = orig_image->GetDimensions();
this->m_Mask = vtkImageData::New();
this->m_Mask->SetDimensions(dimensions[0], dimensions[1], dimensions[2]);
this->m_Mask->AllocateScalars(VTK_UNSIGNED_CHAR,1);
unsigned char *mask_data = static_cast<unsigned char*>(this->m_Mask->GetScalarPointer());
unsigned int size = dimensions[0] * dimensions[1] * dimensions[2];
for (unsigned int i = 0u; i < size; ++i)
{
*mask_data++ = 1u;
}
this->m_ImageMaskFilter->SetMaskInputData(this->m_Mask);
this->m_ImageMaskFilter->Modified();
}
}
void mitk::VolumeDataVtkMapper3D::DisableMask()
{
if (this->m_Mask)
{
this->m_Mask->Delete();
this->m_Mask = 0;
}
}
mitk::Image::Pointer mitk::VolumeDataVtkMapper3D::GetMask()
{
if (this->m_Mask)
{
Image::Pointer mask = Image::New();
mask->Initialize(this->m_Mask);
mask->SetImportVolume(this->m_Mask->GetScalarPointer(), 0, 0, Image::ReferenceMemory);
mask->SetGeometry(this->GetInput()->GetGeometry());
return mask;
}
return 0;
}
void mitk::VolumeDataVtkMapper3D::UpdateMask()
{
if (this->m_Mask)
{
this->m_ImageMaskFilter->Modified();
}
}
bool mitk::VolumeDataVtkMapper3D::SetMask(const mitk::Image* mask)
{
if (this->m_Mask)
{
if ( (mask->GetPixelType().GetComponentType() == itk::ImageIOBase::UCHAR)
&&(mask->GetPixelType().GetPixelType() == itk::ImageIOBase::SCALAR ))
{
Image *img = const_cast<Image*>(mask);
this->m_Mask->DeepCopy(img->GetVtkImageData());
this->m_ImageMaskFilter->Modified();
return true;
}
}
return false;
}
diff --git a/Core/Code/Rendering/mitkVtkPropRenderer.cpp b/Core/Code/Rendering/mitkVtkPropRenderer.cpp
index 2735f23325..7e453ff7d5 100644
--- a/Core/Code/Rendering/mitkVtkPropRenderer.cpp
+++ b/Core/Code/Rendering/mitkVtkPropRenderer.cpp
@@ -1,975 +1,975 @@
/*===================================================================
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 "mitkVtkPropRenderer.h"
// MAPPERS
#include "mitkMapper.h"
#include "mitkImageVtkMapper2D.h"
#include "mitkVtkMapper.h"
#include "mitkGLMapper.h"
-#include "mitkGeometry2DDataVtkMapper3D.h"
+#include "mitkPlaneGeometryDataVtkMapper3D.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"
#include "mitkVtkInteractorStyle.h"
// VTK
#include <vtkRenderer.h>
#include <vtkRendererCollection.h>
#include <vtkLight.h>
#include <vtkLightKit.h>
#include <vtkRenderWindow.h>
#include <vtkLinearTransform.h>
#include <vtkCamera.h>
#include <vtkWorldPointPicker.h>
#include <vtkPointPicker.h>
#include <vtkCellPicker.h>
#include <vtkTextActor.h>
#include <vtkTextProperty.h>
#include <vtkProp.h>
#include <vtkAssemblyPath.h>
#include <vtkAssemblyNode.h>
#include <vtkMapper.h>
#include <vtkSmartPointer.h>
#include <vtkTransform.h>
#include <vtkInteractorStyleTrackballCamera.h>
mitk::VtkPropRenderer::VtkPropRenderer( const char* name, vtkRenderWindow * renWin, mitk::RenderingManager* rm, mitk::BaseRenderer::RenderingMode::Type renderingMode )
: BaseRenderer(name,renWin, rm, renderingMode ),
m_VtkMapperPresent(false),
m_CameraInitializedForMapperID(0)
{
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);
+ mitk::PlaneGeometryDataVtkMapper3D::Pointer geometryMapper = mitk::PlaneGeometryDataVtkMapper3D::New();
+ m_CurrentWorldPlaneGeometryMapper = geometryMapper;
+ m_CurrentWorldPlaneGeometryNode->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<mitk::Geometry2DDataVtkMapper3D*>(m_CurrentWorldGeometry2DMapper.GetPointer())->SetDataStorageForTexture( m_DataStorage.GetPointer() );
+ static_cast<mitk::PlaneGeometryDataVtkMapper3D*>(m_CurrentWorldPlaneGeometryMapper.GetPointer())->SetDataStorageForTexture( m_DataStorage.GetPointer() );
// 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::TimeGeometry::Pointer geometry = m_DataStorage->ComputeVisibleBoundingGeometry3D( NULL, "includeInBoundingBox" );
if ( geometry.IsNull() )
return false;
this->SetWorldTimeGeometry(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?
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;
VtkMapper* vtkmapper = dynamic_cast<VtkMapper*>(mapper);
if(vtkmapper)
{
//sthVtkBased = true;
if(!lastVtkBased)
{
Disable2DOpenGL();
lastVtkBased = true;
}
}
else if(lastVtkBased)
{
Enable2DOpenGL();
lastVtkBased = false;
}
mapper->MitkRender(this, type);
}
this->UpdateOverlays();
if (lastVtkBased == false)
Disable2DOpenGL();
// Render text
if (type == VtkPropRenderer::Overlay)
{
if (m_TextCollection.size() > 0)
{
m_TextRenderer->SetViewport( this->GetVtkRenderer()->GetViewport() );
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() ) {
Update();
}
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; i<m_TextCollection.size(); i++ )
{
m_TextCollection[i]->Delete();
}
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;
bool visible = true;
node->GetVisibility(visible, this, "visible");
// The information about LOD-enabled mappers is required by RenderingManager
if ( mapper->IsLODEnabled( this ) && visible )
{
++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();
glLoadIdentity();
// Set up the orthographic projection
const DisplayGeometry* displayGeometry = this->GetDisplayGeometry();
float displayGeometryWidth = displayGeometry->GetSizeInDisplayUnits()[0];
float displayGeometryHeight = displayGeometry->GetSizeInDisplayUnits()[1];
float viewportWidth = iViewport[2];
float viewportHeight = iViewport[3];
/*
The following makes OpenGL mappers draw into the same viewport
that is used by VTK when someone calls vtkRenderer::SetViewport().
The parameters of glOrtho describe what "input" coordinates
(display coordinates generated by the OpenGL mappers) are transformed
into the region defined by the viewport. The call has to consider
that the scene is fit vertically and centered horizontally.
Problem: this is a crude first step towards rendering into viewports.
- mitkViewportRenderingTest demonstrates the non-interactive rendering
that is now possible
- interactors that measure mouse movement in pixels will
probably run into problems with display-to-world transformation
A proper solution should probably modify the DisplayGeometry to
correctly describe the viewport.
*/
// iViewport is (x,y,width,height)
// glOrtho expects (left,right,bottom,top,znear,zfar)
glOrtho( 0
- 0.5 * (viewportWidth/viewportHeight-1.0)*displayGeometryHeight
+ 0.5 * (displayGeometryWidth - displayGeometryHeight)
,
displayGeometryWidth
+ 0.5 * (viewportWidth/viewportHeight-1.0)*displayGeometryHeight
- 0.5 * (displayGeometryWidth - displayGeometryHeight)
,
0, displayGeometryHeight,
-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 );
// disable the texturing here so crosshair is painted in the correct colors
// vtk will reenable texturing every time it is needed
glDisable( GL_TEXTURE_1D );
glDisable( GL_TEXTURE_2D );
glLineWidth(1.0);
}
/*!
\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();
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())
{
GLMapper* glmapper=dynamic_cast<GLMapper*>(mapper.GetPointer());
if(GetDisplayGeometry()->IsValid())
{
if(glmapper != NULL)
{
glmapper->Update(this);
m_VtkMapperPresent=false;
}
else
{
VtkMapper* vtkmapper=dynamic_cast<VtkMapper*>(mapper.GetPointer());
if(vtkmapper != NULL)
{
vtkmapper->Update(this);
vtkmapper->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();
}
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
/*
vtkRenderer* pickingRenderer = vtkRenderer::New();
pickingRenderer->SetActiveCamera( );
DataStorage* dataStorage = m_DataStorage;
TNodePredicateDataType<Surface> 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<VtkMapper3D*>( currentNode->GetMapper( BaseRenderer::Standard3D ) );
if ( baseVtkMapper3D )
{
vtkActor* actor = dynamic_cast<vtkActor*>( 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;
}
case(CellPicking) :
{
m_CellPicker->Pick(displayPoint[0], displayPoint[1], 0, m_VtkRenderer);
vtk2itk(m_CellPicker->GetPickPosition(), worldPoint);
break;
}
}
}
else
{
Superclass::PickWorldPoint(displayPoint, worldPoint);
}
}
mitk::DataNode *
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 )
{
DataNode *node = it->Value();
if ( node == NULL )
continue;
bool pickable = false;
node->GetBoolProperty( "pickable", pickable );
if ( !pickable )
continue;
VtkMapper *mapper = dynamic_cast < VtkMapper * > ( 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)
{
DataNode::Pointer node = it->Value();
if ( node.IsNull() )
continue;
mitk::Mapper * mapper = node->GetMapper( m_MapperID );
if ( mapper == NULL)
continue;
mitk::VtkMapper * vtkmapper = dynamic_cast< VtkMapper * >(mapper);
if(vtkmapper){
//if vtk-based, then ...
if ( vtkmapper->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, float opacity)
{
if(!text.empty())
{
Point2D p;
p[0] = posX;
p[1] = posY;
p = TransformOpenGLPointToViewport(p);
vtkTextActor* textActor = vtkTextActor::New();
textActor->SetPosition(p[0], p[1]);
textActor->SetInput(text.c_str());
textActor->SetTextScaleModeToNone();
textActor->GetTextProperty()->SetColor(color1, color2, color3); //TODO: Read color from node property
textActor->GetTextProperty()->SetOpacity( opacity );
int text_id = m_TextCollection.size();
m_TextCollection.insert(TextMapType::value_type(text_id,textActor));
return text_id;
}
else
{
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)
{
VtkMapper* vtkmapper = dynamic_cast<VtkMapper*>( 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 * mapper = node->GetMapper(m_MapperID);
if (mapper)
{
VtkMapper* vtkmapper = dynamic_cast<VtkMapper*>( mapper );
if(vtkmapper)
vtkmapper->ReleaseGraphicsResources(this);
}
}
}
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();
}
//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();
}
//MITK_INFO << "GLOBAL 3D DECREASE " << glWorkAroundGlobalCount << "\n";
}
}
}
//### Contains all methods which are neceassry before each VTK Render() call
void mitk::VtkPropRenderer::PrepareRender()
{
if ( this->GetMapperID() != m_CameraInitializedForMapperID )
{
Initialize2DvtkCamera(); //Set parallel projection etc.
}
AdjustCameraToScene(); //Prepare camera for 2D render windows
}
bool mitk::VtkPropRenderer::Initialize2DvtkCamera()
{
if ( this->GetMapperID() == Standard3D )
{
//activate parallel projection for 2D
this->GetVtkRenderer()->GetActiveCamera()->SetParallelProjection(false);
this->GetRenderWindow()->GetInteractor()->SetInteractorStyle( vtkInteractorStyleTrackballCamera::New() );
m_CameraInitializedForMapperID = Standard3D;
}
else 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();
this->GetRenderWindow()->GetInteractor()->SetInteractorStyle( mitkVtkInteractorStyle::New() );
m_CameraInitializedForMapperID = Standard2D;
}
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 objectHeightInMM = this->GetCurrentWorldPlaneGeometry()->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<vtkCamera> 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() );
+ const PlaneGeometry *planeGeometry = dynamic_cast< const PlaneGeometry * >( this->GetCurrentWorldPlaneGeometry() );
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<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
vtkSmartPointer<vtkMatrix4x4> matrix = vtkSmartPointer<vtkMatrix4x4>::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);
}
}
}
mitk::Point2D mitk::VtkPropRenderer::TransformOpenGLPointToViewport( mitk::Point2D point )
{
GLint iViewport[4];
// Get a copy of the viewport
glGetIntegerv( GL_VIEWPORT, iViewport );
const mitk::DisplayGeometry* displayGeometry = this->GetDisplayGeometry();
float displayGeometryWidth = displayGeometry->GetSizeInDisplayUnits()[0];
float displayGeometryHeight = displayGeometry->GetSizeInDisplayUnits()[1];
float viewportWidth = iViewport[2];
float viewportHeight = iViewport[3]; // seemingly right
float zoom = viewportHeight / displayGeometryHeight;
// see glOrtho call above for more explanation
point[0] +=
0.5 * (viewportWidth/viewportHeight-1.0)*displayGeometryHeight
- 0.5 * (displayGeometryWidth - displayGeometryHeight)
;
point[0] *= zoom;
point[1] *= zoom;
return point;
}
\ No newline at end of file
diff --git a/Core/Code/Rendering/mitkVtkPropRenderer.h b/Core/Code/Rendering/mitkVtkPropRenderer.h
index 09d11a3bd3..31024e0f8c 100644
--- a/Core/Code/Rendering/mitkVtkPropRenderer.h
+++ b/Core/Code/Rendering/mitkVtkPropRenderer.h
@@ -1,256 +1,256 @@
/*===================================================================
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 MITKVtkPropRenderer_H_HEADER_INCLUDED_C1C29F6D
#define MITKVtkPropRenderer_H_HEADER_INCLUDED_C1C29F6D
#include <MitkCoreExports.h>
#include "mitkBaseRenderer.h"
#include "mitkDataStorage.h"
#include "mitkRenderingManager.h"
#include <itkCommand.h>
#include <map>
#include <utility>
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* );
mitkNewMacro4Param(VtkPropRenderer, const char*, vtkRenderWindow *, mitk::RenderingManager*, mitk::BaseRenderer::RenderingMode::Type );
typedef std::map<int,Mapper*> 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, CellPicking};
/** \brief Set the picking mode.
This method is used to set the picking mode for 3D object picking. The user can select one of
the three options WorldPointPicking, PointPicking and CellPicking. The first option uses the zBuffer
from graphics rendering, the second uses the 3D points from the closest surface mesh, and the third
option uses the cells of that mesh. The last option is the slowest, the first one the fastest.
However, the first option cannot use transparent data object and the tolerance of the picked position
to the selected point should be considered. PointPicking also need a tolerance around the picking
position to select the closest point in the mesh. The CellPicker performs very well, if the
foreground surface part (i.e. the surfacepart that is closest to the scene's cameras) needs to be
picked. */
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, float opacity = 1.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, mitk::BaseRenderer::RenderingMode::Type renderingMode = mitk::BaseRenderer::RenderingMode::Standard );
virtual ~VtkPropRenderer();
virtual void Update();
/**
\brief Convert display geometry coordinates to VTK coordinates.
For use within WriteSimpleText: the input is display geometry coordinates
but the text actor needs positions that fit in a specified viewport.
Conversion is done in this method.
*/
mitk::Point2D TransformOpenGLPointToViewport( mitk::Point2D point );
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,
* double 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;
MapperSlotId m_CameraInitializedForMapperID;
// 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;
+ itk::SmartPointer< mitk::Mapper > m_CurrentWorldPlaneGeometryMapper;
vtkLightKit* m_LightKit;
// sorted list of mappers
MappersMapType m_MappersMap;
// rendering of text
vtkRenderer * m_TextRenderer;
typedef std::map<unsigned int,vtkTextActor*> 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/Testing/DICOMTesting/mitkTestDICOMLoading.cpp b/Core/Code/Testing/DICOMTesting/mitkTestDICOMLoading.cpp
index 35fe8fd9a0..89e7718013 100644
--- a/Core/Code/Testing/DICOMTesting/mitkTestDICOMLoading.cpp
+++ b/Core/Code/Testing/DICOMTesting/mitkTestDICOMLoading.cpp
@@ -1,449 +1,444 @@
/*===================================================================
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.
===================================================================*/
//#define MBILOG_ENABLE_DEBUG
#include <limits>
#include "mitkTestDICOMLoading.h"
#include "mitkImage.h"
#include <stack>
mitk::TestDICOMLoading::TestDICOMLoading()
:m_PreviousCLocale(NULL)
{
}
void mitk::TestDICOMLoading::SetDefaultLocale()
{
// remember old locale only once
if (m_PreviousCLocale == NULL)
{
m_PreviousCLocale = setlocale(LC_NUMERIC, NULL);
// set to "C"
setlocale(LC_NUMERIC, "C");
m_PreviousCppLocale = std::cin.getloc();
std::locale l( "C" );
std::cin.imbue(l);
std::cout.imbue(l);
}
}
void mitk::TestDICOMLoading::ResetUserLocale()
{
if (m_PreviousCLocale)
{
setlocale(LC_NUMERIC, m_PreviousCLocale);
std::cin.imbue(m_PreviousCppLocale);
std::cout.imbue(m_PreviousCppLocale);
m_PreviousCLocale = NULL;
}
}
mitk::TestDICOMLoading::ImageList mitk::TestDICOMLoading::LoadFiles( const StringContainer& files, itk::SmartPointer<Image> preLoadedVolume )
{
for (StringContainer::const_iterator iter = files.begin();
iter != files.end();
++iter)
{
MITK_DEBUG << "File " << *iter;
}
ImageList result;
DicomSeriesReader::FileNamesGrouping seriesInFiles = DicomSeriesReader::GetSeries( files, true );
// TODO sort series UIDs, implementation of map iterator might differ on different platforms (or verify this is a standard topic??)
for (DicomSeriesReader::FileNamesGrouping::const_iterator seriesIter = seriesInFiles.begin();
seriesIter != seriesInFiles.end();
++seriesIter)
{
StringContainer files = seriesIter->second.GetFilenames();
DataNode::Pointer node = DicomSeriesReader::LoadDicomSeries( files, true, true, true, 0, preLoadedVolume ); // true, true, true ist just a copy of the default values
if (node.IsNotNull())
{
Image::Pointer image = dynamic_cast<mitk::Image*>( node->GetData() );
result.push_back( image );
}
else
{
}
}
return result;
}
std::string
mitk::TestDICOMLoading::ComponentTypeToString(int type)
{
if (type == itk::ImageIOBase::UCHAR)
return "UCHAR";
else if (type == itk::ImageIOBase::CHAR)
return "CHAR";
else if (type == itk::ImageIOBase::USHORT)
return "USHORT";
else if (type == itk::ImageIOBase::SHORT)
return "SHORT";
else if (type == itk::ImageIOBase::UINT)
return "UINT";
else if (type == itk::ImageIOBase::INT)
return "INT";
else if (type == itk::ImageIOBase::ULONG)
return "ULONG";
else if (type == itk::ImageIOBase::LONG)
return "LONG";
else if (type == itk::ImageIOBase::FLOAT)
return "FLOAT";
else if (type == itk::ImageIOBase::DOUBLE)
return "DOUBLE";
else
return "UNKNOWN";
}
// add a line to stringstream result (see DumpImageInformation
#define DumpLine(field, data) DumpILine(0, field, data)
// add an indented(!) line to stringstream result (see DumpImageInformation
#define DumpILine(indent, field, data) \
{ \
std::string DumpLine_INDENT; DumpLine_INDENT.resize(indent, ' ' ); \
result << DumpLine_INDENT << field << ": " << data << "\n"; \
}
std::string
mitk::TestDICOMLoading::DumpImageInformation( const Image* image )
{
-
std::stringstream result;
if (image == NULL) return result.str();
SetDefaultLocale();
// basic image data
DumpLine( "Pixeltype", ComponentTypeToString(image->GetPixelType().GetComponentType()) );
DumpLine( "BitsPerPixel", image->GetPixelType().GetBpe() );
DumpLine( "Dimension", image->GetDimension() );
result << "Dimensions: ";
for (unsigned int dim = 0; dim < image->GetDimension(); ++dim)
result << image->GetDimension(dim) << " ";
result << "\n";
// geometry data
result << "Geometry: \n";
- Geometry3D* geometry = image->GetGeometry();
+ BaseGeometry* geometry = image->GetGeometry();
if (geometry)
{
AffineTransform3D* transform = geometry->GetIndexToWorldTransform();
if (transform)
{
result << " " << "Matrix: ";
const AffineTransform3D::MatrixType& matrix = transform->GetMatrix();
for (unsigned int i = 0; i < 3; ++i)
for (unsigned int j = 0; j < 3; ++j)
result << matrix[i][j] << " ";
result << "\n";
result << " " << "Offset: ";
const AffineTransform3D::OutputVectorType& offset = transform->GetOffset();
for (unsigned int i = 0; i < 3; ++i)
result << offset[i] << " ";
result << "\n";
result << " " << "Center: ";
const AffineTransform3D::InputPointType& center = transform->GetCenter();
for (unsigned int i = 0; i < 3; ++i)
result << center[i] << " ";
result << "\n";
result << " " << "Translation: ";
const AffineTransform3D::OutputVectorType& translation = transform->GetTranslation();
for (unsigned int i = 0; i < 3; ++i)
result << translation[i] << " ";
result << "\n";
result << " " << "Scale: ";
const double* scale = transform->GetScale();
for (unsigned int i = 0; i < 3; ++i)
result << scale[i] << " ";
result << "\n";
result << " " << "Origin: ";
const Point3D& origin = geometry->GetOrigin();
for (unsigned int i = 0; i < 3; ++i)
result << origin[i] << " ";
result << "\n";
result << " " << "Spacing: ";
const Vector3D& spacing = geometry->GetSpacing();
for (unsigned int i = 0; i < 3; ++i)
result << spacing[i] << " ";
result << "\n";
result << " " << "TimeBounds: ";
- const TimeBounds timeBounds = geometry->GetTimeBounds();
+ const TimeBounds timeBounds = image->GetTimeGeometry()->GetTimeBounds(0);
for (unsigned int i = 0; i < 2; ++i)
result << timeBounds[i] << " ";
result << "\n";
-
-
}
}
ResetUserLocale();
return result.str();
}
std::string
mitk::TestDICOMLoading::trim(const std::string& pString,
const std::string& pWhitespace)
{
const size_t beginStr = pString.find_first_not_of(pWhitespace);
if (beginStr == std::string::npos)
{
// no content
return "";
}
const size_t endStr = pString.find_last_not_of(pWhitespace);
const size_t range = endStr - beginStr + 1;
return pString.substr(beginStr, range);
}
std::string
mitk::TestDICOMLoading::reduce(const std::string& pString,
const std::string& pFill,
const std::string& pWhitespace)
{
// trim first
std::string result(trim(pString, pWhitespace));
// replace sub ranges
size_t beginSpace = result.find_first_of(pWhitespace);
while (beginSpace != std::string::npos)
{
const size_t endSpace =
result.find_first_not_of(pWhitespace, beginSpace);
const size_t range = endSpace - beginSpace;
result.replace(beginSpace, range, pFill);
const size_t newStart = beginSpace + pFill.length();
beginSpace = result.find_first_of(pWhitespace, newStart);
}
return result;
}
bool
mitk::TestDICOMLoading::CompareSpacedValueFields( const std::string& reference,
const std::string& test,
double /*eps*/ )
{
-
bool result(true);
// tokenize string, compare each token, if possible by float comparison
std::stringstream referenceStream(reduce(reference));
std::stringstream testStream(reduce(test));
std::string refToken;
std::string testToken;
while ( std::getline( referenceStream, refToken, ' ' ) &&
std::getline ( testStream, testToken, ' ' ) )
{
float refNumber;
float testNumber;
if ( this->StringToNumber(refToken, refNumber) )
{
if ( this->StringToNumber(testToken, testNumber) )
{
// print-out compared tokens if DEBUG output allowed
MITK_DEBUG << "Reference Token '" << refToken << "'" << " value " << refNumber
<< ", test Token '" << testToken << "'" << " value " << testNumber;
bool old_result = result;
result &= ( fabs(refNumber - testNumber) < 0.0001 /*mitk::eps*/ );
// log the token/number which causes the test to fail
if( old_result != result)
{
MITK_ERROR << std::setprecision(16) << "Reference Token '" << refToken << "'" << " value " << refNumber
<< ", test Token '" << testToken << "'" << " value " << testNumber;
MITK_ERROR << "[FALSE] - difference: " << std::setprecision(16) << fabs(refNumber - testNumber) << " EPS: " << 0.0001;// mitk::eps;
}
}
else
{
MITK_ERROR << refNumber << " cannot be compared to '" << testToken << "'";
}
}
else
{
MITK_DEBUG << "Token '" << refToken << "'" << " handled as string";
result &= refToken == testToken;
}
}
if ( std::getline( referenceStream, refToken, ' ' ) )
{
MITK_ERROR << "Reference string still had values when test string was already parsed: ref '" << reference << "', test '" << test << "'";
result = false;
}
else if ( std::getline( testStream, testToken, ' ' ) )
{
MITK_ERROR << "Test string still had values when reference string was already parsed: ref '" << reference << "', test '" << test << "'";
result = false;
}
return result;
}
bool
mitk::TestDICOMLoading::CompareImageInformationDumps( const std::string& referenceDump,
const std::string& testDump )
{
KeyValueMap reference = ParseDump(referenceDump);
KeyValueMap test = ParseDump(testDump);
bool testResult(true);
// verify all expected values
for (KeyValueMap::const_iterator refIter = reference.begin();
refIter != reference.end();
++refIter)
{
const std::string& refKey = refIter->first;
const std::string& refValue = refIter->second;
if ( test.find(refKey) != test.end() )
{
const std::string& testValue = test[refKey];
bool thisTestResult = CompareSpacedValueFields( refValue, testValue );
testResult &= thisTestResult;
MITK_DEBUG << refKey << ": '" << refValue << "' == '" << testValue << "' ? " << (thisTestResult?"YES":"NO");
}
else
{
MITK_ERROR << "Reference dump contains a key'" << refKey << "' (value '" << refValue << "')." ;
MITK_ERROR << "This key is expected to be generated for tests (but was not). Most probably you need to update your test data.";
return false;
}
}
// now check test dump does not contain any additional keys
for (KeyValueMap::const_iterator testIter = test.begin();
testIter != test.end();
++testIter)
{
const std::string& key = testIter->first;
const std::string& value = testIter->second;
if ( reference.find(key) == reference.end() )
{
MITK_ERROR << "Test dump contains an unexpected key'" << key << "' (value '" << value << "')." ;
MITK_ERROR << "This key is not expected. Most probably you need to update your test data.";
return false;
}
}
return testResult;
}
mitk::TestDICOMLoading::KeyValueMap
mitk::TestDICOMLoading::ParseDump( const std::string& dump )
{
KeyValueMap parsedResult;
std::string shredder(dump);
std::stack<std::string> surroundingKeys;
std::stack<std::string::size_type> expectedIndents;
expectedIndents.push(0);
while (true)
{
std::string::size_type newLinePos = shredder.find( '\n' );
if (newLinePos == std::string::npos || newLinePos == 0) break;
std::string line = shredder.substr( 0, newLinePos );
shredder = shredder.erase( 0, newLinePos+1 );
std::string::size_type keyPosition = line.find_first_not_of( ' ' );
std::string::size_type colonPosition = line.find( ':' );
std::string key = line.substr(keyPosition, colonPosition - keyPosition);
std::string::size_type firstSpacePosition = key.find_first_of(" ");
if (firstSpacePosition != std::string::npos)
{
key.erase(firstSpacePosition);
}
if ( keyPosition > expectedIndents.top() )
{
// more indent than before
expectedIndents.push(keyPosition);
}
else if (keyPosition == expectedIndents.top() )
{
if (!surroundingKeys.empty())
{
surroundingKeys.pop(); // last of same length
}
}
else
{
// less indent than before
do expectedIndents.pop();
while (expectedIndents.top() != keyPosition); // unwind until current indent is found
}
if (!surroundingKeys.empty())
{
key = surroundingKeys.top() + "." + key; // construct current key name
}
surroundingKeys.push(key); // this is the new embracing key
std::string value = line.substr(colonPosition+1);
MITK_DEBUG << " Key: '" << key << "' value '" << value << "'" ;
parsedResult[key] = value; // store parsing result
}
return parsedResult;
}
-
diff --git a/Core/Code/Testing/files.cmake b/Core/Code/Testing/files.cmake
index bf188c7b01..929ebe6a6c 100644
--- a/Core/Code/Testing/files.cmake
+++ b/Core/Code/Testing/files.cmake
@@ -1,203 +1,203 @@
# tests with no extra command line parameter
set(MODULE_TESTS
# IMPORTANT: If you plan to deactivate / comment out a test please write a bug number to the commented out line of code.
#
# Example: #mitkMyTest #this test is commented out because of bug 12345
#
# It is important that the bug is open and that the test will be activated again before the bug is closed. This assures that
# no test is forgotten after it was commented out. If there is no bug for your current problem, please add a new one and
# mark it as critical.
################## DISABLED TESTS #################################################
#mitkAbstractTransformGeometryTest.cpp #seems as tested class mitkExternAbstractTransformGeometry doesnt exist any more
#mitkStateMachineContainerTest.cpp #rewrite test, indirect since no longer exported Bug 14529
#mitkRegistrationBaseTest.cpp #tested class mitkRegistrationBase doesn't exist any more
#mitkSegmentationInterpolationTest.cpp #file doesn't exist!
#mitkPipelineSmartPointerCorrectnessTest.cpp #file doesn't exist!
#mitkITKThreadingTest.cpp #test outdated because itk::Semaphore was removed from ITK
#mitkAbstractTransformPlaneGeometryTest.cpp #mitkVtkAbstractTransformPlaneGeometry doesn't exist any more
#mitkTestUtilSharedLibrary.cpp #Linker problem with this test...
#mitkTextOverlay2DSymbolsRenderingTest.cpp #Implementation of the tested feature is not finished yet. Ask Christoph or see bug 15104 for details.
################# RUNNING TESTS ###################################################
mitkAccessByItkTest.cpp
mitkCoreObjectFactoryTest.cpp
mitkMaterialTest.cpp
mitkActionTest.cpp
mitkDispatcherTest.cpp
mitkEnumerationPropertyTest.cpp
mitkEventTest.cpp
mitkFocusManagerTest.cpp
mitkGenericPropertyTest.cpp
- mitkGeometry2DTest.cpp
mitkGeometry3DTest.cpp
mitkGeometry3DEqualTest.cpp
mitkGeometryDataToSurfaceFilterTest.cpp
mitkGlobalInteractionTest.cpp
mitkImageEqualTest.cpp
mitkImageDataItemTest.cpp
mitkImageGeneratorTest.cpp
mitkIOUtilTest.cpp
mitkBaseDataTest.cpp
mitkImportItkImageTest.cpp
mitkGrabItkImageMemoryTest.cpp
mitkInstantiateAccessFunctionTest.cpp
mitkInteractorTest.cpp
mitkLevelWindowTest.cpp
mitkMessageTest.cpp
mitkPixelTypeTest.cpp
mitkPlaneGeometryTest.cpp
mitkPointSetTest.cpp
mitkPointSetEqualTest.cpp
mitkPointSetFileIOTest.cpp
mitkPointSetOnEmptyTest.cpp
mitkPointSetWriterTest.cpp
mitkPointSetReaderTest.cpp
mitkPointSetInteractorTest.cpp
mitkPointSetPointOperationsTest.cpp
mitkPropertyTest.cpp
mitkPropertyListTest.cpp
mitkSlicedGeometry3DTest.cpp
mitkSliceNavigationControllerTest.cpp
mitkStateMachineTest.cpp
mitkStateTest.cpp
mitkSurfaceTest.cpp
mitkSurfaceEqualTest.cpp
mitkSurfaceToSurfaceFilterTest.cpp
mitkTimeGeometryTest.cpp
mitkTransitionTest.cpp
mitkUndoControllerTest.cpp
mitkVtkWidgetRenderingTest.cpp
mitkVerboseLimitedLinearUndoTest.cpp
mitkWeakPointerTest.cpp
mitkTransferFunctionTest.cpp
mitkStepperTest.cpp
mitkRenderingManagerTest.cpp
vtkMitkThickSlicesFilterTest.cpp
mitkNodePredicateSourceTest.cpp
mitkVectorTest.cpp
mitkClippedSurfaceBoundsCalculatorTest.cpp
mitkExceptionTest.cpp
mitkExtractSliceFilterTest.cpp
mitkLogTest.cpp
mitkImageDimensionConverterTest.cpp
mitkLoggingAdapterTest.cpp
mitkUIDGeneratorTest.cpp
mitkShaderRepositoryTest.cpp
mitkPlanePositionManagerTest.cpp
mitkAffineTransformBaseTest.cpp
mitkPropertyAliasesTest.cpp
mitkPropertyDescriptionsTest.cpp
mitkPropertyExtensionsTest.cpp
mitkPropertyFiltersTest.cpp
mitkTinyXMLTest.cpp
mitkRawImageFileReaderTest.cpp
mitkInteractionEventTest.cpp
mitkLookupTableTest.cpp
mitkSTLFileReaderTest.cpp
mitkSurfaceToImageFilterTest.cpp
+ mitkBaseGeometryTest.cpp
mitkImageToSurfaceFilterTest.cpp
mitkEqualTest.cpp
mitkLineTest.cpp
)
if(MITK_ENABLE_RENDERING_TESTING) #since mitkInteractionTestHelper is currently creating a vtkRenderWindow
set(MODULE_TESTS
${MODULE_TESTS}
mitkPointSetDataInteractorTest.cpp
)
endif()
# test with image filename as an extra command line parameter
set(MODULE_IMAGE_TESTS
mitkImageTimeSelectorTest.cpp #only runs on images
mitkImageAccessorTest.cpp #only runs on images
mitkDataNodeFactoryTest.cpp #runs on all types of data
)
set(MODULE_SURFACE_TESTS
mitkSurfaceVtkWriterTest.cpp #only runs on surfaces
mitkDataNodeFactoryTest.cpp #runs on all types of data
)
# list of images for which the tests are run
set(MODULE_TESTIMAGES
US4DCyl.nrrd
Pic3D.nrrd
Pic2DplusT.nrrd
BallBinary30x30x30.nrrd
Png2D-bw.png
)
set(MODULE_TESTSURFACES
binary.stl
ball.stl
)
set(MODULE_CUSTOM_TESTS
mitkDataStorageTest.cpp
mitkDataNodeTest.cpp
mitkDicomSeriesReaderTest.cpp
mitkDICOMLocaleTest.cpp
mitkEventMapperTest.cpp
mitkEventConfigTest.cpp
mitkNodeDependentPointSetInteractorTest.cpp
mitkStateMachineFactoryTest.cpp
mitkPointSetLocaleTest.cpp
mitkImageTest.cpp
mitkImageWriterTest.cpp
mitkImageVtkMapper2DTest.cpp
mitkImageVtkMapper2DLevelWindowTest.cpp
mitkImageVtkMapper2DOpacityTest.cpp
mitkImageVtkMapper2DResliceInterpolationPropertyTest.cpp
mitkImageVtkMapper2DColorTest.cpp
mitkImageVtkMapper2DSwivelTest.cpp
mitkImageVtkMapper2DTransferFunctionTest.cpp
mitkImageVtkMapper2DLookupTableTest.cpp
mitkSurfaceVtkMapper3DTest
mitkSurfaceVtkMapper3DTexturedSphereTest.cpp
mitkSurfaceGLMapper2DColorTest.cpp
mitkSurfaceGLMapper2DOpacityTest.cpp
mitkVolumeCalculatorTest.cpp
mitkLevelWindowManagerTest.cpp
mitkPointSetVtkMapper2DTest.cpp
mitkPointSetVtkMapper2DImageTest.cpp
mitkPointSetVtkMapper2DGlyphTypeTest.cpp
mitkPointSetVtkMapper2DTransformedPointsTest.cpp
mitkLabelOverlay3DRendering2DTest.cpp
mitkLabelOverlay3DRendering3DTest.cpp
mitkTextOverlay2DRenderingTest.cpp
mitkTextOverlay2DLayouterRenderingTest.cpp
mitkTextOverlay3DRendering2DTest.cpp
mitkTextOverlay3DRendering3DTest.cpp
mitkTextOverlay3DColorRenderingTest.cpp
mitkVTKRenderWindowSizeTest.cpp
mitkMultiComponentImageDataComparisonFilterTest.cpp
mitkImageToItkTest.cpp
mitkImageSliceSelectorTest.cpp
mitkSurfaceDepthPeelingTest.cpp
mitkSurfaceDepthSortingTest.cpp
)
set(MODULE_RESOURCE_FILES
Interactions/AddAndRemovePoints.xml
Interactions/globalConfig.xml
Interactions/StatemachineTest.xml
Interactions/StatemachineConfigTest.xml
)
# Create an artificial module initializing class for
# the usServiceListenerTest.cpp
usFunctionGenerateExecutableInit(testdriver_init_file
IDENTIFIER ${MODULE_NAME}TestDriver
)
# Embed the resources
set(testdriver_resources )
usFunctionEmbedResources(testdriver_resources
EXECUTABLE_NAME ${MODULE_NAME}TestDriver
ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Resources
FILES ${MODULE_RESOURCE_FILES}
)
set(TEST_CPP_FILES ${testdriver_init_file} ${testdriver_resources})
diff --git a/Core/Code/Testing/mitkBaseDataTest.cpp b/Core/Code/Testing/mitkBaseDataTest.cpp
index 373df3947c..c0a8a3f3a9 100644
--- a/Core/Code/Testing/mitkBaseDataTest.cpp
+++ b/Core/Code/Testing/mitkBaseDataTest.cpp
@@ -1,120 +1,121 @@
/*===================================================================
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 "mitkBaseDataTestImplementation.h"
#include "mitkStringProperty.h"
#include "mitkTestingMacros.h"
#include <mitkTimeGeometry.h>
#include <mitkProportionalTimeGeometry.h>
#include "itkImage.h"
int mitkBaseDataTest(int /*argc*/, char* /*argv*/[])
{
MITK_TEST_BEGIN("BaseData")
//Create a BaseData implementation
MITK_INFO << "Creating a base data instance...";
mitk::BaseDataTestImplementation::Pointer baseDataImpl = mitk::BaseDataTestImplementation::New();
MITK_TEST_CONDITION_REQUIRED(baseDataImpl.IsNotNull(),"Testing instantiation");
MITK_TEST_CONDITION(baseDataImpl->IsInitialized(), "BaseDataTestImplementation is initialized");
MITK_TEST_CONDITION(baseDataImpl->IsEmpty(), "BaseDataTestImplementation is initialized and empty");
mitk::BaseDataTestImplementation::Pointer cloneBaseData = baseDataImpl->Clone();
MITK_TEST_CONDITION_REQUIRED(cloneBaseData.IsNotNull(),"Testing instantiation of base data clone");
MITK_TEST_CONDITION(cloneBaseData->IsInitialized(), "Clone of BaseDataTestImplementation is initialized");
MITK_TEST_CONDITION(cloneBaseData->IsEmpty(), "Clone of BaseDataTestImplementation is initialized and empty");
MITK_INFO << "Testing setter and getter for geometries...";
//test method GetTimeGeometry()
MITK_TEST_CONDITION(baseDataImpl->GetTimeGeometry(), "Testing creation of TimeGeometry");
mitk::TimeGeometry* geo = NULL;
baseDataImpl->SetTimeGeometry(geo);
MITK_TEST_CONDITION(baseDataImpl->GetTimeGeometry() == NULL, "Reset Geometry");
mitk::ProportionalTimeGeometry::Pointer geo2 = mitk::ProportionalTimeGeometry::New();
baseDataImpl->SetTimeGeometry(geo2);
geo2->Initialize(2);
MITK_TEST_CONDITION(baseDataImpl->GetTimeGeometry() == geo2.GetPointer(), "Correct Reinit of TimeGeometry");
//test method GetGeometry(int timeStep)
MITK_TEST_CONDITION(baseDataImpl->GetGeometry(1) != NULL, "... and single Geometries");
//test method Expand(unsigned int timeSteps)
baseDataImpl->Expand(5);
MITK_TEST_CONDITION(baseDataImpl->GetTimeSteps() == 5, "Expand the geometry to further time slices!");
//test method GetUpdatedGeometry(int timeStep);
- mitk::Geometry3D::Pointer geo3 = mitk::Geometry3D::New();
+ mitk::Geometry3D::Pointer geometry3D = mitk::Geometry3D::New();
+ mitk::BaseGeometry::Pointer geo3 = dynamic_cast<mitk::BaseGeometry*>(geometry3D.GetPointer());
mitk::ProportionalTimeGeometry::Pointer timeGeometry = dynamic_cast<mitk::ProportionalTimeGeometry *>(baseDataImpl->GetTimeGeometry());
if (timeGeometry.IsNotNull() )
{
timeGeometry->SetTimeStepGeometry(geo3,1);
}
MITK_TEST_CONDITION(baseDataImpl->GetUpdatedGeometry(1) == geo3, "Set Geometry for time step 1");
MITK_TEST_CONDITION(baseDataImpl->GetMTime()!= 0, "Check if modified time is set");
baseDataImpl->SetClonedGeometry(geo3, 1);
mitk::ScalarType x[3];
x[0] = 2;
x[1] = 4;
x[2] = 6;
mitk::Point3D p3d(x);
baseDataImpl->SetOrigin(p3d);
geo3->SetOrigin(p3d);
MITK_TEST_CONDITION(baseDataImpl->GetGeometry(1)->GetOrigin() == geo3->GetOrigin(), "Testing Origin set");
cloneBaseData = baseDataImpl->Clone();
MITK_TEST_CONDITION(cloneBaseData->GetGeometry(1)->GetOrigin() == geo3->GetOrigin(), "Testing origin set in clone!");
MITK_TEST_CONDITION(!baseDataImpl->IsEmptyTimeStep(1), "Is not empty before clear()!");
baseDataImpl->Clear();
MITK_TEST_CONDITION(baseDataImpl->IsEmptyTimeStep(1), "...but afterwards!");
//test method Set-/GetProperty()
baseDataImpl->SetProperty("property38", mitk::StringProperty::New("testproperty"));
//baseDataImpl->SetProperty("visibility", mitk::BoolProperty::New());
MITK_TEST_CONDITION(baseDataImpl->GetProperty("property38")->GetValueAsString() == "testproperty","Check if base property is set correctly!");
cloneBaseData = baseDataImpl->Clone();
MITK_TEST_CONDITION(cloneBaseData->GetProperty("property38")->GetValueAsString() == "testproperty", "Testing origin set in clone!");
//test method Set-/GetPropertyList
mitk::PropertyList::Pointer propertyList = mitk::PropertyList::New();
propertyList->SetFloatProperty("floatProperty1", 123.45);
propertyList->SetBoolProperty("visibility",true);
propertyList->SetStringProperty("nameXY","propertyName");
baseDataImpl->SetPropertyList(propertyList);
bool value = false;
MITK_TEST_CONDITION(baseDataImpl->GetPropertyList() == propertyList, "Check if base property list is set correctly!");
MITK_TEST_CONDITION(baseDataImpl->GetPropertyList()->GetBoolProperty("visibility", value) == true, "Check if base property is set correctly in the property list!");
//test method UpdateOutputInformation()
baseDataImpl->UpdateOutputInformation();
MITK_TEST_CONDITION(baseDataImpl->GetUpdatedTimeGeometry() == geo2, "TimeGeometry update!");
//Test method CopyInformation()
mitk::BaseDataTestImplementation::Pointer newBaseData = mitk::BaseDataTestImplementation::New();
newBaseData->CopyInformation(baseDataImpl);
MITK_TEST_CONDITION_REQUIRED( newBaseData->GetTimeGeometry()->CountTimeSteps() == 5, "Check copying of of Basedata Data Object!");
MITK_TEST_END()
}
diff --git a/Core/Code/Testing/mitkBaseGeometryTest.cpp b/Core/Code/Testing/mitkBaseGeometryTest.cpp
new file mode 100644
index 0000000000..8eee786cd7
--- /dev/null
+++ b/Core/Code/Testing/mitkBaseGeometryTest.cpp
@@ -0,0 +1,1227 @@
+/*===================================================================
+
+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 "mitkTestingMacros.h"
+#include <mitkTestingConfig.h>
+#include <mitkTestFixture.h>
+
+#include <mitkBaseGeometry.h>
+#include <MitkCoreExports.h>
+#include <mitkCommon.h>
+#include "mitkoperationactor.h"
+
+#include <itkBoundingBox.h>
+#include "mitkvector.h"
+#include <itkAffineGeometryFrame.h>
+#include <itkQuaternionRigidTransform.h>
+#include "itkScalableAffineTransform.h"
+#include <itkIndex.h>
+#include <vtkMatrixToLinearTransform.h>
+#include <vtkMatrix4x4.h>
+
+#include "mitkRotationOperation.h"
+#include "mitkInteractionConst.h"
+#include <mitkMatrixConvert.h>
+#include <mitkImageCast.h>
+
+class vtkMatrix4x4;
+class vtkMatrixToLinearTransform;
+class vtkLinearTransform;
+
+typedef itk::BoundingBox<unsigned long, 3, mitk::ScalarType> BoundingBox;
+typedef itk::BoundingBox<unsigned long, 3, mitk::ScalarType> BoundingBoxType;
+typedef BoundingBoxType::BoundsArrayType BoundsArrayType;
+typedef BoundingBoxType::Pointer BoundingBoxPointer;
+
+// Dummy instance of abstract base class
+class DummyTestClass : public mitk::BaseGeometry
+{
+public:
+ DummyTestClass(){};
+ DummyTestClass(const DummyTestClass& other) : BaseGeometry(other){};
+ ~DummyTestClass(){};
+
+ mitkClassMacro(DummyTestClass, mitk::BaseGeometry);
+ itkNewMacro(Self);
+ mitkNewMacro1Param(Self,Self);
+
+ itk::LightObject::Pointer DummyTestClass::InternalClone() const
+ {
+ Self::Pointer newGeometry = new Self(*this);
+ newGeometry->UnRegister();
+ return newGeometry.GetPointer();
+ }
+
+ virtual void PrintSelf(std::ostream& os, itk::Indent indent) const{};
+
+};
+
+class mitkBaseGeometryTestSuite : public mitk::TestFixture
+{
+ // List of Tests
+ CPPUNIT_TEST_SUITE(mitkBaseGeometryTestSuite);
+
+ //Constructor
+ MITK_TEST(TestConstructors);
+ MITK_TEST(TestInitialize);
+
+ //Set
+ MITK_TEST(TestSetOrigin);
+ MITK_TEST(TestSetBounds);
+ MITK_TEST(TestSetFloatBounds);
+ MITK_TEST(TestSetFloatBoundsDouble);
+ MITK_TEST(TestSetFrameOfReferenceID);
+ MITK_TEST(TestSetIndexToWorldTransform);
+ MITK_TEST(TestSetSpacing);
+ MITK_TEST(TestTransferItkToVtkTransform);
+ MITK_TEST(TestSetIndexToWorldTransformByVtkMatrix);
+ MITK_TEST(TestSetIdentity);
+ MITK_TEST(TestSetImageGeometry);
+ //Equal
+ MITK_TEST(Equal_CloneAndOriginal_ReturnsTrue);
+ MITK_TEST(Equal_DifferentOrigin_ReturnsFalse);
+ MITK_TEST(Equal_DifferentIndexToWorldTransform_ReturnsFalse);
+ MITK_TEST(Equal_DifferentSpacing_ReturnsFalse);
+ MITK_TEST(Equal_InputIsNull_ReturnsFalse);
+ MITK_TEST(Equal_DifferentBoundingBox_ReturnsFalse);
+ //other Functions
+ MITK_TEST(TestComposeTransform);
+ MITK_TEST(TestComposeVtkMatrix);
+ MITK_TEST(TestTranslate);
+ MITK_TEST(TestIndexToWorld);
+ MITK_TEST(TestExecuteOperation);
+ MITK_TEST(TestCalculateBoundingBoxRelToTransform);
+ //MITK_TEST(TestSetTimeBounds);
+ MITK_TEST(TestIs2DConvertable);
+ MITK_TEST(TestGetCornerPoint);
+ MITK_TEST(TestExtentInMM);
+ MITK_TEST(TestGetAxisVector);
+ MITK_TEST(TestGetCenter);
+ MITK_TEST(TestGetDiagonalLength);
+ MITK_TEST(TestGetExtent);
+ MITK_TEST(TestIsInside);
+ MITK_TEST(TestGetMatrixColumn);
+
+ CPPUNIT_TEST_SUITE_END();
+
+ // Used Variables
+private:
+ mitk::Point3D aPoint;
+ float aFloatSpacing[3];
+ mitk::Vector3D aSpacing;
+ mitk::AffineTransform3D::Pointer aTransform;
+ BoundingBoxPointer aBoundingBox;
+ mitk::AffineTransform3D::MatrixType aMatrix;
+
+ mitk::Point3D anotherPoint;
+ mitk::Vector3D anotherSpacing;
+ BoundingBoxPointer anotherBoundingBox;
+ BoundingBoxPointer aThirdBoundingBox;
+ mitk::AffineTransform3D::Pointer anotherTransform;
+ mitk::AffineTransform3D::Pointer aThirdTransform;
+ mitk::AffineTransform3D::MatrixType anotherMatrix;
+ mitk::AffineTransform3D::MatrixType aThirdMatrix;
+
+ DummyTestClass::Pointer aDummyGeometry;
+ DummyTestClass::Pointer anotherDummyGeometry;
+
+public:
+
+ // Set up for variables
+ void setUp()
+ {
+ mitk::FillVector3D(aFloatSpacing, 1,1,1);
+ mitk::FillVector3D(aSpacing, 1,1,1);
+ mitk::FillVector3D(aPoint, 0,0,0);
+
+ //Transform
+ aTransform = mitk::AffineTransform3D::New();
+ aTransform->SetIdentity();
+
+ aMatrix.SetIdentity();
+
+ anotherTransform = mitk::AffineTransform3D::New();
+
+ anotherMatrix.SetIdentity();
+ anotherMatrix(1,1) = 2;
+ anotherTransform->SetMatrix( anotherMatrix );
+
+ aThirdTransform = mitk::AffineTransform3D::New();
+
+ aThirdMatrix.SetIdentity();
+ aThirdMatrix(1,1) = 7;
+ aThirdTransform->SetMatrix( aThirdMatrix );
+
+ //Bounding Box
+ float bounds[6] = {0,1,0,1,0,1};
+ mitk::BoundingBox::BoundsArrayType b;
+ const float *input = bounds;
+ int j=0;
+ for(mitk::BoundingBox::BoundsArrayType::Iterator it = b.Begin(); j < 6 ;++j) *it++ = (mitk::ScalarType)*input++;
+
+ aBoundingBox = BoundingBoxType::New();
+
+ BoundingBoxType::PointsContainer::Pointer pointscontainer = BoundingBoxType::PointsContainer::New();
+ BoundingBoxType::PointType p;
+ BoundingBoxType::PointIdentifier pointid;
+ for(pointid=0; pointid<2;++pointid)
+ {
+ unsigned int i;
+ for(i=0; i<3; ++i)
+ {
+ p[i] = bounds[2*i+pointid];
+ }
+ pointscontainer->InsertElement(pointid, p);
+ }
+
+ aBoundingBox->SetPoints(pointscontainer);
+ aBoundingBox->ComputeBoundingBox();
+
+ anotherBoundingBox = BoundingBoxType::New();
+ p[0]=11;
+ p[1]=12;
+ p[2]=13;
+ pointscontainer->InsertElement(1, p);
+ anotherBoundingBox->SetPoints(pointscontainer);
+ anotherBoundingBox->ComputeBoundingBox();
+
+ aThirdBoundingBox = BoundingBoxType::New();
+ p[0]=22;
+ p[1]=23;
+ p[2]=24;
+ pointscontainer->InsertElement(1, p);
+ aThirdBoundingBox->SetPoints(pointscontainer);
+ aThirdBoundingBox->ComputeBoundingBox();
+
+ mitk::FillVector3D(anotherPoint, 2,3,4);
+ mitk::FillVector3D(anotherSpacing, 5,6.5,7);
+
+ aDummyGeometry = DummyTestClass::New();
+ aDummyGeometry->Initialize();
+ anotherDummyGeometry = aDummyGeometry->Clone();
+ }
+
+ void tearDown()
+ {
+ aDummyGeometry = NULL;
+ anotherDummyGeometry = NULL;
+ }
+
+ // Test functions
+
+ void TestSetOrigin()
+ {
+ DummyTestClass::Pointer dummy = DummyTestClass::New();
+ dummy->SetOrigin(anotherPoint);
+ CPPUNIT_ASSERT(anotherPoint==dummy->GetOrigin());
+
+ //undo changes, new and changed object need to be the same!
+ dummy->SetOrigin(aPoint);
+ DummyTestClass::Pointer newDummy = DummyTestClass::New();
+ CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true));
+ }
+
+ void TestSetImageGeometry()
+ {
+ DummyTestClass::Pointer dummy = DummyTestClass::New();
+ dummy->SetImageGeometry(true);
+ CPPUNIT_ASSERT(dummy->GetImageGeometry());
+
+ //undo changes, new and changed object need to be the same!
+ dummy->SetImageGeometry(false);
+ CPPUNIT_ASSERT(dummy->GetImageGeometry()==false);
+ DummyTestClass::Pointer newDummy = DummyTestClass::New();
+ CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true));
+ }
+
+ void TestSetFloatBounds(){
+ float bounds[6] = {0,11,0,12,0,13};
+ DummyTestClass::Pointer dummy = DummyTestClass::New();
+ dummy->SetFloatBounds(bounds);
+ CPPUNIT_ASSERT(mitk::Equal( dummy->GetBoundingBox(), anotherBoundingBox, mitk::eps, true));
+
+ //Wrong bounds, test needs to fail
+ bounds[1]=7;
+ dummy->SetFloatBounds(bounds);
+ CPPUNIT_ASSERT((mitk::Equal( dummy->GetBoundingBox(), anotherBoundingBox, mitk::eps, false))==false);
+
+ //undo changes, new and changed object need to be the same!
+ float originalBounds[6] = {0,1,0,1,0,1};
+ dummy->SetFloatBounds(originalBounds);
+ DummyTestClass::Pointer newDummy = DummyTestClass::New();
+ CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true));
+ }
+
+ void TestSetBounds(){
+ DummyTestClass::Pointer dummy = DummyTestClass::New();
+ dummy->SetBounds(anotherBoundingBox->GetBounds());
+ CPPUNIT_ASSERT(mitk::Equal( dummy->GetBoundingBox(), anotherBoundingBox, mitk::eps, true));
+
+ //Test needs to fail now
+ dummy->SetBounds(aThirdBoundingBox->GetBounds());
+ CPPUNIT_ASSERT(mitk::Equal( dummy->GetBoundingBox(), anotherBoundingBox, mitk::eps, false)==false);
+
+ //undo changes, new and changed object need to be the same!
+ dummy->SetBounds(aBoundingBox->GetBounds());
+ DummyTestClass::Pointer newDummy = DummyTestClass::New();
+ CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true));
+ }
+
+ void TestSetFloatBoundsDouble(){
+ double bounds[6] = {0,11,0,12,0,13};
+ DummyTestClass::Pointer dummy = DummyTestClass::New();
+ dummy->SetFloatBounds(bounds);
+ CPPUNIT_ASSERT(mitk::Equal( dummy->GetBoundingBox(), anotherBoundingBox, mitk::eps, true));
+
+ //Test needs to fail now
+ bounds[3]=7;
+ dummy->SetFloatBounds(bounds);
+ CPPUNIT_ASSERT(mitk::Equal( dummy->GetBoundingBox(), anotherBoundingBox, mitk::eps, false)==false);
+
+ //undo changes, new and changed object need to be the same!
+ double originalBounds[6] = {0,1,0,1,0,1};
+ dummy->SetFloatBounds(originalBounds);
+ DummyTestClass::Pointer newDummy = DummyTestClass::New();
+ CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true));
+ }
+
+ void TestSetFrameOfReferenceID()
+ {
+ DummyTestClass::Pointer dummy = DummyTestClass::New();
+ dummy->SetFrameOfReferenceID(5);
+ CPPUNIT_ASSERT(dummy->GetFrameOfReferenceID()==5);
+
+ //undo changes, new and changed object need to be the same!
+ dummy->SetFrameOfReferenceID(0);
+ DummyTestClass::Pointer newDummy = DummyTestClass::New();
+ CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true));
+ }
+
+ void TestSetIndexToWorldTransform()
+ {
+ DummyTestClass::Pointer dummy = DummyTestClass::New();
+ dummy->SetIndexToWorldTransform(anotherTransform);
+ CPPUNIT_ASSERT(mitk::Equal(anotherTransform,dummy->GetIndexToWorldTransform(),mitk::eps,true));
+
+ //Test needs to fail now
+ dummy->SetIndexToWorldTransform(aThirdTransform);
+ CPPUNIT_ASSERT(mitk::Equal(anotherTransform,dummy->GetIndexToWorldTransform(),mitk::eps,false)==false);
+
+ //undo changes, new and changed object need to be the same!
+ dummy->SetIndexToWorldTransform(aTransform);
+ DummyTestClass::Pointer newDummy = DummyTestClass::New();
+ CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true));
+ }
+
+ void TestSetIndexToWorldTransformByVtkMatrix()
+ {
+ vtkMatrix4x4* vtkmatrix;
+ vtkmatrix = vtkMatrix4x4::New();
+ vtkmatrix->Identity();
+ vtkmatrix->SetElement(1,1,2);
+ DummyTestClass::Pointer dummy = DummyTestClass::New();
+ dummy->SetIndexToWorldTransformByVtkMatrix(vtkmatrix);
+ CPPUNIT_ASSERT(mitk::Equal(anotherTransform,dummy->GetIndexToWorldTransform(),mitk::eps,true));
+
+ //test needs to fail now
+ vtkmatrix->SetElement(1,1,7);
+ dummy->SetIndexToWorldTransformByVtkMatrix(vtkmatrix);
+ CPPUNIT_ASSERT(mitk::Equal(anotherTransform,dummy->GetIndexToWorldTransform(),mitk::eps,false)==false);
+
+ //undo changes, new and changed object need to be the same!
+ vtkmatrix->SetElement(1,1,1);
+ dummy->SetIndexToWorldTransformByVtkMatrix(vtkmatrix);
+ DummyTestClass::Pointer newDummy = DummyTestClass::New();
+ CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true));
+ }
+
+ void TestSetIdentity()
+ {
+ DummyTestClass::Pointer dummy = DummyTestClass::New();
+ //Change IndextoWorldTransform and Origin
+ dummy->SetIndexToWorldTransform(anotherTransform);
+ dummy->SetOrigin(anotherPoint);
+
+ //Set Identity should reset ITWT and Origin
+ dummy->SetIdentity();
+
+ CPPUNIT_ASSERT(mitk::Equal(aTransform,dummy->GetIndexToWorldTransform(),mitk::eps,true));
+ CPPUNIT_ASSERT(aPoint==dummy->GetOrigin());
+ CPPUNIT_ASSERT(aSpacing==dummy->GetSpacing());
+
+ //new and changed object need to be the same!
+ DummyTestClass::Pointer newDummy = DummyTestClass::New();
+ CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true));
+ }
+
+ void TestSetSpacing()
+ {
+ DummyTestClass::Pointer dummy = DummyTestClass::New();
+ dummy->SetSpacing(anotherSpacing);
+ CPPUNIT_ASSERT(anotherSpacing==dummy->GetSpacing());
+
+ //undo changes, new and changed object need to be the same!
+ dummy->SetSpacing(aSpacing);
+ DummyTestClass::Pointer newDummy = DummyTestClass::New();
+ CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true));
+ }
+
+ void TestTransferItkToVtkTransform()
+ {
+ DummyTestClass::Pointer dummy = DummyTestClass::New();
+ dummy->SetIndexToWorldTransform(anotherTransform); //calls TransferItkToVtkTransform
+ mitk::AffineTransform3D::Pointer dummyTransform = dummy->GetIndexToWorldTransform();
+ CPPUNIT_ASSERT(mitk::MatrixEqualElementWise( anotherMatrix, dummyTransform->GetMatrix() ));
+ }
+
+ void TestConstructors()
+ {
+ //test standard constructor
+ DummyTestClass::Pointer dummy1 = DummyTestClass::New();
+ bool test = dummy1->IsValid();
+ CPPUNIT_ASSERT(test == true);
+ CPPUNIT_ASSERT(dummy1->GetFrameOfReferenceID() == 0);
+ CPPUNIT_ASSERT(dummy1->GetIndexToWorldTransformLastModified() == 0);
+
+ CPPUNIT_ASSERT(dummy1->GetSpacing() == aSpacing);
+ CPPUNIT_ASSERT(dummy1->GetOrigin()==aPoint);
+
+ CPPUNIT_ASSERT(dummy1->GetImageGeometry()==false);
+
+ CPPUNIT_ASSERT(mitk::Equal( dummy1->GetIndexToWorldTransform(), aTransform, mitk::eps, true));
+
+ CPPUNIT_ASSERT(mitk::Equal( dummy1->GetBoundingBox(), aBoundingBox, mitk::eps, true));
+
+ DummyTestClass::Pointer dummy2 = DummyTestClass::New();
+ dummy2->SetOrigin(anotherPoint);
+ float bounds[6] = {0,11,0,12,0,13};
+ dummy2->SetFloatBounds(bounds);
+ dummy2->SetIndexToWorldTransform(anotherTransform);
+ dummy2->SetSpacing(anotherSpacing);
+
+ DummyTestClass::Pointer dummy3;
+ dummy3 = DummyTestClass::New(*dummy2);
+ CPPUNIT_ASSERT(mitk::Equal(dummy3,dummy2,mitk::eps,true));
+ }
+
+ //Equal Tests
+
+ void Equal_CloneAndOriginal_ReturnsTrue()
+ {
+ CPPUNIT_ASSERT( mitk::Equal(aDummyGeometry, anotherDummyGeometry, mitk::eps,true));
+ }
+
+ void Equal_DifferentOrigin_ReturnsFalse()
+ {
+ anotherDummyGeometry->SetOrigin(anotherPoint);
+
+ CPPUNIT_ASSERT( mitk::Equal(aDummyGeometry, anotherDummyGeometry, mitk::eps,false)==false);
+ }
+
+ void Equal_DifferentIndexToWorldTransform_ReturnsFalse()
+ {
+ anotherDummyGeometry->SetIndexToWorldTransform(anotherTransform);
+
+ CPPUNIT_ASSERT( mitk::Equal(aDummyGeometry, anotherDummyGeometry, mitk::eps,false)==false);
+ }
+
+ void Equal_DifferentSpacing_ReturnsFalse()
+ {
+ anotherDummyGeometry->SetSpacing(anotherSpacing);
+
+ CPPUNIT_ASSERT( mitk::Equal(aDummyGeometry, anotherDummyGeometry, mitk::eps,false)==false);
+ }
+
+ void Equal_InputIsNull_ReturnsFalse()
+ {
+ DummyTestClass::Pointer geometryNull = NULL;
+ CPPUNIT_ASSERT( mitk::Equal(geometryNull, anotherDummyGeometry, mitk::eps,false)==false);
+ }
+
+ void Equal_DifferentBoundingBox_ReturnsFalse()
+ {
+ //create different bounds to make the comparison false
+ mitk::ScalarType bounds[ ] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
+ anotherDummyGeometry->SetBounds(bounds);
+
+ CPPUNIT_ASSERT( mitk::Equal(aDummyGeometry, anotherDummyGeometry, mitk::eps,false)==false);
+ }
+
+ void TestComposeTransform(){
+ //Create Transformations to set and compare
+ mitk::AffineTransform3D::Pointer transform1;
+ transform1 = mitk::AffineTransform3D::New();
+ mitk::AffineTransform3D::MatrixType matrix1;
+ matrix1.SetIdentity();
+ matrix1(1,1) = 2;
+ transform1->SetMatrix( matrix1 ); //Spacing = 2
+
+ mitk::AffineTransform3D::Pointer transform2;
+ transform2 = mitk::AffineTransform3D::New();
+ mitk::AffineTransform3D::MatrixType matrix2;
+ matrix2.SetIdentity();
+ matrix2(1,1) = 2;
+ transform2->SetMatrix( matrix2 ); //Spacing = 2
+
+ mitk::AffineTransform3D::Pointer transform3;
+ transform3 = mitk::AffineTransform3D::New();
+ mitk::AffineTransform3D::MatrixType matrix3;
+ matrix3.SetIdentity();
+ matrix3(1,1) = 4;
+ transform3->SetMatrix( matrix3 ); //Spacing = 4
+
+ mitk::AffineTransform3D::Pointer transform4;
+ transform4 = mitk::AffineTransform3D::New();
+ mitk::AffineTransform3D::MatrixType matrix4;
+ matrix4.SetIdentity();
+ matrix4(1,1) = 0.25;
+ transform4->SetMatrix( matrix4 ); //Spacing = 0.25
+
+ //Vector to compare spacing
+ mitk::Vector3D expectedSpacing;
+ expectedSpacing.Fill(1.0);
+ expectedSpacing[1] = 4;
+
+ DummyTestClass::Pointer dummy = DummyTestClass::New();
+ dummy->SetIndexToWorldTransform(transform1); //Spacing = 2
+ dummy->Compose(transform2); //Spacing = 4
+ CPPUNIT_ASSERT(mitk::Equal(dummy->GetSpacing(), expectedSpacing));
+ CPPUNIT_ASSERT(mitk::Equal(transform3,dummy->GetIndexToWorldTransform(),mitk::eps,true)); // 4=4
+
+ //undo changes, new and changed object need to be the same!
+ dummy->Compose(transform4); //Spacing = 1
+ DummyTestClass::Pointer newDummy = DummyTestClass::New();
+ CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true)); // 1=1
+ }
+
+ void TestComposeVtkMatrix(){
+ //Create Transformations to set and compare
+ mitk::AffineTransform3D::Pointer transform1;
+ transform1 = mitk::AffineTransform3D::New();
+ mitk::AffineTransform3D::MatrixType matrix1;
+ matrix1.SetIdentity();
+ matrix1(1,1) = 2;
+ transform1->SetMatrix( matrix1 ); //Spacing = 2
+
+ vtkMatrix4x4* vtkmatrix2;
+ vtkmatrix2 = vtkMatrix4x4::New();
+ vtkmatrix2->Identity();
+ vtkmatrix2->SetElement(1,1,2); //Spacing = 2
+
+ mitk::AffineTransform3D::Pointer transform3;
+ transform3 = mitk::AffineTransform3D::New();
+ mitk::AffineTransform3D::MatrixType matrix3;
+ matrix3.SetIdentity();
+ matrix3(1,1) = 4;
+ transform3->SetMatrix( matrix3 ); //Spacing = 4
+
+ vtkMatrix4x4* vtkmatrix4;
+ vtkmatrix4 = vtkMatrix4x4::New();
+ vtkmatrix4->Identity();
+ vtkmatrix4->SetElement(1,1,0.25); //Spacing = 0.25
+
+ //Vector to compare spacing
+ mitk::Vector3D expectedSpacing;
+ expectedSpacing.Fill(1.0);
+ expectedSpacing[1] = 4;
+
+ DummyTestClass::Pointer dummy = DummyTestClass::New();
+ dummy->SetIndexToWorldTransform(transform1); //Spacing = 2
+ dummy->Compose(vtkmatrix2); //Spacing = 4
+
+ CPPUNIT_ASSERT(mitk::Equal(transform3,dummy->GetIndexToWorldTransform(),mitk::eps,true)); // 4=4
+ CPPUNIT_ASSERT(mitk::Equal(dummy->GetSpacing(), expectedSpacing));
+
+ //undo changes, new and changed object need to be the same!
+ dummy->Compose(vtkmatrix4); //Spacing = 1
+ DummyTestClass::Pointer newDummy = DummyTestClass::New();
+ CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true)); // 1=1
+ }
+
+ void TestTranslate(){
+ DummyTestClass::Pointer dummy = DummyTestClass::New();
+ dummy->SetOrigin(anotherPoint);
+ CPPUNIT_ASSERT(anotherPoint==dummy->GetOrigin());
+
+ //use some random values for translation
+ mitk::Vector3D translationVector;
+ translationVector.SetElement(0, 17.5f);
+ translationVector.SetElement(1, -32.3f);
+ translationVector.SetElement(2, 4.0f);
+
+ //compute ground truth
+ mitk::Point3D tmpResult = anotherPoint + translationVector;
+ dummy->Translate(translationVector);
+ CPPUNIT_ASSERT( mitk::Equal( dummy->GetOrigin(), tmpResult ));
+
+ //undo changes
+ translationVector*=-1;
+ dummy->Translate(translationVector);
+ CPPUNIT_ASSERT( mitk::Equal( dummy->GetOrigin(), anotherPoint ));
+
+ //undo changes, new and changed object need to be the same!
+ translationVector.SetElement(0, -1 * anotherPoint[0]);
+ translationVector.SetElement(1, -1 * anotherPoint[1]);
+ translationVector.SetElement(2, -1 * anotherPoint[2]);
+ dummy->Translate(translationVector);
+
+ DummyTestClass::Pointer newDummy = DummyTestClass::New();
+ CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true));
+ }
+
+ // a part of the test requires axis-parallel coordinates
+ int testIndexAndWorldConsistency(DummyTestClass* dummyGeometry)
+ {
+ //Testing consistency of index and world coordinate systems
+ mitk::Point3D origin = dummyGeometry->GetOrigin();
+ mitk::Point3D dummyPoint;
+
+ //Testing index->world->index conversion consistency
+ dummyGeometry->WorldToIndex(origin, dummyPoint);
+ dummyGeometry->IndexToWorld(dummyPoint, dummyPoint);
+ CPPUNIT_ASSERT(dummyPoint == origin);
+
+ //Testing WorldToIndex(origin, mitk::Point3D)==(0,0,0)
+ mitk::Point3D globalOrigin;
+ mitk::FillVector3D(globalOrigin, 0,0,0);
+
+ mitk::Point3D originContinuousIndex;
+ dummyGeometry->WorldToIndex(origin, originContinuousIndex);
+ CPPUNIT_ASSERT(originContinuousIndex == globalOrigin);
+
+ //Testing WorldToIndex(origin, itk::Index)==(0,0,0)
+ itk::Index<3> itkindex;
+ dummyGeometry->WorldToIndex(origin, itkindex);
+ itk::Index<3> globalOriginIndex;
+ mitk::vtk2itk(globalOrigin, globalOriginIndex);
+ CPPUNIT_ASSERT(itkindex == globalOriginIndex);
+
+ //Testing WorldToIndex(origin-0.5*spacing, itk::Index)==(0,0,0)
+ mitk::Vector3D halfSpacingStep = dummyGeometry->GetSpacing()*0.5;
+ mitk::Matrix3D rotation;
+ mitk::Point3D originOffCenter = origin-halfSpacingStep;
+ dummyGeometry->WorldToIndex(originOffCenter, itkindex);
+ CPPUNIT_ASSERT(itkindex == globalOriginIndex);
+
+ //Testing WorldToIndex(origin+0.5*spacing-eps, itk::Index)==(0,0,0)
+ originOffCenter = origin+halfSpacingStep;
+ originOffCenter -= 0.0001;
+ dummyGeometry->WorldToIndex( originOffCenter, itkindex);
+ CPPUNIT_ASSERT(itkindex == globalOriginIndex);
+
+ //Testing WorldToIndex(origin+0.5*spacing, itk::Index)==(1,1,1)");
+ originOffCenter = origin+halfSpacingStep;
+ itk::Index<3> global111;
+ mitk::FillVector3D(global111, 1,1,1);
+ dummyGeometry->WorldToIndex( originOffCenter, itkindex);
+ CPPUNIT_ASSERT(itkindex == global111);
+
+ //Testing WorldToIndex(GetCenter())==BoundingBox.GetCenter
+ mitk::Point3D center = dummyGeometry->GetCenter();
+ mitk::Point3D centerContIndex;
+ dummyGeometry->WorldToIndex(center, centerContIndex);
+ mitk::BoundingBox::ConstPointer boundingBox = dummyGeometry->GetBoundingBox();
+ mitk::BoundingBox::PointType centerBounds = boundingBox->GetCenter();
+ CPPUNIT_ASSERT(mitk::Equal(centerContIndex,centerBounds));
+
+ //Testing GetCenter()==IndexToWorld(BoundingBox.GetCenter)
+ center = dummyGeometry->GetCenter();
+ mitk::Point3D centerBoundsInWorldCoords;
+ dummyGeometry->IndexToWorld(centerBounds, centerBoundsInWorldCoords);
+ CPPUNIT_ASSERT(mitk::Equal(center,centerBoundsInWorldCoords));
+
+ //Test using random point,
+ //Testing consistency of index and world coordinate systems
+ mitk::Point3D point;
+ mitk::FillVector3D(point,3.5,-2,4.6);
+
+ //Testing index->world->index conversion consistency
+ dummyGeometry->WorldToIndex(point, dummyPoint);
+ dummyGeometry->IndexToWorld(dummyPoint, dummyPoint);
+ CPPUNIT_ASSERT(dummyPoint == point);
+
+ return EXIT_SUCCESS;
+ }
+
+ int testIndexAndWorldConsistencyForVectors(DummyTestClass* dummyGeometry)
+ {
+ //Testing consistency of index and world coordinate systems for vectors
+ mitk::Vector3D xAxisMM = dummyGeometry->GetAxisVector(0);
+ mitk::Vector3D xAxisContinuousIndex;
+
+ mitk::Point3D p, pIndex, origin;
+ origin = dummyGeometry->GetOrigin();
+ p[0] = xAxisMM[0]+origin[0];
+ p[1] = xAxisMM[1]+origin[1];
+ p[2] = xAxisMM[2]+origin[2];
+
+ dummyGeometry->WorldToIndex(p,pIndex);
+
+ dummyGeometry->WorldToIndex(xAxisMM,xAxisContinuousIndex);
+ CPPUNIT_ASSERT(xAxisContinuousIndex[0] == pIndex[0]);
+ CPPUNIT_ASSERT(xAxisContinuousIndex[1] == pIndex[1]);
+ CPPUNIT_ASSERT(xAxisContinuousIndex[2] == pIndex[2]);
+
+ dummyGeometry->IndexToWorld(xAxisContinuousIndex,xAxisContinuousIndex);
+
+ dummyGeometry->IndexToWorld(pIndex,p);
+
+ CPPUNIT_ASSERT(xAxisContinuousIndex == xAxisMM);
+ CPPUNIT_ASSERT(xAxisContinuousIndex[0] == p[0]-origin[0]);
+ CPPUNIT_ASSERT(xAxisContinuousIndex[1] == p[1]-origin[1]);
+ CPPUNIT_ASSERT(xAxisContinuousIndex[2] == p[2]-origin[2]);
+
+ //Test consictency for random vector
+ mitk::Vector3D vector;
+ mitk::FillVector3D(vector, 2.5,-3.2,8.1);
+ mitk::Vector3D vectorContinuousIndex;
+
+ p[0] = vector[0]+origin[0];
+ p[1] = vector[1]+origin[1];
+ p[2] = vector[2]+origin[2];
+
+ dummyGeometry->WorldToIndex(p,pIndex);
+
+ dummyGeometry->WorldToIndex(vector,vectorContinuousIndex);
+ CPPUNIT_ASSERT(vectorContinuousIndex[0] == pIndex[0]);
+ CPPUNIT_ASSERT(vectorContinuousIndex[1] == pIndex[1]);
+ CPPUNIT_ASSERT(vectorContinuousIndex[2] == pIndex[2]);
+
+ dummyGeometry->IndexToWorld(vectorContinuousIndex,vectorContinuousIndex);
+
+ dummyGeometry->IndexToWorld(pIndex,p);
+
+ CPPUNIT_ASSERT(vectorContinuousIndex == vector);
+ CPPUNIT_ASSERT(vectorContinuousIndex[0] == p[0]-origin[0]);
+ CPPUNIT_ASSERT(vectorContinuousIndex[1] == p[1]-origin[1]);
+ CPPUNIT_ASSERT(vectorContinuousIndex[2] == p[2]-origin[2]);
+
+ return EXIT_SUCCESS;
+ }
+
+ int testIndexAndWorldConsistencyForIndex(DummyTestClass* dummyGeometry)
+ {
+ //Testing consistency of index and world coordinate systems
+
+ // creating testing data
+ itk::Index<4> itkIndex4, itkIndex4b;
+ itk::Index<3> itkIndex3, itkIndex3b;
+ itk::Index<2> itkIndex2, itkIndex2b;
+ mitk::Index3D mitkIndex, mitkIndexb;
+
+ itkIndex4[0] = itkIndex4[1] = itkIndex4[2] = itkIndex4[3] = 4;
+ itkIndex3[0] = itkIndex3[1] = itkIndex3[2] = 6;
+ itkIndex2[0] = itkIndex2[1] = 2;
+ mitkIndex[0] = mitkIndex[1] = mitkIndex[2] = 13;
+
+ // check for constistency
+ mitk::Point3D point;
+ dummyGeometry->IndexToWorld(itkIndex2,point);
+ dummyGeometry->WorldToIndex(point,itkIndex2b);
+
+ CPPUNIT_ASSERT(
+ ((itkIndex2b[0] == itkIndex2[0]) &&
+ (itkIndex2b[1] == itkIndex2[1])));
+ //Testing itk::index<2> for IndexToWorld/WorldToIndex consistency
+
+ dummyGeometry->IndexToWorld(itkIndex3,point);
+ dummyGeometry->WorldToIndex(point,itkIndex3b);
+
+ CPPUNIT_ASSERT(
+ ((itkIndex3b[0] == itkIndex3[0]) &&
+ (itkIndex3b[1] == itkIndex3[1]) &&
+ (itkIndex3b[2] == itkIndex3[2])));
+ //Testing itk::index<3> for IndexToWorld/WorldToIndex consistency
+
+ dummyGeometry->IndexToWorld(itkIndex4,point);
+ dummyGeometry->WorldToIndex(point,itkIndex4b);
+
+ CPPUNIT_ASSERT(
+ ((itkIndex4b[0] == itkIndex4[0]) &&
+ (itkIndex4b[1] == itkIndex4[1]) &&
+ (itkIndex4b[2] == itkIndex4[2]) &&
+ (itkIndex4b[3] == 0)));
+ //Testing itk::index<3> for IndexToWorld/WorldToIndex consistency
+
+ dummyGeometry->IndexToWorld(mitkIndex,point);
+ dummyGeometry->WorldToIndex(point,mitkIndexb);
+
+ CPPUNIT_ASSERT(
+ ((mitkIndexb[0] == mitkIndex[0]) &&
+ (mitkIndexb[1] == mitkIndex[1]) &&
+ (mitkIndexb[2] == mitkIndex[2])));
+ //Testing mitk::Index for IndexToWorld/WorldToIndex consistency
+
+ return EXIT_SUCCESS;
+ }
+
+ void TestIndexToWorld(){
+ DummyTestClass::Pointer dummy = DummyTestClass::New();
+
+ testIndexAndWorldConsistency(dummy);
+ testIndexAndWorldConsistencyForVectors(dummy);
+ testIndexAndWorldConsistencyForIndex(dummy);
+
+ //Geometry must not have changed
+ DummyTestClass::Pointer newDummy = DummyTestClass::New();
+ CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true));
+
+ //Test with other geometries
+ dummy->SetOrigin(anotherPoint);
+ testIndexAndWorldConsistency(dummy);
+ testIndexAndWorldConsistencyForVectors(dummy);
+ testIndexAndWorldConsistencyForIndex(dummy);
+
+ dummy->SetIndexToWorldTransform(anotherTransform);
+ testIndexAndWorldConsistency(dummy);
+ testIndexAndWorldConsistencyForVectors(dummy);
+ testIndexAndWorldConsistencyForIndex(dummy);
+
+ dummy->SetOrigin(anotherPoint);
+ testIndexAndWorldConsistency(dummy);
+ testIndexAndWorldConsistencyForVectors(dummy);
+ testIndexAndWorldConsistencyForIndex(dummy);
+
+ dummy->SetSpacing(anotherSpacing);
+ testIndexAndWorldConsistency(dummy);
+ testIndexAndWorldConsistencyForVectors(dummy);
+ testIndexAndWorldConsistencyForIndex(dummy);
+ }
+
+ void TestExecuteOperation(){
+ DummyTestClass::Pointer dummy = DummyTestClass::New();
+
+ //Do same Operations with new Dummy and compare
+ DummyTestClass::Pointer newDummy = DummyTestClass::New();
+
+ //Test operation Nothing
+ mitk::Operation* opN = new mitk::Operation(mitk::OpNOTHING);
+ dummy->ExecuteOperation(opN);
+ CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true));
+
+ //Test operation Move
+ mitk::PointOperation* opP = new mitk::PointOperation(mitk::OpMOVE,anotherPoint);
+ dummy->ExecuteOperation(opP);
+ CPPUNIT_ASSERT(anotherPoint==dummy->GetOrigin());
+ newDummy->SetOrigin(anotherPoint);
+ CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true));
+
+ //Test operation Scale, Scale sets spacing to scale+1
+ mitk::Point3D spacing;
+ spacing[0]=anotherSpacing[0]-1.;
+ spacing[1]=anotherSpacing[1]-1.;
+ spacing[2]=anotherSpacing[2]-1.;
+
+ mitk::PointOperation* opS = new mitk::PointOperation(mitk::OpSCALE,spacing);
+ dummy->ExecuteOperation(opS);
+ CPPUNIT_ASSERT(anotherSpacing==dummy->GetSpacing());
+ newDummy->SetSpacing(anotherSpacing);
+ CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true));
+
+ //change Geometry to test more cases
+ dummy->SetIndexToWorldTransform(anotherTransform);
+ dummy->SetSpacing(anotherSpacing);
+
+ //Testing a rotation of the geometry
+ double angle = 35.0;
+ mitk::Vector3D rotationVector; mitk::FillVector3D( rotationVector, 1, 0, 0 );
+ mitk::Point3D center = dummy->GetCenter();
+ mitk::RotationOperation* opR = new mitk::RotationOperation( mitk::OpROTATE, center, rotationVector, angle );
+ dummy->ExecuteOperation(opR);
+
+ mitk::Matrix3D rotation;
+ mitk::GetRotation(dummy, rotation);
+ mitk::Vector3D voxelStep=rotation*anotherSpacing;
+ mitk::Vector3D voxelStepIndex;
+ dummy->WorldToIndex(voxelStep, voxelStepIndex);
+ mitk::Vector3D expectedVoxelStepIndex;
+ expectedVoxelStepIndex.Fill(1);
+ CPPUNIT_ASSERT(mitk::Equal(voxelStepIndex,expectedVoxelStepIndex));
+
+ delete opR, opN, opS, opP;
+ }
+
+ void TestCalculateBoundingBoxRelToTransform(){
+ DummyTestClass::Pointer dummy = DummyTestClass::New();
+ dummy->SetExtentInMM(0,15);
+ dummy->SetExtentInMM(1,20);
+ dummy->SetExtentInMM(2,8);
+
+ mitk::BoundingBox::Pointer dummyBoundingBox = dummy->CalculateBoundingBoxRelativeToTransform(anotherTransform);
+
+ mitk::BoundingBox::PointsContainer::Pointer pointscontainer=mitk::BoundingBox::PointsContainer::New();
+ mitk::BoundingBox::PointIdentifier pointid=0;
+ unsigned char i;
+ mitk::AffineTransform3D::Pointer inverse = mitk::AffineTransform3D::New();
+ anotherTransform->GetInverse(inverse);
+ for(i=0; i<8; ++i)
+ pointscontainer->InsertElement( pointid++, inverse->TransformPoint( dummy->GetCornerPoint(i) ));
+ mitk::BoundingBox::Pointer result = mitk::BoundingBox::New();
+ result->SetPoints(pointscontainer);
+ result->ComputeBoundingBox();
+
+ CPPUNIT_ASSERT(mitk::Equal(result,dummyBoundingBox,mitk::eps,true));
+
+ //dummy still needs to be unchanged, except for extend
+ DummyTestClass::Pointer newDummy = DummyTestClass::New();
+ newDummy->SetExtentInMM(0,15);
+ newDummy->SetExtentInMM(1,20);
+ newDummy->SetExtentInMM(2,8);
+ CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true));
+ }
+
+ //void TestSetTimeBounds(){
+ // mitk::TimeBounds timeBounds;
+ // timeBounds[0] = 1;
+ // timeBounds[1] = 9;
+
+ // DummyTestClass::Pointer dummy = DummyTestClass::New();
+ // dummy->SetTimeBounds(timeBounds);
+ // mitk::TimeBounds timeBounds2 = dummy->GetTimeBounds();
+
+ // CPPUNIT_ASSERT(timeBounds[0]==timeBounds2[0]);
+ // CPPUNIT_ASSERT(timeBounds[1]==timeBounds2[1]);
+
+ // //undo changes, new and changed object need to be the same!
+ // timeBounds[0]=mitk::ScalarTypeNumericTraits::NonpositiveMin();
+ // timeBounds[1]=mitk::ScalarTypeNumericTraits::max();
+
+ // DummyTestClass::Pointer newDummy = DummyTestClass::New();
+ // CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true));
+ //}
+
+ void TestIs2DConvertable(){
+ DummyTestClass::Pointer dummy = DummyTestClass::New();
+
+ //new initialized geometry is 2D convertable
+ CPPUNIT_ASSERT(dummy->Is2DConvertable());
+
+ //Wrong Spacing needs to fail
+ dummy->SetSpacing(anotherSpacing);
+ CPPUNIT_ASSERT(dummy->Is2DConvertable()==false);
+ //undo
+ dummy->SetSpacing(aSpacing);
+ CPPUNIT_ASSERT(dummy->Is2DConvertable());
+
+ //Wrong Origin needs to fail
+ dummy->SetOrigin(anotherPoint);
+ CPPUNIT_ASSERT(dummy->Is2DConvertable()==false);
+ //undo
+ dummy->SetOrigin(aPoint);
+ CPPUNIT_ASSERT(dummy->Is2DConvertable());
+
+ //third dimension must not be transformed
+ mitk::AffineTransform3D::Pointer dummyTransform = mitk::AffineTransform3D::New();
+ mitk::AffineTransform3D::MatrixType dummyMatrix;
+ dummyMatrix.SetIdentity();
+ dummyTransform->SetMatrix( dummyMatrix );
+ dummy->SetIndexToWorldTransform(dummyTransform);
+
+ //identity matrix is 2DConvertable
+ CPPUNIT_ASSERT(dummy->Is2DConvertable());
+
+ dummyMatrix(0,2) = 3;
+ dummyTransform->SetMatrix( dummyMatrix );
+ CPPUNIT_ASSERT(dummy->Is2DConvertable()==false);
+
+ dummyMatrix.SetIdentity();
+ dummyMatrix(1,2) = 0.4;
+ dummyTransform->SetMatrix( dummyMatrix );
+ CPPUNIT_ASSERT(dummy->Is2DConvertable()==false);
+
+ dummyMatrix.SetIdentity();
+ dummyMatrix(2,2) = 3;
+ dummyTransform->SetMatrix( dummyMatrix );
+ CPPUNIT_ASSERT(dummy->Is2DConvertable()==false);
+
+ dummyMatrix.SetIdentity();
+ dummyMatrix(2,1) = 3;
+ dummyTransform->SetMatrix( dummyMatrix );
+ CPPUNIT_ASSERT(dummy->Is2DConvertable()==false);
+
+ dummyMatrix.SetIdentity();
+ dummyMatrix(2,0) = 3;
+ dummyTransform->SetMatrix( dummyMatrix );
+ CPPUNIT_ASSERT(dummy->Is2DConvertable()==false);
+
+ //undo changes, new and changed object need to be the same!
+ dummyMatrix.SetIdentity();
+ dummyTransform->SetMatrix( dummyMatrix );
+ DummyTestClass::Pointer newDummy = DummyTestClass::New();
+ CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true));
+ }
+
+ void TestGetCornerPoint(){
+ DummyTestClass::Pointer dummy = DummyTestClass::New();
+ dummy->SetIndexToWorldTransform(anotherTransform);
+ double bounds[6] = {0,11,0,12,0,13};
+ dummy->SetFloatBounds(bounds);
+
+ mitk::Point3D corner, refCorner;
+
+ //Corner 0
+ mitk::FillVector3D(refCorner,bounds[0],bounds[2],bounds[4]);
+ refCorner = anotherTransform->TransformPoint(refCorner);
+ corner=dummy->GetCornerPoint(0);
+ CPPUNIT_ASSERT(refCorner==corner);
+ corner=dummy->GetCornerPoint(true,true,true);
+ CPPUNIT_ASSERT(refCorner==corner);
+
+ //Corner 1
+ mitk::FillVector3D(refCorner,bounds[0],bounds[2],bounds[5]);
+ refCorner = anotherTransform->TransformPoint(refCorner);
+ corner=dummy->GetCornerPoint(1);
+ CPPUNIT_ASSERT(refCorner==corner);
+ corner=dummy->GetCornerPoint(true,true,false);
+ CPPUNIT_ASSERT(refCorner==corner);
+
+ //Corner 2
+ mitk::FillVector3D(refCorner,bounds[0],bounds[3],bounds[4]);
+ refCorner = anotherTransform->TransformPoint(refCorner);
+ corner=dummy->GetCornerPoint(2);
+ CPPUNIT_ASSERT(refCorner==corner);
+ corner=dummy->GetCornerPoint(true,false,true);
+ CPPUNIT_ASSERT(refCorner==corner);
+
+ //Corner 3
+ mitk::FillVector3D(refCorner,bounds[0],bounds[3],bounds[5]);
+ refCorner = anotherTransform->TransformPoint(refCorner);
+ corner=dummy->GetCornerPoint(3);
+ CPPUNIT_ASSERT(refCorner==corner);
+ corner=dummy->GetCornerPoint(true,false,false);
+ CPPUNIT_ASSERT(refCorner==corner);
+
+ //Corner 4
+ mitk::FillVector3D(refCorner,bounds[1],bounds[2],bounds[4]);
+ refCorner = anotherTransform->TransformPoint(refCorner);
+ corner=dummy->GetCornerPoint(4);
+ CPPUNIT_ASSERT(refCorner==corner);
+ corner=dummy->GetCornerPoint(false,true,true);
+ CPPUNIT_ASSERT(refCorner==corner);
+
+ //Corner 5
+ mitk::FillVector3D(refCorner,bounds[1],bounds[2],bounds[5]);
+ refCorner = anotherTransform->TransformPoint(refCorner);
+ corner=dummy->GetCornerPoint(5);
+ CPPUNIT_ASSERT(refCorner==corner);
+ corner=dummy->GetCornerPoint(false,true,false);
+ CPPUNIT_ASSERT(refCorner==corner);
+
+ //Corner 6
+ mitk::FillVector3D(refCorner,bounds[1],bounds[3],bounds[4]);
+ refCorner = anotherTransform->TransformPoint(refCorner);
+ corner=dummy->GetCornerPoint(6);
+ CPPUNIT_ASSERT(refCorner==corner);
+ corner=dummy->GetCornerPoint(false,false,true);
+ CPPUNIT_ASSERT(refCorner==corner);
+
+ //Corner 7
+ mitk::FillVector3D(refCorner,bounds[1],bounds[3],bounds[5]);
+ refCorner = anotherTransform->TransformPoint(refCorner);
+ corner=dummy->GetCornerPoint(7);
+ CPPUNIT_ASSERT(refCorner==corner);
+ corner=dummy->GetCornerPoint(false,false,false);
+ CPPUNIT_ASSERT(refCorner==corner);
+
+ //Wrong Corner needs to fail
+ CPPUNIT_ASSERT_THROW(dummy->GetCornerPoint(-1),itk::ExceptionObject);
+
+ //dummy geometry must not have changed!
+ DummyTestClass::Pointer newDummy = DummyTestClass::New();
+ newDummy->SetIndexToWorldTransform(anotherTransform);
+ newDummy->SetFloatBounds(bounds);
+ CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true));
+ }
+
+ void TestExtentInMM()
+ {
+ DummyTestClass::Pointer dummy = DummyTestClass::New();
+ dummy->SetExtentInMM(0,50);
+ CPPUNIT_ASSERT(50==dummy->GetExtentInMM(0));
+ //Vnl Matrix has changed. The next line only works because the spacing is 1!
+ CPPUNIT_ASSERT(50==dummy->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(0).magnitude());
+
+ //Smaller extent than original
+ dummy->SetExtentInMM(0,5);
+ CPPUNIT_ASSERT(5==dummy->GetExtentInMM(0));
+ CPPUNIT_ASSERT(5==dummy->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(0).magnitude());
+
+ dummy->SetExtentInMM(1,4);
+ CPPUNIT_ASSERT(4==dummy->GetExtentInMM(1));
+ CPPUNIT_ASSERT(4==dummy->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(1).magnitude());
+
+ dummy->SetExtentInMM(2,2.5);
+ CPPUNIT_ASSERT(2.5==dummy->GetExtentInMM(2));
+ CPPUNIT_ASSERT(2.5==dummy->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(2).magnitude());
+ }
+
+ void TestGetAxisVector(){
+ DummyTestClass::Pointer dummy = DummyTestClass::New();
+ dummy->SetIndexToWorldTransform(anotherTransform);
+ double bounds[6] = {0,11,0,12,0,13};
+ dummy->SetFloatBounds(bounds);
+
+ mitk::Vector3D vector;
+ mitk::FillVector3D(vector,bounds[1],0,0);
+ dummy->IndexToWorld(vector,vector);
+ CPPUNIT_ASSERT(dummy->GetAxisVector(0)==vector);
+
+ mitk::FillVector3D(vector,0,bounds[3],0);
+ dummy->IndexToWorld(vector,vector);
+ CPPUNIT_ASSERT(dummy->GetAxisVector(1)==vector);
+
+ mitk::FillVector3D(vector,0,0,bounds[5]);
+ dummy->IndexToWorld(vector,vector);
+ CPPUNIT_ASSERT(dummy->GetAxisVector(2)==vector);
+ }
+
+ void TestGetCenter(){
+ DummyTestClass::Pointer dummy = DummyTestClass::New();
+ dummy->SetIndexToWorldTransform(anotherTransform);
+ double bounds[6] = {0,11,2,12,1,13};
+ dummy->SetFloatBounds(bounds);
+
+ mitk::Point3D refCenter;
+ for( int i=0;i<3;i++)
+ refCenter.SetElement(i,( bounds[2 * i] + bounds[2 * i + 1] ) / 2.0);
+
+ dummy->IndexToWorld(refCenter,refCenter);
+
+ CPPUNIT_ASSERT(dummy->GetCenter()==refCenter);
+ }
+
+ void TestGetDiagonalLength(){
+ DummyTestClass::Pointer dummy = DummyTestClass::New();
+ double bounds[6] = {1,3,5,8,7.5,11.5};
+ dummy->SetFloatBounds(bounds);
+ //3-1=2, 8-5=3, 11.5-7.5=4; 2^2+3^2+4^2 = 29
+ double expectedLength = sqrt(29.);
+
+ CPPUNIT_ASSERT(expectedLength==dummy->GetDiagonalLength());
+ CPPUNIT_ASSERT(29==dummy->GetDiagonalLength2());
+
+ //dummy must not have changed
+ DummyTestClass::Pointer newDummy = DummyTestClass::New();
+ newDummy->SetFloatBounds(bounds);
+ CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true));
+ }
+
+ void TestGetExtent(){
+ DummyTestClass::Pointer dummy = DummyTestClass::New();
+ double bounds[6] = {1,3,5,8,7.5,11.5};
+ dummy->SetFloatBounds(bounds);
+
+ CPPUNIT_ASSERT(2==dummy->GetExtent(0));
+ CPPUNIT_ASSERT(3==dummy->GetExtent(1));
+ CPPUNIT_ASSERT(4==dummy->GetExtent(2));
+
+ //dummy must not have changed
+ DummyTestClass::Pointer newDummy = DummyTestClass::New();
+ newDummy->SetFloatBounds(bounds);
+ CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true));
+ }
+
+ void TestIsInside(){
+ DummyTestClass::Pointer dummy = DummyTestClass::New();
+ double bounds[6] = {1,3,5,8,7.5,11.5};
+ dummy->SetFloatBounds(bounds);
+
+ mitk::Point3D insidePoint;
+ mitk::Point3D outsidePoint;
+
+ mitk::FillVector3D(insidePoint,2,6,7.6);
+ mitk::FillVector3D(outsidePoint,0,9,8.2);
+
+ CPPUNIT_ASSERT(dummy->IsIndexInside(insidePoint));
+ CPPUNIT_ASSERT(false==dummy->IsIndexInside(outsidePoint));
+
+ dummy->IndexToWorld(insidePoint,insidePoint);
+ dummy->IndexToWorld(outsidePoint,outsidePoint);
+
+ CPPUNIT_ASSERT(dummy->IsInside(insidePoint));
+ CPPUNIT_ASSERT(false==dummy->IsInside(outsidePoint));
+
+ //dummy must not have changed
+ DummyTestClass::Pointer newDummy = DummyTestClass::New();
+ newDummy->SetFloatBounds(bounds);
+ CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true));
+ }
+
+ void TestInitialize()
+ {
+ //test standard constructor
+ DummyTestClass::Pointer dummy1 = DummyTestClass::New();
+
+ DummyTestClass::Pointer dummy2 = DummyTestClass::New();
+ dummy2->SetOrigin(anotherPoint);
+ dummy2->SetBounds(anotherBoundingBox->GetBounds());
+ //mitk::TimeBounds timeBounds;
+ //timeBounds[0] = 1;
+ //timeBounds[1] = 9;
+ //dummy2->SetTimeBounds(timeBounds);
+ dummy2->SetIndexToWorldTransform(anotherTransform);
+ dummy2->SetSpacing(anotherSpacing);
+
+ dummy1->InitializeGeometry(dummy2);
+
+ CPPUNIT_ASSERT(mitk::Equal(dummy1,dummy2,mitk::eps,true));
+
+ dummy1->Initialize();
+
+ DummyTestClass::Pointer dummy3 = DummyTestClass::New();
+ CPPUNIT_ASSERT(mitk::Equal(dummy3,dummy1,mitk::eps,true));
+ }
+
+ void TestGetMatrixColumn(){
+ DummyTestClass::Pointer dummy = DummyTestClass::New();
+ dummy->SetIndexToWorldTransform(anotherTransform);
+ mitk::Vector3D testVector,refVector;
+
+ testVector.SetVnlVector(dummy->GetMatrixColumn(0));
+ mitk::FillVector3D(refVector,1,0,0);
+ CPPUNIT_ASSERT(testVector==refVector);
+
+ testVector.SetVnlVector(dummy->GetMatrixColumn(1));
+ mitk::FillVector3D(refVector,0,2,0);
+ CPPUNIT_ASSERT(testVector==refVector);
+
+ testVector.SetVnlVector(dummy->GetMatrixColumn(2));
+ mitk::FillVector3D(refVector,0,0,1);
+ CPPUNIT_ASSERT(testVector==refVector);
+
+ //dummy must not have changed
+ DummyTestClass::Pointer newDummy = DummyTestClass::New();
+ newDummy->SetIndexToWorldTransform(anotherTransform);
+ CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true));
+ }
+
+ /*
+
+ void (){
+ DummyTestClass::Pointer dummy = DummyTestClass::New();
+
+ CPPUNIT_ASSERT();
+
+ //undo changes, new and changed object need to be the same!
+
+ DummyTestClass::Pointer newDummy = DummyTestClass::New();
+ CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true));
+ }
+
+ */
+};//end class mitkBaseGeometryTestSuite
+
+MITK_TEST_SUITE_REGISTRATION(mitkBaseGeometry)
diff --git a/Core/Code/Testing/mitkClippedSurfaceBoundsCalculatorTest.cpp b/Core/Code/Testing/mitkClippedSurfaceBoundsCalculatorTest.cpp
index 13d97a5ff8..186dbda875 100644
--- a/Core/Code/Testing/mitkClippedSurfaceBoundsCalculatorTest.cpp
+++ b/Core/Code/Testing/mitkClippedSurfaceBoundsCalculatorTest.cpp
@@ -1,484 +1,484 @@
/*===================================================================
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 "mitkTestingMacros.h"
#include <iostream>
#include "mitkClippedSurfaceBoundsCalculator.h"
#include "mitkGeometry3D.h"
-#include "mitkGeometry2D.h"
+#include "mitkPlaneGeometry.h"
#include "mitkVector.h"
-static void CheckPlanesInsideBoundingBoxOnlyOnOneSlice(mitk::Geometry3D::Pointer geometry3D)
+static void CheckPlanesInsideBoundingBoxOnlyOnOneSlice(mitk::BaseGeometry::Pointer geometry3D)
{
//Check planes which are inside the bounding box
mitk::ClippedSurfaceBoundsCalculator* calculator = new mitk::ClippedSurfaceBoundsCalculator();
mitk::Image::Pointer image = mitk::Image::New();
image->Initialize( mitk::MakePixelType<int, int, 1>(), *(geometry3D.GetPointer()) );
//Check planes which are only on one slice:
//Slice 0
mitk::Point3D origin;
origin[0] = 511;
origin[1] = 0;
origin[2] = 0;
mitk::Vector3D normal;
mitk::FillVector3D(normal, 0, 0, 1);
mitk::PlaneGeometry::Pointer planeOnSliceZero = mitk::PlaneGeometry::New();
planeOnSliceZero->InitializePlane(origin, normal);
calculator->SetInput( planeOnSliceZero , image);
calculator->Update();
mitk::ClippedSurfaceBoundsCalculator::OutputType minMax = calculator->GetMinMaxSpatialDirectionZ();
MITK_TEST_CONDITION(minMax.first == minMax.second, "Check if plane is only on one slice");
MITK_TEST_CONDITION(minMax.first == 0 && minMax.second == 0, "Check if plane is on slice 0");
//Slice 3
origin[2] = 3;
mitk::PlaneGeometry::Pointer planeOnSliceThree = mitk::PlaneGeometry::New();
planeOnSliceThree->InitializePlane(origin, normal);
planeOnSliceThree->SetImageGeometry(false);
calculator->SetInput( planeOnSliceThree , image);
calculator->Update();
minMax = calculator->GetMinMaxSpatialDirectionZ();
MITK_TEST_CONDITION(minMax.first == minMax.second, "Check if plane is only on one slice");
MITK_TEST_CONDITION(minMax.first == 3 && minMax.second == 3, "Check if plane is on slice 3");
//Slice 17
origin[2] = 17;
mitk::PlaneGeometry::Pointer planeOnSliceSeventeen = mitk::PlaneGeometry::New();
planeOnSliceSeventeen->InitializePlane(origin, normal);
calculator->SetInput( planeOnSliceSeventeen , image);
calculator->Update();
minMax = calculator->GetMinMaxSpatialDirectionZ();
MITK_TEST_CONDITION(minMax.first == minMax.second, "Check if plane is only on one slice");
MITK_TEST_CONDITION(minMax.first == 17 && minMax.second == 17, "Check if plane is on slice 17");
//Slice 20
origin[2] = 19;
mitk::PlaneGeometry::Pointer planeOnSliceTwenty = mitk::PlaneGeometry::New();
planeOnSliceTwenty->InitializePlane(origin, normal);
calculator->SetInput( planeOnSliceTwenty , image);
calculator->Update();
minMax = calculator->GetMinMaxSpatialDirectionZ();
MITK_TEST_CONDITION(minMax.first == minMax.second, "Check if plane is only on one slice");
MITK_TEST_CONDITION(minMax.first == 19 && minMax.second == 19, "Check if plane is on slice 19");
delete calculator;
}
-static void CheckPlanesInsideBoundingBox(mitk::Geometry3D::Pointer geometry3D)
+static void CheckPlanesInsideBoundingBox(mitk::BaseGeometry::Pointer geometry3D)
{
//Check planes which are inside the bounding box
mitk::ClippedSurfaceBoundsCalculator* calculator = new mitk::ClippedSurfaceBoundsCalculator();
mitk::Image::Pointer image = mitk::Image::New();
image->Initialize( mitk::MakePixelType<int, int, 1>(), *(geometry3D.GetPointer()) );
//Check planes which are only on one slice:
//Slice 0
mitk::Point3D origin;
origin[0] = 511; // Set to 511.9 so that the intersection point is inside the bounding box
origin[1] = 0;
origin[2] = 0;
mitk::Vector3D normal;
mitk::FillVector3D(normal, 1, 0, 0);
mitk::PlaneGeometry::Pointer planeSagittalOne = mitk::PlaneGeometry::New();
planeSagittalOne->InitializePlane(origin, normal);
calculator->SetInput( planeSagittalOne , image);
calculator->Update();
mitk::ClippedSurfaceBoundsCalculator::OutputType minMax = calculator->GetMinMaxSpatialDirectionZ();
MITK_TEST_CONDITION(minMax.first == 0 && minMax.second == 19, "Check if plane is from slice 0 to slice 19");
//Slice 3
origin[0] = 256;
MITK_INFO << "Case1 origin: " << origin;
mitk::PlaneGeometry::Pointer planeSagittalTwo = mitk::PlaneGeometry::New();
planeSagittalTwo->InitializePlane(origin, normal);
MITK_INFO << "PlaneNormal: " << planeSagittalTwo->GetNormal();
MITK_INFO << "PlaneOrigin: " << planeSagittalTwo->GetOrigin();
calculator->SetInput( planeSagittalTwo , image);
calculator->Update();
minMax = calculator->GetMinMaxSpatialDirectionZ();
MITK_INFO << "min: " << minMax.first << " max: " << minMax.second;
MITK_TEST_CONDITION(minMax.first == 0 && minMax.second == 19, "Check if plane is from slice 0 to slice 19");
//Slice 17
origin[0] = 0; // Set to 0.1 so that the intersection point is inside the bounding box
mitk::PlaneGeometry::Pointer planeOnSliceSeventeen = mitk::PlaneGeometry::New();
planeOnSliceSeventeen->InitializePlane(origin, normal);
calculator->SetInput( planeOnSliceSeventeen , image);
calculator->Update();
minMax = calculator->GetMinMaxSpatialDirectionZ();
MITK_TEST_CONDITION(minMax.first == 0 && minMax.second == 19, "Check if plane is from slice 0 to slice 19");
//Crooked planes:
origin[0] = 0;
origin[1] = 507;
origin[2] = 0;
normal[0] = 1;
normal[1] = -1;
normal[2] = 1;
mitk::PlaneGeometry::Pointer planeCrookedOne = mitk::PlaneGeometry::New();
planeCrookedOne->InitializePlane(origin, normal);
calculator->SetInput( planeCrookedOne , image);
calculator->Update();
minMax = calculator->GetMinMaxSpatialDirectionZ();
MITK_INFO << "min: " << minMax.first << " max: " << minMax.second;
MITK_TEST_CONDITION(minMax.first == 0 && minMax.second == 4, "Check if plane is from slice 0 to slice 4 with inclined plane");
origin[0] = 512;
origin[1] = 0;
origin[2] = 16;
mitk::PlaneGeometry::Pointer planeCrookedTwo = mitk::PlaneGeometry::New();
planeCrookedTwo->InitializePlane(origin, normal);
calculator->SetInput( planeCrookedTwo , image);
calculator->Update();
minMax = calculator->GetMinMaxSpatialDirectionZ();
MITK_INFO << "min: " << minMax.first << " max: " << minMax.second;
MITK_TEST_CONDITION(minMax.first == 17 && minMax.second == 19, "Check if plane is from slice 17 to slice 19 with inclined plane");
origin[0] = 511;
origin[1] = 0;
origin[2] = 0;
normal[1] = 0;
normal[2] = 0.04;
mitk::PlaneGeometry::Pointer planeCrookedThree = mitk::PlaneGeometry::New();
planeCrookedThree->InitializePlane(origin, normal);
calculator->SetInput( planeCrookedThree , image);
calculator->Update();
minMax = calculator->GetMinMaxSpatialDirectionZ();
MITK_INFO << "min: " << minMax.first << " max: " << minMax.second;
MITK_TEST_CONDITION(minMax.first == 0 && minMax.second == 19, "Check if plane is from slice 0 to slice 19 with inclined plane");
delete calculator;
}
-static void CheckPlanesOutsideOfBoundingBox(mitk::Geometry3D::Pointer geometry3D)
+static void CheckPlanesOutsideOfBoundingBox(mitk::BaseGeometry::Pointer geometry3D)
{
//Check planes which are outside of the bounding box
mitk::ClippedSurfaceBoundsCalculator* calculator = new mitk::ClippedSurfaceBoundsCalculator();
mitk::Image::Pointer image = mitk::Image::New();
image->Initialize( mitk::MakePixelType<int, int, 1>(), *(geometry3D.GetPointer()) );
//In front of the bounding box
mitk::Point3D origin;
origin[0] = 511;
origin[1] = 0;
origin[2] = -5;
mitk::Vector3D normal;
mitk::FillVector3D(normal, 0, 0, 1);
mitk::PlaneGeometry::Pointer planeInFront = mitk::PlaneGeometry::New();
planeInFront->InitializePlane(origin, normal);
calculator->SetInput( planeInFront , image);
calculator->Update();
mitk::ClippedSurfaceBoundsCalculator::OutputType minMax = calculator->GetMinMaxSpatialDirectionZ();
MITK_TEST_CONDITION(minMax.first == std::numeric_limits<int>::max(), "Check if min value hasn't been set");
MITK_TEST_CONDITION(minMax.second == std::numeric_limits<int>::min(), "Check if max value hasn't been set");
//Behind the bounding box
origin[2] = 515;
mitk::PlaneGeometry::Pointer planeBehind = mitk::PlaneGeometry::New();
planeBehind->InitializePlane(origin, normal);
calculator->SetInput( planeBehind , image);
calculator->Update();
minMax = calculator->GetMinMaxSpatialDirectionZ();
MITK_TEST_CONDITION(minMax.first == std::numeric_limits<int>::max(), "Check if min value hasn't been set");
MITK_TEST_CONDITION(minMax.second == std::numeric_limits<int>::min(), "Check if max value hasn't been set");
//Above
origin[1] = 515;
mitk::FillVector3D(normal, 0, 1, 0);
mitk::PlaneGeometry::Pointer planeAbove = mitk::PlaneGeometry::New();
planeAbove->InitializePlane(origin, normal);
calculator->SetInput( planeAbove , image);
calculator->Update();
minMax = calculator->GetMinMaxSpatialDirectionZ();
MITK_TEST_CONDITION(minMax.first == std::numeric_limits<int>::max(), "Check if min value hasn't been set");
MITK_TEST_CONDITION(minMax.second == std::numeric_limits<int>::min(), "Check if max value hasn't been set");
//Below
origin[1] = -5;
mitk::PlaneGeometry::Pointer planeBelow = mitk::PlaneGeometry::New();
planeBelow->InitializePlane(origin, normal);
calculator->SetInput( planeBelow , image);
calculator->Update();
minMax = calculator->GetMinMaxSpatialDirectionZ();
MITK_TEST_CONDITION(minMax.first == std::numeric_limits<int>::max(), "Check if min value hasn't been set");
MITK_TEST_CONDITION(minMax.second == std::numeric_limits<int>::min(), "Check if max value hasn't been set");
//Left side
origin[0] = -5;
mitk::FillVector3D(normal, 1, 0, 0);
mitk::PlaneGeometry::Pointer planeLeftSide = mitk::PlaneGeometry::New();
planeLeftSide->InitializePlane(origin, normal);
calculator->SetInput( planeLeftSide , image);
calculator->Update();
minMax = calculator->GetMinMaxSpatialDirectionZ();
MITK_TEST_CONDITION(minMax.first == std::numeric_limits<int>::max(), "Check if min value hasn't been set");
MITK_TEST_CONDITION(minMax.second == std::numeric_limits<int>::min(), "Check if max value hasn't been set");
//Right side
origin[1] = 515;
mitk::PlaneGeometry::Pointer planeRightSide = mitk::PlaneGeometry::New();
planeRightSide->InitializePlane(origin, normal);
calculator->SetInput( planeRightSide , image);
calculator->Update();
minMax = calculator->GetMinMaxSpatialDirectionZ();
MITK_TEST_CONDITION(minMax.first == std::numeric_limits<int>::max(), "Check if min value hasn't been set");
MITK_TEST_CONDITION(minMax.second == std::numeric_limits<int>::min(), "Check if max value hasn't been set");
delete calculator;
}
-static void CheckIntersectionPointsOfTwoGeometry3D(mitk::Geometry3D::Pointer firstGeometry3D, mitk::Geometry3D::Pointer secondGeometry3D)
+static void CheckIntersectionPointsOfTwoGeometry3D(mitk::BaseGeometry::Pointer firstGeometry3D, mitk::BaseGeometry::Pointer secondGeometry3D)
{
mitk::ClippedSurfaceBoundsCalculator* calculator = new mitk::ClippedSurfaceBoundsCalculator();
mitk::Image::Pointer firstImage = mitk::Image::New();
firstImage->Initialize( mitk::MakePixelType<int, int, 1>(), *(firstGeometry3D.GetPointer()) );
calculator->SetInput( secondGeometry3D, firstImage);
calculator->Update();
mitk::ClippedSurfaceBoundsCalculator::OutputType minMax = calculator->GetMinMaxSpatialDirectionZ();
minMax = calculator->GetMinMaxSpatialDirectionZ();
MITK_INFO << "min: " << minMax.first << " max: " << minMax.second;
MITK_TEST_CONDITION(minMax.first == 0 && minMax.second == 19, "Check if plane is from slice 0 to slice 19");
}
-static void CheckIntersectionWithPointCloud( mitk::Geometry3D::Pointer geometry3D )
+static void CheckIntersectionWithPointCloud( mitk::BaseGeometry::Pointer geometry3D )
{
//Check planes which are inside the bounding box
mitk::Image::Pointer image = mitk::Image::New();
image->Initialize( mitk::MakePixelType<int, int, 1>(), *(geometry3D.GetPointer()) );
{
mitk::Point3D pnt1, pnt2;
pnt1[0] = 3;
pnt1[1] = 5;
pnt1[2] = 3;
pnt2[0] = 8;
pnt2[1] = 3;
pnt2[2] = 8;
mitk::ClippedSurfaceBoundsCalculator::PointListType pointlist;
pointlist.push_back( pnt1 );
pointlist.push_back( pnt2 );
mitk::ClippedSurfaceBoundsCalculator calculator;
calculator.SetInput( pointlist, image );
calculator.Update();
mitk::ClippedSurfaceBoundsCalculator::OutputType minMaxZ = calculator.GetMinMaxSpatialDirectionZ();
MITK_TEST_CONDITION(minMaxZ.first == 3 && minMaxZ.second == 8, "Check if points span from slice 3 to slice 8 in axial");
mitk::ClippedSurfaceBoundsCalculator::OutputType minMaxX = calculator.GetMinMaxSpatialDirectionX();
MITK_TEST_CONDITION(minMaxX.first == 3 && minMaxX.second == 5, "Check if points span from slice 3 to slice 5 in sagittal");
}
{
mitk::Point3D pnt1, pnt2;
pnt1.Fill( -3 );
pnt2.Fill( 600 );
mitk::ClippedSurfaceBoundsCalculator::PointListType pointlist;
pointlist.push_back( pnt1 );
pointlist.push_back( pnt2 );
mitk::ClippedSurfaceBoundsCalculator calculator;
calculator.SetInput( pointlist, image );
calculator.Update();
mitk::ClippedSurfaceBoundsCalculator::OutputType minMaxZ = calculator.GetMinMaxSpatialDirectionZ();
MITK_TEST_CONDITION(minMaxZ.first == 0 && minMaxZ.second == 19, "Check if points are correctly clipped to slice 0 and slice 19 in axial");
mitk::ClippedSurfaceBoundsCalculator::OutputType minMaxX = calculator.GetMinMaxSpatialDirectionX();
MITK_TEST_CONDITION(minMaxX.first == 0 && minMaxX.second == 511, "Check if points are correctly clipped to slice 0 and slice 511 in sagittal");
}
}
int mitkClippedSurfaceBoundsCalculatorTest(int, char* [])
{
// always start with this!
MITK_TEST_BEGIN("ClippedSurfaceBoundsCalculator");
/** The class mitkClippedSurfaceBoundsCalculator calculates the intersection points of a PlaneGeometry and a Geometry3D.
* This unittest checks if the correct min and max values for the three spatial directions (x, y, z)
* are calculated. To test this we define artifical PlaneGeometries and Geometry3Ds and test different
* scenarios:
*
* 1. planes which are inside the bounding box of a 3D geometry but only on one slice
* 2. planes which are outside of the bounding box
* 3. planes which are inside the bounding box but over more than one slice
*
* Note: Currently rotated geometries are not tested!
*/
/********************* Define Geometry3D ***********************/
//Define origin:
mitk::Point3D origin;
origin[0] = 511;
origin[1] = 0;
origin[2] = 0;
//Define normal:
mitk::Vector3D normal;
mitk::FillVector3D(normal, 0, 0, 1);
//Initialize PlaneGeometry:
mitk::PlaneGeometry::Pointer planeGeometry = mitk::PlaneGeometry::New();
planeGeometry->InitializePlane(origin, normal);
//Set Bounds:
mitk::BoundingBox::BoundsArrayType bounds = planeGeometry->GetBounds();
bounds[0] = 0;
bounds[1] = 512;
bounds[2] = 0;
bounds[3] = 512;
bounds[4] = 0;
bounds[5] = 1;
planeGeometry->SetBounds(bounds);
//Initialize SlicedGeometry3D:
mitk::SlicedGeometry3D::Pointer slicedGeometry3D = mitk::SlicedGeometry3D::New();
- slicedGeometry3D->InitializeEvenlySpaced(dynamic_cast<mitk::Geometry2D*>(planeGeometry.GetPointer()), 20);
- mitk::Geometry3D::Pointer geometry3D = dynamic_cast< mitk::Geometry3D* > ( slicedGeometry3D.GetPointer() );
+ slicedGeometry3D->InitializeEvenlySpaced(dynamic_cast<mitk::PlaneGeometry*>(planeGeometry.GetPointer()), 20);
+ mitk::BaseGeometry::Pointer geometry3D = dynamic_cast< mitk::BaseGeometry* > ( slicedGeometry3D.GetPointer() );
geometry3D->SetImageGeometry(true);
//Define origin for second Geometry3D;
mitk::Point3D origin2;
origin2[0] = 511;
origin2[1] = 60;
origin2[2] = 0;
//Define normal:
mitk::Vector3D normal2;
mitk::FillVector3D(normal2, 0, 1, 0);
//Initialize PlaneGeometry:
mitk::PlaneGeometry::Pointer planeGeometry2 = mitk::PlaneGeometry::New();
planeGeometry2->InitializePlane(origin2, normal2);
//Initialize SlicedGeometry3D:
mitk::SlicedGeometry3D::Pointer secondSlicedGeometry3D = mitk::SlicedGeometry3D::New();
- secondSlicedGeometry3D->InitializeEvenlySpaced(dynamic_cast<mitk::Geometry2D*>(planeGeometry2.GetPointer()), 20);
- mitk::Geometry3D::Pointer secondGeometry3D = dynamic_cast< mitk::Geometry3D* > ( secondSlicedGeometry3D.GetPointer() );
+ secondSlicedGeometry3D->InitializeEvenlySpaced(dynamic_cast<mitk::PlaneGeometry*>(planeGeometry2.GetPointer()), 20);
+ mitk::BaseGeometry::Pointer secondGeometry3D = dynamic_cast< mitk::BaseGeometry* > ( secondSlicedGeometry3D.GetPointer() );
secondGeometry3D->SetImageGeometry(true);
/***************************************************************/
CheckPlanesInsideBoundingBoxOnlyOnOneSlice(geometry3D);
CheckPlanesOutsideOfBoundingBox(geometry3D);
CheckPlanesInsideBoundingBox(geometry3D);
CheckIntersectionPointsOfTwoGeometry3D(geometry3D, secondGeometry3D);
CheckIntersectionWithPointCloud( geometry3D );
/** ToDo:
* test also rotated 3D geometry!
*/
MITK_TEST_END();
}
diff --git a/Core/Code/Testing/mitkDataNodeTest.cpp b/Core/Code/Testing/mitkDataNodeTest.cpp
index 23635a286b..5e75b81bb4 100644
--- a/Core/Code/Testing/mitkDataNodeTest.cpp
+++ b/Core/Code/Testing/mitkDataNodeTest.cpp
@@ -1,295 +1,295 @@
/*===================================================================
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 "mitkDataNode.h"
#include <vtkWindow.h>
#include "mitkVtkPropRenderer.h"
#include "mitkTestingMacros.h"
#include "mitkGlobalInteraction.h"
#include <iostream>
//Basedata Test
#include <mitkRenderWindowFrame.h>
#include <mitkGeometryData.h>
-#include <mitkGeometry2DData.h>
+#include <mitkPlaneGeometryData.h>
#include <mitkGradientBackground.h>
#include <mitkManufacturerLogo.h>
#include <mitkPointSet.h>
#include <mitkImage.h>
#include <mitkSurface.h>
//Mapper Test
-#include <mitkGeometry2DDataMapper2D.h>
-#include <mitkGeometry2DDataMapper2D.h>
+#include <mitkPlaneGeometryDataMapper2D.h>
+#include <mitkPlaneGeometryDataMapper2D.h>
#include <mitkImageVtkMapper2D.h>
#include <mitkSurfaceGLMapper2D.h>
-#include <mitkGeometry2DDataVtkMapper3D.h>
+#include <mitkPlaneGeometryDataVtkMapper3D.h>
#include <mitkPointSetVtkMapper3D.h>
#include <mitkPointSetVtkMapper2D.h>
#include <mitkSurfaceVtkMapper3D.h>
#include <mitkVolumeDataVtkMapper3D.h>
//Interactors
#include <mitkAffineInteractor.h>
#include <mitkPointSetInteractor.h>
//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();
+ baseData = mitk::PlaneGeometryData::New();
dataNode->SetData(baseData);
- MITK_TEST_CONDITION( baseData == dataNode->GetData(), "Testing if a Geometry2DData object was set correctly" )
+ MITK_TEST_CONDITION( baseData == dataNode->GetData(), "Testing if a PlaneGeometryData 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();
+ mapper = mitk::PlaneGeometryDataMapper2D::New();
dataNode->SetMapper(1,mapper);
- MITK_TEST_CONDITION( mapper == dataNode->GetMapper(1), "Testing if a Geometry2DDataMapper2D was set correctly" )
+ MITK_TEST_CONDITION( mapper == dataNode->GetMapper(1), "Testing if a PlaneGeometryDataMapper2D was set correctly" )
MITK_TEST_CONDITION( dataNode == mapper->GetDataNode(), "Testing if the mapper returns the right DataNode" )
mapper = mitk::ImageVtkMapper2D::New();
dataNode->SetMapper(1,mapper);
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::PointSetVtkMapper2D::New();
dataNode->SetMapper(1,mapper);
MITK_TEST_CONDITION( mapper == dataNode->GetMapper(1), "Testing if a PointSetVtkMapper2D 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();
+ mapper = mitk::PlaneGeometryDataVtkMapper3D::New();
dataNode->SetMapper(1,mapper);
- MITK_TEST_CONDITION( mapper == dataNode->GetMapper(1), "Testing if a Geometry2DDataVtkMapper3D was set correctly" )
+ MITK_TEST_CONDITION( mapper == dataNode->GetMapper(1), "Testing if a PlaneGeometryDataVtkMapper3D 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/Testing/mitkDataStorageTest.cpp b/Core/Code/Testing/mitkDataStorageTest.cpp
index 1f53a1806f..d67be2fbee 100644
--- a/Core/Code/Testing/mitkDataStorageTest.cpp
+++ b/Core/Code/Testing/mitkDataStorageTest.cpp
@@ -1,876 +1,872 @@
/*===================================================================
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 <fstream>
#include <algorithm>
#include "mitkImage.h"
#include "mitkSurface.h"
#include "mitkStringProperty.h"
#include "mitkColorProperty.h"
#include "mitkGroupTagProperty.h"
#include "mitkDataNode.h"
#include "mitkReferenceCountWatcher.h"
#include "mitkDataStorage.h"
#include "mitkStandaloneDataStorage.h"
#include "mitkNodePredicateProperty.h"
#include "mitkNodePredicateDataType.h"
#include "mitkNodePredicateDimension.h"
#include "mitkNodePredicateData.h"
#include "mitkNodePredicateNot.h"
#include "mitkNodePredicateAnd.h"
#include "mitkNodePredicateOr.h"
#include "mitkNodePredicateSource.h"
#include "mitkMessage.h"
//#include "mitkPicFileReader.h"
#include "mitkTestingMacros.h"
#include "mitkItkImageFileReader.h"
void TestDataStorage(mitk::DataStorage* ds, std::string filename);
namespace mitk
{
class TestStandaloneDataStorage: public StandaloneDataStorage
{
public:
mitkClassMacro(TestStandaloneDataStorage, mitk::DataStorage);
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
std::map<const mitk::DataNode*, unsigned long>
GetModifiedObserverTags() const {return m_NodeModifiedObserverTags;}
std::map<const mitk::DataNode*, unsigned long>
GetDeletedObserverTags() const { return m_NodeDeleteObserverTags; }
protected:
TestStandaloneDataStorage() {}
};
}
class DSEventReceiver // Helper class for event testing
{
public:
const mitk::DataNode* m_NodeAdded;
const mitk::DataNode* m_NodeRemoved;
DSEventReceiver()
: m_NodeAdded(NULL), m_NodeRemoved(NULL)
{
}
void OnAdd(const mitk::DataNode* node)
{
m_NodeAdded = node;
}
void OnRemove(const mitk::DataNode* node)
{
m_NodeRemoved = node;
}
};
///
/// \brief a class for checking if the datastorage is really thread safe
///
/// Therefore it listens to a node contained in the datastorage. when this node
/// gets removed and deleted, this class gets informed by calling OnObjectDelete().
/// in OnObjectDelete() an empty node gets added. this must not cause a deadlock
///
struct ItkDeleteEventListener
{
ItkDeleteEventListener( mitk::DataStorage* ds )
: m_Node(0), m_DataStorage(ds),
m_DeleteObserverTag(0)
{
}
void SetNode( mitk::DataNode* _Node )
{
if(m_Node)
return;
m_Node = _Node;
itk::MemberCommand<ItkDeleteEventListener>::Pointer onObjectDelete =
itk::MemberCommand<ItkDeleteEventListener>::New();
onObjectDelete->SetCallbackFunction(this, &ItkDeleteEventListener::OnObjectDelete);
m_DeleteObserverTag = m_Node->AddObserver(itk::DeleteEvent(), onObjectDelete);
}
void OnObjectDelete( const itk::Object* /*caller*/, const itk::EventObject & )
{
mitk::DataNode::Pointer node = mitk::DataNode::New();
m_DataStorage->Add( node ); // SHOULD NOT CAUSE A DEADLOCK!
m_DataStorage->Remove( node ); // tidy up: remove the empty node again
m_Node = 0;
}
protected:
mitk::DataNode* m_Node;
mitk::DataStorage::Pointer m_DataStorage;
unsigned int m_DeleteObserverTag;
};
//## Documentation
//## main testing method
//## NOTE: the current Singleton implementation of DataTreeStorage will lead to crashes if a testcase fails
//## and therefore mitk::DataStorage::ShutdownSingleton() is not called.
int mitkDataStorageTest(int argc, char* argv[])
{
MITK_TEST_BEGIN("DataStorageTest");
// muellerm: test observer tag remove
mitk::TestStandaloneDataStorage::Pointer testDS
= mitk::TestStandaloneDataStorage::New();
mitk::DataNode::Pointer n1 = mitk::DataNode::New();
testDS->Add(n1);
MITK_TEST_CONDITION_REQUIRED(
testDS->GetModifiedObserverTags().size()==1, "Testing if modified"
" observer was added.");
MITK_TEST_CONDITION_REQUIRED(
testDS->GetDeletedObserverTags().size()==1, "Testing if delete"
" observer was added.");
testDS->Remove(n1);
MITK_TEST_CONDITION_REQUIRED(
testDS->GetModifiedObserverTags().size()==0, "Testing if modified"
" observer was removed.");
MITK_TEST_CONDITION_REQUIRED(
testDS->GetDeletedObserverTags().size()==0, "Testing if delete"
" observer was removed.");
/* Create StandaloneDataStorage */
MITK_TEST_OUTPUT( << "Create StandaloneDataStorage : ");
mitk::StandaloneDataStorage::Pointer sds;
try
{
sds = mitk::StandaloneDataStorage::New();
MITK_TEST_CONDITION_REQUIRED(sds.IsNotNull(), "Testing Instatiation");
}
catch (...)
{
MITK_TEST_FAILED_MSG( << "Exception during creation of StandaloneDataStorage");
}
MITK_TEST_OUTPUT( << "Testing StandaloneDataStorage: ");
MITK_TEST_CONDITION_REQUIRED(argc>1, "Testing correct test invocation");
TestDataStorage(sds,argv[1]);
// TODO: Add specific StandaloneDataStorage Tests here
sds = NULL;
MITK_TEST_END();
}
//##Documentation
//## @brief Test for the DataStorage class and its associated classes (e.g. the predicate classes)
//## This method will be called once for each subclass of DataStorage
void TestDataStorage( mitk::DataStorage* ds, std::string filename )
{
/* DataStorage valid? */
MITK_TEST_CONDITION_REQUIRED(ds != NULL, "DataStorage valid?");
// Take the ItkImageFile Reader for the .nrrd data format.
// (was previously pic which is now deprecated format)
mitk::ItkImageFileReader::Pointer reader = mitk::ItkImageFileReader::New();
reader -> SetFileName(filename.c_str());
reader -> Update();
mitk::Image::Pointer image = reader->GetOutput();
// create some DataNodes to fill the ds
mitk::DataNode::Pointer n1 = mitk::DataNode::New(); // node with image and name property
// mitk::Image::Pointer image = mitk::Image::New();
// unsigned int imageDimensions[] = { 10, 10, 10, 10 };
// mitk::PixelType pt(typeid(int));
// image->Initialize( pt, 4, imageDimensions );
n1->SetData(image);
n1->SetProperty("name", mitk::StringProperty::New("Node 1 - Image Node"));
mitk::DataStorage::SetOfObjects::Pointer parents1 = mitk::DataStorage::SetOfObjects::New();
mitk::DataNode::Pointer n2 = mitk::DataNode::New(); // node with surface and name and color properties
mitk::Surface::Pointer surface = mitk::Surface::New();
n2->SetData(surface);
n2->SetProperty("name", mitk::StringProperty::New("Node 2 - Surface Node"));
mitk::Color color; color.Set(1.0f, 1.0f, 0.0f);
n2->SetColor(color);
n2->SetProperty("Resection Proposal 1", mitk::GroupTagProperty::New());
mitk::DataStorage::SetOfObjects::Pointer parents2 = mitk::DataStorage::SetOfObjects::New();
parents2->InsertElement(0, n1); // n1 (image node) is source of n2 (surface node)
mitk::DataNode::Pointer n3 = mitk::DataNode::New(); // node without data but with name property
n3->SetProperty("name", mitk::StringProperty::New("Node 3 - Empty Node"));
n3->SetProperty("Resection Proposal 1", mitk::GroupTagProperty::New());
n3->SetProperty("Resection Proposal 2", mitk::GroupTagProperty::New());
mitk::DataStorage::SetOfObjects::Pointer parents3 = mitk::DataStorage::SetOfObjects::New();
parents3->InsertElement(0, n2); // n2 is source of n3
mitk::DataNode::Pointer n4 = mitk::DataNode::New(); // node without data but with color property
n4->SetColor(color);
n4->SetProperty("Resection Proposal 2", mitk::GroupTagProperty::New());
mitk::DataStorage::SetOfObjects::Pointer parents4 = mitk::DataStorage::SetOfObjects::New();
parents4->InsertElement(0, n2);
parents4->InsertElement(1, n3); // n2 and n3 are sources of n4
mitk::DataNode::Pointer n5 = mitk::DataNode::New(); // extra node
n5->SetProperty("name", mitk::StringProperty::New("Node 5"));
try /* adding objects */
{
/* Add an object */
ds->Add(n1, parents1);
MITK_TEST_CONDITION_REQUIRED((ds->GetAll()->Size() == 1) && (ds->GetAll()->GetElement(0) == n1), "Testing Adding a new object");
/* Check exception on adding the same object again */
MITK_TEST_OUTPUT( << "Check exception on adding the same object again: ");
MITK_TEST_FOR_EXCEPTION(..., ds->Add(n1, parents1));
MITK_TEST_CONDITION(ds->GetAll()->Size() == 1, "Test if object count is correct after exception");
/* Add an object that has a source object */
ds->Add(n2, parents2);
MITK_TEST_CONDITION_REQUIRED(ds->GetAll()->Size() == 2, "Testing Adding an object that has a source object");
/* Add some more objects needed for further tests */
ds->Add(n3, parents3); // n3 object that has name property and one parent
ds->Add(n4, parents4); // n4 object that has color property
ds->Add(n5); // n5 has no parents
MITK_TEST_CONDITION_REQUIRED(ds->GetAll()->Size() == 5, "Adding some more objects needed for further tests");
}
catch(...)
{
MITK_TEST_FAILED_MSG( << "Exeption during object creation");
}
try /* object retrieval methods */
{
/* Requesting all Objects */
{
const mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetAll();
std::vector<mitk::DataNode::Pointer> stlAll = all->CastToSTLConstContainer();
MITK_TEST_CONDITION(
(stlAll.size() == 5) // check if all tree nodes are in resultset
&& (std::find(stlAll.begin(), stlAll.end(), n1) != stlAll.end()) && (std::find(stlAll.begin(), stlAll.end(), n2) != stlAll.end())
&& (std::find(stlAll.begin(), stlAll.end(), n3) != stlAll.end()) && (std::find(stlAll.begin(), stlAll.end(), n4) != stlAll.end())
&& (std::find(stlAll.begin(), stlAll.end(), n5) != stlAll.end()),
"Testing GetAll()"
);
}
/* Requesting a named object */
{
mitk::NodePredicateProperty::Pointer predicate(mitk::NodePredicateProperty::New("name", mitk::StringProperty::New("Node 2 - Surface Node")));
mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetSubset(predicate);
MITK_TEST_CONDITION((all->Size() == 1) && (all->GetElement(0) == n2), "Requesting a named object");
}
/* Requesting objects of specific data type */
{
mitk::NodePredicateDataType::Pointer predicate(mitk::NodePredicateDataType::New("Image"));
mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetSubset(predicate);
MITK_TEST_CONDITION((all->Size() == 1) && (all->GetElement(0) == n1), "Requesting objects of specific data type")
}
/* Requesting objects of specific dimension */
{
mitk::NodePredicateDimension::Pointer predicate(mitk::NodePredicateDimension::New( 4 ));
mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetSubset(predicate);
MITK_TEST_CONDITION((all->Size() == 1) && (all->GetElement(0) == n1), "Requesting objects of specific dimension")
}
/* Requesting objects with specific data object */
{
mitk::NodePredicateData::Pointer predicate(mitk::NodePredicateData::New(image));
mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetSubset(predicate);
MITK_TEST_CONDITION((all->Size() == 1) && (all->GetElement(0) == n1), "Requesting objects with specific data object")
}
/* Requesting objects with NULL data */
{
mitk::NodePredicateData::Pointer predicate(mitk::NodePredicateData::New(NULL));
mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetSubset(predicate);
MITK_TEST_CONDITION(
(all->Size() == 3)
&& (std::find(all->begin(), all->end(), n3) != all->end())
&& (std::find(all->begin(), all->end(), n4) != all->end())
&& (std::find(all->begin(), all->end(), n5) != all->end())
, "Requesting objects with NULL data");
}
/* Requesting objects that meet a conjunction criteria */
{
mitk::NodePredicateDataType::Pointer p1 = mitk::NodePredicateDataType::New("Surface");
mitk::NodePredicateProperty::Pointer p2 = mitk::NodePredicateProperty::New("color", mitk::ColorProperty::New(color));
mitk::NodePredicateAnd::Pointer predicate = mitk::NodePredicateAnd::New();
predicate->AddPredicate(p1);
predicate->AddPredicate(p2); // objects must be of datatype "Surface" and have red color (= n2)
const mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetSubset(predicate);
MITK_TEST_CONDITION((all->Size() == 1) && (all->GetElement(0) == n2), "Requesting objects that meet a conjunction criteria");
}
/* Requesting objects that meet a disjunction criteria */
{
mitk::NodePredicateDataType::Pointer p1(mitk::NodePredicateDataType::New("Image"));
mitk::NodePredicateProperty::Pointer p2(mitk::NodePredicateProperty::New("color", mitk::ColorProperty::New(color)));
mitk::NodePredicateOr::Pointer predicate = mitk::NodePredicateOr::New();
predicate->AddPredicate(p1);
predicate->AddPredicate(p2); // objects must be of datatype "Surface" or have red color (= n1, n2, n4)
const mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetSubset(predicate);
MITK_TEST_CONDITION(
(all->Size() == 3)
&& (std::find(all->begin(), all->end(), n1) != all->end())
&& (std::find(all->begin(), all->end(), n2) != all->end())
&& (std::find(all->begin(), all->end(), n4) != all->end()),
"Requesting objects that meet a disjunction criteria");
}
/* Requesting objects that do not meet a criteria */
{
mitk::ColorProperty::Pointer cp = mitk::ColorProperty::New(color);
mitk::NodePredicateProperty::Pointer proppred(mitk::NodePredicateProperty::New("color", cp));
mitk::NodePredicateNot::Pointer predicate(mitk::NodePredicateNot::New(proppred));
const mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetSubset(predicate);
std::vector<mitk::DataNode::Pointer> stlAll = all->CastToSTLConstContainer();
MITK_TEST_CONDITION(
(all->Size() == 3) // check if correct objects are in resultset
&& (std::find(stlAll.begin(), stlAll.end(), n1) != stlAll.end())
&& (std::find(stlAll.begin(), stlAll.end(), n3) != stlAll.end())
&& (std::find(stlAll.begin(), stlAll.end(), n5) != stlAll.end()), "Requesting objects that do not meet a criteria");
}
/* Requesting *direct* source objects */
{
const mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetSources(n3, NULL, true); // Get direct parents of n3 (=n2)
std::vector<mitk::DataNode::Pointer> stlAll = all->CastToSTLConstContainer();
MITK_TEST_CONDITION(
(all->Size() == 1) && (std::find(stlAll.begin(), stlAll.end(), n2) != stlAll.end()),
"Requesting *direct* source objects");
}
/* Requesting *all* source objects */
{
const mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetSources(n3, NULL, false); // Get all parents of n3 (= n1 + n2)
std::vector<mitk::DataNode::Pointer> stlAll = all->CastToSTLConstContainer();
MITK_TEST_CONDITION(
(all->Size() == 2)
&& (std::find(stlAll.begin(), stlAll.end(), n1) != stlAll.end())
&& (std::find(stlAll.begin(), stlAll.end(), n2) != stlAll.end()),
"Requesting *all* source objects"); // check if n1 and n2 are the resultset
}
/* Requesting *all* sources of object with multiple parents */
{
const mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetSources(n4, NULL, false); // Get all parents of n4 (= n1 + n2 + n3)
std::vector<mitk::DataNode::Pointer> stlAll = all->CastToSTLConstContainer();
MITK_TEST_CONDITION(
(all->Size() == 3)
&& (std::find(stlAll.begin(), stlAll.end(), n1) != stlAll.end())
&& (std::find(stlAll.begin(), stlAll.end(), n2) != stlAll.end())
&& (std::find(stlAll.begin(), stlAll.end(), n3) != stlAll.end()) // check if n1 and n2 and n3 are the resultset
, "Requesting *all* sources of object with multiple parents");
}
/* Requesting *direct* derived objects */
{
const mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetDerivations(n1, NULL, true); // Get direct childs of n1 (=n2)
std::vector<mitk::DataNode::Pointer> stlAll = all->CastToSTLConstContainer();
MITK_TEST_CONDITION(
(all->Size() == 1)
&& (std::find(stlAll.begin(), stlAll.end(), n2) != stlAll.end())// check if n1 is the resultset
, "Requesting *direct* derived objects");
-
}
///* Requesting *direct* derived objects with multiple parents/derivations */
{
const mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetDerivations(n2, NULL, true); // Get direct childs of n2 (=n3 + n4)
std::vector<mitk::DataNode::Pointer> stlAll = all->CastToSTLConstContainer();
MITK_TEST_CONDITION(
(all->Size() == 2)
&& (std::find(stlAll.begin(), stlAll.end(), n3) != stlAll.end()) // check if n3 is the resultset
&& (std::find(stlAll.begin(), stlAll.end(), n4) != stlAll.end()) // check if n4 is the resultset
, "Requesting *direct* derived objects with multiple parents/derivations");
}
//* Requesting *all* derived objects */
{
const mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetDerivations(n1, NULL, false); // Get all childs of n1 (=n2, n3, n4)
std::vector<mitk::DataNode::Pointer> stlAll = all->CastToSTLConstContainer();
MITK_TEST_CONDITION(
(all->Size() == 3)
&& (std::find(stlAll.begin(), stlAll.end(), n2) != stlAll.end())
&& (std::find(stlAll.begin(), stlAll.end(), n3) != stlAll.end())
&& (std::find(stlAll.begin(), stlAll.end(), n4) != stlAll.end())
, "Requesting *all* derived objects");
}
/* Checking for circular source relationships */
{
parents1->InsertElement(0, n4); // make n1 derived from n4 (which is derived from n2, which is derived from n1)
const mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetSources(n4, NULL, false); // Get all parents of n4 (= n1 + n2 + n3, not n4 itself and not multiple versions of the nodes!)
std::vector<mitk::DataNode::Pointer> stlAll = all->CastToSTLConstContainer();
MITK_TEST_CONDITION(
(all->Size() == 3)
&& (std::find(stlAll.begin(), stlAll.end(), n1) != stlAll.end())
&& (std::find(stlAll.begin(), stlAll.end(), n2) != stlAll.end())
&& (std::find(stlAll.begin(), stlAll.end(), n3) != stlAll.end()) // check if n1 and n2 and n3 are the resultset
, "Checking for circular source relationships");
}
///* Checking for circular derivation relationships can not be performed, because the internal derivations datastructure
// can not be accessed from the outside. (Therefore it should not be possible to create these circular relations */
//* Checking GroupTagProperty */
{
mitk::GroupTagProperty::Pointer tp = mitk::GroupTagProperty::New();
mitk::NodePredicateProperty::Pointer pred(mitk::NodePredicateProperty::New("Resection Proposal 1", tp));
const mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetSubset(pred);
std::vector<mitk::DataNode::Pointer> stlAll = all->CastToSTLConstContainer();
MITK_TEST_CONDITION(
(all->Size() == 2) // check if n2 and n3 are in resultset
&& (std::find(stlAll.begin(), stlAll.end(), n2) != stlAll.end())
&& (std::find(stlAll.begin(), stlAll.end(), n3) != stlAll.end())
, "Checking GroupTagProperty");
}
/* Checking GroupTagProperty 2 */
{
mitk::GroupTagProperty::Pointer tp = mitk::GroupTagProperty::New();
mitk::NodePredicateProperty::Pointer pred(mitk::NodePredicateProperty::New("Resection Proposal 2", tp));
const mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetSubset(pred);
std::vector<mitk::DataNode::Pointer> stlAll = all->CastToSTLConstContainer();
MITK_TEST_CONDITION(
(all->Size() == 2) // check if n3 and n4 are in resultset
&& (std::find(stlAll.begin(), stlAll.end(), n3) != stlAll.end())
&& (std::find(stlAll.begin(), stlAll.end(), n4) != stlAll.end())
, "Checking GroupTagProperty 2");
-
}
/* Checking direct sources with condition */
{
mitk::NodePredicateDataType::Pointer pred = mitk::NodePredicateDataType::New("Surface");
const mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetSources(n4, pred, true);
std::vector<mitk::DataNode::Pointer> stlAll = all->CastToSTLConstContainer();
MITK_TEST_CONDITION(
(all->Size() == 1) // check if n2 is in resultset
&& (std::find(stlAll.begin(), stlAll.end(), n2) != stlAll.end())
, "checking direct sources with condition");
}
/* Checking all sources with condition */
{
mitk::NodePredicateDataType::Pointer pred = mitk::NodePredicateDataType::New("Image");
const mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetSources(n4, pred, false);
std::vector<mitk::DataNode::Pointer> stlAll = all->CastToSTLConstContainer();
MITK_TEST_CONDITION(
(all->Size() == 1) // check if n1 is in resultset
&& (std::find(stlAll.begin(), stlAll.end(), n1) != stlAll.end())
, "Checking all sources with condition");
}
/* Checking all sources with condition with empty resultset */
{
mitk::NodePredicateDataType::Pointer pred = mitk::NodePredicateDataType::New("VesselTree");
const mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetSources(n4, pred, false);
MITK_TEST_CONDITION(all->Size() == 0 , "Checking all sources with condition with empty resultset"); // check if resultset is empty
}
/* Checking direct derivations with condition */
{
mitk::NodePredicateProperty::Pointer pred = mitk::NodePredicateProperty::New("color");
const mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetDerivations(n1, pred, true);
std::vector<mitk::DataNode::Pointer> stlAll = all->CastToSTLConstContainer();
MITK_TEST_CONDITION(
(all->Size() == 1) // check if n2 is in resultset
&& (std::find(stlAll.begin(), stlAll.end(), n2) != stlAll.end())
, "Checking direct derivations with condition");
}
/* Checking all derivations with condition */
{
mitk::NodePredicateProperty::Pointer pred = mitk::NodePredicateProperty::New("color");
const mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetDerivations(n1, pred, false);
std::vector<mitk::DataNode::Pointer> stlAll = all->CastToSTLConstContainer();
MITK_TEST_CONDITION(
(all->Size() == 2) // check if n2 and n4 are in resultset
&& (std::find(stlAll.begin(), stlAll.end(), n2) != stlAll.end())
&& (std::find(stlAll.begin(), stlAll.end(), n4) != stlAll.end())
, "Checking direct derivations with condition");
}
/* Checking named node method */
MITK_TEST_CONDITION(ds->GetNamedNode("Node 2 - Surface Node") == n2, "Checking named node method");
MITK_TEST_CONDITION(ds->GetNamedNode(std::string("Node 2 - Surface Node")) == n2, "Checking named node(std::string) method");
/* Checking named node method with wrong name */
MITK_TEST_CONDITION(ds->GetNamedNode("This name does not exist") == NULL, "Checking named node method with wrong name");
/* Checking named object method */
MITK_TEST_CONDITION(ds->GetNamedObject<mitk::Image>("Node 1 - Image Node") == image, "Checking named object method");
MITK_TEST_CONDITION(ds->GetNamedObject<mitk::Image>(std::string("Node 1 - Image Node")) == image, "Checking named object(std::string) method");
/* Checking named object method with wrong DataType */
MITK_TEST_CONDITION(ds->GetNamedObject<mitk::Surface>("Node 1 - Image Node") == NULL, "Checking named object method with wrong DataType");
/* Checking named object method with wrong name */
MITK_TEST_CONDITION(ds->GetNamedObject<mitk::Image>("This name does not exist") == NULL, "Checking named object method with wrong name");
/* Checking GetNamedDerivedNode with valid name and direct derivation only */
MITK_TEST_CONDITION(ds->GetNamedDerivedNode("Node 2 - Surface Node", n1, true) == n2, "Checking GetNamedDerivedNode with valid name & direct derivation only");
/* Checking GetNamedDerivedNode with invalid Name and direct derivation only */
MITK_TEST_CONDITION(ds->GetNamedDerivedNode("wrong name", n1, true) == NULL, "Checking GetNamedDerivedNode with invalid name & direct derivation only");
/* Checking GetNamedDerivedNode with invalid Name and direct derivation only */
MITK_TEST_CONDITION(ds->GetNamedDerivedNode("Node 3 - Empty Node", n1, false) == n3, "Checking GetNamedDerivedNode with invalid name & direct derivation only");
/* Checking GetNamedDerivedNode with valid Name but direct derivation only */
MITK_TEST_CONDITION(ds->GetNamedDerivedNode("Node 3 - Empty Node", n1, true) == NULL, "Checking GetNamedDerivedNode with valid Name but direct derivation only");
/* Checking GetNode with valid predicate */
{
mitk::NodePredicateDataType::Pointer p(mitk::NodePredicateDataType::New("Image"));
MITK_TEST_CONDITION(ds->GetNode(p) == n1, "Checking GetNode with valid predicate");
}
/* Checking GetNode with invalid predicate */
{
mitk::NodePredicateDataType::Pointer p(mitk::NodePredicateDataType::New("PointSet"));
MITK_TEST_CONDITION(ds->GetNode(p) == NULL, "Checking GetNode with invalid predicate");
}
-
} // object retrieval methods
catch(...)
{
MITK_TEST_FAILED_MSG( << "Exeption during object retrieval (GetXXX() Methods)");
}
try /* object removal methods */
{
-
/* Checking removal of a node without relations */
{
mitk::DataNode::Pointer extra = mitk::DataNode::New();
extra->SetProperty("name", mitk::StringProperty::New("extra"));
mitk::ReferenceCountWatcher::Pointer watcher = new mitk::ReferenceCountWatcher(extra);
int refCountbeforeDS = watcher->GetReferenceCount();
ds->Add(extra);
MITK_TEST_CONDITION(ds->GetNamedNode("extra") == extra, "Adding extra node");
ds->Remove(extra);
MITK_TEST_CONDITION(
(ds->GetNamedNode("extra") == NULL)
&& (refCountbeforeDS == watcher->GetReferenceCount())
, "Checking removal of a node without relations");
extra = NULL;
}
/* Checking removal of a node with a parent */
{
mitk::DataNode::Pointer extra = mitk::DataNode::New();
extra->SetProperty("name", mitk::StringProperty::New("extra"));
mitk::ReferenceCountWatcher::Pointer watcher = new mitk::ReferenceCountWatcher(extra);
int refCountbeforeDS = watcher->GetReferenceCount();
ds->Add(extra, n1); // n1 is parent of extra
MITK_TEST_CONDITION(
(ds->GetNamedNode("extra") == extra)
&& (ds->GetDerivations(n1)->Size() == 2) // n2 and extra should be derived from n1
, "Adding extra node");
ds->Remove(extra);
MITK_TEST_CONDITION(
(ds->GetNamedNode("extra") == NULL)
&& (refCountbeforeDS == watcher->GetReferenceCount())
&& (ds->GetDerivations(n1)->Size() == 1)
, "Checking removal of a node with a parent");
extra = NULL;
}
/* Checking removal of a node with two parents */
{
mitk::DataNode::Pointer extra = mitk::DataNode::New();
extra->SetProperty("name", mitk::StringProperty::New("extra"));
mitk::ReferenceCountWatcher::Pointer watcher = new mitk::ReferenceCountWatcher(extra);
int refCountbeforeDS = watcher->GetReferenceCount();
mitk::DataStorage::SetOfObjects::Pointer p = mitk::DataStorage::SetOfObjects::New();
p->push_back(n1);
p->push_back(n2);
ds->Add(extra, p); // n1 and n2 are parents of extra
MITK_TEST_CONDITION(
(ds->GetNamedNode("extra") == extra)
&& (ds->GetDerivations(n1)->Size() == 2) // n2 and extra should be derived from n1
&& (ds->GetDerivations(n2)->Size() == 3)
, "add extra node");
ds->Remove(extra);
MITK_TEST_CONDITION(
(ds->GetNamedNode("extra") == NULL)
&& (refCountbeforeDS == watcher->GetReferenceCount())
&& (ds->GetDerivations(n1)->Size() == 1) // after remove, only n2 should be derived from n1
&& (ds->GetDerivations(n2)->Size() == 2) // after remove, only n3 and n4 should be derived from n2
, "Checking removal of a node with two parents");
extra = NULL;
}
/* Checking removal of a node with two derived nodes */
{
mitk::DataNode::Pointer extra = mitk::DataNode::New();
extra->SetProperty("name", mitk::StringProperty::New("extra"));
mitk::ReferenceCountWatcher::Pointer watcher = new mitk::ReferenceCountWatcher(extra);
int refCountbeforeDS = watcher->GetReferenceCount();
ds->Add(extra);
mitk::DataNode::Pointer d1 = mitk::DataNode::New();
d1->SetProperty("name", mitk::StringProperty::New("d1"));
ds->Add(d1, extra);
mitk::DataNode::Pointer d2 = mitk::DataNode::New();
d2->SetProperty("name", mitk::StringProperty::New("d2"));
ds->Add(d2, extra);
MITK_TEST_CONDITION(
(ds->GetNamedNode("extra") == extra)
&& (ds->GetNamedNode("d1") == d1)
&& (ds->GetNamedNode("d2") == d2)
&& (ds->GetSources(d1)->Size() == 1) // extra should be source of d1
&& (ds->GetSources(d2)->Size() == 1) // extra should be source of d2
&& (ds->GetDerivations(extra)->Size() == 2) // d1 and d2 should be derived from extra
, "add extra node");
ds->Remove(extra);
MITK_TEST_CONDITION(
(ds->GetNamedNode("extra") == NULL)
&& (ds->GetNamedNode("d1") == d1)
&& (ds->GetNamedNode("d2") == d2)
&& (refCountbeforeDS == watcher->GetReferenceCount())
&& (ds->GetSources(d1)->Size() == 0) // after remove, d1 should not have a source anymore
&& (ds->GetSources(d2)->Size() == 0) // after remove, d2 should not have a source anymore
, "Checking removal of a node with two derived nodes");
extra = NULL;
}
/* Checking removal of a node with two parents and two derived nodes */
{
mitk::DataNode::Pointer extra = mitk::DataNode::New();
extra->SetProperty("name", mitk::StringProperty::New("extra"));
mitk::ReferenceCountWatcher::Pointer watcher = new mitk::ReferenceCountWatcher(extra);
mitk::ReferenceCountWatcher::Pointer n1watcher = new mitk::ReferenceCountWatcher(n1);
int refCountbeforeDS = watcher->GetReferenceCount();
mitk::DataStorage::SetOfObjects::Pointer p = mitk::DataStorage::SetOfObjects::New();
p->push_back(n1);
p->push_back(n2);
ds->Add(extra, p); // n1 and n2 are parents of extra
mitk::DataNode::Pointer d1 = mitk::DataNode::New();
d1->SetProperty("name", mitk::StringProperty::New("d1x"));
ds->Add(d1, extra);
mitk::DataNode::Pointer d2 = mitk::DataNode::New();
d2->SetProperty("name", mitk::StringProperty::New("d2x"));
ds->Add(d2, extra);
MITK_TEST_CONDITION(
(ds->GetNamedNode("extra") == extra)
&& (ds->GetNamedNode("d1x") == d1)
&& (ds->GetNamedNode("d2x") == d2)
&& (ds->GetSources(d1)->Size() == 1) // extra should be source of d1
&& (ds->GetSources(d2)->Size() == 1) // extra should be source of d2
&& (ds->GetDerivations(n1)->Size() == 2) // n2 and extra should be derived from n1
&& (ds->GetDerivations(n2)->Size() == 3) // n3, n4 and extra should be derived from n2
&& (ds->GetDerivations(extra)->Size() == 2) // d1 and d2 should be derived from extra
, "add extra node");
ds->Remove(extra);
MITK_TEST_CONDITION(
(ds->GetNamedNode("extra") == NULL)
&& (ds->GetNamedNode("d1x") == d1)
&& (ds->GetNamedNode("d2x") == d2)
&& (refCountbeforeDS == watcher->GetReferenceCount())
&& (ds->GetDerivations(n1)->Size() == 1) // after remove, only n2 should be derived from n1
&& (ds->GetDerivations(n2)->Size() == 2) // after remove, only n3 and n4 should be derived from n2
&& (ds->GetSources(d1)->Size() == 0) // after remove, d1 should not have a source anymore
&& (ds->GetSources(d2)->Size() == 0) // after remove, d2 should not have a source anymore
, "Checking removal of a node with two parents and two derived nodes");
extra = NULL;
}
}
catch(...)
{
MITK_TEST_FAILED_MSG( << "Exeption during object removal methods");
}
/* Checking for node is it's own parent exception */
{
MITK_TEST_FOR_EXCEPTION_BEGIN(...);
mitk::DataNode::Pointer extra = mitk::DataNode::New();
extra->SetProperty("name", mitk::StringProperty::New("extra"));
mitk::DataStorage::SetOfObjects::Pointer p = mitk::DataStorage::SetOfObjects::New();
p->push_back(n1);
p->push_back(extra); // extra is parent of extra!!!
ds->Add(extra, p);
MITK_TEST_FOR_EXCEPTION_END(...);
}
/* Checking reference count of node after add and remove */
{
mitk::DataNode::Pointer extra = mitk::DataNode::New();
mitk::ReferenceCountWatcher::Pointer watcher = new mitk::ReferenceCountWatcher(extra);
extra->SetProperty("name", mitk::StringProperty::New("extra"));
mitk::DataStorage::SetOfObjects::Pointer p = mitk::DataStorage::SetOfObjects::New();
p->push_back(n1);
p->push_back(n3);
ds->Add(extra, p);
extra = NULL;
ds->Remove(ds->GetNamedNode("extra"));
MITK_TEST_CONDITION(watcher->GetReferenceCount() == 0, "Checking reference count of node after add and remove");
}
/* Checking removal of a node with two derived nodes [ dataStorage->GetDerivations( rootNode )] see bug #3426 */
{
mitk::DataNode::Pointer extra = mitk::DataNode::New();
extra->SetProperty("name", mitk::StringProperty::New("extra"));
ds->Add(extra);
mitk::DataNode::Pointer d1y = mitk::DataNode::New();
d1y->SetProperty("name", mitk::StringProperty::New("d1y"));
mitk::ReferenceCountWatcher::Pointer watcherD1y = new mitk::ReferenceCountWatcher(d1y);
int refCountbeforeDS = watcherD1y->GetReferenceCount();
ds->Add(d1y, extra);
mitk::DataNode::Pointer d2y = mitk::DataNode::New();
d2y->SetProperty("name", mitk::StringProperty::New("d2y"));
ds->Add(d2y, extra);
MITK_TEST_CONDITION(
(ds->GetNamedNode("extra") == extra)
&& (ds->GetNamedNode("d1y") == d1y)
&& (ds->GetNamedNode("d2y") == d2y)
&& (ds->GetSources(d1y)->Size() == 1) // extra should be source of d1y
&& (ds->GetSources(d2y)->Size() == 1) // extra should be source of d2y
&& (ds->GetDerivations(extra)->Size() == 2) // d1y and d2y should be derived from extra
, "add extra node");
ds->Remove(ds->GetDerivations( extra));
MITK_TEST_CONDITION(
(ds->GetNamedNode("extra") == extra)
&& (ds->GetNamedNode("d1y") == NULL) // d1y should be NULL now
&& (ds->GetNamedNode("d2y") == NULL) // d2y should be NULL now
&& (refCountbeforeDS == watcherD1y->GetReferenceCount())
, "Checking removal of subset of two derived nodes from one parent node");
ds->Remove(extra);
MITK_TEST_CONDITION(
(ds->GetNamedNode("extra") == NULL)
, "Checking removal of a parent node");
extra = NULL;
}
/* Checking GetGrouptags() */
{
const std::set<std::string> groupTags = ds->GetGroupTags();
MITK_TEST_CONDITION(
(groupTags.size() == 2)
&& (std::find(groupTags.begin(), groupTags.end(), "Resection Proposal 1") != groupTags.end())
&& (std::find(groupTags.begin(), groupTags.end(), "Resection Proposal 2") != groupTags.end())
, "Checking GetGrouptags()");
}
/* Checking Event handling */
DSEventReceiver listener;
try
{
ds->AddNodeEvent += mitk::MessageDelegate1<DSEventReceiver, const mitk::DataNode*>(&listener, &DSEventReceiver::OnAdd);
ds->RemoveNodeEvent += mitk::MessageDelegate1<DSEventReceiver, const mitk::DataNode*>(&listener, &DSEventReceiver::OnRemove);
mitk::DataNode::Pointer extra = mitk::DataNode::New();
mitk::ReferenceCountWatcher::Pointer watcher = new mitk::ReferenceCountWatcher(extra);
ds->Add(extra);
MITK_TEST_CONDITION(listener.m_NodeAdded == extra.GetPointer(), "Checking AddEvent");
ds->Remove(extra);
MITK_TEST_CONDITION(listener.m_NodeRemoved == extra.GetPointer(), "Checking RemoveEvent");
/* RemoveListener */
ds->AddNodeEvent -= mitk::MessageDelegate1<DSEventReceiver, const mitk::DataNode*>(&listener, &DSEventReceiver::OnAdd);
ds->RemoveNodeEvent -= mitk::MessageDelegate1<DSEventReceiver, const mitk::DataNode*>(&listener, &DSEventReceiver::OnRemove);
listener.m_NodeAdded = NULL;
listener.m_NodeRemoved = NULL;
ds->Add(extra);
ds->Remove(extra);
MITK_TEST_CONDITION((listener.m_NodeRemoved == NULL) && (listener.m_NodeAdded == NULL), "Checking RemoveListener");
std::cout << "Pointer handling after event handling: " << std::flush;
extra = NULL; // delete reference to the node. its memory should be freed now
MITK_TEST_CONDITION(watcher->GetReferenceCount() == 0, "Pointer handling after event handling");
}
catch(...)
{
/* cleanup */
ds->AddNodeEvent -= mitk::MessageDelegate1<DSEventReceiver, const mitk::DataNode*>(&listener, &DSEventReceiver::OnAdd);
ds->RemoveNodeEvent -= mitk::MessageDelegate1<DSEventReceiver, const mitk::DataNode*>(&listener, &DSEventReceiver::OnRemove);
MITK_TEST_FAILED_MSG( << "Exception during object removal methods");
}
//Checking ComputeBoundingGeometry3D method*/
const mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetAll();
mitk::TimeGeometry::Pointer geometry = ds->ComputeBoundingGeometry3D();
MITK_TEST_CONDITION(geometry->CountTimeSteps()==4, "Test for number or time steps with ComputeBoundingGeometry()");
mitk::TimeBounds timebounds = geometry->GetTimeBounds();
MITK_TEST_CONDITION((timebounds[0]==0)&&(timebounds[1]==4),"Test for timebounds with ComputeBoundingGeometry()");
for (unsigned int i=0; i<geometry->CountTimeSteps(); i++)
{
- mitk::Geometry3D::Pointer subGeometry = geometry->GetGeometryForTimeStep(i);
- mitk::TimeBounds bounds = subGeometry->GetTimeBounds();
+ mitk::BaseGeometry::Pointer subGeometry = geometry->GetGeometryForTimeStep(i);
+ mitk::TimeBounds bounds = geometry->GetTimeBounds(i);
MITK_TEST_CONDITION((bounds[0]==i)&&(bounds[1]==i+1),"Test for timebounds of geometry at different time steps with ComputeBoundingGeometry()");
}
geometry = ds->ComputeBoundingGeometry3D(all);
MITK_TEST_CONDITION(geometry->CountTimeSteps()==4, "Test for number or time steps with ComputeBoundingGeometry(allNodes)");
timebounds = geometry->GetTimeBounds();
MITK_TEST_CONDITION((timebounds[0]==0)&&(timebounds[1]==4),"Test for timebounds with ComputeBoundingGeometry(allNodes)");
for (unsigned int i=0; i<geometry->CountTimeSteps(); i++)
{
- mitk::Geometry3D::Pointer subGeometry = geometry->GetGeometryForTimeStep(i);
- mitk::TimeBounds bounds = subGeometry->GetTimeBounds();
+ mitk::BaseGeometry::Pointer subGeometry = geometry->GetGeometryForTimeStep(i);
+ mitk::TimeBounds bounds = geometry->GetTimeBounds(i);
MITK_TEST_CONDITION((bounds[0]==i)&&(bounds[1]==i+1),"Test for timebounds of geometry at different time steps with ComputeBoundingGeometry()");
}
// test for thread safety of DataStorage
try
{
mitk::StandaloneDataStorage::Pointer standaloneDataStorage
= mitk::StandaloneDataStorage::New();
ItkDeleteEventListener listener( standaloneDataStorage );
{
mitk::DataNode::Pointer emptyNode = mitk::DataNode::New();
mitk::DataNode* pEmptyNode = emptyNode;
listener.SetNode( emptyNode );
standaloneDataStorage->Add( emptyNode );
emptyNode = 0; // emptyNode is still alive because standaloneDataStorage
// owns it
standaloneDataStorage->Remove( pEmptyNode ); // this should not freeze the whole thing
}
}
catch(...)
{
MITK_TEST_FAILED_MSG( << "Exception during testing DataStorage thread safe");
}
/* Clear DataStorage */
ds->Remove(ds->GetAll());
MITK_TEST_CONDITION(ds->GetAll()->Size() == 0, "Checking Clear DataStorage");
}
diff --git a/Core/Code/Testing/mitkGeometry2DTest.cpp b/Core/Code/Testing/mitkGeometry2DTest.cpp
deleted file mode 100644
index eb340562c4..0000000000
--- a/Core/Code/Testing/mitkGeometry2DTest.cpp
+++ /dev/null
@@ -1,157 +0,0 @@
-/*===================================================================
-
-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 "mitkGeometry3D.h"
-
-#include <vnl/vnl_quaternion.h>
-#include <vnl/vnl_quaternion.txx>
-
-#include "mitkRotationOperation.h"
-#include "mitkInteractionConst.h"
-#include <mitkMatrixConvert.h>
-#include <mitkImageCast.h>
-
-#include "mitkTestingMacros.h"
-#include <fstream>
-#include <mitkVector.h>
-
-
-mitk::Geometry2D::Pointer createGeometry2D()
-{
- mitk::Vector3D mySpacing;
- mySpacing[0] = 31;
- mySpacing[1] = 0.1;
- mySpacing[2] = 5.4;
- mitk::Point3D myOrigin;
- myOrigin[0] = 8;
- myOrigin[1] = 9;
- myOrigin[2] = 10;
- mitk::AffineTransform3D::Pointer myTransform = mitk::AffineTransform3D::New();
- itk::Matrix<mitk::ScalarType, 3,3> transMatrix;
- transMatrix.Fill(0);
- transMatrix[0][0] = 1;
- transMatrix[1][1] = 2;
- transMatrix[2][2] = 4;
-
- myTransform->SetMatrix(transMatrix);
-
- mitk::Geometry2D::Pointer geometry2D = mitk::Geometry2D::New();
- geometry2D->SetIndexToWorldTransform(myTransform);
- geometry2D->SetSpacing(mySpacing);
- geometry2D->SetOrigin(myOrigin);
- return geometry2D;
-}
-
-int testGeometry2DCloning()
-{
- mitk::Geometry2D::Pointer geometry2D = createGeometry2D();
-
- try
- {
- mitk::Geometry2D::Pointer clone = geometry2D->Clone();
- itk::Matrix<mitk::ScalarType,3,3> matrix = clone->GetIndexToWorldTransform()->GetMatrix();
- MITK_TEST_CONDITION(matrix[0][0] == 31, "Test if matrix element exists...");
-
- double origin = geometry2D->GetOrigin()[0];
- MITK_TEST_CONDITION(mitk::Equal(origin, 8),"First Point of origin as expected...");
-
- double spacing = geometry2D->GetSpacing()[0];
- MITK_TEST_CONDITION(mitk::Equal(spacing, 31),"First Point of spacing as expected...");
- }
- catch (...)
- {
- MITK_TEST_CONDITION(false, "Error during access on a member of cloned geometry");
- }
- // direction [row] [coloum]
- MITK_TEST_OUTPUT( << "Casting a rotated 2D ITK Image to a MITK Image and check if Geometry is still same" );
-
- return EXIT_SUCCESS;
-}
-
-bool compareMatrix(itk::Matrix<mitk::ScalarType, 3,3> left, itk::Matrix<mitk::ScalarType, 3,3> right)
-{
- bool equal = true;
- for (int i = 0; i < 3; ++i)
- for (int j = 0; j < 3; ++j)
- equal &= mitk::Equal(left[i][j], right[i][j]);
- return equal;
-}
-
-int testGeometry2DInitializeOrder()
-{
- mitk::Vector3D mySpacing;
- mySpacing[0] = 31;
- mySpacing[1] = 0.1;
- mySpacing[2] = 5.4;
- mitk::Point3D myOrigin;
- myOrigin[0] = 8;
- myOrigin[1] = 9;
- myOrigin[2] = 10;
- mitk::AffineTransform3D::Pointer myTransform = mitk::AffineTransform3D::New();
- itk::Matrix<mitk::ScalarType, 3,3> transMatrix;
- transMatrix.Fill(0);
- transMatrix[0][0] = 1;
- transMatrix[1][1] = 2;
- transMatrix[2][2] = 4;
-
- myTransform->SetMatrix(transMatrix);
-
- mitk::Geometry2D::Pointer geometry2D1 = mitk::Geometry2D::New();
- geometry2D1->SetIndexToWorldTransform(myTransform);
- geometry2D1->SetSpacing(mySpacing);
- geometry2D1->SetOrigin(myOrigin);
-
- mitk::Geometry2D::Pointer geometry2D2 = mitk::Geometry2D::New();
- geometry2D2->SetSpacing(mySpacing);
- geometry2D2->SetOrigin(myOrigin);
- geometry2D2->SetIndexToWorldTransform(myTransform);
-
- mitk::Geometry2D::Pointer geometry2D3 = mitk::Geometry2D::New();
- geometry2D3->SetIndexToWorldTransform(myTransform);
- geometry2D3->SetSpacing(mySpacing);
- geometry2D3->SetOrigin(myOrigin);
- geometry2D3->SetIndexToWorldTransform(myTransform);
-
- MITK_TEST_CONDITION(mitk::Equal(geometry2D1->GetOrigin(), geometry2D2->GetOrigin()),"Origin of Geometry 1 match those of Geometry 2.");
- MITK_TEST_CONDITION(mitk::Equal(geometry2D1->GetOrigin(), geometry2D3->GetOrigin()),"Origin of Geometry 1 match those of Geometry 3.");
- MITK_TEST_CONDITION(mitk::Equal(geometry2D2->GetOrigin(), geometry2D3->GetOrigin()),"Origin of Geometry 2 match those of Geometry 3.");
-
- MITK_TEST_CONDITION(mitk::Equal(geometry2D1->GetSpacing(), geometry2D2->GetSpacing()),"Spacing of Geometry 1 match those of Geometry 2.");
- MITK_TEST_CONDITION(mitk::Equal(geometry2D1->GetSpacing(), geometry2D3->GetSpacing()),"Spacing of Geometry 1 match those of Geometry 3.");
- MITK_TEST_CONDITION(mitk::Equal(geometry2D2->GetSpacing(), geometry2D3->GetSpacing()),"Spacing of Geometry 2 match those of Geometry 3.");
-
- MITK_TEST_CONDITION(compareMatrix(geometry2D1->GetIndexToWorldTransform()->GetMatrix(), geometry2D2->GetIndexToWorldTransform()->GetMatrix()),"Transformation of Geometry 1 match those of Geometry 2.");
- MITK_TEST_CONDITION(compareMatrix(geometry2D1->GetIndexToWorldTransform()->GetMatrix(), geometry2D3->GetIndexToWorldTransform()->GetMatrix()),"Transformation of Geometry 1 match those of Geometry 3.");
- MITK_TEST_CONDITION(compareMatrix(geometry2D2->GetIndexToWorldTransform()->GetMatrix(), geometry2D3->GetIndexToWorldTransform()->GetMatrix()),"Transformation of Geometry 2 match those of Geometry 3.");
- return EXIT_SUCCESS;
-}
-
-int mitkGeometry2DTest(int /*argc*/, char* /*argv*/[])
-{
- MITK_TEST_BEGIN(mitkGeometry3DTest);
-
- int result;
-
- MITK_TEST_CONDITION_REQUIRED ( (result = testGeometry2DCloning()) == EXIT_SUCCESS, "");
-
- // See bug 15990
- // MITK_TEST_CONDITION_REQUIRED ( (result = testGeometry2DInitializeOrder()) == EXIT_SUCCESS, "");
-
-
- MITK_TEST_END();
-
- return EXIT_SUCCESS;
-}
diff --git a/Core/Code/Testing/mitkGeometry3DTest.cpp b/Core/Code/Testing/mitkGeometry3DTest.cpp
index fff1266cea..486683b9cd 100644
--- a/Core/Code/Testing/mitkGeometry3DTest.cpp
+++ b/Core/Code/Testing/mitkGeometry3DTest.cpp
@@ -1,614 +1,614 @@
/*===================================================================
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 "mitkGeometry3D.h"
#include <vnl/vnl_quaternion.h>
#include <vnl/vnl_quaternion.txx>
#include "mitkRotationOperation.h"
#include "mitkInteractionConst.h"
#include <mitkMatrixConvert.h>
#include <mitkImageCast.h>
#include "mitkTestingMacros.h"
#include <fstream>
#include <mitkVector.h>
bool testGetAxisVectorVariants(mitk::Geometry3D* geometry)
{
- int direction;
- for(direction=0; direction<3; ++direction)
- {
- mitk::Vector3D frontToBack;
- switch(direction)
- {
- case 0: frontToBack = geometry->GetCornerPoint(false, false, false)-geometry->GetCornerPoint(true , false, false); break; //7-3
- case 1: frontToBack = geometry->GetCornerPoint(false, false, false)-geometry->GetCornerPoint(false, true , false); break; //7-5
- case 2: frontToBack = geometry->GetCornerPoint(false, false, false)-geometry->GetCornerPoint(false , false, true); break; //7-2
- }
- std::cout << "Testing GetAxisVector(int) vs GetAxisVector(bool, bool, bool): ";
- if(mitk::Equal(geometry->GetAxisVector(direction), frontToBack) == false)
- {
- std::cout<<"[FAILED]"<<std::endl;
- return false;
- }
- std::cout<<"[PASSED]"<<std::endl;
- }
- return true;
+ int direction;
+ for(direction=0; direction<3; ++direction)
+ {
+ mitk::Vector3D frontToBack;
+ switch(direction)
+ {
+ case 0: frontToBack = geometry->GetCornerPoint(false, false, false)-geometry->GetCornerPoint(true , false, false); break; //7-3
+ case 1: frontToBack = geometry->GetCornerPoint(false, false, false)-geometry->GetCornerPoint(false, true , false); break; //7-5
+ case 2: frontToBack = geometry->GetCornerPoint(false, false, false)-geometry->GetCornerPoint(false , false, true); break; //7-2
+ }
+ std::cout << "Testing GetAxisVector(int) vs GetAxisVector(bool, bool, bool): ";
+ if(mitk::Equal(geometry->GetAxisVector(direction), frontToBack) == false)
+ {
+ std::cout<<"[FAILED]"<<std::endl;
+ return false;
+ }
+ std::cout<<"[PASSED]"<<std::endl;
+ }
+ return true;
}
bool testGetAxisVectorExtent(mitk::Geometry3D* geometry)
{
- int direction;
- for(direction=0; direction<3; ++direction)
- {
- if(mitk::Equal(geometry->GetAxisVector(direction).GetNorm(), geometry->GetExtentInMM(direction)) == false)
- {
- std::cout<<"[FAILED]"<<std::endl;
- return false;
- }
- std::cout<<"[PASSED]"<<std::endl;
- }
- return true;
+ int direction;
+ for(direction=0; direction<3; ++direction)
+ {
+ if(mitk::Equal(geometry->GetAxisVector(direction).GetNorm(), geometry->GetExtentInMM(direction)) == false)
+ {
+ std::cout<<"[FAILED]"<<std::endl;
+ return false;
+ }
+ std::cout<<"[PASSED]"<<std::endl;
+ }
+ return true;
}
// a part of the test requires axis-parallel coordinates
int testIndexAndWorldConsistency(mitk::Geometry3D* geometry3d)
{
- MITK_TEST_OUTPUT( << "Testing consistency of index and world coordinate systems: ");
- mitk::Point3D origin = geometry3d->GetOrigin();
- mitk::Point3D dummy;
-
- MITK_TEST_OUTPUT( << " Testing index->world->index conversion consistency");
- geometry3d->WorldToIndex(origin, dummy);
- geometry3d->IndexToWorld(dummy, dummy);
- MITK_TEST_CONDITION_REQUIRED(dummy == origin, "");
-
- MITK_TEST_OUTPUT( << " Testing WorldToIndex(origin, mitk::Point3D)==(0,0,0)");
- mitk::Point3D globalOrigin;
- mitk::FillVector3D(globalOrigin, 0,0,0);
-
- mitk::Point3D originContinuousIndex;
- geometry3d->WorldToIndex(origin, originContinuousIndex);
- MITK_TEST_CONDITION_REQUIRED(originContinuousIndex == globalOrigin, "");
-
- MITK_TEST_OUTPUT( << " Testing WorldToIndex(origin, itk::Index)==(0,0,0)");
- itk::Index<3> itkindex;
- geometry3d->WorldToIndex(origin, itkindex);
- itk::Index<3> globalOriginIndex;
- mitk::vtk2itk(globalOrigin, globalOriginIndex);
- MITK_TEST_CONDITION_REQUIRED(itkindex == globalOriginIndex, "");
-
- MITK_TEST_OUTPUT( << " Testing WorldToIndex(origin-0.5*spacing, itk::Index)==(0,0,0)");
- mitk::Vector3D halfSpacingStep = geometry3d->GetSpacing()*0.5;
- mitk::Matrix3D rotation;
- mitk::Point3D originOffCenter = origin-halfSpacingStep;
- geometry3d->WorldToIndex(originOffCenter, itkindex);
- MITK_TEST_CONDITION_REQUIRED(itkindex == globalOriginIndex, "");
-
- MITK_TEST_OUTPUT( << " Testing WorldToIndex(origin+0.5*spacing-eps, itk::Index)==(0,0,0)");
- originOffCenter = origin+halfSpacingStep;
- originOffCenter -= 0.0001;
- geometry3d->WorldToIndex( originOffCenter, itkindex);
- MITK_TEST_CONDITION_REQUIRED(itkindex == globalOriginIndex, "");
-
- MITK_TEST_OUTPUT( << " Testing WorldToIndex(origin+0.5*spacing, itk::Index)==(1,1,1)");
- originOffCenter = origin+halfSpacingStep;
- itk::Index<3> global111;
- mitk::FillVector3D(global111, 1,1,1);
- geometry3d->WorldToIndex( originOffCenter, itkindex);
- MITK_TEST_CONDITION_REQUIRED(itkindex == global111, "");
-
- MITK_TEST_OUTPUT( << " Testing WorldToIndex(GetCenter())==BoundingBox.GetCenter: ");
- mitk::Point3D center = geometry3d->GetCenter();
- mitk::Point3D centerContIndex;
- geometry3d->WorldToIndex(center, centerContIndex);
- mitk::BoundingBox::ConstPointer boundingBox = geometry3d->GetBoundingBox();
- mitk::BoundingBox::PointType centerBounds = boundingBox->GetCenter();
- MITK_TEST_CONDITION_REQUIRED(mitk::Equal(centerContIndex,centerBounds), "");
-
- MITK_TEST_OUTPUT( << " Testing GetCenter()==IndexToWorld(BoundingBox.GetCenter): ");
- center = geometry3d->GetCenter();
- mitk::Point3D centerBoundsInWorldCoords;
- geometry3d->IndexToWorld(centerBounds, centerBoundsInWorldCoords);
- MITK_TEST_CONDITION_REQUIRED(mitk::Equal(center,centerBoundsInWorldCoords), "");
-
- return EXIT_SUCCESS;
+ MITK_TEST_OUTPUT( << "Testing consistency of index and world coordinate systems: ");
+ mitk::Point3D origin = geometry3d->GetOrigin();
+ mitk::Point3D dummy;
+
+ MITK_TEST_OUTPUT( << " Testing index->world->index conversion consistency");
+ geometry3d->WorldToIndex(origin, dummy);
+ geometry3d->IndexToWorld(dummy, dummy);
+ MITK_TEST_CONDITION_REQUIRED(dummy == origin, "");
+
+ MITK_TEST_OUTPUT( << " Testing WorldToIndex(origin, mitk::Point3D)==(0,0,0)");
+ mitk::Point3D globalOrigin;
+ mitk::FillVector3D(globalOrigin, 0,0,0);
+
+ mitk::Point3D originContinuousIndex;
+ geometry3d->WorldToIndex(origin, originContinuousIndex);
+ MITK_TEST_CONDITION_REQUIRED(originContinuousIndex == globalOrigin, "");
+
+ MITK_TEST_OUTPUT( << " Testing WorldToIndex(origin, itk::Index)==(0,0,0)");
+ itk::Index<3> itkindex;
+ geometry3d->WorldToIndex(origin, itkindex);
+ itk::Index<3> globalOriginIndex;
+ mitk::vtk2itk(globalOrigin, globalOriginIndex);
+ MITK_TEST_CONDITION_REQUIRED(itkindex == globalOriginIndex, "");
+
+ MITK_TEST_OUTPUT( << " Testing WorldToIndex(origin-0.5*spacing, itk::Index)==(0,0,0)");
+ mitk::Vector3D halfSpacingStep = geometry3d->GetSpacing()*0.5;
+ mitk::Matrix3D rotation;
+ mitk::Point3D originOffCenter = origin-halfSpacingStep;
+ geometry3d->WorldToIndex(originOffCenter, itkindex);
+ MITK_TEST_CONDITION_REQUIRED(itkindex == globalOriginIndex, "");
+
+ MITK_TEST_OUTPUT( << " Testing WorldToIndex(origin+0.5*spacing-eps, itk::Index)==(0,0,0)");
+ originOffCenter = origin+halfSpacingStep;
+ originOffCenter -= 0.0001;
+ geometry3d->WorldToIndex( originOffCenter, itkindex);
+ MITK_TEST_CONDITION_REQUIRED(itkindex == globalOriginIndex, "");
+
+ MITK_TEST_OUTPUT( << " Testing WorldToIndex(origin+0.5*spacing, itk::Index)==(1,1,1)");
+ originOffCenter = origin+halfSpacingStep;
+ itk::Index<3> global111;
+ mitk::FillVector3D(global111, 1,1,1);
+ geometry3d->WorldToIndex( originOffCenter, itkindex);
+ MITK_TEST_CONDITION_REQUIRED(itkindex == global111, "");
+
+ MITK_TEST_OUTPUT( << " Testing WorldToIndex(GetCenter())==BoundingBox.GetCenter: ");
+ mitk::Point3D center = geometry3d->GetCenter();
+ mitk::Point3D centerContIndex;
+ geometry3d->WorldToIndex(center, centerContIndex);
+ mitk::BoundingBox::ConstPointer boundingBox = geometry3d->GetBoundingBox();
+ mitk::BoundingBox::PointType centerBounds = boundingBox->GetCenter();
+ MITK_TEST_CONDITION_REQUIRED(mitk::Equal(centerContIndex,centerBounds), "");
+
+ MITK_TEST_OUTPUT( << " Testing GetCenter()==IndexToWorld(BoundingBox.GetCenter): ");
+ center = geometry3d->GetCenter();
+ mitk::Point3D centerBoundsInWorldCoords;
+ geometry3d->IndexToWorld(centerBounds, centerBoundsInWorldCoords);
+ MITK_TEST_CONDITION_REQUIRED(mitk::Equal(center,centerBoundsInWorldCoords), "");
+
+ return EXIT_SUCCESS;
}
int testIndexAndWorldConsistencyForVectors(mitk::Geometry3D* geometry3d)
{
- MITK_TEST_OUTPUT( << "Testing consistency of index and world coordinate systems for vectors: ");
- mitk::Vector3D xAxisMM = geometry3d->GetAxisVector(0);
- mitk::Vector3D xAxisContinuousIndex;
- mitk::Vector3D xAxisContinuousIndexDeprecated;
-
- mitk::Point3D p, pIndex, origin;
- origin = geometry3d->GetOrigin();
- p[0] = xAxisMM[0];
- p[1] = xAxisMM[1];
- p[2] = xAxisMM[2];
-
- geometry3d->WorldToIndex(p,pIndex);
-
- geometry3d->WorldToIndex(xAxisMM, xAxisContinuousIndexDeprecated);
- geometry3d->WorldToIndex(xAxisMM,xAxisContinuousIndex);
- MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndex[0] == pIndex[0],"");
- MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndex[1] == pIndex[1],"");
- MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndex[2] == pIndex[2],"");
-
- MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndex[0] == xAxisContinuousIndexDeprecated[0],"");
- MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndex[1] == xAxisContinuousIndexDeprecated[1],"");
- MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndex[2] == xAxisContinuousIndexDeprecated[2],"");
-
- MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndexDeprecated[0] == pIndex[0],"");
- MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndexDeprecated[1] == pIndex[1],"");
- MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndexDeprecated[2] == pIndex[2],"");
-
- geometry3d->IndexToWorld(xAxisContinuousIndex,xAxisContinuousIndex);
- geometry3d->IndexToWorld(xAxisContinuousIndexDeprecated,xAxisContinuousIndexDeprecated);
- geometry3d->IndexToWorld(pIndex,p);
-
- MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndex == xAxisMM,"");
- MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndex[0] == p[0],"");
- MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndex[1] == p[1],"");
- MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndex[2] == p[2],"");
-
- MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndexDeprecated == xAxisMM,"");
- MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndexDeprecated[0] == p[0],"");
- MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndexDeprecated[1] == p[1],"");
- MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndexDeprecated[2] == p[2],"");
-
- return EXIT_SUCCESS;
+ MITK_TEST_OUTPUT( << "Testing consistency of index and world coordinate systems for vectors: ");
+ mitk::Vector3D xAxisMM = geometry3d->GetAxisVector(0);
+ mitk::Vector3D xAxisContinuousIndex;
+ mitk::Vector3D xAxisContinuousIndexDeprecated;
+
+ mitk::Point3D p, pIndex, origin;
+ origin = geometry3d->GetOrigin();
+ p[0] = xAxisMM[0];
+ p[1] = xAxisMM[1];
+ p[2] = xAxisMM[2];
+
+ geometry3d->WorldToIndex(p,pIndex);
+
+ geometry3d->WorldToIndex(xAxisMM, xAxisContinuousIndexDeprecated);
+ geometry3d->WorldToIndex(xAxisMM,xAxisContinuousIndex);
+ MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndex[0] == pIndex[0],"");
+ MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndex[1] == pIndex[1],"");
+ MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndex[2] == pIndex[2],"");
+
+ MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndex[0] == xAxisContinuousIndexDeprecated[0],"");
+ MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndex[1] == xAxisContinuousIndexDeprecated[1],"");
+ MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndex[2] == xAxisContinuousIndexDeprecated[2],"");
+
+ MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndexDeprecated[0] == pIndex[0],"");
+ MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndexDeprecated[1] == pIndex[1],"");
+ MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndexDeprecated[2] == pIndex[2],"");
+
+ geometry3d->IndexToWorld(xAxisContinuousIndex,xAxisContinuousIndex);
+ geometry3d->IndexToWorld(xAxisContinuousIndexDeprecated,xAxisContinuousIndexDeprecated);
+ geometry3d->IndexToWorld(pIndex,p);
+
+ MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndex == xAxisMM,"");
+ MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndex[0] == p[0],"");
+ MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndex[1] == p[1],"");
+ MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndex[2] == p[2],"");
+
+ MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndexDeprecated == xAxisMM,"");
+ MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndexDeprecated[0] == p[0],"");
+ MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndexDeprecated[1] == p[1],"");
+ MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndexDeprecated[2] == p[2],"");
+
+ return EXIT_SUCCESS;
}
int testIndexAndWorldConsistencyForIndex(mitk::Geometry3D* geometry3d)
{
- MITK_TEST_OUTPUT( << "Testing consistency of index and world coordinate systems: ");
-
- // creating testing data
- itk::Index<4> itkIndex4, itkIndex4b;
- itk::Index<3> itkIndex3, itkIndex3b;
- itk::Index<2> itkIndex2, itkIndex2b;
- mitk::Index3D mitkIndex, mitkIndexb;
-
- itkIndex4[0] = itkIndex4[1] = itkIndex4[2] = itkIndex4[3] = 4;
- itkIndex3[0] = itkIndex3[1] = itkIndex3[2] = 6;
- itkIndex2[0] = itkIndex2[1] = 2;
- mitkIndex[0] = mitkIndex[1] = mitkIndex[2] = 13;
-
- // check for constistency
- mitk::Point3D point;
- geometry3d->IndexToWorld(itkIndex2,point);
- geometry3d->WorldToIndex(point,itkIndex2b);
-
- MITK_TEST_CONDITION_REQUIRED(
- ((itkIndex2b[0] == itkIndex2[0]) &&
- (itkIndex2b[1] == itkIndex2[1])),
- "Testing itk::index<2> for IndexToWorld/WorldToIndex consistency");
-
- geometry3d->IndexToWorld(itkIndex3,point);
- geometry3d->WorldToIndex(point,itkIndex3b);
-
- MITK_TEST_CONDITION_REQUIRED(
- ((itkIndex3b[0] == itkIndex3[0]) &&
- (itkIndex3b[1] == itkIndex3[1]) &&
- (itkIndex3b[2] == itkIndex3[2])),
- "Testing itk::index<3> for IndexToWorld/WorldToIndex consistency");
-
- geometry3d->IndexToWorld(itkIndex4,point);
- geometry3d->WorldToIndex(point,itkIndex4b);
-
- MITK_TEST_CONDITION_REQUIRED(
- ((itkIndex4b[0] == itkIndex4[0]) &&
- (itkIndex4b[1] == itkIndex4[1]) &&
- (itkIndex4b[2] == itkIndex4[2]) &&
- (itkIndex4b[3] == 0)),
- "Testing itk::index<3> for IndexToWorld/WorldToIndex consistency");
-
- geometry3d->IndexToWorld(mitkIndex,point);
- geometry3d->WorldToIndex(point,mitkIndexb);
-
- MITK_TEST_CONDITION_REQUIRED(
- ((mitkIndexb[0] == mitkIndex[0]) &&
- (mitkIndexb[1] == mitkIndex[1]) &&
- (mitkIndexb[2] == mitkIndex[2])),
- "Testing mitk::Index for IndexToWorld/WorldToIndex consistency");
-
- return EXIT_SUCCESS;
+ MITK_TEST_OUTPUT( << "Testing consistency of index and world coordinate systems: ");
+
+ // creating testing data
+ itk::Index<4> itkIndex4, itkIndex4b;
+ itk::Index<3> itkIndex3, itkIndex3b;
+ itk::Index<2> itkIndex2, itkIndex2b;
+ mitk::Index3D mitkIndex, mitkIndexb;
+
+ itkIndex4[0] = itkIndex4[1] = itkIndex4[2] = itkIndex4[3] = 4;
+ itkIndex3[0] = itkIndex3[1] = itkIndex3[2] = 6;
+ itkIndex2[0] = itkIndex2[1] = 2;
+ mitkIndex[0] = mitkIndex[1] = mitkIndex[2] = 13;
+
+ // check for constistency
+ mitk::Point3D point;
+ geometry3d->IndexToWorld(itkIndex2,point);
+ geometry3d->WorldToIndex(point,itkIndex2b);
+
+ MITK_TEST_CONDITION_REQUIRED(
+ ((itkIndex2b[0] == itkIndex2[0]) &&
+ (itkIndex2b[1] == itkIndex2[1])),
+ "Testing itk::index<2> for IndexToWorld/WorldToIndex consistency");
+
+ geometry3d->IndexToWorld(itkIndex3,point);
+ geometry3d->WorldToIndex(point,itkIndex3b);
+
+ MITK_TEST_CONDITION_REQUIRED(
+ ((itkIndex3b[0] == itkIndex3[0]) &&
+ (itkIndex3b[1] == itkIndex3[1]) &&
+ (itkIndex3b[2] == itkIndex3[2])),
+ "Testing itk::index<3> for IndexToWorld/WorldToIndex consistency");
+
+ geometry3d->IndexToWorld(itkIndex4,point);
+ geometry3d->WorldToIndex(point,itkIndex4b);
+
+ MITK_TEST_CONDITION_REQUIRED(
+ ((itkIndex4b[0] == itkIndex4[0]) &&
+ (itkIndex4b[1] == itkIndex4[1]) &&
+ (itkIndex4b[2] == itkIndex4[2]) &&
+ (itkIndex4b[3] == 0)),
+ "Testing itk::index<3> for IndexToWorld/WorldToIndex consistency");
+
+ geometry3d->IndexToWorld(mitkIndex,point);
+ geometry3d->WorldToIndex(point,mitkIndexb);
+
+ MITK_TEST_CONDITION_REQUIRED(
+ ((mitkIndexb[0] == mitkIndex[0]) &&
+ (mitkIndexb[1] == mitkIndex[1]) &&
+ (mitkIndexb[2] == mitkIndex[2])),
+ "Testing mitk::Index for IndexToWorld/WorldToIndex consistency");
+
+ return EXIT_SUCCESS;
}
#include <itkImage.h>
int testItkImageIsCenterBased()
{
- MITK_TEST_OUTPUT(<< "Testing whether itk::Image coordinates are center-based.");
- typedef itk::Image<int,3> ItkIntImage3D;
- ItkIntImage3D::Pointer itkintimage = ItkIntImage3D::New();
- ItkIntImage3D::SizeType size;
- size.Fill(10);
- mitk::Point3D origin;
- mitk::FillVector3D(origin, 2,3,7);
- itkintimage->Initialize();
- itkintimage->SetRegions(size);
- itkintimage->SetOrigin(origin);
- std::cout<<"[PASSED]"<<std::endl;
-
- MITK_TEST_OUTPUT( << " Testing itk::Image::TransformPhysicalPointToContinuousIndex(origin)==(0,0,0)");
- mitk::Point3D globalOrigin;
- mitk::FillVector3D(globalOrigin, 0,0,0);
-
- itk::ContinuousIndex<mitk::ScalarType, 3> originContinuousIndex;
- itkintimage->TransformPhysicalPointToContinuousIndex(origin, originContinuousIndex);
- MITK_TEST_CONDITION_REQUIRED(originContinuousIndex == globalOrigin, "");
-
- MITK_TEST_OUTPUT( << " Testing itk::Image::TransformPhysicalPointToIndex(origin)==(0,0,0)");
- itk::Index<3> itkindex;
- itkintimage->TransformPhysicalPointToIndex(origin, itkindex);
- itk::Index<3> globalOriginIndex;
- mitk::vtk2itk(globalOrigin, globalOriginIndex);
- MITK_TEST_CONDITION_REQUIRED(itkindex == globalOriginIndex, "");
-
- MITK_TEST_OUTPUT( << " Testing itk::Image::TransformPhysicalPointToIndex(origin-0.5*spacing)==(0,0,0)");
- mitk::Vector3D halfSpacingStep = itkintimage->GetSpacing()*0.5;
- mitk::Matrix3D rotation;
- mitk::Point3D originOffCenter = origin-halfSpacingStep;
- itkintimage->TransformPhysicalPointToIndex(originOffCenter, itkindex);
- MITK_TEST_CONDITION_REQUIRED(itkindex == globalOriginIndex, "");
-
- MITK_TEST_OUTPUT( << " Testing itk::Image::TransformPhysicalPointToIndex(origin+0.5*spacing-eps, itk::Index)==(0,0,0)");
- originOffCenter = origin+halfSpacingStep;
- originOffCenter -= 0.0001;
- itkintimage->TransformPhysicalPointToIndex( originOffCenter, itkindex);
- MITK_TEST_CONDITION_REQUIRED(itkindex == globalOriginIndex, "");
-
- MITK_TEST_OUTPUT( << " Testing itk::Image::TransformPhysicalPointToIndex(origin+0.5*spacing, itk::Index)==(1,1,1)");
- originOffCenter = origin+halfSpacingStep;
- itk::Index<3> global111;
- mitk::FillVector3D(global111, 1,1,1);
- itkintimage->TransformPhysicalPointToIndex( originOffCenter, itkindex);
- MITK_TEST_CONDITION_REQUIRED(itkindex == global111, "");
-
- MITK_TEST_OUTPUT( << "=> Yes, itk::Image coordinates are center-based.");
-
- return EXIT_SUCCESS;
+ MITK_TEST_OUTPUT(<< "Testing whether itk::Image coordinates are center-based.");
+ typedef itk::Image<int,3> ItkIntImage3D;
+ ItkIntImage3D::Pointer itkintimage = ItkIntImage3D::New();
+ ItkIntImage3D::SizeType size;
+ size.Fill(10);
+ mitk::Point3D origin;
+ mitk::FillVector3D(origin, 2,3,7);
+ itkintimage->Initialize();
+ itkintimage->SetRegions(size);
+ itkintimage->SetOrigin(origin);
+ std::cout<<"[PASSED]"<<std::endl;
+
+ MITK_TEST_OUTPUT( << " Testing itk::Image::TransformPhysicalPointToContinuousIndex(origin)==(0,0,0)");
+ mitk::Point3D globalOrigin;
+ mitk::FillVector3D(globalOrigin, 0,0,0);
+
+ itk::ContinuousIndex<mitk::ScalarType, 3> originContinuousIndex;
+ itkintimage->TransformPhysicalPointToContinuousIndex(origin, originContinuousIndex);
+ MITK_TEST_CONDITION_REQUIRED(originContinuousIndex == globalOrigin, "");
+
+ MITK_TEST_OUTPUT( << " Testing itk::Image::TransformPhysicalPointToIndex(origin)==(0,0,0)");
+ itk::Index<3> itkindex;
+ itkintimage->TransformPhysicalPointToIndex(origin, itkindex);
+ itk::Index<3> globalOriginIndex;
+ mitk::vtk2itk(globalOrigin, globalOriginIndex);
+ MITK_TEST_CONDITION_REQUIRED(itkindex == globalOriginIndex, "");
+
+ MITK_TEST_OUTPUT( << " Testing itk::Image::TransformPhysicalPointToIndex(origin-0.5*spacing)==(0,0,0)");
+ mitk::Vector3D halfSpacingStep = itkintimage->GetSpacing()*0.5;
+ mitk::Matrix3D rotation;
+ mitk::Point3D originOffCenter = origin-halfSpacingStep;
+ itkintimage->TransformPhysicalPointToIndex(originOffCenter, itkindex);
+ MITK_TEST_CONDITION_REQUIRED(itkindex == globalOriginIndex, "");
+
+ MITK_TEST_OUTPUT( << " Testing itk::Image::TransformPhysicalPointToIndex(origin+0.5*spacing-eps, itk::Index)==(0,0,0)");
+ originOffCenter = origin+halfSpacingStep;
+ originOffCenter -= 0.0001;
+ itkintimage->TransformPhysicalPointToIndex( originOffCenter, itkindex);
+ MITK_TEST_CONDITION_REQUIRED(itkindex == globalOriginIndex, "");
+
+ MITK_TEST_OUTPUT( << " Testing itk::Image::TransformPhysicalPointToIndex(origin+0.5*spacing, itk::Index)==(1,1,1)");
+ originOffCenter = origin+halfSpacingStep;
+ itk::Index<3> global111;
+ mitk::FillVector3D(global111, 1,1,1);
+ itkintimage->TransformPhysicalPointToIndex( originOffCenter, itkindex);
+ MITK_TEST_CONDITION_REQUIRED(itkindex == global111, "");
+
+ MITK_TEST_OUTPUT( << "=> Yes, itk::Image coordinates are center-based.");
+
+ return EXIT_SUCCESS;
}
int testGeometry3D(bool imageGeometry)
{
- // Build up a new image Geometry
- mitk::Geometry3D::Pointer geometry3d = mitk::Geometry3D::New();
- float bounds[ ] = {-10.0, 17.0, -12.0, 188.0, 13.0, 211.0};
-
- MITK_TEST_OUTPUT( << "Initializing");
- geometry3d->Initialize();
-
- MITK_TEST_OUTPUT(<< "Setting ImageGeometry to " << imageGeometry);
- geometry3d->SetImageGeometry(imageGeometry);
-
- MITK_TEST_OUTPUT(<< "Setting bounds by SetFloatBounds(): " << bounds);
- geometry3d->SetFloatBounds(bounds);
-
- MITK_TEST_OUTPUT( << "Testing AxisVectors");
- if(testGetAxisVectorVariants(geometry3d) == false)
- return EXIT_FAILURE;
-
- if(testGetAxisVectorExtent(geometry3d) == false)
- return EXIT_FAILURE;
-
- MITK_TEST_OUTPUT( << "Creating an AffineTransform3D transform");
- mitk::AffineTransform3D::MatrixType matrix;
- matrix.SetIdentity();
- matrix(1,1) = 2;
- mitk::AffineTransform3D::Pointer transform;
- transform = mitk::AffineTransform3D::New();
- transform->SetMatrix(matrix);
-
- MITK_TEST_OUTPUT( << "Testing a SetIndexToWorldTransform");
- geometry3d->SetIndexToWorldTransform(transform);
-
- MITK_TEST_OUTPUT( << "Testing correctness of value returned by GetSpacing");
- const mitk::Vector3D& spacing1 = geometry3d->GetSpacing();
- mitk::Vector3D expectedSpacing;
- expectedSpacing.Fill(1.0);
- expectedSpacing[1] = 2;
- if( mitk::Equal(spacing1, expectedSpacing) == false )
- {
- MITK_TEST_OUTPUT( << " [FAILED]");
- return EXIT_FAILURE;
- }
-
- MITK_TEST_OUTPUT( << "Testing a Compose(transform)");
- geometry3d->Compose(transform);
-
- MITK_TEST_OUTPUT( << "Testing correctness of value returned by GetSpacing");
- const mitk::Vector3D& spacing2 = geometry3d->GetSpacing();
- expectedSpacing[1] = 4;
- if( mitk::Equal(spacing2, expectedSpacing) == false )
- {
- MITK_TEST_OUTPUT( << " [FAILED]");
- return EXIT_FAILURE;
- }
-
- MITK_TEST_OUTPUT( << "Testing correctness of SetSpacing");
- mitk::Vector3D newspacing;
- mitk::FillVector3D(newspacing, 1.5, 2.5, 3.5);
- geometry3d->SetSpacing(newspacing);
- const mitk::Vector3D& spacing3 = geometry3d->GetSpacing();
- if( mitk::Equal(spacing3, newspacing) == false )
- {
- MITK_TEST_OUTPUT( << " [FAILED]");
- return EXIT_FAILURE;
- }
-
- // Seperate Test function for Index and World consistency
- testIndexAndWorldConsistency(geometry3d);
- testIndexAndWorldConsistencyForVectors(geometry3d);
- testIndexAndWorldConsistencyForIndex(geometry3d);
-
- MITK_TEST_OUTPUT( << "Testing a rotation of the geometry");
- double angle = 35.0;
- mitk::Vector3D rotationVector; mitk::FillVector3D( rotationVector, 1, 0, 0 );
- mitk::Point3D center = geometry3d->GetCenter();
- mitk::RotationOperation* op = new mitk::RotationOperation( mitk::OpROTATE, center, rotationVector, angle );
- geometry3d->ExecuteOperation(op);
-
- MITK_TEST_OUTPUT( << "Testing mitk::GetRotation() and success of rotation");
- mitk::Matrix3D rotation;
- mitk::GetRotation(geometry3d, rotation);
- mitk::Vector3D voxelStep=rotation*newspacing;
- mitk::Vector3D voxelStepIndex;
- geometry3d->WorldToIndex(voxelStep, voxelStepIndex);
- mitk::Vector3D expectedVoxelStepIndex;
- expectedVoxelStepIndex.Fill(1);
- MITK_TEST_CONDITION_REQUIRED(mitk::Equal(voxelStepIndex,expectedVoxelStepIndex), "");
- delete op;
- std::cout<<"[PASSED]"<<std::endl;
-
- MITK_TEST_OUTPUT( << "Testing that ImageGeometry is still " << imageGeometry);
- MITK_TEST_CONDITION_REQUIRED(geometry3d->GetImageGeometry() == imageGeometry, "");
-
- //Test if the translate function moves the origin correctly.
- mitk::Point3D oldOrigin = geometry3d->GetOrigin();
-
- //use some random values for translation
- mitk::Vector3D translationVector;
- translationVector.SetElement(0, 17.5f);
- translationVector.SetElement(1, -32.3f);
- translationVector.SetElement(2, 4.0f);
- //compute ground truth
- mitk::Point3D tmpResult = geometry3d->GetOrigin() + translationVector;
- geometry3d->Translate(translationVector);
- MITK_TEST_CONDITION( mitk::Equal( geometry3d->GetOrigin(), tmpResult ), "Testing if origin was translated.");
-
- translationVector*=-1; //vice versa
- geometry3d->Translate(translationVector);
-
- MITK_TEST_CONDITION( mitk::Equal( geometry3d->GetOrigin(), oldOrigin ), "Testing if the translation could be done vice versa." );
-
- return EXIT_SUCCESS;
+ // Build up a new image Geometry
+ mitk::Geometry3D::Pointer geometry3d = mitk::Geometry3D::New();
+ float bounds[ ] = {-10.0, 17.0, -12.0, 188.0, 13.0, 211.0};
+
+ MITK_TEST_OUTPUT( << "Initializing");
+ geometry3d->Initialize();
+
+ MITK_TEST_OUTPUT(<< "Setting ImageGeometry to " << imageGeometry);
+ geometry3d->SetImageGeometry(imageGeometry);
+
+ MITK_TEST_OUTPUT(<< "Setting bounds by SetFloatBounds(): " << bounds);
+ geometry3d->SetFloatBounds(bounds);
+
+ MITK_TEST_OUTPUT( << "Testing AxisVectors");
+ if(testGetAxisVectorVariants(geometry3d) == false)
+ return EXIT_FAILURE;
+
+ if(testGetAxisVectorExtent(geometry3d) == false)
+ return EXIT_FAILURE;
+
+ MITK_TEST_OUTPUT( << "Creating an AffineTransform3D transform");
+ mitk::AffineTransform3D::MatrixType matrix;
+ matrix.SetIdentity();
+ matrix(1,1) = 2;
+ mitk::AffineTransform3D::Pointer transform;
+ transform = mitk::AffineTransform3D::New();
+ transform->SetMatrix(matrix);
+
+ MITK_TEST_OUTPUT( << "Testing a SetIndexToWorldTransform");
+ geometry3d->SetIndexToWorldTransform(transform);
+
+ MITK_TEST_OUTPUT( << "Testing correctness of value returned by GetSpacing");
+ const mitk::Vector3D& spacing1 = geometry3d->GetSpacing();
+ mitk::Vector3D expectedSpacing;
+ expectedSpacing.Fill(1.0);
+ expectedSpacing[1] = 2;
+ if( mitk::Equal(spacing1, expectedSpacing) == false )
+ {
+ MITK_TEST_OUTPUT( << " [FAILED]");
+ return EXIT_FAILURE;
+ }
+
+ MITK_TEST_OUTPUT( << "Testing a Compose(transform)");
+ geometry3d->Compose(transform);
+
+ MITK_TEST_OUTPUT( << "Testing correctness of value returned by GetSpacing");
+ const mitk::Vector3D& spacing2 = geometry3d->GetSpacing();
+ expectedSpacing[1] = 4;
+ if( mitk::Equal(spacing2, expectedSpacing) == false )
+ {
+ MITK_TEST_OUTPUT( << " [FAILED]");
+ return EXIT_FAILURE;
+ }
+
+ MITK_TEST_OUTPUT( << "Testing correctness of SetSpacing");
+ mitk::Vector3D newspacing;
+ mitk::FillVector3D(newspacing, 1.5, 2.5, 3.5);
+ geometry3d->SetSpacing(newspacing);
+ const mitk::Vector3D& spacing3 = geometry3d->GetSpacing();
+ if( mitk::Equal(spacing3, newspacing) == false )
+ {
+ MITK_TEST_OUTPUT( << " [FAILED]");
+ return EXIT_FAILURE;
+ }
+
+ // Seperate Test function for Index and World consistency
+ testIndexAndWorldConsistency(geometry3d);
+ testIndexAndWorldConsistencyForVectors(geometry3d);
+ testIndexAndWorldConsistencyForIndex(geometry3d);
+
+ MITK_TEST_OUTPUT( << "Testing a rotation of the geometry");
+ double angle = 35.0;
+ mitk::Vector3D rotationVector; mitk::FillVector3D( rotationVector, 1, 0, 0 );
+ mitk::Point3D center = geometry3d->GetCenter();
+ mitk::RotationOperation* op = new mitk::RotationOperation( mitk::OpROTATE, center, rotationVector, angle );
+ geometry3d->ExecuteOperation(op);
+
+ MITK_TEST_OUTPUT( << "Testing mitk::GetRotation() and success of rotation");
+ mitk::Matrix3D rotation;
+ mitk::GetRotation(geometry3d, rotation);
+ mitk::Vector3D voxelStep=rotation*newspacing;
+ mitk::Vector3D voxelStepIndex;
+ geometry3d->WorldToIndex(voxelStep, voxelStepIndex);
+ mitk::Vector3D expectedVoxelStepIndex;
+ expectedVoxelStepIndex.Fill(1);
+ MITK_TEST_CONDITION_REQUIRED(mitk::Equal(voxelStepIndex,expectedVoxelStepIndex), "");
+ delete op;
+ std::cout<<"[PASSED]"<<std::endl;
+
+ MITK_TEST_OUTPUT( << "Testing that ImageGeometry is still " << imageGeometry);
+ MITK_TEST_CONDITION_REQUIRED(geometry3d->GetImageGeometry() == imageGeometry, "");
+
+ //Test if the translate function moves the origin correctly.
+ mitk::Point3D oldOrigin = geometry3d->GetOrigin();
+
+ //use some random values for translation
+ mitk::Vector3D translationVector;
+ translationVector.SetElement(0, 17.5f);
+ translationVector.SetElement(1, -32.3f);
+ translationVector.SetElement(2, 4.0f);
+ //compute ground truth
+ mitk::Point3D tmpResult = geometry3d->GetOrigin() + translationVector;
+ geometry3d->Translate(translationVector);
+ MITK_TEST_CONDITION( mitk::Equal( geometry3d->GetOrigin(), tmpResult ), "Testing if origin was translated.");
+
+ translationVector*=-1; //vice versa
+ geometry3d->Translate(translationVector);
+
+ MITK_TEST_CONDITION( mitk::Equal( geometry3d->GetOrigin(), oldOrigin ), "Testing if the translation could be done vice versa." );
+
+ return EXIT_SUCCESS;
}
int testGeometryAfterCasting()
{
- // Epsilon. Allowed difference for rotationvalue
- float eps = 0.0001;
-
- // Cast ITK and MITK images and see if geometry stays
- typedef itk::Image<double,2> Image2DType;
- typedef itk::Image<double,3> Image3DType;
-
- // Create 3D ITK Image from Scratch, cast to 3D MITK image, compare Geometries
- Image3DType::Pointer image3DItk = Image3DType::New();
- Image3DType::RegionType myRegion;
- Image3DType::SizeType mySize;
- Image3DType::IndexType myIndex;
- Image3DType::SpacingType mySpacing;
- Image3DType::DirectionType myDirection, rotMatrixX, rotMatrixY, rotMatrixZ;
- mySpacing[0] = 31;
- mySpacing[1] = 0.1;
- mySpacing[2] = 2.9;
- myIndex[0] = -15;
- myIndex[1] = 15;
- myIndex[2] = 12;
- mySize[0] = 10;
- mySize[1] = 2;
- mySize[2] = 555;
- myRegion.SetSize( mySize);
- myRegion.SetIndex( myIndex );
- image3DItk->SetSpacing(mySpacing);
- image3DItk->SetRegions( myRegion);
- image3DItk->Allocate();
- image3DItk->FillBuffer(0);
-
- myDirection.SetIdentity();
- rotMatrixX.SetIdentity();
- rotMatrixY.SetIdentity();
- rotMatrixZ.SetIdentity();
-
- mitk::Image::Pointer mitkImage;
-
- // direction [row] [coloum]
- MITK_TEST_OUTPUT( << "Casting a rotated 3D ITK Image to a MITK Image and check if Geometry is still same" );
- for (double rotX=0; rotX < (itk::Math::pi*2); rotX+=0.4 )
- {
- // Set Rotation X
- rotMatrixX[1][1] = cos( rotX );
- rotMatrixX[1][2] = -sin( rotX );
- rotMatrixX[2][1] = sin( rotX );
- rotMatrixX[2][2] = cos( rotX );
-
- for (double rotY=0; rotY < (itk::Math::pi*2); rotY+=0.33 )
+ // Epsilon. Allowed difference for rotationvalue
+ float eps = 0.0001;
+
+ // Cast ITK and MITK images and see if geometry stays
+ typedef itk::Image<double,2> Image2DType;
+ typedef itk::Image<double,3> Image3DType;
+
+ // Create 3D ITK Image from Scratch, cast to 3D MITK image, compare Geometries
+ Image3DType::Pointer image3DItk = Image3DType::New();
+ Image3DType::RegionType myRegion;
+ Image3DType::SizeType mySize;
+ Image3DType::IndexType myIndex;
+ Image3DType::SpacingType mySpacing;
+ Image3DType::DirectionType myDirection, rotMatrixX, rotMatrixY, rotMatrixZ;
+ mySpacing[0] = 31;
+ mySpacing[1] = 0.1;
+ mySpacing[2] = 2.9;
+ myIndex[0] = -15;
+ myIndex[1] = 15;
+ myIndex[2] = 12;
+ mySize[0] = 10;
+ mySize[1] = 2;
+ mySize[2] = 555;
+ myRegion.SetSize( mySize);
+ myRegion.SetIndex( myIndex );
+ image3DItk->SetSpacing(mySpacing);
+ image3DItk->SetRegions( myRegion);
+ image3DItk->Allocate();
+ image3DItk->FillBuffer(0);
+
+ myDirection.SetIdentity();
+ rotMatrixX.SetIdentity();
+ rotMatrixY.SetIdentity();
+ rotMatrixZ.SetIdentity();
+
+ mitk::Image::Pointer mitkImage;
+
+ // direction [row] [coloum]
+ MITK_TEST_OUTPUT( << "Casting a rotated 3D ITK Image to a MITK Image and check if Geometry is still same" );
+ for (double rotX=0; rotX < (itk::Math::pi*2); rotX+=0.4 )
+ {
+ // Set Rotation X
+ rotMatrixX[1][1] = cos( rotX );
+ rotMatrixX[1][2] = -sin( rotX );
+ rotMatrixX[2][1] = sin( rotX );
+ rotMatrixX[2][2] = cos( rotX );
+
+ for (double rotY=0; rotY < (itk::Math::pi*2); rotY+=0.33 )
+ {
+ // Set Rotation Y
+ rotMatrixY[0][0] = cos( rotY );
+ rotMatrixY[0][2] = sin( rotY );
+ rotMatrixY[2][0] = -sin( rotY );
+ rotMatrixY[2][2] = cos( rotY );
+
+ for (double rotZ=0; rotZ < (itk::Math::pi*2); rotZ+=0.5 )
{
- // Set Rotation Y
- rotMatrixY[0][0] = cos( rotY );
- rotMatrixY[0][2] = sin( rotY );
- rotMatrixY[2][0] = -sin( rotY );
- rotMatrixY[2][2] = cos( rotY );
-
- for (double rotZ=0; rotZ < (itk::Math::pi*2); rotZ+=0.5 )
- {
- // Set Rotation Z
- rotMatrixZ[0][0] = cos( rotZ );
- rotMatrixZ[0][1] = -sin( rotZ );
- rotMatrixZ[1][0] = sin( rotZ );
- rotMatrixZ[1][1] = cos( rotZ );
-
- // Multiply matrizes
- myDirection = myDirection * rotMatrixX * rotMatrixY * rotMatrixZ;
- image3DItk->SetDirection(myDirection);
- mitk::CastToMitkImage(image3DItk, mitkImage);
- const mitk::AffineTransform3D::MatrixType& matrix = mitkImage->GetGeometry()->GetIndexToWorldTransform()->GetMatrix();
-
- for (int row=0; row<3; row++)
+ // Set Rotation Z
+ rotMatrixZ[0][0] = cos( rotZ );
+ rotMatrixZ[0][1] = -sin( rotZ );
+ rotMatrixZ[1][0] = sin( rotZ );
+ rotMatrixZ[1][1] = cos( rotZ );
+
+ // Multiply matrizes
+ myDirection = myDirection * rotMatrixX * rotMatrixY * rotMatrixZ;
+ image3DItk->SetDirection(myDirection);
+ mitk::CastToMitkImage(image3DItk, mitkImage);
+ const mitk::AffineTransform3D::MatrixType& matrix = mitkImage->GetGeometry()->GetIndexToWorldTransform()->GetMatrix();
+
+ for (int row=0; row<3; row++)
+ {
+ for (int col=0; col<3; col++)
+ {
+ double mitkValue = matrix[row][col] / mitkImage->GetGeometry()->GetSpacing()[col];
+ double itkValue = myDirection[row][col];
+ double diff = mitkValue - itkValue;
+ // if you decrease this value, you can see that there might be QUITE high inaccuracy!!!
+ if (diff > eps) // need to check, how exact it SHOULD be .. since it is NOT EXACT!
{
- for (int col=0; col<3; col++)
- {
- double mitkValue = matrix[row][col] / mitkImage->GetGeometry()->GetSpacing()[col];
- double itkValue = myDirection[row][col];
- double diff = mitkValue - itkValue;
- // if you decrease this value, you can see that there might be QUITE high inaccuracy!!!
- if (diff > eps) // need to check, how exact it SHOULD be .. since it is NOT EXACT!
- {
- std::cout << "Had a difference of : " << diff;
- std::cout << "Error: Casting altered Geometry!";
- std::cout << "ITK Matrix:\n" << myDirection;
- std::cout << "Mitk Matrix (With Spacing):\n" << matrix;
- std::cout << "Mitk Spacing: " << mitkImage->GetGeometry()->GetSpacing();
- MITK_TEST_CONDITION_REQUIRED(false == true, "");
- return false;
- }
- }
+ std::cout << "Had a difference of : " << diff;
+ std::cout << "Error: Casting altered Geometry!";
+ std::cout << "ITK Matrix:\n" << myDirection;
+ std::cout << "Mitk Matrix (With Spacing):\n" << matrix;
+ std::cout << "Mitk Spacing: " << mitkImage->GetGeometry()->GetSpacing();
+ MITK_TEST_CONDITION_REQUIRED(false == true, "");
+ return false;
}
- }
+ }
+ }
}
- }
-
- // Create 2D ITK Image from Scratch, cast to 2D MITK image, compare Geometries
- Image2DType::Pointer image2DItk = Image2DType::New();
- Image2DType::RegionType myRegion2D;
- Image2DType::SizeType mySize2D;
- Image2DType::IndexType myIndex2D;
- Image2DType::SpacingType mySpacing2D;
- Image2DType::DirectionType myDirection2D, rotMatrix;
- mySpacing2D[0] = 31;
- mySpacing2D[1] = 0.1;
- myIndex2D[0] = -15;
- myIndex2D[1] = 15;
- mySize2D[0] = 10;
- mySize2D[1] = 2;
- myRegion2D.SetSize( mySize2D);
- myRegion2D.SetIndex( myIndex2D );
- image2DItk->SetSpacing(mySpacing2D);
- image2DItk->SetRegions( myRegion2D);
- image2DItk->Allocate();
- image2DItk->FillBuffer(0);
-
- myDirection2D.SetIdentity();
- rotMatrix.SetIdentity();
-
- // direction [row] [coloum]
- MITK_TEST_OUTPUT( << "Casting a rotated 2D ITK Image to a MITK Image and check if Geometry is still same" );
- for (double rotTheta=0; rotTheta < (itk::Math::pi*2); rotTheta+=0.1 )
- {
- // Set Rotation
- rotMatrix[0][0] = cos(rotTheta);
- rotMatrix[0][1] = -sin(rotTheta);
- rotMatrix[1][0] = sin(rotTheta);
- rotMatrix[1][1] = cos(rotTheta);
-
- // Multiply matrizes
- myDirection2D = myDirection2D * rotMatrix;
- image2DItk->SetDirection(myDirection2D);
- mitk::CastToMitkImage(image2DItk, mitkImage);
- const mitk::AffineTransform3D::MatrixType& matrix = mitkImage->GetGeometry()->GetIndexToWorldTransform()->GetMatrix();
-
- // Compare MITK and ITK matrix
- for (int row=0; row<3; row++)
+ }
+ }
+
+ // Create 2D ITK Image from Scratch, cast to 2D MITK image, compare Geometries
+ Image2DType::Pointer image2DItk = Image2DType::New();
+ Image2DType::RegionType myRegion2D;
+ Image2DType::SizeType mySize2D;
+ Image2DType::IndexType myIndex2D;
+ Image2DType::SpacingType mySpacing2D;
+ Image2DType::DirectionType myDirection2D, rotMatrix;
+ mySpacing2D[0] = 31;
+ mySpacing2D[1] = 0.1;
+ myIndex2D[0] = -15;
+ myIndex2D[1] = 15;
+ mySize2D[0] = 10;
+ mySize2D[1] = 2;
+ myRegion2D.SetSize( mySize2D);
+ myRegion2D.SetIndex( myIndex2D );
+ image2DItk->SetSpacing(mySpacing2D);
+ image2DItk->SetRegions( myRegion2D);
+ image2DItk->Allocate();
+ image2DItk->FillBuffer(0);
+
+ myDirection2D.SetIdentity();
+ rotMatrix.SetIdentity();
+
+ // direction [row] [coloum]
+ MITK_TEST_OUTPUT( << "Casting a rotated 2D ITK Image to a MITK Image and check if Geometry is still same" );
+ for (double rotTheta=0; rotTheta < (itk::Math::pi*2); rotTheta+=0.1 )
+ {
+ // Set Rotation
+ rotMatrix[0][0] = cos(rotTheta);
+ rotMatrix[0][1] = -sin(rotTheta);
+ rotMatrix[1][0] = sin(rotTheta);
+ rotMatrix[1][1] = cos(rotTheta);
+
+ // Multiply matrizes
+ myDirection2D = myDirection2D * rotMatrix;
+ image2DItk->SetDirection(myDirection2D);
+ mitk::CastToMitkImage(image2DItk, mitkImage);
+ const mitk::AffineTransform3D::MatrixType& matrix = mitkImage->GetGeometry()->GetIndexToWorldTransform()->GetMatrix();
+
+ // Compare MITK and ITK matrix
+ for (int row=0; row<3; row++)
+ {
+ for (int col=0; col<3; col++)
{
- for (int col=0; col<3; col++)
- {
- double mitkValue = matrix[row][col] / mitkImage->GetGeometry()->GetSpacing()[col];
- if ((row == 2) && (col == row))
- {
- if (mitkValue != 1)
- {
- MITK_TEST_OUTPUT(<< "After casting a 2D ITK to 3D MITK images, MITK matrix values for 0|2, 1|2, 2|0, 2|1 MUST be 0 and value for 2|2 must be 1");
- return false;
- }
- }
- else if ((row == 2) || (col == 2))
- {
- if (mitkValue != 0)
- {
- MITK_TEST_OUTPUT(<< "After casting a 2D ITK to 3D MITK images, MITK matrix values for 0|2, 1|2, 2|0, 2|1 MUST be 0 and value for 2|2 must be 1");
- return false;
- }
- }
- else
- {
- double itkValue = myDirection2D[row][col];
- double diff = mitkValue - itkValue;
- // if you decrease this value, you can see that there might be QUITE high inaccuracy!!!
- if (diff > eps) // need to check, how exact it SHOULD be .. since it is NOT EXACT!
- {
- std::cout << "Had a difference of : " << diff;
- std::cout << "Error: Casting altered Geometry!";
- std::cout << "ITK Matrix:\n" << myDirection2D;
- std::cout << "Mitk Matrix (With Spacing):\n" << matrix;
- std::cout << "Mitk Spacing: " << mitkImage->GetGeometry()->GetSpacing();
- MITK_TEST_CONDITION_REQUIRED(false == true, "");
- return false;
- }
- }
- }
+ double mitkValue = matrix[row][col] / mitkImage->GetGeometry()->GetSpacing()[col];
+ if ((row == 2) && (col == row))
+ {
+ if (mitkValue != 1)
+ {
+ MITK_TEST_OUTPUT(<< "After casting a 2D ITK to 3D MITK images, MITK matrix values for 0|2, 1|2, 2|0, 2|1 MUST be 0 and value for 2|2 must be 1");
+ return false;
+ }
+ }
+ else if ((row == 2) || (col == 2))
+ {
+ if (mitkValue != 0)
+ {
+ MITK_TEST_OUTPUT(<< "After casting a 2D ITK to 3D MITK images, MITK matrix values for 0|2, 1|2, 2|0, 2|1 MUST be 0 and value for 2|2 must be 1");
+ return false;
+ }
+ }
+ else
+ {
+ double itkValue = myDirection2D[row][col];
+ double diff = mitkValue - itkValue;
+ // if you decrease this value, you can see that there might be QUITE high inaccuracy!!!
+ if (diff > eps) // need to check, how exact it SHOULD be .. since it is NOT EXACT!
+ {
+ std::cout << "Had a difference of : " << diff;
+ std::cout << "Error: Casting altered Geometry!";
+ std::cout << "ITK Matrix:\n" << myDirection2D;
+ std::cout << "Mitk Matrix (With Spacing):\n" << matrix;
+ std::cout << "Mitk Spacing: " << mitkImage->GetGeometry()->GetSpacing();
+ MITK_TEST_CONDITION_REQUIRED(false == true, "");
+ return false;
+ }
+ }
}
- }
+ }
+ }
- // THIS WAS TESTED:
- // 2D ITK -> 2D MITK,
- // 3D ITK -> 3D MITK,
+ // THIS WAS TESTED:
+ // 2D ITK -> 2D MITK,
+ // 3D ITK -> 3D MITK,
- // Still need to test: 2D MITK Image with ADDITIONAL INFORMATION IN MATRIX -> 2D ITK
- // 1. Possibility: 3x3 MITK matrix can be converted without loss into 2x2 ITK matrix
- // 2. Possibility: 3x3 MITK matrix can only be converted with loss into 2x2 ITK matrix
- // .. before implementing this, we wait for further development in geometry classes (e.g. Geoemtry3D::SetRotation(..))
+ // Still need to test: 2D MITK Image with ADDITIONAL INFORMATION IN MATRIX -> 2D ITK
+ // 1. Possibility: 3x3 MITK matrix can be converted without loss into 2x2 ITK matrix
+ // 2. Possibility: 3x3 MITK matrix can only be converted with loss into 2x2 ITK matrix
+ // .. before implementing this, we wait for further development in geometry classes (e.g. Geoemtry3D::SetRotation(..))
- return EXIT_SUCCESS;
+ return EXIT_SUCCESS;
}
int mitkGeometry3DTest(int /*argc*/, char* /*argv*/[])
{
- MITK_TEST_BEGIN(mitkGeometry3DTest);
+ MITK_TEST_BEGIN(mitkGeometry3DTest);
- int result;
+ int result;
- MITK_TEST_CONDITION_REQUIRED( (result = testItkImageIsCenterBased()) == EXIT_SUCCESS, "");
+ MITK_TEST_CONDITION_REQUIRED( (result = testItkImageIsCenterBased()) == EXIT_SUCCESS, "");
- MITK_TEST_OUTPUT(<< "Running main part of test with ImageGeometry = false");
- MITK_TEST_CONDITION_REQUIRED( (result = testGeometry3D(false)) == EXIT_SUCCESS, "");
+ MITK_TEST_OUTPUT(<< "Running main part of test with ImageGeometry = false");
+ MITK_TEST_CONDITION_REQUIRED( (result = testGeometry3D(false)) == EXIT_SUCCESS, "");
- MITK_TEST_OUTPUT(<< "Running main part of test with ImageGeometry = true");
- MITK_TEST_CONDITION_REQUIRED( (result = testGeometry3D(true)) == EXIT_SUCCESS, "");
+ MITK_TEST_OUTPUT(<< "Running main part of test with ImageGeometry = true");
+ MITK_TEST_CONDITION_REQUIRED( (result = testGeometry3D(true)) == EXIT_SUCCESS, "");
- MITK_TEST_OUTPUT(<< "Running test to see if Casting MITK to ITK and the other way around destroys geometry");
- MITK_TEST_CONDITION_REQUIRED( (result = testGeometryAfterCasting()) == EXIT_SUCCESS, "");
+ MITK_TEST_OUTPUT(<< "Running test to see if Casting MITK to ITK and the other way around destroys geometry");
+ MITK_TEST_CONDITION_REQUIRED( (result = testGeometryAfterCasting()) == EXIT_SUCCESS, "");
- MITK_TEST_END();
+ MITK_TEST_END();
- return EXIT_SUCCESS;
-}
\ No newline at end of file
+ return EXIT_SUCCESS;
+}
diff --git a/Core/Code/Testing/mitkGeometryDataToSurfaceFilterTest.cpp b/Core/Code/Testing/mitkGeometryDataToSurfaceFilterTest.cpp
index dbd63895d4..2d7df08084 100644
--- a/Core/Code/Testing/mitkGeometryDataToSurfaceFilterTest.cpp
+++ b/Core/Code/Testing/mitkGeometryDataToSurfaceFilterTest.cpp
@@ -1,253 +1,253 @@
/*===================================================================
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 "mitkGeometry2DDataToSurfaceFilter.h"
+#include "mitkPlaneGeometryDataToSurfaceFilter.h"
#include "mitkSurface.h"
#include "mitkPlaneGeometry.h"
-#include "mitkGeometry2DData.h"
+#include "mitkPlaneGeometryData.h"
#include "vtkPolyData.h"
#include <fstream>
template <typename TScalarType>
-int testExpectedIndexBoundingBox(mitk::Geometry3D* geometry, TScalarType expectedIndexBounds[6])
+int testExpectedIndexBoundingBox(mitk::BaseGeometry* geometry, TScalarType expectedIndexBounds[6])
{
mitk::BoundingBox* bb = const_cast<mitk::BoundingBox*>(geometry->GetBoundingBox());
mitk::BoundingBox::BoundsArrayType bounds = bb->GetBounds();
int i;
for(i=0;i<6;++i)
{
if( mitk::Equal(bounds[i], expectedIndexBounds[i]) == false)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
}
std::cout<<"[PASSED]"<<std::endl;
return EXIT_SUCCESS;
}
template <typename TScalarType>
-int testExpectedAxisParallelBoundingBox(mitk::Geometry3D* geometry, TScalarType expectedAxisParallelBounds[6])
+int testExpectedAxisParallelBoundingBox(mitk::BaseGeometry* geometry, TScalarType expectedAxisParallelBounds[6])
{
mitk::BoundingBox::Pointer bb = geometry->CalculateBoundingBoxRelativeToTransform(NULL);
mitk::BoundingBox::BoundsArrayType bounds = bb->GetBounds();
int i;
for(i=0;i<6;++i)
{
if( mitk::Equal(bounds[i], expectedAxisParallelBounds[i]) == false)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
}
std::cout<<"[PASSED]"<<std::endl;
return EXIT_SUCCESS;
}
int testSurfaceBoundingBoxConsistency(mitk::Surface* surface, bool expectIdentityTransform)
{
int result;
std::cout << " Testing surface contents: ";
if ((surface == NULL )
|| (surface->GetVtkPolyData() == NULL)
|| (surface->GetVtkPolyData()->GetNumberOfPoints() == 0 )) {
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
else {
std::cout<<"[PASSED]"<<std::endl;
}
double bounds[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
vtkPolyData* polys = surface->GetVtkPolyData();
polys->ComputeBounds();
polys->GetBounds( bounds );
int i;
if(expectIdentityTransform == false)
{
- mitk::Geometry2D::Pointer geometry = mitk::Geometry2D::New();
+ mitk::PlaneGeometry::Pointer geometry = mitk::PlaneGeometry::New();
geometry->SetFloatBounds(bounds);
geometry->SetIndexToWorldTransform(surface->GetGeometry()->GetIndexToWorldTransform());
mitk::BoundingBox::BoundsArrayType bb = const_cast<mitk::BoundingBox*>(geometry->GetBoundingBox())->GetBounds();
for(i=0;i<6;++i)
bounds[i]=bb[i];
}
std::cout << " Testing GetBoundingBox() ";
if((result=testExpectedIndexBoundingBox(surface->GetGeometry(), bounds)) != EXIT_SUCCESS)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
return EXIT_SUCCESS;
}
-int testGeometryDataToSurfaceFilter(mitk::Geometry2DDataToSurfaceFilter* geometryToSurfaceFilter, mitk::ScalarType expectedIndexBounds[6], mitk::ScalarType expectedAxisParallelBounds[6], bool expectIdentityTransform)
+int testGeometryDataToSurfaceFilter(mitk::PlaneGeometryDataToSurfaceFilter* geometryToSurfaceFilter, mitk::ScalarType expectedIndexBounds[6], mitk::ScalarType expectedAxisParallelBounds[6], bool expectIdentityTransform)
{
int result;
std::cout << "Testing SetRequestedRegionToLargestPossibleRegion(): ";
geometryToSurfaceFilter->GetOutput()->SetRequestedRegionToLargestPossibleRegion();
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing UpdateOutputInformation(): ";
geometryToSurfaceFilter->UpdateOutputInformation();
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing correctness of bounding-box after UpdateOutputInformation(): ";
if((result=testExpectedIndexBoundingBox(geometryToSurfaceFilter->GetOutput()->GetGeometry(), expectedIndexBounds)) != EXIT_SUCCESS) {
return result;
}
std::cout << "Testing correctness of axis-parallel bounding-box after UpdateOutputInformation(): ";
if((result=testExpectedAxisParallelBoundingBox(geometryToSurfaceFilter->GetOutput()->GetGeometry(), expectedAxisParallelBounds)) != EXIT_SUCCESS) {
return result;
}
std::cout << "Testing Update(): ";
geometryToSurfaceFilter->Update();
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing correctness of bounding-box after Update(): ";
if((result=testExpectedIndexBoundingBox(geometryToSurfaceFilter->GetOutput()->GetGeometry(), expectedIndexBounds)) != EXIT_SUCCESS) {
return result;
}
std::cout << "Testing correctness of axis-parallel bounding-box after UpdateOutputInformation(): ";
if((result=testExpectedAxisParallelBoundingBox(geometryToSurfaceFilter->GetOutput()->GetGeometry(), expectedAxisParallelBounds)) != EXIT_SUCCESS) {
return result;
}
std::cout << "Testing bounding-box consistency: "<<std::endl;
if((result=testSurfaceBoundingBoxConsistency(geometryToSurfaceFilter->GetOutput(), expectIdentityTransform)) != EXIT_SUCCESS) {
std::cout<<"[FAILED]"<<std::endl;
return result;
}
else {
std::cout<<"[PASSED]"<<std::endl;
}
return EXIT_SUCCESS;
}
int mitkGeometryDataToSurfaceFilterTest(int /*argc*/, char* /*argv*/[])
{
int result;
- std::cout << "Testing mitk::Geometry2DDataToSurfaceFilter: " << std::endl;
+ std::cout << "Testing mitk::PlaneGeometryDataToSurfaceFilter: " << std::endl;
- mitk::Geometry2DDataToSurfaceFilter::Pointer geometryToSurfaceFilter;
- std::cout << "Testing Geometry2DDataToSurfaceFilter::New(): ";
- geometryToSurfaceFilter = mitk::Geometry2DDataToSurfaceFilter::New();
+ mitk::PlaneGeometryDataToSurfaceFilter::Pointer geometryToSurfaceFilter;
+ std::cout << "Testing PlaneGeometryDataToSurfaceFilter::New(): ";
+ geometryToSurfaceFilter = mitk::PlaneGeometryDataToSurfaceFilter::New();
if (geometryToSurfaceFilter.IsNull()) {
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
else {
std::cout<<"[PASSED]"<<std::endl;
}
mitk::Point3D origin;
mitk::PlaneGeometry::Pointer plane = mitk::PlaneGeometry::New();
plane->InitializeStandardPlane(50, 100);
mitk::FillVector3D(origin, 1.0, 2.0, 3.0);
plane->SetOrigin(origin);
- mitk::Geometry2DData::Pointer geometryData = mitk::Geometry2DData::New();
- geometryData->SetGeometry2D(plane);
+ mitk::PlaneGeometryData::Pointer geometryData = mitk::PlaneGeometryData::New();
+ geometryData->SetPlaneGeometry(plane);
std::cout << "Testing SetInput(): ";
geometryToSurfaceFilter->SetInput(geometryData);
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing GetInput(): ";
if (geometryToSurfaceFilter->GetInput() != geometryData ) {
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
else {
std::cout<<"[PASSED]"<<std::endl;
}
- std::cout << "Testing default of Geometry2DDataToSurfaceFilter::m_PlaceByGeometry (expected is false): ";
+ std::cout << "Testing default of PlaneGeometryDataToSurfaceFilter::m_PlaceByGeometry (expected is false): ";
if (geometryToSurfaceFilter->GetPlaceByGeometry() != false ) {
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
else {
std::cout<<"[PASSED]"<<std::endl;
}
// test with m_PlaceByGeometry==false
mitk::ScalarType expectedBoundsFinal[6] = {1.0, 51.0, 2.0, 102.0, 3.0, 3.0};
if((result=testGeometryDataToSurfaceFilter(geometryToSurfaceFilter, expectedBoundsFinal, expectedBoundsFinal, true)) != EXIT_SUCCESS) {
return result;
}
- std::cout << "Testing Geometry2DDataToSurfaceFilter::SetPlaceByGeometry(true): ";
+ std::cout << "Testing PlaneGeometryDataToSurfaceFilter::SetPlaceByGeometry(true): ";
geometryToSurfaceFilter->SetPlaceByGeometry(true);
if (geometryToSurfaceFilter->GetPlaceByGeometry() != true ) {
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
else {
std::cout<<"[PASSED]"<<std::endl;
}
// test with m_PlaceByGeometry==true
mitk::ScalarType expectedIndexBounds[6] = {0.0, 50.0, 0.0, 100.0, 0.0, 0.0};
mitk::ScalarType expectedAxisParallelBounds[6] = {1.0, 51.0, 2.0, 102.0, 3.0, 3.0};
if((result=testGeometryDataToSurfaceFilter(geometryToSurfaceFilter, expectedIndexBounds, expectedAxisParallelBounds, true)) != EXIT_SUCCESS) {
return result;
}
// test with specified BoundingBox (m_PlaceByGeometry is irrelevant for this test)
mitk::BoundingBox::Pointer boundingBox = mitk::BoundingBox::New();
mitk::Point3D bbMin, bbMax;
mitk::FillVector3D( bbMin, 10.0, 10.0, -6.0 );
mitk::FillVector3D( bbMax, 40.0, 90.0, 6.0 );
mitk::BoundingBox::PointsContainer::Pointer pointsContainer = mitk::BoundingBox::PointsContainer::New();
pointsContainer->InsertElement( 0, bbMin );
pointsContainer->InsertElement( 1, bbMax );
boundingBox->SetPoints( pointsContainer );
boundingBox->ComputeBoundingBox();
geometryToSurfaceFilter->SetPlaceByGeometry( true );
geometryToSurfaceFilter->SetBoundingBox( boundingBox );
mitk::ScalarType expectedIndexBoundsWithBB[6] = {9.0, 39.0, 8.0, 88.0, 0.0, 0.0};
mitk::ScalarType expectedAxisParallelBoundsWithBB[6] = {10.0, 40.0, 10.0, 90.0, 3.0, 3.0};
if((result=testGeometryDataToSurfaceFilter(geometryToSurfaceFilter, expectedIndexBoundsWithBB, expectedAxisParallelBoundsWithBB, true)) != EXIT_SUCCESS) {
return result;
}
std::cout<<"[TEST DONE]"<<std::endl;
return EXIT_SUCCESS;
}
diff --git a/Core/Code/Testing/mitkIOUtilTest.cpp b/Core/Code/Testing/mitkIOUtilTest.cpp
index f273d03d7e..bbe74167ad 100644
--- a/Core/Code/Testing/mitkIOUtilTest.cpp
+++ b/Core/Code/Testing/mitkIOUtilTest.cpp
@@ -1,204 +1,202 @@
/*===================================================================
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 "mitkTestingMacros.h"
#include <mitkTestingConfig.h>
#include <mitkTestFixture.h>
#include <mitkIOUtil.h>
#include <mitkImageGenerator.h>
#include <itksys/SystemTools.hxx>
class mitkIOUtilTestSuite : public mitk::TestFixture
{
-
CPPUNIT_TEST_SUITE(mitkIOUtilTestSuite);
MITK_TEST(TestTempMethods);
MITK_TEST(TestLoadAndSaveImage);
MITK_TEST(TestLoadAndSavePointSet);
MITK_TEST(TestLoadAndSaveSurface);
MITK_TEST(TestTempMethodsForUniqueFilenames);
CPPUNIT_TEST_SUITE_END();
private:
std::string m_ImagePath;
std::string m_SurfacePath;
std::string m_PointSetPath;
public:
void setUp()
{
m_ImagePath = GetTestDataFilePath("Pic3D.nrrd");
m_SurfacePath = GetTestDataFilePath("binary.stl");
m_PointSetPath = GetTestDataFilePath("pointSet.mps");
}
void TestTempMethods()
{
std::string tmpPath = mitk::IOUtil::GetTempPath();
CPPUNIT_ASSERT(!tmpPath.empty());
std::ofstream tmpFile;
std::string tmpFilePath = mitk::IOUtil::CreateTemporaryFile(tmpFile);
CPPUNIT_ASSERT(tmpFile && tmpFile.is_open());
CPPUNIT_ASSERT(tmpFilePath.size() > tmpPath.size());
CPPUNIT_ASSERT(tmpFilePath.substr(0, tmpPath.size()) == tmpPath);
tmpFile.close();
CPPUNIT_ASSERT(std::remove(tmpFilePath.c_str()) == 0);
std::string programPath = mitk::IOUtil::GetProgramPath();
CPPUNIT_ASSERT(!programPath.empty());
std::ofstream tmpFile2;
std::string tmpFilePath2 = mitk::IOUtil::CreateTemporaryFile(tmpFile2, "my-XXXXXX", programPath);
CPPUNIT_ASSERT(tmpFile2 && tmpFile2.is_open());
CPPUNIT_ASSERT(tmpFilePath2.size() > programPath.size());
CPPUNIT_ASSERT(tmpFilePath2.substr(0, programPath.size()) == programPath);
tmpFile2.close();
CPPUNIT_ASSERT(std::remove(tmpFilePath2.c_str()) == 0);
std::ofstream tmpFile3;
std::string tmpFilePath3 = mitk::IOUtil::CreateTemporaryFile(tmpFile3, std::ios_base::binary,
- "my-XXXXXX.TXT", programPath);
+ "my-XXXXXX.TXT", programPath);
CPPUNIT_ASSERT(tmpFile3 && tmpFile3.is_open());
CPPUNIT_ASSERT(tmpFilePath3.size() > programPath.size());
CPPUNIT_ASSERT(tmpFilePath3.substr(0, programPath.size()) == programPath);
CPPUNIT_ASSERT(tmpFilePath3.substr(tmpFilePath3.size() - 13, 3) == "my-");
CPPUNIT_ASSERT(tmpFilePath3.substr(tmpFilePath3.size() - 4) == ".TXT");
tmpFile3.close();
//CPPUNIT_ASSERT(std::remove(tmpFilePath3.c_str()) == 0)
std::string tmpFilePath4 = mitk::IOUtil::CreateTemporaryFile();
std::ofstream file;
file.open(tmpFilePath4.c_str());
CPPUNIT_ASSERT_MESSAGE("Testing if file exists after CreateTemporaryFile()",file.is_open());
CPPUNIT_ASSERT_THROW(mitk::IOUtil::CreateTemporaryFile(tmpFile2, "XX"), mitk::Exception);
std::string tmpDir = mitk::IOUtil::CreateTemporaryDirectory();
CPPUNIT_ASSERT(tmpDir.size() > tmpPath.size());
CPPUNIT_ASSERT(tmpDir.substr(0, tmpPath.size()) == tmpPath);
CPPUNIT_ASSERT(itksys::SystemTools::RemoveADirectory(tmpDir.c_str()));
std::string tmpDir2 = mitk::IOUtil::CreateTemporaryDirectory("my-XXXXXX", programPath);
CPPUNIT_ASSERT(tmpDir2.size() > programPath.size());
CPPUNIT_ASSERT(tmpDir2.substr(0, programPath.size()) == programPath);
CPPUNIT_ASSERT(itksys::SystemTools::RemoveADirectory(tmpDir2.c_str()));
}
void TestTempMethodsForUniqueFilenames()
{
int numberOfFiles = 100;
//create 100 empty files
std::vector<std::string> v100filenames;
for(int i=0; i<numberOfFiles; i++) {v100filenames.push_back(mitk::IOUtil::CreateTemporaryFile());}
//check if all of them are unique
for(int i=0; i<numberOfFiles; i++) for(int j=0; j<numberOfFiles; j++)
{
if(i!=j)
{
std::stringstream message;
message << "Checking if file " << i << " and file " << j << " are different, which should be the case because each of them should be unique.";
CPPUNIT_ASSERT_MESSAGE(message.str(),(v100filenames.at(i)!=v100filenames.at(j)));
}
}
//delete all the files / clean up
for(int i=0; i<numberOfFiles; i++) {std::remove(v100filenames.at(i).c_str());}
}
void TestLoadAndSaveImage()
{
mitk::Image::Pointer img1 = mitk::IOUtil::LoadImage(m_ImagePath);
CPPUNIT_ASSERT( img1.IsNotNull());
std::ofstream tmpStream;
std::string imagePath = mitk::IOUtil::CreateTemporaryFile(tmpStream, "diffpic3d-XXXXXX.nrrd");
tmpStream.close();
std::string imagePath2 = mitk::IOUtil::CreateTemporaryFile(tmpStream, "diffpic3d-XXXXXX.nii.gz");
tmpStream.close();
// the cases where no exception should be thrown
CPPUNIT_ASSERT(mitk::IOUtil::SaveImage(img1, imagePath));
CPPUNIT_ASSERT(mitk::IOUtil::SaveBaseData(img1.GetPointer(), imagePath2));
//load data which does not exist
CPPUNIT_ASSERT_THROW(mitk::IOUtil::LoadImage("fileWhichDoesNotExist.nrrd"), mitk::Exception);
//delete the files after the test is done
std::remove(imagePath.c_str());
std::remove(imagePath2.c_str());
mitk::Image::Pointer relativImage = mitk::ImageGenerator::GenerateGradientImage<float>(4,4,4,1);
std::string imagePath3 = mitk::IOUtil::CreateTemporaryFile(tmpStream, "XXXXXX.nrrd");
tmpStream.close();
mitk::IOUtil::SaveImage(relativImage, imagePath3);
CPPUNIT_ASSERT_NO_THROW(mitk::IOUtil::LoadImage(imagePath3));
std::remove(imagePath3.c_str());
}
void TestLoadAndSavePointSet()
{
mitk::PointSet::Pointer pointset = mitk::IOUtil::LoadPointSet(m_PointSetPath);
CPPUNIT_ASSERT( pointset.IsNotNull());
std::ofstream tmpStream;
std::string pointSetPath = mitk::IOUtil::CreateTemporaryFile(tmpStream, "XXXXXX.mps");
tmpStream.close();
std::string pointSetPathWithDefaultExtension = mitk::IOUtil::CreateTemporaryFile(tmpStream, "XXXXXX.mps");
tmpStream.close();
std::string pointSetPathWithoutDefaultExtension = mitk::IOUtil::CreateTemporaryFile(tmpStream, "XXXXXX.xXx");
tmpStream.close();
// the cases where no exception should be thrown
CPPUNIT_ASSERT(mitk::IOUtil::SavePointSet(pointset, pointSetPathWithDefaultExtension));
// test if defaultextension is inserted if no extension is present
CPPUNIT_ASSERT(mitk::IOUtil::SavePointSet(pointset, pointSetPathWithoutDefaultExtension.c_str()));
//delete the files after the test is done
std::remove(pointSetPath.c_str());
std::remove(pointSetPathWithDefaultExtension.c_str());
std::remove(pointSetPathWithoutDefaultExtension.c_str());
}
void TestLoadAndSaveSurface()
{
mitk::Surface::Pointer surface = mitk::IOUtil::LoadSurface(m_SurfacePath);
CPPUNIT_ASSERT( surface.IsNotNull());
std::ofstream tmpStream;
std::string surfacePath = mitk::IOUtil::CreateTemporaryFile(tmpStream, "diffsurface-XXXXXX.stl");
// the cases where no exception should be thrown
CPPUNIT_ASSERT(mitk::IOUtil::SaveSurface(surface, surfacePath));
// test if exception is thrown as expected on unknown extsension
CPPUNIT_ASSERT_THROW(mitk::IOUtil::SaveSurface(surface,"testSurface.xXx"), mitk::Exception);
//delete the files after the test is done
std::remove(surfacePath.c_str());
}
-
};
MITK_TEST_SUITE_REGISTRATION(mitkIOUtil)
diff --git a/Core/Code/Testing/mitkImageTest.cpp b/Core/Code/Testing/mitkImageTest.cpp
index ad3aedf736..ffbbc84044 100644
--- a/Core/Code/Testing/mitkImageTest.cpp
+++ b/Core/Code/Testing/mitkImageTest.cpp
@@ -1,526 +1,526 @@
/*===================================================================
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.
===================================================================*/
// mitk includes
#include <mitkImage.h>
#include <mitkImageDataItem.h>
#include <mitkImageCast.h>
#include "mitkItkImageFileReader.h"
#include <mitkTestingMacros.h>
#include <mitkImageStatisticsHolder.h>
#include "mitkImageGenerator.h"
#include "mitkImageReadAccessor.h"
#include "mitkException.h"
#include "mitkPixelTypeMultiplex.h"
#include "mitkImagePixelReadAccessor.h"
#include "mitkImageSliceSelector.h"
// itk includes
#include <itkImage.h>
#include <itkMersenneTwisterRandomVariateGenerator.h>
// stl includes
#include <fstream>
// vtk includes
#include <vtkImageData.h>
// Checks if reference count is correct after using GetVtkImageData()
bool ImageVtkDataReferenceCheck(const char* fname) {
const std::string filename = std::string(fname);
mitk::ItkImageFileReader::Pointer imageReader = mitk::ItkImageFileReader::New();
try
{
imageReader->SetFileName(filename);
imageReader->Update();
}
catch(...) {
MITK_TEST_FAILED_MSG(<< "Could not read file for testing: " << filename);
return false;
}
{
mitk::Image::Pointer image = imageReader->GetOutput();
vtkImageData* vtk = image->GetVtkImageData();
if(vtk == NULL)
return false;
}
return true;
}
template <class T>
void TestRandomPixelAccess( const mitk::PixelType ptype, mitk::Image::Pointer image, mitk::Point3D & point, mitk::ScalarType & value )
{
// generate a random point in world coordinates
mitk::Point3D xMax, yMax, zMax, xMaxIndex, yMaxIndex, zMaxIndex;
xMaxIndex.Fill(0.0f);
yMaxIndex.Fill(0.0f);
zMaxIndex.Fill(0.0f);
xMaxIndex[0] = image->GetLargestPossibleRegion().GetSize()[0];
yMaxIndex[1] = image->GetLargestPossibleRegion().GetSize()[1];
zMaxIndex[2] = image->GetLargestPossibleRegion().GetSize()[2];
image->GetGeometry()->IndexToWorld(xMaxIndex, xMax);
image->GetGeometry()->IndexToWorld(yMaxIndex, yMax);
image->GetGeometry()->IndexToWorld(zMaxIndex, zMax);
MITK_INFO << "Origin " << image->GetGeometry()->GetOrigin()[0] << " "<< image->GetGeometry()->GetOrigin()[1] << " "<< image->GetGeometry()->GetOrigin()[2] << "";
MITK_INFO << "MaxExtend " << xMax[0] << " "<< yMax[1] << " "<< zMax[2] << "";
itk::Statistics::MersenneTwisterRandomVariateGenerator::Pointer randomGenerator = itk::Statistics::MersenneTwisterRandomVariateGenerator::New();
randomGenerator->Initialize( std::rand() ); // initialize with random value, to get sensible random points for the image
point[0] = randomGenerator->GetUniformVariate( image->GetGeometry()->GetOrigin()[0], xMax[0]);
point[1] = randomGenerator->GetUniformVariate( image->GetGeometry()->GetOrigin()[1], yMax[1]);
point[2] = randomGenerator->GetUniformVariate( image->GetGeometry()->GetOrigin()[2], zMax[2]);
MITK_INFO << "RandomPoint " << point[0] << " "<< point[1] << " "<< point[2] << "";
// test values and max/min
mitk::ScalarType imageMin = image->GetStatistics()->GetScalarValueMin();
mitk::ScalarType imageMax = image->GetStatistics()->GetScalarValueMax();
// test accessing PixelValue with coordinate leading to a negative index
const mitk::Point3D geom_origin = image->GetGeometry()->GetOrigin();
const mitk::Point3D geom_center = image->GetGeometry()->GetCenter();
// shift position from origin outside of the image ( in the opposite direction to [center-origin] vector which points in the inside)
mitk::Point3D position = geom_origin + (geom_origin - geom_center);
MITK_INFO << "Testing access outside of the image";
unsigned int dim = image->GetDimension();
if(dim == 3 || dim == 4){
mitk::ImagePixelReadAccessor<T,3> imAccess3(image,image->GetVolumeData(0));
// Comparison ?>=0 not needed since all position[i] and timestep are unsigned int
// (position[0]>=0 && position[1] >=0 && position[2]>=0 && timestep>=0)
// bug-11978 : we still need to catch index with negative values
if ( point[0] < 0 ||
point[1] < 0 ||
point[2] < 0 )
{
MITK_WARN << "Given position ("<< point << ") is out of image range, returning 0." ;
}
else {
value = static_cast<mitk::ScalarType>(imAccess3.GetPixelByWorldCoordinates(point));
MITK_TEST_CONDITION( (value >= imageMin && value <= imageMax), "Value returned is between max/min");
}
mitk::Index3D itkIndex;
image->GetGeometry()->WorldToIndex(position, itkIndex);
MITK_TEST_FOR_EXCEPTION_BEGIN(mitk::Exception);
imAccess3.GetPixelByIndexSafe(itkIndex);
MITK_TEST_FOR_EXCEPTION_END(mitk::Exception);
}
MITK_INFO << imageMin << " "<< imageMax << " "<< value << "";
}
class mitkImageTestClass
{
public:
void SetClonedGeometry_None_ClonedEqualInput()
{
mitk::Image::Pointer image = mitk::ImageGenerator::GenerateRandomImage<float>(100, 100, 100, 1, 0.2, 0.3, 0.4);
//-----------------
// geometry information for image
mitk::Point3D origin;
mitk::Vector3D right, bottom;
mitk::Vector3D spacing;
mitk::FillVector3D(origin, 17.0, 19.92, 7.83);
mitk::FillVector3D(right, 1.0, 2.0, 3.0);
mitk::FillVector3D(bottom, 0.0, -3.0, 2.0);
mitk::FillVector3D(spacing, 0.78, 0.91, 2.23);
//InitializeStandardPlane(rightVector, downVector, spacing)
mitk::PlaneGeometry::Pointer planegeometry = mitk::PlaneGeometry::New();
planegeometry->InitializeStandardPlane(100, 100, right, bottom, &spacing);
planegeometry->SetOrigin(origin);
planegeometry->ChangeImageGeometryConsideringOriginOffset(true);
image->SetClonedGeometry(planegeometry);
- mitk::Geometry3D::Pointer imageGeometry = image->GetGeometry();
+ mitk::BaseGeometry::Pointer imageGeometry = image->GetGeometry();
itk::ScalableAffineTransform<mitk::ScalarType,3>* frameNew = imageGeometry->GetIndexToWorldTransform();
itk::ScalableAffineTransform<mitk::ScalarType,3>* frameOld = planegeometry->GetIndexToWorldTransform();
bool matrixEqual = true;
for (int i = 0; i < 16; ++i)
{
double valueNew = *(frameNew->GetMatrix()[i]);
double valueOld = *(frameOld->GetMatrix()[i]);
//MITK_INFO << "Index: " << i << " Old: " << valueOld << " New: " << valueNew << " Difference:" << valueOld-valueNew<< std::endl;
matrixEqual = matrixEqual && mitk::Equal(valueNew, valueOld, mitk::eps);
}
// Disabled because this test fails on the dashboard. Does not fail on my machine.
// See Bug 6505
// MITK_TEST_CONDITION(matrixEqual, "Matrix elements of cloned matrix equal original matrix");
}
};
int mitkImageTest(int argc, char* argv[])
{
MITK_TEST_BEGIN(mitkImageTest);
mitkImageTestClass tester;
tester.SetClonedGeometry_None_ClonedEqualInput();
//Create Image out of nowhere
mitk::Image::Pointer imgMem = mitk::Image::New();
mitk::PixelType pt = mitk::MakeScalarPixelType<int>();
unsigned int dim[]={100,100,20};
MITK_TEST_CONDITION_REQUIRED( imgMem.IsNotNull(), "An image was created. ");
// Initialize image
imgMem->Initialize( pt, 3, dim);
MITK_TEST_CONDITION_REQUIRED( imgMem->IsInitialized(), "Image::IsInitialized() ?");
MITK_TEST_CONDITION_REQUIRED( imgMem->GetPixelType() == pt, "PixelType was set correctly.");
int *p = NULL;
int *p2 = NULL;
try
{
mitk::ImageReadAccessor imgMemAcc(imgMem);
p = (int*)imgMemAcc.GetData();
}
catch (mitk::Exception& e)
{
MITK_ERROR << e.what();
}
MITK_TEST_CONDITION( p != NULL, "GetData() returned not-NULL pointer.");
// filling image
const unsigned int size = dim[0]*dim[1]*dim[2];
for(unsigned int i=0; i<size; ++i, ++p)
*p = (signed int)i;
// Getting it again and compare with filled values:
try
{
mitk::ImageReadAccessor imgMemAcc(imgMem);
p2 = (int*)imgMemAcc.GetData();
}
catch (mitk::Exception &e)
{
MITK_ERROR << e.what();
}
MITK_TEST_CONDITION( p2 != NULL, "GetData() returned not-NULL pointer.");
bool isEqual = true;
for(unsigned int i=0; i<size; ++i, ++p2)
{
if(*p2 != (signed int) i )
{
isEqual = false;
}
}
MITK_TEST_CONDITION( isEqual, "The values previously set as data are correct [pixelwise comparison].");
// Testing GetSliceData() and compare with filled values:
try
{
mitk::ImageReadAccessor imgMemAcc(imgMem, imgMem->GetSliceData(dim[2]/2));
p2 = (int*)imgMemAcc.GetData();
}
catch (mitk::Exception& e)
{
MITK_ERROR << e.what();
}
MITK_TEST_CONDITION_REQUIRED( p2 != NULL, "Valid slice data returned");
unsigned int xy_size = dim[0]*dim[1];
unsigned int start_mid_slice = (dim[2]/2)*xy_size;
isEqual = true;
for(unsigned int i=0; i<xy_size; ++i, ++p2)
{
if(*p2!=(signed int)(i+start_mid_slice))
{
isEqual = false;
}
}
MITK_TEST_CONDITION( isEqual, "The SliceData are correct [pixelwise comparison]. ");
imgMem = mitk::Image::New();
// testing re-initialization of test image
mitk::PixelType pType = mitk::MakePixelType<int, int, 1>();
imgMem->Initialize( pType , 3, dim);
MITK_TEST_CONDITION_REQUIRED(imgMem->GetDimension()== 3, "Testing initialization parameter dimension!");
MITK_TEST_CONDITION_REQUIRED(imgMem->GetPixelType() == pType, "Testing initialization parameter pixeltype!");
MITK_TEST_CONDITION_REQUIRED(imgMem->GetDimension(0) == dim[0] &&
imgMem->GetDimension(1)== dim[1] && imgMem->GetDimension(2)== dim[2], "Testing initialization of dimensions!");
MITK_TEST_CONDITION( imgMem->IsInitialized(), "Image is initialized.");
// Setting volume again:
try
{
mitk::ImageReadAccessor imgMemAcc(imgMem);
imgMem->SetVolume(imgMemAcc.GetData());
}
catch (mitk::Exception& e)
{
MITK_ERROR << e.what();
}
//-----------------
// geometry information for image
mitk::Point3D origin;
mitk::Vector3D right, bottom;
mitk::Vector3D spacing;
mitk::FillVector3D(origin, 17.0, 19.92, 7.83);
mitk::FillVector3D(right, 1.0, 2.0, 3.0);
mitk::FillVector3D(bottom, 0.0, -3.0, 2.0);
mitk::FillVector3D(spacing, 0.78, 0.91, 2.23);
//InitializeStandardPlane(rightVector, downVector, spacing)
mitk::PlaneGeometry::Pointer planegeometry = mitk::PlaneGeometry::New();
planegeometry->InitializeStandardPlane(100, 100, right, bottom, &spacing);
planegeometry->SetOrigin(origin);
// Testing Initialize(const mitk::PixelType& type, const mitk::Geometry3D& geometry, unsigned int slices) with PlaneGeometry and GetData(): ";
imgMem->Initialize( mitk::MakePixelType<int, int, 1>(), *planegeometry);
- MITK_TEST_CONDITION_REQUIRED( imgMem->GetGeometry()->GetOrigin() == static_cast<mitk::Geometry3D*>(planegeometry)->GetOrigin(), "Testing correct setting of geometry via initialize!");
+ MITK_TEST_CONDITION_REQUIRED( imgMem->GetGeometry()->GetOrigin() == static_cast<mitk::BaseGeometry*>(planegeometry)->GetOrigin(), "Testing correct setting of geometry via initialize!");
try
{
mitk::ImageReadAccessor imgMemAcc(imgMem);
p = (int*)imgMemAcc.GetData();
}
catch (mitk::Exception& e)
{
MITK_ERROR << e.what();
}
MITK_TEST_CONDITION_REQUIRED( p!=NULL, "GetData() returned valid pointer.");
// Testing Initialize(const mitk::PixelType& type, int sDim, const mitk::PlaneGeometry& geometry) and GetData(): ";
imgMem->Initialize( mitk::MakePixelType<int, int, 1>() , 40, *planegeometry);
try
{
mitk::ImageReadAccessor imgMemAcc(imgMem);
p = (int*)imgMemAcc.GetData();
}
catch (mitk::Exception& e)
{
MITK_ERROR << e.what();
}
MITK_TEST_CONDITION_REQUIRED( p != NULL, "GetData() returned valid pointer.");
//-----------------
// testing origin information and methods
MITK_TEST_CONDITION_REQUIRED( mitk::Equal(imgMem->GetGeometry()->GetOrigin(), origin), "Testing correctness of origin via GetGeometry()->GetOrigin(): ");
// Setting origin via SetOrigin(origin): ";
mitk::FillVector3D(origin, 37.0, 17.92, 27.83); imgMem->SetOrigin(origin);
// Test origin
MITK_TEST_CONDITION_REQUIRED( mitk::Equal(imgMem->GetGeometry()->GetOrigin(), origin), "Testing correctness of changed origin via GetGeometry()->GetOrigin(): ");
- MITK_TEST_CONDITION_REQUIRED( mitk::Equal(imgMem->GetSlicedGeometry()->GetGeometry2D(0)->GetOrigin(), origin), "Testing correctness of changed origin via GetSlicedGeometry()->GetGeometry2D(0)->GetOrigin(): ");
+ MITK_TEST_CONDITION_REQUIRED( mitk::Equal(imgMem->GetSlicedGeometry()->GetPlaneGeometry(0)->GetOrigin(), origin), "Testing correctness of changed origin via GetSlicedGeometry()->GetPlaneGeometry(0)->GetOrigin(): ");
//-----------------
// testing spacing information and methodsunsigned int dim[]={100,100,20};
MITK_TEST_CONDITION_REQUIRED(mitk::Equal(imgMem->GetGeometry()->GetSpacing(), spacing), "Testing correct spacing from Geometry3D!");
mitk::FillVector3D(spacing, 7.0, 0.92, 1.83);
imgMem->SetSpacing(spacing);
MITK_TEST_CONDITION_REQUIRED( mitk::Equal(imgMem->GetGeometry()->GetSpacing(), spacing), "Testing correctness of changed spacing via GetGeometry()->GetSpacing(): ");
- MITK_TEST_CONDITION_REQUIRED( mitk::Equal(imgMem->GetSlicedGeometry()->GetGeometry2D(0)->GetSpacing(), spacing), "Testing correctness of changed spacing via GetSlicedGeometry()->GetGeometry2D(0)->GetSpacing(): ");
+ MITK_TEST_CONDITION_REQUIRED( mitk::Equal(imgMem->GetSlicedGeometry()->GetPlaneGeometry(0)->GetSpacing(), spacing), "Testing correctness of changed spacing via GetSlicedGeometry()->GetPlaneGeometry(0)->GetSpacing(): ");
mitk::Image::Pointer vecImg = mitk::Image::New();
try
{
mitk::ImageReadAccessor imgMemAcc(imgMem);
vecImg->Initialize( imgMem->GetPixelType(), *imgMem->GetGeometry(), 2 /* #channels */, 0 /*tDim*/ );
vecImg->SetImportChannel(const_cast<void*>(imgMemAcc.GetData()), 0, mitk::Image::CopyMemory );
vecImg->SetImportChannel(const_cast<void*>(imgMemAcc.GetData()), 1, mitk::Image::CopyMemory );
mitk::ImageReadAccessor vecImgAcc(vecImg);
mitk::ImageReadAccessor vecImgAcc0(vecImg, vecImg->GetChannelData(0));
mitk::ImageReadAccessor vecImgAcc1(vecImg, vecImg->GetChannelData(1));
MITK_TEST_CONDITION_REQUIRED(vecImgAcc0.GetData() != NULL && vecImgAcc1.GetData() != NULL, "Testing set and return of channel data!");
MITK_TEST_CONDITION_REQUIRED( vecImg->IsValidSlice(0,0,1) , "");
MITK_TEST_OUTPUT(<< " Testing whether CopyMemory worked");
MITK_TEST_CONDITION_REQUIRED(imgMemAcc.GetData() != vecImgAcc.GetData(), "");
MITK_TEST_OUTPUT(<< " Testing destruction after SetImportChannel");
vecImg = NULL;
MITK_TEST_CONDITION_REQUIRED(vecImg.IsNull() , "testing destruction!");
}
catch (mitk::Exception& e)
{
MITK_ERROR << e.what();
}
//-----------------
MITK_TEST_OUTPUT(<< "Testing initialization via vtkImageData");
MITK_TEST_OUTPUT(<< " Setting up vtkImageData");
vtkImageData* vtkimage = vtkImageData::New();
vtkimage->Initialize();
vtkimage->SetDimensions( 2, 3, 4);
double vtkorigin[] = {-350,-358.203, -1363.5};
vtkimage->SetOrigin(vtkorigin);
mitk::Point3D vtkoriginAsMitkPoint;
mitk::vtk2itk(vtkorigin, vtkoriginAsMitkPoint);
double vtkspacing[] = {1.367, 1.367, 2};
vtkimage->SetSpacing(vtkspacing);
vtkimage->AllocateScalars(VTK_SHORT,1);
std::cout<<"[PASSED]"<<std::endl;
MITK_TEST_OUTPUT(<< " Testing mitk::Image::Initialize(vtkImageData*, ...)");
mitk::Image::Pointer mitkByVtkImage = mitk::Image::New();
mitkByVtkImage ->Initialize(vtkimage);
MITK_TEST_CONDITION_REQUIRED(mitkByVtkImage->IsInitialized(), "");
vtkimage->Delete();
MITK_TEST_OUTPUT(<< " Testing whether spacing has been correctly initialized from vtkImageData");
mitk::Vector3D spacing2 = mitkByVtkImage->GetGeometry()->GetSpacing();
mitk::Vector3D vtkspacingAsMitkVector;
mitk::vtk2itk(vtkspacing, vtkspacingAsMitkVector);
MITK_TEST_CONDITION_REQUIRED(mitk::Equal(spacing2,vtkspacingAsMitkVector), "");
MITK_TEST_OUTPUT(<< " Testing whether GetSlicedGeometry(0)->GetOrigin() has been correctly initialized from vtkImageData");
mitk::Point3D origin2 = mitkByVtkImage->GetSlicedGeometry(0)->GetOrigin();
MITK_TEST_CONDITION_REQUIRED(mitk::Equal(origin2,vtkoriginAsMitkPoint), "");
MITK_TEST_OUTPUT(<< " Testing whether GetGeometry()->GetOrigin() has been correctly initialized from vtkImageData");
origin2 = mitkByVtkImage->GetGeometry()->GetOrigin();
MITK_TEST_CONDITION_REQUIRED(mitk::Equal(origin2,vtkoriginAsMitkPoint), "");
// TODO test the following initializers on channel-incorporation
// void mitk::Image::Initialize(const mitk::PixelType& type, unsigned int dimension, unsigned int *dimensions, unsigned int channels)
- // void mitk::Image::Initialize(const mitk::PixelType& type, int sDim, const mitk::Geometry2D& geometry2d, bool flipped, unsigned int channels, int tDim )
+ // void mitk::Image::Initialize(const mitk::PixelType& type, int sDim, const mitk::PlaneGeometry& geometry2d, bool flipped, unsigned int channels, int tDim )
// void mitk::Image::Initialize(const mitk::Image* image)
// void mitk::Image::Initialize(const mitkIpPicDescriptor* pic, int channels, int tDim, int sDim)
//mitk::Image::Pointer vecImg = mitk::Image::New();
//vecImg->Initialize(PixelType(typeid(float), 6, itk::ImageIOBase::SYMMETRICSECONDRANKTENSOR), *imgMem->GetGeometry(), 2 /* #channels */, 0 /*tDim*/, false /*shiftBoundingBoxMinimumToZero*/ );
//vecImg->Initialize(PixelType(typeid(itk::Vector<float,6>)), *imgMem->GetGeometry(), 2 /* #channels */, 0 /*tDim*/, false /*shiftBoundingBoxMinimumToZero*/ );
// testing access by index coordinates and by world coordinates
MITK_TEST_CONDITION_REQUIRED(argc == 2, "Check if test image is accessible!");
const std::string filename = std::string(argv[1]);
mitk::ItkImageFileReader::Pointer imageReader = mitk::ItkImageFileReader::New();
try
{
imageReader->SetFileName(filename);
imageReader->Update();
}
catch(...) {
MITK_TEST_FAILED_MSG(<< "Could not read file for testing: " << filename);
return 0;
}
mitk::Image::Pointer image = imageReader->GetOutput();
mitk::Point3D point;
mitk::ScalarType value = -1.;
mitkPixelTypeMultiplex3(TestRandomPixelAccess,image->GetImageDescriptor()->GetChannelTypeById(0),image,point,value)
{
// testing the clone method of mitk::Image
mitk::Image::Pointer cloneImage = image->Clone();
MITK_TEST_CONDITION_REQUIRED(cloneImage->GetDimension() == image->GetDimension(), "Clone (testing dimension)");
MITK_TEST_CONDITION_REQUIRED(cloneImage->GetPixelType() == image->GetPixelType(), "Clone (testing pixel type)");
// After cloning an image the geometry of both images should be equal too
MITK_TEST_CONDITION_REQUIRED(cloneImage->GetGeometry()->GetOrigin() == image->GetGeometry()->GetOrigin(), "Clone (testing origin)");
MITK_TEST_CONDITION_REQUIRED(cloneImage->GetGeometry()->GetSpacing() == image->GetGeometry()->GetSpacing(), "Clone (testing spacing)");
MITK_TEST_CONDITION_REQUIRED(mitk::MatrixEqualElementWise(cloneImage->GetGeometry()->GetIndexToWorldTransform()->GetMatrix(), image->GetGeometry()->GetIndexToWorldTransform()->GetMatrix()),
"Clone (testing transformation matrix)");
MITK_TEST_CONDITION_REQUIRED(mitk::MatrixEqualElementWise(cloneImage->GetTimeGeometry()->GetGeometryForTimeStep(cloneImage->GetDimension(3)-1)->GetIndexToWorldTransform()->GetMatrix(),
cloneImage->GetTimeGeometry()->GetGeometryForTimeStep(image->GetDimension(3)-1)->GetIndexToWorldTransform()->GetMatrix()), "Clone(testing time sliced geometry)");
for (unsigned int i = 0u; i < cloneImage->GetDimension(); ++i)
{
MITK_TEST_CONDITION_REQUIRED(cloneImage->GetDimension(i) == image->GetDimension(i), "Clone (testing dimension " << i << ")");
}
}
//access via itk
if(image->GetDimension()> 3) // CastToItk only works with 3d images so we need to check for 4d images
{
mitk::ImageTimeSelector::Pointer selector = mitk::ImageTimeSelector::New();
selector->SetTimeNr(0);
selector->SetInput(image);
selector->Update();
image = selector->GetOutput();
}
if(image->GetDimension()==3)
{
typedef itk::Image<double,3> ItkFloatImage3D;
ItkFloatImage3D::Pointer itkimage;
try
{
mitk::CastToItkImage(image, itkimage);
MITK_TEST_CONDITION_REQUIRED(itkimage.IsNotNull(), "Test conversion to itk::Image!");
}
catch (std::exception& e)
{
MITK_INFO << e.what();
}
mitk::Point3D itkPhysicalPoint;
image->GetGeometry()->WorldToItkPhysicalPoint(point, itkPhysicalPoint);
MITK_INFO << "ITKPoint " << itkPhysicalPoint[0] << " "<< itkPhysicalPoint[1] << " "<< itkPhysicalPoint[2] << "";
mitk::Point3D backTransformedPoint;
image->GetGeometry()->ItkPhysicalPointToWorld(itkPhysicalPoint, backTransformedPoint);
MITK_TEST_CONDITION_REQUIRED( mitk::Equal(point,backTransformedPoint), "Testing world->itk-physical->world consistency");
itk::Index<3> idx;
bool status = itkimage->TransformPhysicalPointToIndex(itkPhysicalPoint, idx);
MITK_INFO << "ITK Index " << idx[0] << " "<< idx[1] << " "<< idx[2] << "";
if(status && value != -1.)
{
float valByItk = itkimage->GetPixel(idx);
MITK_TEST_CONDITION_REQUIRED( mitk::Equal(valByItk, value), "Compare value of pixel returned by mitk in comparison to itk");
}
else
{
MITK_WARN<< "Index is out buffered region!";
}
}
else
{
MITK_INFO << "Image does not contain three dimensions, some test cases are skipped!";
}
// clone generated 3D image with one slice in z direction (cf. bug 11058)
unsigned int* threeDdim = new unsigned int[3];
threeDdim[0] = 100;
threeDdim[1] = 200;
threeDdim[2] = 1;
mitk::Image::Pointer threeDImage = mitk::Image::New();
threeDImage->Initialize(mitk::MakeScalarPixelType<float>(), 3, threeDdim);
mitk::Image::Pointer cloneThreeDImage = threeDImage->Clone();
// check that the clone image has the same dimensionality as the source image
MITK_TEST_CONDITION_REQUIRED( cloneThreeDImage->GetDimension() == 3, "Testing if the clone image initializes with 3D!");
MITK_TEST_CONDITION_REQUIRED( ImageVtkDataReferenceCheck(argv[1]), "Checking reference count of Image after using GetVtkImageData()");
MITK_TEST_END();
}
diff --git a/Core/Code/Testing/mitkImageWriterTest.cpp b/Core/Code/Testing/mitkImageWriterTest.cpp
index d30f1c9f24..7c798c0175 100644
--- a/Core/Code/Testing/mitkImageWriterTest.cpp
+++ b/Core/Code/Testing/mitkImageWriterTest.cpp
@@ -1,287 +1,287 @@
/*===================================================================
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 "mitkImageWriter.h"
#include "mitkDataNodeFactory.h"
#include "mitkTestingMacros.h"
#include "mitkItkImageFileReader.h"
#include "mitkException.h"
#include <mitkExtractSliceFilter.h>
#include "mitkIOUtil.h"
#include <iostream>
#include <fstream>
#ifdef WIN32
#include "process.h"
#else
#include <unistd.h>
#endif
std::string AppendExtension(const std::string &filename, const char *extension)
{
std::string new_filename = filename;
new_filename += extension;
return new_filename;
}
bool CompareImageMetaData( mitk::Image::Pointer image, mitk::Image::Pointer reference, bool checkPixelType = true )
{
// switch to AreIdentical() methods as soon as Bug 11925 (Basic comparison operators) is fixed
if( image->GetDimension() != reference->GetDimension() )
{
MITK_ERROR << "The image dimension differs: IN (" << image->GetDimension() << ") REF(" << reference->GetDimension() << ")";
return false;
}
// pixel type
if( checkPixelType &&
( image->GetPixelType() != reference->GetPixelType()
&& image->GetPixelType().GetBitsPerComponent() != reference->GetPixelType().GetBitsPerComponent() ) )
{
MITK_ERROR << "Pixeltype differs ( image=" << image->GetPixelType().GetPixelTypeAsString() << "[" << image->GetPixelType().GetBitsPerComponent() << "]" << " reference=" << reference->GetPixelType().GetPixelTypeAsString() << "[" << reference->GetPixelType().GetBitsPerComponent() << "]" << " )";
return false;
}
return true;
}
/*
Test writing picture formats like *.bmp, *.png, *.tiff or *.jpg
NOTE: Saving as picture format must ignore PixelType comparison - not all bits per components are supported (see specification of the format)
*/
void TestPictureWriting(mitk::Image* image, const std::string& filename, const std::string& extension)
{
mitk::ImageWriter::Pointer myImageWriter = mitk::ImageWriter::New();
myImageWriter->SetFileName(AppendExtension(filename, extension.c_str()) );
myImageWriter->SetFilePrefix("pref");
myImageWriter->SetFilePattern("pattern");
myImageWriter->SetInput(image);
mitk::Image::Pointer singleSliceImage = NULL;
if( image->GetDimension() == 3 )
{
mitk::ExtractSliceFilter::Pointer extractFilter = mitk::ExtractSliceFilter::New();
extractFilter->SetInput( image );
- extractFilter->SetWorldGeometry( image->GetSlicedGeometry()->GetGeometry2D(0) );
+ extractFilter->SetWorldGeometry( image->GetSlicedGeometry()->GetPlaneGeometry(0) );
extractFilter->Update();
singleSliceImage = extractFilter->GetOutput();
// test 3D writing in format supporting only 2D
myImageWriter->Update();
// test images
unsigned int foundImagesCount = 0;
//if the image only contains one sinlge slice the itkImageSeriesWriter won't add a number like filename.XX.extension
if(image->GetDimension(2) == 1)
{
std::stringstream series_filenames;
series_filenames << filename << extension;
mitk::Image::Pointer compareImage = mitk::IOUtil::LoadImage( series_filenames.str() );
if( compareImage.IsNotNull() )
{
foundImagesCount++;
MITK_TEST_CONDITION(CompareImageMetaData( singleSliceImage, compareImage, false ), "Image meta data unchanged after writing and loading again. "); //ignore bits per component
}
remove( series_filenames.str().c_str() );
}
else //test the whole slice stack
{
for( unsigned int i=0; i< image->GetDimension(2); i++)
{
std::stringstream series_filenames;
series_filenames << filename << "." << i+1 << extension;
mitk::Image::Pointer compareImage = mitk::IOUtil::LoadImage( series_filenames.str() );
if( compareImage.IsNotNull() )
{
foundImagesCount++;
MITK_TEST_CONDITION(CompareImageMetaData( singleSliceImage, compareImage, false ), "Image meta data unchanged after writing and loading again. "); //ignore bits per component
}
remove( series_filenames.str().c_str() );
}
}
MITK_TEST_CONDITION( foundImagesCount == image->GetDimension(2), "All 2D-Slices of a 3D image were stored correctly.");
}
else if( image->GetDimension() == 2 )
{
singleSliceImage = image;
}
// test 2D writing
if( singleSliceImage.IsNotNull() )
{
try
{
myImageWriter->SetInput( singleSliceImage );
myImageWriter->Update();
mitk::Image::Pointer compareImage = mitk::IOUtil::LoadImage( AppendExtension(filename, extension.c_str()).c_str());
MITK_TEST_CONDITION_REQUIRED( compareImage.IsNotNull(), "Image stored was succesfully loaded again");
MITK_TEST_CONDITION_REQUIRED( CompareImageMetaData(singleSliceImage, compareImage, false ), "Image meta data unchanged after writing and loading again. ");//ignore bits per component
remove(AppendExtension(filename, extension.c_str()).c_str());
}
catch(itk::ExceptionObject &e)
{
MITK_TEST_FAILED_MSG(<< "Exception during file writing for ." << extension << ": " << e.what() );
}
}
}
/**
* test for "ImageWriter".
*
* 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).
*/
int mitkImageWriterTest(int argc , char* argv[])
{
// always start with this!
MITK_TEST_BEGIN("ImageWriter")
// let's create an object of our class
mitk::ImageWriter::Pointer myImageWriter = mitk::ImageWriter::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(myImageWriter.IsNotNull(),"Testing instantiation")
// 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!
// load image
MITK_TEST_CONDITION_REQUIRED(argc > 1, "File to load has been specified");
mitk::Image::Pointer image = NULL;
try
{
MITK_TEST_OUTPUT(<< "Loading file: " << argv[1]);
image = mitk::IOUtil::LoadImage( argv[1] );
}
catch (itk::ExceptionObject & ex)
{
MITK_TEST_FAILED_MSG(<< "Exception during file loading: " << ex.GetDescription());
}
MITK_TEST_CONDITION_REQUIRED(image.IsNotNull(),"loaded image not NULL")
std::stringstream filename_stream;
#ifdef WIN32
filename_stream << "test" << _getpid();
#else
filename_stream << "test" << getpid();
#endif
std::string filename = filename_stream.str();
std::cout << filename << std::endl;
// test set/get methods
myImageWriter->SetInput(image);
MITK_TEST_CONDITION_REQUIRED(myImageWriter->GetInput()==image,"test Set/GetInput()");
myImageWriter->SetFileName(filename);
MITK_TEST_CONDITION_REQUIRED(!strcmp(myImageWriter->GetFileName(),filename.c_str()),"test Set/GetFileName()");
myImageWriter->SetFilePrefix("pref");
MITK_TEST_CONDITION_REQUIRED(!strcmp(myImageWriter->GetFilePrefix(),"pref"),"test Set/GetFilePrefix()");
myImageWriter->SetFilePattern("pattern");
MITK_TEST_CONDITION_REQUIRED(!strcmp(myImageWriter->GetFilePattern(),"pattern"),"test Set/GetFilePattern()");
// write ITK .mhd image (2D and 3D only)
if( image->GetDimension() <= 3 )
{
try
{
myImageWriter->SetExtension(".mhd");
myImageWriter->Update();
mitk::Image::Pointer compareImage = mitk::IOUtil::LoadImage( AppendExtension(filename, ".mhd").c_str() );
MITK_TEST_CONDITION_REQUIRED( compareImage.IsNotNull(), "Image stored in MHD format was succesfully loaded again! ");
std::string rawExtension = ".raw";
std::fstream rawPartIn;
rawPartIn.open(AppendExtension(filename, ".raw").c_str());
if( !rawPartIn.is_open() )
{
rawExtension = ".zraw";
rawPartIn.open(AppendExtension(filename, ".zraw").c_str());
}
MITK_TEST_CONDITION_REQUIRED(rawPartIn.is_open(),"Write .raw file");
rawPartIn.close();
// delete
remove(AppendExtension(filename, ".mhd").c_str());
remove(AppendExtension(filename, rawExtension.c_str()).c_str());
}
catch (...)
{
MITK_TEST_FAILED_MSG(<< "Exception during .mhd file writing");
}
}
//testing more component image writing as nrrd files
try
{
myImageWriter->SetExtension(".nrrd");
myImageWriter->Update();
std::fstream fin;
mitk::Image::Pointer compareImage = mitk::IOUtil::LoadImage(AppendExtension(filename, ".nrrd").c_str());
MITK_TEST_CONDITION_REQUIRED(compareImage.IsNotNull(), "Image stored in NRRD format was succesfully loaded again");
fin.close();
remove(AppendExtension(filename, ".nrrd").c_str());
}
catch(...)
{
MITK_TEST_FAILED_MSG(<< "Exception during .nrrd file writing");
}
TestPictureWriting(image, filename, ".png");
TestPictureWriting(image, filename, ".jpg");
TestPictureWriting(image, filename, ".tiff");
TestPictureWriting(image, filename, ".bmp");
// test for exception handling
try
{
MITK_TEST_FOR_EXCEPTION_BEGIN(itk::ExceptionObject)
myImageWriter->SetInput(image);
myImageWriter->SetFileName("/usr/bin");
myImageWriter->Update();
MITK_TEST_FOR_EXCEPTION_END(itk::ExceptionObject)
}
catch(...) {
//this means that a wrong exception (i.e. no itk:Exception) has been thrown
MITK_TEST_FAILED_MSG(<< "Wrong exception (i.e. no itk:Exception) caught during write");
}
// always end with this!
MITK_TEST_END();
}
diff --git a/Core/Code/Testing/mitkImportItkImageTest.cpp b/Core/Code/Testing/mitkImportItkImageTest.cpp
index db55e5bdc7..d27804a90a 100644
--- a/Core/Code/Testing/mitkImportItkImageTest.cpp
+++ b/Core/Code/Testing/mitkImportItkImageTest.cpp
@@ -1,240 +1,240 @@
/*===================================================================
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 "mitkTestingMacros.h"
#include "mitkITKImageImport.h"
#include "mitkImagePixelReadAccessor.h"
#include <itkImageRegionConstIteratorWithIndex.h>
#include <itkRandomImageSource.h>
/**
* Create a test image with random pixel values. The image size is determined by the input parameter.
*
* @param size the number of voxels in each dimension
*/
template <typename TPixel, unsigned int VDimension>
typename itk::Image<TPixel, VDimension>::Pointer CreateTestImageRandom( short int size )
{
typedef typename itk::Image< TPixel, VDimension> ImageType;
typedef typename ImageType::Pointer ImagePointer;
itk::Size<VDimension> regionSize;
regionSize.Fill(size);
typename itk::RandomImageSource<ImageType>::Pointer randomImageSource = itk::RandomImageSource<ImageType>::New();
randomImageSource->SetNumberOfThreads(1); // to produce non-random results
randomImageSource->SetSize(regionSize);
randomImageSource->Update();
return randomImageSource->GetOutput();
}
/**
* Create a test image with a single pixel value. The image size is determined by the input parameter.
*
* @param value the pixel value the created image is filled with
* @param size the number of voxels in each dimension
*/
template <typename TPixel, unsigned int VDimension>
typename itk::Image<TPixel, VDimension>::Pointer CreateTestImageFixedValue(size_t size, TPixel value)
{
typedef typename itk::Image< TPixel, VDimension> ImageType;
typedef typename ImageType::Pointer ImagePointer;
typename ImageType::RegionType imageRegion;
typename ImageType::RegionType::SizeType regionSize;
regionSize.Fill(size);
typename ImageType::RegionType::IndexType regionIndex;
regionIndex.Fill(0);
imageRegion.SetSize( regionSize );
imageRegion.SetIndex( regionIndex );
typename ImageType::SpacingType imageSpacing;
imageSpacing.Fill(1.0f);
typename ImageType::PointType imageOrigin;
imageOrigin.Fill(0.0f);
ImagePointer itkImage = ImageType::New();
itkImage->SetRegions( imageRegion );
itkImage->SetOrigin( imageOrigin );
itkImage->SetSpacing( imageSpacing );
itkImage->Allocate();
itkImage->FillBuffer( value );
return itkImage;
}
/**
* Compares the meta information of both given images for equality.
*/
template <typename ImageType>
bool Assert_ImageMetaData_AreEqual( typename ImageType::Pointer itkImage, mitk::Image::Pointer mitkImage )
{
bool return_value = true;
typename ImageType::RegionType itkRegion = itkImage->GetLargestPossibleRegion();
typename ImageType::SizeType itkImageSize = itkRegion.GetSize();
// check dimension
for( unsigned int idx=0; idx < mitkImage->GetDimension(); idx++)
{
return_value &= ( itkImageSize[idx] == mitkImage->GetDimension(idx) );
}
MITK_TEST_CONDITION( return_value, " - Dimensions equal!")
// check pixel type
bool ptype_compare = ( mitkImage->GetPixelType() == mitk::MakePixelType<ImageType>() );
return_value &= ptype_compare;
MITK_TEST_CONDITION( ptype_compare, " - Pixel types equal!")
- mitk::Geometry3D* imageGeometry = mitkImage->GetGeometry();
+ mitk::BaseGeometry* imageGeometry = mitkImage->GetGeometry();
const mitk::Point3D origin = imageGeometry->GetOrigin();
bool origin_compare = true;
for( unsigned int idx=0; idx < 3; idx++)
{
origin_compare &= ( itkImage->GetOrigin()[idx] == origin[idx] );
}
return_value &= origin_compare;
MITK_TEST_CONDITION( origin_compare, " - Origin equals!")
return return_value;
}
/**
* Generates a random itk image and imports it to mitk image through ImportItkImage and compares the values
* voxel-wise afterwards
*/
template <typename TPixel, unsigned int VDimension>
void Assert_ItkImageImportRandomValuesSucceded_ReturnsTrue()
{
std::stringstream msg;
msg << "Current type: (Random Image, " << VDimension << "D):" << typeid(TPixel).name() << "\n";
std::cout << msg.str();
bool assert_value = true;
typedef typename itk::Image< TPixel, VDimension> ImageType;
typedef typename ImageType::Pointer ImagePointer;
ImagePointer itkImage = CreateTestImageRandom<TPixel, VDimension>(5);
mitk::Image::Pointer output_import = mitk::ImportItkImage( itkImage );
itk::ImageRegionConstIteratorWithIndex< ImageType > iter( itkImage, itkImage->GetLargestPossibleRegion() );
iter.GoToBegin();
mitk::ImagePixelReadAccessor< TPixel, VDimension > readAccessor( output_import );
bool difference = false;
while( !iter.IsAtEnd() )
{
TPixel ref = iter.Get();
TPixel val = readAccessor.GetPixelByIndex( iter.GetIndex() );
difference |= ( ref != val );
if( difference )
{
std::cout << iter.GetIndex() << ":" << ref << " ? " << val << "\n";
}
++iter;
}
assert_value = Assert_ImageMetaData_AreEqual<ImageType>( itkImage, output_import );
MITK_TEST_CONDITION( assert_value && (!difference), "Pixel values are same in voxel-wise comparison." );
}
/**
* Generates an itk image with fixed pixel value and imports it to mitk image through ImportItkImage
* and compares the values voxel-wise afterwards
*/
template <typename TPixel, unsigned int VDimension>
void Assert_ItkImageImportSucceded_ReturnsTrue()
{
std::stringstream msg;
msg << "Current type: " << VDimension << "D):" << typeid(TPixel).name() << "\n";
std::cout << msg.str();
bool assert_value = true;
typedef typename itk::Image< TPixel, VDimension> ImageType;
typedef typename ImageType::Pointer ImagePointer;
ImagePointer itkImage = CreateTestImageFixedValue<TPixel, VDimension>(5, itk::NumericTraits<TPixel>::min());
mitk::Image::Pointer output_import = mitk::ImportItkImage( itkImage );
itk::ImageRegionConstIteratorWithIndex< ImageType > iter( itkImage, itkImage->GetLargestPossibleRegion() );
iter.GoToBegin();
mitk::ImagePixelReadAccessor< TPixel, VDimension > readAccessor( output_import );
bool difference = false;
while( !iter.IsAtEnd() )
{
TPixel ref = iter.Get();
TPixel val = readAccessor.GetPixelByIndex( iter.GetIndex() );
difference |= ( ref != val );
if( difference )
{
std::cout << iter.GetIndex() << ":" << ref << " ? " << val << "\n";
}
++iter;
}
assert_value = Assert_ImageMetaData_AreEqual<ImageType>( itkImage, output_import );
MITK_TEST_CONDITION( assert_value && (!difference), "Pixel values are same in voxel-wise comparison." );
}
int mitkImportItkImageTest(int /*argc*/, char* /*argv*/[])
{
MITK_TEST_BEGIN("mitkImportItkImageTest")
Assert_ItkImageImportSucceded_ReturnsTrue<short, 3>();// "Import succesfull on 3D short");
Assert_ItkImageImportSucceded_ReturnsTrue<float, 3>();// "Import succesfull on float");
Assert_ItkImageImportSucceded_ReturnsTrue<unsigned char, 3>();// "Import succesfull on uchar");
Assert_ItkImageImportSucceded_ReturnsTrue<int, 3>();// "Import succesfull on int");
Assert_ItkImageImportRandomValuesSucceded_ReturnsTrue<short, 3>();// "Import succesfull on 3D short");
Assert_ItkImageImportRandomValuesSucceded_ReturnsTrue<float, 3>();// "Import succesfull on float");
Assert_ItkImageImportRandomValuesSucceded_ReturnsTrue<unsigned char, 3>();// "Import succesfull on uchar");
Assert_ItkImageImportRandomValuesSucceded_ReturnsTrue<int, 3>();// "Import succesfull on int");
Assert_ItkImageImportRandomValuesSucceded_ReturnsTrue<short, 4>();// "Import succesfull on 3D short");
Assert_ItkImageImportRandomValuesSucceded_ReturnsTrue<float, 4>();// "Import succesfull on float");
Assert_ItkImageImportRandomValuesSucceded_ReturnsTrue<unsigned char, 4>();// "Import succesfull on uchar");
Assert_ItkImageImportRandomValuesSucceded_ReturnsTrue<int, 4>();// "Import succesfull on int");
MITK_TEST_END()
}
diff --git a/Core/Code/Testing/mitkPlaneGeometryTest.cpp b/Core/Code/Testing/mitkPlaneGeometryTest.cpp
index f418cfd2de..e5149f574c 100644
--- a/Core/Code/Testing/mitkPlaneGeometryTest.cpp
+++ b/Core/Code/Testing/mitkPlaneGeometryTest.cpp
@@ -1,1025 +1,1141 @@
/*===================================================================
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 "mitkPlaneGeometry.h"
#include "mitkRotationOperation.h"
#include "mitkInteractionConst.h"
#include "mitkLine.h"
#include "mitkTestingMacros.h"
#include <vnl/vnl_quaternion.h>
#include <vnl/vnl_quaternion.txx>
#include <fstream>
#include <iomanip>
static const mitk::ScalarType testEps = 1E-9; // the epsilon used in this test == at least float precision.
int mappingTests2D(const mitk::PlaneGeometry* planegeometry, const mitk::ScalarType& width, const mitk::ScalarType& height, const mitk::ScalarType& widthInMM, const mitk::ScalarType& heightInMM, const mitk::Point3D& origin, const mitk::Vector3D& right, const mitk::Vector3D& bottom)
{
std::cout << "Testing mapping Map(pt2d_mm(x=widthInMM/2.3,y=heightInMM/2.5), pt3d_mm) and compare with expected: ";
mitk::Point2D pt2d_mm;
mitk::Point3D pt3d_mm, expected_pt3d_mm;
pt2d_mm[0] = widthInMM/2.3; pt2d_mm[1] = heightInMM/2.5;
expected_pt3d_mm = origin+right*(pt2d_mm[0]/right.GetNorm())+bottom*(pt2d_mm[1]/bottom.GetNorm());
planegeometry->Map(pt2d_mm, pt3d_mm);
if(mitk::Equal(pt3d_mm, expected_pt3d_mm, testEps) == false)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing mapping Map(pt3d_mm, pt2d_mm) and compare with expected: ";
mitk::Point2D testpt2d_mm;
planegeometry->Map(pt3d_mm, testpt2d_mm);
std::cout << std::setprecision(12) << "Expected pt2d_mm " << pt2d_mm << std::endl;
std::cout << std::setprecision(12) << "Result testpt2d_mm " << testpt2d_mm << std::endl;
std::cout << std::setprecision(12) << "10*mitk::eps " << 10*mitk::eps << std::endl;
//This eps is temporarily set to 10*mitk::eps. See bug #15037 for details.
if(mitk::Equal(pt2d_mm, testpt2d_mm, 10*mitk::eps) == false)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing IndexToWorld(pt2d_units, pt2d_mm) and compare with expected: ";
mitk::Point2D pt2d_units;
pt2d_units[0] = width/2.0; pt2d_units[1] = height/2.0;
pt2d_mm[0] = widthInMM/2.0; pt2d_mm[1] = heightInMM/2.0;
planegeometry->IndexToWorld(pt2d_units, testpt2d_mm);
std::cout << std::setprecision(12) << "Expected pt2d_mm " << pt2d_mm << std::endl;
std::cout << std::setprecision(12) << "Result testpt2d_mm " << testpt2d_mm << std::endl;
std::cout << std::setprecision(12) << "10*mitk::eps " << 10*mitk::eps << std::endl;
//This eps is temporarily set to 10*mitk::eps. See bug #15037 for details.
if(mitk::Equal(pt2d_mm, testpt2d_mm, 10*mitk::eps) == false)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing WorldToIndex(pt2d_mm, pt2d_units) and compare with expected: ";
mitk::Point2D testpt2d_units;
planegeometry->WorldToIndex(pt2d_mm, testpt2d_units);
std::cout << std::setprecision(12) << "Expected pt2d_units " << pt2d_units << std::endl;
std::cout << std::setprecision(12) << "Result testpt2d_units " << testpt2d_units << std::endl;
std::cout << std::setprecision(12) << "10*mitk::eps " << 10*mitk::eps << std::endl;
//This eps is temporarily set to 10*mitk::eps. See bug #15037 for details.
if(mitk::Equal(pt2d_units, testpt2d_units, 10*mitk::eps) == false)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
return EXIT_SUCCESS;
}
int TestCase1210()
{
mitk::PlaneGeometry::Pointer planegeometry = mitk::PlaneGeometry::New();
mitk::Point3D origin;
mitk::Vector3D right, down, spacing;
mitk::FillVector3D(origin, 4.5, 7.3, 11.2);
mitk::FillVector3D(right,
1.015625, 1.015625, 1.1999969482421875
);
mitk::FillVector3D(down,
1.4012984643248170709237295832899161312802619418765e-45, 0, 0
);
mitk::FillVector3D(spacing,
0, 1.4713633875410579244699160624544119378442750389703e-43, 9.2806360452222355258639080851310540729807238879469e-32
);
std::cout << "Testing InitializeStandardPlane(rightVector, downVector, spacing = NULL): "<<std::endl;
planegeometry->InitializeStandardPlane(right, down, &spacing);
/*
std::cout << "Testing width, height and thickness (in units): ";
if((mitk::Equal(planegeometry->GetExtent(0),width)==false) ||
(mitk::Equal(planegeometry->GetExtent(1),height)==false) ||
(mitk::Equal(planegeometry->GetExtent(2),1)==false)
)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing width, height and thickness (in mm): ";
if((mitk::Equal(planegeometry->GetExtentInMM(0),widthInMM)==false) ||
(mitk::Equal(planegeometry->GetExtentInMM(1),heightInMM)==false) ||
(mitk::Equal(planegeometry->GetExtentInMM(2),thicknessInMM)==false)
)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
*/
std::cout<<"[PASSED]"<<std::endl;
return EXIT_SUCCESS;
}
/**
* @brief This method tests method IntersectionPoint
*
* See also bug #7151. (ref 2 this test: iggy)
* This test was written due to incorrect calculation of the intersection point
* between a given line and plane. This only occured when the pointdistance of
* the line was less than 1.
* Test Behavour:
* ==============
* we have a given line and a given plane.
* we let the line intersect the plane.
* when testing several positions on the line the resulting intersection point must be the same
* we test a position where the distance between the correspoinding points is < 0 and another position where the distance is > 0.
*
*/
int TestIntersectionPoint()
{
//init plane with its parameter
mitk::PlaneGeometry::Pointer myPlaneGeometry = mitk::PlaneGeometry::New();
mitk::Point3D origin;
origin[0] = 0.0;
origin[1] = 2.0;
origin[2] = 0.0;
mitk::Vector3D normal;
normal[0] = 0.0;
normal[1] = 1.0;
normal[2] = 0.0;
myPlaneGeometry->InitializePlane(origin,normal);
//generate points and line for intersection testing
//point distance of given line > 1
mitk::Point3D pointP1;
pointP1[0] = 2.0;
pointP1[1] = 1.0;
pointP1[2] = 0.0;
mitk::Point3D pointP2;
pointP2[0] = 2.0;
pointP2[1] = 4.0;
pointP2[2] = 0.0;
mitk::Vector3D lineDirection;
lineDirection[0] = pointP2[0] - pointP1[0];
lineDirection[1] = pointP2[1] - pointP1[1];
lineDirection[2] = pointP2[2] - pointP1[2];
mitk::Line3D xingline( pointP1, lineDirection );
mitk::Point3D calcXingPoint;
myPlaneGeometry->IntersectionPoint(xingline, calcXingPoint);
//point distance of given line < 1
mitk::Point3D pointP3;
pointP3[0] = 2.0;
pointP3[1] = 2.2;
pointP3[2] = 0.0;
mitk::Point3D pointP4;
pointP4[0] = 2.0;
pointP4[1] = 1.7;
pointP4[2] = 0.0;
mitk::Vector3D lineDirection2;
lineDirection2[0] = pointP4[0] - pointP3[0];
lineDirection2[1] = pointP4[1] - pointP3[1];
lineDirection2[2] = pointP4[2] - pointP3[2];
mitk::Line3D xingline2( pointP3, lineDirection2 );
mitk::Point3D calcXingPoint2;
myPlaneGeometry->IntersectionPoint( xingline2, calcXingPoint2 );
//intersection points must be the same
if (calcXingPoint == calcXingPoint2) {
return EXIT_SUCCESS;
} else {
return EXIT_FAILURE;
}
}
/**
* @brief This method tests method ProjectPointOntoPlane.
*
* See also bug #3409.
*/
int TestProjectPointOntoPlane()
{
mitk::PlaneGeometry::Pointer myPlaneGeometry = mitk::PlaneGeometry::New();
//create normal
mitk::Vector3D normal;
normal[0] = 0.0;
normal[1] = 0.0;
normal[2] = 1.0;
//create origin
mitk::Point3D origin;
origin[0] = -27.582859;
origin[1] = 50;
origin[2] = 200.27742;
//initialize plane geometry
myPlaneGeometry->InitializePlane(origin,normal);
//output to descripe the test
std::cout << "Testing PlaneGeometry according to bug #3409" << std::endl;
std::cout << "Our normal is: " << normal << std::endl;
std::cout << "So ALL projected points should have exactly the same z-value!" << std::endl;
//create a number of points
mitk::Point3D myPoints[5];
myPoints[0][0] = -27.582859;
myPoints[0][1] = 50.00;
myPoints[0][2] = 200.27742;
myPoints[1][0] = -26.58662;
myPoints[1][1] = 50.00;
myPoints[1][2] = 200.19026;
myPoints[2][0] = -26.58662;
myPoints[2][1] = 50.00;
myPoints[2][2] = 200.33124;
myPoints[3][0] = 104.58662;
myPoints[3][1] = 452.12313;
myPoints[3][2] = 866.41236;
myPoints[4][0] = -207.58662;
myPoints[4][1] = 312.00;
myPoints[4][2] = -300.12346;
//project points onto plane
mitk::Point3D myProjectedPoints[5];
for ( unsigned int i = 0; i < 5; ++i )
{
myProjectedPoints[i] = myPlaneGeometry->ProjectPointOntoPlane( myPoints[i] );
}
//compare z-values with z-value of plane (should be equal)
bool allPointsOnPlane = true;
for ( unsigned int i = 0; i < 5; ++i )
{
if ( fabs(myProjectedPoints[i][2] - origin[2]) > mitk::sqrteps )
{
allPointsOnPlane = false;
}
}
if (!allPointsOnPlane)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
else
{
std::cout<<"[PASSED]"<<std::endl;
return EXIT_SUCCESS;
}
}
+mitk::PlaneGeometry::Pointer createPlaneGeometry()
+{
+ mitk::Vector3D mySpacing;
+ mySpacing[0] = 31;
+ mySpacing[1] = 0.1;
+ mySpacing[2] = 5.4;
+ mitk::Point3D myOrigin;
+ myOrigin[0] = 8;
+ myOrigin[1] = 9;
+ myOrigin[2] = 10;
+ mitk::AffineTransform3D::Pointer myTransform = mitk::AffineTransform3D::New();
+ itk::Matrix<mitk::ScalarType, 3,3> transMatrix;
+ transMatrix.Fill(0);
+ transMatrix[0][0] = 1;
+ transMatrix[1][1] = 2;
+ transMatrix[2][2] = 4;
+
+ myTransform->SetMatrix(transMatrix);
+
+ mitk::PlaneGeometry::Pointer geometry2D = mitk::PlaneGeometry::New();
+ geometry2D->SetIndexToWorldTransform(myTransform);
+ geometry2D->SetSpacing(mySpacing);
+ geometry2D->SetOrigin(myOrigin);
+ return geometry2D;
+}
+
+int testPlaneGeometryCloning()
+{
+ mitk::PlaneGeometry::Pointer geometry2D = createPlaneGeometry();
+
+ try
+ {
+ mitk::PlaneGeometry::Pointer clone = geometry2D->Clone();
+ itk::Matrix<mitk::ScalarType,3,3> matrix = clone->GetIndexToWorldTransform()->GetMatrix();
+ MITK_TEST_CONDITION(matrix[0][0] == 31, "Test if matrix element exists...");
+
+ double origin = geometry2D->GetOrigin()[0];
+ MITK_TEST_CONDITION(mitk::Equal(origin, 8),"First Point of origin as expected...");
+
+ double spacing = geometry2D->GetSpacing()[0];
+ MITK_TEST_CONDITION(mitk::Equal(spacing, 31),"First Point of spacing as expected...");
+ }
+ catch (...)
+ {
+ MITK_TEST_CONDITION(false, "Error during access on a member of cloned geometry");
+ }
+ // direction [row] [coloum]
+ MITK_TEST_OUTPUT( << "Casting a rotated 2D ITK Image to a MITK Image and check if Geometry is still same" );
+
+ return EXIT_SUCCESS;
+}
+
+bool compareMatrix(itk::Matrix<mitk::ScalarType, 3,3> left, itk::Matrix<mitk::ScalarType, 3,3> right)
+{
+ bool equal = true;
+ for (int i = 0; i < 3; ++i)
+ for (int j = 0; j < 3; ++j)
+ equal &= mitk::Equal(left[i][j], right[i][j]);
+ return equal;
+}
+
+int testPlaneGeometryInitializeOrder()
+{
+ mitk::Vector3D mySpacing;
+ mySpacing[0] = 31;
+ mySpacing[1] = 0.1;
+ mySpacing[2] = 5.4;
+ mitk::Point3D myOrigin;
+ myOrigin[0] = 8;
+ myOrigin[1] = 9;
+ myOrigin[2] = 10;
+ mitk::AffineTransform3D::Pointer myTransform = mitk::AffineTransform3D::New();
+ itk::Matrix<mitk::ScalarType, 3,3> transMatrix;
+ transMatrix.Fill(0);
+ transMatrix[0][0] = 1;
+ transMatrix[1][1] = 2;
+ transMatrix[2][2] = 4;
+
+ myTransform->SetMatrix(transMatrix);
+
+ mitk::PlaneGeometry::Pointer geometry2D1 = mitk::PlaneGeometry::New();
+ geometry2D1->SetIndexToWorldTransform(myTransform);
+ geometry2D1->SetSpacing(mySpacing);
+ geometry2D1->SetOrigin(myOrigin);
+
+ mitk::PlaneGeometry::Pointer geometry2D2 = mitk::PlaneGeometry::New();
+ geometry2D2->SetSpacing(mySpacing);
+ geometry2D2->SetOrigin(myOrigin);
+ geometry2D2->SetIndexToWorldTransform(myTransform);
+
+ mitk::PlaneGeometry::Pointer geometry2D3 = mitk::PlaneGeometry::New();
+ geometry2D3->SetIndexToWorldTransform(myTransform);
+ geometry2D3->SetSpacing(mySpacing);
+ geometry2D3->SetOrigin(myOrigin);
+ geometry2D3->SetIndexToWorldTransform(myTransform);
+
+ MITK_TEST_CONDITION(mitk::Equal(geometry2D1->GetOrigin(), geometry2D2->GetOrigin()),"Origin of Geometry 1 match those of Geometry 2.");
+ MITK_TEST_CONDITION(mitk::Equal(geometry2D1->GetOrigin(), geometry2D3->GetOrigin()),"Origin of Geometry 1 match those of Geometry 3.");
+ MITK_TEST_CONDITION(mitk::Equal(geometry2D2->GetOrigin(), geometry2D3->GetOrigin()),"Origin of Geometry 2 match those of Geometry 3.");
+
+ MITK_TEST_CONDITION(mitk::Equal(geometry2D1->GetSpacing(), geometry2D2->GetSpacing()),"Spacing of Geometry 1 match those of Geometry 2.");
+ MITK_TEST_CONDITION(mitk::Equal(geometry2D1->GetSpacing(), geometry2D3->GetSpacing()),"Spacing of Geometry 1 match those of Geometry 3.");
+ MITK_TEST_CONDITION(mitk::Equal(geometry2D2->GetSpacing(), geometry2D3->GetSpacing()),"Spacing of Geometry 2 match those of Geometry 3.");
+
+ MITK_TEST_CONDITION(compareMatrix(geometry2D1->GetIndexToWorldTransform()->GetMatrix(), geometry2D2->GetIndexToWorldTransform()->GetMatrix()),"Transformation of Geometry 1 match those of Geometry 2.");
+ MITK_TEST_CONDITION(compareMatrix(geometry2D1->GetIndexToWorldTransform()->GetMatrix(), geometry2D3->GetIndexToWorldTransform()->GetMatrix()),"Transformation of Geometry 1 match those of Geometry 3.");
+ MITK_TEST_CONDITION(compareMatrix(geometry2D2->GetIndexToWorldTransform()->GetMatrix(), geometry2D3->GetIndexToWorldTransform()->GetMatrix()),"Transformation of Geometry 2 match those of Geometry 3.");
+ return EXIT_SUCCESS;
+}
+
int mitkPlaneGeometryTest(int /*argc*/, char* /*argv*/[])
{
int result;
/*
// the following can be used to reproduce a bug in ITK matrix inversion
// which was found while investigating bug #1210.
result = TestCase1210();
if(result!=EXIT_SUCCESS)
return result;
*/
mitk::PlaneGeometry::Pointer planegeometry = mitk::PlaneGeometry::New();
mitk::Point3D origin;
mitk::Vector3D right, bottom, normal;
mitk::ScalarType width, height;
mitk::ScalarType widthInMM, heightInMM, thicknessInMM;
width = 100; widthInMM = width;
height = 200; heightInMM = height;
thicknessInMM = 1.0;
mitk::FillVector3D(origin, 4.5, 7.3, 11.2);
mitk::FillVector3D(right, widthInMM, 0, 0);
mitk::FillVector3D(bottom, 0, heightInMM, 0);
mitk::FillVector3D(normal, 0, 0, thicknessInMM);
std::cout << "Testing InitializeStandardPlane(rightVector, downVector, spacing = NULL): "<<std::endl;
planegeometry->InitializeStandardPlane(right.GetVnlVector(), bottom.GetVnlVector());
std::cout << "Testing width, height and thickness (in units): ";
if((mitk::Equal(planegeometry->GetExtent(0),width, testEps)==false) ||
(mitk::Equal(planegeometry->GetExtent(1),height, testEps)==false) ||
(mitk::Equal(planegeometry->GetExtent(2),1, testEps)==false)
)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing width, height and thickness (in mm): ";
if((mitk::Equal(planegeometry->GetExtentInMM(0),widthInMM, testEps)==false) ||
(mitk::Equal(planegeometry->GetExtentInMM(1),heightInMM, testEps)==false) ||
(mitk::Equal(planegeometry->GetExtentInMM(2),thicknessInMM, testEps)==false)
)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing GetAxisVector(): ";
if((mitk::Equal(planegeometry->GetAxisVector(0), right, testEps)==false) || (mitk::Equal(planegeometry->GetAxisVector(1), bottom, testEps)==false) || (mitk::Equal(planegeometry->GetAxisVector(2), normal, testEps)==false))
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing InitializeStandardPlane(rightVector, downVector, spacing = {1.0, 1.0, 1.5}): "<<std::endl;
mitk::Vector3D spacing;
thicknessInMM = 1.5;
normal.Normalize(); normal *= thicknessInMM;
mitk::FillVector3D(spacing, 1.0, 1.0, thicknessInMM);
planegeometry->InitializeStandardPlane(right.GetVnlVector(), bottom.GetVnlVector(), &spacing);
std::cout << "Testing width, height and thickness (in units): ";
if((mitk::Equal(planegeometry->GetExtent(0),width, testEps)==false) ||
(mitk::Equal(planegeometry->GetExtent(1),height, testEps)==false) ||
(mitk::Equal(planegeometry->GetExtent(2),1, testEps)==false)
)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing width, height and thickness (in mm): ";
if((mitk::Equal(planegeometry->GetExtentInMM(0),widthInMM, testEps)==false) ||
(mitk::Equal(planegeometry->GetExtentInMM(1),heightInMM, testEps)==false) ||
(mitk::Equal(planegeometry->GetExtentInMM(2),thicknessInMM, testEps)==false)
)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing GetAxisVector(): ";
if((mitk::Equal(planegeometry->GetAxisVector(0), right, testEps)==false) || (mitk::Equal(planegeometry->GetAxisVector(1), bottom, testEps)==false) || (mitk::Equal(planegeometry->GetAxisVector(2), normal, testEps)==false))
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing SetExtentInMM(2, ...), querying by GetExtentInMM(2): ";
thicknessInMM = 3.5;
normal.Normalize(); normal *= thicknessInMM;
planegeometry->SetExtentInMM(2, thicknessInMM);
if(mitk::Equal(planegeometry->GetExtentInMM(2),thicknessInMM, testEps)==false)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing SetExtentInMM(2, ...), querying by GetAxisVector(2) and comparing to normal: ";
if(mitk::Equal(planegeometry->GetAxisVector(2), normal, testEps)==false)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing SetOrigin: ";
planegeometry->SetOrigin(origin);
if(mitk::Equal(planegeometry->GetOrigin(), origin, testEps)==false)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing GetAxisVector() after SetOrigin: ";
if((mitk::Equal(planegeometry->GetAxisVector(0), right, testEps)==false) || (mitk::Equal(planegeometry->GetAxisVector(1), bottom, testEps)==false) || (mitk::Equal(planegeometry->GetAxisVector(2), normal, testEps)==false))
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
result = mappingTests2D(planegeometry, width, height, widthInMM, heightInMM, origin, right, bottom);
if(result!=EXIT_SUCCESS)
return result;
std::cout << "Changing the IndexToWorldTransform to a rotated version by SetIndexToWorldTransform() (keep origin): "<<std::endl;
mitk::AffineTransform3D::Pointer transform = mitk::AffineTransform3D::New();
mitk::AffineTransform3D::MatrixType::InternalMatrixType vnlmatrix;
vnlmatrix = planegeometry->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix();
mitk::VnlVector axis(3);
mitk::FillVector3D(axis, 1.0, 1.0, 1.0); axis.normalize();
vnl_quaternion<mitk::ScalarType> rotation(axis, 0.223);
vnlmatrix = rotation.rotation_matrix_transpose()*vnlmatrix;
mitk::Matrix3D matrix;
matrix = vnlmatrix;
transform->SetMatrix(matrix);
transform->SetOffset(planegeometry->GetIndexToWorldTransform()->GetOffset());
right.SetVnlVector( rotation.rotation_matrix_transpose()*right.GetVnlVector() );
bottom.SetVnlVector(rotation.rotation_matrix_transpose()*bottom.GetVnlVector());
normal.SetVnlVector(rotation.rotation_matrix_transpose()*normal.GetVnlVector());
planegeometry->SetIndexToWorldTransform(transform);
//The origin changed,because m_Origin=m_IndexToWorldTransform->GetOffset()+GetAxisVector(2)*0.5
//and the AxisVector changes due to the rotation. In other words: the rotation was done around
//the corner of the box, not around the planes origin. Now change it to a rotation around
//the origin, simply by re-setting the origin to the original one:
planegeometry->SetOrigin(origin);
mitk::Point3D cornerpoint0 = planegeometry->GetCornerPoint(0);
std::cout << "Testing whether SetIndexToWorldTransform kept origin: ";
if(mitk::Equal(planegeometry->GetOrigin(), origin, testEps)==false)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
MITK_TEST_OUTPUT( << "Testing consistancy of index and world coordinates. ");
mitk::Point2D point; point[0] = 4; point[1] = 3;
mitk::Point2D dummy;
planegeometry->WorldToIndex(point, dummy);
planegeometry->IndexToWorld(dummy, dummy);
MITK_TEST_CONDITION_REQUIRED(dummy == point, "");
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing width, height and thickness (in mm) of rotated version: ";
if((mitk::Equal(planegeometry->GetExtentInMM(0),widthInMM, testEps)==false) ||
(mitk::Equal(planegeometry->GetExtentInMM(1),heightInMM, testEps)==false) ||
(mitk::Equal(planegeometry->GetExtentInMM(2),thicknessInMM, testEps)==false)
)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing GetAxisVector() of rotated version: ";
if((mitk::Equal(planegeometry->GetAxisVector(0), right, testEps)==false) || (mitk::Equal(planegeometry->GetAxisVector(1), bottom, testEps)==false) || (mitk::Equal(planegeometry->GetAxisVector(2), normal, testEps)==false))
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing GetAxisVector(direction).GetNorm() != planegeometry->GetExtentInMM(direction) of rotated version: ";
if((mitk::Equal(planegeometry->GetAxisVector(0).GetNorm(),planegeometry->GetExtentInMM(0), testEps)==false) ||
(mitk::Equal(planegeometry->GetAxisVector(1).GetNorm(),planegeometry->GetExtentInMM(1), testEps)==false) ||
(mitk::Equal(planegeometry->GetAxisVector(2).GetNorm(),planegeometry->GetExtentInMM(2), testEps)==false)
)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
result = mappingTests2D(planegeometry, width, height, widthInMM, heightInMM, origin, right, bottom);
if(result!=EXIT_SUCCESS)
return result;
std::cout << "Testing SetSizeInUnits() of rotated version: "<<std::endl;
width *= 2;
height *= 3;
planegeometry->SetSizeInUnits(width, height);
std::cout << "Testing width, height and thickness (in units): ";
if((mitk::Equal(planegeometry->GetExtent(0),width, testEps)==false) ||
(mitk::Equal(planegeometry->GetExtent(1),height, testEps)==false) ||
(mitk::Equal(planegeometry->GetExtent(2),1, testEps)==false)
)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing width, height and thickness (in mm) of version with changed size in units: ";
if(!mitk::Equal(planegeometry->GetExtentInMM(0), widthInMM, testEps) || !mitk::Equal(planegeometry->GetExtentInMM(1), heightInMM, testEps) || !mitk::Equal(planegeometry->GetExtentInMM(2), thicknessInMM, testEps))
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing GetAxisVector() of version with changed size in units: ";
if((mitk::Equal(planegeometry->GetAxisVector(0), right, testEps)==false) || (mitk::Equal(planegeometry->GetAxisVector(1), bottom, testEps)==false) || (mitk::Equal(planegeometry->GetAxisVector(2), normal, testEps)==false))
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing GetAxisVector(direction).GetNorm() != planegeometry->GetExtentInMM(direction) of rotated version: ";
if((mitk::Equal(planegeometry->GetAxisVector(0).GetNorm(),planegeometry->GetExtentInMM(0), testEps)==false) ||
(mitk::Equal(planegeometry->GetAxisVector(1).GetNorm(),planegeometry->GetExtentInMM(1), testEps)==false) ||
(mitk::Equal(planegeometry->GetAxisVector(2).GetNorm(),planegeometry->GetExtentInMM(2), testEps)==false)
)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
result = mappingTests2D(planegeometry, width, height, widthInMM, heightInMM, origin, right, bottom);
if(result!=EXIT_SUCCESS)
return result;
std::cout << "Testing Clone(): ";
mitk::PlaneGeometry::Pointer clonedplanegeometry = dynamic_cast<mitk::PlaneGeometry*>(planegeometry->Clone().GetPointer());
if((clonedplanegeometry.IsNull()) || (clonedplanegeometry->GetReferenceCount()!=1))
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing origin of cloned version: ";
if(mitk::Equal(clonedplanegeometry->GetOrigin(), origin, testEps)==false)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing width, height and thickness (in units) of cloned version: ";
if((mitk::Equal(clonedplanegeometry->GetExtent(0),width, testEps)==false) ||
(mitk::Equal(clonedplanegeometry->GetExtent(1),height, testEps)==false) ||
(mitk::Equal(clonedplanegeometry->GetExtent(2),1, testEps)==false)
)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing width, height and thickness (in mm) of cloned version: ";
if(!mitk::Equal(clonedplanegeometry->GetExtentInMM(0), widthInMM, testEps) || !mitk::Equal(clonedplanegeometry->GetExtentInMM(1), heightInMM, testEps) || !mitk::Equal(clonedplanegeometry->GetExtentInMM(2), thicknessInMM, testEps))
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing GetAxisVector() of cloned version: ";
if((mitk::Equal(clonedplanegeometry->GetAxisVector(0), right, testEps)==false) || (mitk::Equal(clonedplanegeometry->GetAxisVector(1), bottom, testEps)==false) || (mitk::Equal(clonedplanegeometry->GetAxisVector(2), normal, testEps)==false))
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
result = mappingTests2D(clonedplanegeometry, width, height, widthInMM, heightInMM, origin, right, bottom);
if(result!=EXIT_SUCCESS)
return result;
// Clone, move, rotate and test for 'IsParallel' and 'IsOnPlane'
std::cout << "Testing Clone(): ";
mitk::PlaneGeometry::Pointer clonedplanegeometry2 = dynamic_cast<mitk::PlaneGeometry*>(planegeometry->Clone().GetPointer());
if((clonedplanegeometry2.IsNull()) || (clonedplanegeometry2->GetReferenceCount()!=1))
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout << "Testing if cloned and original version are at the same place: ";
if(mitk::Equal(clonedplanegeometry2->IsOnPlane(planegeometry.GetPointer()), true) ==false)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing if the origin is on the plane: ";
if(mitk::Equal(clonedplanegeometry2->IsOnPlane(origin), true)==false)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
mitk::VnlVector newaxis(3);
mitk::FillVector3D(newaxis, 1.0, 1.0, 1.0); newaxis.normalize();
vnl_quaternion<mitk::ScalarType> rotation2(newaxis, 0.0);
mitk::Vector3D clonednormal = clonedplanegeometry2->GetNormal();
mitk::Point3D clonedorigin = clonedplanegeometry2->GetOrigin();
mitk::RotationOperation* planerot = new mitk::RotationOperation( mitk::OpROTATE, origin, clonedplanegeometry2->GetAxisVector( 0 ), 180.0 );
clonedplanegeometry2->ExecuteOperation( planerot );
std::cout << "Testing whether the flipped plane is still the original plane: ";
if( mitk::Equal( clonedplanegeometry2->IsOnPlane(planegeometry.GetPointer()), true )==false )
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
clonedorigin += clonednormal;
clonedplanegeometry2->SetOrigin( clonedorigin );
std::cout << "Testing if the translated (cloned, flipped) plane is parallel to its origin plane: ";
if( mitk::Equal( clonedplanegeometry2->IsParallel(planegeometry), true )==false )
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
delete planerot;
planerot = new mitk::RotationOperation( mitk::OpROTATE, origin, clonedplanegeometry2->GetAxisVector( 0 ), 0.5 );
clonedplanegeometry2->ExecuteOperation( planerot );
std::cout << "Testing if a non-paralell plane gets recognized as not paralell [rotation +0.5 degree] : ";
if( mitk::Equal( clonedplanegeometry2->IsParallel(planegeometry), false )==false )
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
delete planerot;
planerot = new mitk::RotationOperation( mitk::OpROTATE, origin, clonedplanegeometry2->GetAxisVector( 0 ), -1.0 );
clonedplanegeometry2->ExecuteOperation( planerot );
std::cout << "Testing if a non-paralell plane gets recognized as not paralell [rotation -0.5 degree] : ";
if( mitk::Equal( clonedplanegeometry2->IsParallel(planegeometry), false )==false )
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
delete planerot;
planerot = new mitk::RotationOperation( mitk::OpROTATE, origin, clonedplanegeometry2->GetAxisVector( 0 ), 360.5 );
clonedplanegeometry2->ExecuteOperation( planerot );
std::cout << "Testing if a non-paralell plane gets recognized as not paralell [rotation 360 degree] : ";
if( mitk::Equal( clonedplanegeometry2->IsParallel(planegeometry), true )==false )
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing InitializeStandardPlane(clonedplanegeometry, planeorientation = Axial, zPosition = 0, frontside=true): " <<std::endl;
planegeometry->InitializeStandardPlane(clonedplanegeometry);
std::cout << "Testing origin of axially initialized version: ";
if(mitk::Equal(planegeometry->GetOrigin(), origin)==false)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing GetCornerPoint(0) of axially initialized version: ";
if(mitk::Equal(planegeometry->GetCornerPoint(0), cornerpoint0)==false)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing width, height and thickness (in units) of axially initialized version (should be same as in mm due to unit spacing, except for thickness, which is always 1): ";
if(!mitk::Equal(planegeometry->GetExtent(0), width, testEps) || !mitk::Equal(planegeometry->GetExtent(1), height, testEps) || !mitk::Equal(planegeometry->GetExtent(2), 1, testEps))
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing width, height and thickness (in mm) of axially initialized version: ";
if(!mitk::Equal(planegeometry->GetExtentInMM(0), widthInMM, testEps) || !mitk::Equal(planegeometry->GetExtentInMM(1), heightInMM, testEps) || !mitk::Equal(planegeometry->GetExtentInMM(2), thicknessInMM, testEps))
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing GetAxisVector() of axially initialized version: ";
if((mitk::Equal(planegeometry->GetAxisVector(0), right, testEps)==false) || (mitk::Equal(planegeometry->GetAxisVector(1), bottom, testEps)==false) || (mitk::Equal(planegeometry->GetAxisVector(2), normal, testEps)==false))
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
result = mappingTests2D(planegeometry, width, height, widthInMM, heightInMM, origin, right, bottom);
if(result!=EXIT_SUCCESS)
return result;
mitk::Vector3D newright, newbottom, newnormal;
mitk::ScalarType newthicknessInMM;
std::cout << "Testing InitializeStandardPlane(clonedplanegeometry, planeorientation = Frontal, zPosition = 0, frontside=true): " <<std::endl;
planegeometry->InitializeStandardPlane(clonedplanegeometry, mitk::PlaneGeometry::Frontal);
newright = right;
newbottom = normal; newbottom.Normalize(); newbottom *= thicknessInMM;
newthicknessInMM = heightInMM/height*1.0/*extent in normal direction is 1*/;
newnormal = -bottom; newnormal.Normalize(); newnormal *= newthicknessInMM;
std::cout << "Testing GetCornerPoint(0) of frontally initialized version: ";
if(mitk::Equal(planegeometry->GetCornerPoint(0), cornerpoint0, testEps)==false)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
//ok, corner was fine, so we can dare to believe the origin is ok.
origin = planegeometry->GetOrigin();
std::cout << "Testing width, height and thickness (in units) of frontally initialized version: ";
if(!mitk::Equal(planegeometry->GetExtent(0), width, testEps) || !mitk::Equal(planegeometry->GetExtent(1), 1, testEps) || !mitk::Equal(planegeometry->GetExtent(2), 1, testEps))
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing width, height and thickness (in mm) of frontally initialized version: ";
if(!mitk::Equal(planegeometry->GetExtentInMM(0), widthInMM, testEps) || !mitk::Equal(planegeometry->GetExtentInMM(1), thicknessInMM, testEps) || !mitk::Equal(planegeometry->GetExtentInMM(2), newthicknessInMM, testEps))
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing GetAxisVector() of frontally initialized version: ";
if((mitk::Equal(planegeometry->GetAxisVector(0), newright, testEps)==false) || (mitk::Equal(planegeometry->GetAxisVector(1), newbottom, testEps)==false) || (mitk::Equal(planegeometry->GetAxisVector(2), newnormal, testEps)==false))
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
result = mappingTests2D(planegeometry, width, 1, widthInMM, thicknessInMM, origin, newright, newbottom);
if(result!=EXIT_SUCCESS)
return result;
std::cout << "Changing plane to in-plane unit spacing using SetSizeInUnits: " <<std::endl;
planegeometry->SetSizeInUnits(planegeometry->GetExtentInMM(0), planegeometry->GetExtentInMM(1));
std::cout << "Testing origin of unit spaced, frontally initialized version: ";
if(mitk::Equal(planegeometry->GetOrigin(), origin, testEps)==false)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing width, height and thickness (in units) of unit spaced, frontally initialized version: ";
if(!mitk::Equal(planegeometry->GetExtent(0), widthInMM, testEps) || !mitk::Equal(planegeometry->GetExtent(1), thicknessInMM, testEps) || !mitk::Equal(planegeometry->GetExtent(2), 1, testEps))
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing width, height and thickness (in mm) of unit spaced, frontally initialized version: ";
if(!mitk::Equal(planegeometry->GetExtentInMM(0), widthInMM, testEps) || !mitk::Equal(planegeometry->GetExtentInMM(1), thicknessInMM, testEps) || !mitk::Equal(planegeometry->GetExtentInMM(2), newthicknessInMM, testEps))
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing GetAxisVector() of unit spaced, frontally initialized version: ";
if((mitk::Equal(planegeometry->GetAxisVector(0), newright, testEps)==false) || (mitk::Equal(planegeometry->GetAxisVector(1), newbottom, testEps)==false) || (mitk::Equal(planegeometry->GetAxisVector(2), newnormal, testEps)==false))
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
result = mappingTests2D(planegeometry, widthInMM, thicknessInMM, widthInMM, thicknessInMM, origin, newright, newbottom);
if(result!=EXIT_SUCCESS)
return result;
std::cout << "Changing plane to unit spacing also in normal direction using SetExtentInMM(2, 1.0): " <<std::endl;
planegeometry->SetExtentInMM(2, 1.0);
newnormal.Normalize();
std::cout << "Testing origin of unit spaced, frontally initialized version: ";
if(mitk::Equal(planegeometry->GetOrigin(), origin, testEps)==false)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing width, height and thickness (in units) of unit spaced, frontally initialized version: ";
if(!mitk::Equal(planegeometry->GetExtent(0), widthInMM, testEps) || !mitk::Equal(planegeometry->GetExtent(1), thicknessInMM, testEps) || !mitk::Equal(planegeometry->GetExtent(2), 1, testEps))
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing width, height and thickness (in mm) of unit spaced, frontally initialized version: ";
if(!mitk::Equal(planegeometry->GetExtentInMM(0), widthInMM, testEps) || !mitk::Equal(planegeometry->GetExtentInMM(1), thicknessInMM, testEps) || !mitk::Equal(planegeometry->GetExtentInMM(2), 1.0, testEps))
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing GetAxisVector() of unit spaced, frontally initialized version: ";
if((mitk::Equal(planegeometry->GetAxisVector(0), newright, testEps)==false) || (mitk::Equal(planegeometry->GetAxisVector(1), newbottom, testEps)==false) || (mitk::Equal(planegeometry->GetAxisVector(2), newnormal, testEps)==false))
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
result = mappingTests2D(planegeometry, widthInMM, thicknessInMM, widthInMM, thicknessInMM, origin, newright, newbottom);
if(result!=EXIT_SUCCESS)
return result;
std::cout << "Testing InitializeStandardPlane(clonedplanegeometry, planeorientation = Sagittal, zPosition = 0, frontside=true): " <<std::endl;
planegeometry->InitializeStandardPlane(clonedplanegeometry, mitk::PlaneGeometry::Sagittal);
newright = bottom;
newthicknessInMM = widthInMM/width*1.0/*extent in normal direction is 1*/;
newnormal = right; newnormal.Normalize(); newnormal *= newthicknessInMM;
std::cout << "Testing GetCornerPoint(0) of sagitally initialized version: ";
if(mitk::Equal(planegeometry->GetCornerPoint(0), cornerpoint0, testEps)==false)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
//ok, corner was fine, so we can dare to believe the origin is ok.
origin = planegeometry->GetOrigin();
std::cout << "Testing width, height and thickness (in units) of sagitally initialized version: ";
if(!mitk::Equal(planegeometry->GetExtent(0), height, testEps) || !mitk::Equal(planegeometry->GetExtent(1), 1, testEps) || !mitk::Equal(planegeometry->GetExtent(2), 1, testEps))
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing width, height and thickness (in mm) of sagitally initialized version: ";
if(!mitk::Equal(planegeometry->GetExtentInMM(0), heightInMM, testEps) || !mitk::Equal(planegeometry->GetExtentInMM(1), thicknessInMM, testEps) || !mitk::Equal(planegeometry->GetExtentInMM(2), newthicknessInMM, testEps))
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing GetAxisVector() of sagitally initialized version: ";
if((mitk::Equal(planegeometry->GetAxisVector(0), newright, testEps)==false) || (mitk::Equal(planegeometry->GetAxisVector(1), newbottom, testEps)==false) || (mitk::Equal(planegeometry->GetAxisVector(2), newnormal, testEps)==false))
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
result = mappingTests2D(planegeometry, height, 1, heightInMM, thicknessInMM, origin, newright, newbottom);
if(result!=EXIT_SUCCESS)
return result;
//set origin back to the one of the axial slice:
origin = clonedplanegeometry->GetOrigin();
std::cout << "Testing backside initialization: InitializeStandardPlane(clonedplanegeometry, planeorientation = Axial, zPosition = 0, frontside=false, rotated=true): " <<std::endl;
planegeometry->InitializeStandardPlane(clonedplanegeometry, mitk::PlaneGeometry::Axial, 0, false, true);
mitk::Point3D backsideorigin;
backsideorigin=origin+clonedplanegeometry->GetAxisVector(1);//+clonedplanegeometry->GetAxisVector(2);
std::cout << "Testing origin of backsidedly, axially initialized version: ";
if(mitk::Equal(planegeometry->GetOrigin(), backsideorigin, testEps)==false)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing GetCornerPoint(0) of sagitally initialized version: ";
mitk::Point3D backsidecornerpoint0;
backsidecornerpoint0 = cornerpoint0+clonedplanegeometry->GetAxisVector(1);//+clonedplanegeometry->GetAxisVector(2);
if(mitk::Equal(planegeometry->GetCornerPoint(0), backsidecornerpoint0, testEps)==false)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing width, height and thickness (in units) of backsidedly, axially initialized version (should be same as in mm due to unit spacing, except for thickness, which is always 1): ";
if(!mitk::Equal(planegeometry->GetExtent(0), width, testEps) || !mitk::Equal(planegeometry->GetExtent(1), height, testEps) || !mitk::Equal(planegeometry->GetExtent(2), 1, testEps))
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing width, height and thickness (in mm) of backsidedly, axially initialized version: ";
if(!mitk::Equal(planegeometry->GetExtentInMM(0), widthInMM, testEps) || !mitk::Equal(planegeometry->GetExtentInMM(1), heightInMM, testEps) || !mitk::Equal(planegeometry->GetExtentInMM(2), thicknessInMM, testEps))
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing GetAxisVector() of backsidedly, axially initialized version: ";
if((mitk::Equal(planegeometry->GetAxisVector(0), right, testEps)==false) || (mitk::Equal(planegeometry->GetAxisVector(1), -bottom, testEps)==false) || (mitk::Equal(planegeometry->GetAxisVector(2), -normal, testEps)==false))
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
result = mappingTests2D(planegeometry, width, height, widthInMM, heightInMM, backsideorigin, right, -bottom);
if(result!=EXIT_SUCCESS)
return result;
// test method mitk::PlaneGeometry::ProjectPointOntoPlane()
// (see also bug #3409)
result = TestProjectPointOntoPlane();
if(result!=EXIT_SUCCESS)
return result;
// testing mitk::PlaneGeometry::IntersectionPoint()
std::cout << std::endl;
std::cout << "Testing IntersectionPoint using given plane and given line: ";
result = TestIntersectionPoint();
if (result != EXIT_SUCCESS) {
std::cout << "[FAILED]" << std::endl;
return result;
}
std::cout<<"[PASSED]"<<std::endl<<std::endl;
+ int result2;
+
+ MITK_TEST_CONDITION_REQUIRED ( (result2 = testPlaneGeometryCloning()) == EXIT_SUCCESS, "");
+
+ // See bug 15990
+ // MITK_TEST_CONDITION_REQUIRED ( (result = testPlaneGeometryInitializeOrder()) == EXIT_SUCCESS, "");
std::cout<<"[TEST DONE]"<<std::endl;
return EXIT_SUCCESS;
}
diff --git a/Core/Code/Testing/mitkSliceNavigationControllerTest.cpp b/Core/Code/Testing/mitkSliceNavigationControllerTest.cpp
index 77340c28fc..6541f21663 100644
--- a/Core/Code/Testing/mitkSliceNavigationControllerTest.cpp
+++ b/Core/Code/Testing/mitkSliceNavigationControllerTest.cpp
@@ -1,572 +1,572 @@
/*===================================================================
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 "mitkSliceNavigationController.h"
#include "mitkPlaneGeometry.h"
#include "mitkSlicedGeometry3D.h"
#include "mitkRotationOperation.h"
#include "mitkInteractionConst.h"
#include "mitkPlanePositionManager.h"
#include "mitkTestingMacros.h"
#include "usGetModuleContext.h"
#include "usModuleContext.h"
#include "usServiceReference.h"
#include <vnl/vnl_quaternion.h>
#include <vnl/vnl_quaternion.txx>
#include <fstream>
bool operator==(const mitk::Geometry3D & left, const mitk::Geometry3D & right)
{
mitk::BoundingBox::BoundsArrayType leftbounds, rightbounds;
leftbounds =left.GetBounds();
rightbounds=right.GetBounds();
unsigned int i;
for(i=0;i<6;++i)
if(mitk::Equal(leftbounds[i],rightbounds[i])==false) return false;
const mitk::Geometry3D::TransformType::MatrixType & leftmatrix = left.GetIndexToWorldTransform()->GetMatrix();
const mitk::Geometry3D::TransformType::MatrixType & rightmatrix = right.GetIndexToWorldTransform()->GetMatrix();
unsigned int j;
for(i=0;i<3;++i)
{
const mitk::Geometry3D::TransformType::MatrixType::ValueType* leftvector = leftmatrix[i];
const mitk::Geometry3D::TransformType::MatrixType::ValueType* rightvector = rightmatrix[i];
for(j=0;j<3;++j)
if(mitk::Equal(leftvector[i],rightvector[i])==false) return false;
}
const mitk::Geometry3D::TransformType::OffsetType & leftoffset = left.GetIndexToWorldTransform()->GetOffset();
const mitk::Geometry3D::TransformType::OffsetType & rightoffset = right.GetIndexToWorldTransform()->GetOffset();
for(i=0;i<3;++i)
if(mitk::Equal(leftoffset[i],rightoffset[i])==false) return false;
return true;
}
int compareGeometry(const mitk::TimeGeometry & timeGeometry,
const mitk::ScalarType& width, const mitk::ScalarType& height, const mitk::ScalarType& numSlices,
const mitk::ScalarType& widthInMM, const mitk::ScalarType& heightInMM, const mitk::ScalarType& thicknessInMM,
const mitk::Point3D& cornerpoint0, const mitk::Vector3D& right, const mitk::Vector3D& bottom, const mitk::Vector3D& normal)
{
//Probleme durch umstellung von Time-SlicedGeometry auf TimeGeometry?
//Eventuell gibt es keine Entsprechung mehr.
- const mitk::Geometry3D::Pointer geometry= timeGeometry.GetGeometryForTimeStep(0);
+ const mitk::BaseGeometry::Pointer geometry= timeGeometry.GetGeometryForTimeStep(0);
std::cout << "Testing width, height and thickness (in units): ";
if((mitk::Equal(geometry->GetExtent(0),width)==false) ||
(mitk::Equal(geometry->GetExtent(1),height)==false) ||
(mitk::Equal(geometry->GetExtent(2),numSlices)==false)
)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing width, height and thickness (in mm): ";
if((mitk::Equal(geometry->GetExtentInMM(0),widthInMM)==false) ||
(mitk::Equal(geometry->GetExtentInMM(1),heightInMM)==false) ||
(mitk::Equal(geometry->GetExtentInMM(2),thicknessInMM)==false)
)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing GetAxisVector(): ";
std::cout << "dir=0 ";
mitk::Vector3D dv;
dv=right; dv.Normalize(); dv*=widthInMM;
if((mitk::Equal(geometry->GetAxisVector(0), dv)==false))
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]";
std::cout << ", dir=1 ";
dv=bottom; dv.Normalize(); dv*=heightInMM;
if((mitk::Equal(geometry->GetAxisVector(1), dv)==false))
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]";
std::cout << ", dir=2 ";
dv=normal; dv.Normalize(); dv*=thicknessInMM;
if((mitk::Equal(geometry->GetAxisVector(2), dv)==false))
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing offset: ";
if((mitk::Equal(geometry->GetCornerPoint(0),cornerpoint0, (double) vnl_math::float_eps)==false))
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
return EXIT_SUCCESS;
}
int testGeometry(const mitk::Geometry3D * geometry,
const mitk::ScalarType& width, const mitk::ScalarType& height, const mitk::ScalarType& numSlices,
const mitk::ScalarType& widthInMM, const mitk::ScalarType& heightInMM, const mitk::ScalarType& thicknessInMM,
const mitk::Point3D& cornerpoint0, const mitk::Vector3D& right, const mitk::Vector3D& bottom, const mitk::Vector3D& normal)
{
int result=EXIT_FAILURE;
std::cout << "Comparing GetCornerPoint(0) of Geometry3D with provided cornerpoint0: ";
if(mitk::Equal(geometry->GetCornerPoint(0), cornerpoint0)==false)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Creating and initializing a SliceNavigationController with the Geometry3D: ";
mitk::SliceNavigationController::Pointer sliceCtrl = mitk::SliceNavigationController::New();
sliceCtrl->SetInputWorldGeometry3D(geometry);
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing SetViewDirection(mitk::SliceNavigationController::Axial): ";
sliceCtrl->SetViewDirection(mitk::SliceNavigationController::Axial);
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing Update(): ";
sliceCtrl->Update();
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing result of CreatedWorldGeometry(): ";
mitk::Point3D axialcornerpoint0;
axialcornerpoint0 = cornerpoint0+bottom+normal*(numSlices-1+0.5); //really -1?
result = compareGeometry(*sliceCtrl->GetCreatedWorldGeometry(), width, height, numSlices, widthInMM, heightInMM, thicknessInMM*numSlices, axialcornerpoint0, right, bottom*(-1.0), normal*(-1.0));
if(result!=EXIT_SUCCESS)
{
std::cout<<"[FAILED]"<<std::endl;
return result;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing SetViewDirection(mitk::SliceNavigationController::Frontal): ";
sliceCtrl->SetViewDirection(mitk::SliceNavigationController::Frontal);
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing Update(): ";
sliceCtrl->Update();
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing result of CreatedWorldGeometry(): ";
mitk::Point3D frontalcornerpoint0;
frontalcornerpoint0 = cornerpoint0+geometry->GetAxisVector(1)*(+0.5/geometry->GetExtent(1));
result = compareGeometry(*sliceCtrl->GetCreatedWorldGeometry(), width, numSlices, height, widthInMM, thicknessInMM*numSlices, heightInMM, frontalcornerpoint0, right, normal, bottom);
if(result!=EXIT_SUCCESS)
{
std::cout<<"[FAILED]"<<std::endl;
return result;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing SetViewDirection(mitk::SliceNavigationController::Sagittal): ";
sliceCtrl->SetViewDirection(mitk::SliceNavigationController::Sagittal);
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing Update(): "<<std::endl;
sliceCtrl->Update();
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing result of CreatedWorldGeometry(): ";
mitk::Point3D sagittalcornerpoint0;
sagittalcornerpoint0 = cornerpoint0+geometry->GetAxisVector(0)*(+0.5/geometry->GetExtent(0));
result = compareGeometry(*sliceCtrl->GetCreatedWorldGeometry(), height, numSlices, width, heightInMM, thicknessInMM*numSlices, widthInMM, sagittalcornerpoint0, bottom, normal, right);
if(result!=EXIT_SUCCESS)
{
std::cout<<"[FAILED]"<<std::endl;
return result;
}
std::cout<<"[PASSED]"<<std::endl;
return EXIT_SUCCESS;
}
int testReorientPlanes ()
{
//Create PlaneGeometry
mitk::PlaneGeometry::Pointer planegeometry = mitk::PlaneGeometry::New();
mitk::Point3D origin;
mitk::Vector3D right, bottom, normal;
mitk::ScalarType width, height;
mitk::ScalarType widthInMM, heightInMM, thicknessInMM;
width = 100; widthInMM = width;
height = 200; heightInMM = height;
thicknessInMM = 1.5;
mitk::FillVector3D(origin, 4.5, 7.3, 11.2);
mitk::FillVector3D(right, widthInMM, 0, 0);
mitk::FillVector3D(bottom, 0, heightInMM, 0);
mitk::FillVector3D(normal, 0, 0, thicknessInMM);
mitk::Vector3D spacing;
normal.Normalize(); normal *= thicknessInMM;
mitk::FillVector3D(spacing, 1.0, 1.0, thicknessInMM);
planegeometry->InitializeStandardPlane(right.GetVnlVector(), bottom.GetVnlVector(), &spacing);
planegeometry->SetOrigin(origin);
//Create SlicedGeometry3D out of planeGeometry
mitk::SlicedGeometry3D::Pointer slicedgeometry1 = mitk::SlicedGeometry3D::New();
unsigned int numSlices = 20;
slicedgeometry1->InitializeEvenlySpaced(planegeometry, thicknessInMM, numSlices, false);
//Create another slicedgeo which will be rotated
mitk::SlicedGeometry3D::Pointer slicedgeometry2 = mitk::SlicedGeometry3D::New();
slicedgeometry2->InitializeEvenlySpaced(planegeometry, thicknessInMM, numSlices, false);
//Create geo3D as reference
mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New();
geometry->SetBounds(slicedgeometry1->GetBounds());
geometry->SetIndexToWorldTransform(slicedgeometry1->GetIndexToWorldTransform());
//Initialize planes
for (int i=0; i < (int)numSlices; i++)
{
mitk::PlaneGeometry::Pointer geo2d = mitk::PlaneGeometry::New();
geo2d->Initialize();
geo2d->SetReferenceGeometry(geometry);
- slicedgeometry1->SetGeometry2D(geo2d,i);
+ slicedgeometry1->SetPlaneGeometry(geo2d,i);
}
for (int i=0; i < (int)numSlices; i++)
{
mitk::PlaneGeometry::Pointer geo2d = mitk::PlaneGeometry::New();
geo2d->Initialize();
geo2d->SetReferenceGeometry(geometry);
- slicedgeometry2->SetGeometry2D(geo2d,i);
+ slicedgeometry2->SetPlaneGeometry(geo2d,i);
}
slicedgeometry1->SetReferenceGeometry(geometry);
slicedgeometry2->SetReferenceGeometry(geometry);
//Create SNC
mitk::SliceNavigationController::Pointer sliceCtrl1 = mitk::SliceNavigationController::New();
sliceCtrl1->SetInputWorldGeometry3D(slicedgeometry1);
sliceCtrl1->Update();
mitk::SliceNavigationController::Pointer sliceCtrl2 = mitk::SliceNavigationController::New();
sliceCtrl2->SetInputWorldGeometry3D(slicedgeometry2);
sliceCtrl2->Update();
slicedgeometry1->SetSliceNavigationController(sliceCtrl1);
slicedgeometry2->SetSliceNavigationController(sliceCtrl2);
// Whats current geometry?
MITK_INFO << "center: " << sliceCtrl1->GetCurrentPlaneGeometry()->GetCenter();
MITK_INFO << "normal: " << sliceCtrl1->GetCurrentPlaneGeometry()->GetNormal();
MITK_INFO << "origin: " << sliceCtrl1->GetCurrentPlaneGeometry()->GetOrigin();
MITK_INFO << "axis0 : " << sliceCtrl1->GetCurrentPlaneGeometry()->GetAxisVector(0);
MITK_INFO << "aixs1 : " << sliceCtrl1->GetCurrentPlaneGeometry()->GetAxisVector(1);
//
// Now reorient slices (ONE POINT, ONE NORMAL)
mitk::Point3D oldCenter, oldOrigin;
mitk::Vector3D oldAxis0, oldAxis1;
oldCenter = sliceCtrl1->GetCurrentPlaneGeometry()->GetCenter();
oldOrigin = sliceCtrl1->GetCurrentPlaneGeometry()->GetOrigin();
oldAxis0 = sliceCtrl1->GetCurrentPlaneGeometry()->GetAxisVector(0);
oldAxis1 = sliceCtrl1->GetCurrentPlaneGeometry()->GetAxisVector(1);
mitk::Point3D orientCenter;
mitk::Vector3D orientNormal;
orientCenter = oldCenter;
mitk::FillVector3D(orientNormal, 0.3, 0.1, 0.8);
orientNormal.Normalize();
sliceCtrl1->ReorientSlices(orientCenter,orientNormal);
mitk::Point3D newCenter, newOrigin;
mitk::Vector3D newNormal;
newCenter = sliceCtrl1->GetCurrentPlaneGeometry()->GetCenter();
newOrigin = sliceCtrl1->GetCurrentPlaneGeometry()->GetOrigin();
newNormal = sliceCtrl1->GetCurrentPlaneGeometry()->GetNormal();
newNormal.Normalize();
itk::Index<3> orientCenterIdx;
itk::Index<3> newCenterIdx;
sliceCtrl1->GetCurrentGeometry3D()->WorldToIndex(orientCenter, orientCenterIdx);
sliceCtrl1->GetCurrentGeometry3D()->WorldToIndex(newCenter, newCenterIdx);
if (
(newCenterIdx != orientCenterIdx) ||
( !mitk::Equal(orientNormal, newNormal) )
)
{
MITK_INFO << "Reorient Planes (1 point, 1 vector) not working as it should";
MITK_INFO << "orientCenterIdx: " << orientCenterIdx;
MITK_INFO << "newCenterIdx: " << newCenterIdx;
MITK_INFO << "orientNormal: " << orientNormal;
MITK_INFO << "newNormal: " << newNormal;
return EXIT_FAILURE;
}
//
// Now reorient slices (center, vec0, vec1 )
mitk::Vector3D orientAxis0, orientAxis1, newAxis0, newAxis1;
mitk::FillVector3D(orientAxis0, 1.0, 0.0, 0.0);
mitk::FillVector3D(orientAxis1, 0.0, 1.0, 0.0);
orientAxis0.Normalize();
orientAxis1.Normalize();
sliceCtrl1->ReorientSlices(orientCenter,orientAxis0, orientAxis1);
newAxis0 = sliceCtrl1->GetCurrentPlaneGeometry()->GetAxisVector(0);
newAxis1 = sliceCtrl1->GetCurrentPlaneGeometry()->GetAxisVector(1);
newCenter = sliceCtrl1->GetCurrentPlaneGeometry()->GetCenter();
newAxis0.Normalize();
newAxis1.Normalize();
sliceCtrl1->GetCurrentGeometry3D()->WorldToIndex(orientCenter, orientCenterIdx);
sliceCtrl1->GetCurrentGeometry3D()->WorldToIndex(newCenter, newCenterIdx);
if (
(newCenterIdx != orientCenterIdx) ||
( !mitk::Equal(orientAxis0, newAxis0, 1E-12) ) ||
( !mitk::Equal(orientAxis1, newAxis1, 1E-12 ))
)
{
MITK_INFO << "Reorient Planes (point, vec, vec) not working as it should";
MITK_INFO << "orientCenterIdx: " << orientCenterIdx;
MITK_INFO << "newCenterIdx: " << newCenterIdx;
MITK_INFO << "orientAxis0: " << orientAxis0;
MITK_INFO << "newAxis0: " << newAxis0;
MITK_INFO << "orientAxis1: " << orientAxis1;
MITK_INFO << "newAxis1: " << newAxis1;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
int testRestorePlanePostionOperation ()
{
//Create PlaneGeometry
mitk::PlaneGeometry::Pointer planegeometry = mitk::PlaneGeometry::New();
mitk::Point3D origin;
mitk::Vector3D right, bottom, normal;
mitk::ScalarType width, height;
mitk::ScalarType widthInMM, heightInMM, thicknessInMM;
width = 100; widthInMM = width;
height = 200; heightInMM = height;
thicknessInMM = 1.5;
mitk::FillVector3D(origin, 4.5, 7.3, 11.2);
mitk::FillVector3D(right, widthInMM, 0, 0);
mitk::FillVector3D(bottom, 0, heightInMM, 0);
mitk::FillVector3D(normal, 0, 0, thicknessInMM);
mitk::Vector3D spacing;
normal.Normalize(); normal *= thicknessInMM;
mitk::FillVector3D(spacing, 1.0, 1.0, thicknessInMM);
planegeometry->InitializeStandardPlane(right.GetVnlVector(), bottom.GetVnlVector(), &spacing);
planegeometry->SetOrigin(origin);
//Create SlicedGeometry3D out of planeGeometry
mitk::SlicedGeometry3D::Pointer slicedgeometry1 = mitk::SlicedGeometry3D::New();
unsigned int numSlices = 300;
slicedgeometry1->InitializeEvenlySpaced(planegeometry, thicknessInMM, numSlices, false);
//Create another slicedgeo which will be rotated
mitk::SlicedGeometry3D::Pointer slicedgeometry2 = mitk::SlicedGeometry3D::New();
slicedgeometry2->InitializeEvenlySpaced(planegeometry, thicknessInMM, numSlices, false);
//Create geo3D as reference
mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New();
geometry->SetBounds(slicedgeometry1->GetBounds());
geometry->SetIndexToWorldTransform(slicedgeometry1->GetIndexToWorldTransform());
//Initialize planes
for (int i=0; i < (int)numSlices; i++)
{
mitk::PlaneGeometry::Pointer geo2d = mitk::PlaneGeometry::New();
geo2d->Initialize();
geo2d->SetReferenceGeometry(geometry);
- slicedgeometry1->SetGeometry2D(geo2d,i);
+ slicedgeometry1->SetPlaneGeometry(geo2d,i);
}
for (int i=0; i < (int)numSlices; i++)
{
mitk::PlaneGeometry::Pointer geo2d = mitk::PlaneGeometry::New();
geo2d->Initialize();
geo2d->SetReferenceGeometry(geometry);
- slicedgeometry2->SetGeometry2D(geo2d,i);
+ slicedgeometry2->SetPlaneGeometry(geo2d,i);
}
slicedgeometry1->SetReferenceGeometry(geometry);
slicedgeometry2->SetReferenceGeometry(geometry);
//Create SNC
mitk::SliceNavigationController::Pointer sliceCtrl1 = mitk::SliceNavigationController::New();
sliceCtrl1->SetInputWorldGeometry3D(slicedgeometry1);
sliceCtrl1->Update();
mitk::SliceNavigationController::Pointer sliceCtrl2 = mitk::SliceNavigationController::New();
sliceCtrl2->SetInputWorldGeometry3D(slicedgeometry2);
sliceCtrl2->Update();
slicedgeometry1->SetSliceNavigationController(sliceCtrl1);
slicedgeometry2->SetSliceNavigationController(sliceCtrl2);
//Rotate slicedgeo2
double angle = 63.84;
mitk::Vector3D rotationVector; mitk::FillVector3D( rotationVector, 0.5, 0.95, 0.23 );
mitk::Point3D center = slicedgeometry2->GetCenter();
mitk::RotationOperation* op = new mitk::RotationOperation( mitk::OpROTATE, center, rotationVector, angle );
slicedgeometry2->ExecuteOperation(op);
sliceCtrl2->Update();
us::ServiceReference<mitk::PlanePositionManagerService> serviceRef =
us::GetModuleContext()->GetServiceReference<mitk::PlanePositionManagerService>();
mitk::PlanePositionManagerService* service = us::GetModuleContext()->GetService(serviceRef);
- service->AddNewPlanePosition(slicedgeometry2->GetGeometry2D(0), 178);
+ service->AddNewPlanePosition(slicedgeometry2->GetPlaneGeometry(0), 178);
sliceCtrl1->ExecuteOperation(service->GetPlanePosition(0));
sliceCtrl1->Update();
- mitk::Geometry2D* planeRotated = slicedgeometry2->GetGeometry2D(178);
- mitk::Geometry2D* planeRestored = dynamic_cast< const mitk::SlicedGeometry3D*>(sliceCtrl1->GetCurrentGeometry3D())->GetGeometry2D(178);
+ mitk::PlaneGeometry* planeRotated = slicedgeometry2->GetPlaneGeometry(178);
+ mitk::PlaneGeometry* planeRestored = dynamic_cast< const mitk::SlicedGeometry3D*>(sliceCtrl1->GetCurrentGeometry3D())->GetPlaneGeometry(178);
try{
MITK_TEST_CONDITION_REQUIRED(mitk::MatrixEqualElementWise(planeRotated->GetIndexToWorldTransform()->GetMatrix(), planeRestored->GetIndexToWorldTransform()->GetMatrix()),"Testing for IndexToWorld");
MITK_TEST_CONDITION_REQUIRED(mitk::Equal(planeRotated->GetOrigin(), planeRestored->GetOrigin(),2*mitk::eps),"Testing for origin");
MITK_TEST_CONDITION_REQUIRED(mitk::Equal(planeRotated->GetSpacing(), planeRestored->GetSpacing()),"Testing for spacing");
MITK_TEST_CONDITION_REQUIRED(mitk::Equal(slicedgeometry2->GetDirectionVector(), dynamic_cast< const mitk::SlicedGeometry3D*>(sliceCtrl1->GetCurrentGeometry3D())->GetDirectionVector()),"Testing for directionvector");
MITK_TEST_CONDITION_REQUIRED(mitk::Equal(slicedgeometry2->GetSlices(), dynamic_cast< const mitk::SlicedGeometry3D*>(sliceCtrl1->GetCurrentGeometry3D())->GetSlices()),"Testing for numslices");
MITK_TEST_CONDITION_REQUIRED(mitk::MatrixEqualElementWise(slicedgeometry2->GetIndexToWorldTransform()->GetMatrix(), dynamic_cast< const mitk::SlicedGeometry3D*>(sliceCtrl1->GetCurrentGeometry3D())->GetIndexToWorldTransform()->GetMatrix()),"Testing for IndexToWorld");
}
catch(...)
{
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
int mitkSliceNavigationControllerTest(int /*argc*/, char* /*argv*/[])
{
int result=EXIT_FAILURE;
std::cout << "Creating and initializing a PlaneGeometry: ";
mitk::PlaneGeometry::Pointer planegeometry = mitk::PlaneGeometry::New();
mitk::Point3D origin;
mitk::Vector3D right, bottom, normal;
mitk::ScalarType width, height;
mitk::ScalarType widthInMM, heightInMM, thicknessInMM;
width = 100; widthInMM = width;
height = 200; heightInMM = height;
thicknessInMM = 1.5;
// mitk::FillVector3D(origin, 0, 0, thicknessInMM*0.5);
mitk::FillVector3D(origin, 4.5, 7.3, 11.2);
mitk::FillVector3D(right, widthInMM, 0, 0);
mitk::FillVector3D(bottom, 0, heightInMM, 0);
mitk::FillVector3D(normal, 0, 0, thicknessInMM);
mitk::Vector3D spacing;
normal.Normalize(); normal *= thicknessInMM;
mitk::FillVector3D(spacing, 1.0, 1.0, thicknessInMM);
planegeometry->InitializeStandardPlane(right.GetVnlVector(), bottom.GetVnlVector(), &spacing);
planegeometry->SetOrigin(origin);
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Creating and initializing a SlicedGeometry3D with the PlaneGeometry: ";
mitk::SlicedGeometry3D::Pointer slicedgeometry = mitk::SlicedGeometry3D::New();
unsigned int numSlices = 5;
slicedgeometry->InitializeEvenlySpaced(planegeometry, thicknessInMM, numSlices, false);
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Creating a Geometry3D with the same extent as the SlicedGeometry3D: ";
mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New();
geometry->SetBounds(slicedgeometry->GetBounds());
geometry->SetIndexToWorldTransform(slicedgeometry->GetIndexToWorldTransform());
std::cout<<"[PASSED]"<<std::endl;
mitk::Point3D cornerpoint0;
cornerpoint0 = geometry->GetCornerPoint(0);
result=testGeometry(geometry, width, height, numSlices, widthInMM, heightInMM, thicknessInMM, cornerpoint0, right, bottom, normal);
if(result!=EXIT_SUCCESS)
return result;
mitk::AffineTransform3D::Pointer transform = mitk::AffineTransform3D::New();
transform->SetMatrix(geometry->GetIndexToWorldTransform()->GetMatrix());
mitk::BoundingBox::Pointer boundingbox = geometry->CalculateBoundingBoxRelativeToTransform(transform);
geometry->SetBounds(boundingbox->GetBounds());
cornerpoint0 = geometry->GetCornerPoint(0);
result=testGeometry(geometry, width, height, numSlices, widthInMM, heightInMM, thicknessInMM, cornerpoint0, right, bottom, normal);
if(result!=EXIT_SUCCESS)
return result;
std::cout << "Changing the IndexToWorldTransform of the geometry to a rotated version by SetIndexToWorldTransform() (keep cornerpoint0): ";
transform = mitk::AffineTransform3D::New();
mitk::AffineTransform3D::MatrixType::InternalMatrixType vnlmatrix;
vnlmatrix = planegeometry->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix();
mitk::VnlVector axis(3);
mitk::FillVector3D(axis, 1.0, 1.0, 1.0); axis.normalize();
vnl_quaternion<mitk::ScalarType> rotation(axis, 0.223);
vnlmatrix = rotation.rotation_matrix_transpose()*vnlmatrix;
mitk::Matrix3D matrix;
matrix = vnlmatrix;
transform->SetMatrix(matrix);
transform->SetOffset(cornerpoint0.GetVectorFromOrigin());
right.SetVnlVector( rotation.rotation_matrix_transpose()*right.GetVnlVector() );
bottom.SetVnlVector(rotation.rotation_matrix_transpose()*bottom.GetVnlVector());
normal.SetVnlVector(rotation.rotation_matrix_transpose()*normal.GetVnlVector());
geometry->SetIndexToWorldTransform(transform);
std::cout<<"[PASSED]"<<std::endl;
cornerpoint0 = geometry->GetCornerPoint(0);
result = testGeometry(geometry, width, height, numSlices, widthInMM, heightInMM, thicknessInMM, cornerpoint0, right, bottom, normal);
if(result!=EXIT_SUCCESS)
return result;
//Testing Execute RestorePlanePositionOperation
result = testRestorePlanePostionOperation();
if(result!=EXIT_SUCCESS)
return result;
// Re-Orient planes not working as it should on windows
// However, this might be adjusted during a geometry redesign.
/*
//Testing ReorientPlanes
result = testReorientPlanes();
if(result!=EXIT_SUCCESS)
return result;
*/
std::cout<<"[TEST DONE]"<<std::endl;
return EXIT_SUCCESS;
}
\ No newline at end of file
diff --git a/Core/Code/Testing/mitkSlicedGeometry3DTest.cpp b/Core/Code/Testing/mitkSlicedGeometry3DTest.cpp
index 25dfb12c92..6555c4425e 100644
--- a/Core/Code/Testing/mitkSlicedGeometry3DTest.cpp
+++ b/Core/Code/Testing/mitkSlicedGeometry3DTest.cpp
@@ -1,257 +1,257 @@
/*===================================================================
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 "mitkImage.h"
#include "mitkPlaneGeometry.h"
#include "mitkSlicedGeometry3D.h"
#include "mitkTestingMacros.h"
#include <vnl/vnl_quaternion.h>
#include <vnl/vnl_quaternion.txx>
#include <fstream>
static const mitk::ScalarType slicedGeometryEps = 1E-9; // epsilon for this testfile. Set to float precision.
void mitkSlicedGeometry3D_ChangeImageGeometryConsideringOriginOffset_Test()
{
//Tests for Offset
MITK_TEST_OUTPUT( << "====== NOW RUNNING: Tests for pixel-center-based offset concerns ========");
// create a SlicedGeometry3D
mitk::SlicedGeometry3D::Pointer slicedGeo3D=mitk::SlicedGeometry3D::New();
int num_slices = 5;
slicedGeo3D->InitializeSlicedGeometry(num_slices); // 5 slices
mitk::Point3D newOrigin;
newOrigin[0] = 91.3;
newOrigin[1] = -13.3;
newOrigin[2] = 0;
slicedGeo3D->SetOrigin(newOrigin);
mitk::Vector3D newSpacing;
newSpacing[0] = 1.0f;
newSpacing[1] = 0.9f;
newSpacing[2] = 0.3f;
slicedGeo3D->SetSpacing(newSpacing);
// create subslices as well
for (int i=0; i < num_slices; i++)
{
- mitk::Geometry2D::Pointer geo2d = mitk::Geometry2D::New();
+ mitk::PlaneGeometry::Pointer geo2d = mitk::PlaneGeometry::New();
geo2d->Initialize();
- slicedGeo3D->SetGeometry2D(geo2d,i);
+ slicedGeo3D->SetPlaneGeometry(geo2d,i);
}
// now run tests
MITK_TEST_OUTPUT( << "Testing whether slicedGeo3D->GetImageGeometry() is false by default");
MITK_TEST_CONDITION_REQUIRED( slicedGeo3D->GetImageGeometry()==false, "");
MITK_TEST_OUTPUT( << "Testing whether first and last geometry in the SlicedGeometry3D have GetImageGeometry()==false by default");
- mitk::Geometry3D* subSliceGeo2D_first = slicedGeo3D->GetGeometry2D(0);
- mitk::Geometry3D* subSliceGeo2D_last = slicedGeo3D->GetGeometry2D(num_slices-1);
+ mitk::BaseGeometry* subSliceGeo2D_first = slicedGeo3D->GetPlaneGeometry(0);
+ mitk::BaseGeometry* subSliceGeo2D_last = slicedGeo3D->GetPlaneGeometry(num_slices-1);
MITK_TEST_CONDITION_REQUIRED( subSliceGeo2D_first->GetImageGeometry()==false, "");
MITK_TEST_CONDITION_REQUIRED( subSliceGeo2D_last->GetImageGeometry()==false, "");
// Save some Origins and cornerpoints
mitk::Point3D OriginSlicedGeo( slicedGeo3D->GetOrigin() );
mitk::Point3D OriginFirstGeo( subSliceGeo2D_first->GetOrigin() );
mitk::Point3D OriginLastGeo( subSliceGeo2D_last->GetOrigin() );
mitk::Point3D CornerPoint0SlicedGeo(slicedGeo3D->GetCornerPoint(0));
mitk::Point3D CornerPoint1FirstGeo(subSliceGeo2D_first->GetCornerPoint(1));
mitk::Point3D CornerPoint2LastGeo(subSliceGeo2D_last->GetCornerPoint(2));
MITK_TEST_OUTPUT( << "Calling slicedGeo3D->ChangeImageGeometryConsideringOriginOffset(true)");
//std::cout << "vorher Origin: " << subSliceGeo2D_first->GetOrigin() << std::endl;
//std::cout << "vorher Corner: " << subSliceGeo2D_first->GetCornerPoint(0) << std::endl;
slicedGeo3D->ChangeImageGeometryConsideringOriginOffset(true);
//std::cout << "nachher Origin: " << subSliceGeo2D_first->GetOrigin() << std::endl;
//std::cout << "nachher Corner: " << subSliceGeo2D_first->GetCornerPoint(0) << std::endl;
MITK_TEST_OUTPUT( << "Testing whether slicedGeo3D->GetImageGeometry() is now true");
MITK_TEST_CONDITION_REQUIRED( slicedGeo3D->GetImageGeometry()==true, "");
MITK_TEST_OUTPUT( << "Testing whether first and last geometry in the SlicedGeometry3D have GetImageGeometry()==true now");
MITK_TEST_CONDITION_REQUIRED( subSliceGeo2D_first->GetImageGeometry()==true, "");
MITK_TEST_CONDITION_REQUIRED( subSliceGeo2D_last->GetImageGeometry()==true, "");
MITK_TEST_OUTPUT( << "Testing wether offset has been added to origins");
// Manually adding Offset.
OriginSlicedGeo[0] += (slicedGeo3D->GetSpacing()[0]) / 2;
OriginSlicedGeo[1] += (slicedGeo3D->GetSpacing()[1]) / 2;
OriginSlicedGeo[2] += (slicedGeo3D->GetSpacing()[2]) / 2;
OriginFirstGeo[0] += (subSliceGeo2D_first->GetSpacing()[0]) / 2;
OriginFirstGeo[1] += (subSliceGeo2D_first->GetSpacing()[1]) / 2;
OriginFirstGeo[2] += (subSliceGeo2D_first->GetSpacing()[2]) / 2;
OriginLastGeo[0] += (subSliceGeo2D_last->GetSpacing()[0]) / 2;
OriginLastGeo[1] += (subSliceGeo2D_last->GetSpacing()[1]) / 2;
OriginLastGeo[2] += (subSliceGeo2D_last->GetSpacing()[2]) / 2;
MITK_TEST_CONDITION_REQUIRED( subSliceGeo2D_first->GetCornerPoint(1)==CornerPoint1FirstGeo, "");
MITK_TEST_CONDITION_REQUIRED( subSliceGeo2D_last->GetCornerPoint(2)==CornerPoint2LastGeo, "");
MITK_TEST_CONDITION_REQUIRED( slicedGeo3D->GetCornerPoint(0)==CornerPoint0SlicedGeo, "");
MITK_TEST_CONDITION_REQUIRED( slicedGeo3D->GetOrigin()==OriginSlicedGeo, "");
MITK_TEST_CONDITION_REQUIRED( subSliceGeo2D_first->GetOrigin()==OriginFirstGeo, "");
MITK_TEST_CONDITION_REQUIRED( subSliceGeo2D_last->GetOrigin()==OriginLastGeo, "");
MITK_TEST_OUTPUT( << "Calling slicedGeo3D->ChangeImageGeometryConsideringOriginOffset(false)");
slicedGeo3D->ChangeImageGeometryConsideringOriginOffset(false);
MITK_TEST_OUTPUT( << "Testing whether slicedGeo3D->GetImageGeometry() is now false");
MITK_TEST_CONDITION_REQUIRED( slicedGeo3D->GetImageGeometry()==false, "");
MITK_TEST_OUTPUT( << "Testing whether first and last geometry in the SlicedGeometry3D have GetImageGeometry()==false now");
MITK_TEST_CONDITION_REQUIRED( subSliceGeo2D_first->GetImageGeometry()==false, "");
MITK_TEST_CONDITION_REQUIRED( subSliceGeo2D_last->GetImageGeometry()==false, "");
MITK_TEST_OUTPUT( << "Testing wether offset has been added to origins of geometry");
// Manually substracting Offset.
OriginSlicedGeo[0] -= (slicedGeo3D->GetSpacing()[0]) / 2;
OriginSlicedGeo[1] -= (slicedGeo3D->GetSpacing()[1]) / 2;
OriginSlicedGeo[2] -= (slicedGeo3D->GetSpacing()[2]) / 2;
OriginFirstGeo[0] -= (subSliceGeo2D_first->GetSpacing()[0]) / 2;
OriginFirstGeo[1] -= (subSliceGeo2D_first->GetSpacing()[1]) / 2;
OriginFirstGeo[2] -= (subSliceGeo2D_first->GetSpacing()[2]) / 2;
OriginLastGeo[0] -= (subSliceGeo2D_last->GetSpacing()[0]) / 2;
OriginLastGeo[1] -= (subSliceGeo2D_last->GetSpacing()[1]) / 2;
OriginLastGeo[2] -= (subSliceGeo2D_last->GetSpacing()[2]) / 2;
MITK_TEST_CONDITION_REQUIRED( subSliceGeo2D_first->GetCornerPoint(1)==CornerPoint1FirstGeo, "");
MITK_TEST_CONDITION_REQUIRED( subSliceGeo2D_last->GetCornerPoint(2)==CornerPoint2LastGeo, "");
MITK_TEST_CONDITION_REQUIRED( slicedGeo3D->GetCornerPoint(0)==CornerPoint0SlicedGeo, "");
MITK_TEST_CONDITION_REQUIRED( slicedGeo3D->GetOrigin()==OriginSlicedGeo, "");
MITK_TEST_CONDITION_REQUIRED( subSliceGeo2D_first->GetOrigin()==OriginFirstGeo, "");
MITK_TEST_CONDITION_REQUIRED( subSliceGeo2D_last->GetOrigin()==OriginLastGeo, "");
MITK_TEST_OUTPUT( << "ALL SUCCESSFULLY!");
}
int mitkSlicedGeometry3DTest(int /*argc*/, char* /*argv*/[])
{
mitk::PlaneGeometry::Pointer planegeometry1 = mitk::PlaneGeometry::New();
mitk::Point3D origin;
mitk::Vector3D right, bottom, normal;
mitk::ScalarType width, height;
mitk::ScalarType widthInMM, heightInMM, thicknessInMM;
width = 100; widthInMM = width;
height = 200; heightInMM = height;
thicknessInMM = 3.5;
mitk::FillVector3D(origin, 4.5, 7.3, 11.2);
mitk::FillVector3D(right, widthInMM, 0, 0);
mitk::FillVector3D(bottom, 0, heightInMM, 0);
mitk::FillVector3D(normal, 0, 0, thicknessInMM);
std::cout << "Initializing planegeometry1 by InitializeStandardPlane(rightVector, downVector, spacing = NULL): "<<std::endl;
planegeometry1->InitializeStandardPlane(right.GetVnlVector(), bottom.GetVnlVector());
std::cout << "Setting planegeometry2 to a cloned version of planegeometry1: "<<std::endl;
mitk::PlaneGeometry::Pointer planegeometry2;
planegeometry2 = dynamic_cast<mitk::PlaneGeometry*>(planegeometry1->Clone().GetPointer());;
std::cout << "Changing the IndexToWorldTransform of planegeometry2 to a rotated version by SetIndexToWorldTransform() (keep origin): "<<std::endl;
mitk::AffineTransform3D::Pointer transform = mitk::AffineTransform3D::New();
mitk::AffineTransform3D::MatrixType::InternalMatrixType vnlmatrix;
vnlmatrix = planegeometry2->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix();
mitk::VnlVector axis(3);
mitk::FillVector3D(axis, 1.0, 1.0, 1.0); axis.normalize();
vnl_quaternion<mitk::ScalarType> rotation(axis, 0.123);
vnlmatrix = rotation.rotation_matrix_transpose()*vnlmatrix;
mitk::Matrix3D matrix;
matrix = vnlmatrix;
transform->SetMatrix(matrix);
transform->SetOffset(planegeometry2->GetIndexToWorldTransform()->GetOffset());
right.SetVnlVector( rotation.rotation_matrix_transpose()*right.GetVnlVector() );
bottom.SetVnlVector(rotation.rotation_matrix_transpose()*bottom.GetVnlVector());
normal.SetVnlVector(rotation.rotation_matrix_transpose()*normal.GetVnlVector());
planegeometry2->SetIndexToWorldTransform(transform);
std::cout << "Setting planegeometry3 to the backside of planegeometry2: " <<std::endl;
mitk::PlaneGeometry::Pointer planegeometry3 = mitk::PlaneGeometry::New();
planegeometry3->InitializeStandardPlane(planegeometry2, mitk::PlaneGeometry::Axial, 0, false);
std::cout << "Testing SlicedGeometry3D::InitializeEvenlySpaced(planegeometry3, zSpacing = 1, slices = 5, flipped = false): " <<std::endl;
mitk::SlicedGeometry3D::Pointer slicedWorldGeometry=mitk::SlicedGeometry3D::New();
unsigned int numSlices = 5;
slicedWorldGeometry->InitializeEvenlySpaced(planegeometry3, 1, numSlices, false);
std::cout << "Testing availability and type (PlaneGeometry) of first geometry in the SlicedGeometry3D: ";
- mitk::PlaneGeometry* accessedplanegeometry3 = dynamic_cast<mitk::PlaneGeometry*>(slicedWorldGeometry->GetGeometry2D(0));
+ mitk::PlaneGeometry* accessedplanegeometry3 = dynamic_cast<mitk::PlaneGeometry*>(slicedWorldGeometry->GetPlaneGeometry(0));
if(accessedplanegeometry3==NULL)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing whether the first geometry in the SlicedGeometry3D is identical to planegeometry3 by axis comparison and origin: "<<std::endl;
if((mitk::Equal(accessedplanegeometry3->GetAxisVector(0), planegeometry3->GetAxisVector(0), slicedGeometryEps)==false) ||
(mitk::Equal(accessedplanegeometry3->GetAxisVector(1), planegeometry3->GetAxisVector(1), slicedGeometryEps)==false) ||
(mitk::Equal(accessedplanegeometry3->GetAxisVector(2), planegeometry3->GetAxisVector(2), slicedGeometryEps)==false) ||
(mitk::Equal(accessedplanegeometry3->GetOrigin(), planegeometry3->GetOrigin(), slicedGeometryEps)==false))
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing availability and type (PlaneGeometry) of the last geometry in the SlicedGeometry3D: ";
- mitk::PlaneGeometry* accessedplanegeometry3last = dynamic_cast<mitk::PlaneGeometry*>(slicedWorldGeometry->GetGeometry2D(numSlices-1));
+ mitk::PlaneGeometry* accessedplanegeometry3last = dynamic_cast<mitk::PlaneGeometry*>(slicedWorldGeometry->GetPlaneGeometry(numSlices-1));
mitk::Point3D origin3last; origin3last = planegeometry3->GetOrigin()+slicedWorldGeometry->GetDirectionVector()*(numSlices-1);
if(accessedplanegeometry3last==NULL)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing whether the last geometry in the SlicedGeometry3D is identical to planegeometry3 by axis comparison: "<<std::endl;
if((mitk::Equal(accessedplanegeometry3last->GetAxisVector(0), planegeometry3->GetAxisVector(0), slicedGeometryEps)==false) ||
(mitk::Equal(accessedplanegeometry3last->GetAxisVector(1), planegeometry3->GetAxisVector(1), slicedGeometryEps)==false) ||
(mitk::Equal(accessedplanegeometry3last->GetAxisVector(2), planegeometry3->GetAxisVector(2), slicedGeometryEps)==false) ||
(mitk::Equal(accessedplanegeometry3last->GetOrigin(), origin3last, slicedGeometryEps)==false) ||
(mitk::Equal(accessedplanegeometry3last->GetIndexToWorldTransform()->GetOffset(), origin3last.GetVectorFromOrigin(), slicedGeometryEps)==false))
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Again for first slice - Testing availability and type (PlaneGeometry) of first geometry in the SlicedGeometry3D: ";
- accessedplanegeometry3 = dynamic_cast<mitk::PlaneGeometry*>(slicedWorldGeometry->GetGeometry2D(0));
+ accessedplanegeometry3 = dynamic_cast<mitk::PlaneGeometry*>(slicedWorldGeometry->GetPlaneGeometry(0));
if(accessedplanegeometry3==NULL)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Again for first slice - Testing whether the first geometry in the SlicedGeometry3D is identical to planegeometry3 by axis comparison and origin: "<<std::endl;
if((mitk::Equal(accessedplanegeometry3->GetAxisVector(0), planegeometry3->GetAxisVector(0), slicedGeometryEps)==false) ||
(mitk::Equal(accessedplanegeometry3->GetAxisVector(1), planegeometry3->GetAxisVector(1), slicedGeometryEps)==false) ||
(mitk::Equal(accessedplanegeometry3->GetAxisVector(2), planegeometry3->GetAxisVector(2), slicedGeometryEps)==false) ||
(mitk::Equal(accessedplanegeometry3->GetOrigin(), planegeometry3->GetOrigin(), slicedGeometryEps)==false) ||
(mitk::Equal(accessedplanegeometry3->GetIndexToWorldTransform()->GetOffset(), planegeometry3->GetOrigin().GetVectorFromOrigin(), slicedGeometryEps)==false))
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
mitkSlicedGeometry3D_ChangeImageGeometryConsideringOriginOffset_Test();
std::cout<<"[TEST DONE]"<<std::endl;
return EXIT_SUCCESS;
}
diff --git a/Core/Code/Testing/mitkTextOverlay3DRendering2DTest.cpp b/Core/Code/Testing/mitkTextOverlay3DRendering2DTest.cpp
index d076f25f8c..a7908efb15 100644
--- a/Core/Code/Testing/mitkTextOverlay3DRendering2DTest.cpp
+++ b/Core/Code/Testing/mitkTextOverlay3DRendering2DTest.cpp
@@ -1,89 +1,89 @@
/*===================================================================
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.
===================================================================*/
//MITK
#include "mitkTestingMacros.h"
#include "mitkRenderingTestHelper.h"
#include <mitkOverlayManager.h>
//VTK
#include <vtkRegressionTestImage.h>
#include "mitkTextOverlay3D.h"
#include <mitkPointSet.h>
int mitkTextOverlay3DRendering2DTest(int argc, char* argv[])
{
// load all arguments into a datastorage, take last argument as reference rendering
// setup a renderwindow of fixed size X*Y
// render the datastorage
// compare rendering to reference image
MITK_TEST_BEGIN("mitkTextOverlay3DRendering2DTest")
mitk::RenderingTestHelper renderingHelper(640, 480, argc, argv);
mitk::BaseRenderer* renderer = mitk::BaseRenderer::GetInstance(renderingHelper.GetVtkRenderWindow());
mitk::OverlayManager::Pointer overlayManager = mitk::OverlayManager::New();
renderer->SetOverlayManager(overlayManager);
mitk::PointSet::Pointer pointset = mitk::PointSet::New();
// This vector is used to define an offset for the annotations, in order to show them with a margin to the actual coordinate.
mitk::Point3D offset;
offset[0] = .5;
offset[1] = .5;
offset[2] = .5;
//Just a loop to create some points
for(int i=0 ; i < 5 ; i++){
//To each point, a TextOverlay3D is created
mitk::TextOverlay3D::Pointer textOverlay3D = mitk::TextOverlay3D::New();
mitk::Point3D point;
point[0] = i*2;
point[1] = i*3;
point[2] = -i*5;
pointset->InsertPoint(i, point);
textOverlay3D->SetText("A Point");
// The Position is set to the point coordinate to create an annotation to the point in the PointSet.
textOverlay3D->SetPosition3D(point);
// move the annotation away from the actual point
textOverlay3D->SetOffsetVector(offset);
overlayManager->AddOverlay(textOverlay3D.GetPointer());
}
// also show the created pointset
mitk::DataNode::Pointer datanode = mitk::DataNode::New();
datanode->SetData(pointset);
datanode->SetName("pointSet");
renderingHelper.AddNodeToStorage(datanode);
renderingHelper.Render();
//use this to generate a reference screenshot or save the file:
- bool generateReferenceScreenshot = false;
+ bool generateReferenceScreenshot = true;
if(generateReferenceScreenshot)
{
- renderingHelper.SaveReferenceScreenShot("/home/christoph/Pictures/RenderingTestData/mitkTextOverlay3DRendering2DTest_ball.png");
+ renderingHelper.SaveReferenceScreenShot("d:/tmp/mitkTextOverlay3DRendering2DTest_ball.png");
}
//### Usage of CompareRenderWindowAgainstReference: See docu of mitkRrenderingTestHelper
MITK_TEST_CONDITION( renderingHelper.CompareRenderWindowAgainstReference(argc, argv) == true, "CompareRenderWindowAgainstReference test result positive?" );
MITK_TEST_END();
}
diff --git a/Core/Code/Testing/mitkTimeGeometryTest.cpp b/Core/Code/Testing/mitkTimeGeometryTest.cpp
index c2521ca66e..ec19b05a4d 100644
--- a/Core/Code/Testing/mitkTimeGeometryTest.cpp
+++ b/Core/Code/Testing/mitkTimeGeometryTest.cpp
@@ -1,775 +1,775 @@
/*===================================================================
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 "mitkTimeGeometry.h"
#include "mitkGeometry3D.h"
#include "mitkRotationOperation.h"
#include "mitkInteractionConst.h"
#include <mitkMatrixConvert.h>
#include <mitkImageCast.h>
#include "mitkTestingMacros.h"
#include <fstream>
#include <mitkVector.h>
#include <mitkStandaloneDataStorage.h>
#include "mitkImageGenerator.h"
#include "mitkPointSet.h"
#include <limits>
static const mitk::ScalarType test_eps = 1E-6; /* some reference values in the test seem
to have been calculated with float precision. Thus, set this to float precision epsilon.*/
static const mitk::ScalarType test_eps_square = 1E-3;
class mitkTimeGeometryTestClass
{
public:
void Translation_Image_MovedOrigin(unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT)
{
// DimX, DimY, DimZ,
mitk::Image::Pointer image = mitk::ImageGenerator::GenerateRandomImage<mitk::ScalarType>(DimX, DimY, DimZ, DimT,0.5,0.33,0.78,100);
- mitk::Geometry3D::Pointer geometry = image->GetTimeGeometry()->GetGeometryForTimeStep(0);
+ mitk::BaseGeometry::Pointer geometry = image->GetTimeGeometry()->GetGeometryForTimeStep(0);
mitk::Point3D imageOrigin = geometry->GetOrigin();
mitk::Point3D expectedOrigin;
expectedOrigin[0] = 0;
expectedOrigin[1] = 0;
expectedOrigin[2] = 0;
MITK_TEST_CONDITION(mitk::Equal(imageOrigin, expectedOrigin), "Original origin match expected origin");
expectedOrigin[0] = 0.325;
expectedOrigin[1] = 0.487;
expectedOrigin[2] = 0.78;
mitk::Vector3D translationVector;
translationVector[0] = expectedOrigin[0];
translationVector[1] = expectedOrigin[1];
translationVector[2] = expectedOrigin[2];
for (mitk::TimeStepType timeStep = 0; timeStep < image->GetTimeGeometry()->CountTimeSteps(); ++timeStep)
{
image->GetTimeGeometry()->GetGeometryForTimeStep(timeStep)->Translate(translationVector);
}
imageOrigin = image->GetGeometry(0)->GetOrigin();
MITK_TEST_CONDITION(mitk::Equal(imageOrigin, expectedOrigin), "Translated origin match expected origin");
expectedOrigin[0] = 2*translationVector[0];
expectedOrigin[1] = 2*translationVector[1];
expectedOrigin[2] = 2*translationVector[2];
for (mitk::TimeStepType timeStep = 0; timeStep < image->GetTimeGeometry()->CountTimeSteps(); ++timeStep)
{
image->GetTimeGeometry()->GetGeometryForTimeStep(timeStep)->Translate(translationVector);
}
imageOrigin = image->GetGeometry(0)->GetOrigin();
MITK_TEST_CONDITION(mitk::Equal(imageOrigin, expectedOrigin), "Translated origin match expected origin");
}
void Rotate_Image_RotatedPoint(mitk::BaseData* baseData, unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT)
{
mitk::StandaloneDataStorage::Pointer ds = mitk::StandaloneDataStorage::New();
mitk::DataNode::Pointer dataNode = mitk::DataNode::New();
// DimX, DimY, DimZ,
dataNode->SetData(baseData);
ds->Add(dataNode);
- mitk::Geometry3D::Pointer geometry = baseData->GetTimeGeometry()->GetGeometryForTimeStep(0);
+ mitk::BaseGeometry::Pointer geometry = baseData->GetTimeGeometry()->GetGeometryForTimeStep(0);
mitk::Point3D expectedPoint;
expectedPoint[0] = 3*0.5;
expectedPoint[1] = 3*0.33;
expectedPoint[2] = 3*0.78;
mitk::Point3D originalPoint;
originalPoint[0] = 3;
originalPoint[1] = 3;
originalPoint[2] = 3;
mitk::Point3D worldPoint;
geometry->IndexToWorld(originalPoint, worldPoint);
MITK_TEST_CONDITION(mitk::Equal(worldPoint, expectedPoint, test_eps), "Index-to-World without rotation as expected ");
mitk::Point3D pointOfRotation;
pointOfRotation[0] = 0;
pointOfRotation[1] = 0;
pointOfRotation[2] = 0;
mitk::Vector3D vectorOfRotation;
vectorOfRotation[0] = 1;
vectorOfRotation[1] = 0.5;
vectorOfRotation[2] = 0.2;
mitk::ScalarType angleOfRotation = 73.0;
mitk::RotationOperation* rotation = new mitk::RotationOperation(mitk::OpROTATE,pointOfRotation, vectorOfRotation, angleOfRotation);
baseData->GetTimeGeometry()->ExecuteOperation(rotation);
delete rotation;
expectedPoint[0] = 2.6080379;
expectedPoint[1] = -0.75265157;
expectedPoint[2] = 1.1564401;
baseData->GetGeometry(0)->IndexToWorld(originalPoint,worldPoint);
MITK_TEST_CONDITION(mitk::Equal(worldPoint, expectedPoint, test_eps), "Rotation returns expected values ");
}
void Scale_Image_ScaledPoint(unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT)
{
// DimX, DimY, DimZ,
mitk::Image::Pointer image = mitk::ImageGenerator::GenerateRandomImage<mitk::ScalarType>(DimX, DimY, DimZ, DimT,0.5,0.33,0.78,100);
- mitk::Geometry3D::Pointer geometry = image->GetTimeGeometry()->GetGeometryForTimeStep(0);
+ mitk::BaseGeometry::Pointer geometry = image->GetTimeGeometry()->GetGeometryForTimeStep(0);
mitk::Point3D expectedPoint;
expectedPoint[0] = 3*0.5;
expectedPoint[1] = 3*0.33;
expectedPoint[2] = 3*0.78;
mitk::Point3D originalPoint;
originalPoint[0] = 3;
originalPoint[1] = 3;
originalPoint[2] = 3;
mitk::Point3D worldPoint;
geometry->IndexToWorld(originalPoint, worldPoint);
MITK_TEST_CONDITION(mitk::Equal(worldPoint, expectedPoint, test_eps), "Index-to-World with old Scaling as expected ");
mitk::Vector3D newSpacing;
newSpacing[0] = 2;
newSpacing[1] = 1.254;
newSpacing[2] = 0.224;
image->SetSpacing(newSpacing);
expectedPoint[0] = 3*2;
expectedPoint[1] = 3*1.254;
expectedPoint[2] = 3*0.224;
image->GetGeometry(0)->IndexToWorld(originalPoint,worldPoint);
MITK_TEST_CONDITION(mitk::Equal(worldPoint, expectedPoint), "Index-toWorld with new Scaling returns expected values ");
}
void GetMinimumTimePoint_4DBaseData_Zero(mitk::BaseData* baseData, unsigned int DimT)
{
baseData->Update();
mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry();
mitk::TimePointType expectedTimePoint = geometry->GetMinimumTimePoint();
MITK_TEST_CONDITION(mitk::Equal(expectedTimePoint, 0), "Returns correct minimum time point ");
}
void GetMaximumTimePoint_4DBaseData_DimT(mitk::BaseData* baseData, unsigned int DimT)
{
baseData->Update();
mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry();
mitk::TimePointType expectedTimePoint = geometry->GetMaximumTimePoint();
MITK_TEST_CONDITION(mitk::Equal(expectedTimePoint, DimT), "Returns correct maximum time point ");
}
void CountTimeSteps_Image_ReturnDimT(mitk::BaseData* baseData, unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT)
{
mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry();
mitk::TimeStepType expectedTimeSteps = geometry->CountTimeSteps();
MITK_TEST_CONDITION(mitk::Equal(expectedTimeSteps, DimT), "Returns correct number of time Steps ");
}
void GetMinimumTimePoint_3DImage_Min(mitk::BaseData* baseData, unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT)
{
mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry();
mitk::TimePointType expectedTimePoint = geometry->GetMinimumTimePoint();
MITK_TEST_CONDITION(mitk::Equal(expectedTimePoint, -std::numeric_limits<mitk::TimePointType>().max()), "Returns correct minimum time point ");
}
void GetMaximumTimePoint_3DImage_Max(mitk::BaseData* baseData,unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT)
{
mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry();
mitk::TimePointType expectedTimePoint = geometry->GetMaximumTimePoint();
MITK_INFO << expectedTimePoint;
MITK_INFO << std::numeric_limits<mitk::TimePointType>().max();
MITK_TEST_CONDITION(mitk::Equal(expectedTimePoint, std::numeric_limits<mitk::TimePointType>().max()), "Returns correct maximum time point ");
}
void GetTimeBounds_4DImage_ZeroAndDimT(unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT)
{
mitk::Image::Pointer image = mitk::ImageGenerator::GenerateRandomImage<mitk::ScalarType>(DimX, DimY, DimZ, DimT,0.5,0.33,0.78,100);
mitk::TimeGeometry::Pointer geometry = image->GetTimeGeometry();
mitk::TimeBounds expectedTimeBounds = geometry->GetTimeBounds();
MITK_TEST_CONDITION(mitk::Equal(expectedTimeBounds[0], 0), "Returns correct minimum time point ");
MITK_TEST_CONDITION(mitk::Equal(expectedTimeBounds[1], DimT), "Returns correct maximum time point ");
}
void GetTimeBounds_3DImage_ZeroAndDimT(mitk::BaseData* baseData, unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT)
{
baseData->Update();
mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry();
mitk::TimeBounds expectedTimeBounds = geometry->GetTimeBounds();
MITK_TEST_CONDITION(mitk::Equal(expectedTimeBounds[0], -std::numeric_limits<mitk::TimePointType>().max()), "Returns correct minimum time point ");
MITK_TEST_CONDITION(mitk::Equal(expectedTimeBounds[1], std::numeric_limits<mitk::TimePointType>().max()), "Returns correct maximum time point ");
}
void IsValidTimePoint_ImageValidTimePoint_True(mitk::BaseData* baseData, unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT)
{
baseData->Update();
mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry();
bool isValid = geometry->IsValidTimePoint(DimT-1);
MITK_TEST_CONDITION(mitk::Equal(isValid, true), "Is valid time Point correct minimum time point ");
}
void IsValidTimePoint_ImageNegativInvalidTimePoint_False(unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT)
{
mitk::Image::Pointer image = mitk::ImageGenerator::GenerateRandomImage<mitk::ScalarType>(DimX, DimY, DimZ, DimT,0.5,0.33,0.78,100);
mitk::TimeGeometry::Pointer geometry = image->GetTimeGeometry();
bool isValid = geometry->IsValidTimePoint(-DimT);
MITK_TEST_CONDITION(mitk::Equal(isValid, false), "Is invalid time Point correct minimum time point ");
}
void IsValidTimePoint_ImageInvalidTimePoint_False(unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT)
{
mitk::Image::Pointer image = mitk::ImageGenerator::GenerateRandomImage<mitk::ScalarType>(DimX, DimY, DimZ, DimT,0.5,0.33,0.78,100);
mitk::TimeGeometry::Pointer geometry = image->GetTimeGeometry();
bool isValid = geometry->IsValidTimePoint(DimT+1);
MITK_TEST_CONDITION(mitk::Equal(isValid, false), "Is invalid time Point correct minimum time point ");
}
void IsValidTimeStep_ImageValidTimeStep_True(mitk::BaseData* baseData, unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT)
{
mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry();
bool isValid = geometry->IsValidTimeStep(DimT-1);
MITK_TEST_CONDITION(mitk::Equal(isValid, true), "Is valid time Point correct minimum time point ");
}
void IsValidTimeStep_ImageNegativInvalidTimeStep_False(mitk::BaseData* baseData, unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT)
{
mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry();
bool isValid = geometry->IsValidTimeStep(-DimT);
MITK_TEST_CONDITION(mitk::Equal(isValid, false), "Is invalid time Point correct minimum time point ");
}
void IsValidTimeStep_ImageInvalidTimeStep_False(mitk::BaseData* baseData, unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT)
{
mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry();
bool isValid = geometry->IsValidTimeStep(DimT);
MITK_TEST_CONDITION(mitk::Equal(isValid, false), "Is invalid time Point correct minimum time point ");
}
void TimeStepToTimePoint_ImageValidTimeStep_TimePoint(mitk::BaseData* baseData, unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT)
{
mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry();
mitk::TimePointType timePoint= geometry->TimeStepToTimePoint(DimT-1);
MITK_TEST_CONDITION(mitk::Equal(timePoint, DimT-1), "Calculated right time Point for Time Step ");
}
void TimeStepToTimePoint_ImageInvalidTimeStep_TimePoint(mitk::BaseData* baseData, unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT)
{
mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry();
mitk::TimePointType timePoint= geometry->TimeStepToTimePoint(DimT+1);
MITK_TEST_CONDITION(mitk::Equal(timePoint, DimT+1), "Calculated right time Point for invalid Time Step ");
}
void TimePointToTimeStep_ImageValidTimePoint_TimePoint(mitk::BaseData* baseData, unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT)
{
mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry();
mitk::TimeStepType timePoint= geometry->TimePointToTimeStep(DimT-0.5);
MITK_TEST_CONDITION(mitk::Equal(timePoint, DimT-1), "Calculated right time step for valid time point");
}
void TimePointToTimeStep_4DImageInvalidTimePoint_TimePoint(unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT)
{
mitk::Image::Pointer image = mitk::ImageGenerator::GenerateRandomImage<mitk::ScalarType>(DimX, DimY, DimZ, DimT,0.5,0.33,0.78,100);
mitk::TimeGeometry::Pointer geometry = image->GetTimeGeometry();
mitk::TimeStepType timePoint= geometry->TimePointToTimeStep(DimT+1.5);
MITK_TEST_CONDITION(mitk::Equal(timePoint, DimT+1), "Calculated right time step for invalid time point");
}
void TimePointToTimeStep_4DImageNegativInvalidTimePoint_TimePoint(unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT)
{
mitk::Image::Pointer image = mitk::ImageGenerator::GenerateRandomImage<mitk::ScalarType>(DimX, DimY, DimZ, DimT,0.5,0.33,0.78,100);
mitk::TimeGeometry::Pointer geometry = image->GetTimeGeometry();
mitk::TimePointType negativTimePoint = (-1.0*DimT) - 1.5;
mitk::TimeStepType timePoint= geometry->TimePointToTimeStep(negativTimePoint);
MITK_TEST_CONDITION(mitk::Equal(timePoint, 0), "Calculated right time step for negativ invalid time point");
}
void GetGeometryForTimeStep_BaseDataValidTimeStep_CorrectGeometry(mitk::BaseData* baseData,
mitk::ScalarType inputX, mitk::ScalarType inputY, mitk::ScalarType inputZ,
mitk::ScalarType outputX, mitk::ScalarType outputY, mitk::ScalarType outputZ, unsigned int DimT)
{
baseData->Update();
mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry();
- mitk::Geometry3D::Pointer geometry3D = geometry->GetGeometryForTimeStep(DimT-1);
+ mitk::BaseGeometry::Pointer geometry3D = geometry->GetGeometryForTimeStep(DimT-1);
MITK_TEST_CONDITION(geometry3D.IsNotNull(), "Non-zero geometry returned");
mitk::Point3D expectedPoint;
expectedPoint[0] = outputX;
expectedPoint[1] = outputY;
expectedPoint[2] = outputZ;
mitk::Point3D originalPoint;
originalPoint[0] = inputX;
originalPoint[1] = inputY;
originalPoint[2] = inputZ;
mitk::Point3D worldPoint;
geometry3D->IndexToWorld(originalPoint, worldPoint);
MITK_TEST_CONDITION(mitk::Equal(worldPoint, expectedPoint, test_eps), "Geometry transformation match expection. ");
}
void GetGeometryForTimeStep_ImageInvalidTimeStep_NullPointer(mitk::BaseData* baseData, unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT)
{
mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry();
- mitk::Geometry3D::Pointer geometry3D = geometry->GetGeometryForTimeStep(DimT+1);
+ mitk::BaseGeometry::Pointer geometry3D = geometry->GetGeometryForTimeStep(DimT+1);
MITK_TEST_CONDITION(geometry3D.IsNull(), "Null-Pointer geometry returned");
}
void GetGeometryForTimePoint_BaseDataValidTimePoint_CorrectGeometry(mitk::BaseData* baseData,
mitk::ScalarType inputX, mitk::ScalarType inputY, mitk::ScalarType inputZ,
mitk::ScalarType outputX, mitk::ScalarType outputY, mitk::ScalarType outputZ, unsigned int DimT)
{
baseData->Update();
mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry();
- mitk::Geometry3D::Pointer geometry3D = geometry->GetGeometryForTimePoint(DimT-0.5);
+ mitk::BaseGeometry::Pointer geometry3D = geometry->GetGeometryForTimePoint(DimT-0.5);
MITK_TEST_CONDITION(geometry3D.IsNotNull(), "Non-zero geometry returned");
mitk::Point3D expectedPoint;
expectedPoint[0] = outputX;
expectedPoint[1] = outputY;
expectedPoint[2] = outputZ;
mitk::Point3D originalPoint;
originalPoint[0] = inputX;
originalPoint[1] = inputY;
originalPoint[2] = inputZ;
mitk::Point3D worldPoint;
geometry3D->IndexToWorld(originalPoint, worldPoint);
MITK_TEST_CONDITION(mitk::Equal(worldPoint, expectedPoint, test_eps), "Geometry transformation match expection. ");
}
void GetGeometryForTimePoint_4DImageInvalidTimePoint_NullPointer(unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT)
{
mitk::Image::Pointer image = mitk::ImageGenerator::GenerateRandomImage<mitk::ScalarType>(DimX, DimY, DimZ, DimT,0.5,0.33,0.78,100);
mitk::TimeGeometry::Pointer geometry = image->GetTimeGeometry();
- mitk::Geometry3D::Pointer geometry3D = geometry->GetGeometryForTimePoint(DimT+1);
+ mitk::BaseGeometry::Pointer geometry3D = geometry->GetGeometryForTimePoint(DimT+1);
MITK_TEST_CONDITION(geometry3D.IsNull(), "Null-Pointer geometry returned with invalid time point");
}
void GetGeometryForTimePoint_4DImageNEgativInvalidTimePoint_NullPointer(unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT)
{
mitk::Image::Pointer image = mitk::ImageGenerator::GenerateRandomImage<mitk::ScalarType>(DimX, DimY, DimZ, DimT,0.5,0.33,0.78,100);
mitk::TimeGeometry::Pointer geometry = image->GetTimeGeometry();
mitk::TimePointType timePoint = (-1.0*(DimT)) -1;
- mitk::Geometry3D::Pointer geometry3D = geometry->GetGeometryForTimePoint(timePoint);
+ mitk::BaseGeometry::Pointer geometry3D = geometry->GetGeometryForTimePoint(timePoint);
MITK_TEST_CONDITION(geometry3D.IsNull(), "Null-Pointer geometry returned with invalid negativ time point");
}
void GetGeometryCloneForTimeStep_BaseDataValidTimeStep_CorrectGeometry(mitk::BaseData* baseData, unsigned int DimT)
{
mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry();
- mitk::Geometry3D::Pointer geometry3D = geometry->GetGeometryCloneForTimeStep(DimT-1);
+ mitk::BaseGeometry::Pointer geometry3D = geometry->GetGeometryCloneForTimeStep(DimT-1);
MITK_TEST_CONDITION(geometry3D.IsNotNull(), "Non-zero geometry returned");
mitk::Point3D expectedPoint;
mitk::Point3D originalPoint;
originalPoint[0] = 3;
originalPoint[1] = 3;
originalPoint[2] = 3;
mitk::Point3D worldPoint;
geometry3D->IndexToWorld(originalPoint, expectedPoint);
mitk::Vector3D translationVector;
translationVector[0] = 5;
translationVector[1] = 8;
translationVector[2] = 7;
geometry3D->Translate(translationVector);
geometry3D = geometry->GetGeometryForTimeStep(DimT-1);
geometry3D->IndexToWorld(originalPoint, worldPoint);
MITK_TEST_CONDITION(mitk::Equal(worldPoint, expectedPoint), "Geometry transformation not changed. ");
}
void GetGeometryCloneForTimeStep_ImageInvalidTimeStep_NullPointer(mitk::BaseData* baseData, unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT)
{
mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry();
- mitk::Geometry3D::Pointer geometry3D = geometry->GetGeometryCloneForTimeStep(DimT+1);
+ mitk::BaseGeometry::Pointer geometry3D = geometry->GetGeometryCloneForTimeStep(DimT+1);
MITK_TEST_CONDITION(geometry3D.IsNull(), "Null-Pointer geometry returned");
}
void SetTimeStepGeometry_BaseDataValidTimeStep_CorrectGeometry(mitk::BaseData* baseData, mitk::ScalarType scaleX, mitk::ScalarType scaleY, mitk::ScalarType scaleZ, unsigned int DimT)
{
baseData->Update();
mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry();
- mitk::Geometry3D::Pointer geometry3D = geometry->GetGeometryCloneForTimeStep(DimT-1);
+ mitk::BaseGeometry::Pointer geometry3D = geometry->GetGeometryCloneForTimeStep(DimT-1);
MITK_TEST_CONDITION(geometry3D.IsNotNull(), "Non-zero geometry returned");
mitk::Vector3D translationVector;
translationVector[0] = 5;
translationVector[1] = 8;
translationVector[2] = 7;
geometry3D->Translate(translationVector);
geometry->SetTimeStepGeometry(geometry3D,DimT-1);
mitk::Point3D expectedPoint;
expectedPoint[0] = 3*scaleX+5;
expectedPoint[1] = 3*scaleY+8;
expectedPoint[2] = 3*scaleZ+7;
mitk::Point3D originalPoint;
originalPoint[0] = 3;
originalPoint[1] = 3;
originalPoint[2] = 3;
mitk::Point3D worldPoint;
geometry->GetGeometryForTimeStep(DimT-1)->IndexToWorld(originalPoint, worldPoint);
MITK_TEST_CONDITION(mitk::Equal(worldPoint, expectedPoint, test_eps), "Geometry transformation match expection. ");
}
void Expand_BaseDataDoubleSize_SizeChanged(mitk::BaseData* baseData, unsigned int DimT)
{
mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry();
MITK_TEST_CONDITION(geometry->CountTimeSteps()==DimT, "Number of time Steps match expection. ");
geometry->Expand(DimT * 2);
MITK_TEST_CONDITION(geometry->CountTimeSteps()==DimT*2, "Number of time Steps match expection. ");
- mitk::Geometry3D::Pointer geometry3D = geometry->GetGeometryForTimeStep(DimT*2 -1);
+ mitk::BaseGeometry::Pointer geometry3D = geometry->GetGeometryForTimeStep(DimT*2 -1);
MITK_TEST_CONDITION(geometry3D.IsNotNull(), "Non-zero geometry is generated. ");
}
void CheckBounds_BaseData_PointsAsExpected(mitk::BaseData* baseData, mitk::ScalarType minX, mitk::ScalarType minY, mitk::ScalarType minZ, mitk::ScalarType maxX, mitk::ScalarType maxY, mitk::ScalarType maxZ)
{
baseData->Update();
mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry();
mitk::Point3D expectedPoint;
expectedPoint[0] = minX;
expectedPoint[1] = minY;
expectedPoint[2] = minZ;
mitk::Point3D point = geometry->GetCornerPointInWorld(0);
MITK_TEST_CONDITION(mitk::Equal(expectedPoint, point, test_eps), "Bounding Point 0 as expected ");
point = geometry->GetCornerPointInWorld(true,true,true);
MITK_TEST_CONDITION(mitk::Equal(expectedPoint, point, test_eps), "Bounding Point 0 as expected ");
point = geometry->GetCornerPointInWorld(1);
expectedPoint[0] = minX;
expectedPoint[1] = minY;
expectedPoint[2] = maxZ;
MITK_TEST_CONDITION(mitk::Equal(expectedPoint, point, test_eps), "GBounding Point 1 as expected ");
point = geometry->GetCornerPointInWorld(true,true,false);
MITK_TEST_CONDITION(mitk::Equal(expectedPoint, point, test_eps), "Bounding Point 1 as expected ");
point = geometry->GetCornerPointInWorld(2);
expectedPoint[0] = minX;
expectedPoint[1] = maxY;
expectedPoint[2] = minZ;
MITK_TEST_CONDITION(mitk::Equal(expectedPoint, point, test_eps), "Bounding Point 2 as expected ");
point = geometry->GetCornerPointInWorld(true,false,true);
MITK_TEST_CONDITION(mitk::Equal(expectedPoint, point, test_eps), "Bounding Point 2 as expected ");
point = geometry->GetCornerPointInWorld(3);
expectedPoint[0] = minX;
expectedPoint[1] = maxY;
expectedPoint[2] = maxZ;
MITK_TEST_CONDITION(mitk::Equal(expectedPoint, point, test_eps), "Bounding Point 3 as expected ");
point = geometry->GetCornerPointInWorld(true,false,false);
MITK_TEST_CONDITION(mitk::Equal(expectedPoint, point, test_eps), "Bounding Point 3 as expected ");
point = geometry->GetCornerPointInWorld(4);
expectedPoint[0] = maxX;
expectedPoint[1] = minY;
expectedPoint[2] = minZ;
MITK_TEST_CONDITION(mitk::Equal(expectedPoint, point, test_eps), "Bounding Point 4 as expected ");
point = geometry->GetCornerPointInWorld(false,true,true);
MITK_TEST_CONDITION(mitk::Equal(expectedPoint, point, test_eps), "Bounding Point 4 as expected ");
point = geometry->GetCornerPointInWorld(5);
expectedPoint[0] = maxX;
expectedPoint[1] = minY;
expectedPoint[2] = maxZ;
MITK_TEST_CONDITION(mitk::Equal(expectedPoint, point, test_eps), "Bounding Point 5 as expected ");
point = geometry->GetCornerPointInWorld(false,true,false);
MITK_TEST_CONDITION(mitk::Equal(expectedPoint, point, test_eps), "Bounding Point 5 as expected ");
point = geometry->GetCornerPointInWorld(6);
expectedPoint[0] = maxX;
expectedPoint[1] = maxY;
expectedPoint[2] = minZ;
MITK_TEST_CONDITION(mitk::Equal(expectedPoint, point, test_eps), "Bounding Point 6 as expected ");
point = geometry->GetCornerPointInWorld(false,false,true);
MITK_TEST_CONDITION(mitk::Equal(expectedPoint, point, test_eps), "Bounding Point 6 as expected ");
point = geometry->GetCornerPointInWorld(7);
expectedPoint[0] = maxX;
expectedPoint[1] = maxY;
expectedPoint[2] = maxZ;
MITK_TEST_CONDITION(mitk::Equal(expectedPoint, point, test_eps), "Bounding Point 7 as expected ");
point = geometry->GetCornerPointInWorld(false,false,false);
MITK_TEST_CONDITION(mitk::Equal(expectedPoint, point, test_eps), "Bounding Point 7 as expected ");
}
void CheckLength_BaseData_AsExpected(mitk::BaseData* baseData, double length, double squareLength)
{
baseData->Update();
mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry();
double dimension = geometry->GetDiagonalLengthInWorld();
MITK_TEST_CONDITION(mitk::Equal(dimension,length, test_eps ), "Length as expected ");
dimension = geometry->GetDiagonalLength2InWorld();
MITK_TEST_CONDITION(mitk::Equal(dimension, squareLength, test_eps_square ), "Square length as expected ");
}
void CheckPointInside_BaseDataPointInside_True(mitk::BaseData* baseData, mitk::ScalarType pointX, mitk::ScalarType pointY, mitk::ScalarType pointZ)
{
baseData->Update();
mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry();
mitk::Point3D expectedPoint;
expectedPoint[0] = pointX;
expectedPoint[1] = pointY;
expectedPoint[2] = pointZ;
bool isInside = geometry->IsWorldPointInside(expectedPoint);
MITK_TEST_CONDITION(isInside, "Point is inside Image...");
}
void CheckPointInside_BaseDataPointOutside_False(mitk::BaseData* baseData, mitk::ScalarType pointX, mitk::ScalarType pointY, mitk::ScalarType pointZ)
{
baseData->Update();
mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry();
mitk::Point3D expectedPoint;
expectedPoint[0] = pointX;
expectedPoint[1] = pointY;
expectedPoint[2] = pointZ;
bool isInside = geometry->IsWorldPointInside(expectedPoint);
MITK_TEST_CONDITION(!isInside, "Point is outside Image...");
}
void CheckBounds_Image_AsSet(unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT)
{
mitk::Image::Pointer image = mitk::ImageGenerator::GenerateRandomImage<mitk::ScalarType>(DimX, DimY, DimZ, DimT,0.5,0.33,0.78,100);
mitk::TimeGeometry::Pointer geometry = image->GetTimeGeometry();
mitk::BoundingBox::BoundsArrayType bound = geometry->GetBoundsInWorld();
bool isEqual = true;
isEqual = isEqual && mitk::Equal(bound[0], -0.5*0.5, test_eps);
isEqual = isEqual && mitk::Equal(bound[1], 29.5*0.5, test_eps);
isEqual = isEqual && mitk::Equal(bound[2], -0.5*0.33, test_eps);
isEqual = isEqual && mitk::Equal(bound[3], 24.5*0.33, test_eps);
isEqual = isEqual && mitk::Equal(bound[4], -0.5*0.78, test_eps);
isEqual = isEqual && mitk::Equal(bound[5], 19.5*0.78, test_eps);
MITK_TEST_CONDITION(isEqual, "Bounds as precalculated...");
}
void CheckBounds_BaseData_AsSet(mitk::BaseData* baseData, mitk::ScalarType minBoundX, mitk::ScalarType maxBoundX, mitk::ScalarType minBoundY, mitk::ScalarType maxBoundY, mitk::ScalarType minBoundZ, mitk::ScalarType maxBoundZ)
{
baseData->Update();
mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry();
mitk::BoundingBox::BoundsArrayType bound = geometry->GetBoundsInWorld();
bool isEqual = true;
isEqual = isEqual && mitk::Equal(bound[0], minBoundX);
isEqual = isEqual && mitk::Equal(bound[1], maxBoundX);
isEqual = isEqual && mitk::Equal(bound[2], minBoundY);
isEqual = isEqual && mitk::Equal(bound[3], maxBoundY);
isEqual = isEqual && mitk::Equal(bound[4], minBoundZ);
isEqual = isEqual && mitk::Equal(bound[5], maxBoundZ);
MITK_TEST_CONDITION(isEqual, "Bounds as precalculated...");
}
void CheckExtent_BaseData_AsSet(mitk::BaseData* baseData, double extentX, double extentY, double extentZ)
{
baseData->Update();
mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry();
bool isEqual = true;
isEqual = isEqual && mitk::Equal(geometry->GetExtentInWorld(0), extentX, test_eps);//30*0.5);
isEqual = isEqual && mitk::Equal(geometry->GetExtentInWorld(1), extentY, test_eps);//25*0.33);
isEqual = isEqual && mitk::Equal(geometry->GetExtentInWorld(2), extentZ, test_eps);//20*0.78);
MITK_TEST_CONDITION(isEqual, "Extent as precalculated...");
}
mitk::PointSet::Pointer makePointset()
{
mitk::PointSet::Pointer pointSet = mitk::PointSet::New();
mitk::Point3D pointA, pointB, pointC;
pointA.Fill(1);
pointB.Fill(2);
pointC.Fill(3);
pointSet->SetPoint(1,pointA);
pointSet->SetPoint(2,pointB);
pointSet->SetPoint(3,pointC);
pointSet->Update();
MITK_INFO<< pointSet->GetPoint(0);
MITK_INFO<< pointSet->GetPoint(1);
MITK_INFO<< pointSet->GetPoint(2);
MITK_INFO<< pointSet->GetPoint(3);
mitk::PointSet::Pointer pointSet2 = pointSet->Clone();
MITK_INFO<< pointSet2->GetPoint(0);
MITK_INFO<< pointSet2->GetPoint(1);
MITK_INFO<< pointSet2->GetPoint(2);
MITK_INFO<< pointSet2->GetPoint(3);
return pointSet;
}
};
int mitkTimeGeometryTest(int /*argc*/, char* /*argv*/[])
{
MITK_TEST_BEGIN(mitkTimeGeometryTest);
mitkTimeGeometryTestClass testClass;
MITK_TEST_OUTPUT(<< "Test for 3D image");
mitk::Image::Pointer image = mitk::ImageGenerator::GenerateRandomImage<mitk::ScalarType>(30, 25, 20, 1,0.5,0.33,0.78,100);
testClass.Translation_Image_MovedOrigin(30,25,20,1);
testClass.Rotate_Image_RotatedPoint(image->Clone(),30,25,20,1);
testClass.Scale_Image_ScaledPoint(30,25,20,1);
testClass.CountTimeSteps_Image_ReturnDimT(image->Clone(),30,25,20,1);
testClass.GetMinimumTimePoint_3DImage_Min(image->Clone(),30,25,20,1);
testClass.GetMaximumTimePoint_3DImage_Max(image->Clone(),30,25,20,1);
testClass.GetTimeBounds_3DImage_ZeroAndDimT(image->Clone(),30,25,20,1);
testClass.IsValidTimePoint_ImageValidTimePoint_True(image->Clone(),30,25,20,1);
testClass.IsValidTimeStep_ImageValidTimeStep_True(image->Clone(), 30,25,20,1);
testClass.IsValidTimeStep_ImageNegativInvalidTimeStep_False(image->Clone(), 30,25,20,1);
testClass.IsValidTimeStep_ImageInvalidTimeStep_False(image->Clone(), 30,25,20,1);
testClass.TimeStepToTimePoint_ImageValidTimeStep_TimePoint(image->Clone(), 30,25,20,1);
testClass.TimeStepToTimePoint_ImageInvalidTimeStep_TimePoint(image->Clone(), 30,25,20,1);
testClass.TimePointToTimeStep_ImageValidTimePoint_TimePoint(image->Clone(), 30,25,20,1);
testClass.GetGeometryForTimeStep_BaseDataValidTimeStep_CorrectGeometry(image->Clone(), 3,3,3,3*0.5,3*0.33,3*0.78,1);
testClass.GetGeometryForTimeStep_ImageInvalidTimeStep_NullPointer(image->Clone(), 30,25,20,1);
testClass.GetGeometryForTimePoint_BaseDataValidTimePoint_CorrectGeometry(image->Clone(), 3,3,3,3*0.5,3*0.33,3*0.78,1);
testClass.GetGeometryCloneForTimeStep_BaseDataValidTimeStep_CorrectGeometry(image->Clone(),1);
testClass.GetGeometryCloneForTimeStep_ImageInvalidTimeStep_NullPointer(image->Clone(), 30,25,20,1);
testClass.SetTimeStepGeometry_BaseDataValidTimeStep_CorrectGeometry(image->Clone(),0.5,0.33,0.78,1);
testClass.Expand_BaseDataDoubleSize_SizeChanged(image->Clone(),1);
testClass.CheckBounds_BaseData_PointsAsExpected(image->Clone(),-0.5*0.5,-0.5*0.33,-0.5*0.78,29.5*0.5,24.5*0.33,19.5*0.78);
testClass.CheckLength_BaseData_AsExpected(image->Clone(), 23.160796233014466, 536.42248214721712);
testClass.CheckPointInside_BaseDataPointInside_True(image->Clone(),10,5,5);
testClass.CheckPointInside_BaseDataPointOutside_False(image->Clone(),100,500,100);
testClass.CheckBounds_Image_AsSet(30,25,20,1);
testClass.CheckExtent_BaseData_AsSet(image->Clone(), 30*0.5,25*0.33,20*0.78);
MITK_TEST_OUTPUT(<< "Test for 2D image");
image = mitk::ImageGenerator::GenerateRandomImage<mitk::ScalarType>(30, 25, 1, 1,0.5,0.33,0.78,100);
testClass.Translation_Image_MovedOrigin(30,25,1,1);
testClass.Rotate_Image_RotatedPoint(image->Clone(),30,25,1,1);
testClass.Scale_Image_ScaledPoint(30,25,1,1);
testClass.CountTimeSteps_Image_ReturnDimT(image->Clone(),30,25,1,1);
testClass.GetMinimumTimePoint_3DImage_Min(image->Clone(),30,25,1,1);
testClass.GetMaximumTimePoint_3DImage_Max(image->Clone(),30,25,1,1);
testClass.GetTimeBounds_3DImage_ZeroAndDimT(image->Clone(),30,25,1,1);
testClass.IsValidTimePoint_ImageValidTimePoint_True(image->Clone(),30,25,1,1);
testClass.IsValidTimeStep_ImageValidTimeStep_True(image->Clone(), 30,25,1,1);
testClass.IsValidTimeStep_ImageNegativInvalidTimeStep_False(image->Clone(), 30,25,1,1);
testClass.IsValidTimeStep_ImageInvalidTimeStep_False(image->Clone(), 30,25,1,1);
testClass.TimeStepToTimePoint_ImageValidTimeStep_TimePoint(image->Clone(), 30,25,1,1);
testClass.TimeStepToTimePoint_ImageInvalidTimeStep_TimePoint(image->Clone(), 30,25,1,1);
testClass.TimePointToTimeStep_ImageValidTimePoint_TimePoint(image->Clone(), 30,25,1,1);
testClass.GetGeometryForTimeStep_BaseDataValidTimeStep_CorrectGeometry(image->Clone(), 3,3,3,3*0.5,3*0.33,3*0.78,1);
testClass.GetGeometryForTimeStep_ImageInvalidTimeStep_NullPointer(image->Clone(), 30,25,1,1);
testClass.GetGeometryForTimePoint_BaseDataValidTimePoint_CorrectGeometry(image->Clone(), 3,3,3,3*0.5,3*0.33,3*0.78,1);
testClass.GetGeometryCloneForTimeStep_BaseDataValidTimeStep_CorrectGeometry(image->Clone(),1);
testClass.GetGeometryCloneForTimeStep_ImageInvalidTimeStep_NullPointer(image->Clone(), 30,25,1,1);
testClass.SetTimeStepGeometry_BaseDataValidTimeStep_CorrectGeometry(image->Clone(),0.5,0.33,0.78,1);
testClass.Expand_BaseDataDoubleSize_SizeChanged(image->Clone(),1);
testClass.CheckBounds_BaseData_PointsAsExpected(image->Clone(),-0.5*0.5,-0.5*0.33,-0.5*0.78,29.5*0.5,24.5*0.33,0.5*0.78);
testClass.CheckLength_BaseData_AsExpected(image->Clone(), 17.1368287615, 293.6709);
testClass.CheckPointInside_BaseDataPointInside_True(image->Clone(),10,5,0);
testClass.CheckPointInside_BaseDataPointOutside_False(image->Clone(),100,500,0.5);
testClass.CheckExtent_BaseData_AsSet(image->Clone(), 30*0.5,25*0.33,1*0.78);
MITK_TEST_OUTPUT(<< "Test for 3D+time image");
image = mitk::ImageGenerator::GenerateRandomImage<mitk::ScalarType>(30, 25, 20, 5,0.5,0.33,0.78,100);
testClass.Translation_Image_MovedOrigin(30,25,20,5); // Test with 3D+t-Image
testClass.Rotate_Image_RotatedPoint(image->Clone(),30,25,20,5); // Test with 3D+t-Image
testClass.Scale_Image_ScaledPoint(30,25,20,5); // Test with 3D+t-Image
testClass.CountTimeSteps_Image_ReturnDimT(image->Clone(),30,25,20,5);
testClass.GetMinimumTimePoint_4DBaseData_Zero(image->Clone(),5);
testClass.GetMaximumTimePoint_4DBaseData_DimT(image->Clone(),5);
testClass.GetTimeBounds_4DImage_ZeroAndDimT(30,25,20,5);
testClass.IsValidTimePoint_ImageValidTimePoint_True(image->Clone(),30,25,20,5);
testClass.IsValidTimePoint_ImageNegativInvalidTimePoint_False(30,25,20,5);
testClass.IsValidTimePoint_ImageInvalidTimePoint_False(30,25,20,5);
testClass.IsValidTimeStep_ImageValidTimeStep_True(image->Clone(), 30,25,20,5);
testClass.IsValidTimeStep_ImageNegativInvalidTimeStep_False(image->Clone(), 30,25,20,5);
testClass.IsValidTimeStep_ImageInvalidTimeStep_False(image->Clone(), 30,25,20,5);
testClass.TimeStepToTimePoint_ImageValidTimeStep_TimePoint(image->Clone(), 30,25,20,5);
testClass.TimeStepToTimePoint_ImageInvalidTimeStep_TimePoint(image->Clone(), 30,25,20,5);
testClass.TimePointToTimeStep_ImageValidTimePoint_TimePoint(image->Clone(), 30,25,20,5);
testClass.TimePointToTimeStep_4DImageInvalidTimePoint_TimePoint(30,25,20,5);
testClass.TimePointToTimeStep_4DImageNegativInvalidTimePoint_TimePoint(30,25,20,5);
testClass.GetGeometryForTimeStep_BaseDataValidTimeStep_CorrectGeometry(image->Clone(), 3,3,3,3*0.5,3*0.33,3*0.78,5);
testClass.GetGeometryForTimeStep_ImageInvalidTimeStep_NullPointer(image->Clone(), 30,25,20,5);
testClass.GetGeometryForTimePoint_BaseDataValidTimePoint_CorrectGeometry(image->Clone(), 3,3,3,3*0.5,3*0.33,3*0.78,5);
testClass.GetGeometryForTimePoint_4DImageInvalidTimePoint_NullPointer(30,25,20,5);
testClass.GetGeometryForTimePoint_4DImageNEgativInvalidTimePoint_NullPointer(30,25,20,5);
testClass.GetGeometryCloneForTimeStep_BaseDataValidTimeStep_CorrectGeometry(image->Clone(),5);
testClass.GetGeometryCloneForTimeStep_ImageInvalidTimeStep_NullPointer(image->Clone(), 30,25,20,5);
testClass.SetTimeStepGeometry_BaseDataValidTimeStep_CorrectGeometry(image->Clone(),0.5,0.33,0.78,5);
testClass.Expand_BaseDataDoubleSize_SizeChanged(image->Clone(),5);
testClass.CheckBounds_BaseData_PointsAsExpected(image->Clone(),-0.5*0.5,-0.5*0.33,-0.5*0.78,29.5*0.5,24.5*0.33,19.5*0.78);
testClass.CheckLength_BaseData_AsExpected(image->Clone(), 23.160796233014466, 536.42248214721712);
testClass.CheckPointInside_BaseDataPointInside_True(image->Clone(),10,5,5);
testClass.CheckPointInside_BaseDataPointOutside_False(image->Clone(), 100,100,500);
testClass.CheckBounds_Image_AsSet(30,25,20,5);
testClass.CheckExtent_BaseData_AsSet(image->Clone(), 30*0.5,25*0.33,20*0.78);
/*
MITK_TEST_OUTPUT(<< "Test for 2D+time image");
testClass.Translation_Image_MovedOrigin(30,25,1 ,5); // Test with 2D+t-Image
testClass.Rotate_Image_RotatedPoint(30,25,1 ,5); // Test with 2D+t-Image
testClass.Scale_Image_ScaledPoint(30,25,1 ,5); // Test with 2D+t-Image
*/
mitk::PointSet::Pointer pointSet = mitk::PointSet::New();
mitk::Point3D pointA, pointB, pointC;
pointA.Fill(1);
pointB.Fill(2);
pointC.Fill(3);
pointSet->SetPoint(0,pointA);
pointSet->SetPoint(1,pointB);
pointSet->SetPoint(2,pointC);
testClass.CountTimeSteps_Image_ReturnDimT(pointSet->Clone(),30,25,20,1);
//testClass.GetMinimumTimePoint_3DImage_Min(pointSet->Clone(),30,25,20,1);
//testClass.GetMaximumTimePoint_3DImage_Max(pointSet->Clone(),30,25,20,1);
//testClass.GetTimeBounds_3DImage_ZeroAndDimT(pointSet->Clone(),30,25,20,1);
testClass.IsValidTimePoint_ImageValidTimePoint_True(pointSet->Clone(),30,25,20,1);
testClass.IsValidTimeStep_ImageValidTimeStep_True(pointSet->Clone(),30,25,20,1);
testClass.IsValidTimeStep_ImageNegativInvalidTimeStep_False(pointSet->Clone(),30,25,20,1);
testClass.IsValidTimeStep_ImageInvalidTimeStep_False(pointSet->Clone(),30,25,20,1);
testClass.TimeStepToTimePoint_ImageValidTimeStep_TimePoint(pointSet->Clone(),30,25,20,1);
testClass.TimeStepToTimePoint_ImageInvalidTimeStep_TimePoint(pointSet->Clone(),30,25,20,1);
testClass.TimePointToTimeStep_ImageValidTimePoint_TimePoint(pointSet->Clone(),30,25,20,1);
testClass.GetGeometryForTimeStep_BaseDataValidTimeStep_CorrectGeometry(pointSet->Clone(), 3,3,3,3,3,3,1);
testClass.GetGeometryForTimeStep_ImageInvalidTimeStep_NullPointer(pointSet->Clone(), 30,25,20,1);
testClass.GetGeometryForTimePoint_BaseDataValidTimePoint_CorrectGeometry(pointSet->Clone(), 3,3,3,3,3,3,1);
testClass.GetGeometryCloneForTimeStep_BaseDataValidTimeStep_CorrectGeometry(pointSet->Clone(),1);
testClass.GetGeometryCloneForTimeStep_ImageInvalidTimeStep_NullPointer(pointSet->Clone(), 30,25,20,1);
testClass.SetTimeStepGeometry_BaseDataValidTimeStep_CorrectGeometry(pointSet->Clone(), 1,1,1,1);
testClass.Expand_BaseDataDoubleSize_SizeChanged(pointSet->Clone(),1);
testClass.CheckBounds_BaseData_PointsAsExpected(pointSet->Clone(),1,1,1,3,3,3);
testClass.CheckLength_BaseData_AsExpected(pointSet->Clone(),3.46410161,12);
testClass.CheckPointInside_BaseDataPointInside_True(pointSet->Clone(),2,2,3);
testClass.CheckPointInside_BaseDataPointOutside_False(pointSet->Clone(),4,5,1);
testClass.CheckBounds_BaseData_AsSet(pointSet->Clone(),1,3,1,3,1,3);
testClass.CheckExtent_BaseData_AsSet(pointSet->Clone(),2,2,2 );
MITK_TEST_END();
return EXIT_SUCCESS;
}
diff --git a/Core/Code/files.cmake b/Core/Code/files.cmake
index 48d311471f..772bd25bde 100644
--- a/Core/Code/files.cmake
+++ b/Core/Code/files.cmake
@@ -1,405 +1,406 @@
set(H_FILES
Algorithms/itkImportMitkImageContainer.h
Algorithms/itkImportMitkImageContainer.txx
Algorithms/itkMITKScalarImageToHistogramGenerator.h
Algorithms/itkMITKScalarImageToHistogramGenerator.txx
Algorithms/mitkInstantiateAccessFunctions.h
Algorithms/mitkPixelTypeList.h
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
Algorithms/mitkExtractSliceFilter.h
Algorithms/mitkConvert2Dto3DImageFilter.h
Algorithms/mitkPlaneClipping.h
Common/mitkCommon.h
Common/mitkExceptionMacro.h
DataManagement/mitkProportionalTimeGeometry.h
DataManagement/mitkTimeGeometry.h
DataManagement/mitkImageAccessByItk.h
DataManagement/mitkImageCast.h
DataManagement/mitkImagePixelAccessor.h
DataManagement/mitkImagePixelReadAccessor.h
DataManagement/mitkImagePixelWriteAccessor.h
DataManagement/mitkImageReadAccessor.h
DataManagement/mitkImageWriteAccessor.h
DataManagement/mitkITKImageImport.h
DataManagement/mitkITKImageImport.txx
DataManagement/mitkImageToItk.h
DataManagement/mitkShaderProperty.h
DataManagement/mitkImageToItk.txx
- DataManagement/mitkTimeSlicedGeometry.h # Deprecated, empty for compatibilty reasons.
+ DataManagement/mitkTimeSlicedGeometry.h # Deprecated, empty for compatibility reasons.
DataManagement/mitkPropertyListReplacedObserver.cpp
Interactions/mitkEventMapperAddOn.h
Interfaces/mitkIDataNodeReader.h
Rendering/mitkLocalStorageHandler.h
Rendering/Colortables/HotIron.h
Rendering/Colortables/Jet.h
Rendering/Colortables/PET20.h
Rendering/Colortables/PETColor.h
IO/mitkPixelTypeTraits.h
+
)
set(CPP_FILES
Algorithms/mitkBaseDataSource.cpp
Algorithms/mitkCompareImageDataFilter.cpp
Algorithms/mitkMultiComponentImageDataComparisonFilter.cpp
Algorithms/mitkDataNodeSource.cpp
- Algorithms/mitkGeometry2DDataToSurfaceFilter.cpp
+ Algorithms/mitkPlaneGeometryDataToSurfaceFilter.cpp
Algorithms/mitkHistogramGenerator.cpp
Algorithms/mitkImageChannelSelector.cpp
Algorithms/mitkImageSliceSelector.cpp
Algorithms/mitkImageSource.cpp
Algorithms/mitkImageTimeSelector.cpp
Algorithms/mitkImageToImageFilter.cpp
Algorithms/mitkImageToSurfaceFilter.cpp
Algorithms/mitkPointSetSource.cpp
Algorithms/mitkPointSetToPointSetFilter.cpp
Algorithms/mitkRGBToRGBACastImageFilter.cpp
Algorithms/mitkSubImageSelector.cpp
Algorithms/mitkSurfaceSource.cpp
Algorithms/mitkSurfaceToImageFilter.cpp
Algorithms/mitkSurfaceToSurfaceFilter.cpp
Algorithms/mitkUIDGenerator.cpp
Algorithms/mitkVolumeCalculator.cpp
Algorithms/mitkClippedSurfaceBoundsCalculator.cpp
Algorithms/mitkExtractSliceFilter.cpp
Algorithms/mitkConvert2Dto3DImageFilter.cpp
Controllers/mitkBaseController.cpp
Controllers/mitkCallbackFromGUIThread.cpp
Controllers/mitkCameraController.cpp
Controllers/mitkCameraRotationController.cpp
Controllers/mitkCoreActivator.cpp
Controllers/mitkFocusManager.cpp
Controllers/mitkLimitedLinearUndo.cpp
Controllers/mitkOperationEvent.cpp
Controllers/mitkPlanePositionManager.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/mitkProportionalTimeGeometry.cpp
DataManagement/mitkTimeGeometry.cpp
DataManagement/mitkAbstractTransformGeometry.cpp
DataManagement/mitkAnnotationProperty.cpp
DataManagement/mitkApplicationCursor.cpp
DataManagement/mitkBaseData.cpp
+ DataManagement/mitkBaseGeometry.cpp
DataManagement/mitkBaseProperty.cpp
DataManagement/mitkClippingProperty.cpp
DataManagement/mitkChannelDescriptor.cpp
DataManagement/mitkColorProperty.cpp
DataManagement/mitkDataStorage.cpp
# DataManagement/mitkDataTree.cpp
DataManagement/mitkDataNode.cpp
DataManagement/mitkDataNodeFactory.cpp
# DataManagement/mitkDataTreeStorage.cpp
DataManagement/mitkDisplayGeometry.cpp
DataManagement/mitkEnumerationProperty.cpp
- DataManagement/mitkGeometry2D.cpp
- DataManagement/mitkGeometry2DData.cpp
+ DataManagement/mitkPlaneGeometryData.cpp
DataManagement/mitkGeometry3D.cpp
DataManagement/mitkGeometryData.cpp
DataManagement/mitkGroupTagProperty.cpp
DataManagement/mitkImage.cpp
DataManagement/mitkImageAccessorBase.cpp
DataManagement/mitkImageCaster.cpp
DataManagement/mitkImageCastPart1.cpp
DataManagement/mitkImageCastPart2.cpp
DataManagement/mitkImageCastPart3.cpp
DataManagement/mitkImageCastPart4.cpp
DataManagement/mitkImageDataItem.cpp
DataManagement/mitkImageDescriptor.cpp
DataManagement/mitkImageVtkAccessor.cpp
DataManagement/mitkImageStatisticsHolder.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/mitkModifiedLock.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/mitkPropertyObserver.cpp
DataManagement/mitkRestorePlanePositionOperation.cpp
DataManagement/mitkApplyTransformMatrixOperation.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/mitkTransferFunction.cpp
DataManagement/mitkTransferFunctionProperty.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/mitkRenderingModeProperty.cpp
DataManagement/mitkResliceMethodProperty.cpp
DataManagement/mitkMaterial.cpp
DataManagement/mitkPointSetShapeProperty.cpp
DataManagement/mitkFloatPropertyExtension.cpp
DataManagement/mitkIntPropertyExtension.cpp
DataManagement/mitkPropertyExtension.cpp
DataManagement/mitkPropertyFilter.cpp
DataManagement/mitkPropertyAliases.cpp
DataManagement/mitkPropertyDescriptions.cpp
DataManagement/mitkPropertyExtensions.cpp
DataManagement/mitkPropertyFilters.cpp
DataManagement/mitkShaderProperty.cpp
Interactions/mitkAction.cpp
Interactions/mitkAffineInteractor.cpp
Interactions/mitkBindDispatcherInteractor.cpp
Interactions/mitkCoordinateSupplier.cpp
Interactions/mitkDataInteractor.cpp
Interactions/mitkDispatcher.cpp
Interactions/mitkDisplayCoordinateOperation.cpp
Interactions/mitkDisplayInteractor.cpp
Interactions/mitkDisplayPositionEvent.cpp
# Interactions/mitkDisplayVectorInteractorLevelWindow.cpp # legacy, prob even now unneeded
# Interactions/mitkDisplayVectorInteractorScroll.cpp
Interactions/mitkEvent.cpp
Interactions/mitkEventConfig.cpp
Interactions/mitkEventDescription.cpp
Interactions/mitkEventFactory.cpp
Interactions/mitkInteractionEventHandler.cpp
Interactions/mitkEventMapper.cpp
Interactions/mitkEventRecorder.cpp
Interactions/mitkEventStateMachine.cpp
Interactions/mitkGlobalInteraction.cpp
Interactions/mitkInteractor.cpp
Interactions/mitkInternalEvent.cpp
Interactions/mitkInteractionEvent.cpp
Interactions/mitkInteractionEventConst.cpp
Interactions/mitkInteractionPositionEvent.cpp
Interactions/mitkInteractionKeyEvent.cpp
Interactions/mitkMousePressEvent.cpp
Interactions/mitkMouseMoveEvent.cpp
Interactions/mitkMouseReleaseEvent.cpp
Interactions/mitkMouseWheelEvent.cpp
Interactions/mitkMouseDoubleClickEvent.cpp
Interactions/mitkMouseModeSwitcher.cpp
Interactions/mitkMouseMovePointSetInteractor.cpp
Interactions/mitkMoveBaseDataInteractor.cpp
Interactions/mitkNodeDepententPointSetInteractor.cpp
Interactions/mitkPointSetDataInteractor.cpp
Interactions/mitkPointSetInteractor.cpp
Interactions/mitkPositionEvent.cpp
Interactions/mitkPositionTracker.cpp
Interactions/mitkStateMachineAction.cpp
Interactions/mitkStateMachineCondition.cpp
Interactions/mitkStateMachineState.cpp
Interactions/mitkStateMachineTransition.cpp
Interactions/mitkState.cpp
Interactions/mitkStateMachineContainer.cpp
Interactions/mitkStateEvent.cpp
Interactions/mitkStateMachine.cpp
Interactions/mitkStateMachineFactory.cpp
Interactions/mitkTransition.cpp
Interactions/mitkWheelEvent.cpp
Interactions/mitkKeyEvent.cpp
Interactions/mitkVtkEventAdapter.cpp
Interactions/mitkVtkInteractorStyle.cxx
Interactions/mitkCrosshairPositionEvent.cpp
Interactions/mitkXML2EventParser.cpp
Interfaces/mitkInteractionEventObserver.cpp
Interfaces/mitkIShaderRepository.cpp
Interfaces/mitkIPropertyAliases.cpp
Interfaces/mitkIPropertyDescriptions.cpp
Interfaces/mitkIPropertyExtensions.cpp
Interfaces/mitkIPropertyFilters.cpp
Interfaces/mitkIPersistenceService.cpp
IO/mitkBaseDataIOFactory.cpp
IO/mitkCoreDataNodeReader.cpp
IO/mitkDicomSeriesReader.cpp
IO/mitkDicomSR_LoadDICOMScalar.cpp
IO/mitkDicomSR_LoadDICOMScalar4D.cpp
IO/mitkDicomSR_LoadDICOMRGBPixel.cpp
IO/mitkDicomSR_LoadDICOMRGBPixel4D.cpp
IO/mitkDicomSR_ImageBlockDescriptor.cpp
IO/mitkDicomSR_GantryTiltInformation.cpp
IO/mitkDicomSR_SliceGroupingResult.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/mitkItkLoggingAdapter.cpp
IO/mitkItkPictureWrite.cpp
IO/mitkIOUtil.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/mitkVtkLoggingAdapter.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/mitkVtkMapper.cpp
Rendering/mitkRenderWindowFrame.cpp
- Rendering/mitkGeometry2DDataMapper2D.cpp
- Rendering/mitkGeometry2DDataVtkMapper3D.cpp
+ Rendering/mitkPlaneGeometryDataMapper2D.cpp
+ Rendering/mitkPlaneGeometryDataVtkMapper3D.cpp
Rendering/mitkGLMapper.cpp
Rendering/mitkGradientBackground.cpp
Rendering/mitkManufacturerLogo.cpp
Rendering/mitkMapper.cpp
Rendering/mitkPointSetGLMapper2D.cpp
Rendering/mitkPointSetVtkMapper2D.cpp
Rendering/mitkPointSetVtkMapper3D.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/mitkImageVtkMapper2D.cpp
Rendering/vtkMitkThickSlicesFilter.cpp
Rendering/vtkMitkLevelWindowFilter.cpp
Rendering/vtkNeverTranslucentTexture.cpp
Rendering/mitkOverlay.cpp
Rendering/mitkVtkOverlay.cpp
Rendering/mitkVtkOverlay2D.cpp
Rendering/mitkVtkOverlay3D.cpp
Rendering/mitkOverlayManager.cpp
Rendering/mitkAbstractOverlayLayouter.cpp
Rendering/mitkTextOverlay2D.cpp
Rendering/mitkTextOverlay3D.cpp
Rendering/mitkLabelOverlay3D.cpp
Rendering/mitkOverlay2DLayouter.cpp
Rendering/mitkScaleLegendOverlay
Common/mitkException.cpp
Common/mitkCommon.h
Common/mitkCoreObjectFactoryBase.cpp
Common/mitkCoreObjectFactory.cpp
Common/mitkCoreServices.cpp
)
set(RESOURCE_FILES
Interactions/globalConfig.xml
Interactions/DisplayInteraction.xml
Interactions/DisplayConfig.xml
Interactions/DisplayConfigPACS.xml
Interactions/DisplayConfigPACSPan.xml
Interactions/DisplayConfigPACSScroll.xml
Interactions/DisplayConfigPACSZoom.xml
Interactions/DisplayConfigPACSLevelWindow.xml
Interactions/DisplayConfigMITK.xml
Interactions/PointSet.xml
Interactions/Legacy/StateMachine.xml
Interactions/Legacy/DisplayConfigMITKTools.xml
Interactions/PointSetConfig.xml
mitkLevelWindowPresets.xml
)
diff --git a/Core/Documentation/Doxygen/Concepts/GeometryOverview.dox b/Core/Documentation/Doxygen/Concepts/GeometryOverview.dox
index e7876f2061..0de56b2e00 100644
--- a/Core/Documentation/Doxygen/Concepts/GeometryOverview.dox
+++ b/Core/Documentation/Doxygen/Concepts/GeometryOverview.dox
@@ -1,132 +1,134 @@
namespace mitk{
/**
\page GeometryOverviewPage Geometry Overview
\tableofcontents
\section GeometryOverviewPage_Introduction Introduction to Geometries
Geometries are used to describe the geometrical properties of data objects in space and time.\n
To use the geometry classes in the right way you have to understand the three different coordinate types present in MITK:\n\n
\image html CoordinateTypes.png
<center><b>The different coordinate types\n\n</b></center>\n
- -# World coordinates:
- - World coordinates are describing the actual spacial position of all MITK objects regarding a global coordinate system, normally specified by the imaging modality
- - World coordinates are represented by mitk::Point3D objects.
- - The geometry defines the offset, orientation, and scale of the considered data objects in reference to the world coordinate systems.
- - World coordinates are always measured in mm
- - If you are dealing with an image geometry, the origin of an image is pointing to the CENTER of the bottom-left-back voxel.\n
- - If you are NOT dealing with an image geometry (no defined discrete Voxels), the origin is pointing to the bottom-left-back CORNER
- - Index coordinates can be converted to world coordinates by calling Geometry3D::IndexToWorld()\n\n
+ -# World coordinates:
+ - World coordinates are describing the actual spacial position of all MITK objects regarding a global coordinate system, normally specified by the imaging modality
+ - World coordinates are represented by mitk::Point3D objects.
+ - The geometry defines the offset, orientation, and scale of the considered data objects in reference to the world coordinate systems.
+ - World coordinates are always measured in mm
+ - If you are dealing with an image geometry, the origin of an image is pointing to the CENTER of the bottom-left-back voxel.\n
+ - If you are NOT dealing with an image geometry (no defined discrete Voxels), the origin is pointing to the bottom-left-back CORNER
+ - Index coordinates can be converted to world coordinates by calling BaseGeometry::IndexToWorld()\n\n
\image html worldcoordinateSystem.png
<center><b>Corner-based coordinates\n\n</b></center>
\image html WorldcoordinateSystemCenterBased.png
<center><b>Center-based image-coordinates\n\n</b></center>\n
- -# Continuous index coordinates:
- - Dividing world coordinates through the pixel spacing and simultanously taking the offset into account leads to continuous index coordinates inside your dataobject.\n
- So continuous coordinates can be float values!
- - Continuous index coordinates are represented by mitk::Point3D objects.
- - They can be obtained by calling Geometry3D::WorldToIndex(), where &pt_mm is a point in worldcoordinates.\n
- -# Index coordinate system:
- - Index coordinates are discrete values that address voxels of a data object explicitly.
- - Index coordinates are represented by mitk::Index3D objects.
- - Basically they are continuous index coordinates which are rounded from half integer up.
- - E.g. (0,0) specifies the very first pixel of a 2D image, (0,1) the pixel of the next column in the same row
- - If you have world coordinates, they can be converted to discrete index coordinates by calling
- Geometry3D::WorldToIndex()\n\n
+ -# Continuous index coordinates:
+ - Dividing world coordinates through the pixel spacing and simultanously taking the offset into account leads to continuous index coordinates inside your dataobject.\n
+ So continuous coordinates can be float values!
+ - Continuous index coordinates are represented by mitk::Point3D objects.
+ - They can be obtained by calling BaseGeometry::WorldToIndex(), where &pt_mm is a point in worldcoordinates.\n
+ -# Index coordinate system:
+ - Index coordinates are discrete values that address voxels of a data object explicitly.
+ - Index coordinates are represented by mitk::Index3D objects.
+ - Basically they are continuous index coordinates which are rounded from half integer up.
+ - E.g. (0,0) specifies the very first pixel of a 2D image, (0,1) the pixel of the next column in the same row
+ - If you have world coordinates, they can be converted to discrete index coordinates by calling
+ BaseGeometry::WorldToIndex()\n\n
\section GeometryOverviewPage_PointsAndVector Difference between Points and Vectors
-Like ITK, MITK differenciate between points and vectors. A point defines a position in a coordinate system while a
+Like ITK, MITK differenciate between points and vectors. A point defines a position in a coordinate system while a
vector is the distance between two points. Therefore points and vectors behave different if a coordinate transformation
-is applied. An offest in a coordinate transformation will affect a transformed point but not a vector.
+is applied. An offest in a coordinate transformation will affect a transformed point but not a vector.
An Example:\n
-If two systems are given, which differ by a offset of (1,0,0). The point A(2,2,2) in system one will correspont to point A'(3,2,2) in the second system.
+If two systems are given, which differ by a offset of (1,0,0). The point A(2,2,2) in system one will correspont to point A'(3,2,2) in the second system.
But a vector a(2,2,2) will correspond to the vector a'(2,2,2).
-
+
\section GeometryOverviewPage_Concept The Geometry Concept
-As the superclass of all MITK geometries Geometry3D holds:
- - a spacial bounding box which is axes-parallel in index coordinates (often discrete indices of pixels), to be accessed by Geometry3D::GetBoundingBox()
- - a time related bounding box which holds the temporal validity of the considered data object in milliseconds (start and end time), to be accessed by Geometry3D::GetTimeBounds().\n
- The default for 3D geometries is minus infinity to plus infinity, meaning the object is always displayed independent of displayed time in MITK.
- - position information in form of a Euclidean transform in respect to world coordinates (i.e. a linear transformation matrix and offset) to convert (discrete or continuous) index coordinates to world coordinates and vice versa,\n
- to be accessed by Geometry3D::GetIndexToWorldTransform()\n
- See also: \ref GeometryOverviewPage_Introduction "Introduction to Geometries"
- - Many other properties (e.g. origin, extent, ...) which can be found in the \ref Geometry3D "class documentation"
- - <b> VERY IMPORTANT:</b>\n A flag called <i>isImageGeometry</i>, which indicates whether the coordinates are center-based or not!\n
- See also: \ref GeometryOverviewPage_Introduction "Introduction to Geometries" and \ref GeometryOverviewPage_Putting_Together "IMPORTANT: Putting it together for an Image"\n\n
+As the superclass of all MITK geometries BaseGeometry holds:
+ - a spacial bounding box which is axes-parallel in index coordinates (often discrete indices of pixels), to be accessed by BaseGeometry::GetBoundingBox()
+ - a time related bounding box which holds the temporal validity of the considered data object in milliseconds (start and end time), to be accessed by BaseGeometry::GetTimeBounds().\n
+ The default for 3D geometries is minus infinity to plus infinity, meaning the object is always displayed independent of displayed time in MITK.
+ - position information in form of a Euclidean transform in respect to world coordinates (i.e. a linear transformation matrix and offset) to convert (discrete or continuous) index coordinates to world coordinates and vice versa,\n
+ to be accessed by BaseGeometry::GetIndexToWorldTransform()\n
+ See also: \ref GeometryOverviewPage_Introduction "Introduction to Geometries"
+ - Many other properties (e.g. origin, extent, ...) which can be found in the \ref BaseGeometry "class documentation"
+ - <b> VERY IMPORTANT:</b>\n A flag called <i>isImageGeometry</i>, which indicates whether the coordinates are center-based or not!\n
+ See also: \ref GeometryOverviewPage_Introduction "Introduction to Geometries" and \ref GeometryOverviewPage_Putting_Together "IMPORTANT: Putting it together for an Image"\n\n
+
+Every data object (sub-)class of BaseData has a TimeGeometry which is accessed by BaseData::GetTimeGeometry(). This TimeGeometry holds one or more BaseGeometry objects which describes the object at specific time points, e.g. provides conversion between world and index coordinates and contains bounding boxes covering the area in which the data are placed. There is the possibility of using different implementations of the abstract TimeGeometry class which may differ in how the time steps are saved and the times are calculated.
-Every data object (sub-)class of BaseData has a TimeGeometry which is accessed by BaseData::GetTimeGeometry(). This TimeGeometry holds one or more Geometry3D objects which describes the object at specific time points, e.g. provides conversion between world and index coordinates and contains bounding boxes covering the area in which the data are placed. There is the possibility of using different implementations of the abstract TimeGeometry class which may differ in how the time steps are saved and the times are calculated.
+There are two ways to represent a time, either by a TimePointType or a TimeStepType. The first is similar to the continous index coordinates and defines a Time Point in milliseconds from timepoint zero. The second type is similar to index coordinates. These are discrete values which specify the number of the current time step going from 0 to GetNumberOfTimeSteps(). The conversion between a time point and a time step is done by calling the method TimeGeometry::TimeStepToTimePoint() or TimeGeometry::TimePointToTimeStep(). Note that the duration of a time step may differ from object to object, so in general it is better to calculate the corresponding time steps by using time points. Also the distance of the time steps does not need to be equidistant over time, it depends on the used TimeGeometry implementation.
-There are two ways to represent a time, either by a TimePointType or a TimeStepType. The first is similar to the continous index coordinates and defines a Time Point in milliseconds from timepoint zero. The second type is similar to index coordinates. These are discrete values which specify the number of the current time step going from 0 to GetNumberOfTimeSteps(). The conversion between a time point and a time step is done by calling the method TimeGeometry::TimeStepToTimePoint() or TimeGeometry::TimePointToTimeStep(). Note that the duration of a time step may differ from object to object, so in general it is better to calculate the corresponding time steps by using time points. Also the distance of the time steps does not need to be equidistant over time, it depends on the used TimeGeometry implementation.
+Each TimeGeometry has a bounding box covering the whole area in which the corresponding object is situated during all time steps. This bounding box may be accessed by calling TimeGeometry::GetBoundingBoxInWorld() and is always in world coordinates. The bounding box is calculated from all time steps, to manually start this calculation process call TimeGeometry::Update(). The bounding box is not updated if the getter is called.
-Each TimeGeometry has a bounding box covering the whole area in which the corresponding object is situated during all time steps. This bounding box may be accessed by calling TimeGeometry::GetBoundingBoxInWorld() and is always in world coordinates. The bounding box is calculated from all time steps, to manually start this calculation process call TimeGeometry::Update(). The bounding box is not updated if the getter is called.
+The TimeGeometry does not provide a transformation of world coordinates into image coordinates since each time step may has a different transformation. If a conversion between image and world is needed, the BaseGeometry for a specific time step or time point must be fetched either by TimeGeometry::GetGeometryForTimeStep() or TimeGeometry::GetGeometryForTimePoint() and then the conversion is calculated by using this geometry.
-The TimeGeometry does not provide a transformation of world coordinates into image coordinates since each time step may has a different transformation. If a conversion between image and world is needed, the Geometry3D for a specific time step or time point must be fetched either by TimeGeometry::GetGeometryForTimeStep() or TimeGeometry::GetGeometryForTimePoint() and then the conversion is calculated by using this geometry.
+The TimeGeometry class is an abstract class therefore it is not possible to instantiate it. Instead a derived class must be used. Currently the only class that can be chosen is ProportionalTimeGeometry() which assumes that the time steps are ordered equidistant. To initialize an object with given geometries call ProportionalTimeGeometry::Initialize() with an existing BaseGeometry and the number of time steps. The given geometries will be copied and not referenced!
-The TimeGeometry class is an abstract class therefore it is not possible to instantiate it. instead a derived class must be used. Currently the only class that can be chosen is ProportionalTimeGeometry() which assumes that the time steps are ordered equidistant. To initialize an object with given geometries call ProportionalTimeGeometry::Initialize() with an existing Geometry3D and the number of time steps. The given geometries will be copied and not referenced!
+Also, the BaseGeometry is an abstract class and derived classes must be used. The most simple implementation, i.e. the one to one implementation of the BaseGeometry class, is the class Geometry3D.
-SlicedGeometry3D is a sub-class of Geometry3D, which describes data objects consisting of slices, e.g., objects of type Image (or SlicedData, which is the super-class of Image).
+SlicedGeometry3D is a sub-class of BaseGeometry, which describes data objects consisting of slices, e.g., objects of type Image (or SlicedData, which is the super-class of Image).
Therefore, Image::GetTimeGeometry() will contain a list of SlicedGeometry3D instances. There is a special method SlicedData::GetSlicedGeometry(t) which directly returns\n
a SlicedGeometry3D to avoid the need of casting.
-The class SlicedGeometry3D contains a list of Geometry2D objects describing the slices in the image.We have here spatial steps from 0 to GetSlices().
-SlicedGeometry3D::InitializeEvenlySpaced (Geometry2D *geometry2D, unsigned int slices) initializes a stack of slices with the same thickness, one starting at the position where the previous one ends.
+The class SlicedGeometry3D contains a list of PlaneGeometry objects describing the slices in the image.We have here spatial steps from 0 to GetSlices().
+SlicedGeometry3D::InitializeEvenlySpaced (PlaneGeometry *planeGeometry, unsigned int slices) initializes a stack of slices with the same thickness, one starting at the position where the previous one ends.
-Geometry2D provides methods for working with 2D manifolds (i.e., simply spoken, an object that can be described using a 2D coordinate-system) in 3D space.\n
-For example it allows mapping of a 3D point on the 2D manifold using Geometry2D::Map(). A subclass of Geometry2D called PlaneGeometry, explicitly describes a 2D rectangular plane.\n
-Another important subclass of Geometry2D is the DisplayGeometry which describes the geometry of the display (the monitor screen). Basically it represents a rectangular view on a 2D world geometry\n
+PlaneGeometry provides methods for working with 2D manifolds (i.e., simply spoken, an object that can be described using a 2D coordinate-system) in 3D space.\n
+For example it allows mapping of a 3D point on the 2D manifold using PlaneGeometry::Map(). \n
+An important subclass of PlaneGeometry is the DisplayGeometry which describes the geometry of the display (the monitor screen). Basically it represents a rectangular view on a 2D world geometry.\n
The DisplayGeometry converts between screen and world coordinates, processes input events (e.g. mouse click) and provides methods for zooming and panning.\n
\image html DisplayGeometry.png
<center><b>Display Geometry\n\n</b></center>
-Finally there is the AbstractTransformGeometry which describes a 2D manifold in 3D space, defined by a vtkAbstractTransform. It is a abstract superclass for arbitrary user defined geometries\n
+Finally there is the AbstractTransformGeometry which describes a 2D manifold in 3D space, defined by a vtkAbstractTransform. It is a abstract superclass for arbitrary user defined geometries.\n
An example is the ThinPlateSplineCurvedGeometry.\n
\subsection GeometryOverviewPage_Putting_Together IMPORTANT: Putting it together for an Image
Please read this section accurately if you are working with Images!
The definition of the position of the corners of an image is different than the one of other data objects:
As mentioned in the previous section, world coordinates of data objects (e.g. surfaces ) usually specify the bottom left back corner of an object.
-In contrast to that a geometry of an Image is center-based, which means that the world coordinates of a voxel belonging to an image points to the center of that voxel.
+In contrast to that a geometry of an Image is center-based, which means that the world coordinates of a voxel belonging to an image points to the center of that voxel.
E.g:
\image html PixelCenterBased.png
<center><b>Center-based voxel\n\n</b></center>
If the origin of e.g. a surface lies at (15,10,0) in world coordinates, the origin`s world coordinates for an image are internally calculated like the following:
- <center>(15-0.5*X-Spacing\n
- 10-0.5*Y-Spacing\n
- 0-0.5*Z-Spacing)\n</center>
-
+ <center>(15-0.5*X-Spacing\n
+ 10-0.5*Y-Spacing\n
+ 0-0.5*Z-Spacing)\n</center>
+
If the image`s spacing is (x,y,z)=(1,1,3) then the corner coordinates are (14.5,9.5,-1.5).
-<b>If your geometry describes an image, the member variable <i>isImageGeometry</i> must be changed to true. This variable indicates also if your geometry is center-based or not.\n
+<b>If your geometry describes an image, the member variable <i>isImageGeometry</i> must be changed to true. This variable indicates also if your geometry is center-based or not.\n
The change can be done in two ways:\n
- -# You are sure that your origin is already center-based. Whether because you adjusted it manually or you copied it from another image.\n
- In that case, you can call the function <i>setImageGeometry(true)</i> or <i>imageGeometryOn()</i> to set the bool variable to true.
- -# You created a new geometry, did not manually adjust the origin to be center-based and have the bool value isImageGeometry set to false (default).\n
- In that case, call the function <i>ChangeImageGeometryConsideringOriginOffset(true)</i>. It will adjust your origin automatically and set the bool flag to true.\n
+ -# You are sure that your origin is already center-based. Whether because you adjusted it manually or you copied it from another image.\n
+ In that case, you can call the function <i>setImageGeometry(true)</i> or <i>imageGeometryOn()</i> to set the bool variable to true.
+ -# You created a new geometry, did not manually adjust the origin to be center-based and have the bool value isImageGeometry set to false (default).\n
+ In that case, call the function <i>ChangeImageGeometryConsideringOriginOffset(true)</i>. It will adjust your origin automatically and set the bool flag to true.\n
If you experience displaced contours, figures or other stuff, it is an indicator that you have not considered the origin offset mentioned above.</b>\n\n
-An image has a TimeGeometry, which contains one or more SlicedGeometry3D instances (one for each time step), all of which contain one or more instances of (sub-classes of) Geometry2D (usually PlaneGeometry).\n
-As a reminder: Geometry instances referring to images need a slightly different definition of corners, see Geometry3D::SetImageGeometry. This is usualy automatically called by Image.\n\n
+An image has a TimeGeometry, which contains one or more SlicedGeometry3D instances (one for each time step), all of which contain one or more instances of (sub-classes of) PlaneGeometry.\n
+As a reminder: Geometry instances referring to images need a slightly different definition of corners, see BaseGeometry::SetImageGeometry. This is usualy automatically called by Image.\n\n
\section GeometryOverviewPage_Connection Connection between MITK, ITK and VTK Geometries
\image html ITK_VTK_MITK_Geometries.png
\n\n
- - VTK transformation for rendering
- - ITK transformation for calculations
- - Both automatically updated when one is changed\n
+ - VTK transformation for rendering
+ - ITK transformation for calculations
+ - Both automatically updated when one is changed\n
Attention:<b>Not</b> automatically updated when changed hardcoded. Example: geometry->GetVtkMatrix()->Rotate(....)
*/
-}
\ No newline at end of file
+}
diff --git a/Documentation/Doxygen/DeveloperManual/Toolkit/ModuleManuals/GeometryMigration.dox b/Documentation/Doxygen/DeveloperManual/Toolkit/ModuleManuals/GeometryMigration.dox
new file mode 100644
index 0000000000..dee3eed592
--- /dev/null
+++ b/Documentation/Doxygen/DeveloperManual/Toolkit/ModuleManuals/GeometryMigration.dox
@@ -0,0 +1,148 @@
+/**
+
+\page GeometryMigration Migration Guide to new Geometry Concept
+
+\tableofcontents
+
+
+\section GeneralChanges General Changes
+
+\subsection OldClasses Old class diagram
+Until now, all geometry classes inherited from Geometry3D. This inheritance didn't make sense. For example, there is no reason, why we need a Geometry2D and a PlaneGeometry as both describe the same thing. Also, why does a two-dimensional class need to inherit from a three-dimensional class?
+\image html oldClasses.png "Old class diagram."
+
+\subsection NewClasses New class diagram
+Therefore, we inserted an abstract BaseGeometry class, from which all other geometry classes should inherit. The classes Geometry2D and PlaneGeometry are combined in the new PlaneGeometry class. Also, the LandmarkBasedCurvedGeometry is included in LandmarkProjectorBasedCurvedGeometry.
+\image html currentClasses.png "New class diagram."
+
+
+\section Howto How to adapt your code
+Most content of the BaseGeometry class consists of functions and variables of the former Geometry3D.
+Here are some guidelines, how to change your code to the new geometry scheme.
+
+\subsection privateVariables Variables are private.
+ All variables of BaseGeometry (former in Geometry3D) are private now. Hence, use the Set and Get methods to access the variables.
+
+\subsection geo2d Always use PlaneGeometry instead of Geometry2D.
+ The class Geometry2D does not exist any more. In most cases, you can just replace the Geometry2D by PlaneGeometry. Please pay attention if you use the function "IsAbove(Point3D point)". There were two different implementations in Geometry2D and PlaneGeometry. The default behavior is implemented according to the former function of PlaneGeometry. If you want to use the implementation of the former Geometry2D, please call "IsAbove(point,true)".\n
+
+ Here are the different implementations:
+\code
+ bool PlaneGeometry::IsAbove( const Point3D &pt3d_mm , bool considerBoundingBox = false) const
+ {
+ if(considerBoundingBox)
+ {
+ //This is the implementation of former Geometry2D
+ Point3D pt3d_units;
+ BaseGeometry::WorldToIndex(pt3d_mm, pt3d_units);
+ return (pt3d_units[2] > this->GetBoundingBox()->GetBounds()[4]);
+ }
+ else
+ {
+ //This is the implementation of former PlaneGeometry and the default behavior.
+ return SignedDistanceFromPlane(pt3d_mm) > 0;
+ }
+ }
+\endcode
+
+\subsection geo2ddata Rename Geometry2D... classes.
+ All ...Geometry2D... classes and functions are renamed to ...PlaneGeometry... . The new names are for example PlaneGeometryData instead of Geometry2DData. An example for functions is GetGeometry2D, which is now called GetPlaneGeometry. A simple search & replace of Geometry2D should work in most cases.\n\n
+ List of all names changed (excluding variables):
+ <ul>
+ <li> Geometry2D
+ <li> Geometry2DData
+ <li> Geometry2DDataToSurfaceFilter
+ <li> Geometry2DDataMapper2D
+ <li> Geometry2DDataVTKMapper
+ <li> GetCurrentWorldGeometry2D
+ <li> GetCurrentWorldGeometry2DNode
+ <li> GetCurrentWorldGeometry2DUpdateTime
+ <li> SetCurrentWorldGeometry2D
+ <li> GetGeometry2DData
+ <li> GetGeometry2D
+ <li> SetGeometry2D
+ </ul>
+
+
+\subsection geo3d In some cases, use BaseGeometry instead of Geometry3D.
+ As there are no classes any more, which inherit from Geometry3D, you cannot insert other classes (i.e. SlicedGeometry3D) for a Geometry3D.
+ If you have trouble, e.g. calling a function which expects a Geometry3D parameter, try one of the following steps:
+ <ul>
+ <li> Do you really need a Geometry3D? Maybe you always use e.g. a PlaneGeometry. Change your function to PlaneGeometry.
+ <li> If your function/object needs to be flexible for all geometry classes, change the Geometry3D to BaseGeometry.
+ <li> Try dynamic type casts to BaseGeometry.
+ </ul>
+
+\subsection clone Clones of BaseGeometry.
+ The BaseGeometry class is an abstract class. You cannot create an object of BaseGeometry. If you need a clone of BaseGeometry to call a function, use the following code:
+ \code
+ itk::LightObject::Pointer lopointer = geometry.Clone();
+ Initialize(dynamic_cast<BaseGeometry*>(lopointer.GetPointer()));
+ \endcode
+
+ instead of:
+ \code
+ Geometry3D::Pointer geometry3D = geometry.Clone();
+ Initialize(geometry3D.GetPointer());
+ \endcode
+
+\subsection object Create an object of BaseGeometry.
+ Again, you cannot create an object of BaseGeometry. However, there are cases, where we need a flexible Variable which can contain objects of any other geometry class later on. This might be the case for member variables, etc. In this case, try:
+ \code
+ mitk::Geometry3D::Pointer geo3D = Geometry3D::New();
+ mitk::BaseGeometry::Pointer m_geometry = dynamic_cast<BaseGeometry*>(geo3D.GetPointer());
+ \endcode
+
+ instead of
+
+ \code
+ mitk::Geometry3D::Pointer m_geometry = mitk::Geometry3D::New();
+ \endcode
+
+\subsection virtual Virtual functions.
+ To ensure a reliable behavior of functions, most functions are not virtual any more. However, if a function needs a different behavior in subclasses, there are virtual Pre- and Post- functions, which allow for additional code. The pre-functions are called at the very beginning of a function, the post-functions at the end. In the BaseGeometry, all pre- and post-functions are empty.\n
+ An example:\n
+ The function "SetIndexToWorldTransform" is not virtual any more.
+ For a PlaneGeometry, we need a perpendicular normal before the transformation is set. Afterwards, we need to apply the transformation to the scaling factors.\n
+ Code of the BaseGeometry class:
+
+\code
+ void SetIndexToWorldTransform(mitk::AffineTransform3D* transform)
+ {
+ PreSetIndexToWorldTransform(transform);
+ if(m_IndexToWorldTransform.GetPointer() != transform)
+ {
+ m_IndexToWorldTransform = transform;
+ CopySpacingFromTransform(m_IndexToWorldTransform, m_Spacing);
+ vtk2itk(m_IndexToWorldTransform->GetOffset(), m_Origin);
+ TransferItkToVtkTransform();
+ Modified();
+ }
+ PostSetIndexToWorldTransform(transform);
+ }
+ virtual void PreSetIndexToWorldTransform(mitk::AffineTransform3D* transform){};
+ virtual void PostSetIndexToWorldTransform(mitk::AffineTransform3D* transform){};
+\endcode
+
+Code of PlaneGeometry:
+\code
+ void PlaneGeometry::PreSetIndexToWorldTransform(mitk::AffineTransform3D *transform)
+ {
+ EnsurePerpendicularNormal(transform);
+ }
+ void PlaneGeometry::PostSetIndexToWorldTransform(mitk::AffineTransform3D* transform)
+ {
+ m_ScaleFactorMMPerUnitX=GetExtentInMM(0)/GetExtent(0);
+ m_ScaleFactorMMPerUnitY=GetExtentInMM(1)/GetExtent(1);
+ }
+\endcode
+
+\subsection parametric Parametric functions are not part of BaseGeometry.
+ In Geometry3D, there were several "Parametric" functions (e.g. GetParametricExtent, GetParametricTransform), which only called the non-parametric function (e.g. GetExtent, GetIndexToWorldTransform). These functions are removed, please use the non-parametric implementation instead. However, in the AbstractTransformGeometry (and all subclasses), these parametric functions behave different and are still available.
+
+\subsection floatspacing There is no float spacing any more.
+ Use GetSpacing instead of GetFloatSpacing.
+
+\subsection LandmarkBased Always use LandmarkProjectorBasedCurvedGeometry instead of LandmarkBasedCurvedGeometry.
+ The class LandmarkBasedCurvedGeometry does not exist any more. Please use LandmarkProjectorBasedCurvedGeometry.
+*/
diff --git a/Documentation/Doxygen/DeveloperManual/Toolkit/ModuleManuals/MITKModuleManualsList.dox b/Documentation/Doxygen/DeveloperManual/Toolkit/ModuleManuals/MITKModuleManualsList.dox
index a6cf1818b2..6e43c61bb7 100644
--- a/Documentation/Doxygen/DeveloperManual/Toolkit/ModuleManuals/MITKModuleManualsList.dox
+++ b/Documentation/Doxygen/DeveloperManual/Toolkit/ModuleManuals/MITKModuleManualsList.dox
@@ -1,25 +1,26 @@
/**
\page MITKModuleManualsListPage MITK Module Manuals
\section MITKModuleManualsListPageOverview Overview
The modules are shared libraries that provide functionality that can be used by developers.
\section MITKModuleManualsListPageModuleManualList List of Module Manuals
\li \subpage IGTGeneralModulePage
\li \subpage MitkOpenCL_Overview
\li \subpage GeneratingDeviceModulesPage
\li \subpage mitkPython_Overview
\li \subpage USModulePage
\section MITKModuleManualsListPageAdditionalInformation Additional Information on Certain Modules
\li \ref PlanarPropertiesPage
\li \subpage DiffusionImagingPropertiesPage
\li \subpage ConnectomicsRenderingPropertiesPage
\section MITKMigrationGuides Migration Guides
\li \subpage InteractionMigration
+ \li \subpage GeometryMigration
*/
diff --git a/Documentation/Doxygen/DeveloperManual/Toolkit/ModuleManuals/currentClasses.png b/Documentation/Doxygen/DeveloperManual/Toolkit/ModuleManuals/currentClasses.png
new file mode 100644
index 0000000000..f40fd3f7aa
Binary files /dev/null and b/Documentation/Doxygen/DeveloperManual/Toolkit/ModuleManuals/currentClasses.png differ
diff --git a/Documentation/Doxygen/DeveloperManual/Toolkit/ModuleManuals/oldClasses.png b/Documentation/Doxygen/DeveloperManual/Toolkit/ModuleManuals/oldClasses.png
new file mode 100644
index 0000000000..a276cfc5f9
Binary files /dev/null and b/Documentation/Doxygen/DeveloperManual/Toolkit/ModuleManuals/oldClasses.png differ
diff --git a/Modules/AlgorithmsExt/mitkAutoCropImageFilter.cpp b/Modules/AlgorithmsExt/mitkAutoCropImageFilter.cpp
index 4f9a7ca59a..a40080264a 100644
--- a/Modules/AlgorithmsExt/mitkAutoCropImageFilter.cpp
+++ b/Modules/AlgorithmsExt/mitkAutoCropImageFilter.cpp
@@ -1,363 +1,363 @@
/*===================================================================
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 "mitkAutoCropImageFilter.h"
#include "mitkImageCast.h"
#include "mitkImageAccessByItk.h"
#include "mitkGeometry3D.h"
#include "mitkStatusBar.h"
#include "mitkImageReadAccessor.h"
#include "mitkPlaneGeometry.h"
#include <itkImageRegionConstIterator.h>
#include <itkRegionOfInterestImageFilter.h>
#include <mitkProportionalTimeGeometry.h>
mitk::AutoCropImageFilter::AutoCropImageFilter()
: m_BackgroundValue(0),
m_MarginFactor(1.0),
m_TimeSelector(NULL),
m_OverrideCroppingRegion(false)
{
}
mitk::AutoCropImageFilter::~AutoCropImageFilter()
{
}
template < typename TPixel, unsigned int VImageDimension>
void mitk::AutoCropImageFilter::ITKCrop3DImage( itk::Image< TPixel, VImageDimension >* inputItkImage, unsigned int timestep)
{
if (inputItkImage == NULL)
{
mitk::StatusBar::GetInstance()->DisplayErrorText ("An internal error occurred. Can't convert Image. Please report to bugs@mitk.org");
MITK_ERROR << "image is NULL...returning" << std::endl;
return;
}
typedef itk::Image< TPixel, VImageDimension > InternalImageType;
typedef typename InternalImageType::Pointer InternalImagePointer;
typedef itk::RegionOfInterestImageFilter < InternalImageType, InternalImageType > ROIFilterType;
typedef typename itk::RegionOfInterestImageFilter < InternalImageType, InternalImageType >::Pointer ROIFilterPointer;
InternalImagePointer outputItk = InternalImageType::New();
ROIFilterPointer roiFilter = ROIFilterType::New();
roiFilter->SetInput(0,inputItkImage);
roiFilter->SetRegionOfInterest(this->GetCroppingRegion());
roiFilter->Update();
outputItk = roiFilter->GetOutput();
outputItk->DisconnectPipeline();
mitk::Image::Pointer newMitkImage = mitk::Image::New();
mitk::CastToMitkImage( outputItk, newMitkImage );
MITK_INFO << "Crop-Output dimension: " << (newMitkImage->GetDimension() == 3) << " Filter-Output dimension: "<<this->GetOutput()->GetDimension()<< " Timestep: " << timestep;
mitk::ImageReadAccessor newMitkImgAcc(newMitkImage);
this->GetOutput()->SetVolume( newMitkImgAcc.GetData(), timestep);
}
void mitk::AutoCropImageFilter::GenerateOutputInformation()
{
mitk::Image::Pointer input = const_cast<mitk::Image*> (this->GetInput());
mitk::Image::Pointer output = this->GetOutput();
if(input->GetDimension() <= 2)
{
MITK_ERROR << "Only 3D any 4D images are supported." << std::endl;
return;
}
ComputeNewImageBounds();
if ((output->IsInitialized()) && (output->GetPipelineMTime() <= m_TimeOfHeaderInitialization.GetMTime()))
return;
itkDebugMacro(<<"GenerateOutputInformation()");
// PART I: initialize input requested region. We do this already here (and not
// later when GenerateInputRequestedRegion() is called), because we
// also need the information to setup the output.
// pre-initialize input-requested-region to largest-possible-region
// and correct time-region; spatial part will be cropped by
// bounding-box of bounding-object below
m_InputRequestedRegion = input->GetLargestPossibleRegion();
// build region out of index and size calculated in ComputeNewImageBounds()
mitk::SlicedData::IndexType index;
index[0] = m_RegionIndex[0];
index[1] = m_RegionIndex[1];
index[2] = m_RegionIndex[2];
index[3] = m_InputRequestedRegion.GetIndex()[3];
index[4] = m_InputRequestedRegion.GetIndex()[4];
mitk::SlicedData::SizeType size;
size[0] = m_RegionSize[0];
size[1] = m_RegionSize[1];
size[2] = m_RegionSize[2];
size[3] = m_InputRequestedRegion.GetSize()[3];
size[4] = m_InputRequestedRegion.GetSize()[4];
mitk::SlicedData::RegionType cropRegion(index, size);
// crop input-requested-region with cropping region computed from the image data
if(m_InputRequestedRegion.Crop(cropRegion)==false)
{
// crop not possible => do nothing: set time size to 0.
size.Fill(0);
m_InputRequestedRegion.SetSize(size);
return;
}
// set input-requested-region, because we access it later in
// GenerateInputRequestedRegion (there we just set the time)
input->SetRequestedRegion(&m_InputRequestedRegion);
// PART II: initialize output image
unsigned int dimension = input->GetDimension();
unsigned int *dimensions = new unsigned int [dimension];
itk2vtk(m_InputRequestedRegion.GetSize(), dimensions);
if(dimension>3)
memcpy(dimensions+3, input->GetDimensions()+3, (dimension-3)*sizeof(unsigned int));
// create basic slicedGeometry that will be initialized below
output->Initialize(mitk::PixelType( GetOutputPixelType() ), dimension, dimensions);
delete [] dimensions;
//clone the IndexToWorldTransform from the input, otherwise we will overwrite it, when adjusting the origin of the output image!!
itk::ScalableAffineTransform< mitk::ScalarType,3 >::Pointer cloneTransform = itk::ScalableAffineTransform< mitk::ScalarType,3 >::New();
cloneTransform->Compose(input->GetGeometry()->GetIndexToWorldTransform());
output->GetGeometry()->SetIndexToWorldTransform( cloneTransform.GetPointer() );
// Position the output Image to match the corresponding region of the input image
mitk::SlicedGeometry3D* slicedGeometry = output->GetSlicedGeometry();
mitk::SlicedGeometry3D::Pointer inputGeometry = input->GetSlicedGeometry();
const mitk::SlicedData::IndexType& start = m_InputRequestedRegion.GetIndex();
mitk::Point3D origin; vtk2itk(start, origin);
input->GetSlicedGeometry()->IndexToWorld(origin, origin);
slicedGeometry->SetOrigin(origin);
// get the PlaneGeometry for the first slice of the original image
- mitk::PlaneGeometry::Pointer plane = dynamic_cast<mitk::PlaneGeometry*>( inputGeometry->GetGeometry2D( 0 )->Clone().GetPointer() );
+ mitk::PlaneGeometry::Pointer plane = dynamic_cast<mitk::PlaneGeometry*>( inputGeometry->GetPlaneGeometry( 0 )->Clone().GetPointer() );
assert( plane );
// re-initialize the plane according to the new requirements:
// dimensions of the cropped image
// right- and down-vector as well as spacing do not change, so use the ones from
// input image
ScalarType dimX = output->GetDimensions()[0];
ScalarType dimY = output->GetDimensions()[1];
mitk::Vector3D right = plane->GetAxisVector(0);
mitk::Vector3D down = plane->GetAxisVector(1);
mitk::Vector3D spacing = plane->GetSpacing();
plane->InitializeStandardPlane( dimX, dimY, right, down, &spacing );
// set the new origin on the PlaneGeometry as well
plane->SetOrigin(origin);
// re-initialize the slicedGeometry with the correct planeGeometry
// in order to get a fully initialized SlicedGeometry3D
slicedGeometry->InitializeEvenlySpaced( plane, inputGeometry->GetSpacing()[2], output->GetSlicedGeometry()->GetSlices() );
mitk::TimeGeometry* timeSlicedGeometry = output->GetTimeGeometry();
mitk::ProportionalTimeGeometry* propTimeGeometry = dynamic_cast<ProportionalTimeGeometry*>(timeSlicedGeometry);
propTimeGeometry->Initialize(slicedGeometry, output->GetDimension(3));
m_TimeOfHeaderInitialization.Modified();
output->SetPropertyList(input->GetPropertyList()->Clone());
}
void mitk::AutoCropImageFilter::GenerateData()
{
mitk::Image::ConstPointer input = this->GetInput();
mitk::Image::Pointer output = this->GetOutput();
if(input.IsNull())
return;
if(input->GetDimension() <= 2)
{
MITK_ERROR << "Only 3D and 4D images supported";
return;
}
if((output->IsInitialized()==false) )
return;
if( m_TimeSelector.IsNull() ) m_TimeSelector = mitk::ImageTimeSelector::New();
m_TimeSelector->SetInput(input);
mitk::SlicedData::RegionType outputRegion = input->GetRequestedRegion();
int tstart = outputRegion.GetIndex(3);
int tmax = tstart + outputRegion.GetSize(3);
for( int timestep=tstart;timestep<tmax;++timestep )
{
m_TimeSelector->SetTimeNr(timestep);
m_TimeSelector->UpdateLargestPossibleRegion();
AccessFixedDimensionByItk_1( m_TimeSelector->GetOutput(), ITKCrop3DImage, 3, timestep );
}
// this->GetOutput()->Update(); // Not sure if this is necessary...
m_TimeOfHeaderInitialization.Modified();
}
void mitk::AutoCropImageFilter::ComputeNewImageBounds()
{
mitk::Image::ConstPointer inputMitk = this->GetInput();
if (m_OverrideCroppingRegion)
{
for (unsigned int i=0; i<3; ++i)
{
m_RegionIndex[i] = m_CroppingRegion.GetIndex()[i];
m_RegionSize[i] = m_CroppingRegion.GetSize()[i];
if (m_RegionIndex[i] >= static_cast<RegionType::IndexValueType>(inputMitk->GetDimension(i)))
{
itkExceptionMacro("Cropping index is not inside the image. "
<< std::endl << "Index:"
<< std::endl << m_CroppingRegion.GetIndex()
<< std::endl << "Size:"
<< std::endl << m_CroppingRegion.GetSize());
}
if (m_RegionIndex[i] + m_RegionSize[i] >= inputMitk->GetDimension(i))
{
m_RegionSize[i] = inputMitk->GetDimension(i) - m_RegionIndex[i];
}
}
for (unsigned int i=0; i<3; ++i)
{
m_RegionIndex[i] = m_CroppingRegion.GetIndex()[i];
m_RegionSize[i] = m_CroppingRegion.GetSize()[i];
}
}
else
{
// Check if a 3D or 4D image is present
unsigned int timeSteps = 1;
if (inputMitk->GetDimension() == 4 )
timeSteps = inputMitk->GetDimension(3);
ImageType::IndexType minima,maxima;
if (inputMitk->GetDimension() == 4)
{
// initialize with time step 0
m_TimeSelector = mitk::ImageTimeSelector::New();
m_TimeSelector->SetInput( inputMitk );
m_TimeSelector->SetTimeNr( 0 );
m_TimeSelector->UpdateLargestPossibleRegion();
inputMitk = m_TimeSelector->GetOutput();
}
ImagePointer inputItk = ImageType::New();
mitk::CastToItkImage( inputMitk , inputItk );
// it is assumed that all volumes in a time series have the same 3D dimensions
ImageType::RegionType origRegion = inputItk->GetLargestPossibleRegion();
// Initialize min and max on the first (or only) time step
maxima = inputItk->GetLargestPossibleRegion().GetIndex();
minima[0] = inputItk->GetLargestPossibleRegion().GetSize()[0];
minima[1] = inputItk->GetLargestPossibleRegion().GetSize()[1];
minima[2] = inputItk->GetLargestPossibleRegion().GetSize()[2];
typedef itk::ImageRegionConstIterator< ImageType > ConstIteratorType;
for(unsigned int idx = 0; idx < timeSteps; ++idx)
{
// if 4D image, update time step and itk image
if( idx > 0)
{
m_TimeSelector->SetTimeNr( idx );
m_TimeSelector->UpdateLargestPossibleRegion();
inputMitk = m_TimeSelector->GetOutput();
mitk::CastToItkImage( inputMitk , inputItk );
}
ConstIteratorType inIt( inputItk, origRegion );
for ( inIt.GoToBegin(); !inIt.IsAtEnd(); ++inIt)
{
float pix_val = inIt.Get();
if ( fabs(pix_val - m_BackgroundValue) > mitk::eps )
{
for (int i=0; i < 3; i++)
{
minima[i] = vnl_math_min((int)minima[i],(int)(inIt.GetIndex()[i]));
maxima[i] = vnl_math_max((int)maxima[i],(int)(inIt.GetIndex()[i]));
}
}
}
}
typedef ImageType::RegionType::SizeType::SizeValueType SizeValueType;
m_RegionSize[0] = (SizeValueType)(m_MarginFactor * (maxima[0] - minima[0] + 1 ));
m_RegionSize[1] = (SizeValueType)(m_MarginFactor * (maxima[1] - minima[1] + 1 ));
m_RegionSize[2] = (SizeValueType)(m_MarginFactor * (maxima[2] - minima[2] + 1 ));
m_RegionIndex = minima;
m_RegionIndex[0] -= (m_RegionSize[0] - maxima[0] + minima[0] - 1 )/2;
m_RegionIndex[1] -= (m_RegionSize[1] - maxima[1] + minima[1] - 1 )/2;
m_RegionIndex[2] -= (m_RegionSize[2] - maxima[2] + minima[2] - 1 )/2;
ImageType::RegionType cropRegion(m_RegionIndex,m_RegionSize);
origRegion.Crop(cropRegion);
m_RegionSize[0] = origRegion.GetSize()[0];
m_RegionSize[1] = origRegion.GetSize()[1];
m_RegionSize[2] = origRegion.GetSize()[2];
m_RegionIndex[0] = origRegion.GetIndex()[0];
m_RegionIndex[1] = origRegion.GetIndex()[1];
m_RegionIndex[2] = origRegion.GetIndex()[2];
m_CroppingRegion = origRegion;
}
}
void mitk::AutoCropImageFilter::GenerateInputRequestedRegion()
{
}
const mitk::PixelType mitk::AutoCropImageFilter::GetOutputPixelType()
{
return this->GetInput()->GetPixelType();
}
void mitk::AutoCropImageFilter::SetCroppingRegion(RegionType overrideRegion)
{
m_CroppingRegion = overrideRegion;
m_OverrideCroppingRegion = true;
}
diff --git a/Modules/AlgorithmsExt/mitkBoundingObjectCutter.cpp b/Modules/AlgorithmsExt/mitkBoundingObjectCutter.cpp
index d09fb325eb..5cc238802e 100644
--- a/Modules/AlgorithmsExt/mitkBoundingObjectCutter.cpp
+++ b/Modules/AlgorithmsExt/mitkBoundingObjectCutter.cpp
@@ -1,226 +1,226 @@
/*===================================================================
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 "mitkBoundingObjectCutter.h"
#include "mitkBoundingObjectCutter.txx"
#include "mitkTimeHelper.h"
#include "mitkImageAccessByItk.h"
#include "mitkBoundingObject.h"
#include "mitkGeometry3D.h"
#include <math.h>
namespace mitk
{
void BoundingObjectCutter::SetBoundingObject( const mitk::BoundingObject* boundingObject )
{
m_BoundingObject = const_cast<mitk::BoundingObject*>(boundingObject);
// Process object is not const-correct so the const_cast is required here
this->ProcessObject::SetNthInput(1,
const_cast< mitk::BoundingObject * >( boundingObject ) );
}
const mitk::BoundingObject* BoundingObjectCutter::GetBoundingObject() const
{
return m_BoundingObject.GetPointer();
}
BoundingObjectCutter::BoundingObjectCutter()
: m_BoundingObject(NULL), m_InsideValue(1), m_OutsideValue(0), m_AutoOutsideValue(false),
m_UseInsideValue(false), m_OutsidePixelCount(0), m_InsidePixelCount(0), m_UseWholeInputRegion(false)
{
this->SetNumberOfIndexedInputs(2);
this->SetNumberOfRequiredInputs(2);
m_InputTimeSelector = mitk::ImageTimeSelector::New();
m_OutputTimeSelector = mitk::ImageTimeSelector::New();
}
BoundingObjectCutter::~BoundingObjectCutter()
{
}
const mitk::PixelType BoundingObjectCutter::GetOutputPixelType()
{
return this->GetInput()->GetPixelType();
}
void BoundingObjectCutter::GenerateInputRequestedRegion()
{
mitk::Image* output = this->GetOutput();
if((output->IsInitialized()==false) || (m_BoundingObject.IsNull()) || (m_BoundingObject->GetTimeGeometry()->CountTimeSteps() == 0))
return;
// we have already calculated the spatial part of the
// input-requested-region in m_InputRequestedRegion in
// GenerateOutputInformation (which is called before
// GenerateInputRequestedRegion).
GenerateTimeInInputRegion(output, const_cast< mitk::Image * > ( this->GetInput() ));
GenerateTimeInInputRegion(output, m_BoundingObject.GetPointer());
}
void BoundingObjectCutter::GenerateOutputInformation()
{
mitk::Image::Pointer output = this->GetOutput();
if ((output->IsInitialized()) && (output->GetPipelineMTime() <= m_TimeOfHeaderInitialization.GetMTime()))
return;
mitk::Image::Pointer input = const_cast< mitk::Image * > ( this->GetInput() );
if(input.IsNull())
{
MITK_WARN << "Input is not a mitk::Image";
return;
}
itkDebugMacro(<<"GenerateOutputInformation()");
unsigned int dimension = input->GetDimension();
if (dimension < 3)
{
MITK_WARN << "ImageCropper cannot handle 1D or 2D Objects. Operation aborted.";
return;
}
if((m_BoundingObject.IsNull()) || (m_BoundingObject->GetTimeGeometry()->CountTimeSteps() == 0))
return;
- mitk::Geometry3D* boGeometry = m_BoundingObject->GetGeometry();
- mitk::Geometry3D* inputImageGeometry = input->GetSlicedGeometry();
+ mitk::BaseGeometry* boGeometry = m_BoundingObject->GetGeometry();
+ mitk::BaseGeometry* inputImageGeometry = input->GetSlicedGeometry();
// calculate bounding box of bounding-object relative to the geometry
// of the input image. The result is in pixel coordinates of the input
// image (because the m_IndexToWorldTransform includes the spacing).
mitk::BoundingBox::Pointer boBoxRelativeToImage = boGeometry->CalculateBoundingBoxRelativeToTransform( inputImageGeometry->GetIndexToWorldTransform() );
// PART I: initialize input requested region. We do this already here (and not
// later when GenerateInputRequestedRegion() is called), because we
// also need the information to setup the output.
// pre-initialize input-requested-region to largest-possible-region
// and correct time-region; spatial part will be cropped by
// bounding-box of bounding-object below
m_InputRequestedRegion = input->GetLargestPossibleRegion();
// build region out of bounding-box of bounding-object
mitk::SlicedData::IndexType index=m_InputRequestedRegion.GetIndex(); //init times and channels
mitk::BoundingBox::PointType min = boBoxRelativeToImage->GetMinimum();
index[0] = (mitk::SlicedData::IndexType::IndexValueType)(std::ceil(min[0]));
index[1] = (mitk::SlicedData::IndexType::IndexValueType)(std::ceil(min[1]));
index[2] = (mitk::SlicedData::IndexType::IndexValueType)(std::ceil(min[2]));
mitk::SlicedData::SizeType size = m_InputRequestedRegion.GetSize(); //init times and channels
mitk::BoundingBox::PointType max = boBoxRelativeToImage->GetMaximum();
size[0] = (mitk::SlicedData::SizeType::SizeValueType)(std::ceil(max[0])-index[0]);
size[1] = (mitk::SlicedData::SizeType::SizeValueType)(std::ceil(max[1])-index[1]);
size[2] = (mitk::SlicedData::SizeType::SizeValueType)(std::ceil(max[2])-index[2]);
mitk::SlicedData::RegionType boRegion(index, size);
if(m_UseWholeInputRegion == false)
{
// crop input-requested-region with region of bounding-object
if(m_InputRequestedRegion.Crop(boRegion)==false)
{
// crop not possible => do nothing: set time size to 0.
size.Fill(0);
m_InputRequestedRegion.SetSize(size);
boRegion.SetSize(size);
m_BoundingObject->SetRequestedRegion(&boRegion);
return;
}
}
// set input-requested-region, because we access it later in
// GenerateInputRequestedRegion (there we just set the time)
input->SetRequestedRegion(&m_InputRequestedRegion);
// PART II: initialize output image
unsigned int *dimensions = new unsigned int [dimension];
itk2vtk(m_InputRequestedRegion.GetSize(), dimensions);
if(dimension>3)
memcpy(dimensions+3, input->GetDimensions()+3, (dimension-3)*sizeof(unsigned int));
output->Initialize(mitk::PixelType(GetOutputPixelType()), dimension, dimensions);
delete [] dimensions;
// now we have everything to initialize the transform of the output
mitk::SlicedGeometry3D* slicedGeometry = output->GetSlicedGeometry();
// set the transform: use the transform of the input;
// the origin will be replaced afterwards
AffineTransform3D::Pointer indexToWorldTransform = AffineTransform3D::New();
indexToWorldTransform->SetParameters(input->GetSlicedGeometry()->GetIndexToWorldTransform()->GetParameters());
slicedGeometry->SetIndexToWorldTransform(indexToWorldTransform);
// Position the output Image to match the corresponding region of the input image
const mitk::SlicedData::IndexType& start = m_InputRequestedRegion.GetIndex();
mitk::Point3D origin; vtk2itk(start, origin);
inputImageGeometry->IndexToWorld(origin, origin);
slicedGeometry->SetOrigin(origin);
m_TimeOfHeaderInitialization.Modified();
}
void BoundingObjectCutter::ComputeData(mitk::Image* input3D, int boTimeStep)
{
AccessFixedDimensionByItk_2(input3D, CutImage, 3, this, boTimeStep);
}
void BoundingObjectCutter::GenerateData()
{
mitk::Image::ConstPointer input = this->GetInput();
mitk::Image::Pointer output = this->GetOutput();
if(input.IsNull())
return;
if((output->IsInitialized()==false) || (m_BoundingObject.IsNull()) || (m_BoundingObject->GetTimeGeometry()->CountTimeSteps() == 0))
return;
m_InputTimeSelector->SetInput(input);
m_OutputTimeSelector->SetInput(this->GetOutput());
mitk::Surface::RegionType outputRegion = output->GetRequestedRegion();
const mitk::TimeGeometry *outputTimeGeometry = output->GetTimeGeometry();
const mitk::TimeGeometry *inputTimeGeometry = input->GetTimeGeometry();
const mitk::TimeGeometry *boundingObjectTimeGeometry = m_BoundingObject->GetTimeGeometry();
TimePointType timeInMS;
int timestep=0;
int tstart=outputRegion.GetIndex(3);
int tmax=tstart+outputRegion.GetSize(3);
int t;
for(t=tstart;t<tmax;++t)
{
timeInMS = outputTimeGeometry->TimeStepToTimePoint( t );
timestep = inputTimeGeometry->TimePointToTimeStep( timeInMS );
m_InputTimeSelector->SetTimeNr(timestep);
m_InputTimeSelector->UpdateLargestPossibleRegion();
m_OutputTimeSelector->SetTimeNr(t);
m_OutputTimeSelector->UpdateLargestPossibleRegion();
timestep = boundingObjectTimeGeometry->TimePointToTimeStep( timeInMS );
ComputeData(m_InputTimeSelector->GetOutput(), timestep);
}
m_InputTimeSelector->SetInput(NULL);
m_OutputTimeSelector->SetInput(NULL);
m_TimeOfHeaderInitialization.Modified();
}
} // of namespace mitk
diff --git a/Modules/AlgorithmsExt/mitkBoundingObjectCutter.txx b/Modules/AlgorithmsExt/mitkBoundingObjectCutter.txx
index 9c602b2a60..a1062d802a 100644
--- a/Modules/AlgorithmsExt/mitkBoundingObjectCutter.txx
+++ b/Modules/AlgorithmsExt/mitkBoundingObjectCutter.txx
@@ -1,151 +1,151 @@
/*===================================================================
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 MITKBOUNDINGOBJECTCUTTER_TXX
#define MITKBOUNDINGOBJECTCUTTER_TXX
#include "mitkStatusBar.h"
#include "mitkImageToItk.h"
#include "itkImageRegionIteratorWithIndex.h"
namespace mitk
{
template < typename TPixel, unsigned int VImageDimension, typename TOutputPixel >
void CutImageWithOutputTypeSelect
( itk::Image<TPixel, VImageDimension>* inputItkImage, mitk::BoundingObjectCutter* cutter, int /* boTimeStep */, TOutputPixel* /* dummy */)
{
typedef itk::Image<TPixel, VImageDimension> ItkInputImageType;
typedef itk::Image<TOutputPixel, VImageDimension> ItkOutputImageType;
typedef typename itk::ImageBase<VImageDimension>::RegionType ItkRegionType;
typedef itk::ImageRegionIteratorWithIndex< ItkInputImageType > ItkInputImageIteratorType;
typedef itk::ImageRegionIteratorWithIndex< ItkOutputImageType > ItkOutputImageIteratorType;
if(cutter->m_BoundingObject.IsNull())
return;
if (inputItkImage == NULL)
{
mitk::StatusBar::GetInstance()->DisplayErrorText ("An internal error occurred. Can't convert Image. Please report to bugs@mitk.org");
std::cout << " image is NULL...returning" << std::endl;
return;
}
// PART 1: convert m_InputRequestedReg ion (type mitk::SlicedData::RegionType)
// into ITK-image-region (ItkImageType::RegionType)
// unfortunately, we cannot use input->GetRequestedRegion(), because it
// has been destroyed by the mitk::CastToItkImage call of PART 1
// (which sets the m_RequestedRegion to the LargestPossibleRegion).
// Thus, use our own member m_InputRequestedRegion insead.
// first convert the index
typename ItkRegionType::IndexType::IndexValueType tmpIndex[3];
itk2vtk(cutter->m_InputRequestedRegion.GetIndex(), tmpIndex);
typename ItkRegionType::IndexType index;
index.SetIndex(tmpIndex);
// then convert the size
typename ItkRegionType::SizeType::SizeValueType tmpSize[3];
itk2vtk(cutter->m_InputRequestedRegion.GetSize(), tmpSize);
typename ItkRegionType::SizeType size;
size.SetSize(tmpSize);
//create the ITK-image-region out of index and size
ItkRegionType inputRegionOfInterest(index, size);
// PART 2: get access to the MITK output image via an ITK image
typename mitk::ImageToItk<ItkOutputImageType>::Pointer outputimagetoitk = mitk::ImageToItk<ItkOutputImageType>::New();
outputimagetoitk->SetInput(cutter->m_OutputTimeSelector->GetOutput());
outputimagetoitk->Update();
typename ItkOutputImageType::Pointer outputItkImage = outputimagetoitk->GetOutput();
// PART 3: iterate over input and output using ITK iterators
// create the iterators
ItkInputImageIteratorType inputIt( inputItkImage, inputRegionOfInterest );
ItkOutputImageIteratorType outputIt( outputItkImage, outputItkImage->GetLargestPossibleRegion() );
// Cut the boundingbox out of the image by iterating through
// all pixels and checking if they are inside using IsInside()
cutter->m_OutsidePixelCount = 0;
cutter->m_InsidePixelCount = 0;
mitk::Point3D p;
- mitk::Geometry3D* inputGeometry = cutter->GetInput()->GetGeometry();
+ mitk::BaseGeometry* inputGeometry = cutter->GetInput()->GetGeometry();
TOutputPixel outsideValue;
if(cutter->m_AutoOutsideValue)
{
outsideValue = itk::NumericTraits<TOutputPixel>::min();
}
else
{
outsideValue = (TOutputPixel) cutter->m_OutsideValue;
}
//shall we use a fixed value for each inside pixel?
if (cutter->GetUseInsideValue())
{
TOutputPixel insideValue = (TOutputPixel) cutter->m_InsideValue;
// yes, use a fixed value for each inside pixel (create a binary mask of the bounding object)
for ( inputIt.GoToBegin(), outputIt.GoToBegin(); !inputIt.IsAtEnd(); ++inputIt, ++outputIt)
{
vtk2itk(inputIt.GetIndex(), p);
inputGeometry->IndexToWorld(p, p);
if(cutter->m_BoundingObject->IsInside(p))
{
outputIt.Set(insideValue);
++cutter->m_InsidePixelCount;
}
else
{
outputIt.Set(outsideValue);
++cutter->m_OutsidePixelCount;
}
}
}
else
{
// no, use the pixel value of the original image (normal cutting)
for ( inputIt.GoToBegin(), outputIt.GoToBegin(); !inputIt.IsAtEnd(); ++inputIt, ++outputIt)
{
vtk2itk(inputIt.GetIndex(), p);
inputGeometry->IndexToWorld(p, p);
if(cutter->m_BoundingObject->IsInside(p))
{
outputIt.Set( (TOutputPixel) inputIt.Value() );
++cutter->m_InsidePixelCount;
}
else
{
outputIt.Set( outsideValue );
++cutter->m_OutsidePixelCount;
}
}
}
}
template < typename TPixel, unsigned int VImageDimension >
void CutImage( itk::Image< TPixel, VImageDimension >* inputItkImage, mitk::BoundingObjectCutter* cutter, int boTimeStep )
{
TPixel* dummy = NULL;
CutImageWithOutputTypeSelect<TPixel, VImageDimension, TPixel>(inputItkImage, cutter, boTimeStep, dummy);
}
} // of namespace mitk
#include "mitkImageCast.h"
#endif // of MITKBOUNDINGOBJECTCUTTER_TXX
diff --git a/Modules/AlgorithmsExt/mitkBoundingObjectToSegmentationFilter.cpp b/Modules/AlgorithmsExt/mitkBoundingObjectToSegmentationFilter.cpp
index a8e61637e1..09e089d73b 100644
--- a/Modules/AlgorithmsExt/mitkBoundingObjectToSegmentationFilter.cpp
+++ b/Modules/AlgorithmsExt/mitkBoundingObjectToSegmentationFilter.cpp
@@ -1,121 +1,121 @@
/*===================================================================
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 "mitkBoundingObjectToSegmentationFilter.h"
#include "mitkImageCast.h"
#include <itkImageRegionIteratorWithIndex.h>
mitk::BoundingObjectToSegmentationFilter::BoundingObjectToSegmentationFilter()
{
this->SetNumberOfRequiredInputs(1);
}
mitk::BoundingObjectToSegmentationFilter::~BoundingObjectToSegmentationFilter()
{
}
void mitk::BoundingObjectToSegmentationFilter::SetBoundingObject(mitk::BoundingObject::Pointer boundingObject)
{
mitk::BoundingObjectGroup* testgroup = dynamic_cast<mitk::BoundingObjectGroup*> (boundingObject.GetPointer());
if (testgroup)
m_boundingObjectGroup = testgroup;
else
{
m_boundingObjectGroup = mitk::BoundingObjectGroup::New();
m_boundingObjectGroup->AddBoundingObject(boundingObject);
}
}
void mitk::BoundingObjectToSegmentationFilter::GenerateData()
{
typedef itk::Image<unsigned char, 3> itkImageType;
mitk::Image::Pointer outputImage = this->GetOutput();
mitk::Image::ConstPointer inputImage = this->GetInput();
outputImage->Initialize(inputImage);
itkImageType::Pointer itkImage;
CastToItkImage(outputImage, itkImage);
itkImage->FillBuffer(0);
for (unsigned int i=0; i<m_boundingObjectGroup->GetCount(); i++)
{
//create region for boundingobject
mitk::BoundingObject::Pointer boundingObject = m_boundingObjectGroup->GetBoundingObjects().at(i);
- mitk::Geometry3D::Pointer boGeometry = boundingObject->GetGeometry();
- mitk::Geometry3D::Pointer inputImageGeometry = inputImage->GetSlicedGeometry();
+ mitk::BaseGeometry::Pointer boGeometry = boundingObject->GetGeometry();
+ mitk::BaseGeometry::Pointer inputImageGeometry = inputImage->GetSlicedGeometry();
mitk::BoundingBox::Pointer boToIm = boGeometry->CalculateBoundingBoxRelativeToTransform(inputImageGeometry->GetIndexToWorldTransform());
mitk::BoundingBox::ConstPointer imgBB = inputImageGeometry->GetBoundingBox();
mitk::BoundingBox::PointType minImg = imgBB->GetMinimum();
mitk::BoundingBox::PointType maxImg = imgBB->GetMaximum();
itkImageType::IndexType boIndex;
itkImageType::SizeType boSize;
mitk::BoundingBox::PointType min = boToIm->GetMinimum();
mitk::BoundingBox::PointType max = boToIm->GetMaximum();
//check if boundingbox is inside imageregion
for (int i =0; i<3; i++)
{
if (min [i] < minImg[i])
min[i] = minImg[i];
if (max [i] < minImg[i])
max[i] = minImg[i];
if (max[i] > maxImg[i])
max[i] = maxImg[i];
if (min [i] > maxImg[i])
min[i] = maxImg[i]-1;
}
// add 0.5 (boGeometry is no image geometry)
boIndex[0] = (mitk::SlicedData::IndexType::IndexValueType)(min[0] + 0.5);
boIndex[1] = (mitk::SlicedData::IndexType::IndexValueType)(min[1] + 0.5);
boIndex[2] = (mitk::SlicedData::IndexType::IndexValueType)(min[2] + 0.5);
// add 1 because we need 0.5 for each index
boSize[0] = (mitk::SlicedData::IndexType::IndexValueType) (max[0]-min[0]);
boSize[1] = (mitk::SlicedData::IndexType::IndexValueType) (max[1]-min[1]);
boSize[2] = (mitk::SlicedData::IndexType::IndexValueType) (max[2]-min[2]);
itkImageType::RegionType region(boIndex, boSize);
//create region iterator
itk::ImageRegionIteratorWithIndex<itkImageType> itBoundingObject = itk::ImageRegionIteratorWithIndex<itkImageType>(itkImage, region );
itBoundingObject.GoToBegin();
while(!itBoundingObject.IsAtEnd())
{
itkImageType::IndexType index = itBoundingObject.GetIndex();
mitk::Point3D p;
p[0] = index[0];
p[1] = index[1];
p[2] = index[2];
inputImageGeometry->IndexToWorld(p,p);
if (boundingObject->IsInside(p) && boundingObject->GetPositive())
itBoundingObject.Set(1);
else if (boundingObject->IsInside(p) && !boundingObject->GetPositive())
itBoundingObject.Set(0);
++itBoundingObject;
}
}
CastToMitkImage(itkImage, outputImage);
}
diff --git a/Modules/AlgorithmsExt/mitkGeometryClipImageFilter.cpp b/Modules/AlgorithmsExt/mitkGeometryClipImageFilter.cpp
index dcce736a30..7fcaadd8bc 100644
--- a/Modules/AlgorithmsExt/mitkGeometryClipImageFilter.cpp
+++ b/Modules/AlgorithmsExt/mitkGeometryClipImageFilter.cpp
@@ -1,263 +1,263 @@
/*===================================================================
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 "mitkGeometryClipImageFilter.h"
#include "mitkImageTimeSelector.h"
#include "mitkTimeHelper.h"
#include "mitkProperties.h"
#include "mitkImageToItk.h"
#include "itkImageRegionConstIterator.h"
#include "itkImageRegionIteratorWithIndex.h"
#include <limits>
mitk::GeometryClipImageFilter::GeometryClipImageFilter()
: m_ClippingGeometry(NULL),
m_ClipPartAboveGeometry(true),
m_OutsideValue(0),
m_AutoOutsideValue(false),
m_LabelBothSides(false),
m_AutoOrientLabels(false),
m_AboveGeometryLabel(1),
m_BelowGeometryLabel(2)
{
this->SetNumberOfIndexedInputs(2);
this->SetNumberOfRequiredInputs(2);
m_InputTimeSelector = mitk::ImageTimeSelector::New();
m_OutputTimeSelector = mitk::ImageTimeSelector::New();
m_ClippingGeometryData = mitk::GeometryData::New();
}
mitk::GeometryClipImageFilter::~GeometryClipImageFilter()
{
}
void mitk::GeometryClipImageFilter::SetClippingGeometry(const mitk::TimeGeometry* timeClippingGeometry)
{
m_TimeClippingGeometry = timeClippingGeometry;
SetClippingGeometry(timeClippingGeometry->GetGeometryForTimeStep(0));
}
-void mitk::GeometryClipImageFilter::SetClippingGeometry(const mitk::Geometry3D* aClippingGeometry)
+void mitk::GeometryClipImageFilter::SetClippingGeometry(const mitk::BaseGeometry* aClippingGeometry)
{
if(aClippingGeometry != m_ClippingGeometry.GetPointer())
{
m_ClippingGeometry = aClippingGeometry;
- m_ClippingGeometryData->SetGeometry(const_cast<mitk::Geometry3D*>(aClippingGeometry));
+ m_ClippingGeometryData->SetGeometry(const_cast<mitk::BaseGeometry*>(aClippingGeometry));
SetNthInput(1, m_ClippingGeometryData);
Modified();
}
}
-const mitk::Geometry3D* mitk::GeometryClipImageFilter::GetClippingGeometry() const
+const mitk::BaseGeometry* mitk::GeometryClipImageFilter::GetClippingGeometry() const
{
return m_ClippingGeometry;
}
const mitk::TimeGeometry* mitk::GeometryClipImageFilter::GetClippingTimeGeometry() const
{
return m_TimeClippingGeometry;
}
void mitk::GeometryClipImageFilter::GenerateInputRequestedRegion()
{
Superclass::GenerateInputRequestedRegion();
mitk::Image* output = this->GetOutput();
mitk::Image* input = const_cast< mitk::Image * > ( this->GetInput() );
if((output->IsInitialized()==false) || (m_ClippingGeometry.IsNull()))
return;
input->SetRequestedRegionToLargestPossibleRegion();
GenerateTimeInInputRegion(output, input);
}
void mitk::GeometryClipImageFilter::GenerateOutputInformation()
{
mitk::Image::ConstPointer input = this->GetInput();
mitk::Image::Pointer output = this->GetOutput();
if ((output->IsInitialized()) && (this->GetMTime() <= m_TimeOfHeaderInitialization.GetMTime()))
return;
itkDebugMacro(<<"GenerateOutputInformation()");
unsigned int i;
unsigned int *tmpDimensions = new unsigned int[input->GetDimension()];
for(i=0;i<input->GetDimension();++i)
tmpDimensions[i]=input->GetDimension(i);
output->Initialize(input->GetPixelType(),
input->GetDimension(),
tmpDimensions,
input->GetNumberOfChannels());
delete [] tmpDimensions;
- output->SetGeometry(static_cast<mitk::Geometry3D*>(input->GetGeometry()->Clone().GetPointer()));
+ output->SetGeometry(static_cast<mitk::BaseGeometry*>(input->GetGeometry()->Clone().GetPointer()));
output->SetPropertyList(input->GetPropertyList()->Clone());
m_TimeOfHeaderInitialization.Modified();
}
template < typename TPixel, unsigned int VImageDimension >
-void mitk::_InternalComputeClippedImage(itk::Image<TPixel, VImageDimension>* inputItkImage, mitk::GeometryClipImageFilter* geometryClipper, const mitk::Geometry2D* clippingGeometry2D)
+void mitk::_InternalComputeClippedImage(itk::Image<TPixel, VImageDimension>* inputItkImage, mitk::GeometryClipImageFilter* geometryClipper, const mitk::PlaneGeometry* clippingPlaneGeometry)
{
typedef itk::Image<TPixel, VImageDimension> ItkInputImageType;
typedef itk::Image<TPixel, VImageDimension> ItkOutputImageType;
typedef itk::ImageRegionConstIteratorWithIndex< ItkInputImageType > ItkInputImageIteratorType;
typedef itk::ImageRegionIteratorWithIndex< ItkOutputImageType > ItkOutputImageIteratorType;
typename mitk::ImageToItk<ItkOutputImageType>::Pointer outputimagetoitk = mitk::ImageToItk<ItkOutputImageType>::New();
outputimagetoitk->SetInput(geometryClipper->m_OutputTimeSelector->GetOutput());
outputimagetoitk->Update();
typename ItkOutputImageType::Pointer outputItkImage = outputimagetoitk->GetOutput();
// create the iterators
typename ItkInputImageType::RegionType inputRegionOfInterest = inputItkImage->GetLargestPossibleRegion();
ItkInputImageIteratorType inputIt( inputItkImage, inputRegionOfInterest );
ItkOutputImageIteratorType outputIt( outputItkImage, inputRegionOfInterest );
typename ItkOutputImageType::PixelType outsideValue;
if(geometryClipper->m_AutoOutsideValue)
outsideValue = itk::NumericTraits<typename ItkOutputImageType::PixelType>::min();
else
outsideValue = (typename ItkOutputImageType::PixelType) geometryClipper->m_OutsideValue;
- mitk::Geometry3D* inputGeometry = geometryClipper->m_InputTimeSelector->GetOutput()->GetGeometry();
+ mitk::BaseGeometry* inputGeometry = geometryClipper->m_InputTimeSelector->GetOutput()->GetGeometry();
typedef itk::Index<VImageDimension> IndexType;
Point3D indexPt; indexPt.Fill(0);
int i, dim=IndexType::GetIndexDimension();
Point3D pointInMM;
bool above = geometryClipper->m_ClipPartAboveGeometry;
bool labelBothSides = geometryClipper->GetLabelBothSides();
if (geometryClipper->GetAutoOrientLabels())
{
Point3D leftMostPoint;
leftMostPoint.Fill( std::numeric_limits<float>::min() / 2.0 );
- if(clippingGeometry2D->IsAbove(pointInMM) != above)
+ if(clippingPlaneGeometry->IsAbove(pointInMM) != above)
{
// invert meaning of above --> left is always the "above" side
above = !above;
MITK_INFO << leftMostPoint << " is BELOW geometry. Inverting meaning of above" << std::endl;
}
else
MITK_INFO << leftMostPoint << " is above geometry" << std::endl;
}
typename ItkOutputImageType::PixelType aboveLabel = (typename ItkOutputImageType::PixelType)geometryClipper->GetAboveGeometryLabel();
typename ItkOutputImageType::PixelType belowLabel = (typename ItkOutputImageType::PixelType)geometryClipper->GetBelowGeometryLabel();
for ( inputIt.GoToBegin(), outputIt.GoToBegin(); !inputIt.IsAtEnd(); ++inputIt, ++outputIt)
{
if((typename ItkOutputImageType::PixelType)inputIt.Get() == outsideValue)
{
outputIt.Set(outsideValue);
}
else
{
for(i=0;i<dim;++i)
indexPt[i]=(mitk::ScalarType)inputIt.GetIndex()[i];
inputGeometry->IndexToWorld(indexPt, pointInMM);
- if(clippingGeometry2D->IsAbove(pointInMM) == above)
+ if(clippingPlaneGeometry->IsAbove(pointInMM) == above)
{
if ( labelBothSides )
outputIt.Set( aboveLabel );
else
outputIt.Set( outsideValue );
}
else
{
if ( labelBothSides)
outputIt.Set( belowLabel );
else
outputIt.Set( inputIt.Get() );
}
}
}
}
#include "mitkImageAccessByItk.h"
void mitk::GeometryClipImageFilter::GenerateData()
{
Image::ConstPointer input = this->GetInput();
Image::Pointer output = this->GetOutput();
if((output->IsInitialized()==false) || (m_ClippingGeometry.IsNull()))
return;
- const Geometry2D * clippingGeometryOfCurrentTimeStep = NULL;
+ const PlaneGeometry * clippingGeometryOfCurrentTimeStep = NULL;
if(m_TimeClippingGeometry.IsNull())
{
- clippingGeometryOfCurrentTimeStep = dynamic_cast<const Geometry2D*>(m_ClippingGeometry.GetPointer());
+ clippingGeometryOfCurrentTimeStep = dynamic_cast<const PlaneGeometry*>(m_ClippingGeometry.GetPointer());
}
else
{
- clippingGeometryOfCurrentTimeStep = dynamic_cast<const Geometry2D*>(m_TimeClippingGeometry->GetGeometryForTimeStep(0).GetPointer());
+ clippingGeometryOfCurrentTimeStep = dynamic_cast<const PlaneGeometry*>(m_TimeClippingGeometry->GetGeometryForTimeStep(0).GetPointer());
}
if(clippingGeometryOfCurrentTimeStep == NULL)
return;
m_InputTimeSelector->SetInput(input);
m_OutputTimeSelector->SetInput(this->GetOutput());
mitk::Image::RegionType outputRegion = output->GetRequestedRegion();
const mitk::TimeGeometry *outputTimeGeometry = output->GetTimeGeometry();
const mitk::TimeGeometry *inputTimeGeometry = input->GetTimeGeometry();
ScalarType timeInMS;
int timestep=0;
int tstart=outputRegion.GetIndex(3);
int tmax=tstart+outputRegion.GetSize(3);
int t;
for(t=tstart;t<tmax;++t)
{
timeInMS = outputTimeGeometry->TimeStepToTimePoint( t );
timestep = inputTimeGeometry->TimePointToTimeStep( timeInMS );
m_InputTimeSelector->SetTimeNr(timestep);
m_InputTimeSelector->UpdateLargestPossibleRegion();
m_OutputTimeSelector->SetTimeNr(t);
m_OutputTimeSelector->UpdateLargestPossibleRegion();
if(m_TimeClippingGeometry.IsNotNull())
{
timestep = m_TimeClippingGeometry->TimePointToTimeStep( timeInMS );
if(m_TimeClippingGeometry->IsValidTimeStep(timestep) == false)
continue;
- clippingGeometryOfCurrentTimeStep = dynamic_cast<const Geometry2D*>(m_TimeClippingGeometry->GetGeometryForTimeStep(timestep).GetPointer());
+ clippingGeometryOfCurrentTimeStep = dynamic_cast<const PlaneGeometry*>(m_TimeClippingGeometry->GetGeometryForTimeStep(timestep).GetPointer());
}
AccessByItk_2(m_InputTimeSelector->GetOutput(),_InternalComputeClippedImage,this,clippingGeometryOfCurrentTimeStep);
}
m_TimeOfHeaderInitialization.Modified();
}
diff --git a/Modules/AlgorithmsExt/mitkGeometryClipImageFilter.h b/Modules/AlgorithmsExt/mitkGeometryClipImageFilter.h
index b25314fbfc..ee573543eb 100644
--- a/Modules/AlgorithmsExt/mitkGeometryClipImageFilter.h
+++ b/Modules/AlgorithmsExt/mitkGeometryClipImageFilter.h
@@ -1,181 +1,181 @@
/*===================================================================
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 MITKGEOMETRYCLIPIMAGEFILTER_H_HEADER_INCLUDED_C1F48A22
#define MITKGEOMETRYCLIPIMAGEFILTER_H_HEADER_INCLUDED_C1F48A22
#include "mitkCommon.h"
#include "MitkAlgorithmsExtExports.h"
#include "mitkImageToImageFilter.h"
#include "mitkImageTimeSelector.h"
#include "mitkGeometryData.h"
namespace itk {
template <class TPixel, unsigned int VImageDimension> class ITK_EXPORT Image;
}
namespace mitk {
//##Documentation
-//## @brief Filter for clipping an image with a Geometry2D
+//## @brief Filter for clipping an image with a PlaneGeometry
//##
-//## The given geometry for clipping can be either a Geometry2D
+//## The given geometry for clipping can be either a PlaneGeometry
//## or a TimeGeometry containing multiple instances
-//## of Geometry2D
+//## of PlaneGeometry
//##
//## \todo add AutoOrientLabels, which makes the "left" side (minimum X value) side of the image get one defined label.
//## left-most because vtkPolyDataNormals uses the same definition and this filter is used for visualization of
//## front/back side of curved planes
//##
//## @ingroup Process
class MitkAlgorithmsExt_EXPORT GeometryClipImageFilter : public ImageToImageFilter
{
public:
mitkClassMacro(GeometryClipImageFilter, ImageToImageFilter);
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/**
* Set the geometry to be used for clipping
*
- * The given geometry for clipping must be a Geometry2D.
+ * The given geometry for clipping must be a PlaneGeometry.
*/
- void SetClippingGeometry(const mitk::Geometry3D* aClippingGeometry);
+ void SetClippingGeometry(const mitk::BaseGeometry* aClippingGeometry);
/**
* Set the geometry to be used for clipping
*
* The given geometry for clipping must a
* TimeGeometry containing multiple instances
- * of Geometry2D
+ * of PlaneGeometry
*/
void SetClippingGeometry(const mitk::TimeGeometry* aClippingGeometry);
- const mitk::Geometry3D* GetClippingGeometry() const;
+ const mitk::BaseGeometry* GetClippingGeometry() const;
const mitk::TimeGeometry* GetClippingTimeGeometry() const;
//##Description
//## @brief Get whether the part above or below the geometry
//## shall be clipped (default: @a true)
itkGetConstMacro(ClipPartAboveGeometry, bool);
//## @brief Set whether the part above or below the geometry
//## shall be clipped (default: @a true)
itkSetMacro(ClipPartAboveGeometry, bool);
//## @brief Set whether the part above or below the geometry
//## shall be clipped (default: @a true)
itkBooleanMacro(ClipPartAboveGeometry);
//##Description
//## @brief Set value for outside pixels (default: 0),
//## used when m_AutoOutsideValue is \a false
itkSetMacro(OutsideValue, ScalarType);
itkGetConstMacro(OutsideValue, ScalarType);
//##Description
//## @brief If set to \a true the minimum of the ouput pixel type is
//## used as outside value (default: \a false)
itkSetMacro(AutoOutsideValue, bool);
itkGetConstMacro(AutoOutsideValue, bool);
itkBooleanMacro(AutoOutsideValue);
itkSetMacro(AutoOrientLabels, bool);
itkGetConstMacro(AutoOrientLabels, bool);
//##Description
//## @brief If set to \a true both sides of the clipping
//## geometry will be labeld using m_AboveGeometryLabel and
//## m_BelowGeometryLabel
itkSetMacro(LabelBothSides, bool);
itkGetConstMacro(LabelBothSides, bool);
itkBooleanMacro(LabelBothSides);
//##Description
//## @brief Set for voxels above the clipping geometry.
//## This value is only used, if m_LabelBothSides is set to true.
itkSetMacro(AboveGeometryLabel, ScalarType);
itkGetConstMacro(AboveGeometryLabel, ScalarType);
//##Description
//## @brief Set for voxels below the clipping geometry.
//## This value is only used, if m_LabelBothSides is set to true.
itkSetMacro(BelowGeometryLabel, ScalarType);
itkGetConstMacro(BelowGeometryLabel, ScalarType);
protected:
GeometryClipImageFilter();
~GeometryClipImageFilter();
virtual void GenerateInputRequestedRegion();
virtual void GenerateOutputInformation();
virtual void GenerateData();
template < typename TPixel, unsigned int VImageDimension >
- friend void _InternalComputeClippedImage(itk::Image<TPixel, VImageDimension>* itkImage, mitk::GeometryClipImageFilter* geometryClipper, const mitk::Geometry2D* clippingGeometry2D);
+ friend void _InternalComputeClippedImage(itk::Image<TPixel, VImageDimension>* itkImage, mitk::GeometryClipImageFilter* geometryClipper, const mitk::PlaneGeometry* clippingPlaneGeometry);
- mitk::Geometry3D::ConstPointer m_ClippingGeometry;
+ mitk::BaseGeometry::ConstPointer m_ClippingGeometry;
mitk::GeometryData::Pointer m_ClippingGeometryData;
mitk::TimeGeometry::ConstPointer m_TimeClippingGeometry;
mitk::ImageTimeSelector::Pointer m_InputTimeSelector;
mitk::ImageTimeSelector::Pointer m_OutputTimeSelector;
//##Description
//## @brief Defines whether the part above or below the geometry
//## shall be clipped (default: @a true)
bool m_ClipPartAboveGeometry;
//##Description
//## @brief Value for outside pixels (default: 0)
//##
//## Used only if m_AutoOutsideValue is \a false.
ScalarType m_OutsideValue;
//##Description
//## @brief If \a true the minimum of the ouput pixel type is
//## used as outside value (default: \a false)
bool m_AutoOutsideValue;
//##Description
//## @brief If \a true all pixels above and below the geometry
//## are labeled with m_AboveGeometryLabel and m_BelowGeometryLabel
bool m_LabelBothSides;
/**
* \brief Orient above like vtkPolyDataNormals does with AutoOrientNormals
*/
bool m_AutoOrientLabels;
//##Description
//## @brief Is used for labeling all pixels above the geometry
//## when m_LabelBothSides is on
ScalarType m_AboveGeometryLabel;
//##Description
//## @brief Is used for labeling all pixels below the geometry
//## when m_LabelBothSides is on
ScalarType m_BelowGeometryLabel;
//##Description
//## @brief Time when Header was last initialized
itk::TimeStamp m_TimeOfHeaderInitialization;
};
} // namespace mitk
#endif /* MITKGEOMETRYCLIPIMAGEFILTER_H_HEADER_INCLUDED_C1F48A22 */
diff --git a/Modules/AlgorithmsExt/mitkHeightFieldSurfaceClipImageFilter.cpp b/Modules/AlgorithmsExt/mitkHeightFieldSurfaceClipImageFilter.cpp
index 55e85258b1..f52d9dbef1 100644
--- a/Modules/AlgorithmsExt/mitkHeightFieldSurfaceClipImageFilter.cpp
+++ b/Modules/AlgorithmsExt/mitkHeightFieldSurfaceClipImageFilter.cpp
@@ -1,465 +1,465 @@
/*===================================================================
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 "mitkHeightFieldSurfaceClipImageFilter.h"
#include "mitkImageTimeSelector.h"
#include "mitkTimeHelper.h"
#include "mitkProperties.h"
#include "mitkImageToItk.h"
#include "mitkImageAccessByItk.h"
#include <itkImageRegionConstIterator.h>
#include <itkImageRegionIteratorWithIndex.h>
#include <itkImageSliceConstIteratorWithIndex.h>
#include <vtkPolyData.h>
#include <vtkCellLocator.h>
#include <limits>
namespace mitk
{
HeightFieldSurfaceClipImageFilter::HeightFieldSurfaceClipImageFilter()
: m_ClippingMode( CLIPPING_MODE_CONSTANT ),
m_ClippingConstant( 0.0 ),
m_MultiplicationFactor( 2.0 ),
m_MultiPlaneValue(2),
m_HeightFieldResolutionX( 256 ),
m_HeightFieldResolutionY( 256 ),
m_MaxHeight( 1024.0 )
{
this->SetNumberOfIndexedInputs(8);
this->SetNumberOfRequiredInputs(2);
m_InputTimeSelector = ImageTimeSelector::New();
m_OutputTimeSelector = ImageTimeSelector::New();
}
HeightFieldSurfaceClipImageFilter::~HeightFieldSurfaceClipImageFilter()
{
}
void HeightFieldSurfaceClipImageFilter::SetClippingSurface(
Surface *clippingSurface )
{
this->SetNthInput( 1, clippingSurface );
}
void HeightFieldSurfaceClipImageFilter::SetClippingSurfaces(ClippingPlaneList planeList)
{
if(planeList.size() > 7)
{
MITK_WARN<<"Only 7 clipping planes are allowed!";
}
for (unsigned int i = 0; i < planeList.size(); ++i)
{
this->SetNthInput(i+1, planeList.at(i));
}
}
const Surface* HeightFieldSurfaceClipImageFilter::GetClippingSurface() const
{
return dynamic_cast< const Surface * >( itk::ProcessObject::GetInput( 1 ) );
}
void HeightFieldSurfaceClipImageFilter::SetClippingMode( int mode )
{
m_ClippingMode = mode;
}
int HeightFieldSurfaceClipImageFilter::GetClippingMode()
{
return m_ClippingMode;
}
void HeightFieldSurfaceClipImageFilter::SetClippingModeToConstant()
{
m_ClippingMode = CLIPPING_MODE_CONSTANT;
}
void HeightFieldSurfaceClipImageFilter::SetClippingModeToMultiplyByFactor()
{
m_ClippingMode = CLIPPING_MODE_MULTIPLYBYFACTOR;
}
void HeightFieldSurfaceClipImageFilter::SetClippingModeToMultiPlaneValue()
{
m_ClippingMode = CLIPPING_MODE_MULTIPLANE;
}
void HeightFieldSurfaceClipImageFilter::GenerateInputRequestedRegion()
{
Image *outputImage = this->GetOutput();
Image *inputImage = const_cast< Image * >( this->GetInput( 0 ) );
const Surface *inputSurface = dynamic_cast< const Surface * >( this->GetInput( 1 ) );
if ( !outputImage->IsInitialized() || inputSurface == NULL )
{
return;
}
inputImage->SetRequestedRegionToLargestPossibleRegion();
GenerateTimeInInputRegion( outputImage, inputImage );
}
void HeightFieldSurfaceClipImageFilter::GenerateOutputInformation()
{
const Image *inputImage = this->GetInput( 0 );
Image *outputImage = this->GetOutput();
if ( outputImage->IsInitialized()
&& (this->GetMTime() <= m_TimeOfHeaderInitialization.GetMTime()) )
{
return;
}
itkDebugMacro(<<"GenerateOutputInformation()");
unsigned int i;
unsigned int *tmpDimensions = new unsigned int[inputImage->GetDimension()];
for ( i = 0; i < inputImage->GetDimension(); ++i )
{
tmpDimensions[i] = inputImage->GetDimension( i );
}
outputImage->Initialize( inputImage->GetPixelType(),
inputImage->GetDimension(),
tmpDimensions,
inputImage->GetNumberOfChannels() );
delete[] tmpDimensions;
outputImage->SetGeometry(
static_cast< Geometry3D * >( inputImage->GetGeometry()->Clone().GetPointer() ) );
outputImage->SetPropertyList( inputImage->GetPropertyList()->Clone() );
m_TimeOfHeaderInitialization.Modified();
}
template < typename TPixel, unsigned int VImageDimension >
void HeightFieldSurfaceClipImageFilter::_InternalComputeClippedImage(
itk::Image< TPixel, VImageDimension > *inputItkImage,
HeightFieldSurfaceClipImageFilter *clipImageFilter,
vtkPolyData *clippingPolyData,
AffineTransform3D *imageToPlaneTransform )
{
typedef itk::Image< TPixel, VImageDimension > ItkInputImageType;
typedef itk::Image< TPixel, VImageDimension > ItkOutputImageType;
typedef itk::ImageSliceConstIteratorWithIndex< ItkInputImageType > ItkInputImageIteratorType;
typedef itk::ImageRegionIteratorWithIndex< ItkOutputImageType > ItkOutputImageIteratorType;
typename ImageToItk<ItkOutputImageType >::Pointer outputimagetoitk =
ImageToItk<ItkOutputImageType>::New();
outputimagetoitk->SetInput( clipImageFilter->m_OutputTimeSelector->GetOutput() );
outputimagetoitk->Update();
typename ItkOutputImageType::Pointer outputItkImage = outputimagetoitk->GetOutput();
std::vector< double > test;
// create the iterators
typename ItkInputImageType::RegionType inputRegionOfInterest =
inputItkImage->GetLargestPossibleRegion();
ItkInputImageIteratorType inputIt( inputItkImage, inputRegionOfInterest );
ItkOutputImageIteratorType outputIt( outputItkImage, inputRegionOfInterest );
// Get bounds of clipping data
clippingPolyData->ComputeBounds();
double *bounds = clippingPolyData->GetBounds();
double xWidth = bounds[1] - bounds[0];
double yWidth = bounds[3] - bounds[2];
// Create vtkCellLocator for clipping poly data
vtkCellLocator *cellLocator = vtkCellLocator::New();
cellLocator->SetDataSet( clippingPolyData );
cellLocator->CacheCellBoundsOn();
cellLocator->AutomaticOn();
cellLocator->BuildLocator();
// Allocate memory for 2D image to hold the height field generated by
// projecting the clipping data onto the plane
double *heightField = new double[m_HeightFieldResolutionX * m_HeightFieldResolutionY];
// Walk through height field and for each entry calculate height of the
// clipping poly data at this point by means of vtkCellLocator. The
// clipping data x/y bounds are used for converting from poly data space to
// image (height-field) space.
MITK_INFO << "Calculating Height Field..." << std::endl;
for ( unsigned int y = 0; y < m_HeightFieldResolutionY; ++y )
{
for ( unsigned int x = 0; x < m_HeightFieldResolutionX; ++x )
{
double p0[3], p1[3], surfacePoint[3], pcoords[3];
p0[0] = bounds[0] + xWidth * x / (double) m_HeightFieldResolutionX;
p0[1] = bounds[2] + yWidth * y / (double) m_HeightFieldResolutionY;
p0[2] = -m_MaxHeight;
p1[0] = p0[0];
p1[1] = p0[1];
p1[2] = m_MaxHeight;
double t, distance;
int subId;
if ( cellLocator->IntersectWithLine( p0, p1, 0.1, t, surfacePoint, pcoords, subId ) )
{
distance = (2.0 * t - 1.0) * m_MaxHeight;
}
else
{
distance = -65536.0;
}
heightField[y * m_HeightFieldResolutionX + x] = distance;
itk::Image<double,2>::IndexType index;
index[0] = x;
index[1] = y;
}
}
// Walk through entire input image and for each point determine its distance
// from the x/y plane.
MITK_INFO << "Performing clipping..." << std::endl;
TPixel factor = static_cast< TPixel >( clipImageFilter->m_MultiplicationFactor );
TPixel clippingConstant = clipImageFilter->m_ClippingConstant;
inputIt.SetFirstDirection( 0 );
inputIt.SetSecondDirection( 1 );
//through all slices
for ( inputIt.GoToBegin(), outputIt.GoToBegin();
!inputIt.IsAtEnd();
inputIt.NextSlice() )
{
//through all lines of a slice
for ( ; !inputIt.IsAtEndOfSlice(); inputIt.NextLine() )
{
//Transform the start(line) point from the image to the plane
Point3D imageP0, planeP0;
imageP0[0] = inputIt.GetIndex()[0];
imageP0[1] = inputIt.GetIndex()[1];
imageP0[2] = inputIt.GetIndex()[2];
planeP0 = imageToPlaneTransform->TransformPoint( imageP0 );
//Transform the end point (line) from the image to the plane
Point3D imageP1, planeP1;
imageP1[0] = imageP0[0] + inputRegionOfInterest.GetSize( 0 );
imageP1[1] = imageP0[1];
imageP1[2] = imageP0[2];
planeP1 = imageToPlaneTransform->TransformPoint( imageP1 );
//calculate the step size (if the plane is rotate, you go "crossway" through the image)
Vector3D step = (planeP1 - planeP0) / (double) inputRegionOfInterest.GetSize( 0 );
//over all pixel
for ( ; !inputIt.IsAtEndOfLine(); ++inputIt, ++outputIt, planeP0 += step )
{
//Only ConstantMode: if image pixel value == constant mode value-->set output pixel value directly
if ( (clipImageFilter->m_ClippingMode == CLIPPING_MODE_CONSTANT)
&& ((TPixel)inputIt.Get() == clippingConstant ) )
{
outputIt.Set( clippingConstant );
}
else
{
int x0 = (int) ((double)(m_HeightFieldResolutionX) * (planeP0[0] - bounds[0]) / xWidth);
int y0 = (int) ((double)(m_HeightFieldResolutionY) * (planeP0[1] - bounds[2]) / yWidth);
bool clip;
//if the current point is outside of the plane region (RegionOfInterest)-->clip the pixel allways
if ( (x0 < 0) || (x0 >= (int)m_HeightFieldResolutionX)
|| (y0 < 0) || (y0 >= (int)m_HeightFieldResolutionY) )
{
clip = true;
}
else
{
// Calculate bilinearly interpolated height field value at plane point
int x1 = x0 + 1;
int y1 = y0 + 1;
if ( x1 >= (int)m_HeightFieldResolutionX ) { x1 = x0; }
if ( y1 >= (int)m_HeightFieldResolutionY ) { y1 = y0; }
//Get the neighbour points for the interpolation
ScalarType q00, q01, q10, q11;
q00 = heightField[y0 * m_HeightFieldResolutionX + x0];
q01 = heightField[y0 * m_HeightFieldResolutionX + x1];
q10 = heightField[y1 * m_HeightFieldResolutionX + x0];
q11 = heightField[y1 * m_HeightFieldResolutionX + x1];
double p00 = ((double)(m_HeightFieldResolutionX) * (planeP0[0] - bounds[0]) / xWidth);
double p01 = ((double)(m_HeightFieldResolutionY) * (planeP0[1] - bounds[2]) / yWidth);
ScalarType q =
q00 * ((double) x1 - p00) * ((double) y1 - p01)
+ q01 * (p00 - (double) x0) * ((double) y1 - p01)
+ q10 * ((double) x1 - p00) * (p01 - (double) y0)
+ q11 * (p00 - (double) x0) * (p01 - (double) y0);
if ( q - planeP0[2] < 0 )
{
clip = true;
}
else
{
clip = false;
}
}
//different modes: differnt values for the clipped pixel
if ( clip )
{
if ( clipImageFilter->m_ClippingMode == CLIPPING_MODE_CONSTANT )
{
outputIt.Set( clipImageFilter->m_ClippingConstant );
}
else if ( clipImageFilter->m_ClippingMode == CLIPPING_MODE_MULTIPLYBYFACTOR )
{
outputIt.Set( inputIt.Get() * factor );
}
else if ( clipImageFilter->m_ClippingMode == CLIPPING_MODE_MULTIPLANE )
{
if(inputIt.Get() != 0)
outputIt.Set( inputIt.Get() + m_MultiPlaneValue);
else
outputIt.Set( inputIt.Get() );
}
}
// the non-clipped pixel keeps his value
else
{
outputIt.Set( inputIt.Get() );
}
}
}
}
}
MITK_INFO << "DONE!" << std::endl;
// Clean-up
cellLocator->Delete();
}
void HeightFieldSurfaceClipImageFilter::GenerateData()
{
const Image *inputImage = this->GetInput( 0 );
const Image *outputImage = this->GetOutput();
m_InputTimeSelector->SetInput( inputImage );
m_OutputTimeSelector->SetInput( outputImage );
Image::RegionType outputRegion = outputImage->GetRequestedRegion();
const TimeGeometry *outputTimeGeometry = outputImage->GetTimeGeometry();
const TimeGeometry *inputTimeGeometry = inputImage->GetTimeGeometry();
ScalarType timeInMS;
int timestep = 0;
int tstart = outputRegion.GetIndex( 3 );
int tmax = tstart + outputRegion.GetSize( 3 );
for (unsigned int i = 1; i < this->GetNumberOfInputs(); ++i)
{
Surface *inputSurface = const_cast< Surface * >(
dynamic_cast< Surface * >( itk::ProcessObject::GetInput( i ) ) );
if ( !outputImage->IsInitialized() || inputSurface == NULL )
return;
MITK_INFO<<"Plane: "<<i;
MITK_INFO << "Clipping: Start\n";
- //const Geometry2D *clippingGeometryOfCurrentTimeStep = NULL;
+ //const PlaneGeometry *clippingGeometryOfCurrentTimeStep = NULL;
int t;
for( t = tstart; t < tmax; ++t )
{
timeInMS = outputTimeGeometry->TimeStepToTimePoint( t );
timestep = inputTimeGeometry->TimePointToTimeStep( timeInMS );
m_InputTimeSelector->SetTimeNr( timestep );
m_InputTimeSelector->UpdateLargestPossibleRegion();
m_OutputTimeSelector->SetTimeNr( t );
m_OutputTimeSelector->UpdateLargestPossibleRegion();
// Compose IndexToWorld transform of image with WorldToIndexTransform of
// clipping data for conversion from image index space to plane index space
AffineTransform3D::Pointer planeWorldToIndexTransform = AffineTransform3D::New();
inputSurface->GetGeometry( t )->GetIndexToWorldTransform()
->GetInverse( planeWorldToIndexTransform );
AffineTransform3D::Pointer imageToPlaneTransform =
AffineTransform3D::New();
imageToPlaneTransform->SetIdentity();
imageToPlaneTransform->Compose(
inputTimeGeometry->GetGeometryForTimeStep( t )->GetIndexToWorldTransform() );
imageToPlaneTransform->Compose( planeWorldToIndexTransform );
MITK_INFO << "Accessing ITK function...\n";
if(i==1)
{
AccessByItk_3(
m_InputTimeSelector->GetOutput(),
_InternalComputeClippedImage,
this,
inputSurface->GetVtkPolyData( t ),
imageToPlaneTransform );
}
else
{
mitk::Image::Pointer extensionImage = m_OutputTimeSelector->GetOutput()->Clone();
AccessByItk_3(
extensionImage,
_InternalComputeClippedImage,
this,
inputSurface->GetVtkPolyData( t ),
imageToPlaneTransform );
}
if (m_ClippingMode == CLIPPING_MODE_MULTIPLANE)
m_MultiPlaneValue = m_MultiPlaneValue*2;
}
}
m_TimeOfHeaderInitialization.Modified();
}
} // namespace
diff --git a/Modules/AlgorithmsExt/mitkLabeledImageToSurfaceFilter.cpp b/Modules/AlgorithmsExt/mitkLabeledImageToSurfaceFilter.cpp
index abeee6c26b..6e08103e14 100644
--- a/Modules/AlgorithmsExt/mitkLabeledImageToSurfaceFilter.cpp
+++ b/Modules/AlgorithmsExt/mitkLabeledImageToSurfaceFilter.cpp
@@ -1,362 +1,362 @@
/*===================================================================
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 <mitkLabeledImageToSurfaceFilter.h>
#include <vtkImageChangeInformation.h>
#include <vtkImageThreshold.h>
#include <vtkImageGaussianSmooth.h>
#include <vtkImageMarchingCubes.h>
#include <vtkPolyData.h>
#include <vtkSmoothPolyDataFilter.h>
#include <vtkDecimatePro.h>
#include <vtkLinearTransform.h>
#include <vtkMatrix4x4.h>
#include <mitkImageAccessByItk.h>
#include <mitkInstantiateAccessFunctions.h>
#include <itkImageRegionIterator.h>
#include <itkNumericTraits.h>
mitk::LabeledImageToSurfaceFilter::LabeledImageToSurfaceFilter() :
m_GaussianStandardDeviation(1.5),
m_GenerateAllLabels(true),
m_Label(1),
m_BackgroundLabel(0)
{
}
mitk::LabeledImageToSurfaceFilter::~LabeledImageToSurfaceFilter()
{
}
void mitk::LabeledImageToSurfaceFilter::GenerateOutputInformation()
{
Superclass::GenerateOutputInformation();
//
// check which labels are available in the image
//
m_AvailableLabels = this->GetAvailableLabels();
m_IdxToLabels.clear();
//
// if we don't want to generate surfaces for all labels
// we have to remove all labels except m_Label and m_BackgroundLabel
// from the list of available labels
//
if ( ! m_GenerateAllLabels )
{
LabelMapType tmp;
LabelMapType::iterator it;
it = m_AvailableLabels.find( m_Label );
if ( it != m_AvailableLabels.end() )
tmp[m_Label] = it->second;
else
tmp[m_Label] = 0;
it = m_AvailableLabels.find( m_BackgroundLabel );
if ( it != m_AvailableLabels.end() )
tmp[m_BackgroundLabel] = it->second;
else
tmp[m_BackgroundLabel] = 0;
m_AvailableLabels = tmp;
}
//
// check for the number of labels: if the whole image is filled, no
// background is available and thus the numberOfOutpus is equal to the
// number of available labels in the image (which is a special case).
// If we have background voxels, the number of outputs is one less than
// then number of available labels.
//
unsigned int numberOfOutputs = 0;
if ( m_AvailableLabels.find( m_BackgroundLabel ) == m_AvailableLabels.end() )
numberOfOutputs = m_AvailableLabels.size();
else
numberOfOutputs = m_AvailableLabels.size() - 1;
if ( numberOfOutputs == 0 )
{
itkWarningMacro("Number of outputs == 0");
}
//
// determine the number of time steps of the input image
//
mitk::Image* image = ( mitk::Image* )GetInput();
unsigned int numberOfTimeSteps = image->GetTimeGeometry()->CountTimeSteps();
//
// set the number of outputs to the number of labels used.
// initialize the output surfaces accordingly (incl. time steps)
//
this->SetNumberOfIndexedOutputs( numberOfOutputs );
this->SetNumberOfRequiredOutputs( numberOfOutputs );
for ( unsigned int i = 0 ; i < numberOfOutputs; ++i )
{
if ( ! this->GetOutput( i ) )
{
mitk::Surface::Pointer output = static_cast<mitk::Surface*>( this->MakeOutput(0).GetPointer() );
assert ( output.IsNotNull() );
output->Expand( numberOfTimeSteps );
this->SetNthOutput( i, output.GetPointer() );
}
}
}
void mitk::LabeledImageToSurfaceFilter::GenerateData()
{
mitk::Image* image = ( mitk::Image* )GetInput();
if ( image == NULL )
{
itkWarningMacro("Image is NULL");
return;
}
mitk::Image::RegionType outputRegion = image->GetRequestedRegion();
m_IdxToLabels.clear();
if ( this->GetNumberOfOutputs() == 0 )
return;
//
// traverse the known labels and create surfaces for them.
//
unsigned int currentOutputIndex = 0;
for ( LabelMapType::iterator it = m_AvailableLabels.begin() ; it != m_AvailableLabels.end() ; ++it )
{
if ( it->first == m_BackgroundLabel )
continue;
if ( ( it->second == 0 ) && m_GenerateAllLabels )
continue;
assert ( currentOutputIndex < this->GetNumberOfOutputs() );
mitk::Surface::Pointer surface = this->GetOutput( currentOutputIndex );
assert( surface.IsNotNull() );
int tstart=outputRegion.GetIndex(3);
int tmax=tstart+outputRegion.GetSize(3); //GetSize()==1 - will aber 0 haben, wenn nicht zeitaufgeloet
int t;
for( t=tstart; t < tmax; ++t)
{
vtkImageData *vtkimagedata = image->GetVtkImageData( t );
CreateSurface( t,vtkimagedata,surface.GetPointer(), it->first );
}
m_IdxToLabels[ currentOutputIndex ] = it->first;
currentOutputIndex++;
}
}
void mitk::LabeledImageToSurfaceFilter::CreateSurface( int time, vtkImageData *vtkimage, mitk::Surface * surface, mitk::LabeledImageToSurfaceFilter::LabelType label )
{
vtkImageChangeInformation *indexCoordinatesImageFilter = vtkImageChangeInformation::New();
indexCoordinatesImageFilter->SetInputData(vtkimage);
indexCoordinatesImageFilter->SetOutputOrigin(0.0,0.0,0.0);
vtkImageThreshold* threshold = vtkImageThreshold::New();
threshold->SetInputConnection( indexCoordinatesImageFilter->GetOutputPort() );
//indexCoordinatesImageFilter->Delete();
threshold->SetInValue( 100 );
threshold->SetOutValue( 0 );
threshold->ThresholdBetween( label, label );
threshold->SetOutputScalarTypeToUnsignedChar();
threshold->ReleaseDataFlagOn();
vtkImageGaussianSmooth *gaussian = vtkImageGaussianSmooth::New();
gaussian->SetInputConnection( threshold->GetOutputPort() );
//threshold->Delete();
gaussian->SetDimensionality( 3 );
gaussian->SetRadiusFactor( 0.49 );
gaussian->SetStandardDeviation( GetGaussianStandardDeviation() );
gaussian->ReleaseDataFlagOn();
gaussian->UpdateInformation();
gaussian->Update();
//MarchingCube -->create Surface
vtkMarchingCubes *skinExtractor = vtkMarchingCubes::New();
skinExtractor->ReleaseDataFlagOn();
skinExtractor->SetInputConnection(gaussian->GetOutputPort());//RC++
indexCoordinatesImageFilter->Delete();
skinExtractor->SetValue(0, 50);
vtkPolyData *polydata;
skinExtractor->Update();
polydata = skinExtractor->GetOutput();
polydata->Register(NULL);//RC++
skinExtractor->Delete();
if (m_Smooth)
{
vtkSmoothPolyDataFilter *smoother = vtkSmoothPolyDataFilter::New();
//read poly1 (poly1 can be the original polygon, or the decimated polygon)
smoother->SetInputData(polydata);//RC++
smoother->SetNumberOfIterations( m_SmoothIteration );
smoother->SetRelaxationFactor( m_SmoothRelaxation );
smoother->SetFeatureAngle( 60 );
smoother->FeatureEdgeSmoothingOff();
smoother->BoundarySmoothingOff();
smoother->SetConvergence( 0 );
polydata->Delete();//RC--
smoother->Update();
polydata = smoother->GetOutput();
polydata->Register(NULL);//RC++
smoother->Delete();
}
//decimate = to reduce number of polygons
if(m_Decimate==DecimatePro)
{
vtkDecimatePro *decimate = vtkDecimatePro::New();
decimate->SplittingOff();
decimate->SetErrorIsAbsolute(5);
decimate->SetFeatureAngle(30);
decimate->PreserveTopologyOn();
decimate->BoundaryVertexDeletionOff();
decimate->SetDegree(10); //std-value is 25!
decimate->SetInputData(polydata);//RC++
decimate->SetTargetReduction(m_TargetReduction);
decimate->SetMaximumError(0.002);
polydata->Delete();//RC--
decimate->Update();
polydata = decimate->GetOutput();
polydata->Register(NULL);//RC++
decimate->Delete();
}
if(polydata->GetNumberOfPoints() > 0)
{
mitk::Vector3D spacing = GetInput()->GetGeometry(time)->GetSpacing();
vtkPoints * points = polydata->GetPoints();
vtkMatrix4x4 *vtkmatrix = vtkMatrix4x4::New();
GetInput()->GetGeometry(time)->GetVtkTransform()->GetMatrix(vtkmatrix);
double (*matrix)[4] = vtkmatrix->Element;
unsigned int i,j;
for(i=0;i<3;++i)
for(j=0;j<3;++j)
matrix[i][j]/=spacing[j];
unsigned int n = points->GetNumberOfPoints();
double point[3];
for (i = 0; i < n; i++)
{
points->GetPoint(i, point);
mitkVtkLinearTransformPoint(matrix,point,point);
points->SetPoint(i, point);
}
vtkmatrix->Delete();
}
surface->SetVtkPolyData(polydata, time);
polydata->UnRegister(NULL);
gaussian->Delete();
threshold->Delete();
}
template < typename TPixel, unsigned int VImageDimension >
void GetAvailableLabelsInternal( itk::Image<TPixel, VImageDimension>* image, mitk::LabeledImageToSurfaceFilter::LabelMapType& availableLabels )
{
typedef itk::Image<TPixel, VImageDimension> ImageType;
typedef itk::ImageRegionIterator< ImageType > ImageRegionIteratorType;
availableLabels.clear();
ImageRegionIteratorType it( image, image->GetLargestPossibleRegion() );
it.GoToBegin();
mitk::LabeledImageToSurfaceFilter::LabelMapType::iterator labelIt;
while( ! it.IsAtEnd() )
{
labelIt = availableLabels.find( ( mitk::LabeledImageToSurfaceFilter::LabelType ) ( it.Get() ) );
if ( labelIt == availableLabels.end() )
{
availableLabels[ ( mitk::LabeledImageToSurfaceFilter::LabelType ) ( it.Get() ) ] = 1;
}
else
{
labelIt->second += 1;
}
++it;
}
}
#define InstantiateAccessFunction_GetAvailableLabelsInternal(pixelType, dim) \
template void GetAvailableLabelsInternal(itk::Image<pixelType, dim>*, mitk::LabeledImageToSurfaceFilter::LabelMapType&);
InstantiateAccessFunctionForFixedDimension(GetAvailableLabelsInternal, 3);
mitk::LabeledImageToSurfaceFilter::LabelMapType mitk::LabeledImageToSurfaceFilter::GetAvailableLabels()
{
mitk::Image::Pointer image = ( mitk::Image* )GetInput();
LabelMapType availableLabels;
AccessFixedDimensionByItk_1( image, GetAvailableLabelsInternal, 3, availableLabels );
return availableLabels;
}
void mitk::LabeledImageToSurfaceFilter::CreateSurface(int, vtkImageData*, mitk::Surface*, const ScalarType)
{
itkWarningMacro( "This function should never be called!" );
assert(false);
}
mitk::LabeledImageToSurfaceFilter::LabelType mitk::LabeledImageToSurfaceFilter::GetLabelForNthOutput( const unsigned int& idx )
{
IdxToLabelMapType::iterator it = m_IdxToLabels.find( idx );
if ( it != m_IdxToLabels.end() )
{
return it->second;
}
else
{
itkWarningMacro( "Unknown index encountered: " << idx << ". There are " << this->GetNumberOfOutputs() << " outputs available." );
return itk::NumericTraits<LabelType>::max();
}
}
mitk::ScalarType mitk::LabeledImageToSurfaceFilter::GetVolumeForNthOutput( const unsigned int& i )
{
return GetVolumeForLabel( GetLabelForNthOutput( i ) );
}
mitk::ScalarType mitk::LabeledImageToSurfaceFilter::GetVolumeForLabel( const mitk::LabeledImageToSurfaceFilter::LabelType& label )
{
// get the image spacing
mitk::Image* image = ( mitk::Image* )GetInput();
- const float* spacing = image->GetSlicedGeometry()->GetFloatSpacing();
+ const mitk::Vector3D spacing = image->GetSlicedGeometry()->GetSpacing();
// get the number of voxels encountered for the given label,
// calculate the volume and return it.
LabelMapType::iterator it = m_AvailableLabels.find( label );
if ( it != m_AvailableLabels.end() )
{
return static_cast<float>(it->second) * ( spacing[0] * spacing[1] * spacing[2] / 1000.0f );
}
else
{
itkWarningMacro( "Unknown label encountered: " << label );
return 0.0;
}
}
diff --git a/Modules/AlgorithmsExt/mitkPadImageFilter.cpp b/Modules/AlgorithmsExt/mitkPadImageFilter.cpp
index 46dc40f6d5..8c1f134da6 100644
--- a/Modules/AlgorithmsExt/mitkPadImageFilter.cpp
+++ b/Modules/AlgorithmsExt/mitkPadImageFilter.cpp
@@ -1,113 +1,113 @@
/*===================================================================
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 "mitkPadImageFilter.h"
#include "mitkImageCast.h"
#include "itkBinaryThresholdImageFilter.h"
#include "itkConstantPadImageFilter.h"
mitk::PadImageFilter::PadImageFilter()
{
this->SetNumberOfIndexedInputs(2);
this->SetNumberOfRequiredInputs(2);
m_BinaryFilter = false;
m_PadConstant = -32766;
m_LowerThreshold = -32766;
m_UpperThreshold = -32765;
}
mitk::PadImageFilter::~PadImageFilter()
{
}
void mitk::PadImageFilter::GenerateData()
{
mitk::Image::ConstPointer image = this->GetInput( 0 );
mitk::Image::ConstPointer referenceImage = this->GetInput( 1 );
typedef itk::Image< short, 3 > ImageType;
ImageType::Pointer itkImage = ImageType::New();
mitk::CastToItkImage( image, itkImage );
- mitk::Geometry3D *imageGeometry = image->GetGeometry();
+ mitk::BaseGeometry *imageGeometry = image->GetGeometry();
mitk::Point3D origin = imageGeometry->GetOrigin();
mitk::Vector3D spacing = imageGeometry->GetSpacing();
- mitk::Geometry3D *referenceImageGeometry = referenceImage->GetGeometry();
+ mitk::BaseGeometry *referenceImageGeometry = referenceImage->GetGeometry();
mitk::Point3D referenceOrigin = referenceImageGeometry->GetOrigin();
double outputOrigin[3];
unsigned long padLowerBound[3];
unsigned long padUpperBound[3];
int i;
for ( i = 0; i < 3; ++i )
{
outputOrigin[i] = referenceOrigin[i];
padLowerBound[i] = static_cast< unsigned long >
((origin[i] - referenceOrigin[i]) / spacing[i] + 0.5);
padUpperBound[i] = referenceImage->GetDimension( i )
- image->GetDimension( i ) - padLowerBound[i];
}
// The origin of the input image is passed through the filter and used as
// output origin as well. Hence, it needs to be overwritten accordingly.
itkImage->SetOrigin( outputOrigin );
typedef itk::ConstantPadImageFilter< ImageType, ImageType > PadFilterType;
PadFilterType::Pointer padFilter = PadFilterType::New();
padFilter->SetInput( itkImage );
padFilter->SetConstant( m_PadConstant );
padFilter->SetPadLowerBound( padLowerBound );
padFilter->SetPadUpperBound( padUpperBound );
mitk::Image::Pointer outputImage = this->GetOutput();
// If the Binary flag is set, use an additional binary threshold filter after
// padding.
if ( m_BinaryFilter )
{
typedef itk::Image< unsigned char, 3 > BinaryImageType;
typedef itk::BinaryThresholdImageFilter< ImageType, BinaryImageType >
BinaryFilterType;
BinaryFilterType::Pointer binaryFilter = BinaryFilterType::New();
binaryFilter->SetInput( padFilter->GetOutput() );
binaryFilter->SetLowerThreshold( m_LowerThreshold );
binaryFilter->SetUpperThreshold( m_UpperThreshold );
binaryFilter->SetInsideValue( 1 );
binaryFilter->SetOutsideValue( 0 );
binaryFilter->Update();
mitk::CastToMitkImage( binaryFilter->GetOutput(), outputImage );
}
else
{
padFilter->Update();
mitk::CastToMitkImage( padFilter->GetOutput(), outputImage );
}
outputImage->SetRequestedRegionToLargestPossibleRegion();
}
diff --git a/Modules/ContourModel/Algorithms/mitkContourModelUtils.cpp b/Modules/ContourModel/Algorithms/mitkContourModelUtils.cpp
index 362fea39e9..f7b33aa3a0 100755
--- a/Modules/ContourModel/Algorithms/mitkContourModelUtils.cpp
+++ b/Modules/ContourModel/Algorithms/mitkContourModelUtils.cpp
@@ -1,210 +1,210 @@
/*===================================================================
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 "mitkContourModelUtils.h"
#include "mitkImageCast.h"
#include "mitkImageAccessByItk.h"
#include "mitkContourModel.h"
#include "itkCastImageFilter.h"
#include "mitkImage.h"
#include "mitkSurface.h"
#include "vtkPolyData.h"
#include "mitkContourModelToSurfaceFilter.h"
#include "vtkPolyDataToImageStencil.h"
#include "vtkImageStencil.h"
#include "mitkImageVtkAccessor.h"
#include "vtkSmartPointer.h"
#include "vtkImageData.h"
#include "vtkImageLogic.h"
#include "vtkPointData.h"
mitk::ContourModelUtils::ContourModelUtils()
{
}
mitk::ContourModelUtils::~ContourModelUtils()
{
}
mitk::ContourModel::Pointer mitk::ContourModelUtils::ProjectContourTo2DSlice(Image* slice, ContourModel* contourIn3D, bool itkNotUsed( correctionForIpSegmentation ), bool constrainToInside)
{
if ( !slice || !contourIn3D ) return NULL;
ContourModel::Pointer projectedContour = ContourModel::New();
projectedContour->Initialize(*contourIn3D);
- const Geometry3D* sliceGeometry = slice->GetGeometry();
+ const BaseGeometry* sliceGeometry = slice->GetGeometry();
int numberOfTimesteps = contourIn3D->GetTimeGeometry()->CountTimeSteps();
for(int currentTimestep = 0; currentTimestep < numberOfTimesteps; currentTimestep++)
{
ContourModel::VertexIterator iter = contourIn3D->Begin(currentTimestep);
ContourModel::VertexIterator end = contourIn3D->End(currentTimestep);
while( iter != end)
{
Point3D currentPointIn3D = (*iter)->Coordinates;
Point3D projectedPointIn2D;
projectedPointIn2D.Fill(0.0);
sliceGeometry->WorldToIndex( currentPointIn3D, projectedPointIn2D );
// MITK_INFO << "world point " << currentPointIn3D << " in index is " << projectedPointIn2D;
if ( !sliceGeometry->IsIndexInside( projectedPointIn2D ) && constrainToInside )
{
MITK_INFO << "**" << currentPointIn3D << " is " << projectedPointIn2D << " --> correct it (TODO)" << std::endl;
}
projectedContour->AddVertex( projectedPointIn2D, currentTimestep );
iter++;
}
}
return projectedContour;
}
-mitk::ContourModel::Pointer mitk::ContourModelUtils::BackProjectContourFrom2DSlice(const Geometry3D* sliceGeometry, ContourModel* contourIn2D, bool itkNotUsed( correctionForIpSegmentation ) )
+mitk::ContourModel::Pointer mitk::ContourModelUtils::BackProjectContourFrom2DSlice(const BaseGeometry* sliceGeometry, ContourModel* contourIn2D, bool itkNotUsed( correctionForIpSegmentation ) )
{
if ( !sliceGeometry || !contourIn2D ) return NULL;
ContourModel::Pointer worldContour = ContourModel::New();
worldContour->Initialize(*contourIn2D);
int numberOfTimesteps = contourIn2D->GetTimeGeometry()->CountTimeSteps();
for(int currentTimestep = 0; currentTimestep < numberOfTimesteps; currentTimestep++)
{
ContourModel::VertexIterator iter = contourIn2D->Begin(currentTimestep);
ContourModel::VertexIterator end = contourIn2D->End(currentTimestep);
while( iter != end)
{
Point3D currentPointIn2D = (*iter)->Coordinates;
Point3D worldPointIn3D;
worldPointIn3D.Fill(0.0);
sliceGeometry->IndexToWorld( currentPointIn2D, worldPointIn3D );
//MITK_INFO << "index " << currentPointIn2D << " world " << worldPointIn3D << std::endl;
worldContour->AddVertex( worldPointIn3D, currentTimestep );
iter++;
}
}
return worldContour;
}
void mitk::ContourModelUtils::FillContourInSlice( ContourModel* projectedContour, Image* sliceImage, int paintingPixelValue )
{
mitk::ContourModelUtils::FillContourInSlice(projectedContour, 0, sliceImage, paintingPixelValue);
}
void mitk::ContourModelUtils::FillContourInSlice( ContourModel* projectedContour, unsigned int timeStep, Image* sliceImage, int paintingPixelValue )
{
//create a surface of the input ContourModel
mitk::Surface::Pointer surface = mitk::Surface::New();
mitk::ContourModelToSurfaceFilter::Pointer contourModelFilter = mitk::ContourModelToSurfaceFilter::New();
contourModelFilter->SetInput(projectedContour);
contourModelFilter->Update();
surface = contourModelFilter->GetOutput();
// that's our vtkPolyData-Surface
vtkSmartPointer<vtkPolyData> surface2D = vtkSmartPointer<vtkPolyData>::New();
if (surface->GetVtkPolyData(timeStep) == NULL)
{
MITK_WARN << "No surface has been created from contour model. Add more points to fill contour in slice.";
return;
}
surface2D->SetPoints(surface->GetVtkPolyData(timeStep)->GetPoints());
surface2D->SetLines(surface->GetVtkPolyData(timeStep)->GetLines());
surface2D->Modified();
//surface2D->Update();
// prepare the binary image's voxel grid
vtkSmartPointer<vtkImageData> whiteImage =
vtkSmartPointer<vtkImageData>::New();
whiteImage->DeepCopy(sliceImage->GetVtkImageData());
// fill the image with foreground voxels:
unsigned char inval = 255;
unsigned char outval = 0;
vtkIdType count = whiteImage->GetNumberOfPoints();
for (vtkIdType i = 0; i < count; ++i)
{
whiteImage->GetPointData()->GetScalars()->SetTuple1(i, inval);
}
// polygonal data --> image stencil:
vtkSmartPointer<vtkPolyDataToImageStencil> pol2stenc =
vtkSmartPointer<vtkPolyDataToImageStencil>::New();
pol2stenc->SetTolerance(0);
pol2stenc->SetInputData(surface2D);
pol2stenc->Update();
// cut the corresponding white image and set the background:
vtkSmartPointer<vtkImageStencil> imgstenc =
vtkSmartPointer<vtkImageStencil>::New();
imgstenc->SetInputData(whiteImage);
imgstenc->SetStencilConnection(pol2stenc->GetOutputPort());
imgstenc->ReverseStencilOff();
imgstenc->SetBackgroundValue(outval);
imgstenc->Update();
//Fill according to painting value
vtkSmartPointer<vtkImageLogic> booleanOperation = vtkSmartPointer<vtkImageLogic>::New();
booleanOperation->SetInput2Data(sliceImage->GetVtkImageData());
booleanOperation->SetOperationToOr();
booleanOperation->SetOutputTrueValue(1.0);
if(paintingPixelValue == 1)
{
//COMBINE
//slice or stencil
booleanOperation->SetInputConnection(imgstenc->GetOutputPort());
booleanOperation->SetOperationToOr();
} else
{
//CUT
//slice and not(stencil)
vtkSmartPointer<vtkImageLogic> booleanOperationNOT = vtkSmartPointer<vtkImageLogic>::New();
booleanOperationNOT->SetInputConnection(imgstenc->GetOutputPort());
booleanOperationNOT->SetOperationToNot();
booleanOperationNOT->Update();
booleanOperation->SetInputConnection(booleanOperationNOT->GetOutputPort());
booleanOperation->SetOperationToAnd();
}
booleanOperation->Update();
//copy scalars to output image slice
sliceImage->SetVolume(booleanOperation->GetOutput()->GetScalarPointer());
}
diff --git a/Modules/ContourModel/Algorithms/mitkContourModelUtils.h b/Modules/ContourModel/Algorithms/mitkContourModelUtils.h
index 26ded28b24..a8d55a564c 100644
--- a/Modules/ContourModel/Algorithms/mitkContourModelUtils.h
+++ b/Modules/ContourModel/Algorithms/mitkContourModelUtils.h
@@ -1,77 +1,77 @@
/*===================================================================
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 mitkContourModelUtilshIncludett
#define mitkContourModelUtilshIncludett
#include "mitkImage.h"
#include <MitkContourModelExports.h>
#include "mitkContourModel.h"
#include <itkImage.h>
namespace mitk
{
/**
* \brief Helpful methods for working with contours and images
*
*
*/
class MitkContourModel_EXPORT ContourModelUtils : public itk::Object
{
public:
mitkClassMacro(ContourModelUtils, itk::Object);
/**
\brief Projects a contour onto an image point by point. Converts from world to index coordinates.
\param correctionForIpSegmentation adds 0.5 to x and y index coordinates (difference between ipSegmentation and MITK contours)
*/
static ContourModel::Pointer ProjectContourTo2DSlice(Image* slice, ContourModel* contourIn3D, bool correctionForIpSegmentation, bool constrainToInside);
/**
\brief Projects a slice index coordinates of a contour back into world coordinates.
\param correctionForIpSegmentation subtracts 0.5 to x and y index coordinates (difference between ipSegmentation and MITK contours)
*/
- static ContourModel::Pointer BackProjectContourFrom2DSlice(const Geometry3D* sliceGeometry, ContourModel* contourIn2D, bool correctionForIpSegmentation = false);
+ static ContourModel::Pointer BackProjectContourFrom2DSlice(const BaseGeometry* sliceGeometry, ContourModel* contourIn2D, bool correctionForIpSegmentation = false);
/**
\brief Fill a contour in a 2D slice with a specified pixel value at time step 0.
*/
static void FillContourInSlice( ContourModel* projectedContour, Image* sliceImage, int paintingPixelValue = 1 );
/**
\brief Fill a contour in a 2D slice with a specified pixel value at a given time step.
*/
static void FillContourInSlice( ContourModel* projectedContour, unsigned int timeStep, Image* sliceImage, int paintingPixelValue = 1 );
protected:
ContourModelUtils();
virtual ~ContourModelUtils();
};
}
#endif
diff --git a/Modules/ContourModel/Algorithms/mitkImageToContourModelFilter.h b/Modules/ContourModel/Algorithms/mitkImageToContourModelFilter.h
index d8bb7fbb83..4a57fe244b 100644
--- a/Modules/ContourModel/Algorithms/mitkImageToContourModelFilter.h
+++ b/Modules/ContourModel/Algorithms/mitkImageToContourModelFilter.h
@@ -1,75 +1,75 @@
/*===================================================================
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 _mitkImageToContourModelFilter_h__
#define _mitkImageToContourModelFilter_h__
#include "mitkCommon.h"
#include <MitkContourModelExports.h>
#include "mitkContourModel.h"
#include "mitkContourModelSource.h"
#include <mitkImage.h>
namespace mitk {
/**
*
* \brief Base class for all filters with mitk::Image as input and mitk::ContourModel
*
* \ingroup ContourModelFilters
* \ingroup Process
*/
class MitkContourModel_EXPORT ImageToContourModelFilter : public ContourModelSource
{
public:
mitkClassMacro(ImageToContourModelFilter, ContourModelSource);
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
typedef mitk::Image InputType;
using Superclass::SetInput;
virtual void SetInput( const InputType *input);
virtual void SetInput( unsigned int idx, const InputType * input);
const InputType* GetInput(void);
const InputType* GetInput(unsigned int idx);
protected:
ImageToContourModelFilter();
virtual ~ImageToContourModelFilter();
void GenerateData();
template<typename TPixel, unsigned int VImageDimension>
void Itk2DContourExtraction (itk::Image<TPixel, VImageDimension>* sliceImage);
private:
- const Geometry3D* m_SliceGeometry;
+ const BaseGeometry* m_SliceGeometry;
};
}
#endif
diff --git a/Modules/ContourModel/DataManagement/mitkContourModel.cpp b/Modules/ContourModel/DataManagement/mitkContourModel.cpp
index e269a20678..47b9ed2558 100644
--- a/Modules/ContourModel/DataManagement/mitkContourModel.cpp
+++ b/Modules/ContourModel/DataManagement/mitkContourModel.cpp
@@ -1,709 +1,709 @@
/*===================================================================
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 <mitkContourModel.h>
#include <mitkPlaneGeometry.h>
mitk::ContourModel::ContourModel() :
m_UpdateBoundingBox(true)
{
//set to initial state
this->InitializeEmpty();
}
mitk::ContourModel::ContourModel(const mitk::ContourModel &other) :
mitk::BaseData(other),
m_ContourSeries(other.m_ContourSeries),
m_lineInterpolation(other.m_lineInterpolation)
{
m_SelectedVertex = NULL;
}
mitk::ContourModel::~ContourModel()
{
m_SelectedVertex = NULL;
this->m_ContourSeries.clear();//TODO check destruction
}
void mitk::ContourModel::AddVertex(mitk::Point3D &vertex, int timestep)
{
if(!this->IsEmptyTimeStep(timestep) )
{
this->AddVertex(vertex, false, timestep);
}
}
void mitk::ContourModel::AddVertex(mitk::Point3D &vertex, bool isControlPoint, int timestep)
{
if(!this->IsEmptyTimeStep(timestep))
{
this->m_ContourSeries[timestep]->AddVertex(vertex, isControlPoint);
this->InvokeEvent( ContourModelSizeChangeEvent() );
this->Modified();this->m_UpdateBoundingBox = true;
}
}
void mitk::ContourModel::AddVertex(VertexType &vertex, int timestep)
{
if(!this->IsEmptyTimeStep(timestep))
{
this->m_ContourSeries[timestep]->AddVertex(vertex);
this->InvokeEvent( ContourModelSizeChangeEvent() );
this->Modified();this->m_UpdateBoundingBox = true;
}
}
void mitk::ContourModel::AddVertex(const VertexType* vertex, int timestep)
{
if(vertex != NULL)
{
this->m_ContourSeries[timestep]->AddVertex(*const_cast<VertexType*>(vertex));
}
}
void mitk::ContourModel::AddVertexAtFront(mitk::Point3D &vertex, int timestep)
{
if(!this->IsEmptyTimeStep(timestep) )
{
this->AddVertexAtFront(vertex, false, timestep);
}
}
void mitk::ContourModel::AddVertexAtFront(mitk::Point3D &vertex, bool isControlPoint, int timestep)
{
if(!this->IsEmptyTimeStep(timestep))
{
this->m_ContourSeries[timestep]->AddVertexAtFront(vertex, isControlPoint);
this->InvokeEvent( ContourModelSizeChangeEvent() );
this->Modified();
this->m_UpdateBoundingBox = true;
}
}
void mitk::ContourModel::AddVertexAtFront(VertexType &vertex, int timestep)
{
if(!this->IsEmptyTimeStep(timestep))
{
this->m_ContourSeries[timestep]->AddVertexAtFront(vertex);
this->InvokeEvent( ContourModelSizeChangeEvent() );
this->Modified();
this->m_UpdateBoundingBox = true;
}
}
bool mitk::ContourModel::SetVertexAt(int pointId, const Point3D &point, unsigned int timestep)
{
if(!this->IsEmptyTimeStep(timestep))
{
if(pointId >= 0 && this->m_ContourSeries[timestep]->GetSize() > pointId)
{
this->m_ContourSeries[timestep]->SetVertexAt( pointId, point );
this->Modified();
this->m_UpdateBoundingBox = true;
return true;
}
return false;
}
return false;
}
bool mitk::ContourModel::SetVertexAt(int pointId, const VertexType *vertex, unsigned int timestep)
{
if(vertex==NULL) return false;
if(!this->IsEmptyTimeStep(timestep))
{
if(pointId >= 0 && this->m_ContourSeries[timestep]->GetSize() > pointId)
{
this->m_ContourSeries[timestep]->SetVertexAt( pointId, vertex );
this->Modified();
this->m_UpdateBoundingBox = true;
return true;
}
return false;
}
return false;
}
void mitk::ContourModel::InsertVertexAtIndex(mitk::Point3D &vertex, int index, bool isControlPoint, int timestep)
{
if(!this->IsEmptyTimeStep(timestep))
{
if(index >= 0 && this->m_ContourSeries[timestep]->GetSize() > index)
{
this->m_ContourSeries[timestep]->InsertVertexAtIndex(vertex, isControlPoint, index);
this->InvokeEvent( ContourModelSizeChangeEvent() );
this->Modified();
this->m_UpdateBoundingBox = true;
}
}
}
bool mitk::ContourModel::IsEmpty( int timestep) const
{
if(!this->IsEmptyTimeStep(timestep))
{
return this->m_ContourSeries[timestep]->IsEmpty();
}
return true;
}
bool mitk::ContourModel::IsEmpty() const
{
return this->IsEmpty(0);
}
int mitk::ContourModel::GetNumberOfVertices( int timestep) const
{
if(!this->IsEmptyTimeStep(timestep))
{
return this->m_ContourSeries[timestep]->GetSize();
}
return -1;
}
const mitk::ContourModel::VertexType* mitk::ContourModel::GetVertexAt(int index, int timestep) const
{
if(!this->IsEmptyTimeStep(timestep))
{
return this->m_ContourSeries[timestep]->GetVertexAt(index);
}
return NULL;
}
int mitk::ContourModel::GetIndex(const VertexType *vertex, int timestep)
{
if(!this->IsEmptyTimeStep(timestep))
{
return this->m_ContourSeries[timestep]->GetIndex(vertex);
}
return -1;
}
void mitk::ContourModel::Close( int timestep)
{
if(!this->IsEmptyTimeStep(timestep))
{
this->m_ContourSeries[timestep]->Close();
this->InvokeEvent( ContourModelClosedEvent() );
this->Modified();this->m_UpdateBoundingBox = true;
}
}
void mitk::ContourModel::Open( int timestep)
{
if(!this->IsEmptyTimeStep(timestep))
{
this->m_ContourSeries[timestep]->Open();
this->InvokeEvent( ContourModelClosedEvent() );
this->Modified();this->m_UpdateBoundingBox = true;
}
}
void mitk::ContourModel::SetClosed(bool isClosed, int timestep)
{
if(!this->IsEmptyTimeStep(timestep))
{
this->m_ContourSeries[timestep]->SetClosed(isClosed);
this->InvokeEvent( ContourModelClosedEvent() );
this->Modified();this->m_UpdateBoundingBox = true;
}
}
bool mitk::ContourModel::IsEmptyTimeStep(unsigned int t) const
{
return (this->m_ContourSeries.size() <= t);
}
bool mitk::ContourModel::IsNearContour(mitk::Point3D &point, float eps, int timestep)
{
if(!this->IsEmptyTimeStep(timestep))
{
return this->m_ContourSeries[timestep]->IsNearContour(point, eps);
}
return false;
}
void mitk::ContourModel::Concatenate(mitk::ContourModel* other, int timestep, bool check)
{
if(!this->IsEmptyTimeStep(timestep))
{
if( !this->m_ContourSeries[timestep]->IsClosed() )
{
this->m_ContourSeries[timestep]->Concatenate(other->m_ContourSeries[timestep], check);
this->InvokeEvent( ContourModelSizeChangeEvent() );
this->Modified();this->m_UpdateBoundingBox = true;
}
}
}
mitk::ContourModel::VertexIterator mitk::ContourModel::Begin( int timestep)
{
return this->IteratorBegin(timestep);
}
mitk::ContourModel::VertexIterator mitk::ContourModel::IteratorBegin( int timestep)
{
if(!this->IsEmptyTimeStep(timestep))
{
return this->m_ContourSeries[timestep]->IteratorBegin();
}
else
{
mitkThrow() << "No iterator at invalid timestep " << timestep << ". There are only " << this->GetTimeSteps() << " timesteps available.";
}
}
mitk::ContourModel::VertexIterator mitk::ContourModel::End( int timestep)
{
return this->IteratorEnd(timestep);
}
mitk::ContourModel::VertexIterator mitk::ContourModel::IteratorEnd( int timestep)
{
if(!this->IsEmptyTimeStep(timestep))
{
return this->m_ContourSeries[timestep]->IteratorEnd();
}
else
{
mitkThrow() << "No iterator at invalid timestep " << timestep << ". There are only " << this->GetTimeSteps() << " timesteps available.";
}
}
bool mitk::ContourModel::IsClosed( int timestep)
{
if(!this->IsEmptyTimeStep(timestep))
{
return this->m_ContourSeries[timestep]->IsClosed();
}
return false;
}
bool mitk::ContourModel::SelectVertexAt(mitk::Point3D &point, float eps, int timestep)
{
if(!this->IsEmptyTimeStep(timestep))
{
this->m_SelectedVertex = this->m_ContourSeries[timestep]->GetVertexAt(point, eps);
}
return this->m_SelectedVertex != NULL;
}
bool mitk::ContourModel::SelectVertexAt(int index, int timestep)
{
if(!this->IsEmptyTimeStep(timestep) && index >= 0)
{
return (this->m_SelectedVertex = this->m_ContourSeries[timestep]->GetVertexAt(index));
}
return false;
}
bool mitk::ContourModel::SetControlVertexAt(mitk::Point3D &point, float eps, int timestep)
{
if(!this->IsEmptyTimeStep(timestep))
{
VertexType* vertex = this->m_ContourSeries[timestep]->GetVertexAt(point, eps);
if (vertex != NULL)
{
vertex->IsControlPoint = true;
return true;
}
}
return false;
}
bool mitk::ContourModel::SetControlVertexAt(int index, int timestep)
{
if(!this->IsEmptyTimeStep(timestep) && index >= 0)
{
VertexType* vertex = this->m_ContourSeries[timestep]->GetVertexAt(index);
if (vertex != NULL)
{
vertex->IsControlPoint = true;
return true;
}
}
return false;
}
bool mitk::ContourModel::RemoveVertex(const VertexType *vertex, int timestep)
{
if(!this->IsEmptyTimeStep(timestep))
{
if(this->m_ContourSeries[timestep]->RemoveVertex(vertex))
{
this->Modified();this->m_UpdateBoundingBox = true;
this->InvokeEvent( ContourModelSizeChangeEvent() );
return true;
}
}
return false;
}
bool mitk::ContourModel::RemoveVertexAt(int index, int timestep)
{
if(!this->IsEmptyTimeStep(timestep))
{
if(this->m_ContourSeries[timestep]->RemoveVertexAt(index))
{
this->Modified();this->m_UpdateBoundingBox = true;
this->InvokeEvent( ContourModelSizeChangeEvent() );
return true;
}
}
return false;
}
bool mitk::ContourModel::RemoveVertexAt(mitk::Point3D &point, float eps, int timestep)
{
if(!this->IsEmptyTimeStep(timestep))
{
if(this->m_ContourSeries[timestep]->RemoveVertexAt(point, eps))
{
this->Modified();this->m_UpdateBoundingBox = true;
this->InvokeEvent( ContourModelSizeChangeEvent() );
return true;
}
}
return false;
}
void mitk::ContourModel::ShiftSelectedVertex(mitk::Vector3D &translate)
{
if(this->m_SelectedVertex)
{
this->ShiftVertex(this->m_SelectedVertex,translate);
this->Modified();this->m_UpdateBoundingBox = true;
}
}
void mitk::ContourModel::ShiftContour(mitk::Vector3D &translate, int timestep)
{
if(!this->IsEmptyTimeStep(timestep))
{
VertexListType* vList = this->m_ContourSeries[timestep]->GetVertexList();
VertexIterator it = vList->begin();
VertexIterator end = vList->end();
//shift all vertices
while(it != end)
{
this->ShiftVertex((*it),translate);
it++;
}
this->Modified();this->m_UpdateBoundingBox = true;
this->InvokeEvent( ContourModelShiftEvent() );
}
}
void mitk::ContourModel::ShiftVertex(VertexType* vertex, mitk::Vector3D &vector)
{
vertex->Coordinates[0] += vector[0];
vertex->Coordinates[1] += vector[1];
vertex->Coordinates[2] += vector[2];
}
void mitk::ContourModel::Clear(int timestep)
{
if(!this->IsEmptyTimeStep(timestep))
{
//clear data at timestep
this->m_ContourSeries[timestep]->Clear();
this->InitializeEmpty();
this->Modified();this->m_UpdateBoundingBox = true;
}
}
void mitk::ContourModel::Expand(unsigned int timeSteps )
{
std::size_t oldSize = this->m_ContourSeries.size();
if( static_cast<std::size_t>(timeSteps) > oldSize )
{
Superclass::Expand(timeSteps);
//insert contours for each new timestep
for( std::size_t i = oldSize; i < static_cast<std::size_t>(timeSteps); i++)
{
m_ContourSeries.push_back(mitk::ContourElement::New());
}
this->InvokeEvent( ContourModelExpandTimeBoundsEvent() );
}
}
void mitk::ContourModel::SetRequestedRegionToLargestPossibleRegion ()
{
//no support for regions
}
bool mitk::ContourModel::RequestedRegionIsOutsideOfTheBufferedRegion ()
{
//no support for regions
return false;
}
bool mitk::ContourModel::VerifyRequestedRegion ()
{
//no support for regions
return true;
}
-const mitk::Geometry3D * mitk::ContourModel::GetUpdatedGeometry (int t)
+const mitk::BaseGeometry * mitk::ContourModel::GetUpdatedGeometry (int t)
{
return Superclass::GetUpdatedGeometry(t);
}
-mitk::Geometry3D* mitk::ContourModel::GetGeometry (int t)const
+mitk::BaseGeometry* mitk::ContourModel::GetGeometry (int t)const
{
return Superclass::GetGeometry(t);
}
void mitk::ContourModel::SetRequestedRegion( const itk::DataObject* /*data*/)
{
//no support for regions
}
void mitk::ContourModel::Clear()
{
//clear data and set to initial state again
this->ClearData();
this->InitializeEmpty();
this->Modified();this->m_UpdateBoundingBox = true;
}
void mitk::ContourModel::RedistributeControlVertices(int period, int timestep)
{
if(!this->IsEmptyTimeStep(timestep))
{
this->m_ContourSeries[timestep]->RedistributeControlVertices(this->GetSelectedVertex(), period);
this->InvokeEvent( ContourModelClosedEvent() );
this->Modified();this->m_UpdateBoundingBox = true;
}
}
void mitk::ContourModel::ClearData()
{
//call the superclass, this releases the data of BaseData
Superclass::ClearData();
//clear out the time resolved contours
this->m_ContourSeries.clear();
}
void mitk::ContourModel::Initialize()
{
this->InitializeEmpty();
this->Modified();this->m_UpdateBoundingBox = true;
}
void mitk::ContourModel::Initialize(mitk::ContourModel &other)
{
mitk::TimeStepType numberOfTimesteps = other.GetTimeGeometry()->CountTimeSteps();
this->InitializeTimeGeometry(numberOfTimesteps);
for(mitk::TimeStepType currentTimestep = 0; currentTimestep < numberOfTimesteps; currentTimestep++)
{
this->m_ContourSeries.push_back(mitk::ContourElement::New());
this->SetClosed(other.IsClosed(currentTimestep),currentTimestep);
}
m_SelectedVertex = NULL;
this->m_lineInterpolation = other.m_lineInterpolation;
this->Modified();this->m_UpdateBoundingBox = true;
}
void mitk::ContourModel::InitializeEmpty()
{
//clear data at timesteps
this->m_ContourSeries.resize(0);
this->m_ContourSeries.push_back(mitk::ContourElement::New());
//set number of timesteps to one
this->InitializeTimeGeometry(1);
m_SelectedVertex = NULL;
this->m_lineInterpolation = ContourModel::LINEAR;
}
void mitk::ContourModel::UpdateOutputInformation()
{
if ( this->GetSource() )
{
this->GetSource()->UpdateOutputInformation();
}
if(this->m_UpdateBoundingBox)
{
//update the bounds of the geometry according to the stored vertices
ScalarType mitkBounds[6];
//calculate the boundingbox at each timestep
typedef itk::BoundingBox<unsigned long, 3, ScalarType> BoundingBoxType;
typedef BoundingBoxType::PointsContainer PointsContainer;
int timesteps = this->GetTimeSteps();
//iterate over the timesteps
for(int currenTimeStep = 0; currenTimeStep < timesteps; currenTimeStep++)
{
if( dynamic_cast< mitk::PlaneGeometry* >(this->GetGeometry(currenTimeStep)) )
{
//do not update bounds for 2D geometries, as they are unfortunately defined with min bounds 0!
return;
}
else
{//we have a 3D geometry -> let's update bounds
//only update bounds if the contour was modified
if (this->GetMTime() > this->GetGeometry(currenTimeStep)->GetBoundingBox()->GetMTime())
{
mitkBounds[0] = 0.0;
mitkBounds[1] = 0.0;
mitkBounds[2] = 0.0;
mitkBounds[3] = 0.0;
mitkBounds[4] = 0.0;
mitkBounds[5] = 0.0;
BoundingBoxType::Pointer boundingBox = BoundingBoxType::New();
PointsContainer::Pointer points = PointsContainer::New();
VertexIterator it = this->IteratorBegin(currenTimeStep);
VertexIterator end = this->IteratorEnd(currenTimeStep);
//fill the boundingbox with the points
while(it != end)
{
Point3D currentP = (*it)->Coordinates;
BoundingBoxType::PointType p;
p.CastFrom(currentP);
points->InsertElement(points->Size(), p);
it++;
}
//construct the new boundingBox
boundingBox->SetPoints(points);
boundingBox->ComputeBoundingBox();
BoundingBoxType::BoundsArrayType tmp = boundingBox->GetBounds();
mitkBounds[0] = tmp[0];
mitkBounds[1] = tmp[1];
mitkBounds[2] = tmp[2];
mitkBounds[3] = tmp[3];
mitkBounds[4] = tmp[4];
mitkBounds[5] = tmp[5];
//set boundingBox at current timestep
- Geometry3D* geometry3d = this->GetGeometry(currenTimeStep);
+ BaseGeometry* geometry3d = this->GetGeometry(currenTimeStep);
geometry3d->SetBounds(mitkBounds);
}
}
}
this->m_UpdateBoundingBox = false;
}
GetTimeGeometry()->Update();
}
void mitk::ContourModel::ExecuteOperation(mitk::Operation* /*operation*/)
{
//not supported yet
}
diff --git a/Modules/ContourModel/DataManagement/mitkContourModel.h b/Modules/ContourModel/DataManagement/mitkContourModel.h
index 3d00bd91e1..78a6f9e50f 100644
--- a/Modules/ContourModel/DataManagement/mitkContourModel.h
+++ b/Modules/ContourModel/DataManagement/mitkContourModel.h
@@ -1,474 +1,474 @@
/*===================================================================
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 _MITK_CONTOURMODEL_H_
#define _MITK_CONTOURMODEL_H_
#include "mitkCommon.h"
#include <MitkContourModelExports.h>
#include "mitkBaseData.h"
#include <mitkContourElement.h>
namespace mitk
{
/**
\brief ContourModel is a structure of linked vertices defining a contour in 3D space.
The vertices are stored in a mitk::ContourElement is stored for each timestep.
The contour line segments are implicitly defined by the given linked vertices.
By default two control points are are linked by a straight line.It is possible to add
vertices at front and end of the contour and to iterate in both directions.
Points are specified containing coordinates and additional (data) information,
see mitk::ContourElement.
For accessing a specific vertex either an index or a position in 3D Space can be used.
The vertices are best accessed by using a VertexIterator.
Interaction with the contour is thus available without any mitk interactor class using the
api of ContourModel. It is possible to shift single vertices also as shifting the whole
contour.
A contour can be either open like a single curved line segment or
closed. A closed contour can for example represent a jordan curve.
\section mitkContourModelDisplayOptions Display Options
The default mappers for this data structure are mitk::ContourModelGLMapper2D and
mitk::ContourModelMapper3D. See these classes for display options which can
can be set via properties.
*/
class MitkContourModel_EXPORT ContourModel : public BaseData
{
public:
mitkClassMacro(ContourModel, BaseData);
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/*+++++++++++++++ typedefs +++++++++++++++++++++++++++++++*/
typedef mitk::ContourElement::VertexType VertexType;
typedef mitk::ContourElement::VertexListType VertexListType;
typedef mitk::ContourElement::VertexIterator VertexIterator;
typedef mitk::ContourElement::ConstVertexIterator ConstVertexIterator;
typedef std::vector< mitk::ContourElement::Pointer > ContourModelSeries;
/*+++++++++++++++ END typedefs ++++++++++++++++++++++++++++*/
/** \brief Possible interpolation of the line segments between control points */
enum LineSegmentInterpolation{
LINEAR, B_SPLINE
};
/*++++++++++++++++ inline methods +++++++++++++++++++++++*/
/** \brief Get the current selected vertex.
*/
VertexType* GetSelectedVertex()
{
return this->m_SelectedVertex;
}
/** \brief Deselect vertex.
*/
void Deselect()
{
this->m_SelectedVertex = NULL;
}
/** \brief Set selected vertex as control point
*/
void SetSelectedVertexAsControlPoint(bool isControlPoint=true)
{
if (this->m_SelectedVertex)
{
m_SelectedVertex->IsControlPoint = isControlPoint;
this->Modified();
}
}
/** \brief Set the interpolation of the line segments between control points.
*/
void SetLineSegmentInterpolation(LineSegmentInterpolation interpolation)
{
this->m_lineInterpolation = interpolation;
this->Modified();
}
/** \brief Get the interpolation of the line segments between control points.
*/
LineSegmentInterpolation GetLineSegmentInterpolation()
{
return this->m_lineInterpolation;
}
/*++++++++++++++++ END inline methods +++++++++++++++++++++++*/
/** \brief Add a vertex to the contour at given timestep.
The vertex is added at the end of contour.
\param vertex - coordinate representation of a control point
\param timestep - the timestep at which the vertex will be add ( default 0)
@Note Adding a vertex to a timestep which exceeds the timebounds of the contour
will not be added, the TimeGeometry will not be expanded.
*/
void AddVertex(mitk::Point3D &vertex, int timestep=0);
/** \brief Add a vertex to the contour at given timestep.
The vertex is added at the end of contour.
\param vertex - coordinate representation of a control point
\param timestep - the timestep at which the vertex will be add ( default 0)
@Note Adding a vertex to a timestep which exceeds the timebounds of the contour
will not be added, the TimeGeometry will not be expanded.
*/
void AddVertex(VertexType &vertex, int timestep=0);
/** \brief Add a vertex to the contour at given timestep.
The vertex is added at the end of contour.
\param vertex - coordinate representation of a control point
\param timestep - the timestep at which the vertex will be add ( default 0)
@Note Adding a vertex to a timestep which exceeds the timebounds of the contour
will not be added, the TimeSlicedGeometry will not be expanded.
*/
void AddVertex(const VertexType* vertex, int timestep=0);
/** \brief Add a vertex to the contour.
\param vertex - coordinate representation of a control point
\param timestep - the timestep at which the vertex will be add ( default 0)
\param isControlPoint - specifies the vertex to be handled in a special way (e.g. control points
will be rendered).
@Note Adding a vertex to a timestep which exceeds the timebounds of the contour
will not be added, the TimeGeometry will not be expanded.
*/
void AddVertex(mitk::Point3D &vertex, bool isControlPoint, int timestep=0);
/** \brief Add a vertex to the contour at given timestep AT THE FRONT of the contour.
The vertex is added at the FRONT of contour.
\param vertex - coordinate representation of a control point
\param timestep - the timestep at which the vertex will be add ( default 0)
@Note Adding a vertex to a timestep which exceeds the timebounds of the contour
will not be added, the TimeGeometry will not be expanded.
*/
void AddVertexAtFront(mitk::Point3D &vertex, int timestep=0);
/** \brief Add a vertex to the contour at given timestep AT THE FRONT of the contour.
The vertex is added at the FRONT of contour.
\param vertex - coordinate representation of a control point
\param timestep - the timestep at which the vertex will be add ( default 0)
@Note Adding a vertex to a timestep which exceeds the timebounds of the contour
will not be added, the TimeGeometry will not be expanded.
*/
void AddVertexAtFront(VertexType &vertex, int timestep=0);
/** \brief Add a vertex to the contour at given timestep AT THE FRONT of the contour.
\param vertex - coordinate representation of a control point
\param timestep - the timestep at which the vertex will be add ( default 0)
\param isControlPoint - specifies the vertex to be handled in a special way (e.g. control points
will be rendered).
@Note Adding a vertex to a timestep which exceeds the timebounds of the contour
will not be added, the TimeGeometry will not be expanded.
*/
void AddVertexAtFront(mitk::Point3D &vertex, bool isControlPoint, int timestep=0);
/** \brief Insert a vertex at given index.
*/
void InsertVertexAtIndex(mitk::Point3D &vertex, int index, bool isControlPoint=false, int timestep=0);
/** \brief Set a coordinates for point at given index.
*/
bool SetVertexAt(int pointId, const mitk::Point3D &point, unsigned int timestep=0);
/** \brief Set a coordinates for point at given index.
*/
bool SetVertexAt(int pointId, const VertexType* vertex, unsigned int timestep=0);
/** \brief Return if the contour is closed or not.
*/
bool IsClosed( int timestep=0);
/** \brief Concatenate two contours.
The starting control point of the other will be added at the end of the contour.
\pararm timestep - the timestep at which the vertex will be add ( default 0)
\pararm check - check for intersections ( default false)
*/
void Concatenate(mitk::ContourModel* other, int timestep=0, bool check=false);
/** \brief Returns a const VertexIterator at the start element of the contour.
@throw mitk::Exception if the timestep is invalid.
*/
VertexIterator Begin( int timestep=0);
/** \brief Returns a const VertexIterator at the start element of the contour.
@throw mitk::Exception if the timestep is invalid.
*/
VertexIterator IteratorBegin( int timestep=0);
/** \brief Returns a const VertexIterator at the end element of the contour.
@throw mitk::Exception if the timestep is invalid.
*/
VertexIterator End( int timestep=0);
/** \brief Returns a const VertexIterator at the end element of the contour.
@throw mitk::Exception if the timestep is invalid.
*/
VertexIterator IteratorEnd( int timestep=0);
/** \brief Close the contour.
The last control point will be linked with the first point.
*/
virtual void Close( int timestep=0);
/** \brief Set isClosed to false contour.
The link between the last control point the first point will be removed.
*/
virtual void Open( int timestep=0);
/** \brief Set closed property to given boolean.
false - The link between the last control point the first point will be removed.
true - The last control point will be linked with the first point.
*/
virtual void SetClosed(bool isClosed, int timestep=0);
/** \brief Returns the number of vertices at a given timestep.
\param timestep - default = 0
*/
int GetNumberOfVertices( int timestep=0) const;
/** \brief Returns whether the contour model is empty at a given timestep.
\pararm timestep - default = 0
*/
virtual bool IsEmpty( int timestep) const;
/** \brief Returns whether the contour model is empty.
*/
virtual bool IsEmpty() const;
/** \brief Returns the vertex at the index position within the container.
*/
virtual const VertexType* GetVertexAt(int index, int timestep=0) const;
/** \brief Remove a vertex at given timestep within the container.
\return index of vertex. -1 if not found.
*/
int GetIndex(const VertexType* vertex, int timestep=0);
/** \brief Check if there isn't something at this timestep.
*/
virtual bool IsEmptyTimeStep(unsigned int t) const;
/** \brief Check if mouse cursor is near the contour.
*/
virtual bool IsNearContour(mitk::Point3D &point, float eps, int timestep);
/** \brief Mark a vertex at an index in the container as selected.
*/
bool SelectVertexAt(int index, int timestep=0);
/** \brief Mark a vertex at an index in the container as control point.
*/
bool SetControlVertexAt(int index, int timestep=0);
/** \brief Mark a vertex at a given position in 3D space.
\param point - query point in 3D space
\param eps - radius for nearest neighbour search (error bound).
\param timestep - search at this timestep
@return true = vertex found; false = no vertex found
*/
bool SelectVertexAt(mitk::Point3D &point, float eps, int timestep=0);
/*
\pararm point - query point in 3D space
\pararm eps - radius for nearest neighbour search (error bound).
\pararm timestep - search at this timestep
@return true = vertex found; false = no vertex found
*/
bool SetControlVertexAt(mitk::Point3D &point, float eps, int timestep=0);
/** \brief Remove a vertex at given index within the container.
@return true = the vertex was successfuly removed; false = wrong index.
*/
bool RemoveVertexAt(int index, int timestep=0);
/** \brief Remove a vertex at given timestep within the container.
@return true = the vertex was successfuly removed.
*/
bool RemoveVertex(const VertexType* vertex, int timestep=0);
/** \brief Remove a vertex at a query position in 3D space.
The vertex to be removed will be search by nearest neighbour search.
Note that possibly no vertex at this position and eps is stored inside
the contour.
@return true = the vertex was successfuly removed; false = no vertex found.
*/
bool RemoveVertexAt(mitk::Point3D &point, float eps, int timestep=0);
/** \brief Shift the currently selected vertex by a translation vector.
\param translate - the translation vector.
*/
void ShiftSelectedVertex(mitk::Vector3D &translate);
/** \brief Shift the whole contour by a translation vector at given timestep.
\param translate - the translation vector.
\param timestep - at this timestep the contour will be shifted.
*/
void ShiftContour(mitk::Vector3D &translate, int timestep=0);
/** \brief Clear the storage container at given timestep.
All control points are removed at
timestep.
*/
virtual void Clear(int timestep);
/** \brief Initialize all data objects
*/
virtual void Initialize();
/** \brief Initialize object with specs of other contour.
Note: No data will be copied.
*/
void Initialize(mitk::ContourModel &other);
/*++++++++++++++++++ method inherit from base data +++++++++++++++++++++++++++*/
/**
\brief Inherit from base data - no region support available for contourModel objects.
*/
virtual void SetRequestedRegionToLargestPossibleRegion ();
/**
\brief Inherit from base data - no region support available for contourModel objects.
*/
virtual bool RequestedRegionIsOutsideOfTheBufferedRegion ();
/**
\brief Inherit from base data - no region support available for contourModel objects.
*/
virtual bool VerifyRequestedRegion ();
/**
\brief Get the updated geometry with recomputed bounds.
*/
- virtual const mitk::Geometry3D* GetUpdatedGeometry (int t=0);
+ virtual const mitk::BaseGeometry* GetUpdatedGeometry (int t=0);
/**
- \brief Get the Geometry3D for timestep t.
+ \brief Get the BaseGeometry for timestep t.
*/
- virtual mitk::Geometry3D* GetGeometry (int t=0) const;
+ virtual mitk::BaseGeometry* GetGeometry (int t=0) const;
/**
\brief Inherit from base data - no region support available for contourModel objects.
*/
virtual void SetRequestedRegion( const itk::DataObject *data);
/**
\brief Expand the timebounds of the TimeGeometry to given number of timesteps.
*/
virtual void Expand( unsigned int timeSteps );
/**
\brief Update the OutputInformation of a ContourModel object
The BoundingBox of the contour will be updated, if necessary.
*/
virtual void UpdateOutputInformation();
/**
\brief Clear the storage container.
The object is set to initial state. All control points are removed and the number of
timesteps are set to 1.
*/
virtual void Clear();
/**
\brief overwrite if the Data can be called by an Interactor (StateMachine).
*/
void ExecuteOperation(Operation* operation);
/** \brief Redistributes ontrol vertices with a given period (as number of vertices)
\param period - the number of vertices between control points.
\param timestep - at this timestep all lines will be rebuilt.
*/
virtual void RedistributeControlVertices(int period, int timestep);
protected:
mitkCloneMacro(Self);
ContourModel();
ContourModel(const mitk::ContourModel &other);
virtual ~ContourModel();
//inherit from BaseData. called by Clear()
virtual void ClearData();
//inherit from BaseData. Initial state of a contour with no vertices and a single timestep.
virtual void InitializeEmpty();
//Shift a vertex
void ShiftVertex(VertexType* vertex, mitk::Vector3D &vector);
//Storage with time resolved support.
ContourModelSeries m_ContourSeries;
//The currently selected vertex.
VertexType* m_SelectedVertex;
//The interpolation of the line segment between control points.
LineSegmentInterpolation m_lineInterpolation;
//only update the bounding geometry if necessary
bool m_UpdateBoundingBox;
};
itkEventMacro( ContourModelEvent, itk::AnyEvent );
itkEventMacro( ContourModelShiftEvent, ContourModelEvent );
itkEventMacro( ContourModelSizeChangeEvent, ContourModelEvent );
itkEventMacro( ContourModelAddEvent, ContourModelSizeChangeEvent );
itkEventMacro( ContourModelRemoveEvent, ContourModelSizeChangeEvent );
itkEventMacro( ContourModelExpandTimeBoundsEvent, ContourModelEvent );
itkEventMacro( ContourModelClosedEvent, ContourModelEvent );
}
#endif
diff --git a/Modules/ContourModel/DataManagement/mitkContourModelSet.cpp b/Modules/ContourModel/DataManagement/mitkContourModelSet.cpp
index 21dc6fef9a..e782bc11d8 100644
--- a/Modules/ContourModel/DataManagement/mitkContourModelSet.cpp
+++ b/Modules/ContourModel/DataManagement/mitkContourModelSet.cpp
@@ -1,214 +1,214 @@
/*===================================================================
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 <mitkContourModelSet.h>
#include <vtkMath.h>
#include <algorithm>
mitk::ContourModelSet::ContourModelSet() :
m_Contours(),
m_UpdateBoundingBox(true)
{
this->InitializeEmpty();
}
mitk::ContourModelSet::ContourModelSet(const mitk::ContourModelSet &other) :
mitk::BaseData(other),
m_Contours(other.m_Contours)
{
this->InitializeTimeGeometry(1);
}
mitk::ContourModelSet::~ContourModelSet()
{
this->m_Contours.clear();
}
void mitk::ContourModelSet::InitializeEmpty()
{
this->InitializeTimeGeometry(1);
m_Contours.resize(0);
}
void mitk::ContourModelSet::AddContourModel(mitk::ContourModel &contourModel)
{
this->m_Contours.push_back(&contourModel);
m_UpdateBoundingBox = true;
}
void mitk::ContourModelSet::AddContourModel(mitk::ContourModel::Pointer contourModel)
{
this->m_Contours.push_back(contourModel);
m_UpdateBoundingBox = true;
}
mitk::ContourModel* mitk::ContourModelSet::GetContourModelAt(int index)
{
if( index >= 0 && static_cast<ContourModelListType::size_type>(index) < this->m_Contours.size() )
{
return this->m_Contours.at(index).GetPointer();
}
else
{
return NULL;
}
}
bool mitk::ContourModelSet::IsEmpty() const
{
return this->m_Contours.empty();
}
mitk::ContourModelSet::ContourModelListType* mitk::ContourModelSet::GetContourModelList()
{
return &(this->m_Contours);
}
bool mitk::ContourModelSet::RemoveContourModel(mitk::ContourModel* contourModel)
{
ContourModelSetIterator it = this->m_Contours.begin();
ContourModelSetIterator end = this->m_Contours.end();
//search for ContourModel and remove it if exists
while(it != end)
{
if((*it) == contourModel)
{
this->m_Contours.erase(it);
m_UpdateBoundingBox = true;
return true;
}
it++;
}
return false;
}
bool mitk::ContourModelSet::RemoveContourModelAt(int index)
{
if( index >= 0 && static_cast<ContourModelListType::size_type>(index) < this->m_Contours.size() )
{
this->m_Contours.erase(this->m_Contours.begin()+index);
m_UpdateBoundingBox = true;
return true;
}
else
{
return false;
}
}
void mitk::ContourModelSet::Clear()
{
this->m_Contours.clear();
m_UpdateBoundingBox = true;
}
void mitk::ContourModelSet::UpdateOutputInformation()
{
if ( this->GetSource() )
{
this->GetSource()->UpdateOutputInformation();
}
if(this->m_UpdateBoundingBox)
{
//update the bounds of the geometry according to the stored vertices
mitk::ScalarType mitkBounds[6];
//calculate the boundingbox at each timestep
typedef itk::BoundingBox<unsigned long, 3, ScalarType> BoundingBoxType;
typedef BoundingBoxType::PointsContainer PointsContainer;
int timesteps = this->GetTimeSteps();
//iterate over the timesteps
for(int currenTimeStep = 0; currenTimeStep < timesteps; currenTimeStep++)
{
//only update bounds if the contour was modified
if (this->GetMTime() > this->GetGeometry(currenTimeStep)->GetBoundingBox()->GetMTime())
{
mitkBounds[0] = 0.0;
mitkBounds[1] = 0.0;
mitkBounds[2] = 0.0;
mitkBounds[3] = 0.0;
mitkBounds[4] = 0.0;
mitkBounds[5] = 0.0;
BoundingBoxType::Pointer boundingBox = BoundingBoxType::New();
PointsContainer::Pointer points = PointsContainer::New();
mitk::ContourModelSet::ContourModelSetIterator contoursIt = this->Begin();
mitk::ContourModelSet::ContourModelSetIterator contoursEnd = this->End();
while(contoursIt!=contoursEnd)
{
mitk::ContourModel::VertexIterator it = contoursIt->GetPointer()->Begin(currenTimeStep);
mitk::ContourModel::VertexIterator end = contoursIt->GetPointer()->End(currenTimeStep);
//fill the boundingbox with the points
while(it != end)
{
Point3D currentP = (*it)->Coordinates;
BoundingBoxType::PointType p;
p.CastFrom(currentP);
points->InsertElement(points->Size(), p);
it++;
}
++contoursIt;
}
//construct the new boundingBox
boundingBox->SetPoints(points);
boundingBox->ComputeBoundingBox();
BoundingBoxType::BoundsArrayType tmp = boundingBox->GetBounds();
mitkBounds[0] = tmp[0];
mitkBounds[1] = tmp[1];
mitkBounds[2] = tmp[2];
mitkBounds[3] = tmp[3];
mitkBounds[4] = tmp[4];
mitkBounds[5] = tmp[5];
//set boundingBox at current timestep
- Geometry3D* geometry3d = this->GetGeometry(currenTimeStep);
+ BaseGeometry* geometry3d = this->GetGeometry(currenTimeStep);
geometry3d->SetBounds(mitkBounds);
}
}
this->m_UpdateBoundingBox = false;
}
GetTimeGeometry()->Update();
}
diff --git a/Modules/ContourModel/Rendering/mitkContourModelMapper2D.cpp b/Modules/ContourModel/Rendering/mitkContourModelMapper2D.cpp
index aaf9d84d6e..e07f7ec13f 100644
--- a/Modules/ContourModel/Rendering/mitkContourModelMapper2D.cpp
+++ b/Modules/ContourModel/Rendering/mitkContourModelMapper2D.cpp
@@ -1,393 +1,393 @@
/*===================================================================
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 <mitkContourModelMapper2D.h>
#include <mitkContourModelSubDivisionFilter.h>
#include <vtkPoints.h>
#include <vtkCellArray.h>
#include <vtkAppendPolyData.h>
#include <vtkProperty.h>
#include <vtkPlane.h>
#include <vtkCutter.h>
#include <vtkStripper.h>
#include <vtkTubeFilter.h>
#include <vtkSphereSource.h>
#include <mitkPlaneGeometry.h>
mitk::ContourModelMapper2D::ContourModelMapper2D()
{
}
mitk::ContourModelMapper2D::~ContourModelMapper2D()
{
}
const mitk::ContourModel* mitk::ContourModelMapper2D::GetInput( void )
{
//convient way to get the data from the dataNode
return static_cast< const mitk::ContourModel * >( GetDataNode()->GetData() );
}
vtkProp* mitk::ContourModelMapper2D::GetVtkProp(mitk::BaseRenderer* renderer)
{
//return the actor corresponding to the renderer
return m_LSH.GetLocalStorage(renderer)->m_Actor;
}
void mitk::ContourModelMapper2D::GenerateDataForRenderer( mitk::BaseRenderer *renderer )
{
/*++ convert the contour to vtkPolyData and set it as input for our mapper ++*/
LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);
mitk::ContourModel* inputContour = static_cast< mitk::ContourModel* >( GetDataNode()->GetData() );
unsigned int timestep = renderer->GetTimeStep();
//if there's something to be rendered
if( inputContour->GetNumberOfVertices(timestep) > 0)
{
localStorage->m_OutlinePolyData = this->CreateVtkPolyDataFromContour(inputContour, renderer);
}
this->ApplyContourProperties(renderer);
localStorage->m_Mapper->SetInputData(localStorage->m_OutlinePolyData);
}
void mitk::ContourModelMapper2D::Update(mitk::BaseRenderer* renderer)
{
bool visible = true;
GetDataNode()->GetVisibility(visible, renderer, "visible");
if ( !visible ) return;
//check if there is something to be rendered
mitk::ContourModel* data = static_cast< mitk::ContourModel*>( GetDataNode()->GetData() );
if ( data == NULL )
{
return;
}
// Calculate time step of the input data for the specified renderer (integer value)
this->CalculateTimeStep( renderer );
LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);
// Check if time step is valid
const TimeGeometry *dataTimeGeometry = data->GetTimeGeometry();
if ( ( dataTimeGeometry == NULL )
|| ( dataTimeGeometry->CountTimeSteps() == 0 )
|| ( !dataTimeGeometry->IsValidTimeStep( renderer->GetTimeStep() ) ) )
{
//clear the rendered polydata
localStorage->m_Mapper->RemoveAllInputs();//SetInput(vtkSmartPointer<vtkPolyData>::New());
return;
}
const DataNode *node = this->GetDataNode();
data->UpdateOutputInformation();
//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 < renderer->GetCurrentWorldPlaneGeometryUpdateTime()) //was the geometry modified?
+ || (localStorage->m_LastUpdateTime < renderer->GetCurrentWorldPlaneGeometry()->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();
}
vtkSmartPointer<vtkPolyData> mitk::ContourModelMapper2D::CreateVtkPolyDataFromContour(mitk::ContourModel* inputContour, mitk::BaseRenderer* renderer)
{
unsigned int timestep = this->GetTimestep();
// Create a polydata to store everything in
vtkSmartPointer<vtkPolyData> resultingPolyData = vtkSmartPointer<vtkPolyData>::New();
//check for the worldgeometry from the current render window
- mitk::PlaneGeometry* currentWorldGeometry = dynamic_cast<mitk::PlaneGeometry*>( const_cast<mitk::Geometry2D*>(renderer->GetCurrentWorldGeometry2D()));
+ mitk::PlaneGeometry* currentWorldGeometry = dynamic_cast<mitk::PlaneGeometry*>( const_cast<mitk::PlaneGeometry*>(renderer->GetCurrentWorldPlaneGeometry()));
if(currentWorldGeometry)
{
//origin and normal of vtkPlane
mitk::Point3D origin = currentWorldGeometry->GetOrigin();
mitk::Vector3D normal = currentWorldGeometry->GetNormal();
//the implicit function to slice through the polyData
vtkSmartPointer<vtkPlane> plane = vtkSmartPointer<vtkPlane>::New();
plane->SetOrigin(origin[0], origin[1], origin[2]);
plane->SetNormal(normal[0], normal[1], normal[2]);
/* First of all convert the control points of the contourModel to vtk points
* and add lines in between them
*/
//the points to draw
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
//the lines to connect the points
vtkSmartPointer<vtkCellArray> lines = vtkSmartPointer<vtkCellArray>::New();
// Create a polydata to store everything in
vtkSmartPointer<vtkPolyData> polyDataIn3D = vtkSmartPointer<vtkPolyData>::New();
vtkSmartPointer<vtkAppendPolyData> appendPoly = vtkSmartPointer<vtkAppendPolyData>::New();
mitk::ContourModel::Pointer renderingContour = mitk::ContourModel::New();
renderingContour = inputContour;
bool subdivision = false;
this->GetDataNode()->GetBoolProperty( "subdivision curve", subdivision, renderer );
if (subdivision)
{
mitk::ContourModel::Pointer subdivContour = mitk::ContourModel::New();
mitk::ContourModelSubDivisionFilter::Pointer subdivFilter = mitk::ContourModelSubDivisionFilter::New();
subdivFilter->SetInput(inputContour);
subdivFilter->Update();
subdivContour = subdivFilter->GetOutput();
if(subdivContour->GetNumberOfVertices() == 0 )
{
subdivContour = inputContour;
}
renderingContour = subdivContour;
}
//iterate over all control points
mitk::ContourModel::VertexIterator current = renderingContour->IteratorBegin(timestep);
mitk::ContourModel::VertexIterator next = renderingContour->IteratorBegin(timestep);
if(next != renderingContour->IteratorEnd(timestep))
{
next++;
mitk::ContourModel::VertexIterator end = renderingContour->IteratorEnd(timestep);
while(next != end)
{
mitk::ContourModel::VertexType* currentControlPoint = *current;
mitk::ContourModel::VertexType* nextControlPoint = *next;
vtkIdType p1 = points->InsertNextPoint(currentControlPoint->Coordinates[0], currentControlPoint->Coordinates[1], currentControlPoint->Coordinates[2]);
vtkIdType p2 = points->InsertNextPoint(nextControlPoint->Coordinates[0], nextControlPoint->Coordinates[1], nextControlPoint->Coordinates[2]);
//add the line between both contorlPoints
lines->InsertNextCell(2);
lines->InsertCellPoint(p1);
lines->InsertCellPoint(p2);
if ( currentControlPoint->IsControlPoint )
{
double coordinates[3];
coordinates[0] = currentControlPoint->Coordinates[0];
coordinates[1] = currentControlPoint->Coordinates[1];
coordinates[2] = currentControlPoint->Coordinates[2];
double distance = plane->DistanceToPlane(coordinates);
if(distance < 0.1)
{
vtkSmartPointer<vtkSphereSource> sphere = vtkSmartPointer<vtkSphereSource>::New();
sphere->SetRadius(1.2);
sphere->SetCenter(coordinates[0], coordinates[1], coordinates[2]);
sphere->Update();
appendPoly->AddInputConnection(sphere->GetOutputPort());
}
}
current++;
next++;
}//end while (it!=end)
//check if last control point is enabled to draw it
if ( (*current)->IsControlPoint )
{
double coordinates[3];
coordinates[0] = (*current)->Coordinates[0];
coordinates[1] = (*current)->Coordinates[1];
coordinates[2] = (*current)->Coordinates[2];
double distance = plane->DistanceToPlane(coordinates);
if(distance < 0.1)
{
vtkSmartPointer<vtkSphereSource> sphere = vtkSmartPointer<vtkSphereSource>::New();
sphere->SetRadius(1.2);
sphere->SetCenter(coordinates[0], coordinates[1], coordinates[2]);
sphere->Update();
appendPoly->AddInputConnection(sphere->GetOutputPort());
}
}
/* If the contour is closed an additional line has to be created between the very first point
* and the last point
*/
if(renderingContour->IsClosed(timestep))
{
//add a line from the last to the first control point
mitk::ContourModel::VertexType* firstControlPoint = *(renderingContour->IteratorBegin(timestep));
mitk::ContourModel::VertexType* lastControlPoint = *(--(renderingContour->IteratorEnd(timestep)));
vtkIdType p2 = points->InsertNextPoint(lastControlPoint->Coordinates[0], lastControlPoint->Coordinates[1], lastControlPoint->Coordinates[2]);
vtkIdType p1 = points->InsertNextPoint(firstControlPoint->Coordinates[0], firstControlPoint->Coordinates[1], firstControlPoint->Coordinates[2]);
//add the line between both contorlPoints
lines->InsertNextCell(2);
lines->InsertCellPoint(p1);
lines->InsertCellPoint(p2);
}//end if(isClosed)
// Add the points to the dataset
polyDataIn3D->SetPoints(points);
// Add the lines to the dataset
polyDataIn3D->SetLines(lines);
//cut through polyData
bool useCuttingPlane = false;
this->GetDataNode()->GetBoolProperty( "use cutting plane", useCuttingPlane, renderer );
if (useCuttingPlane)
{
//slice through the data to get a 2D representation of the (possible) 3D contour
//needed because currently there is no outher solution if the contour is within the plane
vtkSmartPointer<vtkTubeFilter> tubeFilter = vtkSmartPointer<vtkTubeFilter>::New();
tubeFilter->SetInputData(polyDataIn3D);
tubeFilter->SetRadius(0.05);
//cuts through vtkPolyData with a given implicit function. In our case a plane
vtkSmartPointer<vtkCutter> cutter = vtkSmartPointer<vtkCutter>::New();
cutter->SetCutFunction(plane);
cutter->SetInputConnection(tubeFilter->GetOutputPort());
//we want the scalars of the input - so turn off generating the scalars within vtkCutter
cutter->GenerateCutScalarsOff();
cutter->Update();
//set to 2D representation of the contour
resultingPolyData= cutter->GetOutput();
}//end if(project contour)
else
{
//set to 3D polyData
resultingPolyData = polyDataIn3D;
}
}//end if (it != end)
appendPoly->AddInputData(resultingPolyData);
appendPoly->Update();
//return contour with control points
return appendPoly->GetOutput();
}else
{
//return empty polyData
return resultingPolyData;
}
}
void mitk::ContourModelMapper2D::ApplyContourProperties(mitk::BaseRenderer* renderer)
{
LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);
float lineWidth(1.0);
if (this->GetDataNode()->GetFloatProperty( "width", lineWidth, renderer ))
{
localStorage->m_Actor->GetProperty()->SetLineWidth(lineWidth);
}
mitk::ColorProperty::Pointer colorprop = dynamic_cast<mitk::ColorProperty*>(GetDataNode()->GetProperty("color", renderer));
if(colorprop)
{
//set the color of the contour
double red = colorprop->GetColor().GetRed();
double green = colorprop->GetColor().GetGreen();
double blue = colorprop->GetColor().GetBlue();
localStorage->m_Actor->GetProperty()->SetColor(red, green, blue);
}
//make sure that directional lighting isn't used for our contour
localStorage->m_Actor->GetProperty()->SetAmbient(1.0);
localStorage->m_Actor->GetProperty()->SetDiffuse(0.0);
localStorage->m_Actor->GetProperty()->SetSpecular(0.0);
}
/*+++++++++++++++++++ LocalStorage part +++++++++++++++++++++++++*/
mitk::ContourModelMapper2D::LocalStorage* mitk::ContourModelMapper2D::GetLocalStorage(mitk::BaseRenderer* renderer)
{
return m_LSH.GetLocalStorage(renderer);
}
mitk::ContourModelMapper2D::LocalStorage::LocalStorage()
{
m_Mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
m_Actor = vtkSmartPointer<vtkActor>::New();
m_OutlinePolyData = vtkSmartPointer<vtkPolyData>::New();
//set the mapper for the actor
m_Actor->SetMapper(m_Mapper);
}
void mitk::ContourModelMapper2D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite)
{
node->AddProperty( "color", ColorProperty::New(0.9, 1.0, 0.1), renderer, overwrite );
node->AddProperty( "width", mitk::FloatProperty::New( 1.0 ), renderer, overwrite );
node->AddProperty( "use cutting plane", mitk::BoolProperty::New( true ), renderer, overwrite );
node->AddProperty( "subdivision curve", mitk::BoolProperty::New( false ), renderer, overwrite );
Superclass::SetDefaultProperties(node, renderer, overwrite);
}
diff --git a/Modules/ContourModel/Rendering/mitkContourModelMapper3D.cpp b/Modules/ContourModel/Rendering/mitkContourModelMapper3D.cpp
index a38fe8ee8f..8607d7e97e 100644
--- a/Modules/ContourModel/Rendering/mitkContourModelMapper3D.cpp
+++ b/Modules/ContourModel/Rendering/mitkContourModelMapper3D.cpp
@@ -1,243 +1,243 @@
/*===================================================================
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 <mitkContourModelMapper3D.h>
#include <vtkPoints.h>
#include <vtkCellArray.h>
#include <vtkProperty.h>
mitk::ContourModelMapper3D::ContourModelMapper3D()
{
}
mitk::ContourModelMapper3D::~ContourModelMapper3D()
{
}
const mitk::ContourModel* mitk::ContourModelMapper3D::GetInput( void )
{
//convient way to get the data from the dataNode
return static_cast< const mitk::ContourModel * >( GetDataNode()->GetData() );
}
vtkProp* mitk::ContourModelMapper3D::GetVtkProp(mitk::BaseRenderer* renderer)
{
//return the actor corresponding to the renderer
return m_LSH.GetLocalStorage(renderer)->m_Actor;
}
void mitk::ContourModelMapper3D::GenerateDataForRenderer( mitk::BaseRenderer *renderer )
{
/* First convert the contourModel to vtkPolyData, then tube filter it and
* set it input for our mapper
*/
LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);
mitk::ContourModel* inputContour = static_cast< mitk::ContourModel* >( GetDataNode()->GetData() );
localStorage->m_OutlinePolyData = this->CreateVtkPolyDataFromContour(inputContour);
this->ApplyContourProperties(renderer);
//tube filter the polyData
localStorage->m_TubeFilter->SetInputData(localStorage->m_OutlinePolyData);
float lineWidth(1.0);
if (this->GetDataNode()->GetFloatProperty( "contour.3D.width", lineWidth, renderer ))
{
localStorage->m_TubeFilter->SetRadius(lineWidth);
}else
{
localStorage->m_TubeFilter->SetRadius(0.5);
}
localStorage->m_TubeFilter->CappingOn();
localStorage->m_TubeFilter->SetNumberOfSides(10);
localStorage->m_TubeFilter->Update();
localStorage->m_Mapper->SetInputConnection(localStorage->m_TubeFilter->GetOutputPort());
}
void mitk::ContourModelMapper3D::Update(mitk::BaseRenderer* renderer)
{
bool visible = true;
GetDataNode()->GetVisibility(visible, renderer, "visible");
mitk::ContourModel* data = static_cast< mitk::ContourModel*>( GetDataNode()->GetData() );
if ( data == NULL )
{
return;
}
// Calculate time step of the input data for the specified renderer (integer value)
this->CalculateTimeStep( renderer );
LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);
// Check if time step is valid
const TimeGeometry *dataTimeGeometry = data->GetTimeGeometry();
if ( ( dataTimeGeometry == NULL )
|| ( dataTimeGeometry->CountTimeSteps() == 0 )
|| ( !dataTimeGeometry->IsValidTimeStep( renderer->GetTimeStep() ) )
|| ( this->GetTimestep() == -1 ) )
{
//clear the rendered polydata
localStorage->m_Mapper->SetInputData(vtkSmartPointer<vtkPolyData>::New());
return;
}
const DataNode *node = this->GetDataNode();
data->UpdateOutputInformation();
//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 < renderer->GetCurrentWorldPlaneGeometryUpdateTime()) //was the geometry modified?
+ || (localStorage->m_LastUpdateTime < renderer->GetCurrentWorldPlaneGeometry()->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();
}
vtkSmartPointer<vtkPolyData> mitk::ContourModelMapper3D::CreateVtkPolyDataFromContour(mitk::ContourModel* inputContour)
{
unsigned int timestep = this->GetTimestep();
//the points to draw
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
//the lines to connect the points
vtkSmartPointer<vtkCellArray> lines = vtkSmartPointer<vtkCellArray>::New();
// Create a polydata to store everything in
vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New();
//iterate over the control points
mitk::ContourModel::VertexIterator current = inputContour->IteratorBegin(timestep);
mitk::ContourModel::VertexIterator next = inputContour->IteratorBegin(timestep);
if(next != inputContour->IteratorEnd(timestep))
{
next++;
mitk::ContourModel::VertexIterator end = inputContour->IteratorEnd(timestep);
while(next != end)
{
mitk::ContourModel::VertexType* currentControlPoint = *current;
mitk::ContourModel::VertexType* nextControlPoint = *next;
if( !(currentControlPoint->Coordinates[0] == nextControlPoint->Coordinates[0] &&
currentControlPoint->Coordinates[1] == nextControlPoint->Coordinates[1] &&
currentControlPoint->Coordinates[2] == nextControlPoint->Coordinates[2]))
{
vtkIdType p1 = points->InsertNextPoint(currentControlPoint->Coordinates[0], currentControlPoint->Coordinates[1], currentControlPoint->Coordinates[2]);
vtkIdType p2 = points->InsertNextPoint(nextControlPoint->Coordinates[0], nextControlPoint->Coordinates[1], nextControlPoint->Coordinates[2]);
//add the line between both contorlPoints
lines->InsertNextCell(2);
lines->InsertCellPoint(p1);
lines->InsertCellPoint(p2);
}
current++;
next++;
}
if(inputContour->IsClosed(timestep))
{
// If the contour is closed add a line from the last to the first control point
mitk::ContourModel::VertexType* firstControlPoint = *(inputContour->IteratorBegin(timestep));
mitk::ContourModel::VertexType* lastControlPoint = *(--(inputContour->IteratorEnd(timestep)));
if( lastControlPoint->Coordinates[0] != firstControlPoint->Coordinates[0] ||
lastControlPoint->Coordinates[1] != firstControlPoint->Coordinates[1] ||
lastControlPoint->Coordinates[2] != firstControlPoint->Coordinates[2])
{
vtkIdType p2 = points->InsertNextPoint(lastControlPoint->Coordinates[0], lastControlPoint->Coordinates[1], lastControlPoint->Coordinates[2]);
vtkIdType p1 = points->InsertNextPoint(firstControlPoint->Coordinates[0], firstControlPoint->Coordinates[1], firstControlPoint->Coordinates[2]);
//add the line to the cellArray
lines->InsertNextCell(2);
lines->InsertCellPoint(p1);
lines->InsertCellPoint(p2);
}
}
// Add the points to the dataset
polyData->SetPoints(points);
// Add the lines to the dataset
polyData->SetLines(lines);
}
return polyData;
}
void mitk::ContourModelMapper3D::ApplyContourProperties(mitk::BaseRenderer* renderer)
{
LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);
mitk::ColorProperty::Pointer colorprop = dynamic_cast<mitk::ColorProperty*>(GetDataNode()->GetProperty
("contour.color", renderer));
if(colorprop)
{
//set the color of the contour
double red = colorprop->GetColor().GetRed();
double green = colorprop->GetColor().GetGreen();
double blue = colorprop->GetColor().GetBlue();
localStorage->m_Actor->GetProperty()->SetColor(red, green, blue);
}
}
/*+++++++++++++++++++ LocalStorage part +++++++++++++++++++++++++*/
mitk::ContourModelMapper3D::LocalStorage* mitk::ContourModelMapper3D::GetLocalStorage(mitk::BaseRenderer* renderer)
{
return m_LSH.GetLocalStorage(renderer);
}
mitk::ContourModelMapper3D::LocalStorage::LocalStorage()
{
m_Mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
m_Actor = vtkSmartPointer<vtkActor>::New();
m_OutlinePolyData = vtkSmartPointer<vtkPolyData>::New();
m_TubeFilter = vtkSmartPointer<vtkTubeFilter>::New();
//set the mapper for the actor
m_Actor->SetMapper(m_Mapper);
}
void mitk::ContourModelMapper3D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite)
{
node->AddProperty( "color", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite );
node->AddProperty( "contour.3D.width", mitk::FloatProperty::New( 0.5 ), renderer, overwrite );
Superclass::SetDefaultProperties(node, renderer, overwrite);
}
diff --git a/Modules/ContourModel/Rendering/mitkContourModelSetMapper3D.cpp b/Modules/ContourModel/Rendering/mitkContourModelSetMapper3D.cpp
index 5de27d6f60..5c2a4dc5df 100644
--- a/Modules/ContourModel/Rendering/mitkContourModelSetMapper3D.cpp
+++ b/Modules/ContourModel/Rendering/mitkContourModelSetMapper3D.cpp
@@ -1,206 +1,206 @@
/*===================================================================
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 <mitkContourModelSetMapper3D.h>
#include <vtkPoints.h>
#include <vtkCellArray.h>
#include <vtkProperty.h>
#include "mitkSurface.h"
mitk::ContourModelSetMapper3D::ContourModelSetMapper3D()
{
}
mitk::ContourModelSetMapper3D::~ContourModelSetMapper3D()
{
}
const mitk::ContourModelSet* mitk::ContourModelSetMapper3D::GetInput( void )
{
//convient way to get the data from the dataNode
return static_cast< const mitk::ContourModelSet * >( GetDataNode()->GetData() );
}
vtkProp* mitk::ContourModelSetMapper3D::GetVtkProp(mitk::BaseRenderer* renderer)
{
//return the actor corresponding to the renderer
return m_LSH.GetLocalStorage(renderer)->m_Assembly;
}
void mitk::ContourModelSetMapper3D::GenerateDataForRenderer( mitk::BaseRenderer *renderer )
{
/* First convert the contourModel to vtkPolyData, then tube filter it and
* set it input for our mapper
*/
LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);
mitk::ContourModelSet* contourSet = static_cast< mitk::ContourModelSet* >( GetDataNode()->GetData() );
mitk::ContourModelSet::ContourModelSetIterator it = contourSet->Begin();
mitk::ContourModelSet::ContourModelSetIterator end = contourSet->End();
while(it!=end)
{
mitk::ContourModel* inputContour = it->GetPointer();
vtkSmartPointer<vtkPolyData> polyData = this->CreateVtkPolyDataFromContour(inputContour, renderer);
vtkSmartPointer<vtkTubeFilter> tubeFilter = vtkSmartPointer<vtkTubeFilter>::New();
tubeFilter->SetInputData(polyData);
float lineWidth(1.0);
if (this->GetDataNode()->GetFloatProperty( "contour.3D.width", lineWidth, renderer ))
{
tubeFilter->SetRadius(lineWidth);
}else
{
tubeFilter->SetRadius(0.5);
}
tubeFilter->CappingOn();
tubeFilter->SetNumberOfSides(10);
tubeFilter->Update();
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
mapper->SetInputConnection(tubeFilter->GetOutputPort());
//mapper->SetInput(polyData);
localStorage->m_Assembly->AddPart(actor);
++it;
}
this->ApplyContourProperties(renderer);
}
void mitk::ContourModelSetMapper3D::Update(mitk::BaseRenderer* renderer)
{
bool visible = true;
GetDataNode()->GetVisibility(visible, renderer, "visible");
mitk::ContourModel* data = static_cast< mitk::ContourModel*>( GetDataNode()->GetData() );
if ( data == NULL )
{
return;
}
// Calculate time step of the input data for the specified renderer (integer value)
this->CalculateTimeStep( renderer );
LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);
if ( this->GetTimestep() == -1 )
{
return;
}
const DataNode *node = this->GetDataNode();
data->UpdateOutputInformation();
//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 < renderer->GetCurrentWorldPlaneGeometryUpdateTime()) //was the geometry modified?
+ || (localStorage->m_LastUpdateTime < renderer->GetCurrentWorldPlaneGeometry()->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();
}
vtkSmartPointer<vtkPolyData> mitk::ContourModelSetMapper3D::CreateVtkPolyDataFromContour(mitk::ContourModel* inputContour, mitk::BaseRenderer* renderer)
{
unsigned int timestep = this->GetTimestep();
LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);
localStorage->m_contourToPolyData->SetInput(inputContour);
localStorage->m_contourToPolyData->Update();
vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New();
polyData = localStorage->m_contourToPolyData->GetOutput()->GetVtkPolyData(timestep);
return polyData;
}
void mitk::ContourModelSetMapper3D::ApplyContourProperties(mitk::BaseRenderer* renderer)
{
LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);
mitk::ColorProperty::Pointer colorprop = dynamic_cast<mitk::ColorProperty*>(GetDataNode()->GetProperty
("contour.color", renderer));
if(colorprop)
{
//set the color of the contour
double red = colorprop->GetColor().GetRed();
double green = colorprop->GetColor().GetGreen();
double blue = colorprop->GetColor().GetBlue();
vtkSmartPointer<vtkPropCollection> collection = vtkSmartPointer<vtkPropCollection>::New();
localStorage->m_Assembly->GetActors(collection);
collection->InitTraversal();
for(vtkIdType i = 0; i < collection->GetNumberOfItems(); i++)
{
vtkActor::SafeDownCast(collection->GetNextProp())->GetProperty()->SetColor(red, green, blue);
}
}
}
/*+++++++++++++++++++ LocalStorage part +++++++++++++++++++++++++*/
mitk::ContourModelSetMapper3D::LocalStorage* mitk::ContourModelSetMapper3D::GetLocalStorage(mitk::BaseRenderer* renderer)
{
return m_LSH.GetLocalStorage(renderer);
}
mitk::ContourModelSetMapper3D::LocalStorage::LocalStorage()
{
m_Assembly = vtkSmartPointer<vtkAssembly>::New();
m_contourToPolyData = mitk::ContourModelToSurfaceFilter::New();
}
void mitk::ContourModelSetMapper3D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite)
{
node->AddProperty( "color", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite );
node->AddProperty( "contour.3D.width", mitk::FloatProperty::New( 0.5 ), renderer, overwrite );
Superclass::SetDefaultProperties(node, renderer, overwrite);
}
diff --git a/Modules/DataTypesExt/mitkBoundingObject.cpp b/Modules/DataTypesExt/mitkBoundingObject.cpp
index c3755b4ac2..0c5340b0f5 100644
--- a/Modules/DataTypesExt/mitkBoundingObject.cpp
+++ b/Modules/DataTypesExt/mitkBoundingObject.cpp
@@ -1,72 +1,72 @@
/*===================================================================
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 "mitkBoundingObject.h"
#include "mitkBaseProcess.h"
mitk::BoundingObject::BoundingObject()
: Surface(), m_Positive(true)
{
// Initialize(1);
/* bounding box around the unscaled bounding object */
ScalarType bounds[6]={-1,1,-1,1,-1,1}; //{xmin,x_max, ymin,y_max,zmin,z_max}
GetGeometry()->SetBounds(bounds);
GetTimeGeometry()->Update();
}
mitk::BoundingObject::~BoundingObject()
{
}
mitk::ScalarType mitk::BoundingObject::GetVolume()
{
return 0.0;
}
-void mitk::BoundingObject::FitGeometry(mitk::Geometry3D* aGeometry3D)
+void mitk::BoundingObject::FitGeometry(mitk::BaseGeometry* aGeometry3D)
{
// Adjusted this function to fix
// BUG 6951 - Image Cropper - Bounding Box is strange
// Still, the behavior of the BoundingObject is really strange.
// One would think that writing "setGeometry(aGeometry3D)" here would do the job.
// But apparently the boundingObject can only be handled correctly, when it's
// indexBounds are from -1 to 1 in all axis (so it is only 2x2x2 Pixels big) and the spacing
// specifies it's actual bounds. This behavior needs to be analyzed and maybe changed.
// Check also BUG 11406
GetGeometry()->SetIdentity();
GetGeometry()->Compose(aGeometry3D->GetIndexToWorldTransform());
// Since aGeometry (which should actually be const), is an imagegeometry and boundingObject is NOT an image,
// we have to adjust the Origin by shifting it half pixel
mitk::Point3D myOrigin = aGeometry3D->GetCenter();
myOrigin[0] -= (aGeometry3D->GetSpacing()[0] / 2.0);
myOrigin[1] -= (aGeometry3D->GetSpacing()[1] / 2.0);
myOrigin[2] -= (aGeometry3D->GetSpacing()[2] / 2.0);
GetGeometry()->SetOrigin(myOrigin);
mitk::Vector3D size;
for(unsigned int i=0; i < 3; ++i)
size[i] = (aGeometry3D->GetExtentInMM(i)/2.0);
GetGeometry()->SetSpacing( size );
GetTimeGeometry()->Update();
}
diff --git a/Modules/DataTypesExt/mitkBoundingObject.h b/Modules/DataTypesExt/mitkBoundingObject.h
index 54db79458f..8e603d724e 100644
--- a/Modules/DataTypesExt/mitkBoundingObject.h
+++ b/Modules/DataTypesExt/mitkBoundingObject.h
@@ -1,69 +1,69 @@
/*===================================================================
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 BOUNDINGOBJECT_H_HEADER_INCLUDED
#define BOUNDINGOBJECT_H_HEADER_INCLUDED
#include <mitkSurface.h>
#include "MitkDataTypesExtExports.h"
namespace mitk {
//##Documentation
//## @brief superclass of all bounding objects (cylinder, cuboid,...)
//##
//## Manages generic functions and provides an interface for IsInside()
//## calculates a generic bounding box
//## @ingroup Data
class MitkDataTypesExt_EXPORT BoundingObject : public mitk::Surface //BaseData
{
public:
mitkClassMacro(BoundingObject, mitk::Surface);
virtual bool IsInside(const mitk::Point3D& p) const=0;
virtual mitk::ScalarType GetVolume();
itkGetMacro(Positive, bool);
itkSetMacro(Positive, bool);
itkBooleanMacro(Positive);
//##Documentation
//## @brief Sets the Geometry3D of the bounding object to fit the given
//## geometry.
//##
//## The fit is done once, so if the given geometry changes it will
//## \em not effect the bounding object.
- virtual void FitGeometry(Geometry3D* aGeometry3D);
+ virtual void FitGeometry(BaseGeometry* aGeometry3D);
protected:
BoundingObject();
virtual ~BoundingObject();
bool WriteXMLData( XMLWriter& xmlWriter );
//##Documentation
//## \brief If \a true, the Boundingobject describes a positive volume,
//## if \a false a negative volume.
//##
bool m_Positive;
private:
BoundingObject(const BoundingObject&);
BoundingObject& operator=(const BoundingObject&);
};
}
#endif /* BOUNDINGOBJECT_H_HEADER_INCLUDED */
diff --git a/Modules/DataTypesExt/mitkBoundingObjectGroup.cpp b/Modules/DataTypesExt/mitkBoundingObjectGroup.cpp
index d274470911..7054a19332 100644
--- a/Modules/DataTypesExt/mitkBoundingObjectGroup.cpp
+++ b/Modules/DataTypesExt/mitkBoundingObjectGroup.cpp
@@ -1,208 +1,208 @@
/*===================================================================
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 "mitkBoundingObjectGroup.h"
#include "mitkBaseProcess.h"
#include <vtkLinearTransform.h>
#include <mitkProportionalTimeGeometry.h>
mitk::BoundingObjectGroup::BoundingObjectGroup()
:m_BoundingObjects(0),
m_Counter(0),
m_CSGMode(Union)// m_CSGMode(Difference) //m_CSGMode(Intersection)
{
ProportionalTimeGeometry::Pointer timeGeometry = ProportionalTimeGeometry::New();
timeGeometry->Initialize(1);
SetTimeGeometry(timeGeometry);
SetVtkPolyData(NULL);
}
mitk::BoundingObjectGroup::~BoundingObjectGroup()
{
}
void mitk::BoundingObjectGroup::UpdateOutputInformation()
{
if ( this->GetSource() )
{
this->GetSource()->UpdateOutputInformation();
}
// calculate global bounding box
if(m_BoundingObjects.size() < 1 ) // if there is no BoundingObject, the bounding box is zero
{
mitk::BoundingBox::BoundsArrayType boundsArray;
boundsArray.Fill(0);
ProportionalTimeGeometry::Pointer timeGeometry = ProportionalTimeGeometry::New();
timeGeometry->Initialize(1);
SetTimeGeometry(timeGeometry);
GetGeometry()->SetBounds(boundsArray);
GetTimeGeometry()->Update();
return;
}
// initialize container
mitk::BoundingBox::PointsContainer::Pointer pointscontainer=mitk::BoundingBox::PointsContainer::New();
mitk::BoundingBox::PointIdentifier pointid=0;
mitk::Point3D point;
mitk::AffineTransform3D* transform = GetGeometry()->GetIndexToWorldTransform();
mitk::AffineTransform3D::Pointer inverse = mitk::AffineTransform3D::New();
transform->GetInverse(inverse);
// calculate a bounding box that includes all BoundingObjects
// \todo probably we should do this additionally for each time-step
//while (boundingObjectsIterator != boundingObjectsIteratorEnd)
for(unsigned int j = 0; j<m_BoundingObjects.size();j++)
{
const TimeGeometry* geometry = m_BoundingObjects.at(j)->GetUpdatedTimeGeometry();
unsigned char i;
for(i=0; i<8; ++i)
{
point = inverse->TransformPoint(geometry->GetCornerPointInWorld(i));
if(point[0]*point[0]+point[1]*point[1]+point[2]*point[2] < mitk::large)
pointscontainer->InsertElement( pointid++, point);
else
{
itkGenericOutputMacro( << "Unrealistically distant corner point encountered. Ignored. BoundingObject: " << m_BoundingObjects.at(j) );
}
}
}
mitk::BoundingBox::Pointer boundingBox = mitk::BoundingBox::New();
boundingBox->SetPoints(pointscontainer);
boundingBox->ComputeBoundingBox();
- Geometry3D* geometry3d = GetGeometry(0);
+ BaseGeometry* geometry3d = GetGeometry(0);
geometry3d->SetIndexToWorldTransform(transform);
geometry3d->SetBounds(boundingBox->GetBounds());
/* the objects position is the center of all sub bounding objects */
//geometry3d->SetOrigin(center);
ProportionalTimeGeometry::Pointer timeGeometry = ProportionalTimeGeometry::New();
timeGeometry->Initialize(geometry3d, GetTimeGeometry()->CountTimeSteps());
SetTimeGeometry(timeGeometry);
}
void mitk::BoundingObjectGroup::AddBoundingObject(mitk::BoundingObject::Pointer boundingObject)
{
if (boundingObject->GetPositive())
m_BoundingObjects.push_front(boundingObject);
else
m_BoundingObjects.push_back(boundingObject);
++m_Counter;
UpdateOutputInformation();
}
void mitk::BoundingObjectGroup::RemoveBoundingObject(mitk::BoundingObject::Pointer boundingObject)
{
std::deque<mitk::BoundingObject::Pointer>::iterator it = m_BoundingObjects.begin();
for (unsigned int i=0 ; i<m_BoundingObjects.size();i++)
{
if (m_BoundingObjects.at(i) == boundingObject)
m_BoundingObjects.erase(it);
++it;
}
--m_Counter;
UpdateOutputInformation();
}
bool mitk::BoundingObjectGroup::IsInside(const mitk::Point3D& p) const
{
bool inside = false; // initialize with true for intersection, with false for union
bool posInside = false;
bool negInside = false;
for (unsigned int i = 0; i<m_BoundingObjects.size();i++)
{
switch(m_CSGMode)
{
case Intersection:
inside = true;
// calculate intersection: each point, that is inside each BoundingObject is considered inside the group
inside = m_BoundingObjects.at(i)->IsInside(p) && inside;
if (!inside) // shortcut, it is enough to find one object that does not contain the point
i=m_BoundingObjects.size();
break;
case Union:
case Difference:
posInside = false;
negInside = false;
// calculate union: each point, that is inside least one BoundingObject is considered inside the group
if (m_BoundingObjects.at(i)->GetPositive())
posInside = m_BoundingObjects.at(i)->IsInside(p) || posInside;
else
negInside = m_BoundingObjects.at(i)->IsInside(p) || negInside;
if (posInside && !negInside)
inside = true;
else
inside = false;
break;
default:
inside = false;
// calculate union: each point, that is inside least one BoundingObject is considered inside the group
inside = m_BoundingObjects.at(i)->IsInside(p) || inside;
if (inside) // shortcut, it is enough to find one object that contains the point
i=m_BoundingObjects.size();
break;
}
}
return inside;
}
unsigned int mitk::BoundingObjectGroup::GetCount() const
{
return m_Counter;
}
bool mitk::BoundingObjectGroup::VerifyRequestedRegion()
{
return m_Counter > 0;
}
-mitk::Geometry3D * mitk::BoundingObjectGroup::GetGeometry (int t) const
+mitk::BaseGeometry * mitk::BoundingObjectGroup::GetGeometry (int t) const
{
//if ( m_BoundingObjects == NULL )
return Superclass::GetGeometry(t);
//mitk::BoundingObjectGroup::BoundingObjectContainer::ConstIterator boI = m_BoundingObjects->Begin();
//const mitk::BoundingObjectGroup::BoundingObjectContainer::ConstIterator boIEnd = m_BoundingObjects->End();
//mitk::Geometry3D* currentGeometry = NULL;
//while ( boI != boIEnd )
//{
// currentGeometry = boI.Value()->GetGeometry( t );
// boI++;
//}
//return currentGeometry;
}
void mitk::BoundingObjectGroup::SetBoundingObjects(const std::deque<mitk::BoundingObject::Pointer> boundingObjects)
{
m_BoundingObjects = boundingObjects;
}
std::deque<mitk::BoundingObject::Pointer> mitk::BoundingObjectGroup::GetBoundingObjects()
{
return m_BoundingObjects;
}
diff --git a/Modules/DataTypesExt/mitkBoundingObjectGroup.h b/Modules/DataTypesExt/mitkBoundingObjectGroup.h
index c7a18c25fe..81fe69e67b 100644
--- a/Modules/DataTypesExt/mitkBoundingObjectGroup.h
+++ b/Modules/DataTypesExt/mitkBoundingObjectGroup.h
@@ -1,71 +1,71 @@
/*===================================================================
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 BOUNDINGOBJECTGROUP_H_HEADER_INCLUDED
#define BOUNDINGOBJECTGROUP_H_HEADER_INCLUDED
#include <mitkBoundingObject.h>
#include "MitkDataTypesExtExports.h"
#include <deque>
namespace mitk {
//##Documentation
//## @brief group object, that contains several mitk::BoundingObjects
//##
//## Calculates a bounding box that contains all sub-bounding boxes.
//## @ingroup Data
class MitkDataTypesExt_EXPORT BoundingObjectGroup : public mitk::BoundingObject
{
public:
enum CSGMode
{
Union,
Intersection,
Difference
};
mitkClassMacro(BoundingObjectGroup, mitk::BoundingObject);// itk::VectorContainer<unsigned int ,mitk::BoundingObject::Pointer>);
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
virtual void UpdateOutputInformation();
virtual bool IsInside(const mitk::Point3D& p) const;
void SetBoundingObjects(const std::deque<mitk::BoundingObject::Pointer> boundingObjects);
std::deque<mitk::BoundingObject::Pointer> GetBoundingObjects();
itkSetMacro(CSGMode, mitk::BoundingObjectGroup::CSGMode);
itkGetMacro(CSGMode, mitk::BoundingObjectGroup::CSGMode);
void AddBoundingObject(mitk::BoundingObject::Pointer boundingObject);
void RemoveBoundingObject(mitk::BoundingObject::Pointer boundingObject);
unsigned int GetCount() const;
- mitk::Geometry3D * GetGeometry (int t=0) const;
+ mitk::BaseGeometry * GetGeometry (int t=0) const;
virtual bool VerifyRequestedRegion();
protected:
BoundingObjectGroup();
virtual ~BoundingObjectGroup();
std::deque<mitk::BoundingObject::Pointer> m_BoundingObjects;
unsigned int m_Counter;
CSGMode m_CSGMode;
};
}
#endif /* BOUNDINGOBJECTGROUP_H_HEADER_INCLUDED */
diff --git a/Modules/DataTypesExt/mitkCompressedImageContainer.h b/Modules/DataTypesExt/mitkCompressedImageContainer.h
index 8a094bea72..9a5c231246 100644
--- a/Modules/DataTypesExt/mitkCompressedImageContainer.h
+++ b/Modules/DataTypesExt/mitkCompressedImageContainer.h
@@ -1,87 +1,87 @@
/*===================================================================
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 mitkCompressedImageContainer_h_Included
#define mitkCompressedImageContainer_h_Included
#include "mitkCommon.h"
#include "MitkDataTypesExtExports.h"
#include "mitkImage.h"
#include "mitkGeometry3D.h"
#include "mitkImageDataItem.h"
#include <itkObject.h>
#include <vector>
namespace mitk
{
/**
\brief Holds one (compressed) mitk::Image
Uses zlib to compress the data of an mitk::Image.
$Author$
*/
class MitkDataTypesExt_EXPORT CompressedImageContainer : public itk::Object
{
public:
mitkClassMacro(CompressedImageContainer, Object);
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/**
* \brief Creates a compressed version of the image.
*
* Will not hold any further SmartPointers to the image.
*
*/
void SetImage( Image* );
/**
* \brief Creates a full mitk::Image from its compressed version.
*
* This Method hold no buffer, so the uncompression algorithm will be
* executed every time you call this method. Don't overdo it.
*
*/
Image::Pointer GetImage();
protected:
CompressedImageContainer(); // purposely hidden
virtual ~CompressedImageContainer();
PixelType *m_PixelType;
unsigned int m_ImageDimension;
std::vector<unsigned int> m_ImageDimensions;
unsigned long m_OneTimeStepImageSizeInBytes;
unsigned int m_NumberOfTimeSteps;
/// one for each timestep. first = pointer to compressed data; second = size of buffer in bytes
std::vector< std::pair<unsigned char*, unsigned long> > m_ByteBuffers;
- Geometry3D::Pointer m_ImageGeometry;
+ BaseGeometry::Pointer m_ImageGeometry;
};
} // namespace
#endif
diff --git a/Modules/DataTypesExt/mitkLabeledImageVolumeCalculator.cpp b/Modules/DataTypesExt/mitkLabeledImageVolumeCalculator.cpp
index 02364f84b1..67e9f20dd4 100644
--- a/Modules/DataTypesExt/mitkLabeledImageVolumeCalculator.cpp
+++ b/Modules/DataTypesExt/mitkLabeledImageVolumeCalculator.cpp
@@ -1,146 +1,146 @@
/*===================================================================
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 "mitkLabeledImageVolumeCalculator.h"
#include "mitkImageAccessByItk.h"
#include <itkImageRegionConstIteratorWithIndex.h>
namespace mitk
{
LabeledImageVolumeCalculator::LabeledImageVolumeCalculator()
{
m_InputTimeSelector = ImageTimeSelector::New();
m_DummyPoint.Fill( 0.0 );
}
LabeledImageVolumeCalculator::~LabeledImageVolumeCalculator()
{
}
double LabeledImageVolumeCalculator::GetVolume( unsigned int label ) const
{
if ( label < m_VolumeVector.size() )
return m_VolumeVector[label];
else
return 0.0;
}
const Point3D &LabeledImageVolumeCalculator::GetCentroid( unsigned int label ) const
{
if ( label < m_CentroidVector.size() )
return m_CentroidVector[label];
else
return m_DummyPoint;
}
const LabeledImageVolumeCalculator::VolumeVector &
LabeledImageVolumeCalculator::GetVolumes() const
{
return m_VolumeVector;
}
const LabeledImageVolumeCalculator::PointVector &
LabeledImageVolumeCalculator::GetCentroids() const
{
return m_CentroidVector;
}
void LabeledImageVolumeCalculator::Calculate()
{
if ( m_Image.IsNull() )
{
itkExceptionMacro( << "Image not set!" );
return;
}
m_InputTimeSelector->SetInput( m_Image );
m_InputTimeSelector->SetTimeNr( 0 );
m_InputTimeSelector->UpdateLargestPossibleRegion();
AccessByItk_2(
m_InputTimeSelector->GetOutput(),
_InternalCalculateVolumes,
this,
m_Image->GetGeometry( 0 ) );
//}
}
template < typename TPixel, unsigned int VImageDimension >
void LabeledImageVolumeCalculator::_InternalCalculateVolumes(
itk::Image< TPixel, VImageDimension > *image,
LabeledImageVolumeCalculator* /*volumeCalculator*/,
- Geometry3D *geometry )
+ BaseGeometry *geometry )
{
typedef itk::Image< TPixel, VImageDimension > ImageType;
typedef typename ImageType::IndexType IndexType;
typedef itk::ImageRegionConstIteratorWithIndex< ImageType > IteratorType;
// Reset volume and centroid vectors
m_VolumeVector.clear();
m_CentroidVector.clear();
// Iterate over image and determine number of voxels and centroid
// per label
IteratorType it( image, image->GetBufferedRegion() );
for ( it.GoToBegin(); !it.IsAtEnd(); ++it )
{
const IndexType &index = it.GetIndex();
unsigned int pixel = static_cast<unsigned int>( it.Get() );
if ( m_VolumeVector.size() <= pixel )
{
m_VolumeVector.resize( pixel + 1 );
m_CentroidVector.resize( pixel + 1 );
}
m_VolumeVector[pixel] += 1.0;
m_CentroidVector[pixel][0] += index[0];
m_CentroidVector[pixel][1] += index[1];
m_CentroidVector[pixel][2] += index[2];
}
// Calculate voxel volume from spacing
const Vector3D &spacing = geometry->GetSpacing();
double voxelVolume = spacing[0] * spacing[1] * spacing[2];
// Calculate centroid (in world coordinates) and volumes for all labels
for ( unsigned int i = 0; i < m_VolumeVector.size(); ++i )
{
if ( m_VolumeVector[i] > 0.0 )
{
m_CentroidVector[i][0] /= m_VolumeVector[i];
m_CentroidVector[i][1] /= m_VolumeVector[i];
m_CentroidVector[i][2] /= m_VolumeVector[i];
geometry->IndexToWorld( m_CentroidVector[i], m_CentroidVector[i] );
m_VolumeVector[i] *= voxelVolume;
}
}
}
}
diff --git a/Modules/DataTypesExt/mitkLabeledImageVolumeCalculator.h b/Modules/DataTypesExt/mitkLabeledImageVolumeCalculator.h
index b477e1665c..0f17e401da 100644
--- a/Modules/DataTypesExt/mitkLabeledImageVolumeCalculator.h
+++ b/Modules/DataTypesExt/mitkLabeledImageVolumeCalculator.h
@@ -1,97 +1,97 @@
/*===================================================================
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 _MITK_LABELEDIMAGEVOLUMECALCULATOR_H
#define _MITK_LABELEDIMAGEVOLUMECALCULATOR_H
#include <itkObject.h>
#include "MitkDataTypesExtExports.h"
#include "mitkImage.h"
#include "mitkImageTimeSelector.h"
#include <itkImage.h>
namespace mitk
{
/**
* \brief Class for calculating the volume (or area) for each label in a
* labeled image.
*
* Labels are expected to be of an unsigned integer type.
*
* TODO: Extend class for time resolved images
*/
class MitkDataTypesExt_EXPORT LabeledImageVolumeCalculator : public itk::Object
{
public:
typedef std::vector< double > VolumeVector;
typedef std::vector< Point3D > PointVector;
mitkClassMacro( LabeledImageVolumeCalculator, itk::Object );
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
itkSetConstObjectMacro( Image, mitk::Image );
virtual void Calculate();
double GetVolume( unsigned int label ) const;
const Point3D &GetCentroid( unsigned int label ) const;
const VolumeVector &GetVolumes() const;
const PointVector &GetCentroids() const;
protected:
LabeledImageVolumeCalculator();
virtual ~LabeledImageVolumeCalculator();
template < typename TPixel, unsigned int VImageDimension >
void _InternalCalculateVolumes(
itk::Image< TPixel, VImageDimension > *image,
LabeledImageVolumeCalculator *volumeCalculator,
- Geometry3D *geometry );
+ BaseGeometry *geometry );
ImageTimeSelector::Pointer m_InputTimeSelector;
Image::ConstPointer m_Image;
VolumeVector m_VolumeVector;
PointVector m_CentroidVector;
Point3D m_DummyPoint;
};
}
#endif // #define _MITK_LABELEDIMAGEVOLUMECALCULATOR_H
diff --git a/Modules/DataTypesExt/mitkMeshUtil.h b/Modules/DataTypesExt/mitkMeshUtil.h
index b276b30b27..b0ce97b42c 100644
--- a/Modules/DataTypesExt/mitkMeshUtil.h
+++ b/Modules/DataTypesExt/mitkMeshUtil.h
@@ -1,1603 +1,1603 @@
/*===================================================================
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 MITKMESHUTIL_H_INCLUDED
#define MITKMESHUTIL_H_INCLUDED
#if(_MSC_VER==1200)
#error MeshUtils currently not supported for MS Visual C++ 6.0. Sorry.
#endif
//#include <itkMesh.h>
#include <itkLineCell.h>
#include <itkTriangleCell.h>
#include <itkPolygonCell.h>
#include <itkQuadrilateralCell.h>
#include <itkCellInterface.h>
//#include <itkDefaultDynamicMeshTraits.h>
#include <itkSphereMeshSource.h>
//#include <itkTransformMeshFilter.h>
//#include <itkTranslationTransform.h>
//#include <itkMinimumMaximumImageCalculator.h>
#include <itkAutomaticTopologyMeshSource.h>
#include <itkRegularSphereMeshSource.h>
#include <vnl/vnl_cross.h>
#include <vtkActor.h>
#include <vtkCellArray.h>
#include <vtkPolyData.h>
#include <vtkUnstructuredGrid.h>
#include <vtkPoints.h>
#include <vtkPointData.h>
#include <vtkCellData.h>
#include <vtkProperty.h>
#include <vtkFloatArray.h>
-#include <mitkGeometry3D.h>
+#include <mitkBaseGeometry.h>
#include <mitkSurface.h>
template <typename MeshType>
class NullScalarAccessor
{
public:
static inline double GetPointScalar(typename MeshType::PointDataContainer* /*pointData*/, typename MeshType::PointIdentifier /*idx*/, MeshType* /*mesh*/ = NULL, unsigned int /*type*/ = 0)
{
return (double) 0.0;
};
static inline double GetCellScalar(typename MeshType::CellDataContainer* /*cellData*/, typename MeshType::CellIdentifier /*idx*/, MeshType* /*mesh*/ = NULL, unsigned int /*type*/ = 0)
{
return (double) 0.0;
};
};
template <typename MeshType>
class MeshScalarAccessor
{
public:
static inline double GetPointScalar(typename MeshType::PointDataContainer* pointData, typename MeshType::PointIdentifier idx, MeshType* /*mesh*/ = NULL, unsigned int /*type*/ = 0)
{
return (double)pointData->GetElement(idx);
};
static inline double GetCellScalar(typename MeshType::CellDataContainer* cellData, typename MeshType::CellIdentifier idx, MeshType* /*mesh*/ = NULL, unsigned int /*type*/ = 0)
{
return (double)cellData->GetElement(idx);
};
};
template <typename MeshType>
class MeanCurvatureAccessor : public NullScalarAccessor<MeshType>
{
public:
static inline double GetPointScalar(typename MeshType::PointDataContainer* /*point*/, typename MeshType::PointIdentifier idx, MeshType* mesh, unsigned int /*type*/ = 0)
{
typename MeshType::PixelType dis = 0;
mesh->GetPointData(idx, &dis);
return (double) dis;
};
};
template <typename MeshType>
class SimplexMeshAccessor : public NullScalarAccessor<MeshType>
{
public:
static inline double GetPointScalar(typename MeshType::PointDataContainer* point, typename MeshType::PointIdentifier idx, MeshType* mesh, unsigned int type = 0 )
{
typename MeshType::GeometryMapPointer geometryData = mesh->GetGeometryData();
if (type == 0)
{
double val = mesh->GetMeanCurvature( idx );
mesh->SetPointData(idx, val);
return val;
}
else if (type == 1)
{
double val = geometryData->GetElement(idx)->meanTension;
mesh->SetPointData(idx, val);
return val;
}
else if (type == 2)
{
double val = geometryData->GetElement(idx)->externalForce.GetNorm();
mesh->SetPointData(idx, val);
return val;
}
else if (type == 3)
return geometryData->GetElement(idx)->internalForce.GetNorm();
else if (type == 4)
return geometryData->GetElement(idx)->externalForce.GetNorm() *
mesh->GetDistance(idx);
else if (type == 5)
{
typename MeshType::PixelType dis = 0;
mesh->GetPointData(idx, &dis);
return (double) dis;
}
else if (type == 6)
{
return (double) ((geometryData->GetElement(idx))->allowSplitting);
}
else
return (double) 0;
};
};
/*!
\brief The class provides mehtods for ITK - VTK mesh conversion
*
* \todo document the inner class
* \todo maybe inner class should be moved out
*/
template <typename MeshType, class ScalarAccessor=NullScalarAccessor<MeshType> >
class MeshUtil
{
/*!
\brief A visitor to create VTK cells by means of a class
defining the InsertImplementation interface
The InsertImplementation interface defines the methods
\code
void InsertLine(vtkIdType *pts);
void InsertTriangle(vtkIdType *pts);
void InsertPolygon(vtkIdType npts, vtkIdType *pts);
void InsertQuad(vtkIdType *pts);
void InsertTetra(vtkIdType *pts);
void InsertHexahedron(vtkIdType *pts);
\endcode
This class calls the appropriate insert-method of the
InsertImplementation according to the cell type of
the visited cell \em and its actual contents: e.g.,
for a polygon cell with just two points, a line will
be created by calling InsertLine.
\sa ExactSwitchByCellType
\sa SingleCellArrayInsertImplementation
\sa DistributeInsertImplementation
*/
template <class InsertImplementation>
class SwitchByCellType : public InsertImplementation
{
// typedef the itk cells we are interested in
typedef typename itk::CellInterface< typename MeshType::CellPixelType,
typename MeshType::CellTraits > CellInterfaceType;
typedef itk::LineCell<CellInterfaceType> floatLineCell;
typedef itk::TriangleCell<CellInterfaceType> floatTriangleCell;
typedef itk::PolygonCell<CellInterfaceType> floatPolygonCell;
typedef itk::QuadrilateralCell<CellInterfaceType> floatQuadrilateralCell;
typedef itk::TetrahedronCell<CellInterfaceType> floatTetrahedronCell;
typedef itk::HexahedronCell<CellInterfaceType> floatHexahedronCell;
typedef typename CellInterfaceType::PointIdConstIterator PointIdIterator;
public:
/*!
Visit a line and create the VTK_LINE cell
*/
void Visit(unsigned long cellId, floatLineCell* t)
{
vtkIdType pts[2];
int i=0;
unsigned long num = t->GetNumberOfVertices();
vtkIdType vtkCellId = -1;
if (num==2) { // useless because itk::LineCell always returns 2
for (PointIdIterator it=t->PointIdsBegin(); it!=t->PointIdsEnd(); it++) pts[i++] = *it;
vtkCellId = this->InsertLine( (vtkIdType*)pts );
}
if (this->m_UseCellScalarAccessor && vtkCellId >= 0)
{
this->m_CellScalars->InsertTuple1(vtkCellId,
ScalarAccessor::GetCellScalar(this->m_CellData, cellId));
}
}
/*!
Visit a polygon and create the VTK_POLYGON cell
*/
void Visit(unsigned long cellId, floatPolygonCell* t)
{
vtkIdType pts[4096];
int i=0;
unsigned long num = t->GetNumberOfVertices();
vtkIdType vtkCellId = -1;
if (num > 4096) {
MITK_ERROR << "Problem in mitkMeshUtil: Polygon with more than maximum number of vertices encountered." << std::endl;
}
else if (num > 3) {
for (PointIdIterator it=t->PointIdsBegin(); it!=t->PointIdsEnd(); it++) pts[i++] = *it;
vtkCellId = this->InsertPolygon( num, (vtkIdType*)pts );
}
else if (num == 3) {
for (PointIdIterator it=t->PointIdsBegin(); it!=t->PointIdsEnd(); it++) pts[i++] = *it;
vtkCellId = this->InsertTriangle( (vtkIdType*)pts );
}
else if (num==2) {
for (PointIdIterator it=t->PointIdsBegin(); it!=t->PointIdsEnd(); it++) pts[i++] = *it;
vtkCellId = this->InsertLine( (vtkIdType*)pts );
}
if (this->m_UseCellScalarAccessor && vtkCellId >= 0)
{
this->m_CellScalars->InsertTuple1(vtkCellId,
ScalarAccessor::GetCellScalar(this->m_CellData, cellId));
}
}
/*!
Visit a triangle and create the VTK_TRIANGLE cell
*/
void Visit(unsigned long cellId, floatTriangleCell* t)
{
vtkIdType pts[3];
int i=0;
unsigned long num = t->GetNumberOfVertices();
vtkIdType vtkCellId = -1;
if (num == 3) {
for (PointIdIterator it=t->PointIdsBegin(); it!=t->PointIdsEnd(); it++) pts[i++] = *it;
vtkCellId = this->InsertTriangle( (vtkIdType*)pts );
}
else if (num==2) {
for (PointIdIterator it=t->PointIdsBegin(); it!=t->PointIdsEnd(); it++) pts[i++] = *it;
vtkCellId = this->InsertLine( (vtkIdType*)pts );
}
if (this->m_UseCellScalarAccessor && vtkCellId >= 0)
{
this->m_CellScalars->InsertTuple1(vtkCellId,
ScalarAccessor::GetCellScalar(this->m_CellData, cellId));
}
}
/*!
Visit a quad and create the VTK_QUAD cell
*/
void Visit(unsigned long cellId, floatQuadrilateralCell* t)
{
vtkIdType pts[4];
int i=0;
unsigned long num = t->GetNumberOfVertices();
vtkIdType vtkCellId = -1;
if (num == 4) {
for (PointIdIterator it=t->PointIdsBegin(); it!=t->PointIdsEnd(); it++)
{
if (i == 2) pts[3] = *it;
else if (i == 3) pts[2] = *it;
else pts[i] = *it;
i++;
//pts[i++] = *it;
}
vtkCellId = this->InsertQuad( (vtkIdType*)pts );
}
else if (num == 3) {
for (PointIdIterator it=t->PointIdsBegin(); it!=t->PointIdsEnd(); it++) pts[i++] = *it;
vtkCellId = this->InsertTriangle( (vtkIdType*)pts );
}
else if (num==2) {
for (PointIdIterator it=t->PointIdsBegin(); it!=t->PointIdsEnd(); it++) pts[i++] = *it;
vtkCellId = this->InsertLine( (vtkIdType*)pts );
}
if (this->m_UseCellScalarAccessor && vtkCellId >= 0)
{
this->m_CellScalars->InsertTuple1(vtkCellId,
ScalarAccessor::GetCellScalar(this->m_CellData, cellId));
}
}
/*!
Visit a tetrahedra and create the VTK_TETRA cell
*/
void Visit(unsigned long cellId, floatTetrahedronCell* t)
{
vtkIdType pts[4];
int i=0;
unsigned long num = t->GetNumberOfVertices();
vtkIdType vtkCellId = -1;
if (num == 4) {
for (PointIdIterator it=t->PointIdsBegin(); it!=t->PointIdsEnd(); it++) pts[i++] = *it;
vtkCellId = this->InsertTetra( (vtkIdType*)pts );
}
else if (num == 3) {
for (PointIdIterator it=t->PointIdsBegin(); it!=t->PointIdsEnd(); it++) pts[i++] = *it;
vtkCellId = this->InsertTriangle( (vtkIdType*)pts );
}
else if (num==2) {
for (PointIdIterator it=t->PointIdsBegin(); it!=t->PointIdsEnd(); it++) pts[i++] = *it;
vtkCellId = this->InsertLine( (vtkIdType*)pts );
}
if (this->m_UseCellScalarAccessor && vtkCellId >= 0)
{
this->m_CellScalars->InsertTuple1(vtkCellId,
ScalarAccessor::GetCellScalar(this->m_CellData, cellId));
}
}
/*!
Visit a hexahedron and create the VTK_HEXAHEDRON cell
*/
void Visit(unsigned long cellId, floatHexahedronCell* t)
{
vtkIdType pts[8];
int i=0;
unsigned long num = t->GetNumberOfVertices();
vtkIdType vtkCellId = -1;
if (num == 8) {
for (PointIdIterator it=t->PointIdsBegin(); it!=t->PointIdsEnd(); it++)
{
if (i == 2)
pts[i++] = *(it+1);
else if (i == 3)
pts[i++] = *(it-1);
else if (i == 6)
pts[i++] = *(it+1);
else if (i == 7)
pts[i++] = *(it-1);
else
pts[i++] = *it;
}
vtkCellId = this->InsertHexahedron( (vtkIdType*)pts );
}
else if (num == 4) {
for (PointIdIterator it=t->PointIdsBegin(); it!=t->PointIdsEnd(); it++) pts[i++] = *it;
vtkCellId = this->InsertQuad( (vtkIdType*)pts );
}
else if (num == 3) {
for (PointIdIterator it=t->PointIdsBegin(); it!=t->PointIdsEnd(); it++) pts[i++] = *it;
vtkCellId = this->InsertTriangle( (vtkIdType*)pts );
}
else if (num==2) {
for (PointIdIterator it=t->PointIdsBegin(); it!=t->PointIdsEnd(); it++) pts[i++] = *it;
vtkCellId = this->InsertLine( (vtkIdType*)pts );
}
if (this->m_UseCellScalarAccessor && vtkCellId >= 0)
{
this->m_CellScalars->InsertTuple1(vtkCellId,
ScalarAccessor::GetCellScalar(this->m_CellData, cellId));
}
}
};
/*!
\brief A visitor similar to SwitchByCellType, but with
exact matching of cell types
Works as described in SwitchByCellType, but does exact
matching of cell types, e.g., for a polygon cell with just
two points, \em no insert-method will be called, because
a polygon must have at least three points.
\sa SwitchByCellType
\sa SingleCellArrayInsertImplementation
\sa DistributeInsertImplementation
*/
template <class InsertImplementation>
class ExactSwitchByCellType : public InsertImplementation
{
// typedef the itk cells we are interested in
typedef typename itk::CellInterface< typename MeshType::CellPixelType,
typename MeshType::CellTraits > CellInterfaceType;
typedef itk::LineCell<CellInterfaceType> floatLineCell;
typedef itk::TriangleCell<CellInterfaceType> floatTriangleCell;
typedef itk::PolygonCell<CellInterfaceType> floatPolygonCell;
typedef itk::QuadrilateralCell<CellInterfaceType> floatQuadrilateralCell;
typedef itk::TetrahedronCell<CellInterfaceType> floatTetrahedronCell;
typedef itk::HexahedronCell<CellInterfaceType> floatHexahedronCell;
typedef typename CellInterfaceType::PointIdConstIterator PointIdIterator;
public:
/*!
Visit a line and create the VTK_LINE cell
*/
void Visit(unsigned long , floatLineCell* t)
{
unsigned long num = t->GetNumberOfVertices();
vtkIdType pts[2];
int i = 0;
if (num==2)
{
for (PointIdIterator it=t->PointIdsBegin(); it!=t->PointIdsEnd(); it++) pts[i++] = *it;
this->InsertLine(pts);
}
}
/*!
Visit a polygon and create the VTK_POLYGON cell
*/
void Visit(unsigned long , floatPolygonCell* t)
{
vtkIdType pts[4096];
unsigned long num = t->GetNumberOfVertices();
if (num > 4096) {
MITK_ERROR << "Problem in mitkMeshUtil: Polygon with more than maximum number of vertices encountered." << std::endl;
}
int i = 0;
if (num > 3)
{
for (PointIdIterator it=t->PointIdsBegin(); it!=t->PointIdsEnd(); it++) pts[i++] = *it;
this->InsertPolygon(num, pts);
}
}
/*!
Visit a triangle and create the VTK_TRIANGLE cell
*/
void Visit(unsigned long , floatTriangleCell* t)
{
unsigned long num = t->GetNumberOfVertices();
vtkIdType pts[3];
int i = 0;
if (num == 3)
{
for (PointIdIterator it=t->PointIdsBegin(); it!=t->PointIdsEnd(); it++) pts[i++] = *it;
this->InsertTriangle(pts);
}
}
/*!
Visit a quadrilateral and create the VTK_QUAD cell
*/
void Visit(unsigned long , floatQuadrilateralCell* t)
{
unsigned long num = t->GetNumberOfVertices();
vtkIdType pts[4];
int i = 0;
if (num == 4)
{
for (PointIdIterator it=t->PointIdsBegin(); it!=t->PointIdsEnd(); it++) pts[i++] = *it;
vtkIdType tmpId = pts[2];
pts[2] = pts[3];
pts[3] = tmpId;
this->InsertQuad(pts);
}
}
/*!
Visit a tetrahedron and create the VTK_TETRA cell
*/
void Visit(unsigned long , floatTetrahedronCell* t)
{
unsigned long num = t->GetNumberOfVertices();
vtkIdType pts[4];
int i = 0;
if (num == 4)
{
for (PointIdIterator it=t->PointIdsBegin(); it!=t->PointIdsEnd(); it++) pts[i++] = *it;
this->InsertTetra(pts);
}
}
/*!
Visit a hexahedron and create the VTK_HEXAHEDRON cell
*/
void Visit(unsigned long , floatHexahedronCell* t)
{
unsigned long num = t->GetNumberOfVertices();
vtkIdType pts[8];
int i = 0;
if (num == 8)
{
for (PointIdIterator it=t->PointIdsBegin(); it!=t->PointIdsEnd(); it++) pts[i++] = *it;
vtkIdType tmp[8];
for (unsigned int i = 0; i < 8; i++) tmp[i] = pts[i];
pts[2] = tmp[3];
pts[3] = tmp[2];
pts[6] = tmp[7];
pts[7] = tmp[6];
this->InsertHexahedron(pts);
}
}
};
/*!
\brief Implementation of the InsertImplementation interface of
SwitchByCellType to define a visitor that create cells
according to their types and put them in a single
vtkCellArray (for vtkUnstructuredGrid construction)
*/
class SingleCellArrayInsertImplementation
{
vtkCellArray* m_Cells;
int* m_TypeArray;
//vtkIdType cellId;
protected:
bool m_UseCellScalarAccessor;
vtkFloatArray* m_CellScalars;
typename MeshType::CellDataContainer::Pointer m_CellData;
public:
SingleCellArrayInsertImplementation() : m_UseCellScalarAccessor(false) {}
/*! Set the vtkCellArray that will be constructed
*/
void SetCellArray(vtkCellArray* cells)
{
m_Cells = cells;
}
/*!
Set the type array for storing the vtk cell types
*/
void SetTypeArray(int* i)
{
m_TypeArray = i;
}
void SetUseCellScalarAccessor(bool flag)
{
m_UseCellScalarAccessor = flag;
}
void SetCellScalars(vtkFloatArray* scalars)
{
m_CellScalars = scalars;
}
vtkFloatArray* GetCellScalars() { return m_CellScalars; }
void SetMeshCellData(typename MeshType::CellDataContainer* data)
{
m_CellData = data;
}
vtkIdType InsertLine(vtkIdType *pts)
{
vtkIdType cellId = m_Cells->InsertNextCell(2, pts);
m_TypeArray[cellId] = VTK_LINE;
return cellId;
}
vtkIdType InsertTriangle(vtkIdType *pts)
{
vtkIdType cellId = m_Cells->InsertNextCell(3, pts);
m_TypeArray[cellId] = VTK_TRIANGLE;
return cellId;
}
vtkIdType InsertPolygon(vtkIdType npts, vtkIdType *pts)
{
vtkIdType cellId = m_Cells->InsertNextCell(npts, pts);
m_TypeArray[cellId] = VTK_POLYGON;
return cellId;
}
vtkIdType InsertQuad(vtkIdType *pts)
{
vtkIdType cellId = m_Cells->InsertNextCell(4, pts);
m_TypeArray[cellId] = VTK_QUAD;
return cellId;
}
vtkIdType InsertTetra(vtkIdType *pts)
{
vtkIdType cellId = m_Cells->InsertNextCell(4, pts);
m_TypeArray[cellId] = VTK_TETRA;
return cellId;
}
vtkIdType InsertHexahedron(vtkIdType *pts)
{
vtkIdType cellId = m_Cells->InsertNextCell(8, pts);
m_TypeArray[cellId] = VTK_HEXAHEDRON;
return cellId;
}
};
/*!
\brief Implementation of the InsertImplementation interface of
SwitchByCellType to define a visitor that distributes cells
according to their types (for vtkPolyData construction)
*/
class DistributeInsertImplementation
{
vtkCellArray* m_LineCells;
vtkCellArray* m_TriangleCells;
vtkCellArray* m_PolygonCells;
vtkCellArray* m_QuadCells;
protected:
bool m_UseCellScalarAccessor;
vtkFloatArray* m_CellScalars;
typename MeshType::CellDataContainer::Pointer m_CellData;
public:
DistributeInsertImplementation() : m_UseCellScalarAccessor(false) {}
/*! Set the vtkCellArray that will be constructed
*/
void SetCellArrays(vtkCellArray* lines, vtkCellArray* triangles, vtkCellArray* polygons, vtkCellArray* quads)
{
m_LineCells = lines;
m_TriangleCells = triangles;
m_PolygonCells = polygons;
m_QuadCells = quads;
}
vtkIdType InsertLine(vtkIdType *pts)
{
return m_LineCells->InsertNextCell(2, pts);
}
vtkIdType InsertTriangle(vtkIdType *pts)
{
return m_TriangleCells->InsertNextCell(3, pts);
}
vtkIdType InsertPolygon(vtkIdType npts, vtkIdType *pts)
{
return m_PolygonCells->InsertNextCell(npts, pts);
}
vtkIdType InsertQuad(vtkIdType *pts)
{
return m_QuadCells->InsertNextCell(4, pts);
}
vtkIdType InsertTetra(vtkIdType *pts) { return -1; } // ignored
vtkIdType InsertHexahedron(vtkIdType *pts) { return -1; } // ignored
};
//typedef typename MeshType::CellType CellType;
//typedef typename itk::LineCell< CellType > LineType;
//typedef typename itk::PolygonCell< CellType > PolygonType;
//typedef typename itk::TriangleCell< CellType > TriangleType;
typedef SwitchByCellType<SingleCellArrayInsertImplementation> SingleCellArrayUserVisitorType;
typedef SwitchByCellType<DistributeInsertImplementation> DistributeUserVisitorType;
typedef ExactSwitchByCellType<DistributeInsertImplementation> ExactUserVisitorType;
public:
typedef itk::MatrixOffsetTransformBase<typename MeshType::CoordRepType,3,3> ITKTransformType;
typedef itk::MatrixOffsetTransformBase<mitk::ScalarType,3,3> MITKTransformType;
/*!
Convert a MITK transformation to an ITK transformation
Necessary because ITK uses double and MITK uses float values
*/
static void ConvertTransformToItk(const MITKTransformType* mitkTransform, ITKTransformType* itkTransform)
{
typename MITKTransformType::MatrixType mitkM = mitkTransform->GetMatrix();
typename ITKTransformType::MatrixType itkM;
typename MITKTransformType::OffsetType mitkO = mitkTransform->GetOffset();
typename ITKTransformType::OffsetType itkO;
for(short i = 0; i < 3; ++i)
{
for(short j = 0; j<3; ++j)
{
itkM[i][j] = (double)mitkM[i][j];
}
itkO[i] = (double)mitkO[i];
}
itkTransform->SetMatrix(itkM);
itkTransform->SetOffset(itkO);
}
/*!
create an itkMesh object from a vtkPolyData
*/
- static typename MeshType::Pointer MeshFromPolyData(vtkPolyData* poly, mitk::Geometry3D* geometryFrame=NULL, mitk::Geometry3D* polyDataGeometryFrame=NULL)
+ static typename MeshType::Pointer MeshFromPolyData(vtkPolyData* poly, mitk::BaseGeometry* geometryFrame=NULL, mitk::BaseGeometry* polyDataGeometryFrame=NULL)
{
// Create a new mesh
typename MeshType::Pointer output = MeshType::New();
output->SetCellsAllocationMethod( MeshType::CellsAllocatedDynamicallyCellByCell );
typedef typename MeshType::CellDataContainer MeshCellDataContainerType;
output->SetCellData(MeshCellDataContainerType::New());
// Get the points from vtk
vtkPoints* vtkpoints = poly->GetPoints();
const unsigned int numPoints = poly->GetNumberOfPoints();
// Create a compatible point container for the mesh
// the mesh is created with a null points container
// MeshType::PointsContainer::Pointer points =
// MeshType::PointsContainer::New();
// // Resize the point container to be able to fit the vtk points
// points->Reserve(numPoints);
// // Set the point container on the mesh
//output->SetPoints(points);
double vtkpoint[3];
typename MeshType::PointType itkPhysicalPoint;
if(geometryFrame==NULL)
{
if(polyDataGeometryFrame==NULL)
{
for(unsigned int i=0; i < numPoints; ++i)
{
vtkpoints->GetPoint(i, vtkpoint);
//MITK_INFO << "next point: " << test[0]<< "," << test[1] << "," << test[2] << std::endl;
//typename MeshType::PixelType* apoint = (typename MeshType::PixelType*) vtkpoints->GetPoint(i);
mitk::vtk2itk(vtkpoint, itkPhysicalPoint);
output->SetPoint( i, itkPhysicalPoint );
}
}
else
{
for(unsigned int i=0; i < numPoints; ++i)
{
vtkpoints->GetPoint(i, vtkpoint);
//MITK_INFO << "next point: " << test[0]<< "," << test[1] << "," << test[2] << std::endl;
//typename MeshType::PixelType* apoint = (typename MeshType::PixelType*) vtkpoints->GetPoint(i);
mitk::Point3D mitkWorldPoint;
mitk::vtk2itk(vtkpoint, mitkWorldPoint);
polyDataGeometryFrame->IndexToWorld(mitkWorldPoint, mitkWorldPoint);
mitk::vtk2itk(mitkWorldPoint, itkPhysicalPoint);
output->SetPoint( i, itkPhysicalPoint );
}
}
}
else
{
mitk::Point3D mitkWorldPoint;
if(polyDataGeometryFrame==NULL)
{
for(unsigned int i=0; i < numPoints; ++i)
{
vtkpoints->GetPoint(i, vtkpoint);
//MITK_INFO << "next point: " << test[0]<< "," << test[1] << "," << test[2] << std::endl;
//typename MeshType::PixelType* apoint = (typename MeshType::PixelType*) vtkpoints->GetPoint(i);
mitk::vtk2itk(vtkpoint, mitkWorldPoint);
geometryFrame->WorldToItkPhysicalPoint(mitkWorldPoint, itkPhysicalPoint);
output->SetPoint( i, itkPhysicalPoint );
}
}
else
{
for(unsigned int i=0; i < numPoints; ++i)
{
vtkpoints->GetPoint(i, vtkpoint);
//MITK_INFO << "next point: " << test[0]<< "," << test[1] << "," << test[2] << std::endl;
//typename MeshType::PixelType* apoint = (typename MeshType::PixelType*) vtkpoints->GetPoint(i);
mitk::vtk2itk(vtkpoint, mitkWorldPoint);
polyDataGeometryFrame->IndexToWorld(mitkWorldPoint, mitkWorldPoint);
geometryFrame->WorldToItkPhysicalPoint(mitkWorldPoint, itkPhysicalPoint);
output->SetPoint( i, itkPhysicalPoint );
}
}
}
vtkCellArray* vtkcells = poly->GetPolys();
// vtkCellArray* vtkcells = poly->GetStrips();
//MeshType::CellsContainerPointer cells = MeshType::CellsContainer::New();
//output->SetCells(cells);
// extract the cell id's from the vtkUnstructuredGrid
int numcells = vtkcells->GetNumberOfCells();
int* vtkCellTypes = new int[numcells];
int cellId = 0;
// poly ids start after verts and lines!
int cellIdOfs = poly->GetNumberOfVerts() + poly->GetNumberOfLines();
for(; cellId < numcells; cellId++)
{
vtkCellTypes[cellId] = poly->GetCellType( cellId+cellIdOfs );
}
// cells->Reserve(numcells);
vtkIdType npts;
vtkIdType* pts;
cellId = 0;
typedef typename MeshType::MeshTraits OMeshTraits;
typedef typename OMeshTraits::PixelType OPixelType;
typedef typename MeshType::CellTraits CellTraits;
typedef typename itk::CellInterface<OPixelType, CellTraits> CellInterfaceType;
typedef typename itk::TriangleCell<CellInterfaceType> TriCellType;
typedef typename TriCellType::CellAutoPointer TriCellPointer;
TriCellPointer newCell;
output->GetCells()->Reserve( poly->GetNumberOfPolys() + poly->GetNumberOfStrips() );
output->GetCellData()->Reserve( poly->GetNumberOfPolys() + poly->GetNumberOfStrips() );
for(vtkcells->InitTraversal(); vtkcells->GetNextCell(npts, pts); cellId++)
{
switch(vtkCellTypes[cellId])
{
case VTK_TRIANGLE:
{
if (npts != 3) continue; // skip non-triangles;
unsigned long pointIds[3];
pointIds[0] = (unsigned long) pts[0];
pointIds[1] = (unsigned long) pts[1];
pointIds[2] = (unsigned long) pts[2];
newCell.TakeOwnership( new TriCellType );
newCell->SetPointIds(pointIds);//(unsigned long*)pts);
output->SetCell(cellId, newCell );
output->SetCellData(cellId, (typename MeshType::PixelType)3);
break;
}
case VTK_QUAD:
{
if (npts != 4 ) continue; // skip non-quadrilateral
unsigned long pointIds[3];
pointIds[0] = (unsigned long) pts[0];
pointIds[1] = (unsigned long) pts[1];
pointIds[2] = (unsigned long) pts[2];
newCell.TakeOwnership( new TriCellType );
newCell->SetPointIds(pointIds);
output->SetCell(cellId, newCell );
output->SetCellData(cellId, (typename MeshType::PixelType)3);
cellId++;
pointIds[0] = (unsigned long) pts[2];
pointIds[1] = (unsigned long) pts[3];
pointIds[2] = (unsigned long) pts[0];
newCell.TakeOwnership( new TriCellType );
newCell->SetPointIds(pointIds);
output->SetCell(cellId, newCell );
output->SetCellData(cellId, (typename MeshType::PixelType)3);
break;
}
case VTK_EMPTY_CELL:
{
if (npts != 3)
{
MITK_ERROR << "Only empty triangle cell supported by now..." << std::endl; // skip non-triangle empty cells;
continue;
}
unsigned long pointIds[3];
pointIds[0] = (unsigned long) pts[0];
pointIds[1] = (unsigned long) pts[1];
pointIds[2] = (unsigned long) pts[2];
newCell.TakeOwnership( new TriCellType );
newCell->SetPointIds(pointIds);
output->SetCell(cellId, newCell );
output->SetCellData(cellId, (typename MeshType::PixelType)3);
break;
}
//case VTK_VERTEX: // If need to implement use
//case VTK_POLY_VERTEX: // the poly->GetVerts() and
//case VTK_LINE: // poly->GetLines() routines
//case VTK_POLY_LINE: // outside of the switch..case.
case VTK_POLYGON:
case VTK_PIXEL:
{
if (npts != 4 ) continue;// skip non-quadrilateral
unsigned long pointIds[3];
for ( unsigned int idx = 0; idx <= 1; idx++ )
{
pointIds[0] = (unsigned long) pts[idx];
pointIds[1] = (unsigned long) pts[idx+1];
pointIds[2] = (unsigned long) pts[idx+2];
newCell.TakeOwnership( new TriCellType );
newCell->SetPointIds(pointIds);
output->SetCell(cellId+idx, newCell );
output->SetCellData(cellId+idx, (typename MeshType::PixelType)3);
}
cellId++;
break;
}
case VTK_TETRA:
case VTK_VOXEL:
case VTK_HEXAHEDRON:
case VTK_WEDGE:
case VTK_PYRAMID:
case VTK_PARAMETRIC_CURVE:
case VTK_PARAMETRIC_SURFACE:
default:
MITK_WARN << "Warning, unhandled cell type "
<< vtkCellTypes[cellId] << std::endl;
}
}
if (poly->GetNumberOfStrips() != 0)
{
vtkcells = poly->GetStrips();
numcells = vtkcells->GetNumberOfCells();
vtkCellTypes = new int[numcells];
int stripId = 0;
// strip ids start after verts, lines and polys!
int stripIdOfs = poly->GetNumberOfVerts() + poly->GetNumberOfLines() + poly->GetNumberOfPolys();
for(; stripId < numcells; stripId++)
{
vtkCellTypes[stripId] = poly->GetCellType( stripId+stripIdOfs );
}
stripId = 0;
vtkcells->InitTraversal();
while( vtkcells->GetNextCell(npts, pts) )
{
if (vtkCellTypes[stripId] != VTK_TRIANGLE_STRIP)
{
MITK_ERROR << "Only triangle strips supported!" << std::endl;
continue;
}
stripId++;
unsigned int numberOfTrianglesInStrip = npts - 2;
unsigned long pointIds[3];
pointIds[0] = (unsigned long) pts[0];
pointIds[1] = (unsigned long) pts[1];
pointIds[2] = (unsigned long) pts[2];
for( unsigned int t=0; t < numberOfTrianglesInStrip; t++ )
{
newCell.TakeOwnership( new TriCellType );
newCell->SetPointIds(pointIds);
output->SetCell(cellId, newCell );
output->SetCellData(cellId, (typename MeshType::PixelType)3);
cellId++;
pointIds[0] = pointIds[1];
pointIds[1] = pointIds[2];
pointIds[2] = pts[t+3];
}
}
}
//output->Print(std::cout);
output->BuildCellLinks();
delete[] vtkCellTypes;
return output;
}
/*!
create an itkMesh object from an mitk::Surface
*/
- static typename MeshType::Pointer MeshFromSurface(mitk::Surface* surface, mitk::Geometry3D* geometryFrame=NULL)
+ static typename MeshType::Pointer MeshFromSurface(mitk::Surface* surface, mitk::BaseGeometry* geometryFrame=NULL)
{
if(surface == NULL)
return NULL;
return MeshFromPolyData(surface->GetVtkPolyData(), geometryFrame, surface->GetGeometry());
}
/*!
create an vtkUnstructuredGrid object from an itkMesh
*/
static vtkUnstructuredGrid* MeshToUnstructuredGrid(
MeshType* mesh,
bool usePointScalarAccessor = false,
bool useCellScalarAccessor = false,
unsigned int pointDataType = 0,
- mitk::Geometry3D* geometryFrame=NULL)
+ mitk::BaseGeometry* geometryFrame=NULL)
{
/*!
default SingleCellArray line cell visitior definition
*/
typedef typename itk::CellInterfaceVisitorImplementation<typename MeshType::CellPixelType,
typename MeshType::CellTraits,
itk::LineCell< typename MeshType::CellType >,
SingleCellArrayUserVisitorType> SingleCellArrayLineVisitor;
/*!
default SingleCellArray polygon cell visitior definition
*/
typedef typename itk::CellInterfaceVisitorImplementation<typename MeshType::CellPixelType,
typename MeshType::CellTraits,
itk::PolygonCell< typename MeshType::CellType >,
SingleCellArrayUserVisitorType> SingleCellArrayPolygonVisitor;
/*!
default SingleCellArray triangle cell visitior definition
*/
typedef typename itk::CellInterfaceVisitorImplementation<typename MeshType::CellPixelType,
typename MeshType::CellTraits,
itk::TriangleCell<itk::CellInterface<typename MeshType::CellPixelType, typename MeshType::CellTraits > >,
SingleCellArrayUserVisitorType> SingleCellArrayTriangleVisitor;
/*!
default SingleCellArray quad cell visitior definition
*/
typedef typename itk::CellInterfaceVisitorImplementation<typename MeshType::CellPixelType, typename MeshType::CellTraits,
itk::QuadrilateralCell< itk::CellInterface<typename MeshType::CellPixelType, typename MeshType::CellTraits > >,
SingleCellArrayUserVisitorType> SingleCellArrayQuadrilateralVisitor;
/*!
default SingleCellArray tetra cell visitior definition
*/
typedef typename itk::CellInterfaceVisitorImplementation<typename MeshType::CellPixelType, typename MeshType::CellTraits,
itk::TetrahedronCell< itk::CellInterface<typename MeshType::CellPixelType, typename MeshType::CellTraits > >,
SingleCellArrayUserVisitorType> SingleCellArrayTetrahedronVisitor;
/*!
default SingleCellArray hex cell visitior definition
*/
typedef typename itk::CellInterfaceVisitorImplementation<typename MeshType::CellPixelType, typename MeshType::CellTraits,
itk::HexahedronCell< itk::CellInterface<typename MeshType::CellPixelType, typename MeshType::CellTraits > >,
SingleCellArrayUserVisitorType> SingleCellArrayHexahedronVisitor;
// Get the number of points in the mesh
int numPoints = mesh->GetNumberOfPoints();
if(numPoints == 0)
{
//mesh->Print(std::cerr);
MITK_FATAL << "no points in Grid " << std::endl;
exit(-1);
}
// Create a vtkUnstructuredGrid
vtkUnstructuredGrid* vgrid = vtkUnstructuredGrid::New();
// Create the vtkPoints object and set the number of points
vtkPoints* vpoints = vtkPoints::New( VTK_DOUBLE );
vtkFloatArray* pointScalars = vtkFloatArray::New();
vtkFloatArray* cellScalars = vtkFloatArray::New();
pointScalars->SetNumberOfComponents(1);
cellScalars->SetNumberOfComponents(1);
typename MeshType::PointsContainer::Pointer points = mesh->GetPoints();
typename MeshType::PointsContainer::Iterator i;
// iterate over all the points in the itk mesh to find
// the maximal index
unsigned int maxIndex = 0;
for(i = points->Begin(); i != points->End(); ++i)
{
if(maxIndex < i->Index())
maxIndex = i->Index();
}
// initialize vtk-classes for points and scalars
vpoints->SetNumberOfPoints(maxIndex+1);
pointScalars->SetNumberOfTuples(maxIndex+1);
cellScalars->SetNumberOfTuples(mesh->GetNumberOfCells());
double vtkpoint[3];
typename MeshType::PointType itkPhysicalPoint;
if (geometryFrame == 0)
{
for(i = points->Begin(); i != points->End(); ++i)
{
// Get the point index from the point container iterator
int idx = i->Index();
itkPhysicalPoint = i->Value();
mitk::itk2vtk(itkPhysicalPoint, vtkpoint);
// Set the vtk point at the index with the the coord array from itk
vpoints->SetPoint(idx, vtkpoint);
if(usePointScalarAccessor)
{
pointScalars->InsertTuple1( idx, ScalarAccessor::GetPointScalar( mesh->GetPointData(), i->Index(), mesh, pointDataType ) );
}
}
}
else
{
mitk::Point3D mitkWorldPoint;
for(i = points->Begin(); i != points->End(); ++i)
{
// Get the point index from the point container iterator
int idx = i->Index();
itkPhysicalPoint = i->Value();
geometryFrame->ItkPhysicalPointToWorld(itkPhysicalPoint, mitkWorldPoint);
mitk::itk2vtk(mitkWorldPoint, vtkpoint);
// Set the vtk point at the index with the the coord array from itk
vpoints->SetPoint(idx, vtkpoint);
if(usePointScalarAccessor)
{
pointScalars->InsertTuple1( idx, ScalarAccessor::GetPointScalar( mesh->GetPointData(), i->Index(), mesh, pointDataType ) );
}
}
}
// Set the points on the vtk grid
vgrid->SetPoints(vpoints);
if (usePointScalarAccessor)
vgrid->GetPointData()->SetScalars(pointScalars);
// Now create the cells using the MultiVisitor
// 1. Create a MultiVisitor
typename MeshType::CellType::MultiVisitor::Pointer mv =
MeshType::CellType::MultiVisitor::New();
// 2. Create visitors
typename SingleCellArrayLineVisitor::Pointer lv = SingleCellArrayLineVisitor::New();
typename SingleCellArrayPolygonVisitor::Pointer pv = SingleCellArrayPolygonVisitor::New();
typename SingleCellArrayTriangleVisitor::Pointer tv = SingleCellArrayTriangleVisitor::New();
typename SingleCellArrayQuadrilateralVisitor::Pointer qv = SingleCellArrayQuadrilateralVisitor::New();
typename SingleCellArrayTetrahedronVisitor::Pointer tetv = SingleCellArrayTetrahedronVisitor::New();
typename SingleCellArrayHexahedronVisitor::Pointer hv = SingleCellArrayHexahedronVisitor::New();
// 3. Set up the visitors
//int vtkCellCount = 0; // running counter for current cell being inserted into vtk
int numCells = mesh->GetNumberOfCells();
int *types = new int[numCells]; // type array for vtk
// create vtk cells and estimate the size
vtkCellArray* cells = vtkCellArray::New();
cells->Allocate(numCells);
// Set the TypeArray CellCount and CellArray for the visitors
lv->SetTypeArray(types);
lv->SetCellArray(cells);
pv->SetTypeArray(types);
pv->SetCellArray(cells);
tv->SetTypeArray(types);
//tv->SetCellCounter(&vtkCellCount);
tv->SetCellArray(cells);
qv->SetTypeArray(types);
//qv->SetCellCounter(&vtkCellCount);
qv->SetCellArray(cells);
tetv->SetTypeArray(types);
tetv->SetCellArray(cells);
hv->SetTypeArray(types);
hv->SetCellArray(cells);
if (useCellScalarAccessor)
{
lv->SetUseCellScalarAccessor(true);
lv->SetCellScalars(cellScalars);
lv->SetMeshCellData(mesh->GetCellData());
pv->SetUseCellScalarAccessor(true);
pv->SetCellScalars(cellScalars);
pv->SetMeshCellData(mesh->GetCellData());
tv->SetUseCellScalarAccessor(true);
tv->SetCellScalars(cellScalars);
tv->SetMeshCellData(mesh->GetCellData());
qv->SetUseCellScalarAccessor(true);
qv->SetCellScalars(cellScalars);
qv->SetMeshCellData(mesh->GetCellData());
tetv->SetUseCellScalarAccessor(true);
tetv->SetCellScalars(cellScalars);
tetv->SetMeshCellData(mesh->GetCellData());
hv->SetUseCellScalarAccessor(true);
hv->SetCellScalars(cellScalars);
hv->SetMeshCellData(mesh->GetCellData());
}
// add the visitors to the multivisitor
mv->AddVisitor(lv);
mv->AddVisitor(pv);
mv->AddVisitor(tv);
mv->AddVisitor(qv);
mv->AddVisitor(tetv);
mv->AddVisitor(hv);
// Now ask the mesh to accept the multivisitor which
// will Call Visit for each cell in the mesh that matches the
// cell types of the visitors added to the MultiVisitor
mesh->Accept(mv);
// Now set the cells on the vtk grid with the type array and cell array
vgrid->SetCells(types, cells);
vgrid->GetCellData()->SetScalars(cellScalars);
// Clean up vtk objects (no vtkSmartPointer ... )
cells->Delete();
vpoints->Delete();
delete[] types;
pointScalars->Delete();
cellScalars->Delete();
//MITK_INFO << "meshToUnstructuredGrid end" << std::endl;
return vgrid;
}
/*!
create a vtkPolyData object from an itkMesh
*/
- static vtkPolyData* MeshToPolyData(MeshType* mesh, bool onlyTriangles = false, bool useScalarAccessor = false, unsigned int pointDataType = 0, mitk::Geometry3D* geometryFrame=NULL, vtkPolyData* polydata = NULL)
+ static vtkPolyData* MeshToPolyData(MeshType* mesh, bool onlyTriangles = false, bool useScalarAccessor = false, unsigned int pointDataType = 0, mitk::BaseGeometry* geometryFrame=NULL, vtkPolyData* polydata = NULL)
{
/*!
default Distribute line cell visitior definition
*/
typedef typename itk::CellInterfaceVisitorImplementation<typename MeshType::CellPixelType,
typename MeshType::CellTraits,
itk::LineCell< typename MeshType::CellType >,
DistributeUserVisitorType> DistributeLineVisitor;
/*!
default Distribute polygon cell visitior definition
*/
typedef typename itk::CellInterfaceVisitorImplementation<typename MeshType::CellPixelType,
typename MeshType::CellTraits,
itk::PolygonCell< typename MeshType::CellType >,
DistributeUserVisitorType> DistributePolygonVisitor;
/*!
default Distribute triangle cell visitior definition
*/
typedef typename itk::CellInterfaceVisitorImplementation<typename MeshType::CellPixelType,
typename MeshType::CellTraits,
itk::TriangleCell<itk::CellInterface<typename MeshType::CellPixelType, typename MeshType::CellTraits > >,
DistributeUserVisitorType> DistributeTriangleVisitor;
/*!
default Distribute quad cell visitior definition
*/
typedef typename itk::CellInterfaceVisitorImplementation<typename MeshType::CellPixelType, typename MeshType::CellTraits,
itk::QuadrilateralCell< itk::CellInterface<typename MeshType::CellPixelType, typename MeshType::CellTraits > >,
DistributeUserVisitorType> DistributeQuadrilateralVisitor;
/*!
default Distribute triangle cell visitior definition
*/
typedef typename itk::CellInterfaceVisitorImplementation<typename MeshType::CellPixelType,
typename MeshType::CellTraits,
itk::TriangleCell<itk::CellInterface<typename MeshType::CellPixelType, typename MeshType::CellTraits > >,
ExactUserVisitorType> ExactTriangleVisitor;
// Get the number of points in the mesh
int numPoints = mesh->GetNumberOfPoints();
if(numPoints == 0)
{
//mesh->Print(std::cerr);
MITK_ERROR << "no points in Grid " << std::endl;
}
// Create a vtkPolyData
if(polydata == NULL)
polydata = vtkPolyData::New();
else
polydata->Initialize();
// Create the vtkPoints object and set the number of points
vtkPoints* vpoints = vtkPoints::New( VTK_DOUBLE );
vtkFloatArray * scalars = vtkFloatArray::New();
scalars->SetNumberOfComponents(1);
typename MeshType::PointsContainer::Pointer points = mesh->GetPoints();
typename MeshType::PointsContainer::Iterator i;
// iterate over all the points in the itk mesh to find
// the maximal index
unsigned int maxIndex = 0;
for(i = points->Begin(); i != points->End(); ++i)
{
if(maxIndex < i->Index())
maxIndex = i->Index();
}
// initialize vtk-classes for points and scalars
vpoints->SetNumberOfPoints(maxIndex+1);
scalars->SetNumberOfTuples(maxIndex+1);
// iterate over all the points in the itk mesh filling in
// the vtkPoints object as we go
double vtkpoint[3];
typename MeshType::PointType itkPhysicalPoint;
if(geometryFrame==NULL)
{
for(i = points->Begin(); i != points->End(); ++i)
{
// Get the point index from the point container iterator
int idx = i->Index();
itkPhysicalPoint = i->Value();
mitk::itk2vtk(itkPhysicalPoint, vtkpoint);
// Set the vtk point at the index with the the coord array from itk
// itk returns a const pointer, but vtk is not const correct, so
// we have to use a const cast to get rid of the const
// vpoints->SetPoint(idx, const_cast<DATATYPE*>(i->Value().GetDataPointer()));
vpoints->SetPoint(idx, vtkpoint);
if(useScalarAccessor)
{
scalars->InsertTuple1( idx, ScalarAccessor::GetPointScalar( mesh->GetPointData(), i->Index(), mesh, pointDataType ) );
}
}
}
else
{
mitk::Point3D mitkWorldPoint;
for(i = points->Begin(); i != points->End(); ++i)
{
// Get the point index from the point container iterator
int idx = i->Index();
itkPhysicalPoint = i->Value();
geometryFrame->ItkPhysicalPointToWorld(itkPhysicalPoint, mitkWorldPoint);
mitk::itk2vtk(mitkWorldPoint, vtkpoint);
// Set the vtk point at the index with the the coord array from itk
// itk returns a const pointer, but vtk is not const correct, so
// we have to use a const cast to get rid of the const
// vpoints->SetPoint(idx, const_cast<DATATYPE*>(i->Value().GetDataPointer()));
vpoints->SetPoint(idx, vtkpoint);
if(useScalarAccessor)
{
scalars->InsertTuple1( idx, ScalarAccessor::GetPointScalar( mesh->GetPointData(), i->Index(), mesh, pointDataType ) );
}
}
}
// Set the points on the vtk grid
polydata->SetPoints(vpoints);
if (useScalarAccessor)
polydata->GetPointData()->SetScalars(scalars);
polydata->GetPointData()->CopyAllOn();
// Now create the cells using the MulitVisitor
// 1. Create a MultiVisitor
typedef typename MeshType::CellType::MultiVisitor MeshMV;
typename MeshMV::Pointer mv = MeshMV::New();
int numCells = mesh->GetNumberOfCells();
if (onlyTriangles)
{
// create vtk cells and allocate
vtkCellArray* trianglecells = vtkCellArray::New();
trianglecells->Allocate(numCells);
// 2. Create a triangle visitor and add it to the multivisitor
typename ExactTriangleVisitor::Pointer tv = ExactTriangleVisitor::New();
tv->SetCellArrays(NULL, trianglecells, NULL, NULL);
mv->AddVisitor(tv);
// 3. Now ask the mesh to accept the multivisitor which
// will Call Visit for each cell in the mesh that matches the
// cell types of the visitors added to the MultiVisitor
mesh->Accept(mv);
// 4. Set the result into our vtkPolyData
if(trianglecells->GetNumberOfCells()>0)
polydata->SetStrips(trianglecells);
// 5. Clean up vtk objects (no vtkSmartPointer ... )
trianglecells->Delete();
}
else
{
// create vtk cells and allocate
vtkCellArray* linecells = vtkCellArray::New();
vtkCellArray* trianglecells = vtkCellArray::New();
vtkCellArray* polygoncells = vtkCellArray::New();
linecells->Allocate(numCells);
trianglecells->Allocate(numCells);
polygoncells->Allocate(numCells);
// 2. Create visitors
typename DistributeLineVisitor::Pointer lv = DistributeLineVisitor::New();
typename DistributePolygonVisitor::Pointer pv = DistributePolygonVisitor::New();
typename DistributeTriangleVisitor::Pointer tv = DistributeTriangleVisitor::New();
typename DistributeQuadrilateralVisitor::Pointer qv = DistributeQuadrilateralVisitor::New();
lv->SetCellArrays(linecells, trianglecells, polygoncells, polygoncells);
pv->SetCellArrays(linecells, trianglecells, polygoncells, polygoncells);
tv->SetCellArrays(linecells, trianglecells, polygoncells, polygoncells);
qv->SetCellArrays(linecells, trianglecells, polygoncells, polygoncells);
// add the visitors to the multivisitor
mv->AddVisitor(tv);
mv->AddVisitor(lv);
mv->AddVisitor(pv);
mv->AddVisitor(qv);
// 3. Now ask the mesh to accept the multivisitor which
// will Call Visit for each cell in the mesh that matches the
// cell types of the visitors added to the MultiVisitor
mesh->Accept(mv);
// 4. Set the result into our vtkPolyData
if(linecells->GetNumberOfCells()>0)
polydata->SetLines(linecells);
if(trianglecells->GetNumberOfCells()>0)
polydata->SetStrips(trianglecells);
if(polygoncells->GetNumberOfCells()>0)
polydata->SetPolys(polygoncells);
// 5. Clean up vtk objects (no vtkSmartPointer ... )
linecells->Delete();
trianglecells->Delete();
polygoncells->Delete();
}
vpoints->Delete();
scalars->Delete();
//MITK_INFO << "meshToPolyData end" << std::endl;
return polydata;
}
static typename MeshType::Pointer CreateRegularSphereMesh(typename MeshType::PointType center, typename MeshType::PointType::VectorType scale, int resolution)
{
typedef itk::RegularSphereMeshSource<MeshType> SphereSourceType;
typename SphereSourceType::Pointer mySphereSource = SphereSourceType::New();
mySphereSource->SetCenter(center);
mySphereSource->SetScale(scale);
mySphereSource->SetResolution( resolution );
mySphereSource->Update();
typename MeshType::Pointer resultMesh = mySphereSource->GetOutput();
resultMesh->Register(); // necessary ????
return resultMesh;
}
static typename MeshType::Pointer CreateSphereMesh(typename MeshType::PointType center, typename MeshType::PointType scale, int* resolution)
{
typedef typename itk::SphereMeshSource<MeshType> SphereSource;
typename SphereSource::Pointer mySphereSource = SphereSource::New();
mySphereSource->SetCenter(center);
mySphereSource->SetScale(scale);
mySphereSource->SetResolutionX(resolution[0]);
mySphereSource->SetResolutionY(resolution[1]);
mySphereSource->SetSquareness1(1);
mySphereSource->SetSquareness2(1);
mySphereSource->Update();
mySphereSource->GetOutput();
typename MeshType::Pointer resultMesh = mySphereSource->GetOutput();
resultMesh->Register();
return resultMesh;
}
// static typename MeshType::Pointer TranslateMesh(typename MeshType::PointType vec, MeshType* input)
// {
//
// typename MeshType::Pointer output = MeshType::New();
// {
// output->SetPoints(input->GetPoints());
// output->SetPointData(input->GetPointData());
// output->SetCells(input->GetCells());
// output->SetLastCellId( input->GetLastCellId() );
// typename MeshType::GeometryMapIterator pointDataIterator = input->GetGeometryData()->Begin();
// typename MeshType::GeometryMapIterator pointDataEnd = input->GetGeometryData()->End();
//
// typename MeshType::PointType inputPoint,outputPoint;
//
// while (pointDataIterator != pointDataEnd)
// {
// unsigned long pointId = pointDataIterator->Index();
// itk::SimplexMeshGeometry* newGeometry = new itk::SimplexMeshGeometry();
// itk::SimplexMeshGeometry* refGeometry = pointDataIterator->Value();
//
// input->GetPoint(pointId, &inputPoint );
// outputPoint[0] = inputPoint[0] + vec[0];
// outputPoint[1] = inputPoint[1] + vec[1];
// outputPoint[2] = inputPoint[2] + vec[2];
// output->SetPoint( pointId, outputPoint );
//
//
// newGeometry->pos = outputPoint;
// newGeometry->neighborIndices = refGeometry->neighborIndices;
// newGeometry->meanCurvature = refGeometry->meanCurvature;
// newGeometry->neighbors = refGeometry->neighbors;
// newGeometry->oldPos = refGeometry->oldPos;
// newGeometry->eps = refGeometry->eps;
// newGeometry->referenceMetrics = refGeometry->referenceMetrics;
// newGeometry->neighborSet = refGeometry->neighborSet;
// newGeometry->distance = refGeometry->distance;
// newGeometry->externalForce = refGeometry->externalForce;
// newGeometry->internalForce = refGeometry->internalForce;
// output->SetGeometryData(pointId, newGeometry);
// pointDataIterator++;
// }
// }
//// output->SetGeometryData( inputMesh->GetGeometryData() );
// return output;
// }
static typename MeshType::Pointer CreateRegularSphereMesh2(typename MeshType::PointType center, typename MeshType::PointType scale, int resolution)
{
typedef typename itk::AutomaticTopologyMeshSource<MeshType> MeshSourceType;
typename MeshSourceType::Pointer mySphereSource = MeshSourceType::New();
typename MeshType::PointType pnt0, pnt1, pnt2, pnt3, pnt4, pnt5, pnt6, pnt7, pnt8, pnt9, pnt10, pnt11;
double c1= 0.5 * (1.0 + sqrt(5.0));
double c2= 1.0;
double len = sqrt( c1*c1 + c2*c2 );
c1 /= len; c2 /= len;
pnt0[0] = center[0] - c1*scale[0]; pnt0[1] = center[1]; pnt0[2] = center[2] + c2*scale[2];
pnt1[0] = center[0]; pnt1[1] = center[1] + c2*scale[1]; pnt1[2] = center[2] - c1*scale[2];
pnt2[0] = center[0]; pnt2[1] = center[1] + c2*scale[1]; pnt2[2] = center[2] + c1*scale[2];
pnt3[0] = center[0] + c1*scale[0]; pnt3[1] = center[1]; pnt3[2] = center[2] - c2*scale[2];
pnt4[0] = center[0] - c2*scale[0]; pnt4[1] = center[1] - c1*scale[1]; pnt4[2] = center[2];
pnt5[0] = center[0] - c2*scale[0]; pnt5[1] = center[1] + c1*scale[1]; pnt5[2] = center[2];
pnt6[0] = center[0]; pnt6[1] = center[1] - c2*scale[1]; pnt6[2] = center[2] + c1*scale[2];
pnt7[0] = center[0] + c2*scale[0]; pnt7[1] = center[1] + c1*scale[1]; pnt7[2] = center[2];
pnt8[0] = center[0]; pnt8[1] = center[1] - c2*scale[1]; pnt8[2] = center[2] - c1*scale[2];
pnt9[0] = center[0] + c1*scale[0]; pnt9[1] = center[1]; pnt9[2] = center[2] + c2*scale[2];
pnt10[0]= center[0] + c2*scale[0]; pnt10[1]= center[1] - c1*scale[1]; pnt10[2]= center[2];
pnt11[0]= center[0] - c1*scale[0]; pnt11[1]= center[1]; pnt11[2]= center[2] - c2*scale[2];
addTriangle( mySphereSource, scale, pnt9, pnt2, pnt6, resolution );
addTriangle( mySphereSource, scale, pnt1, pnt11, pnt5, resolution );
addTriangle( mySphereSource, scale, pnt11, pnt1, pnt8, resolution );
addTriangle( mySphereSource, scale, pnt0, pnt11, pnt4, resolution );
addTriangle( mySphereSource, scale, pnt3, pnt1, pnt7, resolution );
addTriangle( mySphereSource, scale, pnt3, pnt8, pnt1, resolution );
addTriangle( mySphereSource, scale, pnt9, pnt3, pnt7, resolution );
addTriangle( mySphereSource, scale, pnt0, pnt6, pnt2, resolution );
addTriangle( mySphereSource, scale, pnt4, pnt10, pnt6, resolution );
addTriangle( mySphereSource, scale, pnt1, pnt5, pnt7, resolution );
addTriangle( mySphereSource, scale, pnt7, pnt5, pnt2, resolution );
addTriangle( mySphereSource, scale, pnt8, pnt3, pnt10, resolution );
addTriangle( mySphereSource, scale, pnt4, pnt11, pnt8, resolution );
addTriangle( mySphereSource, scale, pnt9, pnt7, pnt2, resolution );
addTriangle( mySphereSource, scale, pnt10, pnt9, pnt6, resolution );
addTriangle( mySphereSource, scale, pnt0, pnt5, pnt11, resolution );
addTriangle( mySphereSource, scale, pnt0, pnt2, pnt5, resolution );
addTriangle( mySphereSource, scale, pnt8, pnt10, pnt4, resolution );
addTriangle( mySphereSource, scale, pnt3, pnt9, pnt10, resolution );
addTriangle( mySphereSource, scale, pnt6, pnt0, pnt4, resolution );
return mySphereSource->GetOutput();
}
private:
static void addTriangle( typename itk::AutomaticTopologyMeshSource<MeshType>::Pointer meshSource, typename MeshType::PointType scale,
typename MeshType::PointType pnt0, typename MeshType::PointType pnt1, typename MeshType::PointType pnt2, int resolution )
{
if (resolution==0) {
// add triangle
meshSource->AddTriangle( meshSource->AddPoint( pnt0 ),
meshSource->AddPoint( pnt1 ),
meshSource->AddPoint( pnt2 ) );
}
else {
vnl_vector_fixed<typename MeshType::CoordRepType, 3> v1, v2, res, pv;
v1 = (pnt1-pnt0).Get_vnl_vector();
v2 = (pnt2-pnt0).Get_vnl_vector();
res = vnl_cross_3d( v1, v2 );
pv = pnt0.GetVectorFromOrigin().Get_vnl_vector();
//double d = res[0]*pv[0] + res[1]*pv[1] + res[2]*pv[2];
// subdivision
typename MeshType::PointType pnt01, pnt12, pnt20;
for (int d=0; d<3; d++) {
pnt01[d] = (pnt0[d] + pnt1[d]) / 2.0;
pnt12[d] = (pnt1[d] + pnt2[d]) / 2.0;
pnt20[d] = (pnt2[d] + pnt0[d]) / 2.0;
}
// map new points to sphere
double lenPnt01=0; for (int d=0; d<3; d++) lenPnt01 += pnt01[d]*pnt01[d]; lenPnt01 = sqrt( lenPnt01 );
double lenPnt12=0; for (int d=0; d<3; d++) lenPnt12 += pnt12[d]*pnt12[d]; lenPnt12 = sqrt( lenPnt12 );
double lenPnt20=0; for (int d=0; d<3; d++) lenPnt20 += pnt20[d]*pnt20[d]; lenPnt20 = sqrt( lenPnt20 );
for (int d=0; d<3; d++) {
pnt01[d] *= scale[d]/lenPnt01;
pnt12[d] *= scale[d]/lenPnt12;
pnt20[d] *= scale[d]/lenPnt20;
}
addTriangle( meshSource, scale, pnt0, pnt01, pnt20, resolution-1 );
addTriangle( meshSource, scale, pnt01, pnt1, pnt12, resolution-1 );
addTriangle( meshSource, scale, pnt20, pnt12, pnt2, resolution-1 );
addTriangle( meshSource, scale, pnt01, pnt12, pnt20, resolution-1 );
}
}
};
#endif // MITKMESHUTIL_H_INCLUDED
diff --git a/Modules/DataTypesExt/mitkSurfaceDeformationDataInteractor3D.cpp b/Modules/DataTypesExt/mitkSurfaceDeformationDataInteractor3D.cpp
index ad946c4722..54bbefb4e3 100644
--- a/Modules/DataTypesExt/mitkSurfaceDeformationDataInteractor3D.cpp
+++ b/Modules/DataTypesExt/mitkSurfaceDeformationDataInteractor3D.cpp
@@ -1,302 +1,302 @@
/*===================================================================
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 "mitkSurfaceDeformationDataInteractor3D.h"
#include "mitkMouseWheelEvent.h"
#include <vtkPointData.h>
#include <vtkPolyData.h>
mitk::SurfaceDeformationDataInteractor3D::SurfaceDeformationDataInteractor3D()
:m_GaussSigma(30.0)
{
m_OriginalPolyData = vtkPolyData::New();
// Initialize vector arithmetic
m_ObjectNormal[0] = 0.0;
m_ObjectNormal[1] = 0.0;
m_ObjectNormal[2] = 1.0;
}
mitk::SurfaceDeformationDataInteractor3D::~SurfaceDeformationDataInteractor3D()
{
m_OriginalPolyData->Delete();
}
void mitk::SurfaceDeformationDataInteractor3D::ConnectActionsAndFunctions()
{
// **Conditions** that can be used in the state machine, to ensure that certain conditions are met, before
// actually executing an action
CONNECT_CONDITION("isOverObject", CheckOverObject);
// **Function** in the statmachine patterns also referred to as **Actions**
CONNECT_FUNCTION("selectObject",SelectObject);
CONNECT_FUNCTION("deselectObject",DeselectObject);
CONNECT_FUNCTION("initDeformation",InitDeformation);
CONNECT_FUNCTION("deformObject",DeformObject);
CONNECT_FUNCTION("scaleRadius", ScaleRadius);
}
void mitk::SurfaceDeformationDataInteractor3D::DataNodeChanged()
{
if(this->GetDataNode().IsNotNull())
{
m_Surface = dynamic_cast<Surface*>(this->GetDataNode()->GetData());
if (m_Surface == NULL)
MITK_ERROR << "SurfaceDeformationDataInteractor3D::DataNodeChanged(): DataNode has to contain a surface.";
}
else
m_Surface = NULL;
}
bool mitk::SurfaceDeformationDataInteractor3D::CheckOverObject(const InteractionEvent* interactionEvent)
{
const InteractionPositionEvent* positionEvent = dynamic_cast<const InteractionPositionEvent*>(interactionEvent);
if(positionEvent == NULL)
return false;
Point2D currentPickedDisplayPoint = positionEvent->GetPointerPositionOnScreen();
Point3D currentPickedPoint;
if(interactionEvent->GetSender()->PickObject(currentPickedDisplayPoint, currentPickedPoint) == this->GetDataNode().GetPointer())
{
// Colorized surface at current picked position
m_SurfaceColorizationCenter = currentPickedPoint;
return true;
}
return false;
}
bool mitk::SurfaceDeformationDataInteractor3D::SelectObject(StateMachineAction*, InteractionEvent* interactionEvent)
{
const InteractionPositionEvent* positionEvent = dynamic_cast<const InteractionPositionEvent*>(interactionEvent);
if(positionEvent == NULL)
return false;
int timeStep = interactionEvent->GetSender()->GetTimeStep(this->GetDataNode()->GetData());
vtkPolyData* polyData = m_Surface->GetVtkPolyData(timeStep);
this->GetDataNode()->SetColor(1.0, 0.0, 0.0);
// Colorize surface / wireframe dependend on distance from picked point
this->ColorizeSurface(polyData, timeStep, m_SurfaceColorizationCenter, COLORIZATION_GAUSS);
interactionEvent->GetSender()->GetRenderingManager()->RequestUpdateAll();
return true;
}
bool mitk::SurfaceDeformationDataInteractor3D::DeselectObject(StateMachineAction*, InteractionEvent* interactionEvent)
{
const InteractionPositionEvent* positionEvent = dynamic_cast<const InteractionPositionEvent*>(interactionEvent);
if(positionEvent == NULL)
return false;
int timeStep = interactionEvent->GetSender()->GetTimeStep(this->GetDataNode()->GetData());
vtkPolyData* polyData = m_Surface->GetVtkPolyData(timeStep);
this->GetDataNode()->SetColor(1.0, 1.0, 1.0);
// Colorize surface / wireframe as inactive
this->ColorizeSurface(polyData, timeStep, m_SurfaceColorizationCenter, COLORIZATION_CONSTANT, -1.0);
interactionEvent->GetSender()->GetRenderingManager()->RequestUpdateAll();
return true;
}
bool mitk::SurfaceDeformationDataInteractor3D::InitDeformation(StateMachineAction*, InteractionEvent* interactionEvent)
{
const InteractionPositionEvent* positionEvent = dynamic_cast<const InteractionPositionEvent*>(interactionEvent);
if(positionEvent == NULL)
return false;
int timeStep = interactionEvent->GetSender()->GetTimeStep(this->GetDataNode()->GetData());
vtkPolyData* polyData = m_Surface->GetVtkPolyData(timeStep);
// Store current picked point
interactionEvent->GetSender()->PickObject(positionEvent->GetPointerPositionOnScreen(), m_InitialPickedPoint);
// Make deep copy of vtkPolyData interacted on
m_OriginalPolyData->DeepCopy(polyData);
return true;
}
bool mitk::SurfaceDeformationDataInteractor3D::DeformObject (StateMachineAction*, InteractionEvent* interactionEvent)
{
const InteractionPositionEvent* positionEvent = dynamic_cast<const InteractionPositionEvent*>(interactionEvent);
if(positionEvent == NULL)
return false;
int timeStep = interactionEvent->GetSender()->GetTimeStep(this->GetDataNode()->GetData());
vtkPolyData* polyData = m_Surface->GetVtkPolyData(timeStep);
- Geometry3D::Pointer geometry = this->GetDataNode()->GetData()->GetGeometry(timeStep);
+ BaseGeometry::Pointer geometry = this->GetDataNode()->GetData()->GetGeometry(timeStep);
Point3D currentPickedPoint = positionEvent->GetPositionInWorld();
// Calculate mouse move in 3D space
Vector3D interactionMove;
interactionMove[0] = currentPickedPoint[0] - m_InitialPickedPoint[0];
interactionMove[1] = currentPickedPoint[1] - m_InitialPickedPoint[1];
interactionMove[2] = currentPickedPoint[2] - m_InitialPickedPoint[2];
// Transform mouse move into geometry space
this->GetDataNode()->GetData()->UpdateOutputInformation();// make sure that the Geometry is up-to-date
Vector3D interactionMoveIndex;
geometry->WorldToIndex(interactionMove, interactionMoveIndex);
// Get picked point and transform into local coordinates
Point3D pickedPoint;
geometry->WorldToIndex(m_InitialPickedPoint, pickedPoint);
Vector3D v1 = pickedPoint.GetVectorFromOrigin();
vtkDataArray* normal = polyData->GetPointData()->GetVectors("planeNormal");
if (normal != NULL)
{
m_ObjectNormal[0] = normal->GetComponent(0, 0);
m_ObjectNormal[1] = normal->GetComponent(0, 1);
m_ObjectNormal[2] = normal->GetComponent(0, 2);
}
Vector3D v2 = m_ObjectNormal * (interactionMoveIndex * m_ObjectNormal);
vtkPoints* originalPoints = m_OriginalPolyData->GetPoints();
vtkPoints* deformedPoints = polyData->GetPoints();
double denom = m_GaussSigma * m_GaussSigma * 2;
double point[3];
for (vtkIdType i = 0; i < deformedPoints->GetNumberOfPoints(); ++i)
{
// Get original point
double* originalPoint = originalPoints->GetPoint( i );
Vector3D v0;
v0[0] = originalPoint[0];
v0[1] = originalPoint[1];
v0[2] = originalPoint[2];
// Calculate distance of this point from line through picked point
double d = itk::CrossProduct(m_ObjectNormal, (v1 - v0)).GetNorm();
Vector3D t = v2 * exp(- d * d / denom);
point[0] = originalPoint[0] + t[0];
point[1] = originalPoint[1] + t[1];
point[2] = originalPoint[2] + t[2];
deformedPoints->SetPoint(i, point);
}
// Make sure that surface is colorized at initial picked position as long as we are in deformation state
m_SurfaceColorizationCenter = m_InitialPickedPoint;
polyData->Modified();
m_Surface->Modified();
interactionEvent->GetSender()->GetRenderingManager()->RequestUpdateAll();
return true;
}
bool mitk::SurfaceDeformationDataInteractor3D::ScaleRadius(StateMachineAction*, InteractionEvent* interactionEvent)
{
const MouseWheelEvent* wheelEvent = dynamic_cast<const MouseWheelEvent*>(interactionEvent);
if(wheelEvent == NULL)
return false;
m_GaussSigma += (double) (wheelEvent->GetWheelDelta()) / 20;
if ( m_GaussSigma < 10.0 )
{
m_GaussSigma = 10.0;
}
else if ( m_GaussSigma > 128.0 )
{
m_GaussSigma = 128.0;
}
int timeStep = interactionEvent->GetSender()->GetTimeStep(this->GetDataNode()->GetData());
vtkPolyData* polyData = m_Surface->GetVtkPolyData(timeStep);
// Colorize surface / wireframe dependend on sigma and distance from picked point
this->ColorizeSurface( polyData, timeStep, m_SurfaceColorizationCenter, COLORIZATION_GAUSS );
interactionEvent->GetSender()->GetRenderingManager()->RequestUpdateAll();
return true;
}
bool mitk::SurfaceDeformationDataInteractor3D::ColorizeSurface(vtkPolyData* polyData, int timeStep, const Point3D &pickedPoint, int mode, double scalar)
{
if (polyData == NULL)
return false;
vtkPoints* points = polyData->GetPoints();
vtkPointData* pointData = polyData->GetPointData();
if ( pointData == NULL )
return false;
vtkDataArray* scalars = pointData->GetScalars();
if (scalars == NULL)
return false;
if (mode == COLORIZATION_GAUSS)
{
// Get picked point and transform into local coordinates
Point3D localPickedPoint;
- Geometry3D::Pointer geometry = this->GetDataNode()->GetData()->GetGeometry(timeStep);
+ BaseGeometry::Pointer geometry = this->GetDataNode()->GetData()->GetGeometry(timeStep);
geometry->WorldToIndex( pickedPoint, localPickedPoint );
Vector3D v1 = localPickedPoint.GetVectorFromOrigin();
vtkDataArray* normal = polyData->GetPointData()->GetVectors("planeNormal");
if (normal != NULL)
{
m_ObjectNormal[0] = normal->GetComponent(0, 0);
m_ObjectNormal[1] = normal->GetComponent(0, 1);
m_ObjectNormal[2] = normal->GetComponent(0, 2);
}
double denom = m_GaussSigma * m_GaussSigma * 2;
for (vtkIdType i = 0; i < points->GetNumberOfPoints(); ++i)
{
// Get original point
double* point = points->GetPoint(i);
Vector3D v0;
v0[0] = point[0];
v0[1] = point[1];
v0[2] = point[2];
// Calculate distance of this point from line through picked point
double d = itk::CrossProduct(m_ObjectNormal, (v1 - v0)).GetNorm();
double t = exp(- d * d / denom);
scalars->SetComponent(i, 0, t);
}
}
else if (mode == COLORIZATION_CONSTANT)
{
for (vtkIdType i = 0; i < pointData->GetNumberOfTuples(); ++i)
{
scalars->SetComponent(i, 0, scalar);
}
}
polyData->Modified();
pointData->Update();
return true;
}
diff --git a/Modules/DataTypesExt/mitkUnstructuredGrid.cpp b/Modules/DataTypesExt/mitkUnstructuredGrid.cpp
index 01f34f61b2..8dfe2970d8 100644
--- a/Modules/DataTypesExt/mitkUnstructuredGrid.cpp
+++ b/Modules/DataTypesExt/mitkUnstructuredGrid.cpp
@@ -1,248 +1,248 @@
/*===================================================================
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 "mitkUnstructuredGrid.h"
#include <vtkUnstructuredGrid.h>
void mitk::UnstructuredGrid::SetVtkUnstructuredGrid( vtkUnstructuredGrid* grid, unsigned int t )
{
this->Expand(t);
if(m_GridSeries[ t ] != NULL)
{
m_GridSeries[ t ]->Delete();
}
m_GridSeries[ t ] = grid;
// call m_VtkPolyData->Register(NULL) to tell the reference counting that we
// want to keep a reference on the object
if (m_GridSeries[t] != 0)
m_GridSeries[t]->Register(grid);
this->Modified();
m_CalculateBoundingBox = true;
}
void mitk::UnstructuredGrid::Expand(unsigned int timeSteps)
{
// check if the vector is long enough to contain the new element
// at the given position. If not, expand it with sufficient zero-filled elements.
if(timeSteps > m_GridSeries.size())
{
Superclass::Expand(timeSteps);
vtkUnstructuredGrid* pdnull = 0;
m_GridSeries.resize( timeSteps, pdnull );
m_CalculateBoundingBox = true;
}
}
void mitk::UnstructuredGrid::ClearData()
{
for ( VTKUnstructuredGridSeries::iterator it = m_GridSeries.begin(); it != m_GridSeries.end(); ++it )
{
if ( ( *it ) != 0 )
( *it )->Delete();
}
m_GridSeries.clear();
Superclass::ClearData();
}
void mitk::UnstructuredGrid::InitializeEmpty()
{
vtkUnstructuredGrid* pdnull = 0;
m_GridSeries.resize( 1, pdnull );
Superclass::InitializeTimeGeometry(1);
m_Initialized = true;
}
vtkUnstructuredGrid* mitk::UnstructuredGrid::GetVtkUnstructuredGrid(unsigned int t)
{
if ( t < m_GridSeries.size() )
{
vtkUnstructuredGrid* grid = m_GridSeries[ t ];
if((grid == 0) && (GetSource().GetPointer() != 0))
{
RegionType requestedregion;
requestedregion.SetIndex(3, t);
requestedregion.SetSize(3, 1);
SetRequestedRegion(&requestedregion);
GetSource()->Update();
}
grid = m_GridSeries[ t ];
return grid;
}
else
return 0;
}
mitk::UnstructuredGrid::UnstructuredGrid() : m_CalculateBoundingBox( false )
{
this->InitializeEmpty();
}
mitk::UnstructuredGrid::UnstructuredGrid(const mitk::UnstructuredGrid &other) :
BaseData(other),
m_LargestPossibleRegion(other.m_LargestPossibleRegion),
m_CalculateBoundingBox( other.m_CalculateBoundingBox )
{
if(!other.m_Initialized)
{
this->InitializeEmpty();
}
else
{
m_GridSeries = other.m_GridSeries;
m_Initialized = other.m_Initialized;
}
this->SetRequestedRegion( const_cast<mitk::UnstructuredGrid*>(&other) );
}
mitk::UnstructuredGrid::~UnstructuredGrid()
{
this->ClearData();
}
void mitk::UnstructuredGrid::UpdateOutputInformation()
{
if ( this->GetSource() )
{
this->GetSource()->UpdateOutputInformation();
}
if ( ( m_CalculateBoundingBox ) && ( m_GridSeries.size() > 0 ) )
CalculateBoundingBox();
else
GetTimeGeometry()->Update();
}
void mitk::UnstructuredGrid::CalculateBoundingBox()
{
//
// first make sure, that the associated time sliced geometry has
// the same number of geometry 3d's as vtkUnstructuredGrids are present
//
TimeGeometry* timeGeometry = GetTimeGeometry();
if ( timeGeometry->CountTimeSteps() != m_GridSeries.size() )
{
itkExceptionMacro(<<"timeGeometry->CountTimeSteps() != m_GridSeries.size() -- use Initialize(timeSteps) with correct number of timeSteps!");
}
//
// Iterate over the vtkUnstructuredGrids and update the Geometry
// information of each of the items.
//
for ( unsigned int i = 0 ; i < m_GridSeries.size() ; ++i )
{
vtkUnstructuredGrid* grid = m_GridSeries[ i ];
double bounds[ ] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
if ( ( grid != 0 ) && ( grid->GetNumberOfCells() > 0 ) )
{
// grid->Update(); //VTK6_TODO
grid->ComputeBounds();
grid->GetBounds( bounds );
}
- mitk::Geometry3D::Pointer g3d = timeGeometry->GetGeometryForTimeStep( i );
+ mitk::BaseGeometry::Pointer g3d = timeGeometry->GetGeometryForTimeStep( i );
assert( g3d.IsNotNull() );
g3d->SetFloatBounds( bounds );
}
timeGeometry->Update();
mitk::BoundingBox::Pointer bb = const_cast<mitk::BoundingBox*>( timeGeometry->GetBoundingBoxInWorld() );
itkDebugMacro( << "boundingbox min: "<< bb->GetMinimum());
itkDebugMacro( << "boundingbox max: "<< bb->GetMaximum());
m_CalculateBoundingBox = false;
}
void mitk::UnstructuredGrid::SetRequestedRegionToLargestPossibleRegion()
{
m_RequestedRegion = GetLargestPossibleRegion();
}
bool mitk::UnstructuredGrid::RequestedRegionIsOutsideOfTheBufferedRegion()
{
RegionType::IndexValueType end = m_RequestedRegion.GetIndex(3)+m_RequestedRegion.GetSize(3);
if(((RegionType::IndexValueType)m_GridSeries.size()) < end)
return true;
for( RegionType::IndexValueType t=m_RequestedRegion.GetIndex(3); t < end; ++t )
if(m_GridSeries[t] == 0)
return true;
return false;
}
bool mitk::UnstructuredGrid::VerifyRequestedRegion()
{
if( (m_RequestedRegion.GetIndex(3)>=0) &&
(m_RequestedRegion.GetIndex(3)+m_RequestedRegion.GetSize(3)<=m_GridSeries.size()) )
return true;
return false;
}
void mitk::UnstructuredGrid::SetRequestedRegion(const itk::DataObject *data )
{
const mitk::UnstructuredGrid *gridData;
gridData = dynamic_cast<const mitk::UnstructuredGrid*>(data);
if (gridData)
{
m_RequestedRegion = gridData->GetRequestedRegion();
}
else
{
// pointer could not be cast back down
itkExceptionMacro( << "mitk::UnstructuredGrid::SetRequestedRegion(DataObject*) cannot cast " << typeid(data).name() << " to " << typeid(UnstructuredGrid*).name() );
}
}
void mitk::UnstructuredGrid::SetRequestedRegion(UnstructuredGrid::RegionType *region) //by arin
{
if(region != 0)
{
m_RequestedRegion = *region;
}
else
{
// pointer could not be cast back down
itkExceptionMacro( << "mitk::UnstructuredGrid::SetRequestedRegion(UnstructuredGrid::RegionType*) cannot cast " << typeid(region).name() << " to " << typeid(UnstructuredGrid*).name() );
}
}
void mitk::UnstructuredGrid::CopyInformation( const itk::DataObject * data )
{
Superclass::CopyInformation(data);
}
void mitk::UnstructuredGrid::Update()
{
if ( GetSource().IsNull() )
{
for ( VTKUnstructuredGridSeries::iterator it = m_GridSeries.begin() ; it != m_GridSeries.end() ; ++it )
{
// if ( ( *it ) != 0 )
// ( *it )->Update(); //VTK6_TODO
}
}
Superclass::Update();
}
diff --git a/Modules/DiffusionImaging/Connectomics/Algorithms/mitkConnectomicsNetworkCreator.cpp b/Modules/DiffusionImaging/Connectomics/Algorithms/mitkConnectomicsNetworkCreator.cpp
index ff5ffc92a4..532263b49b 100644
--- a/Modules/DiffusionImaging/Connectomics/Algorithms/mitkConnectomicsNetworkCreator.cpp
+++ b/Modules/DiffusionImaging/Connectomics/Algorithms/mitkConnectomicsNetworkCreator.cpp
@@ -1,864 +1,864 @@
/*===================================================================
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 "mitkConnectomicsNetworkCreator.h"
#include <sstream>
#include <vector>
#include "mitkConnectomicsConstantsManager.h"
#include "mitkImageAccessByItk.h"
#include "mitkImageStatisticsHolder.h"
#include "mitkImageCast.h"
#include "itkImageRegionIteratorWithIndex.h"
// VTK
#include <vtkPolyData.h>
#include <vtkPolyLine.h>
#include <vtkCellArray.h>
mitk::ConnectomicsNetworkCreator::ConnectomicsNetworkCreator()
: m_FiberBundle()
, m_Segmentation()
, m_ConNetwork( mitk::ConnectomicsNetwork::New() )
, idCounter(0)
, m_LabelToVertexMap()
, m_LabelToNodePropertyMap()
, allowLoops( false )
, m_UseCoMCoordinates( false )
, m_LabelsToCoordinatesMap()
, m_MappingStrategy( EndElementPositionAvoidingWhiteMatter )
, m_EndPointSearchRadius( 10.0 )
, m_ZeroLabelInvalid( true )
, m_AbortConnection( false )
{
}
mitk::ConnectomicsNetworkCreator::ConnectomicsNetworkCreator( mitk::Image::Pointer segmentation, mitk::FiberBundleX::Pointer fiberBundle )
: m_FiberBundle(fiberBundle)
, m_Segmentation(segmentation)
, m_ConNetwork( mitk::ConnectomicsNetwork::New() )
, idCounter(0)
, m_LabelToVertexMap()
, m_LabelToNodePropertyMap()
, allowLoops( false )
, m_LabelsToCoordinatesMap()
, m_MappingStrategy( EndElementPositionAvoidingWhiteMatter )
, m_EndPointSearchRadius( 10.0 )
, m_ZeroLabelInvalid( true )
, m_AbortConnection( false )
{
mitk::CastToItkImage( segmentation, m_SegmentationItk );
}
mitk::ConnectomicsNetworkCreator::~ConnectomicsNetworkCreator()
{
}
void mitk::ConnectomicsNetworkCreator::SetFiberBundle(mitk::FiberBundleX::Pointer fiberBundle)
{
m_FiberBundle = fiberBundle;
}
void mitk::ConnectomicsNetworkCreator::SetSegmentation(mitk::Image::Pointer segmentation)
{
m_Segmentation = segmentation;
mitk::CastToItkImage( segmentation, m_SegmentationItk );
}
itk::Point<float, 3> mitk::ConnectomicsNetworkCreator::GetItkPoint(double point[3])
{
itk::Point<float, 3> itkPoint;
itkPoint[0] = point[0];
itkPoint[1] = point[1];
itkPoint[2] = point[2];
return itkPoint;
}
void mitk::ConnectomicsNetworkCreator::CreateNetworkFromFibersAndSegmentation()
{
//empty graph
m_ConNetwork = mitk::ConnectomicsNetwork::New();
m_LabelToVertexMap.clear();
m_LabelToNodePropertyMap.clear();
idCounter = 0;
vtkSmartPointer<vtkPolyData> fiberPolyData = m_FiberBundle->GetFiberPolyData();
vtkSmartPointer<vtkCellArray> vLines = fiberPolyData->GetLines();
vLines->InitTraversal();
int numFibers = m_FiberBundle->GetNumFibers();
for( int fiberID( 0 ); fiberID < numFibers; fiberID++ )
{
vtkIdType numPointsInCell(0);
vtkIdType* pointsInCell(NULL);
vLines->GetNextCell ( numPointsInCell, pointsInCell );
TractType::Pointer singleTract = TractType::New();
for( int pointInCellID( 0 ); pointInCellID < numPointsInCell ; pointInCellID++)
{
// push back point
PointType point = GetItkPoint( fiberPolyData->GetPoint( pointsInCell[ pointInCellID ] ) );
singleTract->InsertElement( singleTract->Size(), point );
}
if ( singleTract && ( singleTract->Size() > 0 ) )
{
AddConnectionToNetwork(
ReturnAssociatedVertexPairForLabelPair(
ReturnLabelForFiberTract( singleTract, m_MappingStrategy )
)
);
m_AbortConnection = false;
}
}
// Prune unconnected nodes
//m_ConNetwork->PruneUnconnectedSingleNodes();
// provide network with geometry
- m_ConNetwork->SetGeometry( dynamic_cast<mitk::Geometry3D*>(m_Segmentation->GetGeometry()->Clone().GetPointer()) );
+ m_ConNetwork->SetGeometry( dynamic_cast<mitk::BaseGeometry*>(m_Segmentation->GetGeometry()->Clone().GetPointer()) );
m_ConNetwork->UpdateBounds();
m_ConNetwork->SetIsModified( true );
MBI_INFO << mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_INFO_NETWORK_CREATED;
}
void mitk::ConnectomicsNetworkCreator::AddConnectionToNetwork(ConnectionType newConnection)
{
if( m_AbortConnection )
{
MITK_DEBUG << "Connection aborted";
return;
}
VertexType vertexA = newConnection.first;
VertexType vertexB = newConnection.second;
// check for loops (if they are not allowed)
if( allowLoops || !( vertexA == vertexB ) )
{
// If the connection already exists, increment weight, else create connection
if ( m_ConNetwork->EdgeExists( vertexA, vertexB ) )
{
m_ConNetwork->IncreaseEdgeWeight( vertexA, vertexB );
}
else
{
m_ConNetwork->AddEdge( vertexA, vertexB );
}
}
}
mitk::ConnectomicsNetworkCreator::VertexType mitk::ConnectomicsNetworkCreator::ReturnAssociatedVertexForLabel( ImageLabelType label )
{
if( m_ZeroLabelInvalid && ( label == 0 ) )
{
m_AbortConnection = true;
return ULONG_MAX;
}
// if label is not known, create entry
if( ! ( m_LabelToVertexMap.count( label ) > 0 ) )
{
VertexType newVertex = m_ConNetwork->AddVertex( idCounter );
idCounter++;
SupplyVertexWithInformation(label, newVertex);
m_LabelToVertexMap.insert( std::pair< ImageLabelType, VertexType >( label, newVertex ) );
}
//return associated vertex
return m_LabelToVertexMap.find( label )->second;
}
mitk::ConnectomicsNetworkCreator::ConnectionType mitk::ConnectomicsNetworkCreator::ReturnAssociatedVertexPairForLabelPair( ImageLabelPairType labelpair )
{
//hand both labels through to the single label function
ConnectionType connection( ReturnAssociatedVertexForLabel(labelpair.first), ReturnAssociatedVertexForLabel(labelpair.second) );
return connection;
}
mitk::ConnectomicsNetworkCreator::ImageLabelPairType mitk::ConnectomicsNetworkCreator::ReturnLabelForFiberTract( TractType::Pointer singleTract, mitk::ConnectomicsNetworkCreator::MappingStrategy strategy)
{
switch( strategy )
{
case EndElementPosition:
{
return EndElementPositionLabel( singleTract );
}
case JustEndPointVerticesNoLabel:
{
return JustEndPointVerticesNoLabelTest( singleTract );
}
case EndElementPositionAvoidingWhiteMatter:
{
return EndElementPositionLabelAvoidingWhiteMatter( singleTract );
}
case PrecomputeAndDistance:
{
return PrecomputeVertexLocationsBySegmentation( singleTract );
}
}
// To remove warnings, this code should never be reached
MBI_ERROR << mitk::ConnectomicsConstantsManager::CONNECTOMICS_ERROR_INVALID_MAPPING;
ImageLabelPairType nullPair( 0,0 );
return nullPair;
}
mitk::ConnectomicsNetworkCreator::ImageLabelPairType mitk::ConnectomicsNetworkCreator::EndElementPositionLabel( TractType::Pointer singleTract )
{
ImageLabelPairType labelpair;
{// Note: .fib image tracts are safed using index coordinates
mitk::Point3D firstElementFiberCoord, lastElementFiberCoord;
mitk::Point3D firstElementSegCoord, lastElementSegCoord;
mitk::Index3D firstElementSegIndex, lastElementSegIndex;
if( singleTract->front().Size() != 3 )
{
MBI_ERROR << mitk::ConnectomicsConstantsManager::CONNECTOMICS_ERROR_INVALID_DIMENSION_NEED_3;
}
for( unsigned int index = 0; index < singleTract->front().Size(); index++ )
{
firstElementFiberCoord.SetElement( index, singleTract->front().GetElement( index ) );
lastElementFiberCoord.SetElement( index, singleTract->back().GetElement( index ) );
}
// convert from fiber index coordinates to segmentation index coordinates
FiberToSegmentationCoords( firstElementFiberCoord, firstElementSegCoord );
FiberToSegmentationCoords( lastElementFiberCoord, lastElementSegCoord );
for( int index = 0; index < 3; index++ )
{
firstElementSegIndex.SetElement( index, firstElementSegCoord.GetElement( index ) );
lastElementSegIndex.SetElement( index, lastElementSegCoord.GetElement( index ) );
}
int firstLabel = m_SegmentationItk->GetPixel(firstElementSegIndex);
int lastLabel = m_SegmentationItk->GetPixel(lastElementSegIndex );
labelpair.first = firstLabel;
labelpair.second = lastLabel;
// Add property to property map
CreateNewNode( firstLabel, firstElementSegIndex, m_UseCoMCoordinates );
CreateNewNode( lastLabel, lastElementSegIndex, m_UseCoMCoordinates );
}
return labelpair;
}
mitk::ConnectomicsNetworkCreator::ImageLabelPairType mitk::ConnectomicsNetworkCreator::PrecomputeVertexLocationsBySegmentation( TractType::Pointer /*singleTract*/ )
{
ImageLabelPairType labelpair;
return labelpair;
}
mitk::ConnectomicsNetworkCreator::ImageLabelPairType mitk::ConnectomicsNetworkCreator::EndElementPositionLabelAvoidingWhiteMatter( TractType::Pointer singleTract )
{
ImageLabelPairType labelpair;
{// Note: .fib image tracts are safed using index coordinates
mitk::Point3D firstElementFiberCoord, lastElementFiberCoord;
mitk::Point3D firstElementSegCoord, lastElementSegCoord;
mitk::Index3D firstElementSegIndex, lastElementSegIndex;
if( singleTract->front().Size() != 3 )
{
MBI_ERROR << mitk::ConnectomicsConstantsManager::CONNECTOMICS_ERROR_INVALID_DIMENSION_NEED_3;
}
for( unsigned int index = 0; index < singleTract->front().Size(); index++ )
{
firstElementFiberCoord.SetElement( index, singleTract->front().GetElement( index ) );
lastElementFiberCoord.SetElement( index, singleTract->back().GetElement( index ) );
}
// convert from fiber index coordinates to segmentation index coordinates
FiberToSegmentationCoords( firstElementFiberCoord, firstElementSegCoord );
FiberToSegmentationCoords( lastElementFiberCoord, lastElementSegCoord );
for( int index = 0; index < 3; index++ )
{
firstElementSegIndex.SetElement( index, firstElementSegCoord.GetElement( index ) );
lastElementSegIndex.SetElement( index, lastElementSegCoord.GetElement( index ) );
}
int firstLabel = m_SegmentationItk->GetPixel(firstElementSegIndex);
int lastLabel = m_SegmentationItk->GetPixel(lastElementSegIndex );
// Check whether the labels belong to the white matter (which means, that the fibers ended early)
bool extendFront(false), extendEnd(false), retractFront(false), retractEnd(false);
extendFront = !IsNonWhiteMatterLabel( firstLabel );
extendEnd = !IsNonWhiteMatterLabel( lastLabel );
retractFront = IsBackgroundLabel( firstLabel );
retractEnd = IsBackgroundLabel( lastLabel );
//if( extendFront || extendEnd )
//{
//MBI_INFO << "Before Start: " << firstLabel << " at " << firstElementSegIndex[ 0 ] << " " << firstElementSegIndex[ 1 ] << " " << firstElementSegIndex[ 2 ] << " End: " << lastLabel << " at " << lastElementSegIndex[ 0 ] << " " << lastElementSegIndex[ 1 ] << " " << lastElementSegIndex[ 2 ];
//}
if ( extendFront )
{
std::vector< int > indexVectorOfPointsToUse;
//Use first two points for direction
indexVectorOfPointsToUse.push_back( 1 );
indexVectorOfPointsToUse.push_back( 0 );
// label and coordinate temp storage
int tempLabel( firstLabel );
mitk::Index3D tempIndex = firstElementSegIndex;
LinearExtensionUntilGreyMatter( indexVectorOfPointsToUse, singleTract, tempLabel, tempIndex );
firstLabel = tempLabel;
firstElementSegIndex = tempIndex;
}
if ( extendEnd )
{
std::vector< int > indexVectorOfPointsToUse;
//Use last two points for direction
indexVectorOfPointsToUse.push_back( singleTract->Size() - 2 );
indexVectorOfPointsToUse.push_back( singleTract->Size() - 1 );
// label and coordinate temp storage
int tempLabel( lastLabel );
mitk::Index3D tempIndex = lastElementSegIndex;
LinearExtensionUntilGreyMatter( indexVectorOfPointsToUse, singleTract, tempLabel, tempIndex );
lastLabel = tempLabel;
lastElementSegIndex = tempIndex;
}
if ( retractFront )
{
// label and coordinate temp storage
int tempLabel( firstLabel );
mitk::Index3D tempIndex = firstElementSegIndex;
RetractionUntilBrainMatter( true, singleTract, tempLabel, tempIndex );
firstLabel = tempLabel;
firstElementSegIndex = tempIndex;
}
if ( retractEnd )
{
// label and coordinate temp storage
int tempLabel( lastLabel );
mitk::Index3D tempIndex = lastElementSegIndex;
RetractionUntilBrainMatter( false, singleTract, tempLabel, tempIndex );
lastLabel = tempLabel;
lastElementSegIndex = tempIndex;
}
//if( extendFront || extendEnd )
//{
// MBI_INFO << "After Start: " << firstLabel << " at " << firstElementSegIndex[ 0 ] << " " << firstElementSegIndex[ 1 ] << " " << firstElementSegIndex[ 2 ] << " End: " << lastLabel << " at " << lastElementSegIndex[ 0 ] << " " << lastElementSegIndex[ 1 ] << " " << lastElementSegIndex[ 2 ];
//}
labelpair.first = firstLabel;
labelpair.second = lastLabel;
// Add property to property map
CreateNewNode( firstLabel, firstElementSegIndex, m_UseCoMCoordinates );
CreateNewNode( lastLabel, lastElementSegIndex, m_UseCoMCoordinates );
}
return labelpair;
}
mitk::ConnectomicsNetworkCreator::ImageLabelPairType mitk::ConnectomicsNetworkCreator::JustEndPointVerticesNoLabelTest( TractType::Pointer singleTract )
{
ImageLabelPairType labelpair;
{// Note: .fib image tracts are safed using index coordinates
mitk::Point3D firstElementFiberCoord, lastElementFiberCoord;
mitk::Point3D firstElementSegCoord, lastElementSegCoord;
mitk::Index3D firstElementSegIndex, lastElementSegIndex;
if( singleTract->front().Size() != 3 )
{
MBI_ERROR << mitk::ConnectomicsConstantsManager::CONNECTOMICS_ERROR_INVALID_DIMENSION_NEED_3;
}
for( unsigned int index = 0; index < singleTract->front().Size(); index++ )
{
firstElementFiberCoord.SetElement( index, singleTract->front().GetElement( index ) );
lastElementFiberCoord.SetElement( index, singleTract->back().GetElement( index ) );
}
// convert from fiber index coordinates to segmentation index coordinates
FiberToSegmentationCoords( firstElementFiberCoord, firstElementSegCoord );
FiberToSegmentationCoords( lastElementFiberCoord, lastElementSegCoord );
for( int index = 0; index < 3; index++ )
{
firstElementSegIndex.SetElement( index, firstElementSegCoord.GetElement( index ) );
lastElementSegIndex.SetElement( index, lastElementSegCoord.GetElement( index ) );
}
int firstLabel = 1 * firstElementSegIndex[ 0 ] + 1000 * firstElementSegIndex[ 1 ] + 1000000 * firstElementSegIndex[ 2 ];
int lastLabel = 1 * firstElementSegIndex[ 0 ] + 1000 * firstElementSegIndex[ 1 ] + 1000000 * firstElementSegIndex[ 2 ];
labelpair.first = firstLabel;
labelpair.second = lastLabel;
// Add property to property map
CreateNewNode( firstLabel, firstElementSegIndex, m_UseCoMCoordinates );
CreateNewNode( lastLabel, lastElementSegIndex, m_UseCoMCoordinates );
}
return labelpair;
}
void mitk::ConnectomicsNetworkCreator::SupplyVertexWithInformation( ImageLabelType& label, VertexType& vertex )
{ // supply a vertex with the additional information belonging to the label
// TODO: Implement additional information acquisition
m_ConNetwork->SetLabel( vertex, m_LabelToNodePropertyMap.find( label )->second.label );
m_ConNetwork->SetCoordinates( vertex, m_LabelToNodePropertyMap.find( label )->second.coordinates );
}
std::string mitk::ConnectomicsNetworkCreator::LabelToString( ImageLabelType& label )
{
int tempInt = (int) label;
std::stringstream ss;//create a stringstream
std::string tempString;
ss << tempInt;//add number to the stream
tempString = ss.str();
return tempString;//return a string with the contents of the stream
}
mitk::ConnectomicsNetwork::Pointer mitk::ConnectomicsNetworkCreator::GetNetwork()
{
return m_ConNetwork;
}
void mitk::ConnectomicsNetworkCreator::FiberToSegmentationCoords( mitk::Point3D& fiberCoord, mitk::Point3D& segCoord )
{
mitk::Point3D tempPoint;
// convert from fiber index coordinates to segmentation index coordinates
m_FiberBundle->GetGeometry()->IndexToWorld( fiberCoord, tempPoint );
m_Segmentation->GetGeometry()->WorldToIndex( tempPoint, segCoord );
}
void mitk::ConnectomicsNetworkCreator::SegmentationToFiberCoords( mitk::Point3D& segCoord, mitk::Point3D& fiberCoord )
{
mitk::Point3D tempPoint;
// convert from fiber index coordinates to segmentation index coordinates
m_Segmentation->GetGeometry()->IndexToWorld( segCoord, tempPoint );
m_FiberBundle->GetGeometry()->WorldToIndex( tempPoint, fiberCoord );
}
bool mitk::ConnectomicsNetworkCreator::IsNonWhiteMatterLabel( int labelInQuestion )
{
bool isWhite( false );
isWhite = (
( labelInQuestion == freesurfer_Left_Cerebral_White_Matter ) ||
( labelInQuestion == freesurfer_Left_Cerebellum_White_Matter ) ||
( labelInQuestion == freesurfer_Right_Cerebral_White_Matter ) ||
( labelInQuestion == freesurfer_Right_Cerebellum_White_Matter )||
( labelInQuestion == freesurfer_Left_Cerebellum_Cortex ) ||
( labelInQuestion == freesurfer_Right_Cerebellum_Cortex ) ||
( labelInQuestion == freesurfer_Brain_Stem )
);
return !isWhite;
}
bool mitk::ConnectomicsNetworkCreator::IsBackgroundLabel( int labelInQuestion )
{
bool isBackground( false );
isBackground = ( labelInQuestion == 0 );
return isBackground;
}
void mitk::ConnectomicsNetworkCreator::LinearExtensionUntilGreyMatter(
std::vector<int> & indexVectorOfPointsToUse,
TractType::Pointer singleTract,
int & label,
mitk::Index3D & mitkIndex )
{
if( indexVectorOfPointsToUse.size() > singleTract->Size() )
{
MBI_WARN << mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_MORE_POINTS_THAN_PRESENT;
return;
}
if( indexVectorOfPointsToUse.size() < 2 )
{
MBI_WARN << mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_ESTIMATING_LESS_THAN_2;
return;
}
for( unsigned int index( 0 ); index < indexVectorOfPointsToUse.size(); index++ )
{
if( indexVectorOfPointsToUse[ index ] < 0 )
{
MBI_WARN << mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_ESTIMATING_BEYOND_START;
return;
}
if( (unsigned int)indexVectorOfPointsToUse[ index ] > singleTract->Size() )
{
MBI_WARN << mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_ESTIMATING_BEYOND_END;
return;
}
}
mitk::Point3D startPoint, endPoint;
std::vector< double > differenceVector;
differenceVector.resize( singleTract->front().Size() );
{
// which points to use, currently only last two //TODO correct using all points
int endPointIndex = indexVectorOfPointsToUse.size() - 1;
int startPointIndex = indexVectorOfPointsToUse.size() - 2;
// convert to segmentation coords
mitk::Point3D startFiber, endFiber;
for( unsigned int index = 0; index < singleTract->front().Size(); index++ )
{
endFiber.SetElement( index, singleTract->GetElement( indexVectorOfPointsToUse[ endPointIndex ] ).GetElement( index ) );
startFiber.SetElement( index, singleTract->GetElement( indexVectorOfPointsToUse[ startPointIndex ] ).GetElement( index ) );
}
FiberToSegmentationCoords( endFiber, endPoint );
FiberToSegmentationCoords( startFiber, startPoint );
// calculate straight line
for( unsigned int index = 0; index < singleTract->front().Size(); index++ )
{
differenceVector[ index ] = endPoint.GetElement( index ) - startPoint.GetElement( index );
}
// normalizing direction vector
double length( 0.0 );
double sum( 0.0 );
for( unsigned int index = 0; index < differenceVector.size() ; index++ )
{
sum = sum + differenceVector[ index ] * differenceVector[ index ];
}
length = std::sqrt( sum );
for( unsigned int index = 0; index < differenceVector.size() ; index++ )
{
differenceVector[ index ] = differenceVector[ index ] / length;
}
// follow line until first non white matter label
mitk::Index3D tempIndex;
int tempLabel( label );
bool keepOn( true );
itk::ImageRegion<3> itkRegion = m_SegmentationItk->GetLargestPossibleRegion();
for( int parameter( 0 ) ; keepOn ; parameter++ )
{
if( parameter > 1000 )
{
MBI_WARN << mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_DID_NOT_FIND_WHITE;
break;
}
for( int index( 0 ); index < 3; index++ )
{
tempIndex.SetElement( index, endPoint.GetElement( index ) + parameter * differenceVector[ index ] );
}
if( itkRegion.IsInside( tempIndex ) )
{
tempLabel = m_SegmentationItk->GetPixel( tempIndex );
}
else
{
tempLabel = -1;
}
if( IsNonWhiteMatterLabel( tempLabel ) )
{
if( tempLabel < 1 )
{
keepOn = false;
//MBI_WARN << mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_NOT_EXTEND_TO_WHITE;
}
else
{
label = tempLabel;
mitkIndex = tempIndex;
keepOn = false;
}
}
}
}
}
void mitk::ConnectomicsNetworkCreator::RetractionUntilBrainMatter( bool retractFront, TractType::Pointer singleTract,
int & label, mitk::Index3D & mitkIndex )
{
int retractionStartIndex( singleTract->Size() - 1 );
int retractionStepIndexSize( -1 );
int retractionTerminationIndex( 0 );
if( retractFront )
{
retractionStartIndex = 0;
retractionStepIndexSize = 1;
retractionTerminationIndex = singleTract->Size() - 1;
}
int currentRetractionIndex = retractionStartIndex;
bool keepRetracting( true );
mitk::Point3D currentPoint, nextPoint;
std::vector< double > differenceVector;
differenceVector.resize( singleTract->front().Size() );
while( keepRetracting && ( currentRetractionIndex != retractionTerminationIndex ) )
{
// convert to segmentation coords
mitk::Point3D currentPointFiberCoord, nextPointFiberCoord;
for( unsigned int index = 0; index < singleTract->front().Size(); index++ )
{
currentPointFiberCoord.SetElement( index, singleTract->GetElement( currentRetractionIndex ).GetElement( index ) );
nextPointFiberCoord.SetElement( index, singleTract->GetElement( currentRetractionIndex + retractionStepIndexSize ).GetElement( index ) );
}
FiberToSegmentationCoords( currentPointFiberCoord, currentPoint );
FiberToSegmentationCoords( nextPointFiberCoord, nextPoint );
// calculate straight line
for( unsigned int index = 0; index < singleTract->front().Size(); index++ )
{
differenceVector[ index ] = nextPoint.GetElement( index ) - currentPoint.GetElement( index );
}
// calculate length of direction vector
double length( 0.0 );
double sum( 0.0 );
for( unsigned int index = 0; index < differenceVector.size() ; index++ )
{
sum = sum + differenceVector[ index ] * differenceVector[ index ];
}
length = std::sqrt( sum );
// retract
mitk::Index3D tempIndex;
int tempLabel( label );
for( int parameter( 0 ) ; parameter < length ; parameter++ )
{
for( int index( 0 ); index < 3; index++ )
{
tempIndex.SetElement( index,
currentPoint.GetElement( index ) + ( 1.0 + parameter ) / ( 1.0 + length ) * differenceVector[ index ] );
}
tempLabel = m_SegmentationItk->GetPixel( tempIndex );
if( !IsBackgroundLabel( tempLabel ) )
{
// check whether result is within the search space
{
mitk::Point3D endPoint, foundPointSegmentation, foundPointFiber;
for( unsigned int index = 0; index < singleTract->front().Size(); index++ )
{
// this is in fiber (world) coordinates
endPoint.SetElement( index, singleTract->GetElement( retractionStartIndex ).GetElement( index ) );
}
for( int index( 0 ); index < 3; index++ )
{
foundPointSegmentation.SetElement( index,
currentPoint.GetElement( index ) + ( 1.0 + parameter ) / ( 1.0 + length ) * differenceVector[ index ] );
}
SegmentationToFiberCoords( foundPointSegmentation, foundPointFiber );
std::vector< double > finalDistance;
finalDistance.resize( singleTract->front().Size() );
for( unsigned int index = 0; index < singleTract->front().Size(); index++ )
{
finalDistance[ index ] = foundPointFiber.GetElement( index ) - endPoint.GetElement( index );
}
// calculate length of direction vector
double finalLength( 0.0 );
double finalSum( 0.0 );
for( unsigned int index = 0; index < finalDistance.size() ; index++ )
{
finalSum = finalSum + finalDistance[ index ] * finalDistance[ index ];
}
finalLength = std::sqrt( finalSum );
if( finalLength > m_EndPointSearchRadius )
{
// the found point was not within the search space
return;
}
}
label = tempLabel;
mitkIndex = tempIndex;
return;
}
// hit next point without finding brain matter
currentRetractionIndex = currentRetractionIndex + retractionStepIndexSize;
if( ( currentRetractionIndex < 1 ) || ( (unsigned int)currentRetractionIndex > ( singleTract->Size() - 2 ) ) )
{
keepRetracting = false;
}
}
}
}
void mitk::ConnectomicsNetworkCreator::CalculateCenterOfMass()
{
const int dimensions = 3;
int max = m_Segmentation->GetStatistics()->GetScalarValueMax();
int min = m_Segmentation->GetStatistics()->GetScalarValueMin();
int range = max - min +1;
// each label owns a vector of coordinates
std::vector< std::vector< std::vector< double> > > coordinatesPerLabelVector;
coordinatesPerLabelVector.resize( range );
itk::ImageRegionIteratorWithIndex<ITKImageType> it_itkImage( m_SegmentationItk, m_SegmentationItk->GetLargestPossibleRegion() );
for( it_itkImage.GoToBegin(); !it_itkImage.IsAtEnd(); ++it_itkImage )
{
std::vector< double > coordinates;
coordinates.resize(dimensions);
itk::Index< dimensions > index = it_itkImage.GetIndex();
for( int loop(0); loop < dimensions; loop++)
{
coordinates.at( loop ) = index.GetElement( loop );
}
// add the coordinates to the corresponding label vector
coordinatesPerLabelVector.at( it_itkImage.Value() - min ).push_back( coordinates );
}
for(int currentIndex(0), currentLabel( min ); currentIndex < range; currentIndex++, currentLabel++ )
{
std::vector< double > currentCoordinates;
currentCoordinates.resize(dimensions);
int numberOfPoints = coordinatesPerLabelVector.at( currentIndex ).size();
std::vector< double > sumCoords;
sumCoords.resize( dimensions );
for( int loop(0); loop < numberOfPoints; loop++ )
{
for( int loopDimension( 0 ); loopDimension < dimensions; loopDimension++ )
{
sumCoords.at( loopDimension ) += coordinatesPerLabelVector.at( currentIndex ).at( loop ).at( loopDimension );
}
}
for( int loopDimension( 0 ); loopDimension < dimensions; loopDimension++ )
{
currentCoordinates.at( loopDimension ) = sumCoords.at( loopDimension ) / numberOfPoints;
}
m_LabelsToCoordinatesMap.insert( std::pair< int, std::vector<double> >( currentLabel, currentCoordinates ) );
}
//can now use center of mass coordinates
m_UseCoMCoordinates = true;
}
std::vector< double > mitk::ConnectomicsNetworkCreator::GetCenterOfMass( int label )
{
// if label is not known, warn
if( ! ( m_LabelsToCoordinatesMap.count( label ) > 0 ) )
{
MITK_ERROR << "Label " << label << " not found. Could not return coordinates.";
std::vector< double > nullVector;
nullVector.resize(3);
return nullVector;
}
//return associated coordinates
return m_LabelsToCoordinatesMap.find( label )->second;
}
void mitk::ConnectomicsNetworkCreator::CreateNewNode( int label, mitk::Index3D index, bool useCoM )
{
// Only create node if it does not exist yet
if( ! ( m_LabelToNodePropertyMap.count( label ) > 0 ) )
{
NetworkNode newNode;
newNode.coordinates.resize( 3 );
if( !useCoM )
{
for( unsigned int loop = 0; loop < newNode.coordinates.size() ; loop++ )
{
newNode.coordinates[ loop ] = index[ loop ] ;
}
}
else
{
std::vector<double> labelCoords = GetCenterOfMass( label );
for( unsigned int loop = 0; loop < newNode.coordinates.size() ; loop++ )
{
newNode.coordinates[ loop ] = labelCoords.at( loop ) ;
}
}
newNode.label = LabelToString( label );
m_LabelToNodePropertyMap.insert( std::pair< ImageLabelType, NetworkNode >( label, newNode ) );
}
}
diff --git a/Modules/DiffusionImaging/DiffusionCore/Algorithms/mitkPartialVolumeAnalysisHistogramCalculator.cpp b/Modules/DiffusionImaging/DiffusionCore/Algorithms/mitkPartialVolumeAnalysisHistogramCalculator.cpp
index 0162c0858d..c84f89dbbd 100644
--- a/Modules/DiffusionImaging/DiffusionCore/Algorithms/mitkPartialVolumeAnalysisHistogramCalculator.cpp
+++ b/Modules/DiffusionImaging/DiffusionCore/Algorithms/mitkPartialVolumeAnalysisHistogramCalculator.cpp
@@ -1,1256 +1,1256 @@
/*===================================================================
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 "mitkPartialVolumeAnalysisHistogramCalculator.h"
#include "mitkImageAccessByItk.h"
#include "mitkExtractImageFilter.h"
#include <itkScalarImageToHistogramGenerator.h>
#include <itkStatisticsImageFilter.h>
#include <itkLabelStatisticsImageFilter.h>
#include <itkBSplineUpsampleImageFilter.h>
#include <itkBSplineResampleImageFilterBase.h>
#include "itkResampleImageFilter.h"
#include "itkGaussianInterpolateImageFunction.h"
#include <itkCastImageFilter.h>
#include <itkImageFileWriter.h>
#include <itkVTKImageImport.h>
#include <itkVTKImageExport.h>
#include <vtkPoints.h>
#include <vtkCellArray.h>
#include <vtkPolyData.h>
#include <vtkLinearExtrusionFilter.h>
#include <vtkPolyDataToImageStencil.h>
#include <vtkImageStencil.h>
#include <vtkImageImport.h>
#include <vtkImageExport.h>
#include <vtkImageData.h>
#include <vtkMetaImageWriter.h>
#include <exception>
#include "itkGaussianInterpolateImageFunction.h"
#include "itkBSplineInterpolateImageFunction.h"
#include "itkNearestNeighborInterpolateImageFunction.h"
#include "itkImageMaskSpatialObject.h"
#include "itkRegionOfInterestImageFilter.h"
#include "itkListSample.h"
#include <iostream>
#include <sstream>
namespace mitk
{
PartialVolumeAnalysisHistogramCalculator::PartialVolumeAnalysisHistogramCalculator()
: m_MaskingMode( MASKING_MODE_NONE ),
m_MaskingModeChanged( false ),
m_NumberOfBins(256),
m_UpsamplingFactor(1),
m_GaussianSigma(0),
m_ForceUpdate(false),
m_PlanarFigureThickness(0)
{
m_EmptyHistogram = HistogramType::New();
m_EmptyHistogram->SetMeasurementVectorSize(1);
HistogramType::SizeType histogramSize(1);
histogramSize.Fill( 256 );
m_EmptyHistogram->Initialize( histogramSize );
m_EmptyStatistics.Reset();
}
PartialVolumeAnalysisHistogramCalculator::~PartialVolumeAnalysisHistogramCalculator()
{
}
void PartialVolumeAnalysisHistogramCalculator::SetImage( const mitk::Image *image )
{
if ( m_Image != image )
{
m_Image = image;
this->Modified();
m_ImageStatisticsTimeStamp.Modified();
m_ImageStatisticsCalculationTriggerBool = true;
}
}
void PartialVolumeAnalysisHistogramCalculator::AddAdditionalResamplingImage( const mitk::Image *image )
{
m_AdditionalResamplingImages.push_back(image);
this->Modified();
m_ImageStatisticsTimeStamp.Modified();
m_ImageStatisticsCalculationTriggerBool = true;
}
void PartialVolumeAnalysisHistogramCalculator::SetModified( )
{
this->Modified();
m_ImageStatisticsTimeStamp.Modified();
m_ImageStatisticsCalculationTriggerBool = true;
m_MaskedImageStatisticsTimeStamp.Modified();
m_MaskedImageStatisticsCalculationTriggerBool = true;
m_PlanarFigureStatisticsTimeStamp.Modified();
m_PlanarFigureStatisticsCalculationTriggerBool = true;
}
void PartialVolumeAnalysisHistogramCalculator::SetImageMask( const mitk::Image *imageMask )
{
if ( m_Image.IsNull() )
{
itkExceptionMacro( << "Image needs to be set first!" );
}
if ( m_Image->GetTimeSteps() != imageMask->GetTimeSteps() )
{
itkExceptionMacro( << "Image and image mask need to have equal number of time steps!" );
}
if ( m_ImageMask != imageMask )
{
m_ImageMask = imageMask;
this->Modified();
m_MaskedImageStatisticsTimeStamp.Modified();
m_MaskedImageStatisticsCalculationTriggerBool = true;
}
}
void PartialVolumeAnalysisHistogramCalculator::SetPlanarFigure( const mitk::PlanarFigure *planarFigure )
{
if ( m_Image.IsNull() )
{
itkExceptionMacro( << "Image needs to be set first!" );
}
if ( m_PlanarFigure != planarFigure )
{
m_PlanarFigure = planarFigure;
this->Modified();
m_PlanarFigureStatisticsTimeStamp.Modified();
m_PlanarFigureStatisticsCalculationTriggerBool = true;
}
}
void PartialVolumeAnalysisHistogramCalculator::SetMaskingMode( unsigned int mode )
{
if ( m_MaskingMode != mode )
{
m_MaskingMode = mode;
m_MaskingModeChanged = true;
this->Modified();
}
}
void PartialVolumeAnalysisHistogramCalculator::SetMaskingModeToNone()
{
if ( m_MaskingMode != MASKING_MODE_NONE )
{
m_MaskingMode = MASKING_MODE_NONE;
m_MaskingModeChanged = true;
this->Modified();
}
}
void PartialVolumeAnalysisHistogramCalculator::SetMaskingModeToImage()
{
if ( m_MaskingMode != MASKING_MODE_IMAGE )
{
m_MaskingMode = MASKING_MODE_IMAGE;
m_MaskingModeChanged = true;
this->Modified();
}
}
void PartialVolumeAnalysisHistogramCalculator::SetMaskingModeToPlanarFigure()
{
if ( m_MaskingMode != MASKING_MODE_PLANARFIGURE )
{
m_MaskingMode = MASKING_MODE_PLANARFIGURE;
m_MaskingModeChanged = true;
this->Modified();
}
}
bool PartialVolumeAnalysisHistogramCalculator::ComputeStatistics()
{
MITK_DEBUG << "ComputeStatistics() start";
if ( m_Image.IsNull() )
{
itkExceptionMacro( << "Image not set!" );
}
if ( m_Image->GetReferenceCount() == 1 )
{
MITK_DEBUG << "No Stats calculated; no one else holds a reference on it";
return false;
}
// If a mask was set but we are the only ones to still hold a reference on
// it, delete it.
if ( m_ImageMask.IsNotNull() && (m_ImageMask->GetReferenceCount() == 1) )
{
m_ImageMask = NULL;
}
// Check if statistics is already up-to-date
unsigned long imageMTime = m_ImageStatisticsTimeStamp.GetMTime();
unsigned long maskedImageMTime = m_MaskedImageStatisticsTimeStamp.GetMTime();
unsigned long planarFigureMTime = m_PlanarFigureStatisticsTimeStamp.GetMTime();
bool imageStatisticsCalculationTrigger = m_ImageStatisticsCalculationTriggerBool;
bool maskedImageStatisticsCalculationTrigger = m_MaskedImageStatisticsCalculationTriggerBool;
bool planarFigureStatisticsCalculationTrigger = m_PlanarFigureStatisticsCalculationTriggerBool;
if ( /*prevent calculation without mask*/!m_ForceUpdate &&( m_MaskingMode == MASKING_MODE_NONE || (
((m_MaskingMode != MASKING_MODE_NONE) || (imageMTime > m_Image->GetMTime() && !imageStatisticsCalculationTrigger))
&& ((m_MaskingMode != MASKING_MODE_IMAGE) || (m_ImageMask.IsNotNull() && maskedImageMTime > m_ImageMask->GetMTime() && !maskedImageStatisticsCalculationTrigger))
&& ((m_MaskingMode != MASKING_MODE_PLANARFIGURE) || (m_PlanarFigure.IsNotNull() && planarFigureMTime > m_PlanarFigure->GetMTime() && !planarFigureStatisticsCalculationTrigger)) ) ) )
{
MITK_DEBUG << "Returning, statistics already up to date!";
if ( m_MaskingModeChanged )
{
m_MaskingModeChanged = false;
return true;
}
else
{
return false;
}
}
// Reset state changed flag
m_MaskingModeChanged = false;
// Depending on masking mode, extract and/or generate the required image
// and mask data from the user input
this->ExtractImageAndMask( );
Statistics *statistics;
HistogramType::ConstPointer *histogram;
switch ( m_MaskingMode )
{
case MASKING_MODE_NONE:
default:
statistics = &m_ImageStatistics;
histogram = &m_ImageHistogram;
m_ImageStatisticsTimeStamp.Modified();
m_ImageStatisticsCalculationTriggerBool = false;
break;
case MASKING_MODE_IMAGE:
statistics = &m_MaskedImageStatistics;
histogram = &m_MaskedImageHistogram;
m_MaskedImageStatisticsTimeStamp.Modified();
m_MaskedImageStatisticsCalculationTriggerBool = false;
break;
case MASKING_MODE_PLANARFIGURE:
statistics = &m_PlanarFigureStatistics;
histogram = &m_PlanarFigureHistogram;
m_PlanarFigureStatisticsTimeStamp.Modified();
m_PlanarFigureStatisticsCalculationTriggerBool = false;
break;
}
// Calculate statistics and histogram(s)
if ( m_InternalImage->GetDimension() == 3 )
{
if ( m_MaskingMode == MASKING_MODE_NONE )
{
// Reset state changed flag
AccessFixedDimensionByItk_2(
m_InternalImage,
InternalCalculateStatisticsUnmasked,
3,
*statistics,
histogram );
}
else
{
AccessFixedDimensionByItk_3(
m_InternalImage,
InternalCalculateStatisticsMasked,
3,
m_InternalImageMask3D.GetPointer(),
*statistics,
histogram );
}
}
else if ( m_InternalImage->GetDimension() == 2 )
{
if ( m_MaskingMode == MASKING_MODE_NONE )
{
AccessFixedDimensionByItk_2(
m_InternalImage,
InternalCalculateStatisticsUnmasked,
2,
*statistics,
histogram );
}
else
{
AccessFixedDimensionByItk_3(
m_InternalImage,
InternalCalculateStatisticsMasked,
2,
m_InternalImageMask2D.GetPointer(),
*statistics,
histogram );
}
}
else
{
MITK_ERROR << "ImageStatistics: Image dimension not supported!";
}
// Release unused image smart pointers to free memory
// m_InternalImage = mitk::Image::Pointer();
m_InternalImageMask3D = MaskImage3DType::Pointer();
m_InternalImageMask2D = MaskImage2DType::Pointer();
return true;
}
const PartialVolumeAnalysisHistogramCalculator::HistogramType *
PartialVolumeAnalysisHistogramCalculator::GetHistogram( ) const
{
if ( m_Image.IsNull() )
{
return NULL;
}
switch ( m_MaskingMode )
{
case MASKING_MODE_NONE:
default:
return m_ImageHistogram;
case MASKING_MODE_IMAGE:
return m_MaskedImageHistogram;
case MASKING_MODE_PLANARFIGURE:
return m_PlanarFigureHistogram;
}
}
const PartialVolumeAnalysisHistogramCalculator::Statistics &
PartialVolumeAnalysisHistogramCalculator::GetStatistics( ) const
{
if ( m_Image.IsNull() )
{
return m_EmptyStatistics;
}
switch ( m_MaskingMode )
{
case MASKING_MODE_NONE:
default:
return m_ImageStatistics;
case MASKING_MODE_IMAGE:
return m_MaskedImageStatistics;
case MASKING_MODE_PLANARFIGURE:
return m_PlanarFigureStatistics;
}
}
void PartialVolumeAnalysisHistogramCalculator::ExtractImageAndMask( )
{
MITK_DEBUG << "ExtractImageAndMask( ) start";
if ( m_Image.IsNull() )
{
throw std::runtime_error( "Error: image empty!" );
}
mitk::Image *timeSliceImage = const_cast<mitk::Image*>(m_Image.GetPointer());//imageTimeSelector->GetOutput();
switch ( m_MaskingMode )
{
case MASKING_MODE_NONE:
{
m_InternalImage = timeSliceImage;
int s = m_AdditionalResamplingImages.size();
m_InternalAdditionalResamplingImages.resize(s);
for(int i=0; i<s; i++)
{
m_InternalAdditionalResamplingImages[i] = const_cast<mitk::Image*>(m_AdditionalResamplingImages[i].GetPointer());
}
m_InternalImageMask2D = NULL;
m_InternalImageMask3D = NULL;
break;
}
case MASKING_MODE_IMAGE:
{
if ( m_ImageMask.IsNotNull() && (m_ImageMask->GetReferenceCount() > 1) )
{
ImageTimeSelector::Pointer maskedImageTimeSelector = ImageTimeSelector::New();
maskedImageTimeSelector->SetInput( m_ImageMask );
maskedImageTimeSelector->SetTimeNr( 0 );
maskedImageTimeSelector->UpdateLargestPossibleRegion();
mitk::Image *timeSliceMaskedImage = maskedImageTimeSelector->GetOutput();
InternalMaskImage(timeSliceMaskedImage);
if(m_UpsamplingFactor != 1)
{
InternalResampleImage(m_InternalImageMask3D);
}
AccessFixedDimensionByItk_1(
timeSliceImage,
InternalResampleImageFromMask, 3, -1 );
int s = m_AdditionalResamplingImages.size();
m_InternalAdditionalResamplingImages.resize(s);
for(int i=0; i<s; i++)
{
AccessFixedDimensionByItk_1(
m_AdditionalResamplingImages[i],
InternalResampleImageFromMask, 3, i );
}
}
else
{
throw std::runtime_error( "Error: image mask empty!" );
}
break;
}
case MASKING_MODE_PLANARFIGURE:
{
m_InternalImageMask2D = NULL;
if ( m_PlanarFigure.IsNull() )
{
throw std::runtime_error( "Error: planar figure empty!" );
}
if ( !m_PlanarFigure->IsClosed() )
{
throw std::runtime_error( "Masking not possible for non-closed figures" );
}
- const Geometry3D *imageGeometry = timeSliceImage->GetUpdatedGeometry();
+ const BaseGeometry *imageGeometry = timeSliceImage->GetUpdatedGeometry();
if ( imageGeometry == NULL )
{
throw std::runtime_error( "Image geometry invalid!" );
}
- const Geometry2D *planarFigureGeometry2D = m_PlanarFigure->GetGeometry2D();
+ const PlaneGeometry *planarFigureGeometry2D = m_PlanarFigure->GetPlaneGeometry();
if ( planarFigureGeometry2D == NULL )
{
throw std::runtime_error( "Planar-Figure not yet initialized!" );
}
const PlaneGeometry *planarFigureGeometry =
dynamic_cast< const PlaneGeometry * >( planarFigureGeometry2D );
if ( planarFigureGeometry == NULL )
{
throw std::runtime_error( "Non-planar planar figures not supported!" );
}
// unsigned int axis = 2;
// unsigned int slice = 0;
AccessFixedDimensionByItk_3(
timeSliceImage,
InternalReorientImagePlane, 3,
timeSliceImage->GetGeometry(),
m_PlanarFigure->GetGeometry(), -1 );
AccessFixedDimensionByItk_1(
m_InternalImage,
InternalCalculateMaskFromPlanarFigure,
3, 2 );
int s = m_AdditionalResamplingImages.size();
for(int i=0; i<s; i++)
{
AccessFixedDimensionByItk_3(
m_AdditionalResamplingImages[i],
InternalReorientImagePlane, 3,
timeSliceImage->GetGeometry(),
m_PlanarFigure->GetGeometry(), i );
AccessFixedDimensionByItk_1(
m_InternalAdditionalResamplingImages[i],
InternalCropAdditionalImage, 3, i );
}
}
}
}
bool PartialVolumeAnalysisHistogramCalculator::GetPrincipalAxis(
const Geometry3D *geometry, Vector3D vector,
unsigned int &axis )
{
vector.Normalize();
for ( unsigned int i = 0; i < 3; ++i )
{
Vector3D axisVector = geometry->GetAxisVector( i );
axisVector.Normalize();
if ( fabs( fabs( axisVector * vector ) - 1.0) < mitk::eps )
{
axis = i;
return true;
}
}
return false;
}
void PartialVolumeAnalysisHistogramCalculator::InternalMaskImage(
mitk::Image *image )
{
typedef itk::ImageMaskSpatialObject<3> ImageMaskSpatialObject;
typedef itk::Image< unsigned char, 3 > ImageType;
typedef itk::ImageRegion<3> RegionType;
typedef mitk::ImageToItk<ImageType> CastType;
CastType::Pointer caster = CastType::New();
caster->SetInput(image);
caster->Update();
ImageMaskSpatialObject::Pointer maskSO = ImageMaskSpatialObject::New();
maskSO->SetImage ( caster->GetOutput() );
m_InternalMask3D =
maskSO->GetAxisAlignedBoundingBoxRegion();
// check if bounding box is empty, if so set it to 1,1,1
// to prevent empty mask image
if (m_InternalMask3D.GetSize()[0] == 0 )
{
m_InternalMask3D.SetSize(0,1);
m_InternalMask3D.SetSize(1,1);
m_InternalMask3D.SetSize(2,1);
}
MITK_DEBUG << "Bounding Box Region: " << m_InternalMask3D;
typedef itk::RegionOfInterestImageFilter< ImageType, MaskImage3DType > ROIFilterType;
ROIFilterType::Pointer roi = ROIFilterType::New();
roi->SetRegionOfInterest(m_InternalMask3D);
roi->SetInput(caster->GetOutput());
roi->Update();
m_InternalImageMask3D = roi->GetOutput();
MITK_DEBUG << "Created m_InternalImageMask3D";
}
template < typename TPixel, unsigned int VImageDimension >
void PartialVolumeAnalysisHistogramCalculator::InternalReorientImagePlane(
const itk::Image< TPixel, VImageDimension > *image,
- mitk::Geometry3D* , mitk::Geometry3D* planegeo3D, int additionalIndex )
+ mitk::BaseGeometry* , mitk::BaseGeometry* planegeo3D, int additionalIndex )
{
MITK_DEBUG << "InternalReorientImagePlane() start";
typedef itk::Image< TPixel, VImageDimension > ImageType;
typedef itk::Image< float, VImageDimension > FloatImageType;
typedef itk::ResampleImageFilter<ImageType, FloatImageType, double> ResamplerType;
typename ResamplerType::Pointer resampler = ResamplerType::New();
mitk::PlaneGeometry* planegeo = dynamic_cast<mitk::PlaneGeometry*>(planegeo3D);
float upsamp = m_UpsamplingFactor;
float gausssigma = m_GaussianSigma;
// Spacing
typename ResamplerType::SpacingType spacing = planegeo->GetSpacing();
spacing[0] = image->GetSpacing()[0] / upsamp;
spacing[1] = image->GetSpacing()[1] / upsamp;
spacing[2] = image->GetSpacing()[2];
if(m_PlanarFigureThickness)
{
spacing[2] = image->GetSpacing()[2] / upsamp;
}
resampler->SetOutputSpacing( spacing );
// Size
typename ResamplerType::SizeType size;
- size[0] = planegeo->GetParametricExtentInMM(0) / spacing[0];
- size[1] = planegeo->GetParametricExtentInMM(1) / spacing[1];
+ size[0] = planegeo->GetExtentInMM(0) / spacing[0];
+ size[1] = planegeo->GetExtentInMM(1) / spacing[1];
size[2] = 1+2*m_PlanarFigureThickness; // klaus add +2*m_PlanarFigureThickness
MITK_DEBUG << "setting size2:="<<size[2] << " (before " << 1 << ")";
resampler->SetSize( size );
// Origin
typename mitk::Point3D orig = planegeo->GetOrigin();
typename mitk::Point3D corrorig;
planegeo3D->WorldToIndex(orig,corrorig);
corrorig[0] += 0.5/upsamp;
corrorig[1] += 0.5/upsamp;
if(m_PlanarFigureThickness)
{
float thickyyy = m_PlanarFigureThickness;
thickyyy/=upsamp;
corrorig[2] -= thickyyy; // klaus add -= (float)m_PlanarFigureThickness/upsamp statt += 0
}
planegeo3D->IndexToWorld(corrorig,corrorig);
resampler->SetOutputOrigin(corrorig );
// Direction
typename ResamplerType::DirectionType direction;
typename mitk::AffineTransform3D::MatrixType matrix = planegeo->GetIndexToWorldTransform()->GetMatrix();
for(int c=0; c<matrix.ColumnDimensions; c++)
{
double sum = 0;
for(int r=0; r<matrix.RowDimensions; r++)
{
sum += matrix(r,c)*matrix(r,c);
}
for(int r=0; r<matrix.RowDimensions; r++)
{
direction(r,c) = matrix(r,c)/sqrt(sum);
}
}
resampler->SetOutputDirection( direction );
// Gaussian interpolation
if(gausssigma != 0)
{
double sigma[3];
for( unsigned int d = 0; d < 3; d++ )
{
sigma[d] = gausssigma * image->GetSpacing()[d];
}
double alpha = 2.0;
typedef itk::GaussianInterpolateImageFunction<ImageType, double>
GaussianInterpolatorType;
typename GaussianInterpolatorType::Pointer interpolator
= GaussianInterpolatorType::New();
interpolator->SetInputImage( image );
interpolator->SetParameters( sigma, alpha );
resampler->SetInterpolator( interpolator );
}
else
{
// typedef typename itk::BSplineInterpolateImageFunction<ImageType, double>
// InterpolatorType;
typedef typename itk::LinearInterpolateImageFunction<ImageType, double> InterpolatorType;
typename InterpolatorType::Pointer interpolator
= InterpolatorType::New();
interpolator->SetInputImage( image );
resampler->SetInterpolator( interpolator );
}
// Other resampling options
resampler->SetInput( image );
resampler->SetDefaultPixelValue(0);
MITK_DEBUG << "Resampling requested image plane ... ";
resampler->Update();
MITK_DEBUG << " ... done";
if(additionalIndex < 0)
{
this->m_InternalImage = mitk::Image::New();
this->m_InternalImage->InitializeByItk( resampler->GetOutput() );
this->m_InternalImage->SetVolume( resampler->GetOutput()->GetBufferPointer() );
}
else
{
unsigned int myIndex = additionalIndex;
this->m_InternalAdditionalResamplingImages.push_back(mitk::Image::New());
this->m_InternalAdditionalResamplingImages[myIndex]->InitializeByItk( resampler->GetOutput() );
this->m_InternalAdditionalResamplingImages[myIndex]->SetVolume( resampler->GetOutput()->GetBufferPointer() );
}
}
template < typename TPixel, unsigned int VImageDimension >
void PartialVolumeAnalysisHistogramCalculator::InternalResampleImageFromMask(
const itk::Image< TPixel, VImageDimension > *image, int additionalIndex )
{
typedef itk::Image< TPixel, VImageDimension > ImageType;
typename ImageType::Pointer outImage = ImageType::New();
outImage->SetSpacing( m_InternalImageMask3D->GetSpacing() ); // Set the image spacing
outImage->SetOrigin( m_InternalImageMask3D->GetOrigin() ); // Set the image origin
outImage->SetDirection( m_InternalImageMask3D->GetDirection() ); // Set the image direction
outImage->SetRegions( m_InternalImageMask3D->GetLargestPossibleRegion() );
outImage->Allocate();
outImage->FillBuffer(0);
typedef itk::InterpolateImageFunction<ImageType, double>
BaseInterpType;
typedef itk::GaussianInterpolateImageFunction<ImageType, double>
GaussianInterpolatorType;
typedef itk::LinearInterpolateImageFunction<ImageType, double>
LinearInterpolatorType;
typename BaseInterpType::Pointer interpolator;
if(m_GaussianSigma != 0)
{
double sigma[3];
for( unsigned int d = 0; d < 3; d++ )
{
sigma[d] = m_GaussianSigma * image->GetSpacing()[d];
}
double alpha = 2.0;
interpolator = GaussianInterpolatorType::New();
dynamic_cast<GaussianInterpolatorType*>(interpolator.GetPointer())->SetParameters( sigma, alpha );
}
else
{
interpolator = LinearInterpolatorType::New();
}
interpolator->SetInputImage( image );
itk::ImageRegionConstIterator<MaskImage3DType>
itmask(m_InternalImageMask3D, m_InternalImageMask3D->GetLargestPossibleRegion());
itk::ImageRegionIterator<ImageType>
itimage(outImage, outImage->GetLargestPossibleRegion());
itmask.GoToBegin();
itimage.GoToBegin();
itk::Point< double, 3 > point;
itk::ContinuousIndex< double, 3 > index;
while( !itmask.IsAtEnd() )
{
if(itmask.Get() != 0)
{
outImage->TransformIndexToPhysicalPoint (itimage.GetIndex(), point);
image->TransformPhysicalPointToContinuousIndex(point, index);
itimage.Set(interpolator->EvaluateAtContinuousIndex(index));
}
++itmask;
++itimage;
}
if(additionalIndex < 0)
{
this->m_InternalImage = mitk::Image::New();
this->m_InternalImage->InitializeByItk( outImage.GetPointer() );
this->m_InternalImage->SetVolume( outImage->GetBufferPointer() );
}
else
{
this->m_InternalAdditionalResamplingImages[additionalIndex] = mitk::Image::New();
this->m_InternalAdditionalResamplingImages[additionalIndex]->InitializeByItk( outImage.GetPointer() );
this->m_InternalAdditionalResamplingImages[additionalIndex]->SetVolume( outImage->GetBufferPointer() );
}
}
void PartialVolumeAnalysisHistogramCalculator::InternalResampleImage(
const MaskImage3DType *image )
{
typedef itk::ResampleImageFilter<MaskImage3DType, MaskImage3DType, double> ResamplerType;
ResamplerType::Pointer resampler = ResamplerType::New();
// Size
ResamplerType::SizeType size;
size[0] = m_UpsamplingFactor * image->GetLargestPossibleRegion().GetSize()[0];
size[1] = m_UpsamplingFactor * image->GetLargestPossibleRegion().GetSize()[1];
size[2] = m_UpsamplingFactor * image->GetLargestPossibleRegion().GetSize()[2];;
resampler->SetSize( size );
// Origin
mitk::Point3D orig = image->GetOrigin();
resampler->SetOutputOrigin(orig );
// Spacing
ResamplerType::SpacingType spacing;
spacing[0] = image->GetSpacing()[0] / m_UpsamplingFactor;
spacing[1] = image->GetSpacing()[1] / m_UpsamplingFactor;
spacing[2] = image->GetSpacing()[2] / m_UpsamplingFactor;
resampler->SetOutputSpacing( spacing );
resampler->SetOutputDirection( image->GetDirection() );
typedef itk::NearestNeighborInterpolateImageFunction<MaskImage3DType, double>
InterpolatorType;
InterpolatorType::Pointer interpolator
= InterpolatorType::New();
interpolator->SetInputImage( image );
resampler->SetInterpolator( interpolator );
// Other resampling options
resampler->SetInput( image );
resampler->SetDefaultPixelValue(0);
resampler->Update();
m_InternalImageMask3D = resampler->GetOutput();
}
template < typename TPixel, unsigned int VImageDimension >
void PartialVolumeAnalysisHistogramCalculator::InternalCalculateStatisticsUnmasked(
const itk::Image< TPixel, VImageDimension > *image,
Statistics &statistics,
typename HistogramType::ConstPointer *histogram )
{
MITK_DEBUG << "InternalCalculateStatisticsUnmasked()";
typedef itk::Image< TPixel, VImageDimension > ImageType;
typedef itk::Image< unsigned char, VImageDimension > MaskImageType;
typedef typename ImageType::IndexType IndexType;
// Progress listening...
typedef itk::SimpleMemberCommand< PartialVolumeAnalysisHistogramCalculator > ITKCommandType;
ITKCommandType::Pointer progressListener;
progressListener = ITKCommandType::New();
progressListener->SetCallbackFunction( this,
&PartialVolumeAnalysisHistogramCalculator::UnmaskedStatisticsProgressUpdate );
// Issue 100 artificial progress events since ScalarIMageToHistogramGenerator
// does not (yet?) support progress reporting
this->InvokeEvent( itk::StartEvent() );
for ( unsigned int i = 0; i < 100; ++i )
{
this->UnmaskedStatisticsProgressUpdate();
}
// Calculate statistics (separate filter)
typedef itk::StatisticsImageFilter< ImageType > StatisticsFilterType;
typename StatisticsFilterType::Pointer statisticsFilter = StatisticsFilterType::New();
statisticsFilter->SetInput( image );
unsigned long observerTag = statisticsFilter->AddObserver(
itk::ProgressEvent(), progressListener );
statisticsFilter->Update();
statisticsFilter->RemoveObserver( observerTag );
this->InvokeEvent( itk::EndEvent() );
statistics.N = image->GetBufferedRegion().GetNumberOfPixels();
statistics.Min = statisticsFilter->GetMinimum();
statistics.Max = statisticsFilter->GetMaximum();
statistics.Mean = statisticsFilter->GetMean();
statistics.Median = 0.0;
statistics.Sigma = statisticsFilter->GetSigma();
statistics.RMS = sqrt( statistics.Mean * statistics.Mean
+ statistics.Sigma * statistics.Sigma );
typename ImageType::Pointer inImage = const_cast<ImageType*>(image);
// Calculate histogram
typedef itk::Statistics::ScalarImageToHistogramGenerator< ImageType >
HistogramGeneratorType;
typename HistogramGeneratorType::Pointer histogramGenerator = HistogramGeneratorType::New();
histogramGenerator->SetInput( inImage );
histogramGenerator->SetMarginalScale( 10 ); // Defines y-margin width of histogram
histogramGenerator->SetNumberOfBins( m_NumberOfBins ); // CT range [-1024, +2048] --> bin size 4 values
histogramGenerator->SetHistogramMin( statistics.Min );
histogramGenerator->SetHistogramMax( statistics.Max );
histogramGenerator->Compute();
*histogram = histogramGenerator->GetOutput();
}
template < typename TPixel, unsigned int VImageDimension >
void PartialVolumeAnalysisHistogramCalculator::InternalCalculateStatisticsMasked(
const itk::Image< TPixel, VImageDimension > *image,
itk::Image< unsigned char, VImageDimension > *maskImage,
Statistics &,
typename HistogramType::ConstPointer *histogram )
{
MITK_DEBUG << "InternalCalculateStatisticsMasked() start";
typedef itk::Image< TPixel, VImageDimension > ImageType;
typedef itk::Image< unsigned char, VImageDimension > MaskImageType;
typedef typename ImageType::IndexType IndexType;
// generate a list sample of angles at positions
// where the fiber-prob is higher than .2*maxprob
typedef TPixel MeasurementType;
const unsigned int MeasurementVectorLength = 1;
typedef itk::Vector< MeasurementType , MeasurementVectorLength >
MeasurementVectorType;
typedef itk::Statistics::ListSample< MeasurementVectorType > ListSampleType;
typename ListSampleType::Pointer listSample = ListSampleType::New();
listSample->SetMeasurementVectorSize( MeasurementVectorLength );
itk::ImageRegionConstIterator<MaskImageType>
itmask(maskImage, maskImage->GetLargestPossibleRegion());
itk::ImageRegionConstIterator<ImageType>
itimage(image, image->GetLargestPossibleRegion());
itmask.GoToBegin();
itimage.GoToBegin();
while( !itmask.IsAtEnd() )
{
if(itmask.Get() != 0)
{
// apend to list
MeasurementVectorType mv;
mv[0] = ( MeasurementType ) itimage.Get();
listSample->PushBack(mv);
}
++itmask;
++itimage;
}
// generate a histogram from the list sample
typedef double HistogramMeasurementType;
typedef itk::Statistics::Histogram< HistogramMeasurementType, itk::Statistics::DenseFrequencyContainer2 > HistogramType;
typedef itk::Statistics::SampleToHistogramFilter< ListSampleType, HistogramType > GeneratorType;
typename GeneratorType::Pointer generator = GeneratorType::New();
typename GeneratorType::HistogramType::SizeType size(MeasurementVectorLength);
size.Fill(m_NumberOfBins);
generator->SetHistogramSize( size );
generator->SetInput( listSample );
generator->SetMarginalScale( 10.0 );
generator->Update();
*histogram = generator->GetOutput();
}
template < typename TPixel, unsigned int VImageDimension >
void PartialVolumeAnalysisHistogramCalculator::InternalCropAdditionalImage(
itk::Image< TPixel, VImageDimension > *image, int additionalIndex )
{
typedef itk::Image< TPixel, VImageDimension > ImageType;
typedef itk::RegionOfInterestImageFilter< ImageType, ImageType > ROIFilterType;
typename ROIFilterType::Pointer roi = ROIFilterType::New();
roi->SetRegionOfInterest(m_CropRegion);
roi->SetInput(image);
roi->Update();
m_InternalAdditionalResamplingImages[additionalIndex] = mitk::Image::New();
m_InternalAdditionalResamplingImages[additionalIndex]->InitializeByItk(roi->GetOutput());
m_InternalAdditionalResamplingImages[additionalIndex]->SetVolume(roi->GetOutput()->GetBufferPointer());
}
template < typename TPixel, unsigned int VImageDimension >
void PartialVolumeAnalysisHistogramCalculator::InternalCalculateMaskFromPlanarFigure(
itk::Image< TPixel, VImageDimension > *image, unsigned int axis )
{
MITK_DEBUG << "InternalCalculateMaskFromPlanarFigure() start";
typedef itk::Image< TPixel, VImageDimension > ImageType;
typedef itk::CastImageFilter< ImageType, MaskImage3DType > CastFilterType;
// Generate mask image as new image with same header as input image and
// initialize with "1".
MaskImage3DType::Pointer newMaskImage = MaskImage3DType::New();
newMaskImage->SetSpacing( image->GetSpacing() ); // Set the image spacing
newMaskImage->SetOrigin( image->GetOrigin() ); // Set the image origin
newMaskImage->SetDirection( image->GetDirection() ); // Set the image direction
newMaskImage->SetRegions( image->GetLargestPossibleRegion() );
newMaskImage->Allocate();
newMaskImage->FillBuffer( 1 );
// Generate VTK polygon from (closed) PlanarFigure polyline
// (The polyline points are shifted by -0.5 in z-direction to make sure
// that the extrusion filter, which afterwards elevates all points by +0.5
// in z-direction, creates a 3D object which is cut by the the plane z=0)
- const mitk::Geometry2D *planarFigureGeometry2D = m_PlanarFigure->GetGeometry2D();
+ const mitk::PlaneGeometry *planarFigureGeometry2D = m_PlanarFigure->GetPlaneGeometry();
const typename PlanarFigure::PolyLineType planarFigurePolyline = m_PlanarFigure->GetPolyLine( 0 );
- const mitk::Geometry3D *imageGeometry3D = m_InternalImage->GetGeometry( 0 );
+ const mitk::BaseGeometry *imageGeometry3D = m_InternalImage->GetGeometry( 0 );
vtkPolyData *polyline = vtkPolyData::New();
polyline->Allocate( 1, 1 );
// Determine x- and y-dimensions depending on principal axis
int i0, i1;
switch ( axis )
{
case 0:
i0 = 1;
i1 = 2;
break;
case 1:
i0 = 0;
i1 = 2;
break;
case 2:
default:
i0 = 0;
i1 = 1;
break;
}
// Create VTK polydata object of polyline contour
bool outOfBounds = false;
vtkPoints *points = vtkPoints::New();
typename PlanarFigure::PolyLineType::const_iterator it;
for ( it = planarFigurePolyline.begin();
it != planarFigurePolyline.end();
++it )
{
Point3D point3D;
// Convert 2D point back to the local index coordinates of the selected
// image
mitk::Point2D point2D = *it;
planarFigureGeometry2D->WorldToIndex(point2D, point2D);
point2D[0] -= 0.5/m_UpsamplingFactor;
point2D[1] -= 0.5/m_UpsamplingFactor;
planarFigureGeometry2D->IndexToWorld(point2D, point2D);
planarFigureGeometry2D->Map( point2D, point3D );
// Polygons (partially) outside of the image bounds can not be processed
// further due to a bug in vtkPolyDataToImageStencil
if ( !imageGeometry3D->IsInside( point3D ) )
{
outOfBounds = true;
}
imageGeometry3D->WorldToIndex( point3D, point3D );
point3D[i0] += 0.5;
point3D[i1] += 0.5;
// Add point to polyline array
points->InsertNextPoint( point3D[i0], point3D[i1], -0.5 );
}
polyline->SetPoints( points );
points->Delete();
if ( outOfBounds )
{
polyline->Delete();
throw std::runtime_error( "Figure at least partially outside of image bounds!" );
}
std::size_t numberOfPoints = planarFigurePolyline.size();
vtkIdType *ptIds = new vtkIdType[numberOfPoints];
for ( std::size_t i = 0; i < numberOfPoints; ++i )
{
ptIds[i] = i;
}
polyline->InsertNextCell( VTK_POLY_LINE, numberOfPoints, ptIds );
// Extrude the generated contour polygon
vtkLinearExtrusionFilter *extrudeFilter = vtkLinearExtrusionFilter::New();
extrudeFilter->SetInputData( polyline );
extrudeFilter->SetScaleFactor( 1 );
extrudeFilter->SetExtrusionTypeToNormalExtrusion();
extrudeFilter->SetVector( 0.0, 0.0, 1.0 );
// Make a stencil from the extruded polygon
vtkPolyDataToImageStencil *polyDataToImageStencil = vtkPolyDataToImageStencil::New();
polyDataToImageStencil->SetInputConnection( extrudeFilter->GetOutputPort() );
// Export from ITK to VTK (to use a VTK filter)
typedef itk::VTKImageImport< MaskImage3DType > ImageImportType;
typedef itk::VTKImageExport< MaskImage3DType > ImageExportType;
typename ImageExportType::Pointer itkExporter = ImageExportType::New();
itkExporter->SetInput( newMaskImage );
vtkImageImport *vtkImporter = vtkImageImport::New();
this->ConnectPipelines( itkExporter, vtkImporter );
vtkImporter->Update();
// Apply the generated image stencil to the input image
vtkImageStencil *imageStencilFilter = vtkImageStencil::New();
imageStencilFilter->SetInputData( vtkImporter->GetOutput() );
imageStencilFilter->SetStencilConnection(polyDataToImageStencil->GetOutputPort() );
imageStencilFilter->ReverseStencilOff();
imageStencilFilter->SetBackgroundValue( 0 );
imageStencilFilter->Update();
// Export from VTK back to ITK
vtkImageExport *vtkExporter = vtkImageExport::New();
vtkExporter->SetInputData( imageStencilFilter->GetOutput() );
vtkExporter->Update();
typename ImageImportType::Pointer itkImporter = ImageImportType::New();
this->ConnectPipelines( vtkExporter, itkImporter );
itkImporter->Update();
// calculate cropping bounding box
m_InternalImageMask3D = itkImporter->GetOutput();
m_InternalImageMask3D->SetDirection(image->GetDirection());
itk::ImageRegionIterator<MaskImage3DType>
itmask(m_InternalImageMask3D, m_InternalImageMask3D->GetLargestPossibleRegion());
itmask.GoToBegin();
while( !itmask.IsAtEnd() )
{
if(itmask.Get() != 0)
{
typename ImageType::IndexType index = itmask.GetIndex();
for(unsigned int thick=0; thick<2*m_PlanarFigureThickness+1; thick++)
{
index[axis] = thick;
m_InternalImageMask3D->SetPixel(index, itmask.Get());
}
}
++itmask;
}
itmask.GoToBegin();
itk::ImageRegionIterator<ImageType>
itimage(image, image->GetLargestPossibleRegion());
itimage.GoToBegin();
typename ImageType::SizeType lowersize;
lowersize.Fill(std::numeric_limits<typename ImageType::SizeValueType>::max());
typename ImageType::SizeType uppersize;
uppersize.Fill(std::numeric_limits<typename ImageType::SizeValueType>::min());
while( !itmask.IsAtEnd() )
{
if(itmask.Get() == 0)
{
itimage.Set(0);
}
else
{
typename ImageType::IndexType index = itimage.GetIndex();
typename ImageType::SizeType signedindex;
signedindex[0] = index[0];
signedindex[1] = index[1];
signedindex[2] = index[2];
lowersize[0] = signedindex[0] < lowersize[0] ? signedindex[0] : lowersize[0];
lowersize[1] = signedindex[1] < lowersize[1] ? signedindex[1] : lowersize[1];
lowersize[2] = signedindex[2] < lowersize[2] ? signedindex[2] : lowersize[2];
uppersize[0] = signedindex[0] > uppersize[0] ? signedindex[0] : uppersize[0];
uppersize[1] = signedindex[1] > uppersize[1] ? signedindex[1] : uppersize[1];
uppersize[2] = signedindex[2] > uppersize[2] ? signedindex[2] : uppersize[2];
}
++itmask;
++itimage;
}
typename ImageType::IndexType index;
index[0] = lowersize[0];
index[1] = lowersize[1];
index[2] = lowersize[2];
typename ImageType::SizeType size;
size[0] = uppersize[0] - lowersize[0] + 1;
size[1] = uppersize[1] - lowersize[1] + 1;
size[2] = uppersize[2] - lowersize[2] + 1;
m_CropRegion = itk::ImageRegion<3>(index, size);
// crop internal image
typedef itk::RegionOfInterestImageFilter< ImageType, ImageType > ROIFilterType;
typename ROIFilterType::Pointer roi = ROIFilterType::New();
roi->SetRegionOfInterest(m_CropRegion);
roi->SetInput(image);
roi->Update();
m_InternalImage = mitk::Image::New();
m_InternalImage->InitializeByItk(roi->GetOutput());
m_InternalImage->SetVolume(roi->GetOutput()->GetBufferPointer());
// crop internal mask
typedef itk::RegionOfInterestImageFilter< MaskImage3DType, MaskImage3DType > ROIMaskFilterType;
typename ROIMaskFilterType::Pointer roi2 = ROIMaskFilterType::New();
roi2->SetRegionOfInterest(m_CropRegion);
roi2->SetInput(m_InternalImageMask3D);
roi2->Update();
m_InternalImageMask3D = roi2->GetOutput();
// Clean up VTK objects
polyline->Delete();
extrudeFilter->Delete();
polyDataToImageStencil->Delete();
vtkImporter->Delete();
imageStencilFilter->Delete();
//vtkExporter->Delete(); // TODO: crashes when outcommented; memory leak??
delete[] ptIds;
}
void PartialVolumeAnalysisHistogramCalculator::UnmaskedStatisticsProgressUpdate()
{
// Need to throw away every second progress event to reach a final count of
// 100 since two consecutive filters are used in this case
static int updateCounter = 0;
if ( updateCounter++ % 2 == 0 )
{
this->InvokeEvent( itk::ProgressEvent() );
}
}
void PartialVolumeAnalysisHistogramCalculator::MaskedStatisticsProgressUpdate()
{
this->InvokeEvent( itk::ProgressEvent() );
}
}
diff --git a/Modules/DiffusionImaging/DiffusionCore/Algorithms/mitkPartialVolumeAnalysisHistogramCalculator.h b/Modules/DiffusionImaging/DiffusionCore/Algorithms/mitkPartialVolumeAnalysisHistogramCalculator.h
index 4209a67971..dac1f47f95 100644
--- a/Modules/DiffusionImaging/DiffusionCore/Algorithms/mitkPartialVolumeAnalysisHistogramCalculator.h
+++ b/Modules/DiffusionImaging/DiffusionCore/Algorithms/mitkPartialVolumeAnalysisHistogramCalculator.h
@@ -1,384 +1,384 @@
/*===================================================================
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 _MITK_PartialVolumeAnalysisHistogramCalculator_H
#define _MITK_PartialVolumeAnalysisHistogramCalculator_H
#include "MitkDiffusionCoreExports.h"
#include <itkObject.h>
#include <itkImage.h>
#include <itkTimeStamp.h>
#include "mitkImage.h"
#include "mitkImageTimeSelector.h"
#include "mitkPlanarFigure.h"
namespace mitk
{
/**
* \brief Class for calculating statistics and histogram for an (optionally
* masked) image.
*
* Images can be masked by either a (binary) image (of the same dimensions as
* the original image) or by a closed mitk::PlanarFigure, e.g. a circle or
* polygon. When masking with a planar figure, the slice corresponding to the
* plane containing the figure is extracted and then clipped with contour
* defined by the figure. Planar figures need to be aligned along the main axes
* of the image (axial, sagittal, coronal). Planar figures on arbitrary
* rotated planes are not supported.
*
* For each operating mode (no masking, masking by image, masking by planar
* figure), the calculated statistics and histogram are cached so that, when
* switching back and forth between operation modes without modifying mask or
* image, the information doesn't need to be recalculated.
*
* Note: currently time-resolved and multi-channel pictures are not properly
* supported.
*/
class MitkDiffusionCore_EXPORT PartialVolumeAnalysisHistogramCalculator : public itk::Object
{
public:
enum
{
MASKING_MODE_NONE = 0,
MASKING_MODE_IMAGE,
MASKING_MODE_PLANARFIGURE
};
typedef mitk::Image::HistogramType HistogramType;
typedef mitk::Image::HistogramType::ConstIterator HistogramConstIteratorType;
struct Statistics
{
unsigned int N;
double Min;
double Max;
double Mean;
double Median;
double Variance;
double Sigma;
double RMS;
void Reset()
{
N = 0;
Min = 0.0;
Max = 0.0;
Mean = 0.0;
Median = 0.0;
Variance = 0.0;
Sigma = 0.0;
RMS = 0.0;
}
};
typedef Statistics StatisticsType;
typedef itk::TimeStamp TimeStampType;
typedef bool BoolType;
typedef itk::Image< unsigned char, 3 > MaskImage3DType;
typedef itk::Image< unsigned char, 2 > MaskImage2DType;
typedef itk::Image< float, 2 > InternalImage2DType;
mitkClassMacro( PartialVolumeAnalysisHistogramCalculator, itk::Object )
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** \brief Set image from which to compute statistics. */
void SetImage( const mitk::Image *image );
/** \brief Set binary image for masking. */
void SetImageMask( const mitk::Image *imageMask );
/** \brief Set planar figure for masking. */
void SetPlanarFigure( const mitk::PlanarFigure *planarFigure );
/** \brief Set image for which the same resampling will be applied.
and available via GetAdditionalResampledImage() */
void AddAdditionalResamplingImage( const mitk::Image *image );
/** \brief Set/Get operation mode for masking */
void SetMaskingMode( unsigned int mode );
/** \brief Set/Get operation mode for masking */
itkGetMacro( MaskingMode, unsigned int );
/** \brief Set/Get operation mode for masking */
void SetMaskingModeToNone();
/** \brief Set/Get operation mode for masking */
void SetMaskingModeToImage();
/** \brief Set/Get operation mode for masking */
void SetMaskingModeToPlanarFigure();
/** \brief Set histogram number of bins. */
void SetNumberOfBins( unsigned int number )
{
if(m_NumberOfBins != number)
{
m_NumberOfBins = number;
SetModified();
}
}
/** \brief Get histogram number of bins. */
unsigned int GetNumberOfBins( )
{ return m_NumberOfBins; }
/** \brief Set upsampling factor. */
void SetUpsamplingFactor( float number )
{
if(m_UpsamplingFactor != number)
{
m_UpsamplingFactor = number;
SetModified();
}
}
/** \brief Get upsampling factor. */
float GetUpsamplingFactor( )
{ return m_UpsamplingFactor; }
/** \brief Set gaussian sigma. */
void SetGaussianSigma( float number )
{
if(m_GaussianSigma != number)
{
m_GaussianSigma = number;
SetModified();
}
}
/** \brief Get thickness of planar figure. */
unsigned int GetPlanarFigureThickness( )
{ return m_PlanarFigureThickness; }
/** \brief Set thickness of planar figure. */
void SetPlanarFigureThickness( unsigned int number )
{
if(m_PlanarFigureThickness != number)
{
m_PlanarFigureThickness = number;
SetModified();
}
}
/** \brief Get histogram number of bins. */
float GetGaussianSigma( )
{ return m_GaussianSigma; }
void SetModified();
/** \brief Compute statistics (together with histogram) for the current
* masking mode.
*
* Computation is not executed if statistics is already up to date. In this
* case, false is returned; otherwise, true.*/
virtual bool ComputeStatistics( );
/** \brief Retrieve the histogram depending on the current masking mode. */
const HistogramType *GetHistogram( ) const;
/** \brief Retrieve statistics depending on the current masking mode. */
const Statistics &GetStatistics( ) const;
const Image::Pointer GetInternalImage()
{
return m_InternalImage;
}
const Image::Pointer GetInternalAdditionalResampledImage(unsigned int i)
{
if(i < m_InternalAdditionalResamplingImages.size())
{
return m_InternalAdditionalResamplingImages[i];
}
else
{
return NULL;
}
}
void SetForceUpdate(bool b)
{
m_ForceUpdate = b;
}
protected:
PartialVolumeAnalysisHistogramCalculator();
virtual ~PartialVolumeAnalysisHistogramCalculator();
/** \brief Depending on the masking mode, the image and mask from which to
* calculate statistics is extracted from the original input image and mask
* data.
*
* For example, a when using a PlanarFigure as mask, the 2D image slice
* corresponding to the PlanarFigure will be extracted from the original
* image. If masking is disabled, the original image is simply passed
* through. */
void ExtractImageAndMask( );
/** \brief If the passed vector matches any of the three principal axes
* of the passed geometry, the ínteger value corresponding to the axis
* is set and true is returned. */
bool GetPrincipalAxis( const Geometry3D *geometry, Vector3D vector,
unsigned int &axis );
template < typename TPixel, unsigned int VImageDimension >
void InternalCalculateStatisticsUnmasked(
const itk::Image< TPixel, VImageDimension > *image,
Statistics &statistics,
typename HistogramType::ConstPointer *histogram );
template < typename TPixel, unsigned int VImageDimension >
void InternalCalculateStatisticsMasked(
const itk::Image< TPixel, VImageDimension > *image,
itk::Image< unsigned char, VImageDimension > *maskImage,
Statistics &statistics,
typename HistogramType::ConstPointer *histogram );
template < typename TPixel, unsigned int VImageDimension >
void InternalCalculateMaskFromPlanarFigure(
itk::Image< TPixel, VImageDimension > *image, unsigned int axis );
template < typename TPixel, unsigned int VImageDimension >
void InternalReorientImagePlane(
- const itk::Image< TPixel, VImageDimension > *image, mitk::Geometry3D* imggeo, mitk::Geometry3D* planegeo3D, int additionalIndex );
+ const itk::Image< TPixel, VImageDimension > *image, mitk::BaseGeometry* imggeo, mitk::BaseGeometry* planegeo3D, int additionalIndex );
template < typename TPixel, unsigned int VImageDimension >
void InternalResampleImageFromMask(
const itk::Image< TPixel, VImageDimension > *image, int additionalIndex );
void InternalResampleImage(
const MaskImage3DType *image/*, mitk::Geometry3D* imggeo*/ );
template < typename TPixel, unsigned int VImageDimension >
void InternalCropAdditionalImage(
itk::Image< TPixel, VImageDimension > *image, int additionalIndex );
void InternalMaskImage( mitk::Image *image );
/** Connection from ITK to VTK */
template <typename ITK_Exporter, typename VTK_Importer>
void ConnectPipelines(ITK_Exporter exporter, VTK_Importer* importer)
{
importer->SetUpdateInformationCallback(exporter->GetUpdateInformationCallback());
importer->SetPipelineModifiedCallback(exporter->GetPipelineModifiedCallback());
importer->SetWholeExtentCallback(exporter->GetWholeExtentCallback());
importer->SetSpacingCallback(exporter->GetSpacingCallback());
importer->SetOriginCallback(exporter->GetOriginCallback());
importer->SetScalarTypeCallback(exporter->GetScalarTypeCallback());
importer->SetNumberOfComponentsCallback(exporter->GetNumberOfComponentsCallback());
importer->SetPropagateUpdateExtentCallback(exporter->GetPropagateUpdateExtentCallback());
importer->SetUpdateDataCallback(exporter->GetUpdateDataCallback());
importer->SetDataExtentCallback(exporter->GetDataExtentCallback());
importer->SetBufferPointerCallback(exporter->GetBufferPointerCallback());
importer->SetCallbackUserData(exporter->GetCallbackUserData());
}
/** Connection from VTK to ITK */
template <typename VTK_Exporter, typename ITK_Importer>
void ConnectPipelines(VTK_Exporter* exporter, ITK_Importer importer)
{
importer->SetUpdateInformationCallback(exporter->GetUpdateInformationCallback());
importer->SetPipelineModifiedCallback(exporter->GetPipelineModifiedCallback());
importer->SetWholeExtentCallback(exporter->GetWholeExtentCallback());
importer->SetSpacingCallback(exporter->GetSpacingCallback());
importer->SetOriginCallback(exporter->GetOriginCallback());
importer->SetScalarTypeCallback(exporter->GetScalarTypeCallback());
importer->SetNumberOfComponentsCallback(exporter->GetNumberOfComponentsCallback());
importer->SetPropagateUpdateExtentCallback(exporter->GetPropagateUpdateExtentCallback());
importer->SetUpdateDataCallback(exporter->GetUpdateDataCallback());
importer->SetDataExtentCallback(exporter->GetDataExtentCallback());
importer->SetBufferPointerCallback(exporter->GetBufferPointerCallback());
importer->SetCallbackUserData(exporter->GetCallbackUserData());
}
void UnmaskedStatisticsProgressUpdate();
void MaskedStatisticsProgressUpdate();
mitk::Image::ConstPointer m_Image;
mitk::Image::ConstPointer m_ImageMask;
mitk::PlanarFigure::ConstPointer m_PlanarFigure;
HistogramType::ConstPointer m_ImageHistogram;
HistogramType::ConstPointer m_MaskedImageHistogram;
HistogramType::ConstPointer m_PlanarFigureHistogram;
HistogramType::Pointer m_EmptyHistogram;
StatisticsType m_ImageStatistics;
StatisticsType m_MaskedImageStatistics;
StatisticsType m_PlanarFigureStatistics;
Statistics m_EmptyStatistics;
unsigned int m_MaskingMode;
bool m_MaskingModeChanged;
mitk::Image::Pointer m_InternalImage;
MaskImage3DType::Pointer m_InternalImageMask3D;
MaskImage2DType::Pointer m_InternalImageMask2D;
itk::ImageRegion<3> m_InternalMask3D;
std::vector<mitk::Image::ConstPointer> m_AdditionalResamplingImages;
std::vector<mitk::Image::Pointer> m_InternalAdditionalResamplingImages;
TimeStampType m_ImageStatisticsTimeStamp;
TimeStampType m_MaskedImageStatisticsTimeStamp;
TimeStampType m_PlanarFigureStatisticsTimeStamp;
BoolType m_ImageStatisticsCalculationTriggerBool;
BoolType m_MaskedImageStatisticsCalculationTriggerBool;
BoolType m_PlanarFigureStatisticsCalculationTriggerBool;
unsigned int m_NumberOfBins;
float m_UpsamplingFactor;
float m_GaussianSigma;
itk::ImageRegion<3> m_CropRegion;
bool m_ForceUpdate;
unsigned int m_PlanarFigureThickness;
};
}
#endif // #define _MITK_PartialVolumeAnalysisHistogramCalculator_H
diff --git a/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkOdfVtkMapper2D.txx b/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkOdfVtkMapper2D.txx
index d7487e496b..c6bc7b0d53 100644
--- a/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkOdfVtkMapper2D.txx
+++ b/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkOdfVtkMapper2D.txx
@@ -1,884 +1,881 @@
/*===================================================================
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 __mitkOdfVtkMapper2D_txx__
#define __mitkOdfVtkMapper2D_txx__
#include "mitkOdfVtkMapper2D.h"
#include "mitkDataNode.h"
#include "mitkBaseRenderer.h"
#include "mitkMatrixConvert.h"
#include "mitkGeometry3D.h"
#include "mitkTimeGeometry.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 "itkOrientationDistributionFunction.h"
#include "itkFixedArray.h"
#include <mitkGL.h>
#include "vtkOpenGLRenderer.h"
#define _USE_MATH_DEFINES
#include <math.h>
template<class T, int N>
vtkSmartPointer<vtkTransform> mitk::OdfVtkMapper2D<T,N>::m_OdfTransform = vtkSmartPointer<vtkTransform>::New();
template<class T, int N>
vtkSmartPointer<vtkOdfSource> mitk::OdfVtkMapper2D<T,N>::m_OdfSource = vtkSmartPointer<vtkOdfSource>::New();
template<class T, int N>
float mitk::OdfVtkMapper2D<T,N>::m_Scaling;
template<class T, int N>
int mitk::OdfVtkMapper2D<T,N>::m_Normalization;
template<class T, int N>
int mitk::OdfVtkMapper2D<T,N>::m_ScaleBy;
template<class T, int N>
float mitk::OdfVtkMapper2D<T,N>::m_IndexParam1;
template<class T, int N>
float mitk::OdfVtkMapper2D<T,N>::m_IndexParam2;
#define ODF_MAPPER_PI M_PI
template<class T, int N>
mitk::OdfVtkMapper2D<T,N>::LocalStorage::LocalStorage()
{
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]->AddInputData(vtkPolyData::New());
m_OdfsPlanes[1]->AddInputData(vtkPolyData::New());
m_OdfsPlanes[2]->AddInputData(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();
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]);
}
template<class T, int N>
mitk::OdfVtkMapper2D<T,N>
::OdfVtkMapper2D()
{
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_ShowMaxNumber = 500;
}
template<class T, int N>
mitk::OdfVtkMapper2D<T,N>
::~OdfVtkMapper2D()
{
}
template<class T, int N>
mitk::Image* mitk::OdfVtkMapper2D<T,N>
::GetInput()
{
return static_cast<mitk::Image * > ( m_DataNode->GetData() );
}
template<class T, int N>
vtkProp* mitk::OdfVtkMapper2D<T,N>
::GetVtkProp(mitk::BaseRenderer* renderer)
{
LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);
return localStorage->m_PropAssemblies[GetIndex(renderer)];
}
template<class T, int N>
int mitk::OdfVtkMapper2D<T,N>
::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<class T, int N>
void mitk::OdfVtkMapper2D<T,N>
::GlyphMethod(void *arg)
{
vtkMaskedProgrammableGlyphFilter* pfilter=(vtkMaskedProgrammableGlyphFilter*)arg;
double point[3];
double debugpoint[3];
pfilter->GetPoint(point);
pfilter->GetPoint(debugpoint);
itk::Point<double,3> 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<float,N> 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<float> tensor(tensorelems);
odf.InitFromTensor(tensor);
}
else
{
for(int i=0; i<N; i++)
odf[i] = (double)odfvals->GetComponent(id,i);
}
switch(m_ScaleBy)
{
case ODFSB_NONE:
m_OdfSource->SetScale(m_Scaling);
break;
case ODFSB_GFA:
m_OdfSource->SetScale(m_Scaling*odf.GetGeneralizedGFA(m_IndexParam1, m_IndexParam2));
break;
case ODFSB_PC:
m_OdfSource->SetScale(m_Scaling*odf.GetPrincipleCurvature(m_IndexParam1, m_IndexParam2, 0));
break;
}
m_OdfSource->SetNormalization(m_Normalization);
m_OdfSource->SetOdf(odf);
m_OdfSource->Modified();
}
template<class T, int N>
typename mitk::OdfVtkMapper2D<T,N>::OdfDisplayGeometry mitk::OdfVtkMapper2D<T,N>
::MeasureDisplayedGeometry(mitk::BaseRenderer* renderer)
{
- Geometry2D::ConstPointer worldGeometry = renderer->GetCurrentWorldGeometry2D();
- PlaneGeometry::ConstPointer worldPlaneGeometry = dynamic_cast<const PlaneGeometry*>( worldGeometry.GetPointer() );
+ PlaneGeometry::ConstPointer worldPlaneGeometry = renderer->GetCurrentWorldPlaneGeometry();
// set up the cutter orientation according to the current geometry of
// the renderers plane
double vp[ 3 ], vnormal[ 3 ];
Point3D point = worldPlaneGeometry->GetOrigin();
Vector3D normal = worldPlaneGeometry->GetNormal(); normal.Normalize();
vnl2vtk( point.GetVnlVector(), vp );
vnl2vtk( normal.GetVnlVector(), 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];
mitk::Point3D M3D;
dispGeometry->Map(point1, M3D);
point1[0] = L[0]; point1[1] = L[1];
mitk::Point3D L3D;
dispGeometry->Map(point1, L3D);
point1[0] = O[0]; point1[1] = O[1];
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;
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<class T, int N>
void mitk::OdfVtkMapper2D<T,N>
::Slice(mitk::BaseRenderer* renderer, OdfDisplayGeometry dispGeo)
{
LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);
vtkLinearTransform * vtktransform =
this->GetDataNode()->GetVtkTransform(this->GetTimestep());
int index = GetIndex(renderer);
vtkSmartPointer<vtkTransform> inversetransform = vtkSmartPointer<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 );
vtkSmartPointer<vtkPoints> points;
vtkSmartPointer<vtkPoints> tmppoints;
vtkSmartPointer<vtkPolyData> polydata;
vtkSmartPointer<vtkFloatArray> pointdata;
vtkSmartPointer<vtkDelaunay2D> delaunay;
vtkSmartPointer<vtkPolyData> cuttedPlane;
// 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]->SetInputData( 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; i<m_VtkImage->GetNumberOfPoints(); 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; i<tuples; i++)
pointdata->SetTuple(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; j<m_VtkImage->GetNumberOfPoints(); 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->SetInputData( 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]->SetInputData( 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]->SetInputData( m_Clippers1[index]->GetOutput() );
m_Clippers2[index]->SetInsideOut(1);
m_Clippers2[index]->Update();
cuttedPlane = m_Clippers2[index]->GetOutput ();
if(cuttedPlane->GetNumberOfPoints())
{
localStorage->m_OdfsPlanes[index]->RemoveAllInputs();
vtkSmartPointer<vtkPolyDataNormals> normals = vtkSmartPointer<vtkPolyDataNormals>::New();
normals->SetInputConnection( m_OdfSource->GetOutputPort() );
normals->SplittingOff();
normals->ConsistencyOff();
normals->AutoOrientNormalsOff();
normals->ComputePointNormalsOn();
normals->ComputeCellNormalsOff();
normals->FlipNormalsOff();
normals->NonManifoldTraversalOff();
vtkSmartPointer<vtkTransformPolyDataFilter> trans = vtkSmartPointer<vtkTransformPolyDataFilter>::New();
trans->SetInputConnection( normals->GetOutputPort() );
trans->SetTransform(m_OdfTransform);
vtkSmartPointer<vtkMaskedProgrammableGlyphFilter> glyphGenerator = vtkSmartPointer<vtkMaskedProgrammableGlyphFilter>::New();
glyphGenerator->SetMaximumNumberOfPoints(std::min(m_ShowMaxNumber,(int)cuttedPlane->GetNumberOfPoints()));
glyphGenerator->SetRandomMode(0);
glyphGenerator->SetUseMaskPoints(1);
glyphGenerator->SetSourceConnection(trans->GetOutputPort() );
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;
}
localStorage->m_OdfsPlanes[index]->AddInputConnection(glyphGenerator->GetOutputPort());
localStorage->m_OdfsPlanes[index]->Update();
}
}
localStorage->m_PropAssemblies[index]->VisibilityOn();
if(localStorage->m_PropAssemblies[index]->GetParts()->IsItemPresent(localStorage->m_OdfsActors[index]))
localStorage->m_PropAssemblies[index]->RemovePart(localStorage->m_OdfsActors[index]);
localStorage->m_OdfsMappers[index]->SetInputData(localStorage->m_OdfsPlanes[index]->GetOutput());
localStorage->m_PropAssemblies[index]->AddPart(localStorage->m_OdfsActors[index]);
}
template<class T, int N>
bool mitk::OdfVtkMapper2D<T,N>
::IsVisibleOdfs(mitk::BaseRenderer* renderer)
{
mitk::Image::Pointer input = const_cast<mitk::Image*>(this->GetInput());
const TimeGeometry *inputTimeGeometry = input->GetTimeGeometry();
if(inputTimeGeometry==NULL || inputTimeGeometry->CountTimeSteps()==0 || !inputTimeGeometry->IsValidTimeStep(this->GetTimestep()))
return false;
if(this->IsPlaneRotated(renderer))
return false;
bool retval = false;
switch(GetIndex(renderer))
{
case 0:
GetDataNode()->GetVisibility(retval, renderer, "VisibleOdfs_T");
break;
case 1:
GetDataNode()->GetVisibility(retval, renderer, "VisibleOdfs_S");
break;
case 2:
GetDataNode()->GetVisibility(retval, renderer, "VisibleOdfs_C");
break;
}
return retval;
}
template<class T, int N>
void mitk::OdfVtkMapper2D<T,N>
::MitkRenderOverlay(mitk::BaseRenderer* renderer)
{
if ( this->IsVisibleOdfs(renderer)==false )
return;
if ( this->GetVtkProp(renderer)->GetVisibility() )
this->GetVtkProp(renderer)->RenderOverlay(renderer->GetVtkRenderer());
}
template<class T, int N>
void mitk::OdfVtkMapper2D<T,N>
::MitkRenderOpaqueGeometry(mitk::BaseRenderer* renderer)
{
if ( this->IsVisibleOdfs( renderer )==false )
return;
if ( this->GetVtkProp(renderer)->GetVisibility() )
{
// adapt cam pos
this->GetVtkProp(renderer)->RenderOpaqueGeometry( renderer->GetVtkRenderer() );
}
}
template<class T, int N>
void mitk::OdfVtkMapper2D<T,N>
::MitkRenderTranslucentGeometry(mitk::BaseRenderer* renderer)
{
if ( this->IsVisibleOdfs(renderer)==false )
return;
if ( this->GetVtkProp(renderer)->GetVisibility() )
this->GetVtkProp(renderer)->RenderTranslucentPolygonalGeometry(renderer->GetVtkRenderer());
}
template<class T, int N>
void mitk::OdfVtkMapper2D<T,N>
::Update(mitk::BaseRenderer* renderer)
{
bool visible = true;
GetDataNode()->GetVisibility(visible, renderer, "visible");
if ( !visible ) return;
mitk::Image::Pointer input = const_cast<mitk::Image*>( this->GetInput() );
if ( input.IsNull() ) return ;
std::string classname("TensorImage");
if(classname.compare(input->GetNameOfClass())==0)
m_VtkImage = dynamic_cast<mitk::TensorImage*>( this->GetInput() )->GetNonRgbVtkImageData();
std::string qclassname("QBallImage");
if(qclassname.compare(input->GetNameOfClass())==0)
m_VtkImage = dynamic_cast<mitk::QBallImage*>( 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");
}
GenerateDataForRenderer(renderer);
}
else
{
itkWarningMacro( << "m_VtkImage is NULL!" );
return ;
}
}
template<class T, int N>
void mitk::OdfVtkMapper2D<T,N>
::GenerateDataForRenderer( mitk::BaseRenderer *renderer )
{
LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);
OdfDisplayGeometry dispGeo = MeasureDisplayedGeometry( renderer);
if ( (localStorage->m_LastUpdateTime >= m_DataNode->GetMTime()) //was the node modified?
&& (localStorage->m_LastUpdateTime >= m_DataNode->GetPropertyList()->GetMTime()) //was a property modified?
&& (localStorage->m_LastUpdateTime >= m_DataNode->GetPropertyList(renderer)->GetMTime())
&& dispGeo.Equals(m_LastDisplayGeometry))
return;
localStorage->m_LastUpdateTime.Modified();
if(!IsVisibleOdfs(renderer))
{
localStorage->m_OdfsActors[0]->VisibilityOff();
localStorage->m_OdfsActors[1]->VisibilityOff();
localStorage->m_OdfsActors[2]->VisibilityOff();
}
else
{
localStorage->m_OdfsActors[0]->VisibilityOn();
localStorage->m_OdfsActors[1]->VisibilityOn();
localStorage->m_OdfsActors[2]->VisibilityOn();
m_OdfSource->SetAdditionalScale(GetMinImageSpacing(GetIndex(renderer)));
ApplyPropertySettings();
Slice(renderer, dispGeo);
m_LastDisplayGeometry = dispGeo;
}
}
template<class T, int N>
double mitk::OdfVtkMapper2D<T,N>::GetMinImageSpacing( int index )
{
// Spacing adapted scaling
double spacing[3];
m_VtkImage->GetSpacing(spacing);
double min = spacing[0];
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;
}
return min;
}
template<class T, int N>
void mitk::OdfVtkMapper2D<T,N>
::ApplyPropertySettings()
{
this->GetDataNode()->GetFloatProperty( "Scaling", m_Scaling );
this->GetDataNode()->GetIntProperty( "ShowMaxNumber", m_ShowMaxNumber );
OdfNormalizationMethodProperty* nmp = dynamic_cast<OdfNormalizationMethodProperty*>(this->GetDataNode()->GetProperty( "Normalization" ));
if(nmp)
m_Normalization = nmp->GetNormalization();
OdfScaleByProperty* sbp = dynamic_cast<OdfScaleByProperty*>(this->GetDataNode()->GetProperty( "ScaleBy" ));
if(sbp)
m_ScaleBy = sbp->GetScaleBy();
this->GetDataNode()->GetFloatProperty( "IndexParam1", m_IndexParam1);
this->GetDataNode()->GetFloatProperty( "IndexParam2", m_IndexParam2);
}
template <class T, int N>
bool mitk::OdfVtkMapper2D<T,N>
::IsPlaneRotated(mitk::BaseRenderer* renderer)
{
- Geometry2D::ConstPointer worldGeometry =
- renderer->GetCurrentWorldGeometry2D();
PlaneGeometry::ConstPointer worldPlaneGeometry =
- dynamic_cast<const PlaneGeometry*>( worldGeometry.GetPointer() );
+ renderer->GetCurrentWorldPlaneGeometry();
double vnormal[ 3 ];
Vector3D normal = worldPlaneGeometry->GetNormal(); normal.Normalize();
vnl2vtk( normal.GetVnlVector(), vnormal );
vtkLinearTransform * vtktransform =
this->GetDataNode()->GetVtkTransform(this->GetTimestep());
vtkSmartPointer<vtkTransform> inversetransform = vtkSmartPointer<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])>mitk::eps){
nonZeros++;
}
}
if(nonZeros>1)
return true;
return false;
}
template<class T, int N>
void mitk::OdfVtkMapper2D<T,N>
::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 ) );
}
#endif // __mitkOdfVtkMapper2D_txx__
diff --git a/Modules/DiffusionImaging/DiffusionCore/Rendering/vtkMaskedProgrammableGlyphFilter.h b/Modules/DiffusionImaging/DiffusionCore/Rendering/vtkMaskedProgrammableGlyphFilter.h
index 77f0859cf3..d2091a9ab4 100644
--- a/Modules/DiffusionImaging/DiffusionCore/Rendering/vtkMaskedProgrammableGlyphFilter.h
+++ b/Modules/DiffusionImaging/DiffusionCore/Rendering/vtkMaskedProgrammableGlyphFilter.h
@@ -1,114 +1,114 @@
/*===================================================================
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 __vtkMaskedProgrammableGlyphFilter_h
#define __vtkMaskedProgrammableGlyphFilter_h
#include <MitkDiffusionCoreExports.h>
#include "vtkProgrammableGlyphFilter.h"
-#include "mitkGeometry3D.h"
+#include "mitkBaseGeometry.h"
class vtkMaskPoints;
/**
* This class masked points of the input data set and glyphs
* only the selected poitns. Points may be selected either by
* random or by ratio.
* Additionally, this class allows to set the InputScalars,
* InputVectors and InputNormals by their field name in the
* input dataset.
*/
class MitkDiffusionCore_EXPORT vtkMaskedProgrammableGlyphFilter : public vtkProgrammableGlyphFilter
{
public:
vtkTypeMacro(vtkMaskedProgrammableGlyphFilter,vtkProgrammableGlyphFilter);
void PrintSelf(ostream& os, vtkIndent indent);
/**
* Constructor
*/
static vtkMaskedProgrammableGlyphFilter *New();
/**
* Limit the number of points to glyph
*/
vtkSetMacro(MaximumNumberOfPoints, int);
vtkGetMacro(MaximumNumberOfPoints, int);
/**
* Set the input to this filter.
*/
virtual void SetInput(vtkDataSet *input);
/**
* Set/get whether to mask points
*/
vtkSetMacro(UseMaskPoints, int);
vtkGetMacro(UseMaskPoints, int);
/**
* Set/get flag to cause randomization of which points to mask.
*/
void SetRandomMode(int mode);
int GetRandomMode();
///**
// * If you want to use an arbitrary scalars array, then set its name here.
// * By default this in NULL and the filter will use the active scalar array.
// */
//vtkGetStringMacro(InputScalarsSelection);
//void SelectInputScalars(const char *fieldName)
// {this->SetInputScalarsSelection(fieldName);}
///**
// * If you want to use an arbitrary vectors array, then set its name here.
// * By default this in NULL and the filter will use the active vector array.
// */
//vtkGetStringMacro(InputVectorsSelection);
//void SelectInputVectors(const char *fieldName)
// {this->SetInputVectorsSelection(fieldName);}
///**
// * If you want to use an arbitrary normals array, then set its name here.
// * By default this in NULL and the filter will use the active normal array.
// */
//vtkGetStringMacro(InputNormalsSelection);
//void SelectInputNormals(const char *fieldName)
// {this->SetInputNormalsSelection(fieldName);}
- void SetGeometry(mitk::Geometry3D::Pointer geo)
+ void SetGeometry(mitk::BaseGeometry::Pointer geo)
{ this->m_Geometry = geo; }
- mitk::Geometry3D::Pointer GetGeometry()
+ mitk::BaseGeometry::Pointer GetGeometry()
{ return this->m_Geometry; }
protected:
vtkMaskedProgrammableGlyphFilter();
~vtkMaskedProgrammableGlyphFilter();
virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *);
vtkMaskPoints *MaskPoints;
int MaximumNumberOfPoints;
int UseMaskPoints;
- mitk::Geometry3D::Pointer m_Geometry;
+ mitk::BaseGeometry::Pointer m_Geometry;
private:
vtkMaskedProgrammableGlyphFilter(const vtkMaskedProgrammableGlyphFilter&); // Not implemented.
void operator=(const vtkMaskedProgrammableGlyphFilter&); // Not implemented.
};
#endif
diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkConnectomicsNetworkReader.cpp b/Modules/DiffusionImaging/DiffusionIO/mitkConnectomicsNetworkReader.cpp
index 568a9415f0..ac302f1fee 100644
--- a/Modules/DiffusionImaging/DiffusionIO/mitkConnectomicsNetworkReader.cpp
+++ b/Modules/DiffusionImaging/DiffusionIO/mitkConnectomicsNetworkReader.cpp
@@ -1,275 +1,276 @@
/*===================================================================
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 "mitkConnectomicsNetworkReader.h"
#include "mitkConnectomicsNetworkDefinitions.h"
#include <tinyxml.h>
#include "itksys/SystemTools.hxx"
#include <vtkMatrix4x4.h>
+#include "mitkGeometry3D.h"
void mitk::ConnectomicsNetworkReader::GenerateData()
{
MITK_INFO << "Reading connectomics network";
if ( ( ! m_OutputCache ) )
{
Superclass::SetNumberOfRequiredOutputs(0);
this->GenerateOutputInformation();
}
if (!m_OutputCache)
{
itkWarningMacro("Tree cache is empty!");
}
Superclass::SetNumberOfRequiredOutputs(1);
Superclass::SetNthOutput(0, m_OutputCache.GetPointer());
}
void mitk::ConnectomicsNetworkReader::GenerateOutputInformation()
{
m_OutputCache = OutputType::New();
std::string ext = itksys::SystemTools::GetFilenameLastExtension(m_FileName);
ext = itksys::SystemTools::LowerCase(ext);
if ( m_FileName == "")
{
MITK_ERROR << "No file name specified.";
}
else if (ext == ".cnf")
{
try
{
TiXmlDocument doc( m_FileName );
bool loadOkay = doc.LoadFile();
if(!loadOkay)
{
mitkThrow() << "Could not open file " << m_FileName << " for reading.";
}
TiXmlHandle hDoc(&doc);
TiXmlElement* pElem;
TiXmlHandle hRoot(0);
pElem = hDoc.FirstChildElement().Element();
// save this for later
hRoot = TiXmlHandle(pElem);
pElem = hRoot.FirstChildElement(mitk::ConnectomicsNetworkDefinitions::XML_GEOMETRY).Element();
// read geometry
mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New();
// read origin
mitk::Point3D origin;
double temp = 0;
pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_ORIGIN_X, &temp);
origin[0] = temp;
pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_ORIGIN_Y, &temp);
origin[1] = temp;
pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_ORIGIN_Z, &temp);
origin[2] = temp;
geometry->SetOrigin(origin);
// read spacing
ScalarType spacing[3];
pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_SPACING_X, &temp);
spacing[0] = temp;
pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_SPACING_Y, &temp);
spacing[1] = temp;
pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_SPACING_Z, &temp);
spacing[2] = temp;
geometry->SetSpacing(spacing);
// read transform
vtkMatrix4x4* m = vtkMatrix4x4::New();
pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_XX, &temp);
m->SetElement(0,0,temp);
pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_XY, &temp);
m->SetElement(1,0,temp);
pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_XZ, &temp);
m->SetElement(2,0,temp);
pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_YX, &temp);
m->SetElement(0,1,temp);
pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_YY, &temp);
m->SetElement(1,1,temp);
pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_YZ, &temp);
m->SetElement(2,1,temp);
pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_ZX, &temp);
m->SetElement(0,2,temp);
pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_ZY, &temp);
m->SetElement(1,2,temp);
pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_ZZ, &temp);
m->SetElement(2,2,temp);
m->SetElement(0,3,origin[0]);
m->SetElement(1,3,origin[1]);
m->SetElement(2,3,origin[2]);
m->SetElement(3,3,1);
geometry->SetIndexToWorldTransformByVtkMatrix(m);
geometry->SetImageGeometry(true);
m_OutputCache->SetGeometry(geometry);
// read network
std::map< int, mitk::ConnectomicsNetwork::VertexDescriptorType > idToVertexMap;
// read vertices
pElem = hRoot.FirstChildElement(mitk::ConnectomicsNetworkDefinitions::XML_VERTICES).Element();
{
// walk through the vertices
TiXmlElement* vertexElement = pElem->FirstChildElement();
for( ; vertexElement; vertexElement=vertexElement->NextSiblingElement())
{
std::vector< float > pos;
std::string label;
int vertexID(0);
vertexElement->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_X, &temp);
pos.push_back(temp);
vertexElement->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_Y, &temp);
pos.push_back(temp);
vertexElement->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_Z, &temp);
pos.push_back(temp);
vertexElement->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_ID, &vertexID);
vertexElement->QueryStringAttribute(mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_LABEL, &label);
mitk::ConnectomicsNetwork::VertexDescriptorType newVertex = m_OutputCache->AddVertex( vertexID );
m_OutputCache->SetLabel( newVertex, label );
m_OutputCache->SetCoordinates( newVertex, pos );
if ( idToVertexMap.count( vertexID ) > 0 )
{
MITK_ERROR << "Aborting network creation, duplicate vertex ID in file.";
return;
}
idToVertexMap.insert( std::pair< int, mitk::ConnectomicsNetwork::VertexDescriptorType >( vertexID, newVertex) );
}
}
// read edges
pElem = hRoot.FirstChildElement(mitk::ConnectomicsNetworkDefinitions::XML_EDGES).Element();
{
// walk through the edges
TiXmlElement* edgeElement = pElem->FirstChildElement();
for( ; edgeElement; edgeElement=edgeElement->NextSiblingElement())
{
int edgeID(0), edgeSourceID(0), edgeTargetID(0), edgeWeight(0);
edgeElement->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_EDGE_ID, &edgeID);
edgeElement->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_EDGE_SOURCE_ID, &edgeSourceID);
edgeElement->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_EDGE_TARGET_ID, &edgeTargetID);
edgeElement->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_EDGE_WEIGHT_ID, &edgeWeight);
mitk::ConnectomicsNetwork::VertexDescriptorType source = idToVertexMap.find( edgeSourceID )->second;
mitk::ConnectomicsNetwork::VertexDescriptorType target = idToVertexMap.find( edgeTargetID )->second;
m_OutputCache->AddEdge( source, target, edgeSourceID, edgeTargetID, edgeWeight);
}
}
m_OutputCache->UpdateBounds();
MITK_INFO << "Network read";
}
catch (mitk::Exception e)
{
MITK_ERROR << e.GetDescription();
}
catch(...)
{
MITK_ERROR << "Unknown error occured while trying to read file.";
}
}
}
void mitk::ConnectomicsNetworkReader::Update()
{
this->GenerateData();
}
const char* mitk::ConnectomicsNetworkReader::GetFileName() const
{
return m_FileName.c_str();
}
void mitk::ConnectomicsNetworkReader::SetFileName(const char* aFileName)
{
m_FileName = aFileName;
}
const char* mitk::ConnectomicsNetworkReader::GetFilePrefix() const
{
return m_FilePrefix.c_str();
}
void mitk::ConnectomicsNetworkReader::SetFilePrefix(const char* aFilePrefix)
{
m_FilePrefix = aFilePrefix;
}
const char* mitk::ConnectomicsNetworkReader::GetFilePattern() const
{
return m_FilePattern.c_str();
}
void mitk::ConnectomicsNetworkReader::SetFilePattern(const char* aFilePattern)
{
m_FilePattern = aFilePattern;
}
bool mitk::ConnectomicsNetworkReader::CanReadFile(
const std::string filename, const std::string /*filePrefix*/,
const std::string /*filePattern*/)
{
// First check the extension
if( filename == "" )
{
return false;
}
std::string ext = itksys::SystemTools::GetFilenameLastExtension(filename);
ext = itksys::SystemTools::LowerCase(ext);
if (ext == ".cnf")
{
return true;
}
return false;
}
mitk::BaseDataSource::DataObjectPointer mitk::ConnectomicsNetworkReader::MakeOutput(const DataObjectIdentifierType &name)
{
itkDebugMacro("MakeOutput(" << name << ")");
if( this->IsIndexedOutputName(name) )
{
return this->MakeOutput( this->MakeIndexFromOutputName(name) );
}
return static_cast<itk::DataObject*>(OutputType::New().GetPointer());
}
mitk::BaseDataSource::DataObjectPointer mitk::ConnectomicsNetworkReader::MakeOutput(DataObjectPointerArraySizeType /*idx*/)
{
return OutputType::New().GetPointer();
}
diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkConnectomicsNetworkWriter.cpp b/Modules/DiffusionImaging/DiffusionIO/mitkConnectomicsNetworkWriter.cpp
index b880c28151..b23be02b53 100644
--- a/Modules/DiffusionImaging/DiffusionIO/mitkConnectomicsNetworkWriter.cpp
+++ b/Modules/DiffusionImaging/DiffusionIO/mitkConnectomicsNetworkWriter.cpp
@@ -1,157 +1,157 @@
/*===================================================================
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 "mitkConnectomicsNetworkWriter.h"
#include "mitkConnectomicsNetworkDefinitions.h"
#include <tinyxml.h>
#include "itksys/SystemTools.hxx"
mitk::ConnectomicsNetworkWriter::ConnectomicsNetworkWriter()
: m_FileName(""), m_FilePrefix(""), m_FilePattern(""), m_Success(false)
{
this->SetNumberOfRequiredInputs( 1 );
}
mitk::ConnectomicsNetworkWriter::~ConnectomicsNetworkWriter()
{}
void mitk::ConnectomicsNetworkWriter::GenerateData()
{
MITK_INFO << "Writing connectomics network";
m_Success = false;
InputType* input = this->GetInput();
if (input == NULL)
{
itkWarningMacro(<<"Sorry, input to ConnectomicsNetworkWriter is NULL!");
return;
}
if ( m_FileName == "" )
{
itkWarningMacro( << "Sorry, filename has not been set!" );
return ;
}
std::string ext = itksys::SystemTools::GetFilenameLastExtension(m_FileName);
ext = itksys::SystemTools::LowerCase(ext);
if (ext == ".cnf")
{
// Get geometry of the network
- mitk::Geometry3D* geometry = input->GetGeometry();
+ mitk::BaseGeometry* geometry = input->GetGeometry();
// Create XML document
TiXmlDocument documentXML;
{ // begin document
TiXmlDeclaration* declXML = new TiXmlDeclaration( "1.0", "", "" ); // TODO what to write here? encoding? etc....
documentXML.LinkEndChild( declXML );
TiXmlElement* mainXML = new TiXmlElement(mitk::ConnectomicsNetworkDefinitions::XML_CONNECTOMICS_FILE);
mainXML->SetAttribute(mitk::ConnectomicsNetworkDefinitions::XML_FILE_VERSION, mitk::ConnectomicsNetworkDefinitions::VERSION_STRING);
documentXML.LinkEndChild(mainXML);
TiXmlElement* geometryXML = new TiXmlElement(mitk::ConnectomicsNetworkDefinitions::XML_GEOMETRY);
{ // begin geometry
geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_XX, geometry->GetMatrixColumn(0)[0]);
geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_XY, geometry->GetMatrixColumn(0)[1]);
geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_XZ, geometry->GetMatrixColumn(0)[2]);
geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_YX, geometry->GetMatrixColumn(1)[0]);
geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_YY, geometry->GetMatrixColumn(1)[1]);
geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_YZ, geometry->GetMatrixColumn(1)[2]);
geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_ZX, geometry->GetMatrixColumn(2)[0]);
geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_ZY, geometry->GetMatrixColumn(2)[1]);
geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_ZZ, geometry->GetMatrixColumn(2)[2]);
geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_ORIGIN_X, geometry->GetOrigin()[0]);
geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_ORIGIN_Y, geometry->GetOrigin()[1]);
geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_ORIGIN_Z, geometry->GetOrigin()[2]);
geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_SPACING_X, geometry->GetSpacing()[0]);
geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_SPACING_Y, geometry->GetSpacing()[1]);
geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_SPACING_Z, geometry->GetSpacing()[2]);
} // end geometry
mainXML->LinkEndChild(geometryXML);
TiXmlElement* verticesXML = new TiXmlElement(mitk::ConnectomicsNetworkDefinitions::XML_VERTICES);
{ // begin vertices section
VertexVectorType vertexVector = this->GetInput()->GetVectorOfAllNodes();
for( unsigned int index = 0; index < vertexVector.size(); index++ )
{
// not localized as of yet TODO
TiXmlElement* vertexXML = new TiXmlElement(mitk::ConnectomicsNetworkDefinitions::XML_VERTEX );
vertexXML->SetAttribute( mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_ID , vertexVector[ index ].id );
vertexXML->SetAttribute( mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_LABEL , vertexVector[ index ].label );
vertexXML->SetDoubleAttribute( mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_X , vertexVector[ index ].coordinates[0] );
vertexXML->SetDoubleAttribute( mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_Y , vertexVector[ index ].coordinates[1] );
vertexXML->SetDoubleAttribute( mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_Z , vertexVector[ index ].coordinates[2] );
verticesXML->LinkEndChild(vertexXML);
}
} // end vertices section
mainXML->LinkEndChild(verticesXML);
TiXmlElement* edgesXML = new TiXmlElement(mitk::ConnectomicsNetworkDefinitions::XML_EDGES);
{ // begin edges section
EdgeVectorType edgeVector = this->GetInput()->GetVectorOfAllEdges();
for(unsigned int index = 0; index < edgeVector.size(); index++ )
{
TiXmlElement* edgeXML = new TiXmlElement(mitk::ConnectomicsNetworkDefinitions::XML_EDGE );
edgeXML->SetAttribute( mitk::ConnectomicsNetworkDefinitions::XML_EDGE_ID , index );
edgeXML->SetAttribute( mitk::ConnectomicsNetworkDefinitions::XML_EDGE_SOURCE_ID , edgeVector[ index ].second.sourceId );
edgeXML->SetAttribute( mitk::ConnectomicsNetworkDefinitions::XML_EDGE_TARGET_ID , edgeVector[ index ].second.targetId );
edgeXML->SetAttribute( mitk::ConnectomicsNetworkDefinitions::XML_EDGE_WEIGHT_ID , edgeVector[ index ].second.weight );
edgesXML->LinkEndChild(edgeXML);
}
} // end edges section
mainXML->LinkEndChild(edgesXML);
} // end document
documentXML.SaveFile( m_FileName );
m_Success = true;
MITK_INFO << "Connectomics network written";
}
}
void mitk::ConnectomicsNetworkWriter::SetInputConnectomicsNetwork( InputType* conNetwork )
{
this->ProcessObject::SetNthInput( 0, conNetwork );
}
mitk::ConnectomicsNetwork* mitk::ConnectomicsNetworkWriter::GetInput()
{
if ( this->GetNumberOfInputs() < 1 )
{
return NULL;
}
else
{
return dynamic_cast<InputType*> ( this->ProcessObject::GetInput( 0 ) );
}
}
std::vector<std::string> mitk::ConnectomicsNetworkWriter::GetPossibleFileExtensions()
{
std::vector<std::string> possibleFileExtensions;
possibleFileExtensions.push_back(".cnf");
return possibleFileExtensions;
}
diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkFibersFromPlanarFiguresFilter.cpp b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkFibersFromPlanarFiguresFilter.cpp
index 14703174e6..924e1a7e17 100644
--- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkFibersFromPlanarFiguresFilter.cpp
+++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkFibersFromPlanarFiguresFilter.cpp
@@ -1,251 +1,249 @@
/*===================================================================
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 "itkFibersFromPlanarFiguresFilter.h"
#define _USE_MATH_DEFINES
#include <math.h>
// MITK
#include <itkOrientationDistributionFunction.h>
#include <itkDiffusionQballGeneralizedFaImageFilter.h>
#include <mitkStandardFileLocations.h>
#include <mitkFiberBuilder.h>
#include <mitkMetropolisHastingsSampler.h>
#include <itkTensorImageToQBallImageFilter.h>
#include <mitkGibbsEnergyComputer.h>
#include <mitkRotationOperation.h>
#include <mitkInteractionConst.h>
// ITK
#include <itkImageDuplicator.h>
#include <itkResampleImageFilter.h>
#include <itkTimeProbe.h>
#include <itkMersenneTwisterRandomVariateGenerator.h>
// MISC
#include <math.h>
namespace itk{
FibersFromPlanarFiguresFilter::FibersFromPlanarFiguresFilter()
: m_FiberDistribution(DISTRIBUTE_UNIFORM)
, m_Density(1000)
, m_FiberSampling(1)
, m_Tension(0)
, m_Continuity(0)
, m_Bias(0)
, m_Variance(0.1)
{
}
FibersFromPlanarFiguresFilter::~FibersFromPlanarFiguresFilter()
{
}
void FibersFromPlanarFiguresFilter::GeneratePoints()
{
Statistics::MersenneTwisterRandomVariateGenerator::Pointer randGen = Statistics::MersenneTwisterRandomVariateGenerator::New();
randGen->SetSeed((unsigned int)0);
m_2DPoints.clear();
int count = 0;
while (count < m_Density)
{
mitk::Vector2D p;
switch (m_FiberDistribution) {
case DISTRIBUTE_GAUSSIAN:
p[0] = randGen->GetNormalVariate(0, m_Variance);
p[1] = randGen->GetNormalVariate(0, m_Variance);
break;
default:
p[0] = randGen->GetUniformVariate(-1, 1);
p[1] = randGen->GetUniformVariate(-1, 1);
}
if (sqrt(p[0]*p[0]+p[1]*p[1]) <= 1)
{
m_2DPoints.push_back(p);
count++;
}
}
}
// perform global tracking
void FibersFromPlanarFiguresFilter::GenerateData()
{
// check if enough fiducials are available
for (unsigned int i=0; i<m_Fiducials.size(); i++)
if (m_Fiducials.at(i).size()<2)
itkExceptionMacro("At least 2 fiducials needed per fiber bundle!");
for (unsigned int i=0; i<m_Fiducials.size(); i++)
{
vtkSmartPointer<vtkCellArray> m_VtkCellArray = vtkSmartPointer<vtkCellArray>::New();
vtkSmartPointer<vtkPoints> m_VtkPoints = vtkSmartPointer<vtkPoints>::New();
vector< mitk::PlanarEllipse::Pointer > bundle = m_Fiducials.at(i);
vector< unsigned int > fliplist;
if (i<m_FlipList.size())
fliplist = m_FlipList.at(i);
else
fliplist.resize(bundle.size(), 0);
if (fliplist.size()<bundle.size())
fliplist.resize(bundle.size(), 0);
GeneratePoints();
for (int j=0; j<m_Density; j++)
{
vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
mitk::PlanarEllipse::Pointer figure = bundle.at(0);
mitk::Point2D p0 = figure->GetControlPoint(0);
mitk::Point2D p1 = figure->GetControlPoint(1);
mitk::Point2D p2 = figure->GetControlPoint(2);
mitk::Point2D p3 = figure->GetControlPoint(3);
double r1 = p0.EuclideanDistanceTo(p1);
double r2 = p0.EuclideanDistanceTo(p2);
mitk::Vector2D eDir = p1-p0; eDir.Normalize();
mitk::Vector2D tDir = p3-p0; tDir.Normalize();
// apply twist
vnl_matrix_fixed<double, 2, 2> tRot;
tRot[0][0] = tDir[0];
tRot[1][1] = tRot[0][0];
tRot[1][0] = sin(acos(tRot[0][0]));
tRot[0][1] = -tRot[1][0];
if (tDir[1]<0)
tRot.inplace_transpose();
m_2DPoints[j].SetVnlVector(tRot*m_2DPoints[j].GetVnlVector());
// apply new ellipse shape
vnl_vector_fixed< double, 2 > newP;
newP[0] = m_2DPoints.at(j)[0];
newP[1] = m_2DPoints.at(j)[1];
double alpha = acos(eDir[0]);
if (eDir[1]>0)
alpha = 2*M_PI-alpha;
vnl_matrix_fixed<double, 2, 2> eRot;
eRot[0][0] = cos(alpha);
eRot[1][1] = eRot[0][0];
eRot[1][0] = sin(alpha);
eRot[0][1] = -eRot[1][0];
newP = eRot*newP;
newP[0] *= r1;
newP[1] *= r2;
newP = eRot.transpose()*newP;
p0[0] += newP[0];
p0[1] += newP[1];
- const mitk::Geometry2D* pfgeometry = figure->GetGeometry2D();
- const mitk::PlaneGeometry* planeGeo = dynamic_cast<const mitk::PlaneGeometry*>(pfgeometry);
+ const mitk::PlaneGeometry* planeGeo = figure->GetPlaneGeometry();
mitk::Point3D w, wc;
planeGeo->Map(p0, w);
wc = figure->GetWorldControlPoint(0);
vtkIdType id = m_VtkPoints->InsertNextPoint(w.GetDataPointer());
container->GetPointIds()->InsertNextId(id);
vnl_vector_fixed< double, 3 > n = planeGeo->GetNormalVnl();
for (unsigned int k=1; k<bundle.size(); k++)
{
figure = bundle.at(k);
p0 = figure->GetControlPoint(0);
p1 = figure->GetControlPoint(1);
p2 = figure->GetControlPoint(2);
p3 = figure->GetControlPoint(3);
r1 = p0.EuclideanDistanceTo(p1);
r2 = p0.EuclideanDistanceTo(p2);
eDir = p1-p0; eDir.Normalize();
mitk::Vector2D tDir2 = p3-p0; tDir2.Normalize();
mitk::Vector2D temp; temp.SetVnlVector(tRot.transpose() * tDir2.GetVnlVector());
// apply twist
tRot[0][0] = tDir[0]*tDir2[0] + tDir[1]*tDir2[1];
tRot[1][1] = tRot[0][0];
tRot[1][0] = sin(acos(tRot[0][0]));
tRot[0][1] = -tRot[1][0];
if (temp[1]<0)
tRot.inplace_transpose();
m_2DPoints[j].SetVnlVector(tRot*m_2DPoints[j].GetVnlVector());
tDir = tDir2;
// apply new ellipse shape
newP[0] = m_2DPoints.at(j)[0];
newP[1] = m_2DPoints.at(j)[1];
// calculate normal
- mitk::Geometry2D* pfgeometry = const_cast<mitk::Geometry2D*>(figure->GetGeometry2D());
- mitk::PlaneGeometry* planeGeo = dynamic_cast<mitk::PlaneGeometry*>(pfgeometry);
+ mitk::PlaneGeometry* planeGeo = const_cast<mitk::PlaneGeometry*>(figure->GetPlaneGeometry());
mitk::Vector3D perp = wc-planeGeo->ProjectPointOntoPlane(wc); perp.Normalize();
vnl_vector_fixed< double, 3 > n2 = planeGeo->GetNormalVnl();
wc = figure->GetWorldControlPoint(0);
// is flip needed?
if (dot_product(perp.GetVnlVector(),n2)>0 && dot_product(n,n2)<=0.00001)
newP[0] *= -1;
if (fliplist.at(k)>0)
newP[0] *= -1;
n = n2;
alpha = acos(eDir[0]);
if (eDir[1]>0)
alpha = 2*M_PI-alpha;
eRot[0][0] = cos(alpha);
eRot[1][1] = eRot[0][0];
eRot[1][0] = sin(alpha);
eRot[0][1] = -eRot[1][0];
newP = eRot*newP;
newP[0] *= r1;
newP[1] *= r2;
newP = eRot.transpose()*newP;
p0[0] += newP[0];
p0[1] += newP[1];
mitk::Point3D w;
planeGeo->Map(p0, w);
vtkIdType id = m_VtkPoints->InsertNextPoint(w.GetDataPointer());
container->GetPointIds()->InsertNextId(id);
}
m_VtkCellArray->InsertNextCell(container);
}
vtkSmartPointer<vtkPolyData> fiberPolyData = vtkSmartPointer<vtkPolyData>::New();
fiberPolyData->SetPoints(m_VtkPoints);
fiberPolyData->SetLines(m_VtkCellArray);
mitk::FiberBundleX::Pointer mitkFiberBundle = mitk::FiberBundleX::New(fiberPolyData);
mitkFiberBundle->DoFiberSmoothing(m_FiberSampling, m_Tension, m_Continuity, m_Bias);
m_FiberBundles.push_back(mitkFiberBundle);
}
}
}
diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractDensityImageFilter.cpp b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractDensityImageFilter.cpp
index d0000ed0a1..2da65f6632 100644
--- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractDensityImageFilter.cpp
+++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractDensityImageFilter.cpp
@@ -1,227 +1,227 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
Coindex[1]right (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 "itkTractDensityImageFilter.h"
// VTK
#include <vtkPolyLine.h>
#include <vtkCellArray.h>
#include <vtkCellData.h>
// misc
#include <math.h>
#include <boost/progress.hpp>
namespace itk{
template< class OutputImageType >
TractDensityImageFilter< OutputImageType >::TractDensityImageFilter()
: m_InvertImage(false)
, m_FiberBundle(NULL)
, m_UpsamplingFactor(1)
, m_InputImage(NULL)
, m_BinaryOutput(false)
, m_UseImageGeometry(false)
, m_OutputAbsoluteValues(false)
{
}
template< class OutputImageType >
TractDensityImageFilter< OutputImageType >::~TractDensityImageFilter()
{
}
template< class OutputImageType >
itk::Point<float, 3> TractDensityImageFilter< OutputImageType >::GetItkPoint(double point[3])
{
itk::Point<float, 3> itkPoint;
itkPoint[0] = point[0];
itkPoint[1] = point[1];
itkPoint[2] = point[2];
return itkPoint;
}
template< class OutputImageType >
void TractDensityImageFilter< OutputImageType >::GenerateData()
{
// generate upsampled image
- mitk::Geometry3D::Pointer geometry = m_FiberBundle->GetGeometry();
+ mitk::BaseGeometry::Pointer geometry = m_FiberBundle->GetGeometry();
typename OutputImageType::Pointer outImage = this->GetOutput();
// calculate new image parameters
itk::Vector<double,3> newSpacing;
mitk::Point3D newOrigin;
itk::Matrix<double, 3, 3> newDirection;
ImageRegion<3> upsampledRegion;
if (m_UseImageGeometry && !m_InputImage.IsNull())
{
MITK_INFO << "TractDensityImageFilter: using image geometry";
newSpacing = m_InputImage->GetSpacing()/m_UpsamplingFactor;
upsampledRegion = m_InputImage->GetLargestPossibleRegion();
newOrigin = m_InputImage->GetOrigin();
typename OutputImageType::RegionType::SizeType size = upsampledRegion.GetSize();
size[0] *= m_UpsamplingFactor;
size[1] *= m_UpsamplingFactor;
size[2] *= m_UpsamplingFactor;
upsampledRegion.SetSize(size);
newDirection = m_InputImage->GetDirection();
}
else
{
MITK_INFO << "TractDensityImageFilter: using fiber bundle geometry";
newSpacing = geometry->GetSpacing()/m_UpsamplingFactor;
newOrigin = geometry->GetOrigin();
mitk::Geometry3D::BoundsArrayType bounds = geometry->GetBounds();
newOrigin[0] += bounds.GetElement(0);
newOrigin[1] += bounds.GetElement(2);
newOrigin[2] += bounds.GetElement(4);
for (int i=0; i<3; i++)
for (int j=0; j<3; j++)
newDirection[j][i] = geometry->GetMatrixColumn(i)[j];
upsampledRegion.SetSize(0, geometry->GetExtent(0)*m_UpsamplingFactor);
upsampledRegion.SetSize(1, geometry->GetExtent(1)*m_UpsamplingFactor);
upsampledRegion.SetSize(2, geometry->GetExtent(2)*m_UpsamplingFactor);
}
typename OutputImageType::RegionType::SizeType upsampledSize = upsampledRegion.GetSize();
// apply new image parameters
outImage->SetSpacing( newSpacing );
outImage->SetOrigin( newOrigin );
outImage->SetDirection( newDirection );
outImage->SetRegions( upsampledRegion );
outImage->Allocate();
outImage->FillBuffer(0.0);
int w = upsampledSize[0];
int h = upsampledSize[1];
int d = upsampledSize[2];
// set/initialize output
OutPixelType* outImageBufferPointer = (OutPixelType*)outImage->GetBufferPointer();
// resample fiber bundle
float minSpacing = 1;
if(newSpacing[0]<newSpacing[1] && newSpacing[0]<newSpacing[2])
minSpacing = newSpacing[0];
else if (newSpacing[1] < newSpacing[2])
minSpacing = newSpacing[1];
else
minSpacing = newSpacing[2];
MITK_INFO << "TractDensityImageFilter: resampling fibers to ensure sufficient voxel coverage";
m_FiberBundle = m_FiberBundle->GetDeepCopy();
m_FiberBundle->ResampleFibers(minSpacing);
MITK_INFO << "TractDensityImageFilter: starting image generation";
vtkSmartPointer<vtkPolyData> fiberPolyData = m_FiberBundle->GetFiberPolyData();
vtkSmartPointer<vtkCellArray> vLines = fiberPolyData->GetLines();
vLines->InitTraversal();
int numFibers = m_FiberBundle->GetNumFibers();
boost::progress_display disp(numFibers);
for( int i=0; i<numFibers; i++ )
{
++disp;
vtkIdType numPoints(0);
vtkIdType* points(NULL);
vLines->GetNextCell ( numPoints, points );
// fill output image
for( int j=0; j<numPoints; j++)
{
itk::Point<float, 3> vertex = GetItkPoint(fiberPolyData->GetPoint(points[j]));
itk::Index<3> index;
itk::ContinuousIndex<float, 3> contIndex;
outImage->TransformPhysicalPointToIndex(vertex, index);
outImage->TransformPhysicalPointToContinuousIndex(vertex, contIndex);
float frac_x = contIndex[0] - index[0];
float frac_y = contIndex[1] - index[1];
float frac_z = contIndex[2] - index[2];
if (frac_x<0)
{
index[0] -= 1;
frac_x += 1;
}
if (frac_y<0)
{
index[1] -= 1;
frac_y += 1;
}
if (frac_z<0)
{
index[2] -= 1;
frac_z += 1;
}
frac_x = 1-frac_x;
frac_y = 1-frac_y;
frac_z = 1-frac_z;
// int coordinates inside image?
if (index[0] < 0 || index[0] >= w-1)
continue;
if (index[1] < 0 || index[1] >= h-1)
continue;
if (index[2] < 0 || index[2] >= d-1)
continue;
if (m_BinaryOutput)
{
outImageBufferPointer[( index[0] + w*(index[1] + h*index[2] ))] = 1;
outImageBufferPointer[( index[0] + w*(index[1]+1+ h*index[2] ))] = 1;
outImageBufferPointer[( index[0] + w*(index[1] + h*index[2]+h))] = 1;
outImageBufferPointer[( index[0] + w*(index[1]+1+ h*index[2]+h))] = 1;
outImageBufferPointer[( index[0]+1 + w*(index[1] + h*index[2] ))] = 1;
outImageBufferPointer[( index[0]+1 + w*(index[1] + h*index[2]+h))] = 1;
outImageBufferPointer[( index[0]+1 + w*(index[1]+1+ h*index[2] ))] = 1;
outImageBufferPointer[( index[0]+1 + w*(index[1]+1+ h*index[2]+h))] = 1;
}
else
{
outImageBufferPointer[( index[0] + w*(index[1] + h*index[2] ))] += ( frac_x)*( frac_y)*( frac_z);
outImageBufferPointer[( index[0] + w*(index[1]+1+ h*index[2] ))] += ( frac_x)*(1-frac_y)*( frac_z);
outImageBufferPointer[( index[0] + w*(index[1] + h*index[2]+h))] += ( frac_x)*( frac_y)*(1-frac_z);
outImageBufferPointer[( index[0] + w*(index[1]+1+ h*index[2]+h))] += ( frac_x)*(1-frac_y)*(1-frac_z);
outImageBufferPointer[( index[0]+1 + w*(index[1] + h*index[2] ))] += (1-frac_x)*( frac_y)*( frac_z);
outImageBufferPointer[( index[0]+1 + w*(index[1] + h*index[2]+h))] += (1-frac_x)*( frac_y)*(1-frac_z);
outImageBufferPointer[( index[0]+1 + w*(index[1]+1+ h*index[2] ))] += (1-frac_x)*(1-frac_y)*( frac_z);
outImageBufferPointer[( index[0]+1 + w*(index[1]+1+ h*index[2]+h))] += (1-frac_x)*(1-frac_y)*(1-frac_z);
}
}
}
if (!m_OutputAbsoluteValues && !m_BinaryOutput)
{
MITK_INFO << "TractDensityImageFilter: max-normalizing output image";
OutPixelType max = 0;
for (int i=0; i<w*h*d; i++)
if (max < outImageBufferPointer[i])
max = outImageBufferPointer[i];
if (max>0)
for (int i=0; i<w*h*d; i++)
outImageBufferPointer[i] /= max;
}
if (m_InvertImage)
{
MITK_INFO << "TractDensityImageFilter: inverting image";
for (int i=0; i<w*h*d; i++)
outImageBufferPointer[i] = 1-outImageBufferPointer[i];
}
MITK_INFO << "TractDensityImageFilter: finished processing";
}
}
diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToFiberEndingsImageFilter.cpp b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToFiberEndingsImageFilter.cpp
index b2dac9cf49..9cbe7b9db2 100644
--- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToFiberEndingsImageFilter.cpp
+++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToFiberEndingsImageFilter.cpp
@@ -1,160 +1,160 @@
/*===================================================================
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 "itkTractsToFiberEndingsImageFilter.h"
// VTK
#include <vtkPolyLine.h>
#include <vtkCellArray.h>
#include <vtkCellData.h>
#include <boost/progress.hpp>
namespace itk{
template< class OutputImageType >
TractsToFiberEndingsImageFilter< OutputImageType >::TractsToFiberEndingsImageFilter()
: m_InvertImage(false)
, m_UpsamplingFactor(1)
, m_InputImage(NULL)
, m_UseImageGeometry(false)
, m_BinaryOutput(false)
{
}
template< class OutputImageType >
TractsToFiberEndingsImageFilter< OutputImageType >::~TractsToFiberEndingsImageFilter()
{
}
template< class OutputImageType >
itk::Point<float, 3> TractsToFiberEndingsImageFilter< OutputImageType >::GetItkPoint(double point[3])
{
itk::Point<float, 3> itkPoint;
itkPoint[0] = point[0];
itkPoint[1] = point[1];
itkPoint[2] = point[2];
return itkPoint;
}
template< class OutputImageType >
void TractsToFiberEndingsImageFilter< OutputImageType >::GenerateData()
{
// generate upsampled image
- mitk::Geometry3D::Pointer geometry = m_FiberBundle->GetGeometry();
+ mitk::BaseGeometry::Pointer geometry = m_FiberBundle->GetGeometry();
typename OutputImageType::Pointer outImage = this->GetOutput();
// calculate new image parameters
itk::Vector<double, 3> newSpacing;
mitk::Point3D newOrigin;
itk::Matrix<double, 3, 3> newDirection;
ImageRegion<3> upsampledRegion;
if (m_UseImageGeometry && !m_InputImage.IsNull())
{
newSpacing = m_InputImage->GetSpacing()/m_UpsamplingFactor;
upsampledRegion = m_InputImage->GetLargestPossibleRegion();
newOrigin = m_InputImage->GetOrigin();
typename OutputImageType::RegionType::SizeType size = upsampledRegion.GetSize();
size[0] *= m_UpsamplingFactor;
size[1] *= m_UpsamplingFactor;
size[2] *= m_UpsamplingFactor;
upsampledRegion.SetSize(size);
newDirection = m_InputImage->GetDirection();
}
else
{
newSpacing = geometry->GetSpacing()/m_UpsamplingFactor;
newOrigin = geometry->GetOrigin();
mitk::Geometry3D::BoundsArrayType bounds = geometry->GetBounds();
newOrigin[0] += bounds.GetElement(0);
newOrigin[1] += bounds.GetElement(2);
newOrigin[2] += bounds.GetElement(4);
for (int i=0; i<3; i++)
for (int j=0; j<3; j++)
newDirection[j][i] = geometry->GetMatrixColumn(i)[j];
upsampledRegion.SetSize(0, geometry->GetExtent(0)*m_UpsamplingFactor);
upsampledRegion.SetSize(1, geometry->GetExtent(1)*m_UpsamplingFactor);
upsampledRegion.SetSize(2, geometry->GetExtent(2)*m_UpsamplingFactor);
}
typename OutputImageType::RegionType::SizeType upsampledSize = upsampledRegion.GetSize();
// apply new image parameters
outImage->SetSpacing( newSpacing );
outImage->SetOrigin( newOrigin );
outImage->SetDirection( newDirection );
outImage->SetRegions( upsampledRegion );
outImage->Allocate();
int w = upsampledSize[0];
int h = upsampledSize[1];
int d = upsampledSize[2];
// set/initialize output
OutPixelType* outImageBufferPointer = (OutPixelType*)outImage->GetBufferPointer();
for (int i=0; i<w*h*d; i++)
outImageBufferPointer[i] = 0;
// resample fiber bundle
float minSpacing = 1;
if(newSpacing[0]<newSpacing[1] && newSpacing[0]<newSpacing[2])
minSpacing = newSpacing[0];
else if (newSpacing[1] < newSpacing[2])
minSpacing = newSpacing[1];
else
minSpacing = newSpacing[2];
vtkSmartPointer<vtkPolyData> fiberPolyData = m_FiberBundle->GetFiberPolyData();
vtkSmartPointer<vtkCellArray> vLines = fiberPolyData->GetLines();
vLines->InitTraversal();
int numFibers = m_FiberBundle->GetNumFibers();
boost::progress_display disp(numFibers);
for( int i=0; i<numFibers; i++ )
{
++disp;
vtkIdType numPoints(0);
vtkIdType* points(NULL);
vLines->GetNextCell ( numPoints, points );
// fill output image
if (numPoints>0)
{
itk::Point<float, 3> vertex = GetItkPoint(fiberPolyData->GetPoint(points[0]));
itk::Index<3> index;
outImage->TransformPhysicalPointToIndex(vertex, index);
if (m_BinaryOutput)
outImage->SetPixel(index, 1);
else
outImage->SetPixel(index, outImage->GetPixel(index)+1);
}
if (numPoints>2)
{
itk::Point<float, 3> vertex = GetItkPoint(fiberPolyData->GetPoint(points[numPoints-1]));
itk::Index<3> index;
outImage->TransformPhysicalPointToIndex(vertex, index);
if (m_BinaryOutput)
outImage->SetPixel(index, 1);
else
outImage->SetPixel(index, outImage->GetPixel(index)+1);
}
}
if (m_InvertImage)
for (int i=0; i<w*h*d; i++)
outImageBufferPointer[i] = 1-outImageBufferPointer[i];
}
}
diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToRgbaImageFilter.cpp b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToRgbaImageFilter.cpp
index 60fad63e14..c51d12a104 100644
--- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToRgbaImageFilter.cpp
+++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToRgbaImageFilter.cpp
@@ -1,286 +1,286 @@
/*===================================================================
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 "itkTractsToRgbaImageFilter.h"
// VTK
#include <vtkPolyLine.h>
#include <vtkCellArray.h>
#include <vtkCellData.h>
// misc
#include <math.h>
#include <boost/progress.hpp>
namespace itk{
template< class OutputImageType >
TractsToRgbaImageFilter< OutputImageType >::TractsToRgbaImageFilter()
: m_UpsamplingFactor(1)
, m_InputImage(NULL)
, m_UseImageGeometry(false)
{
}
template< class OutputImageType >
TractsToRgbaImageFilter< OutputImageType >::~TractsToRgbaImageFilter()
{
}
template< class OutputImageType >
itk::Point<float, 3> TractsToRgbaImageFilter< OutputImageType >::GetItkPoint(double point[3])
{
itk::Point<float, 3> itkPoint;
itkPoint[0] = point[0];
itkPoint[1] = point[1];
itkPoint[2] = point[2];
return itkPoint;
}
template< class OutputImageType >
void TractsToRgbaImageFilter< OutputImageType >::GenerateData()
{
if(&typeid(OutPixelType) != &typeid(itk::RGBAPixel<unsigned char>))
return;
// generate upsampled image
- mitk::Geometry3D::Pointer geometry = m_FiberBundle->GetGeometry();
+ mitk::BaseGeometry::Pointer geometry = m_FiberBundle->GetGeometry();
typename OutputImageType::Pointer outImage = this->GetOutput();
// calculate new image parameters
itk::Vector<double,3> newSpacing;
mitk::Point3D newOrigin;
itk::Matrix<double, 3, 3> newDirection;
ImageRegion<3> upsampledRegion;
if (m_UseImageGeometry && !m_InputImage.IsNull())
{
newSpacing = m_InputImage->GetSpacing()/m_UpsamplingFactor;
upsampledRegion = m_InputImage->GetLargestPossibleRegion();
newOrigin = m_InputImage->GetOrigin();
typename OutputImageType::RegionType::SizeType size = upsampledRegion.GetSize();
size[0] *= m_UpsamplingFactor;
size[1] *= m_UpsamplingFactor;
size[2] *= m_UpsamplingFactor;
upsampledRegion.SetSize(size);
newDirection = m_InputImage->GetDirection();
}
else
{
newSpacing = geometry->GetSpacing()/m_UpsamplingFactor;
newOrigin = geometry->GetOrigin();
mitk::Geometry3D::BoundsArrayType bounds = geometry->GetBounds();
newOrigin[0] += bounds.GetElement(0);
newOrigin[1] += bounds.GetElement(2);
newOrigin[2] += bounds.GetElement(4);
for (int i=0; i<3; i++)
for (int j=0; j<3; j++)
newDirection[j][i] = geometry->GetMatrixColumn(i)[j];
upsampledRegion.SetSize(0, geometry->GetExtent(0)*m_UpsamplingFactor);
upsampledRegion.SetSize(1, geometry->GetExtent(1)*m_UpsamplingFactor);
upsampledRegion.SetSize(2, geometry->GetExtent(2)*m_UpsamplingFactor);
}
typename OutputImageType::RegionType::SizeType upsampledSize = upsampledRegion.GetSize();
// apply new image parameters
outImage->SetSpacing( newSpacing );
outImage->SetOrigin( newOrigin );
outImage->SetDirection( newDirection );
outImage->SetRegions( upsampledRegion );
outImage->Allocate();
int w = upsampledSize[0];
int h = upsampledSize[1];
int d = upsampledSize[2];
// set/initialize output
unsigned char* outImageBufferPointer = (unsigned char*)outImage->GetBufferPointer();
float* buffer = new float[w*h*d*4];
for (int i=0; i<w*h*d*4; i++)
buffer[i] = 0;
// resample fiber bundle
float minSpacing = 1;
if(newSpacing[0]<newSpacing[1] && newSpacing[0]<newSpacing[2])
minSpacing = newSpacing[0];
else if (newSpacing[1] < newSpacing[2])
minSpacing = newSpacing[1];
else
minSpacing = newSpacing[2];
m_FiberBundle = m_FiberBundle->GetDeepCopy();
m_FiberBundle->ResampleFibers(minSpacing);
vtkSmartPointer<vtkPolyData> fiberPolyData = m_FiberBundle->GetFiberPolyData();
vtkSmartPointer<vtkCellArray> vLines = fiberPolyData->GetLines();
vLines->InitTraversal();
int numFibers = m_FiberBundle->GetNumFibers();
boost::progress_display disp(numFibers);
for( int i=0; i<numFibers; i++ )
{
++disp;
vtkIdType numPoints(0);
vtkIdType* points(NULL);
vLines->GetNextCell ( numPoints, points );
// calc directions (which are used as weights)
std::list< itk::Point<float, 3> > rgbweights;
std::list<float> intensities;
for( int j=0; j<numPoints-1; j++)
{
itk::Point<float, 3> vertex = GetItkPoint(fiberPolyData->GetPoint(points[j]));
itk::Point<float, 3> vertexPost = GetItkPoint(fiberPolyData->GetPoint(points[j+1]));
itk::Point<float, 3> dir;
dir[0] = fabs((vertexPost[0] - vertex[0]) * outImage->GetSpacing()[0]);
dir[1] = fabs((vertexPost[1] - vertex[1]) * outImage->GetSpacing()[1]);
dir[2] = fabs((vertexPost[2] - vertex[2]) * outImage->GetSpacing()[2]);
rgbweights.push_back(dir);
float intensity = sqrt(dir[0]*dir[0]+dir[1]*dir[1]+dir[2]*dir[2]);
intensities.push_back(intensity);
// last point gets same as previous one
if(j==numPoints-2)
{
rgbweights.push_back(dir);
intensities.push_back(intensity);
}
}
// fill output image
for( int j=0; j<numPoints; j++)
{
itk::Point<float, 3> vertex = GetItkPoint(fiberPolyData->GetPoint(points[j]));
itk::Index<3> index;
itk::ContinuousIndex<float, 3> contIndex;
outImage->TransformPhysicalPointToIndex(vertex, index);
outImage->TransformPhysicalPointToContinuousIndex(vertex, contIndex);
float frac_x = contIndex[0] - index[0];
float frac_y = contIndex[1] - index[1];
float frac_z = contIndex[2] - index[2];
int px = index[0];
if (frac_x<0)
{
px -= 1;
frac_x += 1;
}
int py = index[1];
if (frac_y<0)
{
py -= 1;
frac_y += 1;
}
int pz = index[2];
if (frac_z<0)
{
pz -= 1;
frac_z += 1;
}
// int coordinates inside image?
if (px < 0 || px >= w-1)
continue;
if (py < 0 || py >= h-1)
continue;
if (pz < 0 || pz >= d-1)
continue;
float scale = 100 * pow((float)m_UpsamplingFactor,3);
itk::Point<float, 3> rgbweight = rgbweights.front();
rgbweights.pop_front();
float intweight = intensities.front();
intensities.pop_front();
// add to r-channel in output image
buffer[0+4*( px + w*(py + h*pz ))] += (1-frac_x)*(1-frac_y)*(1-frac_z) * rgbweight[0] * scale;
buffer[0+4*( px + w*(py+1+ h*pz ))] += (1-frac_x)*( frac_y)*(1-frac_z) * rgbweight[0] * scale;
buffer[0+4*( px + w*(py + h*pz+h))] += (1-frac_x)*(1-frac_y)*( frac_z) * rgbweight[0] * scale;
buffer[0+4*( px + w*(py+1+ h*pz+h))] += (1-frac_x)*( frac_y)*( frac_z) * rgbweight[0] * scale;
buffer[0+4*( px+1 + w*(py + h*pz ))] += ( frac_x)*(1-frac_y)*(1-frac_z) * rgbweight[0] * scale;
buffer[0+4*( px+1 + w*(py + h*pz+h))] += ( frac_x)*(1-frac_y)*( frac_z) * rgbweight[0] * scale;
buffer[0+4*( px+1 + w*(py+1+ h*pz ))] += ( frac_x)*( frac_y)*(1-frac_z) * rgbweight[0] * scale;
buffer[0+4*( px+1 + w*(py+1+ h*pz+h))] += ( frac_x)*( frac_y)*( frac_z) * rgbweight[0] * scale;
// add to g-channel in output image
buffer[1+4*( px + w*(py + h*pz ))] += (1-frac_x)*(1-frac_y)*(1-frac_z) * rgbweight[1] * scale;
buffer[1+4*( px + w*(py+1+ h*pz ))] += (1-frac_x)*( frac_y)*(1-frac_z) * rgbweight[1] * scale;
buffer[1+4*( px + w*(py + h*pz+h))] += (1-frac_x)*(1-frac_y)*( frac_z) * rgbweight[1] * scale;
buffer[1+4*( px + w*(py+1+ h*pz+h))] += (1-frac_x)*( frac_y)*( frac_z) * rgbweight[1] * scale;
buffer[1+4*( px+1 + w*(py + h*pz ))] += ( frac_x)*(1-frac_y)*(1-frac_z) * rgbweight[1] * scale;
buffer[1+4*( px+1 + w*(py + h*pz+h))] += ( frac_x)*(1-frac_y)*( frac_z) * rgbweight[1] * scale;
buffer[1+4*( px+1 + w*(py+1+ h*pz ))] += ( frac_x)*( frac_y)*(1-frac_z) * rgbweight[1] * scale;
buffer[1+4*( px+1 + w*(py+1+ h*pz+h))] += ( frac_x)*( frac_y)*( frac_z) * rgbweight[1] * scale;
// add to b-channel in output image
buffer[2+4*( px + w*(py + h*pz ))] += (1-frac_x)*(1-frac_y)*(1-frac_z) * rgbweight[2] * scale;
buffer[2+4*( px + w*(py+1+ h*pz ))] += (1-frac_x)*( frac_y)*(1-frac_z) * rgbweight[2] * scale;
buffer[2+4*( px + w*(py + h*pz+h))] += (1-frac_x)*(1-frac_y)*( frac_z) * rgbweight[2] * scale;
buffer[2+4*( px + w*(py+1+ h*pz+h))] += (1-frac_x)*( frac_y)*( frac_z) * rgbweight[2] * scale;
buffer[2+4*( px+1 + w*(py + h*pz ))] += ( frac_x)*(1-frac_y)*(1-frac_z) * rgbweight[2] * scale;
buffer[2+4*( px+1 + w*(py + h*pz+h))] += ( frac_x)*(1-frac_y)*( frac_z) * rgbweight[2] * scale;
buffer[2+4*( px+1 + w*(py+1+ h*pz ))] += ( frac_x)*( frac_y)*(1-frac_z) * rgbweight[2] * scale;
buffer[2+4*( px+1 + w*(py+1+ h*pz+h))] += ( frac_x)*( frac_y)*( frac_z) * rgbweight[2] * scale;
// add to a-channel in output image
buffer[3+4*( px + w*(py + h*pz ))] += (1-frac_x)*(1-frac_y)*(1-frac_z) * intweight * scale;
buffer[3+4*( px + w*(py+1+ h*pz ))] += (1-frac_x)*( frac_y)*(1-frac_z) * intweight * scale;
buffer[3+4*( px + w*(py + h*pz+h))] += (1-frac_x)*(1-frac_y)*( frac_z) * intweight * scale;
buffer[3+4*( px + w*(py+1+ h*pz+h))] += (1-frac_x)*( frac_y)*( frac_z) * intweight * scale;
buffer[3+4*( px+1 + w*(py + h*pz ))] += ( frac_x)*(1-frac_y)*(1-frac_z) * intweight * scale;
buffer[3+4*( px+1 + w*(py + h*pz+h))] += ( frac_x)*(1-frac_y)*( frac_z) * intweight * scale;
buffer[3+4*( px+1 + w*(py+1+ h*pz ))] += ( frac_x)*( frac_y)*(1-frac_z) * intweight * scale;
buffer[3+4*( px+1 + w*(py+1+ h*pz+h))] += ( frac_x)*( frac_y)*( frac_z) * intweight * scale;
}
}
float maxRgb = 0.000000001;
float maxInt = 0.000000001;
int numPix;
numPix = w*h*d*4;
// calc maxima
for(int i=0; i<numPix; i++)
{
if((i-3)%4 != 0)
{
if(buffer[i] > maxRgb)
maxRgb = buffer[i];
}
else
{
if(buffer[i] > maxInt)
maxInt = buffer[i];
}
}
// write output, normalized uchar 0..255
for(int i=0; i<numPix; i++)
{
if((i-3)%4 != 0)
outImageBufferPointer[i] = (unsigned char) (255.0 * buffer[i] / maxRgb);
else
outImageBufferPointer[i] = (unsigned char) (255.0 * buffer[i] / maxInt);
}
}
}
diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToVectorImageFilter.cpp b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToVectorImageFilter.cpp
index c0a7253736..3d17be553e 100644
--- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToVectorImageFilter.cpp
+++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToVectorImageFilter.cpp
@@ -1,832 +1,832 @@
#include "itkTractsToVectorImageFilter.h"
// VTK
#include <vtkPolyLine.h>
#include <vtkCellArray.h>
#include <vtkCellData.h>
// ITK
#include <itkTimeProbe.h>
#include <itkImageRegionIterator.h>
// misc
#define _USE_MATH_DEFINES
#include <math.h>
#include <boost/progress.hpp>
namespace itk{
static bool CompareVectorLengths(const vnl_vector_fixed< double, 3 >& v1, const vnl_vector_fixed< double, 3 >& v2)
{
return (v1.magnitude()>v2.magnitude());
}
template< class PixelType >
TractsToVectorImageFilter< PixelType >::TractsToVectorImageFilter():
m_AngularThreshold(0.7),
m_Epsilon(0.999),
m_MaskImage(NULL),
m_NormalizeVectors(false),
m_UseWorkingCopy(true),
m_UseTrilinearInterpolation(false),
m_MaxNumDirections(3),
m_Thres(0.5),
m_NumDirectionsImage(NULL)
{
this->SetNumberOfRequiredOutputs(1);
}
template< class PixelType >
TractsToVectorImageFilter< PixelType >::~TractsToVectorImageFilter()
{
}
template< class PixelType >
vnl_vector_fixed<double, 3> TractsToVectorImageFilter< PixelType >::GetVnlVector(double point[3])
{
vnl_vector_fixed<double, 3> vnlVector;
vnlVector[0] = point[0];
vnlVector[1] = point[1];
vnlVector[2] = point[2];
return vnlVector;
}
template< class PixelType >
itk::Point<float, 3> TractsToVectorImageFilter< PixelType >::GetItkPoint(double point[3])
{
itk::Point<float, 3> itkPoint;
itkPoint[0] = point[0];
itkPoint[1] = point[1];
itkPoint[2] = point[2];
return itkPoint;
}
template< class PixelType >
void TractsToVectorImageFilter< PixelType >::GenerateData()
{
- mitk::Geometry3D::Pointer geometry = m_FiberBundle->GetGeometry();
+ mitk::BaseGeometry::Pointer geometry = m_FiberBundle->GetGeometry();
// calculate new image parameters
itk::Vector<double> spacing;
itk::Point<double> origin;
itk::Matrix<double, 3, 3> direction;
ImageRegion<3> imageRegion;
if (!m_MaskImage.IsNull())
{
spacing = m_MaskImage->GetSpacing();
imageRegion = m_MaskImage->GetLargestPossibleRegion();
origin = m_MaskImage->GetOrigin();
direction = m_MaskImage->GetDirection();
}
else
{
spacing = geometry->GetSpacing();
origin = geometry->GetOrigin();
- mitk::Geometry3D::BoundsArrayType bounds = geometry->GetBounds();
+ mitk::BaseGeometry::BoundsArrayType bounds = geometry->GetBounds();
origin[0] += bounds.GetElement(0);
origin[1] += bounds.GetElement(2);
origin[2] += bounds.GetElement(4);
for (int i=0; i<3; i++)
for (int j=0; j<3; j++)
direction[j][i] = geometry->GetMatrixColumn(i)[j];
imageRegion.SetSize(0, geometry->GetExtent(0));
imageRegion.SetSize(1, geometry->GetExtent(1));
imageRegion.SetSize(2, geometry->GetExtent(2));
m_MaskImage = ItkUcharImgType::New();
m_MaskImage->SetSpacing( spacing );
m_MaskImage->SetOrigin( origin );
m_MaskImage->SetDirection( direction );
m_MaskImage->SetRegions( imageRegion );
m_MaskImage->Allocate();
m_MaskImage->FillBuffer(1);
}
OutputImageType::RegionType::SizeType outImageSize = imageRegion.GetSize();
m_OutImageSpacing = m_MaskImage->GetSpacing();
m_ClusteredDirectionsContainer = ContainerType::New();
// initialize crossings image
m_CrossingsImage = ItkUcharImgType::New();
m_CrossingsImage->SetSpacing( spacing );
m_CrossingsImage->SetOrigin( origin );
m_CrossingsImage->SetDirection( direction );
m_CrossingsImage->SetRegions( imageRegion );
m_CrossingsImage->Allocate();
m_CrossingsImage->FillBuffer(0);
// initialize num directions image
m_NumDirectionsImage = ItkUcharImgType::New();
m_NumDirectionsImage->SetSpacing( spacing );
m_NumDirectionsImage->SetOrigin( origin );
m_NumDirectionsImage->SetDirection( direction );
m_NumDirectionsImage->SetRegions( imageRegion );
m_NumDirectionsImage->Allocate();
m_NumDirectionsImage->FillBuffer(0);
// resample fiber bundle
float minSpacing = 1;
if(m_OutImageSpacing[0]<m_OutImageSpacing[1] && m_OutImageSpacing[0]<m_OutImageSpacing[2])
minSpacing = m_OutImageSpacing[0];
else if (m_OutImageSpacing[1] < m_OutImageSpacing[2])
minSpacing = m_OutImageSpacing[1];
else
minSpacing = m_OutImageSpacing[2];
if (m_UseWorkingCopy)
m_FiberBundle = m_FiberBundle->GetDeepCopy();
// resample fiber bundle for sufficient voxel coverage
m_FiberBundle->ResampleFibers(minSpacing/3);
// iterate over all fibers
vtkSmartPointer<vtkPolyData> fiberPolyData = m_FiberBundle->GetFiberPolyData();
vtkSmartPointer<vtkCellArray> vLines = fiberPolyData->GetLines();
vLines->InitTraversal();
int numFibers = m_FiberBundle->GetNumFibers();
itk::TimeProbe clock;
m_DirectionsContainer = ContainerType::New();
if (m_UseTrilinearInterpolation)
MITK_INFO << "Generating directions from tractogram (trilinear interpolation)";
else
MITK_INFO << "Generating directions from tractogram";
boost::progress_display disp(numFibers);
for( int i=0; i<numFibers; i++ )
{
++disp;
clock.Start();
vtkIdType numPoints(0);
vtkIdType* points(NULL);
vLines->GetNextCell ( numPoints, points );
if (numPoints<2)
continue;
itk::Index<3> index; index.Fill(0);
itk::ContinuousIndex<float, 3> contIndex;
vnl_vector_fixed<double, 3> dir, wDir;
itk::Point<float, 3> worldPos;
vnl_vector<double> v;
for( int j=0; j<numPoints-1; j++)
{
double* temp = fiberPolyData->GetPoint(points[j]);
worldPos = GetItkPoint(temp);
v = GetVnlVector(temp);
dir = GetVnlVector(fiberPolyData->GetPoint(points[j+1]))-v;
dir.normalize();
m_MaskImage->TransformPhysicalPointToIndex(worldPos, index);
m_MaskImage->TransformPhysicalPointToContinuousIndex(worldPos, contIndex);
if (m_MaskImage->GetPixel(index)==0)
continue;
if (!m_UseTrilinearInterpolation)
{
if (index[0] < 0 || (unsigned long)index[0] >= outImageSize[0])
continue;
if (index[1] < 0 || (unsigned long)index[1] >= outImageSize[1])
continue;
if (index[2] < 0 || (unsigned long)index[2] >= outImageSize[2])
continue;
unsigned int idx = index[0] + outImageSize[0]*(index[1] + outImageSize[1]*index[2]);
DirectionContainerType::Pointer dirCont = DirectionContainerType::New();
if (m_DirectionsContainer->IndexExists(idx))
{
dirCont = m_DirectionsContainer->GetElement(idx);
if (dirCont.IsNull())
{
dirCont = DirectionContainerType::New();
dirCont->InsertElement(0, dir);
m_DirectionsContainer->InsertElement(idx, dirCont);
}
else
dirCont->InsertElement(dirCont->Size(), dir);
}
else
{
dirCont->InsertElement(0, dir);
m_DirectionsContainer->InsertElement(idx, dirCont);
}
continue;
}
float frac_x = contIndex[0] - index[0];
float frac_y = contIndex[1] - index[1];
float frac_z = contIndex[2] - index[2];
if (frac_x<0)
{
index[0] -= 1;
frac_x += 1;
}
if (frac_y<0)
{
index[1] -= 1;
frac_y += 1;
}
if (frac_z<0)
{
index[2] -= 1;
frac_z += 1;
}
frac_x = 1-frac_x;
frac_y = 1-frac_y;
frac_z = 1-frac_z;
// int coordinates inside image?
if (index[0] < 0 || (unsigned long)index[0] >= outImageSize[0]-1)
continue;
if (index[1] < 0 || (unsigned long)index[1] >= outImageSize[1]-1)
continue;
if (index[2] < 0 || (unsigned long)index[2] >= outImageSize[2]-1)
continue;
DirectionContainerType::Pointer dirCont;
int idx;
wDir = dir;
float weight = ( frac_x)*( frac_y)*( frac_z);
if (weight>m_Thres)
{
wDir *= weight;
idx = index[0] + outImageSize[0]*(index[1] + outImageSize[1]*index[2] );
dirCont = DirectionContainerType::New();
if (m_DirectionsContainer->IndexExists(idx))
{
dirCont = m_DirectionsContainer->GetElement(idx);
if (dirCont.IsNull())
{
dirCont = DirectionContainerType::New();
dirCont->InsertElement(0, wDir);
m_DirectionsContainer->InsertElement(idx, dirCont);
}
else
dirCont->InsertElement(dirCont->Size(), wDir);
}
else
{
dirCont->InsertElement(0, wDir);
m_DirectionsContainer->InsertElement(idx, dirCont);
}
}
wDir = dir;
weight = ( frac_x)*(1-frac_y)*( frac_z);
if (weight>m_Thres)
{
wDir *= weight;
idx = index[0] + outImageSize[0]*(index[1]+1+ outImageSize[1]*index[2] );
dirCont = DirectionContainerType::New();
if (m_DirectionsContainer->IndexExists(idx))
{
dirCont = m_DirectionsContainer->GetElement(idx);
if (dirCont.IsNull())
{
dirCont = DirectionContainerType::New();
dirCont->InsertElement(0, wDir);
m_DirectionsContainer->InsertElement(idx, dirCont);
}
else
dirCont->InsertElement(dirCont->Size(), wDir);
}
else
{
dirCont->InsertElement(0, wDir);
m_DirectionsContainer->InsertElement(idx, dirCont);
}
}
wDir = dir;
weight = ( frac_x)*( frac_y)*(1-frac_z);
if (weight>m_Thres)
{
wDir *= weight;
idx = index[0] + outImageSize[0]*(index[1] + outImageSize[1]*index[2]+outImageSize[1]);
dirCont = DirectionContainerType::New();
if (m_DirectionsContainer->IndexExists(idx))
{
dirCont = m_DirectionsContainer->GetElement(idx);
if (dirCont.IsNull())
{
dirCont = DirectionContainerType::New();
dirCont->InsertElement(0, wDir);
m_DirectionsContainer->InsertElement(idx, dirCont);
}
else
dirCont->InsertElement(dirCont->Size(), wDir);
}
else
{
dirCont->InsertElement(0, wDir);
m_DirectionsContainer->InsertElement(idx, dirCont);
}
}
wDir = dir;
weight = ( frac_x)*(1-frac_y)*(1-frac_z);
if (weight>m_Thres)
{
wDir *= weight;
idx = index[0] + outImageSize[0]*(index[1]+1+ outImageSize[1]*index[2]+outImageSize[1]);
dirCont = DirectionContainerType::New();
if (m_DirectionsContainer->IndexExists(idx))
{
dirCont = m_DirectionsContainer->GetElement(idx);
if (dirCont.IsNull())
{
dirCont = DirectionContainerType::New();
dirCont->InsertElement(0, wDir);
m_DirectionsContainer->InsertElement(idx, dirCont);
}
else
dirCont->InsertElement(dirCont->Size(), wDir);
}
else
{
dirCont->InsertElement(0, wDir);
m_DirectionsContainer->InsertElement(idx, dirCont);
}
}
wDir = dir;
weight = (1-frac_x)*( frac_y)*( frac_z);
if (weight>m_Thres)
{
wDir *= weight;
idx = index[0]+1 + outImageSize[0]*(index[1] + outImageSize[1]*index[2] );
dirCont = DirectionContainerType::New();
if (m_DirectionsContainer->IndexExists(idx))
{
dirCont = m_DirectionsContainer->GetElement(idx);
if (dirCont.IsNull())
{
dirCont = DirectionContainerType::New();
dirCont->InsertElement(0, wDir);
m_DirectionsContainer->InsertElement(idx, dirCont);
}
else
dirCont->InsertElement(dirCont->Size(), wDir);
}
else
{
dirCont->InsertElement(0, wDir);
m_DirectionsContainer->InsertElement(idx, dirCont);
}
}
wDir = dir;
weight = (1-frac_x)*( frac_y)*(1-frac_z);
if (weight>m_Thres)
{
wDir *= weight;
idx = index[0]+1 + outImageSize[0]*(index[1] + outImageSize[1]*index[2]+outImageSize[1]);
dirCont = DirectionContainerType::New();
if (m_DirectionsContainer->IndexExists(idx))
{
dirCont = m_DirectionsContainer->GetElement(idx);
if (dirCont.IsNull())
{
dirCont = DirectionContainerType::New();
dirCont->InsertElement(0, wDir);
m_DirectionsContainer->InsertElement(idx, dirCont);
}
else
dirCont->InsertElement(dirCont->Size(), wDir);
}
else
{
dirCont->InsertElement(0, wDir);
m_DirectionsContainer->InsertElement(idx, dirCont);
}
}
wDir = dir;
weight = (1-frac_x)*(1-frac_y)*( frac_z);
if (weight>m_Thres)
{
wDir *= weight;
idx = index[0]+1 + outImageSize[0]*(index[1]+1+ outImageSize[1]*index[2] );
dirCont = DirectionContainerType::New();
if (m_DirectionsContainer->IndexExists(idx))
{
dirCont = m_DirectionsContainer->GetElement(idx);
if (dirCont.IsNull())
{
dirCont = DirectionContainerType::New();
dirCont->InsertElement(0, wDir);
m_DirectionsContainer->InsertElement(idx, dirCont);
}
else
dirCont->InsertElement(dirCont->Size(), wDir);
}
else
{
dirCont->InsertElement(0, wDir);
m_DirectionsContainer->InsertElement(idx, dirCont);
}
}
wDir = dir;
weight = (1-frac_x)*(1-frac_y)*(1-frac_z);
if (weight>m_Thres)
{
wDir *= weight;
idx = index[0]+1 + outImageSize[0]*(index[1]+1+ outImageSize[1]*index[2]+outImageSize[1]);
dirCont = DirectionContainerType::New();
if (m_DirectionsContainer->IndexExists(idx))
{
dirCont = m_DirectionsContainer->GetElement(idx);
if (dirCont.IsNull())
{
dirCont = DirectionContainerType::New();
dirCont->InsertElement(0, wDir);
m_DirectionsContainer->InsertElement(idx, dirCont);
}
else
dirCont->InsertElement(dirCont->Size(), wDir);
}
else
{
dirCont->InsertElement(0, wDir);
m_DirectionsContainer->InsertElement(idx, dirCont);
}
}
}
clock.Stop();
}
vtkSmartPointer<vtkCellArray> m_VtkCellArray = vtkSmartPointer<vtkCellArray>::New();
vtkSmartPointer<vtkPoints> m_VtkPoints = vtkSmartPointer<vtkPoints>::New();
itk::ImageRegionIterator<ItkUcharImgType> dirIt(m_NumDirectionsImage, m_NumDirectionsImage->GetLargestPossibleRegion());
itk::ImageRegionIterator<ItkUcharImgType> crossIt(m_CrossingsImage, m_CrossingsImage->GetLargestPossibleRegion());
m_DirectionImageContainer = DirectionImageContainerType::New();
unsigned int maxNumDirections = 0;
MITK_INFO << "Clustering directions";
boost::progress_display disp2(outImageSize[0]*outImageSize[1]*outImageSize[2]);
for(crossIt.GoToBegin(); !crossIt.IsAtEnd(); ++crossIt)
{
++disp2;
OutputImageType::IndexType index = crossIt.GetIndex();
int idx = index[0]+(index[1]+index[2]*outImageSize[1])*outImageSize[0];
if (!m_DirectionsContainer->IndexExists(idx))
{
++dirIt;
continue;
}
DirectionContainerType::Pointer dirCont = m_DirectionsContainer->GetElement(idx);
if (dirCont.IsNull() || index[0] < 0 || (unsigned long)index[0] >= outImageSize[0] || index[1] < 0 || (unsigned long)index[1] >= outImageSize[1] || index[2] < 0 || (unsigned long)index[2] >= outImageSize[2])
{
++dirIt;
continue;
}
std::vector< DirectionType > directions;
for (unsigned int i=0; i<dirCont->Size(); i++)
if (dirCont->ElementAt(i).magnitude()>0.0001)
directions.push_back(dirCont->ElementAt(i));
if (!directions.empty())
directions = FastClustering(directions);
std::sort( directions.begin(), directions.end(), CompareVectorLengths );
if ( directions.size() > maxNumDirections )
{
for (unsigned int i=maxNumDirections; i<std::min<unsigned int>(directions.size(), m_MaxNumDirections); i++)
{
ItkDirectionImageType::Pointer directionImage = ItkDirectionImageType::New();
directionImage->SetSpacing( spacing );
directionImage->SetOrigin( origin );
directionImage->SetDirection( direction );
directionImage->SetRegions( imageRegion );
directionImage->Allocate();
Vector< float, 3 > nullVec; nullVec.Fill(0.0);
directionImage->FillBuffer(nullVec);
m_DirectionImageContainer->InsertElement(i, directionImage);
}
maxNumDirections = std::min<unsigned int>(directions.size(), m_MaxNumDirections);
}
unsigned int numDir = directions.size();
if (numDir>m_MaxNumDirections)
numDir = m_MaxNumDirections;
for (unsigned int i=0; i<numDir; i++)
{
vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
itk::ContinuousIndex<float, 3> center;
center[0] = index[0];
center[1] = index[1];
center[2] = index[2];
itk::Point<float> worldCenter;
m_MaskImage->TransformContinuousIndexToPhysicalPoint( center, worldCenter );
DirectionType dir = directions.at(i);
// set direction image pixel
ItkDirectionImageType::Pointer directionImage = m_DirectionImageContainer->GetElement(i);
Vector< float, 3 > pixel;
pixel.SetElement(0, dir[0]);
pixel.SetElement(1, dir[1]);
pixel.SetElement(2, dir[2]);
directionImage->SetPixel(index, pixel);
// add direction to vector field (with spacing compensation)
itk::Point<float> worldStart;
worldStart[0] = worldCenter[0]-dir[0]/2*minSpacing;
worldStart[1] = worldCenter[1]-dir[1]/2*minSpacing;
worldStart[2] = worldCenter[2]-dir[2]/2*minSpacing;
vtkIdType id = m_VtkPoints->InsertNextPoint(worldStart.GetDataPointer());
container->GetPointIds()->InsertNextId(id);
itk::Point<float> worldEnd;
worldEnd[0] = worldCenter[0]+dir[0]/2*minSpacing;
worldEnd[1] = worldCenter[1]+dir[1]/2*minSpacing;
worldEnd[2] = worldCenter[2]+dir[2]/2*minSpacing;
id = m_VtkPoints->InsertNextPoint(worldEnd.GetDataPointer());
container->GetPointIds()->InsertNextId(id);
m_VtkCellArray->InsertNextCell(container);
}
dirIt.Set(numDir);
++dirIt;
}
vtkSmartPointer<vtkPolyData> directionsPolyData = vtkSmartPointer<vtkPolyData>::New();
directionsPolyData->SetPoints(m_VtkPoints);
directionsPolyData->SetLines(m_VtkCellArray);
m_OutputFiberBundle = mitk::FiberBundleX::New(directionsPolyData);
}
template< class PixelType >
std::vector< vnl_vector_fixed< double, 3 > > TractsToVectorImageFilter< PixelType >::FastClustering(std::vector< vnl_vector_fixed< double, 3 > >& inDirs)
{
std::vector< vnl_vector_fixed< double, 3 > > outDirs;
if (inDirs.empty())
return outDirs;
vnl_vector_fixed< double, 3 > oldMean, currentMean, workingMean;
std::vector< vnl_vector_fixed< double, 3 > > normalizedDirs;
std::vector< int > touched;
for (unsigned int i=0; i<inDirs.size(); i++)
{
normalizedDirs.push_back(inDirs[i]);
normalizedDirs.back().normalize();
}
// initialize
float max = 0.0;
touched.resize(inDirs.size(), 0);
bool free = true;
currentMean = inDirs[0]; // initialize first seed
while (free)
{
oldMean.fill(0.0);
// start mean-shift clustering
float angle = 0.0;
int counter = 0;
while ((currentMean-oldMean).magnitude()>0.0001)
{
counter = 0;
oldMean = currentMean;
workingMean = oldMean;
workingMean.normalize();
currentMean.fill(0.0);
for (unsigned int i=0; i<normalizedDirs.size(); i++)
{
angle = dot_product(workingMean, normalizedDirs[i]);
if (angle>=m_AngularThreshold)
{
currentMean += inDirs[i];
touched[i] = 1;
counter++;
}
else if (-angle>=m_AngularThreshold)
{
currentMean -= inDirs[i];
touched[i] = 1;
counter++;
}
}
}
// found stable mean
if (counter>0)
{
currentMean /= counter;
float mag = currentMean.magnitude();
if (mag>0)
{
if (mag>max)
max = mag;
outDirs.push_back(currentMean);
}
}
// find next unused seed
free = false;
for (unsigned int i=0; i<touched.size(); i++)
if (touched[i]==0)
{
currentMean = inDirs[i];
free = true;
}
}
if (m_NormalizeVectors)
for (unsigned int i=0; i<outDirs.size(); i++)
outDirs[i].normalize();
else if (max>0)
for (unsigned int i=0; i<outDirs.size(); i++)
outDirs[i] /= max;
if (inDirs.size()==outDirs.size())
return outDirs;
else
return FastClustering(outDirs);
}
template< class PixelType >
std::vector< vnl_vector_fixed< double, 3 > > TractsToVectorImageFilter< PixelType >::Clustering(std::vector< vnl_vector_fixed< double, 3 > >& inDirs)
{
std::vector< vnl_vector_fixed< double, 3 > > outDirs;
if (inDirs.empty())
return outDirs;
vnl_vector_fixed< double, 3 > oldMean, currentMean, workingMean;
std::vector< vnl_vector_fixed< double, 3 > > normalizedDirs;
std::vector< int > touched;
for (std::size_t i=0; i<inDirs.size(); i++)
{
normalizedDirs.push_back(inDirs[i]);
normalizedDirs.back().normalize();
}
// initialize
float max = 0.0;
touched.resize(inDirs.size(), 0);
for (std::size_t j=0; j<inDirs.size(); j++)
{
currentMean = inDirs[j];
oldMean.fill(0.0);
// start mean-shift clustering
float angle = 0.0;
int counter = 0;
while ((currentMean-oldMean).magnitude()>0.0001)
{
counter = 0;
oldMean = currentMean;
workingMean = oldMean;
workingMean.normalize();
currentMean.fill(0.0);
for (std::size_t i=0; i<normalizedDirs.size(); i++)
{
angle = dot_product(workingMean, normalizedDirs[i]);
if (angle>=m_AngularThreshold)
{
currentMean += inDirs[i];
counter++;
}
else if (-angle>=m_AngularThreshold)
{
currentMean -= inDirs[i];
counter++;
}
}
}
// found stable mean
if (counter>0)
{
bool add = true;
vnl_vector_fixed< double, 3 > normMean = currentMean;
normMean.normalize();
for (std::size_t i=0; i<outDirs.size(); i++)
{
vnl_vector_fixed< double, 3 > dir = outDirs[i];
dir.normalize();
if ((normMean-dir).magnitude()<=0.0001)
{
add = false;
break;
}
}
currentMean /= counter;
if (add)
{
float mag = currentMean.magnitude();
if (mag>0)
{
if (mag>max)
max = mag;
outDirs.push_back(currentMean);
}
}
}
}
if (m_NormalizeVectors)
for (std::size_t i=0; i<outDirs.size(); i++)
outDirs[i].normalize();
else if (max>0)
for (std::size_t i=0; i<outDirs.size(); i++)
outDirs[i] /= max;
if (inDirs.size()==outDirs.size())
return outDirs;
else
return FastClustering(outDirs);
}
template< class PixelType >
TractsToVectorImageFilter< PixelType >::DirectionContainerType::Pointer TractsToVectorImageFilter< PixelType >::MeanShiftClustering(DirectionContainerType::Pointer dirCont)
{
DirectionContainerType::Pointer container = DirectionContainerType::New();
float max = 0;
for (DirectionContainerType::ConstIterator it = dirCont->Begin(); it!=dirCont->End(); ++it)
{
vnl_vector_fixed<double, 3> mean = ClusterStep(dirCont, it.Value());
if (mean.is_zero())
continue;
bool addMean = true;
for (DirectionContainerType::ConstIterator it2 = container->Begin(); it2!=container->End(); ++it2)
{
vnl_vector_fixed<double, 3> dir = it2.Value();
float angle = fabs(dot_product(mean, dir)/(mean.magnitude()*dir.magnitude()));
if (angle>=m_Epsilon)
{
addMean = false;
break;
}
}
if (addMean)
{
if (m_NormalizeVectors)
mean.normalize();
else if (mean.magnitude()>max)
max = mean.magnitude();
container->InsertElement(container->Size(), mean);
}
}
// max normalize voxel directions
if (max>0 && !m_NormalizeVectors)
for (std::size_t i=0; i<container->Size(); i++)
container->ElementAt(i) /= max;
if (container->Size()<dirCont->Size())
return MeanShiftClustering(container);
else
return container;
}
template< class PixelType >
vnl_vector_fixed<double, 3> TractsToVectorImageFilter< PixelType >::ClusterStep(DirectionContainerType::Pointer dirCont, vnl_vector_fixed<double, 3> currentMean)
{
vnl_vector_fixed<double, 3> newMean; newMean.fill(0);
for (DirectionContainerType::ConstIterator it = dirCont->Begin(); it!=dirCont->End(); ++it)
{
vnl_vector_fixed<double, 3> dir = it.Value();
float angle = dot_product(currentMean, dir)/(currentMean.magnitude()*dir.magnitude());
if (angle>=m_AngularThreshold)
newMean += dir;
else if (-angle>=m_AngularThreshold)
newMean -= dir;
}
if (fabs(dot_product(currentMean, newMean)/(currentMean.magnitude()*newMean.magnitude()))>=m_Epsilon || newMean.is_zero())
return newMean;
else
return ClusterStep(dirCont, newMean);
}
}
diff --git a/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundleX/mitkFiberBundleX.cpp b/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundleX/mitkFiberBundleX.cpp
index 200253e225..a32ca9c194 100755
--- a/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundleX/mitkFiberBundleX.cpp
+++ b/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundleX/mitkFiberBundleX.cpp
@@ -1,1965 +1,1965 @@
/*===================================================================
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.
===================================================================*/
#define _USE_MATH_DEFINES
#include "mitkFiberBundleX.h"
#include <mitkPlanarCircle.h>
#include <mitkPlanarPolygon.h>
#include <mitkPlanarFigureComposite.h>
#include "mitkImagePixelReadAccessor.h"
#include <mitkPixelTypeMultiplex.h>
#include <vtkPointData.h>
#include <vtkDataArray.h>
#include <vtkUnsignedCharArray.h>
#include <vtkPolyLine.h>
#include <vtkCellArray.h>
#include <vtkCellData.h>
#include <vtkIdFilter.h>
#include <vtkClipPolyData.h>
#include <vtkPlane.h>
#include <vtkDoubleArray.h>
#include <vtkKochanekSpline.h>
#include <vtkParametricFunctionSource.h>
#include <vtkParametricSpline.h>
#include <vtkPolygon.h>
#include <vtkCleanPolyData.h>
#include <cmath>
#include <boost/progress.hpp>
#include <vtkTransformPolyDataFilter.h>
const char* mitk::FiberBundleX::COLORCODING_ORIENTATION_BASED = "Color_Orient";
//const char* mitk::FiberBundleX::COLORCODING_FA_AS_OPACITY = "Color_Orient_FA_Opacity";
const char* mitk::FiberBundleX::COLORCODING_FA_BASED = "FA_Values";
const char* mitk::FiberBundleX::COLORCODING_CUSTOM = "custom";
const char* mitk::FiberBundleX::FIBER_ID_ARRAY = "Fiber_IDs";
using namespace std;
mitk::FiberBundleX::FiberBundleX( vtkPolyData* fiberPolyData )
: m_CurrentColorCoding(NULL)
, m_NumFibers(0)
, m_FiberSampling(0)
{
m_FiberPolyData = vtkSmartPointer<vtkPolyData>::New();
if (fiberPolyData != NULL)
{
m_FiberPolyData = fiberPolyData;
//m_FiberPolyData->DeepCopy(fiberPolyData);
this->DoColorCodingOrientationBased();
}
this->UpdateFiberGeometry();
this->SetColorCoding(COLORCODING_ORIENTATION_BASED);
this->GenerateFiberIds();
}
mitk::FiberBundleX::~FiberBundleX()
{
}
mitk::FiberBundleX::Pointer mitk::FiberBundleX::GetDeepCopy()
{
mitk::FiberBundleX::Pointer newFib = mitk::FiberBundleX::New(m_FiberPolyData);
newFib->SetColorCoding(m_CurrentColorCoding);
return newFib;
}
vtkSmartPointer<vtkPolyData> mitk::FiberBundleX::GeneratePolyDataByIds(std::vector<long> fiberIds)
{
MITK_DEBUG << "\n=====FINAL RESULT: fib_id ======\n";
MITK_DEBUG << "Number of new Fibers: " << fiberIds.size();
// iterate through the vectorcontainer hosting all desired fiber Ids
vtkSmartPointer<vtkPolyData> newFiberPolyData = vtkSmartPointer<vtkPolyData>::New();
vtkSmartPointer<vtkCellArray> newLineSet = vtkSmartPointer<vtkCellArray>::New();
vtkSmartPointer<vtkPoints> newPointSet = vtkSmartPointer<vtkPoints>::New();
// if FA array available, initialize fa double array
// if color orient array is available init color array
vtkSmartPointer<vtkDoubleArray> faValueArray;
vtkSmartPointer<vtkUnsignedCharArray> colorsT;
//colors and alpha value for each single point, RGBA = 4 components
unsigned char rgba[4] = {0,0,0,0};
int componentSize = sizeof(rgba);
if (m_FiberIdDataSet->GetPointData()->HasArray(COLORCODING_FA_BASED)){
MITK_DEBUG << "FA VALUES AVAILABLE, init array for new fiberbundle";
faValueArray = vtkSmartPointer<vtkDoubleArray>::New();
}
if (m_FiberIdDataSet->GetPointData()->HasArray(COLORCODING_ORIENTATION_BASED)){
MITK_DEBUG << "colorValues available, init array for new fiberbundle";
colorsT = vtkUnsignedCharArray::New();
colorsT->SetNumberOfComponents(componentSize);
colorsT->SetName(COLORCODING_ORIENTATION_BASED);
}
std::vector<long>::iterator finIt = fiberIds.begin();
while ( finIt != fiberIds.end() )
{
if (*finIt < 0 || *finIt>GetNumFibers()){
MITK_INFO << "FiberID can not be negative or >NumFibers!!! check id Extraction!" << *finIt;
break;
}
vtkSmartPointer<vtkCell> fiber = m_FiberIdDataSet->GetCell(*finIt);//->DeepCopy(fiber);
vtkSmartPointer<vtkPoints> fibPoints = fiber->GetPoints();
vtkSmartPointer<vtkPolyLine> newFiber = vtkSmartPointer<vtkPolyLine>::New();
newFiber->GetPointIds()->SetNumberOfIds( fibPoints->GetNumberOfPoints() );
for(int i=0; i<fibPoints->GetNumberOfPoints(); i++)
{
// MITK_DEBUG << "id: " << fiber->GetPointId(i);
// MITK_DEBUG << fibPoints->GetPoint(i)[0] << " | " << fibPoints->GetPoint(i)[1] << " | " << fibPoints->GetPoint(i)[2];
newFiber->GetPointIds()->SetId(i, newPointSet->GetNumberOfPoints());
newPointSet->InsertNextPoint(fibPoints->GetPoint(i)[0], fibPoints->GetPoint(i)[1], fibPoints->GetPoint(i)[2]);
if (m_FiberIdDataSet->GetPointData()->HasArray(COLORCODING_FA_BASED)){
// MITK_DEBUG << m_FiberIdDataSet->GetPointData()->GetArray(FA_VALUE_ARRAY)->GetTuple(fiber->GetPointId(i));
}
if (m_FiberIdDataSet->GetPointData()->HasArray(COLORCODING_ORIENTATION_BASED)){
// MITK_DEBUG << "ColorValue: " << m_FiberIdDataSet->GetPointData()->GetArray(COLORCODING_ORIENTATION_BASED)->GetTuple(fiber->GetPointId(i))[0];
}
}
newLineSet->InsertNextCell(newFiber);
++finIt;
}
newFiberPolyData->SetPoints(newPointSet);
newFiberPolyData->SetLines(newLineSet);
MITK_DEBUG << "new fiberbundle polydata points: " << newFiberPolyData->GetNumberOfPoints();
MITK_DEBUG << "new fiberbundle polydata lines: " << newFiberPolyData->GetNumberOfLines();
MITK_DEBUG << "=====================\n";
// mitk::FiberBundleX::Pointer newFib = mitk::FiberBundleX::New(newFiberPolyData);
return newFiberPolyData;
}
// merge two fiber bundles
mitk::FiberBundleX::Pointer mitk::FiberBundleX::AddBundle(mitk::FiberBundleX* fib)
{
if (fib==NULL)
{
MITK_WARN << "trying to call AddBundle with NULL argument";
return NULL;
}
MITK_INFO << "Adding fibers";
vtkSmartPointer<vtkPolyData> vNewPolyData = vtkSmartPointer<vtkPolyData>::New();
vtkSmartPointer<vtkCellArray> vNewLines = vtkSmartPointer<vtkCellArray>::New();
vtkSmartPointer<vtkPoints> vNewPoints = vtkSmartPointer<vtkPoints>::New();
// add current fiber bundle
for (int i=0; i<m_FiberPolyData->GetNumberOfCells(); i++)
{
vtkCell* cell = m_FiberPolyData->GetCell(i);
int numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
for (int j=0; j<numPoints; j++)
{
double p[3];
points->GetPoint(j, p);
vtkIdType id = vNewPoints->InsertNextPoint(p);
container->GetPointIds()->InsertNextId(id);
}
vNewLines->InsertNextCell(container);
}
// add new fiber bundle
for (int i=0; i<fib->GetFiberPolyData()->GetNumberOfCells(); i++)
{
vtkCell* cell = fib->GetFiberPolyData()->GetCell(i);
int numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
for (int j=0; j<numPoints; j++)
{
double p[3];
points->GetPoint(j, p);
vtkIdType id = vNewPoints->InsertNextPoint(p);
container->GetPointIds()->InsertNextId(id);
}
vNewLines->InsertNextCell(container);
}
// initialize polydata
vNewPolyData->SetPoints(vNewPoints);
vNewPolyData->SetLines(vNewLines);
// initialize fiber bundle
mitk::FiberBundleX::Pointer newFib = mitk::FiberBundleX::New(vNewPolyData);
return newFib;
}
// subtract two fiber bundles
mitk::FiberBundleX::Pointer mitk::FiberBundleX::SubtractBundle(mitk::FiberBundleX* fib)
{
MITK_INFO << "Subtracting fibers";
vtkSmartPointer<vtkPolyData> vNewPolyData = vtkSmartPointer<vtkPolyData>::New();
vtkSmartPointer<vtkCellArray> vNewLines = vtkSmartPointer<vtkCellArray>::New();
vtkSmartPointer<vtkPoints> vNewPoints = vtkSmartPointer<vtkPoints>::New();
// iterate over current fibers
boost::progress_display disp(m_NumFibers);
for( int i=0; i<m_NumFibers; i++ )
{
++disp;
vtkCell* cell = m_FiberPolyData->GetCell(i);
int numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
if (points==NULL || numPoints<=0)
continue;
int numFibers2 = fib->GetNumFibers();
bool contained = false;
for( int i2=0; i2<numFibers2; i2++ )
{
vtkCell* cell2 = fib->GetFiberPolyData()->GetCell(i2);
int numPoints2 = cell2->GetNumberOfPoints();
vtkPoints* points2 = cell2->GetPoints();
if (points2==NULL)// || numPoints2<=0)
continue;
// check endpoints
if (numPoints2==numPoints)
{
itk::Point<float, 3> point_start = GetItkPoint(points->GetPoint(0));
itk::Point<float, 3> point_end = GetItkPoint(points->GetPoint(numPoints-1));
itk::Point<float, 3> point2_start = GetItkPoint(points2->GetPoint(0));
itk::Point<float, 3> point2_end = GetItkPoint(points2->GetPoint(numPoints2-1));
if ((point_start.SquaredEuclideanDistanceTo(point2_start)<=mitk::eps && point_end.SquaredEuclideanDistanceTo(point2_end)<=mitk::eps) ||
(point_start.SquaredEuclideanDistanceTo(point2_end)<=mitk::eps && point_end.SquaredEuclideanDistanceTo(point2_start)<=mitk::eps))
{
// further checking ???
contained = true;
break;
}
}
}
// add to result because fiber is not subtracted
if (!contained)
{
vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
for( int j=0; j<numPoints; j++)
{
vtkIdType id = vNewPoints->InsertNextPoint(points->GetPoint(j));
container->GetPointIds()->InsertNextId(id);
}
vNewLines->InsertNextCell(container);
}
}
if(vNewLines->GetNumberOfCells()==0)
return NULL;
// initialize polydata
vNewPolyData->SetPoints(vNewPoints);
vNewPolyData->SetLines(vNewLines);
// initialize fiber bundle
return mitk::FiberBundleX::New(vNewPolyData);
}
itk::Point<float, 3> mitk::FiberBundleX::GetItkPoint(double point[3])
{
itk::Point<float, 3> itkPoint;
itkPoint[0] = point[0];
itkPoint[1] = point[1];
itkPoint[2] = point[2];
return itkPoint;
}
/*
* set polydata (additional flag to recompute fiber geometry, default = true)
*/
void mitk::FiberBundleX::SetFiberPolyData(vtkSmartPointer<vtkPolyData> fiberPD, bool updateGeometry)
{
if (fiberPD == NULL)
this->m_FiberPolyData = vtkSmartPointer<vtkPolyData>::New();
else
{
m_FiberPolyData->DeepCopy(fiberPD);
DoColorCodingOrientationBased();
}
m_NumFibers = m_FiberPolyData->GetNumberOfLines();
if (updateGeometry)
UpdateFiberGeometry();
SetColorCoding(COLORCODING_ORIENTATION_BASED);
GenerateFiberIds();
}
/*
* return vtkPolyData
*/
vtkSmartPointer<vtkPolyData> mitk::FiberBundleX::GetFiberPolyData()
{
return m_FiberPolyData;
}
void mitk::FiberBundleX::DoColorCodingOrientationBased()
{
//===== FOR WRITING A TEST ========================
// colorT size == tupelComponents * tupelElements
// compare color results
// to cover this code 100% also polydata needed, where colorarray already exists
// + one fiber with exactly 1 point
// + one fiber with 0 points
//=================================================
/* make sure that processing colorcoding is only called when necessary */
if ( m_FiberPolyData->GetPointData()->HasArray(COLORCODING_ORIENTATION_BASED) &&
m_FiberPolyData->GetNumberOfPoints() ==
m_FiberPolyData->GetPointData()->GetArray(COLORCODING_ORIENTATION_BASED)->GetNumberOfTuples() )
{
// fiberstructure is already colorcoded
MITK_DEBUG << " NO NEED TO REGENERATE COLORCODING! " ;
this->ResetFiberOpacity();
this->SetColorCoding(COLORCODING_ORIENTATION_BASED);
return;
}
/* Finally, execute color calculation */
vtkPoints* extrPoints = NULL;
extrPoints = m_FiberPolyData->GetPoints();
int numOfPoints = 0;
if (extrPoints!=NULL)
numOfPoints = extrPoints->GetNumberOfPoints();
//colors and alpha value for each single point, RGBA = 4 components
unsigned char rgba[4] = {0,0,0,0};
// int componentSize = sizeof(rgba);
int componentSize = 4;
vtkSmartPointer<vtkUnsignedCharArray> colorsT = vtkSmartPointer<vtkUnsignedCharArray>::New();
colorsT->Allocate(numOfPoints * componentSize);
colorsT->SetNumberOfComponents(componentSize);
colorsT->SetName(COLORCODING_ORIENTATION_BASED);
/* checkpoint: does polydata contain any fibers */
int numOfFibers = m_FiberPolyData->GetNumberOfLines();
if (numOfFibers < 1) {
MITK_DEBUG << "\n ========= Number of Fibers is 0 and below ========= \n";
return;
}
/* extract single fibers of fiberBundle */
vtkCellArray* fiberList = m_FiberPolyData->GetLines();
fiberList->InitTraversal();
for (int fi=0; fi<numOfFibers; ++fi) {
vtkIdType* idList; // contains the point id's of the line
vtkIdType pointsPerFiber; // number of points for current line
fiberList->GetNextCell(pointsPerFiber, idList);
// MITK_DEBUG << "Fib#: " << fi << " of " << numOfFibers << " pnts in fiber: " << pointsPerFiber ;
/* single fiber checkpoints: is number of points valid */
if (pointsPerFiber > 1)
{
/* operate on points of single fiber */
for (int i=0; i <pointsPerFiber; ++i)
{
/* process all points except starting and endpoint
* for calculating color value take current point, previous point and next point */
if (i<pointsPerFiber-1 && i > 0)
{
/* The color value of the current point is influenced by the previous point and next point. */
vnl_vector_fixed< double, 3 > currentPntvtk(extrPoints->GetPoint(idList[i])[0], extrPoints->GetPoint(idList[i])[1],extrPoints->GetPoint(idList[i])[2]);
vnl_vector_fixed< double, 3 > nextPntvtk(extrPoints->GetPoint(idList[i+1])[0], extrPoints->GetPoint(idList[i+1])[1], extrPoints->GetPoint(idList[i+1])[2]);
vnl_vector_fixed< double, 3 > prevPntvtk(extrPoints->GetPoint(idList[i-1])[0], extrPoints->GetPoint(idList[i-1])[1], extrPoints->GetPoint(idList[i-1])[2]);
vnl_vector_fixed< double, 3 > diff1;
diff1 = currentPntvtk - nextPntvtk;
vnl_vector_fixed< double, 3 > diff2;
diff2 = currentPntvtk - prevPntvtk;
vnl_vector_fixed< double, 3 > diff;
diff = (diff1 - diff2) / 2.0;
diff.normalize();
rgba[0] = (unsigned char) (255.0 * std::fabs(diff[0]));
rgba[1] = (unsigned char) (255.0 * std::fabs(diff[1]));
rgba[2] = (unsigned char) (255.0 * std::fabs(diff[2]));
rgba[3] = (unsigned char) (255.0);
} else if (i==0) {
/* First point has no previous point, therefore only diff1 is taken */
vnl_vector_fixed< double, 3 > currentPntvtk(extrPoints->GetPoint(idList[i])[0], extrPoints->GetPoint(idList[i])[1],extrPoints->GetPoint(idList[i])[2]);
vnl_vector_fixed< double, 3 > nextPntvtk(extrPoints->GetPoint(idList[i+1])[0], extrPoints->GetPoint(idList[i+1])[1], extrPoints->GetPoint(idList[i+1])[2]);
vnl_vector_fixed< double, 3 > diff1;
diff1 = currentPntvtk - nextPntvtk;
diff1.normalize();
rgba[0] = (unsigned char) (255.0 * std::fabs(diff1[0]));
rgba[1] = (unsigned char) (255.0 * std::fabs(diff1[1]));
rgba[2] = (unsigned char) (255.0 * std::fabs(diff1[2]));
rgba[3] = (unsigned char) (255.0);
} else if (i==pointsPerFiber-1) {
/* Last point has no next point, therefore only diff2 is taken */
vnl_vector_fixed< double, 3 > currentPntvtk(extrPoints->GetPoint(idList[i])[0], extrPoints->GetPoint(idList[i])[1],extrPoints->GetPoint(idList[i])[2]);
vnl_vector_fixed< double, 3 > prevPntvtk(extrPoints->GetPoint(idList[i-1])[0], extrPoints->GetPoint(idList[i-1])[1], extrPoints->GetPoint(idList[i-1])[2]);
vnl_vector_fixed< double, 3 > diff2;
diff2 = currentPntvtk - prevPntvtk;
diff2.normalize();
rgba[0] = (unsigned char) (255.0 * std::fabs(diff2[0]));
rgba[1] = (unsigned char) (255.0 * std::fabs(diff2[1]));
rgba[2] = (unsigned char) (255.0 * std::fabs(diff2[2]));
rgba[3] = (unsigned char) (255.0);
}
colorsT->InsertTupleValue(idList[i], rgba);
} //end for loop
} else if (pointsPerFiber == 1) {
/* a single point does not define a fiber (use vertex mechanisms instead */
continue;
// colorsT->InsertTupleValue(0, rgba);
} else {
MITK_DEBUG << "Fiber with 0 points detected... please check your tractography algorithm!" ;
continue;
}
}//end for loop
m_FiberPolyData->GetPointData()->AddArray(colorsT);
/*=========================
- this is more relevant for renderer than for fiberbundleX datastructure
- think about sourcing this to a explicit method which coordinates colorcoding */
this->SetColorCoding(COLORCODING_ORIENTATION_BASED);
// ===========================
//mini test, shall be ported to MITK TESTINGS!
if (colorsT->GetSize() != numOfPoints*componentSize)
MITK_DEBUG << "ALLOCATION ERROR IN INITIATING COLOR ARRAY";
}
void mitk::FiberBundleX::DoColorCodingFaBased()
{
if(m_FiberPolyData->GetPointData()->HasArray(COLORCODING_FA_BASED) != 1 )
return;
this->SetColorCoding(COLORCODING_FA_BASED);
MITK_DEBUG << "FBX: done CC FA based";
this->GenerateFiberIds();
}
void mitk::FiberBundleX::DoUseFaFiberOpacity()
{
if(m_FiberPolyData->GetPointData()->HasArray(COLORCODING_FA_BASED) != 1 )
return;
if(m_FiberPolyData->GetPointData()->HasArray(COLORCODING_ORIENTATION_BASED) != 1 )
return;
vtkDoubleArray* FAValArray = (vtkDoubleArray*) m_FiberPolyData->GetPointData()->GetArray(COLORCODING_FA_BASED);
vtkUnsignedCharArray* ColorArray = dynamic_cast<vtkUnsignedCharArray*> (m_FiberPolyData->GetPointData()->GetArray(COLORCODING_ORIENTATION_BASED));
for(long i=0; i<ColorArray->GetNumberOfTuples(); i++) {
double faValue = FAValArray->GetValue(i);
faValue = faValue * 255.0;
ColorArray->SetComponent(i,3, (unsigned char) faValue );
}
this->SetColorCoding(COLORCODING_ORIENTATION_BASED);
MITK_DEBUG << "FBX: done CC OPACITY";
this->GenerateFiberIds();
}
void mitk::FiberBundleX::ResetFiberOpacity() {
vtkUnsignedCharArray* ColorArray = dynamic_cast<vtkUnsignedCharArray*> (m_FiberPolyData->GetPointData()->GetArray(COLORCODING_ORIENTATION_BASED));
if (ColorArray==NULL)
return;
for(long i=0; i<ColorArray->GetNumberOfTuples(); i++)
ColorArray->SetComponent(i,3, 255.0 );
}
void mitk::FiberBundleX::SetFAMap(mitk::Image::Pointer FAimage)
{
mitkPixelTypeMultiplex1( SetFAMap, FAimage->GetPixelType(), FAimage );
}
template <typename TPixel>
void mitk::FiberBundleX::SetFAMap(const mitk::PixelType, mitk::Image::Pointer FAimage)
{
MITK_DEBUG << "SetFAMap";
vtkSmartPointer<vtkDoubleArray> faValues = vtkSmartPointer<vtkDoubleArray>::New();
faValues->SetName(COLORCODING_FA_BASED);
faValues->Allocate(m_FiberPolyData->GetNumberOfPoints());
faValues->SetNumberOfValues(m_FiberPolyData->GetNumberOfPoints());
mitk::ImagePixelReadAccessor<TPixel,3> readFAimage (FAimage, FAimage->GetVolumeData(0));
vtkPoints* pointSet = m_FiberPolyData->GetPoints();
for(long i=0; i<m_FiberPolyData->GetNumberOfPoints(); ++i)
{
Point3D px;
px[0] = pointSet->GetPoint(i)[0];
px[1] = pointSet->GetPoint(i)[1];
px[2] = pointSet->GetPoint(i)[2];
double faPixelValue = 1-readFAimage.GetPixelByWorldCoordinates(px);
faValues->InsertValue(i, faPixelValue);
}
m_FiberPolyData->GetPointData()->AddArray(faValues);
this->GenerateFiberIds();
if(m_FiberPolyData->GetPointData()->HasArray(COLORCODING_FA_BASED))
MITK_DEBUG << "FA VALUE ARRAY SET";
}
void mitk::FiberBundleX::GenerateFiberIds()
{
if (m_FiberPolyData == NULL)
return;
vtkSmartPointer<vtkIdFilter> idFiberFilter = vtkSmartPointer<vtkIdFilter>::New();
idFiberFilter->SetInputData(m_FiberPolyData);
idFiberFilter->CellIdsOn();
// idFiberFilter->PointIdsOn(); // point id's are not needed
idFiberFilter->SetIdsArrayName(FIBER_ID_ARRAY);
idFiberFilter->FieldDataOn();
idFiberFilter->Update();
m_FiberIdDataSet = idFiberFilter->GetOutput();
MITK_DEBUG << "Generating Fiber Ids...[done] | " << m_FiberIdDataSet->GetNumberOfCells();
}
mitk::FiberBundleX::Pointer mitk::FiberBundleX::ExtractFiberSubset(ItkUcharImgType* mask, bool anyPoint)
{
vtkSmartPointer<vtkPolyData> polyData = m_FiberPolyData;
if (anyPoint)
{
float minSpacing = 1;
if(mask->GetSpacing()[0]<mask->GetSpacing()[1] && mask->GetSpacing()[0]<mask->GetSpacing()[2])
minSpacing = mask->GetSpacing()[0];
else if (mask->GetSpacing()[1] < mask->GetSpacing()[2])
minSpacing = mask->GetSpacing()[1];
else
minSpacing = mask->GetSpacing()[2];
mitk::FiberBundleX::Pointer fibCopy = this->GetDeepCopy();
fibCopy->ResampleFibers(minSpacing/10);
polyData = fibCopy->GetFiberPolyData();
}
vtkSmartPointer<vtkPoints> vtkNewPoints = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkCellArray> vtkNewCells = vtkSmartPointer<vtkCellArray>::New();
MITK_INFO << "Extracting fibers";
boost::progress_display disp(m_NumFibers);
for (int i=0; i<m_NumFibers; i++)
{
++disp;
vtkCell* cell = polyData->GetCell(i);
int numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
vtkCell* cellOriginal = m_FiberPolyData->GetCell(i);
int numPointsOriginal = cellOriginal->GetNumberOfPoints();
vtkPoints* pointsOriginal = cellOriginal->GetPoints();
vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
if (numPoints>1 && numPointsOriginal)
{
if (anyPoint)
{
for (int j=0; j<numPoints; j++)
{
double* p = points->GetPoint(j);
itk::Point<float, 3> itkP;
itkP[0] = p[0]; itkP[1] = p[1]; itkP[2] = p[2];
itk::Index<3> idx;
mask->TransformPhysicalPointToIndex(itkP, idx);
if ( mask->GetPixel(idx)>0 && mask->GetLargestPossibleRegion().IsInside(idx) )
{
for (int k=0; k<numPointsOriginal; k++)
{
double* p = pointsOriginal->GetPoint(k);
vtkIdType id = vtkNewPoints->InsertNextPoint(p);
container->GetPointIds()->InsertNextId(id);
}
break;
}
}
}
else
{
double* start = pointsOriginal->GetPoint(0);
itk::Point<float, 3> itkStart;
itkStart[0] = start[0]; itkStart[1] = start[1]; itkStart[2] = start[2];
itk::Index<3> idxStart;
mask->TransformPhysicalPointToIndex(itkStart, idxStart);
double* end = pointsOriginal->GetPoint(numPointsOriginal-1);
itk::Point<float, 3> itkEnd;
itkEnd[0] = end[0]; itkEnd[1] = end[1]; itkEnd[2] = end[2];
itk::Index<3> idxEnd;
mask->TransformPhysicalPointToIndex(itkEnd, idxEnd);
if ( mask->GetPixel(idxStart)>0 && mask->GetPixel(idxEnd)>0 && mask->GetLargestPossibleRegion().IsInside(idxStart) && mask->GetLargestPossibleRegion().IsInside(idxEnd) )
{
for (int j=0; j<numPointsOriginal; j++)
{
double* p = pointsOriginal->GetPoint(j);
vtkIdType id = vtkNewPoints->InsertNextPoint(p);
container->GetPointIds()->InsertNextId(id);
}
}
}
}
vtkNewCells->InsertNextCell(container);
}
if (vtkNewCells->GetNumberOfCells()<=0)
return NULL;
vtkSmartPointer<vtkPolyData> newPolyData = vtkSmartPointer<vtkPolyData>::New();
newPolyData->SetPoints(vtkNewPoints);
newPolyData->SetLines(vtkNewCells);
return mitk::FiberBundleX::New(newPolyData);
}
mitk::FiberBundleX::Pointer mitk::FiberBundleX::RemoveFibersOutside(ItkUcharImgType* mask, bool invert)
{
float minSpacing = 1;
if(mask->GetSpacing()[0]<mask->GetSpacing()[1] && mask->GetSpacing()[0]<mask->GetSpacing()[2])
minSpacing = mask->GetSpacing()[0];
else if (mask->GetSpacing()[1] < mask->GetSpacing()[2])
minSpacing = mask->GetSpacing()[1];
else
minSpacing = mask->GetSpacing()[2];
mitk::FiberBundleX::Pointer fibCopy = this->GetDeepCopy();
fibCopy->ResampleFibers(minSpacing/10);
vtkSmartPointer<vtkPolyData> polyData =fibCopy->GetFiberPolyData();
vtkSmartPointer<vtkPoints> vtkNewPoints = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkCellArray> vtkNewCells = vtkSmartPointer<vtkCellArray>::New();
MITK_INFO << "Cutting fibers";
boost::progress_display disp(m_NumFibers);
for (int i=0; i<m_NumFibers; i++)
{
++disp;
vtkCell* cell = polyData->GetCell(i);
int numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
if (numPoints>1)
{
int newNumPoints = 0;
for (int j=0; j<numPoints; j++)
{
double* p = points->GetPoint(j);
itk::Point<float, 3> itkP;
itkP[0] = p[0]; itkP[1] = p[1]; itkP[2] = p[2];
itk::Index<3> idx;
mask->TransformPhysicalPointToIndex(itkP, idx);
if ( mask->GetPixel(idx)>0 && mask->GetLargestPossibleRegion().IsInside(idx) && !invert )
{
vtkIdType id = vtkNewPoints->InsertNextPoint(p);
container->GetPointIds()->InsertNextId(id);
newNumPoints++;
}
else if ( (mask->GetPixel(idx)<=0 || !mask->GetLargestPossibleRegion().IsInside(idx)) && invert )
{
vtkIdType id = vtkNewPoints->InsertNextPoint(p);
container->GetPointIds()->InsertNextId(id);
newNumPoints++;
}
else if (newNumPoints>0)
{
vtkNewCells->InsertNextCell(container);
newNumPoints = 0;
container = vtkSmartPointer<vtkPolyLine>::New();
}
}
if (newNumPoints>0)
vtkNewCells->InsertNextCell(container);
}
}
if (vtkNewCells->GetNumberOfCells()<=0)
return NULL;
vtkSmartPointer<vtkPolyData> newPolyData = vtkSmartPointer<vtkPolyData>::New();
newPolyData->SetPoints(vtkNewPoints);
newPolyData->SetLines(vtkNewCells);
mitk::FiberBundleX::Pointer newFib = mitk::FiberBundleX::New(newPolyData);
newFib->ResampleFibers(minSpacing/2);
return newFib;
}
mitk::FiberBundleX::Pointer mitk::FiberBundleX::ExtractFiberSubset(mitk::PlanarFigure* pf)
{
if (pf==NULL)
return NULL;
std::vector<long> tmp = ExtractFiberIdSubset(pf);
if (tmp.size()<=0)
return mitk::FiberBundleX::New();
vtkSmartPointer<vtkPolyData> pTmp = GeneratePolyDataByIds(tmp);
return mitk::FiberBundleX::New(pTmp);
}
std::vector<long> mitk::FiberBundleX::ExtractFiberIdSubset(mitk::PlanarFigure* pf)
{
MITK_DEBUG << "Extracting fibers!";
// vector which is returned, contains all extracted FiberIds
std::vector<long> FibersInROI;
if (pf==NULL)
return FibersInROI;
/* Handle type of planarfigure */
// if incoming pf is a pfc
mitk::PlanarFigureComposite::Pointer pfcomp= dynamic_cast<mitk::PlanarFigureComposite*>(pf);
if (!pfcomp.IsNull()) {
// process requested boolean operation of PFC
switch (pfcomp->getOperationType()) {
case 0:
{
MITK_DEBUG << "AND PROCESSING";
//AND
//temporarly store results of the child in this vector, we need that to accumulate the
std::vector<long> childResults = this->ExtractFiberIdSubset(pfcomp->getChildAt(0));
MITK_DEBUG << "first roi got fibers in ROI: " << childResults.size();
MITK_DEBUG << "sorting...";
std::sort(childResults.begin(), childResults.end());
MITK_DEBUG << "sorting done";
std::vector<long> AND_Assamblage(childResults.size());
//std::vector<unsigned long> AND_Assamblage;
fill(AND_Assamblage.begin(), AND_Assamblage.end(), -1);
//AND_Assamblage.reserve(childResults.size()); //max size AND can reach anyway
std::vector<long>::iterator it;
for (int i=1; i<pfcomp->getNumberOfChildren(); ++i)
{
std::vector<long> tmpChild = this->ExtractFiberIdSubset(pfcomp->getChildAt(i));
MITK_DEBUG << "ROI " << i << " has fibers in ROI: " << tmpChild.size();
sort(tmpChild.begin(), tmpChild.end());
it = std::set_intersection(childResults.begin(), childResults.end(),
tmpChild.begin(), tmpChild.end(),
AND_Assamblage.begin() );
}
MITK_DEBUG << "resize Vector";
unsigned long i=0;
while (i < AND_Assamblage.size() && AND_Assamblage[i] != -1){ //-1 represents a placeholder in the array
++i;
}
AND_Assamblage.resize(i);
MITK_DEBUG << "returning AND vector, size: " << AND_Assamblage.size();
return AND_Assamblage;
// break;
}
case 1:
{
//OR
std::vector<long> OR_Assamblage = this->ExtractFiberIdSubset(pfcomp->getChildAt(0));
std::vector<long>::iterator it;
MITK_DEBUG << OR_Assamblage.size();
for (int i=1; i<pfcomp->getNumberOfChildren(); ++i) {
it = OR_Assamblage.end();
std::vector<long> tmpChild = this->ExtractFiberIdSubset(pfcomp->getChildAt(i));
OR_Assamblage.insert(it, tmpChild.begin(), tmpChild.end());
MITK_DEBUG << "ROI " << i << " has fibers in ROI: " << tmpChild.size() << " OR Assamblage: " << OR_Assamblage.size();
}
sort(OR_Assamblage.begin(), OR_Assamblage.end());
it = unique(OR_Assamblage.begin(), OR_Assamblage.end());
OR_Assamblage.resize( it - OR_Assamblage.begin() );
MITK_DEBUG << "returning OR vector, size: " << OR_Assamblage.size();
return OR_Assamblage;
}
case 2:
{
//NOT
//get IDs of all fibers
std::vector<long> childResults;
childResults.reserve(this->GetNumFibers());
vtkSmartPointer<vtkDataArray> idSet = m_FiberIdDataSet->GetCellData()->GetArray(FIBER_ID_ARRAY);
MITK_DEBUG << "m_NumOfFib: " << this->GetNumFibers() << " cellIdNum: " << idSet->GetNumberOfTuples();
for(long i=0; i<this->GetNumFibers(); i++)
{
MITK_DEBUG << "i: " << i << " idset: " << idSet->GetTuple(i)[0];
childResults.push_back(idSet->GetTuple(i)[0]);
}
std::sort(childResults.begin(), childResults.end());
std::vector<long> NOT_Assamblage(childResults.size());
//fill it with -1, otherwise 0 will be stored and 0 can also be an ID of fiber!
fill(NOT_Assamblage.begin(), NOT_Assamblage.end(), -1);
std::vector<long>::iterator it;
for (long i=0; i<pfcomp->getNumberOfChildren(); ++i)
{
std::vector<long> tmpChild = ExtractFiberIdSubset(pfcomp->getChildAt(i));
sort(tmpChild.begin(), tmpChild.end());
it = std::set_difference(childResults.begin(), childResults.end(),
tmpChild.begin(), tmpChild.end(),
NOT_Assamblage.begin() );
}
MITK_DEBUG << "resize Vector";
long i=0;
while (NOT_Assamblage[i] != -1){ //-1 represents a placeholder in the array
++i;
}
NOT_Assamblage.resize(i);
return NOT_Assamblage;
}
default:
MITK_DEBUG << "we have an UNDEFINED composition... ERROR" ;
break;
}
}
else
{
- mitk::Geometry2D::ConstPointer pfgeometry = pf->GetGeometry2D();
+ mitk::PlaneGeometry::ConstPointer pfgeometry = pf->GetPlaneGeometry();
const mitk::PlaneGeometry* planeGeometry = dynamic_cast<const mitk::PlaneGeometry*> (pfgeometry.GetPointer());
Vector3D planeNormal = planeGeometry->GetNormal();
planeNormal.Normalize();
Point3D planeOrigin = planeGeometry->GetOrigin();
MITK_DEBUG << "planeOrigin: " << planeOrigin[0] << " | " << planeOrigin[1] << " | " << planeOrigin[2] << endl;
MITK_DEBUG << "planeNormal: " << planeNormal[0] << " | " << planeNormal[1] << " | " << planeNormal[2] << endl;
std::vector<int> PointsOnPlane; // contains all pointIds which are crossing the cutting plane
std::vector<int> PointsInROI; // based on PointsOnPlane, all ROI relevant point IDs are stored here
/* Define cutting plane by ROI (PlanarFigure) */
vtkSmartPointer<vtkPlane> plane = vtkSmartPointer<vtkPlane>::New();
plane->SetOrigin(planeOrigin[0],planeOrigin[1],planeOrigin[2]);
plane->SetNormal(planeNormal[0],planeNormal[1],planeNormal[2]);
/* get all points/fibers cutting the plane */
MITK_DEBUG << "start clipping";
vtkSmartPointer<vtkClipPolyData> clipper = vtkSmartPointer<vtkClipPolyData>::New();
clipper->SetInputData(m_FiberIdDataSet);
clipper->SetClipFunction(plane);
clipper->GenerateClipScalarsOn();
clipper->GenerateClippedOutputOn();
clipper->Update();
vtkSmartPointer<vtkPolyData> clipperout = clipper->GetClippedOutput();
MITK_DEBUG << "end clipping";
MITK_DEBUG << "init and update clipperoutput";
// clipperout->GetPointData()->Initialize();
// clipperout->Update(); //VTK6_TODO
MITK_DEBUG << "init and update clipperoutput completed";
MITK_DEBUG << "STEP 1: find all points which have distance 0 to the given plane";
/*======STEP 1======
* extract all points, which are crossing the plane */
// Scalar values describe the distance between each remaining point to the given plane. Values sorted by point index
vtkSmartPointer<vtkDataArray> distanceList = clipperout->GetPointData()->GetScalars();
vtkIdType sizeOfList = distanceList->GetNumberOfTuples();
PointsOnPlane.reserve(sizeOfList); /* use reserve for high-performant push_back, no hidden copy procedures are processed then!
* size of list can be optimized by reducing allocation, but be aware of iterator and vector size*/
for (int i=0; i<sizeOfList; ++i) {
double *distance = distanceList->GetTuple(i);
// check if point is on plane.
// 0.01 due to some approximation errors when calculating distance
if (distance[0] >= -0.01 && distance[0] <= 0.01)
PointsOnPlane.push_back(i);
}
MITK_DEBUG << "Num Of points on plane: " << PointsOnPlane.size();
MITK_DEBUG << "Step 2: extract Interesting points with respect to given extraction planarFigure";
PointsInROI.reserve(PointsOnPlane.size());
/*=======STEP 2=====
* extract ROI relevant pointIds */
mitk::PlanarCircle::Pointer circleName = mitk::PlanarCircle::New();
mitk::PlanarPolygon::Pointer polyName = mitk::PlanarPolygon::New();
if ( pf->GetNameOfClass() == circleName->GetNameOfClass() )
{
//calculate circle radius
mitk::Point3D V1w = pf->GetWorldControlPoint(0); //centerPoint
mitk::Point3D V2w = pf->GetWorldControlPoint(1); //radiusPoint
double distPF = V1w.EuclideanDistanceTo(V2w);
for (unsigned int i=0; i<PointsOnPlane.size(); i++)
{
//distance between circle radius and given point
double XdistPnt = sqrt((double) (clipperout->GetPoint(PointsOnPlane[i])[0] - V1w[0]) * (clipperout->GetPoint(PointsOnPlane[i])[0] - V1w[0]) +
(clipperout->GetPoint(PointsOnPlane[i])[1] - V1w[1]) * (clipperout->GetPoint(PointsOnPlane[i])[1] - V1w[1]) +
(clipperout->GetPoint(PointsOnPlane[i])[2] - V1w[2]) * (clipperout->GetPoint(PointsOnPlane[i])[2] - V1w[2])) ;
if( XdistPnt <= distPF)
PointsInROI.push_back(PointsOnPlane[i]);
}
}
else if ( pf->GetNameOfClass() == polyName->GetNameOfClass() )
{
//create vtkPolygon using controlpoints from planarFigure polygon
vtkSmartPointer<vtkPolygon> polygonVtk = vtkSmartPointer<vtkPolygon>::New();
//get the control points from pf and insert them to vtkPolygon
unsigned int nrCtrlPnts = pf->GetNumberOfControlPoints();
for (unsigned int i=0; i<nrCtrlPnts; ++i)
{
polygonVtk->GetPoints()->InsertNextPoint((double)pf->GetWorldControlPoint(i)[0], (double)pf->GetWorldControlPoint(i)[1], (double)pf->GetWorldControlPoint(i)[2] );
}
//prepare everything for using pointInPolygon function
double n[3];
polygonVtk->ComputeNormal(polygonVtk->GetPoints()->GetNumberOfPoints(),
static_cast<double*>(polygonVtk->GetPoints()->GetData()->GetVoidPointer(0)), n);
double bounds[6];
polygonVtk->GetPoints()->GetBounds(bounds);
for (unsigned int i=0; i<PointsOnPlane.size(); i++)
{
double checkIn[3] = {clipperout->GetPoint(PointsOnPlane[i])[0], clipperout->GetPoint(PointsOnPlane[i])[1], clipperout->GetPoint(PointsOnPlane[i])[2]};
int isInPolygon = polygonVtk->PointInPolygon(checkIn, polygonVtk->GetPoints()->GetNumberOfPoints()
, static_cast<double*>(polygonVtk->GetPoints()->GetData()->GetVoidPointer(0)), bounds, n);
if( isInPolygon )
PointsInROI.push_back(PointsOnPlane[i]);
}
}
MITK_DEBUG << "Step3: Identify fibers";
// we need to access the fiberId Array, so make sure that this array is available
if (!clipperout->GetCellData()->HasArray(FIBER_ID_ARRAY))
{
MITK_DEBUG << "ERROR: FiberID array does not exist, no correlation between points and fiberIds possible! Make sure calling GenerateFiberIds()";
return FibersInROI; // FibersInRoi is empty then
}
if (PointsInROI.size()<=0)
return FibersInROI;
// prepare a structure where each point id is represented as an indexId.
// vector looks like: | pntId | fiberIdx |
std::vector< long > pointindexFiberMap;
// walk through the whole subline section and create an vector sorted by point index
vtkCellArray *clipperlines = clipperout->GetLines();
clipperlines->InitTraversal();
long numOfLineCells = clipperlines->GetNumberOfCells();
long numofClippedPoints = clipperout->GetNumberOfPoints();
pointindexFiberMap.resize(numofClippedPoints);
//prepare resulting vector
FibersInROI.reserve(PointsInROI.size());
MITK_DEBUG << "\n===== Pointindex based structure initialized ======\n";
// go through resulting "sub"lines which are stored as cells, "i" corresponds to current line id.
for (int i=0, ic=0 ; i<numOfLineCells; i++, ic+=3)
{ //ic is the index counter for the cells hosting the desired information, eg. 2 | 45 | 46. each cell consits of 3 items.
vtkIdType npts;
vtkIdType *pts;
clipperlines->GetCell(ic, npts, pts);
// go through point ids in hosting subline, "j" corresponds to current pointindex in current line i. eg. idx[0]=45; idx[1]=46
for (long j=0; j<npts; j++)
{
// MITK_DEBUG << "writing fiber id: " << clipperout->GetCellData()->GetArray(FIBER_ID_ARRAY)->GetTuple(i)[0] << " to pointId: " << pts[j];
pointindexFiberMap[ pts[j] ] = clipperout->GetCellData()->GetArray(FIBER_ID_ARRAY)->GetTuple(i)[0];
// MITK_DEBUG << "in array: " << pointindexFiberMap[ pts[j] ];
}
}
MITK_DEBUG << "\n===== Pointindex based structure finalized ======\n";
// get all Points in ROI with according fiberID
for (unsigned long k = 0; k < PointsInROI.size(); k++)
{
//MITK_DEBUG << "point " << PointsInROI[k] << " belongs to fiber " << pointindexFiberMap[ PointsInROI[k] ];
if (pointindexFiberMap[ PointsInROI[k] ]<=GetNumFibers() && pointindexFiberMap[ PointsInROI[k] ]>=0)
FibersInROI.push_back(pointindexFiberMap[ PointsInROI[k] ]);
else
MITK_INFO << "ERROR in ExtractFiberIdSubset; impossible fiber id detected";
}
m_PointsRoi = PointsInROI;
}
// detecting fiberId duplicates
MITK_DEBUG << "check for duplicates";
sort(FibersInROI.begin(), FibersInROI.end());
bool hasDuplicats = false;
for(unsigned long i=0; i<FibersInROI.size()-1; ++i)
{
if(FibersInROI[i] == FibersInROI[i+1])
hasDuplicats = true;
}
if(hasDuplicats)
{
std::vector<long>::iterator it;
it = unique (FibersInROI.begin(), FibersInROI.end());
FibersInROI.resize( it - FibersInROI.begin() );
}
return FibersInROI;
}
void mitk::FiberBundleX::UpdateFiberGeometry()
{
vtkSmartPointer<vtkCleanPolyData> cleaner = vtkSmartPointer<vtkCleanPolyData>::New();
cleaner->SetInputData(m_FiberPolyData);
cleaner->PointMergingOff();
cleaner->Update();
m_FiberPolyData = cleaner->GetOutput();
m_FiberLengths.clear();
m_MeanFiberLength = 0;
m_MedianFiberLength = 0;
m_LengthStDev = 0;
m_NumFibers = m_FiberPolyData->GetNumberOfCells();
if (m_NumFibers<=0) // no fibers present; apply default geometry
{
m_MinFiberLength = 0;
m_MaxFiberLength = 0;
mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New();
geometry->SetImageGeometry(true);
float b[] = {0, 1, 0, 1, 0, 1};
geometry->SetFloatBounds(b);
SetGeometry(geometry);
return;
}
float min = itk::NumericTraits<float>::NonpositiveMin();
float max = itk::NumericTraits<float>::max();
float b[] = {max, min, max, min, max, min};
for (int i=0; i<m_FiberPolyData->GetNumberOfCells(); i++)
{
vtkCell* cell = m_FiberPolyData->GetCell(i);
int p = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
float length = 0;
for (int j=0; j<p; j++)
{
// calculate bounding box
double p1[3];
points->GetPoint(j, p1);
if (p1[0]<b[0])
b[0]=p1[0];
if (p1[0]>b[1])
b[1]=p1[0];
if (p1[1]<b[2])
b[2]=p1[1];
if (p1[1]>b[3])
b[3]=p1[1];
if (p1[2]<b[4])
b[4]=p1[2];
if (p1[2]>b[5])
b[5]=p1[2];
// calculate statistics
if (j<p-1)
{
double p2[3];
points->GetPoint(j+1, p2);
float dist = std::sqrt((p1[0]-p2[0])*(p1[0]-p2[0])+(p1[1]-p2[1])*(p1[1]-p2[1])+(p1[2]-p2[2])*(p1[2]-p2[2]));
length += dist;
}
}
m_FiberLengths.push_back(length);
m_MeanFiberLength += length;
if (i==0)
{
m_MinFiberLength = length;
m_MaxFiberLength = length;
}
else
{
if (length<m_MinFiberLength)
m_MinFiberLength = length;
if (length>m_MaxFiberLength)
m_MaxFiberLength = length;
}
}
m_MeanFiberLength /= m_NumFibers;
std::vector< float > sortedLengths = m_FiberLengths;
std::sort(sortedLengths.begin(), sortedLengths.end());
for (int i=0; i<m_NumFibers; i++)
m_LengthStDev += (m_MeanFiberLength-sortedLengths.at(i))*(m_MeanFiberLength-sortedLengths.at(i));
if (m_NumFibers>1)
m_LengthStDev /= (m_NumFibers-1);
else
m_LengthStDev = 0;
m_LengthStDev = std::sqrt(m_LengthStDev);
m_MedianFiberLength = sortedLengths.at(m_NumFibers/2);
// provide some border margin
for(int i=0; i<=4; i+=2)
b[i] -=10;
for(int i=1; i<=5; i+=2)
b[i] +=10;
mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New();
geometry->SetFloatBounds(b);
this->SetGeometry(geometry);
}
std::vector<std::string> mitk::FiberBundleX::GetAvailableColorCodings()
{
std::vector<std::string> availableColorCodings;
int numColors = m_FiberPolyData->GetPointData()->GetNumberOfArrays();
for(int i=0; i<numColors; i++)
{
availableColorCodings.push_back(m_FiberPolyData->GetPointData()->GetArrayName(i));
}
//this controlstructure shall be implemented by the calling method
if (availableColorCodings.empty())
MITK_DEBUG << "no colorcodings available in fiberbundleX";
return availableColorCodings;
}
char* mitk::FiberBundleX::GetCurrentColorCoding()
{
return m_CurrentColorCoding;
}
void mitk::FiberBundleX::SetColorCoding(const char* requestedColorCoding)
{
if (requestedColorCoding==NULL)
return;
MITK_DEBUG << "SetColorCoding:" << requestedColorCoding;
if( strcmp (COLORCODING_ORIENTATION_BASED,requestedColorCoding) == 0 ) {
this->m_CurrentColorCoding = (char*) COLORCODING_ORIENTATION_BASED;
} else if( strcmp (COLORCODING_FA_BASED,requestedColorCoding) == 0 ) {
this->m_CurrentColorCoding = (char*) COLORCODING_FA_BASED;
} else if( strcmp (COLORCODING_CUSTOM,requestedColorCoding) == 0 ) {
this->m_CurrentColorCoding = (char*) COLORCODING_CUSTOM;
} else {
MITK_DEBUG << "FIBERBUNDLE X: UNKNOWN COLORCODING in FIBERBUNDLEX Datastructure";
this->m_CurrentColorCoding = (char*) COLORCODING_CUSTOM; //will cause blank colorcoding of fibers
}
}
itk::Matrix< double, 3, 3 > mitk::FiberBundleX::TransformMatrix(itk::Matrix< double, 3, 3 > m, double rx, double ry, double rz)
{
rx = rx*M_PI/180;
ry = ry*M_PI/180;
rz = rz*M_PI/180;
itk::Matrix< double, 3, 3 > rotX; rotX.SetIdentity();
rotX[1][1] = cos(rx);
rotX[2][2] = rotX[1][1];
rotX[1][2] = -sin(rx);
rotX[2][1] = -rotX[1][2];
itk::Matrix< double, 3, 3 > rotY; rotY.SetIdentity();
rotY[0][0] = cos(ry);
rotY[2][2] = rotY[0][0];
rotY[0][2] = sin(ry);
rotY[2][0] = -rotY[0][2];
itk::Matrix< double, 3, 3 > rotZ; rotZ.SetIdentity();
rotZ[0][0] = cos(rz);
rotZ[1][1] = rotZ[0][0];
rotZ[0][1] = -sin(rz);
rotZ[1][0] = -rotZ[0][1];
itk::Matrix< double, 3, 3 > rot = rotZ*rotY*rotX;
m = rot*m;
return m;
}
itk::Point<float, 3> mitk::FiberBundleX::TransformPoint(vnl_vector_fixed< double, 3 > point, double rx, double ry, double rz, double tx, double ty, double tz)
{
rx = rx*M_PI/180;
ry = ry*M_PI/180;
rz = rz*M_PI/180;
vnl_matrix_fixed< double, 3, 3 > rotX; rotX.set_identity();
rotX[1][1] = cos(rx);
rotX[2][2] = rotX[1][1];
rotX[1][2] = -sin(rx);
rotX[2][1] = -rotX[1][2];
vnl_matrix_fixed< double, 3, 3 > rotY; rotY.set_identity();
rotY[0][0] = cos(ry);
rotY[2][2] = rotY[0][0];
rotY[0][2] = sin(ry);
rotY[2][0] = -rotY[0][2];
vnl_matrix_fixed< double, 3, 3 > rotZ; rotZ.set_identity();
rotZ[0][0] = cos(rz);
rotZ[1][1] = rotZ[0][0];
rotZ[0][1] = -sin(rz);
rotZ[1][0] = -rotZ[0][1];
vnl_matrix_fixed< double, 3, 3 > rot = rotZ*rotY*rotX;
- mitk::Geometry3D::Pointer geom = this->GetGeometry();
+ mitk::BaseGeometry::Pointer geom = this->GetGeometry();
mitk::Point3D center = geom->GetCenter();
point[0] -= center[0];
point[1] -= center[1];
point[2] -= center[2];
point = rot*point;
point[0] += center[0]+tx;
point[1] += center[1]+ty;
point[2] += center[2]+tz;
itk::Point<float, 3> out; out[0] = point[0]; out[1] = point[1]; out[2] = point[2];
return out;
}
void mitk::FiberBundleX::TransformFibers(double rx, double ry, double rz, double tx, double ty, double tz)
{
rx = rx*M_PI/180;
ry = ry*M_PI/180;
rz = rz*M_PI/180;
vnl_matrix_fixed< double, 3, 3 > rotX; rotX.set_identity();
rotX[1][1] = cos(rx);
rotX[2][2] = rotX[1][1];
rotX[1][2] = -sin(rx);
rotX[2][1] = -rotX[1][2];
vnl_matrix_fixed< double, 3, 3 > rotY; rotY.set_identity();
rotY[0][0] = cos(ry);
rotY[2][2] = rotY[0][0];
rotY[0][2] = sin(ry);
rotY[2][0] = -rotY[0][2];
vnl_matrix_fixed< double, 3, 3 > rotZ; rotZ.set_identity();
rotZ[0][0] = cos(rz);
rotZ[1][1] = rotZ[0][0];
rotZ[0][1] = -sin(rz);
rotZ[1][0] = -rotZ[0][1];
vnl_matrix_fixed< double, 3, 3 > rot = rotZ*rotY*rotX;
- mitk::Geometry3D::Pointer geom = this->GetGeometry();
+ mitk::BaseGeometry::Pointer geom = this->GetGeometry();
mitk::Point3D center = geom->GetCenter();
vtkSmartPointer<vtkPoints> vtkNewPoints = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkCellArray> vtkNewCells = vtkSmartPointer<vtkCellArray>::New();
for (int i=0; i<m_NumFibers; i++)
{
vtkCell* cell = m_FiberPolyData->GetCell(i);
int numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
for (int j=0; j<numPoints; j++)
{
double* p = points->GetPoint(j);
vnl_vector_fixed< double, 3 > dir;
dir[0] = p[0]-center[0];
dir[1] = p[1]-center[1];
dir[2] = p[2]-center[2];
dir = rot*dir;
dir[0] += center[0]+tx;
dir[1] += center[1]+ty;
dir[2] += center[2]+tz;
vtkIdType id = vtkNewPoints->InsertNextPoint(dir.data_block());
container->GetPointIds()->InsertNextId(id);
}
vtkNewCells->InsertNextCell(container);
}
m_FiberPolyData = vtkSmartPointer<vtkPolyData>::New();
m_FiberPolyData->SetPoints(vtkNewPoints);
m_FiberPolyData->SetLines(vtkNewCells);
UpdateColorCoding();
UpdateFiberGeometry();
}
void mitk::FiberBundleX::RotateAroundAxis(double x, double y, double z)
{
x = x*M_PI/180;
y = y*M_PI/180;
z = z*M_PI/180;
vnl_matrix_fixed< double, 3, 3 > rotX; rotX.set_identity();
rotX[1][1] = cos(x);
rotX[2][2] = rotX[1][1];
rotX[1][2] = -sin(x);
rotX[2][1] = -rotX[1][2];
vnl_matrix_fixed< double, 3, 3 > rotY; rotY.set_identity();
rotY[0][0] = cos(y);
rotY[2][2] = rotY[0][0];
rotY[0][2] = sin(y);
rotY[2][0] = -rotY[0][2];
vnl_matrix_fixed< double, 3, 3 > rotZ; rotZ.set_identity();
rotZ[0][0] = cos(z);
rotZ[1][1] = rotZ[0][0];
rotZ[0][1] = -sin(z);
rotZ[1][0] = -rotZ[0][1];
- mitk::Geometry3D::Pointer geom = this->GetGeometry();
+ mitk::BaseGeometry::Pointer geom = this->GetGeometry();
mitk::Point3D center = geom->GetCenter();
vtkSmartPointer<vtkPoints> vtkNewPoints = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkCellArray> vtkNewCells = vtkSmartPointer<vtkCellArray>::New();
for (int i=0; i<m_NumFibers; i++)
{
vtkCell* cell = m_FiberPolyData->GetCell(i);
int numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
for (int j=0; j<numPoints; j++)
{
double* p = points->GetPoint(j);
vnl_vector_fixed< double, 3 > dir;
dir[0] = p[0]-center[0];
dir[1] = p[1]-center[1];
dir[2] = p[2]-center[2];
dir = rotZ*rotY*rotX*dir;
dir[0] += center[0];
dir[1] += center[1];
dir[2] += center[2];
vtkIdType id = vtkNewPoints->InsertNextPoint(dir.data_block());
container->GetPointIds()->InsertNextId(id);
}
vtkNewCells->InsertNextCell(container);
}
m_FiberPolyData = vtkSmartPointer<vtkPolyData>::New();
m_FiberPolyData->SetPoints(vtkNewPoints);
m_FiberPolyData->SetLines(vtkNewCells);
UpdateColorCoding();
UpdateFiberGeometry();
}
void mitk::FiberBundleX::ScaleFibers(double x, double y, double z)
{
MITK_INFO << "Scaling fibers";
boost::progress_display disp(m_NumFibers);
- mitk::Geometry3D* geom = this->GetGeometry();
+ mitk::BaseGeometry* geom = this->GetGeometry();
mitk::Point3D c = geom->GetCenter();
vtkSmartPointer<vtkPoints> vtkNewPoints = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkCellArray> vtkNewCells = vtkSmartPointer<vtkCellArray>::New();
for (int i=0; i<m_NumFibers; i++)
{
++disp ;
vtkCell* cell = m_FiberPolyData->GetCell(i);
int numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
for (int j=0; j<numPoints; j++)
{
double* p = points->GetPoint(j);
p[0] -= c[0]; p[1] -= c[1]; p[2] -= c[2];
p[0] *= x;
p[1] *= y;
p[2] *= z;
p[0] += c[0]; p[1] += c[1]; p[2] += c[2];
vtkIdType id = vtkNewPoints->InsertNextPoint(p);
container->GetPointIds()->InsertNextId(id);
}
vtkNewCells->InsertNextCell(container);
}
m_FiberPolyData = vtkSmartPointer<vtkPolyData>::New();
m_FiberPolyData->SetPoints(vtkNewPoints);
m_FiberPolyData->SetLines(vtkNewCells);
UpdateColorCoding();
UpdateFiberGeometry();
}
void mitk::FiberBundleX::TranslateFibers(double x, double y, double z)
{
vtkSmartPointer<vtkPoints> vtkNewPoints = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkCellArray> vtkNewCells = vtkSmartPointer<vtkCellArray>::New();
for (int i=0; i<m_NumFibers; i++)
{
vtkCell* cell = m_FiberPolyData->GetCell(i);
int numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
for (int j=0; j<numPoints; j++)
{
double* p = points->GetPoint(j);
p[0] += x;
p[1] += y;
p[2] += z;
vtkIdType id = vtkNewPoints->InsertNextPoint(p);
container->GetPointIds()->InsertNextId(id);
}
vtkNewCells->InsertNextCell(container);
}
m_FiberPolyData = vtkSmartPointer<vtkPolyData>::New();
m_FiberPolyData->SetPoints(vtkNewPoints);
m_FiberPolyData->SetLines(vtkNewCells);
UpdateColorCoding();
UpdateFiberGeometry();
}
void mitk::FiberBundleX::MirrorFibers(unsigned int axis)
{
if (axis>2)
return;
MITK_INFO << "Mirroring fibers";
boost::progress_display disp(m_NumFibers);
vtkSmartPointer<vtkPoints> vtkNewPoints = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkCellArray> vtkNewCells = vtkSmartPointer<vtkCellArray>::New();
for (int i=0; i<m_NumFibers; i++)
{
++disp;
vtkCell* cell = m_FiberPolyData->GetCell(i);
int numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
for (int j=0; j<numPoints; j++)
{
double* p = points->GetPoint(j);
p[axis] = -p[axis];
vtkIdType id = vtkNewPoints->InsertNextPoint(p);
container->GetPointIds()->InsertNextId(id);
}
vtkNewCells->InsertNextCell(container);
}
m_FiberPolyData = vtkSmartPointer<vtkPolyData>::New();
m_FiberPolyData->SetPoints(vtkNewPoints);
m_FiberPolyData->SetLines(vtkNewCells);
UpdateColorCoding();
UpdateFiberGeometry();
}
bool mitk::FiberBundleX::ApplyCurvatureThreshold(float minRadius, bool deleteFibers)
{
if (minRadius<0)
return true;
vtkSmartPointer<vtkPoints> vtkNewPoints = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkCellArray> vtkNewCells = vtkSmartPointer<vtkCellArray>::New();
MITK_INFO << "Applying curvature threshold";
boost::progress_display disp(m_FiberPolyData->GetNumberOfCells());
for (int i=0; i<m_FiberPolyData->GetNumberOfCells(); i++)
{
++disp ;
vtkCell* cell = m_FiberPolyData->GetCell(i);
int numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
// calculate curvatures
vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
for (int j=0; j<numPoints-2; j++)
{
double p1[3];
points->GetPoint(j, p1);
double p2[3];
points->GetPoint(j+1, p2);
double p3[3];
points->GetPoint(j+2, p3);
vnl_vector_fixed< float, 3 > v1, v2, v3;
v1[0] = p2[0]-p1[0];
v1[1] = p2[1]-p1[1];
v1[2] = p2[2]-p1[2];
v2[0] = p3[0]-p2[0];
v2[1] = p3[1]-p2[1];
v2[2] = p3[2]-p2[2];
v3[0] = p1[0]-p3[0];
v3[1] = p1[1]-p3[1];
v3[2] = p1[2]-p3[2];
float a = v1.magnitude();
float b = v2.magnitude();
float c = v3.magnitude();
float r = a*b*c/std::sqrt((a+b+c)*(a+b-c)*(b+c-a)*(a-b+c)); // radius of triangle via Heron's formula (area of triangle)
vtkIdType id = vtkNewPoints->InsertNextPoint(p1);
container->GetPointIds()->InsertNextId(id);
if (deleteFibers && r<minRadius)
break;
if (r<minRadius)
{
j += 2;
vtkNewCells->InsertNextCell(container);
container = vtkSmartPointer<vtkPolyLine>::New();
}
else if (j==numPoints-3)
{
id = vtkNewPoints->InsertNextPoint(p2);
container->GetPointIds()->InsertNextId(id);
id = vtkNewPoints->InsertNextPoint(p3);
container->GetPointIds()->InsertNextId(id);
vtkNewCells->InsertNextCell(container);
}
}
}
if (vtkNewCells->GetNumberOfCells()<=0)
return false;
m_FiberPolyData = vtkSmartPointer<vtkPolyData>::New();
m_FiberPolyData->SetPoints(vtkNewPoints);
m_FiberPolyData->SetLines(vtkNewCells);
UpdateColorCoding();
UpdateFiberGeometry();
return true;
}
bool mitk::FiberBundleX::RemoveShortFibers(float lengthInMM)
{
MITK_INFO << "Removing short fibers";
if (lengthInMM<=0 || lengthInMM<m_MinFiberLength)
{
MITK_INFO << "No fibers shorter than " << lengthInMM << " mm found!";
return true;
}
if (lengthInMM>m_MaxFiberLength) // can't remove all fibers
{
MITK_WARN << "Process aborted. No fibers would be left!";
return false;
}
vtkSmartPointer<vtkPoints> vtkNewPoints = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkCellArray> vtkNewCells = vtkSmartPointer<vtkCellArray>::New();
float min = m_MaxFiberLength;
boost::progress_display disp(m_NumFibers);
for (int i=0; i<m_NumFibers; i++)
{
++disp;
vtkCell* cell = m_FiberPolyData->GetCell(i);
int numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
if (m_FiberLengths.at(i)>=lengthInMM)
{
vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
for (int j=0; j<numPoints; j++)
{
double* p = points->GetPoint(j);
vtkIdType id = vtkNewPoints->InsertNextPoint(p);
container->GetPointIds()->InsertNextId(id);
}
vtkNewCells->InsertNextCell(container);
if (m_FiberLengths.at(i)<min)
min = m_FiberLengths.at(i);
}
}
if (vtkNewCells->GetNumberOfCells()<=0)
return false;
m_FiberPolyData = vtkSmartPointer<vtkPolyData>::New();
m_FiberPolyData->SetPoints(vtkNewPoints);
m_FiberPolyData->SetLines(vtkNewCells);
UpdateColorCoding();
UpdateFiberGeometry();
return true;
}
bool mitk::FiberBundleX::RemoveLongFibers(float lengthInMM)
{
if (lengthInMM<=0 || lengthInMM>m_MaxFiberLength)
return true;
if (lengthInMM<m_MinFiberLength) // can't remove all fibers
return false;
vtkSmartPointer<vtkPoints> vtkNewPoints = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkCellArray> vtkNewCells = vtkSmartPointer<vtkCellArray>::New();
MITK_INFO << "Removing long fibers";
boost::progress_display disp(m_NumFibers);
for (int i=0; i<m_NumFibers; i++)
{
++disp;
vtkCell* cell = m_FiberPolyData->GetCell(i);
int numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
if (m_FiberLengths.at(i)<=lengthInMM)
{
vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
for (int j=0; j<numPoints; j++)
{
double* p = points->GetPoint(j);
vtkIdType id = vtkNewPoints->InsertNextPoint(p);
container->GetPointIds()->InsertNextId(id);
}
vtkNewCells->InsertNextCell(container);
}
}
if (vtkNewCells->GetNumberOfCells()<=0)
return false;
m_FiberPolyData = vtkSmartPointer<vtkPolyData>::New();
m_FiberPolyData->SetPoints(vtkNewPoints);
m_FiberPolyData->SetLines(vtkNewCells);
UpdateColorCoding();
UpdateFiberGeometry();
return true;
}
void mitk::FiberBundleX::DoFiberSmoothing(float pointDistance, double tension, double continuity, double bias )
{
if (pointDistance<=0)
return;
vtkSmartPointer<vtkPoints> vtkSmoothPoints = vtkSmartPointer<vtkPoints>::New(); //in smoothpoints the interpolated points representing a fiber are stored.
//in vtkcells all polylines are stored, actually all id's of them are stored
vtkSmartPointer<vtkCellArray> vtkSmoothCells = vtkSmartPointer<vtkCellArray>::New(); //cellcontainer for smoothed lines
vtkIdType pointHelperCnt = 0;
MITK_INFO << "Smoothing fibers";
boost::progress_display disp(m_NumFibers);
for (int i=0; i<m_NumFibers; i++)
{
++disp;
vtkCell* cell = m_FiberPolyData->GetCell(i);
int numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
vtkSmartPointer<vtkPoints> newPoints = vtkSmartPointer<vtkPoints>::New();
for (int j=0; j<numPoints; j++)
newPoints->InsertNextPoint(points->GetPoint(j));
float length = m_FiberLengths.at(i);
int sampling = std::ceil(length/pointDistance);
vtkSmartPointer<vtkKochanekSpline> xSpline = vtkSmartPointer<vtkKochanekSpline>::New();
vtkSmartPointer<vtkKochanekSpline> ySpline = vtkSmartPointer<vtkKochanekSpline>::New();
vtkSmartPointer<vtkKochanekSpline> zSpline = vtkSmartPointer<vtkKochanekSpline>::New();
xSpline->SetDefaultBias(bias); xSpline->SetDefaultTension(tension); xSpline->SetDefaultContinuity(continuity);
ySpline->SetDefaultBias(bias); ySpline->SetDefaultTension(tension); ySpline->SetDefaultContinuity(continuity);
zSpline->SetDefaultBias(bias); zSpline->SetDefaultTension(tension); zSpline->SetDefaultContinuity(continuity);
vtkSmartPointer<vtkParametricSpline> spline = vtkSmartPointer<vtkParametricSpline>::New();
spline->SetXSpline(xSpline);
spline->SetYSpline(ySpline);
spline->SetZSpline(zSpline);
spline->SetPoints(newPoints);
vtkSmartPointer<vtkParametricFunctionSource> functionSource = vtkSmartPointer<vtkParametricFunctionSource>::New();
functionSource->SetParametricFunction(spline);
functionSource->SetUResolution(sampling);
functionSource->SetVResolution(sampling);
functionSource->SetWResolution(sampling);
functionSource->Update();
vtkPolyData* outputFunction = functionSource->GetOutput();
vtkPoints* tmpSmoothPnts = outputFunction->GetPoints(); //smoothPoints of current fiber
vtkSmartPointer<vtkPolyLine> smoothLine = vtkSmartPointer<vtkPolyLine>::New();
smoothLine->GetPointIds()->SetNumberOfIds(tmpSmoothPnts->GetNumberOfPoints());
for (int j=0; j<smoothLine->GetNumberOfPoints(); j++)
{
smoothLine->GetPointIds()->SetId(j, j+pointHelperCnt);
vtkSmoothPoints->InsertNextPoint(tmpSmoothPnts->GetPoint(j));
}
vtkSmoothCells->InsertNextCell(smoothLine);
pointHelperCnt += tmpSmoothPnts->GetNumberOfPoints();
}
m_FiberPolyData = vtkSmartPointer<vtkPolyData>::New();
m_FiberPolyData->SetPoints(vtkSmoothPoints);
m_FiberPolyData->SetLines(vtkSmoothCells);
UpdateColorCoding();
UpdateFiberGeometry();
m_FiberSampling = 10/pointDistance;
}
void mitk::FiberBundleX::DoFiberSmoothing(float pointDistance)
{
DoFiberSmoothing(pointDistance, 0, 0, 0 );
}
// Resample fiber to get equidistant points
void mitk::FiberBundleX::ResampleFibers(float pointDistance)
{
if (pointDistance<=0.00001)
return;
vtkSmartPointer<vtkPolyData> newPoly = vtkSmartPointer<vtkPolyData>::New();
vtkSmartPointer<vtkCellArray> newCellArray = vtkSmartPointer<vtkCellArray>::New();
vtkSmartPointer<vtkPoints> newPoints = vtkSmartPointer<vtkPoints>::New();
int numberOfLines = m_NumFibers;
MITK_INFO << "Resampling fibers";
boost::progress_display disp(m_NumFibers);
for (int i=0; i<numberOfLines; i++)
{
++disp;
vtkCell* cell = m_FiberPolyData->GetCell(i);
int numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
double* point = points->GetPoint(0);
vtkIdType pointId = newPoints->InsertNextPoint(point);
container->GetPointIds()->InsertNextId(pointId);
float dtau = 0;
int cur_p = 1;
itk::Vector<float,3> dR;
float normdR = 0;
for (;;)
{
while (dtau <= pointDistance && cur_p < numPoints)
{
itk::Vector<float,3> v1;
point = points->GetPoint(cur_p-1);
v1[0] = point[0];
v1[1] = point[1];
v1[2] = point[2];
itk::Vector<float,3> v2;
point = points->GetPoint(cur_p);
v2[0] = point[0];
v2[1] = point[1];
v2[2] = point[2];
dR = v2 - v1;
normdR = std::sqrt(dR.GetSquaredNorm());
dtau += normdR;
cur_p++;
}
if (dtau >= pointDistance)
{
itk::Vector<float,3> v1;
point = points->GetPoint(cur_p-1);
v1[0] = point[0];
v1[1] = point[1];
v1[2] = point[2];
itk::Vector<float,3> v2 = v1 - dR*( (dtau-pointDistance)/normdR );
pointId = newPoints->InsertNextPoint(v2.GetDataPointer());
container->GetPointIds()->InsertNextId(pointId);
}
else
{
point = points->GetPoint(numPoints-1);
pointId = newPoints->InsertNextPoint(point);
container->GetPointIds()->InsertNextId(pointId);
break;
}
dtau = dtau-pointDistance;
}
newCellArray->InsertNextCell(container);
}
newPoly->SetPoints(newPoints);
newPoly->SetLines(newCellArray);
m_FiberPolyData = newPoly;
UpdateFiberGeometry();
UpdateColorCoding();
m_FiberSampling = 10/pointDistance;
}
// reapply selected colorcoding in case polydata structure has changed
void mitk::FiberBundleX::UpdateColorCoding()
{
char* cc = GetCurrentColorCoding();
if( strcmp (COLORCODING_ORIENTATION_BASED,cc) == 0 )
DoColorCodingOrientationBased();
else if( strcmp (COLORCODING_FA_BASED,cc) == 0 )
DoColorCodingFaBased();
}
// reapply selected colorcoding in case polydata structure has changed
bool mitk::FiberBundleX::Equals(mitk::FiberBundleX* fib, double eps)
{
if (fib==NULL)
{
MITK_INFO << "Reference bundle is NULL!";
return false;
}
if (m_NumFibers!=fib->GetNumFibers())
{
MITK_INFO << "Unequal number of fibers!";
MITK_INFO << m_NumFibers << " vs. " << fib->GetNumFibers();
return false;
}
for (int i=0; i<m_NumFibers; i++)
{
vtkCell* cell = m_FiberPolyData->GetCell(i);
int numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
vtkCell* cell2 = fib->GetFiberPolyData()->GetCell(i);
int numPoints2 = cell2->GetNumberOfPoints();
vtkPoints* points2 = cell2->GetPoints();
if (numPoints2!=numPoints)
{
MITK_INFO << "Unequal number of points in fiber " << i << "!";
MITK_INFO << numPoints2 << " vs. " << numPoints;
return false;
}
for (int j=0; j<numPoints; j++)
{
double* p1 = points->GetPoint(j);
double* p2 = points2->GetPoint(j);
if (fabs(p1[0]-p2[0])>eps || fabs(p1[1]-p2[1])>eps || fabs(p1[2]-p2[2])>eps)
{
MITK_INFO << "Unequal points in fiber " << i << " at position " << j << "!";
MITK_INFO << "p1: " << p1[0] << ", " << p1[1] << ", " << p1[2];
MITK_INFO << "p2: " << p2[0] << ", " << p2[1] << ", " << p2[2];
return false;
}
}
}
return true;
}
/* ESSENTIAL IMPLEMENTATION OF SUPERCLASS METHODS */
void mitk::FiberBundleX::UpdateOutputInformation()
{
}
void mitk::FiberBundleX::SetRequestedRegionToLargestPossibleRegion()
{
}
bool mitk::FiberBundleX::RequestedRegionIsOutsideOfTheBufferedRegion()
{
return false;
}
bool mitk::FiberBundleX::VerifyRequestedRegion()
{
return true;
}
void mitk::FiberBundleX::SetRequestedRegion(const itk::DataObject* )
{
}
diff --git a/Modules/DiffusionImaging/MiniApps/CopyGeometry.cpp b/Modules/DiffusionImaging/MiniApps/CopyGeometry.cpp
index e7e3d05290..db0770bfe4 100755
--- a/Modules/DiffusionImaging/MiniApps/CopyGeometry.cpp
+++ b/Modules/DiffusionImaging/MiniApps/CopyGeometry.cpp
@@ -1,91 +1,91 @@
/*===================================================================
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 "MiniAppManager.h"
#include <mitkImageCast.h>
#include <mitkDiffusionImage.h>
#include <mitkBaseDataIOFactory.h>
#include <mitkIOUtil.h>
#include <mitkNrrdDiffusionImageWriter.h>
#include "ctkCommandLineParser.h"
using namespace mitk;
#include "ctkCommandLineParser.h"
int CopyGeometry(int argc, char* argv[])
{
ctkCommandLineParser parser;
parser.setArgumentPrefix("--", "-");
parser.addArgument("in", "i", ctkCommandLineParser::String, "input image", us::Any(), false);
parser.addArgument("ref", "r", ctkCommandLineParser::String, "reference image", us::Any(), false);
parser.addArgument("out", "o", ctkCommandLineParser::String, "output image", us::Any(), false);
map<string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0)
return EXIT_FAILURE;
// mandatory arguments
string imageName = us::any_cast<string>(parsedArgs["in"]);
string refImage = us::any_cast<string>(parsedArgs["ref"]);
string outImage = us::any_cast<string>(parsedArgs["out"]);
try
{
MITK_INFO << "Loading image " << imageName;
const std::string s1="", s2="";
std::vector<BaseData::Pointer> infile = BaseDataIO::LoadBaseDataFromFile( refImage, s1, s2, false );
Image::Pointer source = dynamic_cast<Image*>(infile.at(0).GetPointer());
infile = BaseDataIO::LoadBaseDataFromFile( imageName, s1, s2, false );
Image::Pointer target = dynamic_cast<Image*>(infile.at(0).GetPointer());
- mitk::Geometry3D* s_geom = source->GetGeometry();
- mitk::Geometry3D* t_geom = target->GetGeometry();
+ mitk::BaseGeometry* s_geom = source->GetGeometry();
+ mitk::BaseGeometry* t_geom = target->GetGeometry();
t_geom->SetIndexToWorldTransform(s_geom->GetIndexToWorldTransform());
target->SetGeometry(t_geom);
if ( dynamic_cast<DiffusionImage<short>*>(target.GetPointer()) )
{
MITK_INFO << "Writing " << outImage;
DiffusionImage<short>::Pointer dwi = dynamic_cast<DiffusionImage<short>*>(target.GetPointer());
NrrdDiffusionImageWriter<short>::Pointer writer = NrrdDiffusionImageWriter<short>::New();
writer->SetFileName(outImage);
writer->SetInput(dwi);
writer->Update();
}
else
mitk::IOUtil::SaveImage(target, outImage);
}
catch (itk::ExceptionObject e)
{
MITK_INFO << e;
return EXIT_FAILURE;
}
catch (std::exception e)
{
MITK_INFO << e.what();
return EXIT_FAILURE;
}
catch (...)
{
MITK_INFO << "ERROR!?!";
return EXIT_FAILURE;
}
MITK_INFO << "DONE";
return EXIT_SUCCESS;
}
RegisterDiffusionMiniApp(CopyGeometry);
diff --git a/Modules/DiffusionImaging/MiniApps/ExtractImageStatistics.cpp b/Modules/DiffusionImaging/MiniApps/ExtractImageStatistics.cpp
index 1f47a6b043..06ad8f9597 100644
--- a/Modules/DiffusionImaging/MiniApps/ExtractImageStatistics.cpp
+++ b/Modules/DiffusionImaging/MiniApps/ExtractImageStatistics.cpp
@@ -1,121 +1,121 @@
/*===================================================================
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 "MiniAppManager.h"
#include "ctkCommandLineParser.h"
#include "mitkImage.h"
#include "mitkImageStatisticsCalculator.h"
#include "mitkIOUtil.h"
#include <iostream>
#include <usAny.h>
#include <fstream>
int ExtractImageStatistics(int argc, char* argv[])
{
ctkCommandLineParser parser;
parser.setArgumentPrefix("--", "-");
parser.addArgument("help", "h", ctkCommandLineParser::String, "Show this help text");
parser.addArgument("input", "i", ctkCommandLineParser::String, "input image", us::Any(),false);
parser.addArgument("mask", "m", ctkCommandLineParser::String, "mask image / roi image denotin area on which statistics are calculated", us::Any(),false);
parser.addArgument("out", "o", ctkCommandLineParser::String, "output file (default: filenameOfRoi.nrrd_statistics.txt)", us::Any());
map<string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0 || parsedArgs.count("help") || parsedArgs.count("h"))
{
std::cout << "\n\n MiniApp Description: \nCalculates statistics on the supplied image using given mask." << endl;
std::cout << "Output is written to the designated output file in this order:" << endl;
std::cout << "Mean, Standard Deviation, RMS, Max, Min, Number of Voxels, Volume [mm3]" << endl;
std::cout << "\n\n Parameters:"<< endl;
std::cout << parser.helpText();
return EXIT_SUCCESS;
}
// Parameters:
bool ignoreZeroValues = false;
unsigned int timeStep = 0;
std::string inputImageFile = us::any_cast<string>(parsedArgs["input"]);
std::string maskImageFile = us::any_cast<string>(parsedArgs["mask"]);
std::string outFile;
if (parsedArgs.count("out") || parsedArgs.count("o") )
outFile = us::any_cast<string>(parsedArgs["out"]);
else
outFile = inputImageFile + "_statistics.txt";
// Load image and mask
mitk::Image::Pointer maskImage = mitk::IOUtil::LoadImage(maskImageFile);
mitk::Image::Pointer inputImage = mitk::IOUtil::LoadImage(inputImageFile);
// Calculate statistics
mitk::ImageStatisticsCalculator::Statistics statisticsStruct;
mitk::ImageStatisticsCalculator::Pointer calculator = mitk::ImageStatisticsCalculator::New();
try
{
calculator->SetImage(inputImage);
calculator->SetImageMask(maskImage);
calculator->SetMaskingModeToImage();
}
catch( const itk::ExceptionObject& e)
{
MITK_ERROR << "Statistic Calculation Failed - ITK Exception:" << e.what();
return -1;
}
calculator->SetDoIgnorePixelValue(ignoreZeroValues);
calculator->SetIgnorePixelValue(0);
try
{
calculator->ComputeStatistics(timeStep);
}
catch ( mitk::Exception& e)
{
MITK_ERROR<< "MITK Exception: " << e.what();
return -1;
}
statisticsStruct = calculator->GetStatistics(timeStep);
// Calculate Volume
double volume = 0;
- const mitk::Geometry3D *geometry = inputImage->GetGeometry();
+ const mitk::BaseGeometry *geometry = inputImage->GetGeometry();
if ( geometry != NULL )
{
const mitk::Vector3D &spacing = inputImage->GetGeometry()->GetSpacing();
volume = spacing[0] * spacing[1] * spacing[2] * (double) statisticsStruct.N;
}
// Write Results to file
std::ofstream output;
output.open(outFile.c_str());
output << statisticsStruct.Mean << " , ";
output << statisticsStruct.Sigma << " , ";
output << statisticsStruct.RMS << " , ";
output << statisticsStruct.Max << " , ";
output << statisticsStruct.Min << " , ";
output << statisticsStruct.N << " , ";
output << volume << "\n";
output.flush();
output.close();
return 0;
}
RegisterDiffusionMiniApp(ExtractImageStatistics);
diff --git a/Modules/DiffusionImaging/Quantification/IODataStructures/TbssImages/mitkNrrdTbssRoiImageReader.cpp b/Modules/DiffusionImaging/Quantification/IODataStructures/TbssImages/mitkNrrdTbssRoiImageReader.cpp
index c97c142123..b8cbc4de9e 100644
--- a/Modules/DiffusionImaging/Quantification/IODataStructures/TbssImages/mitkNrrdTbssRoiImageReader.cpp
+++ b/Modules/DiffusionImaging/Quantification/IODataStructures/TbssImages/mitkNrrdTbssRoiImageReader.cpp
@@ -1,356 +1,356 @@
/*===================================================================
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 __mitkNrrdTbssRoiReader_cpp
#define __mitkNrrdTbssRoiReader_cpp
#include "mitkNrrdTbssRoiImageReader.h"
#include "itkImageFileReader.h"
#include "itkMetaDataObject.h"
#include "itkNrrdImageIO.h"
#include "itkNiftiImageIO.h"
#include <itkImageFileWriter.h>
#include <iostream>
#include <fstream>
#include "itksys/SystemTools.hxx"
namespace mitk
{
void NrrdTbssRoiImageReader
::GenerateData()
{
try
{
// Change locale if needed
const std::string& locale = "C";
const std::string& currLocale = setlocale( LC_ALL, NULL );
if ( locale.compare(currLocale)!=0 )
{
try
{
MITK_INFO << " ** Changing locale from " << setlocale(LC_ALL, NULL) << " to '" << locale << "'";
setlocale(LC_ALL, locale.c_str());
}
catch(...)
{
MITK_INFO << "Could not set locale " << locale;
}
}
// READ IMAGE INFORMATION
const unsigned int MINDIM = 3;
const unsigned int MAXDIM = 4;
MITK_INFO << "loading " << m_FileName << " via mitk::NrrdTbssImageReader... " << std::endl;
// Check to see if we can read the file given the name or prefix
if ( m_FileName == "" )
{
itkWarningMacro( << "Filename is empty!" )
return;
}
itk::NrrdImageIO::Pointer imageIO = itk::NrrdImageIO::New();
imageIO->SetFileName( m_FileName.c_str() );
imageIO->ReadImageInformation();
unsigned int ndim = imageIO->GetNumberOfDimensions();
if ( ndim < MINDIM || ndim > MAXDIM )
{
itkWarningMacro( << "Sorry, only dimensions 3 is supported. The given file has " << ndim << " dimensions!" )
return;
}
itk::ImageIORegion ioRegion( ndim );
itk::ImageIORegion::SizeType ioSize = ioRegion.GetSize();
itk::ImageIORegion::IndexType ioStart = ioRegion.GetIndex();
unsigned int dimensions[ MAXDIM ];
dimensions[ 0 ] = 0;
dimensions[ 1 ] = 0;
dimensions[ 2 ] = 0;
dimensions[ 3 ] = 0;
ScalarType spacing[ MAXDIM ];
spacing[ 0 ] = 1.0f;
spacing[ 1 ] = 1.0f;
spacing[ 2 ] = 1.0f;
spacing[ 3 ] = 1.0f;
Point3D origin;
origin.Fill(0);
unsigned int i;
for ( i = 0; i < ndim ; ++i )
{
ioStart[ i ] = 0;
ioSize[ i ] = imageIO->GetDimensions( i );
if(i<MAXDIM)
{
dimensions[ i ] = imageIO->GetDimensions( i );
spacing[ i ] = imageIO->GetSpacing( i );
if(spacing[ i ] <= 0)
spacing[ i ] = 1.0f;
}
if(i<3)
{
origin[ i ] = imageIO->GetOrigin( i );
}
}
ioRegion.SetSize( ioSize );
ioRegion.SetIndex( ioStart );
MITK_INFO << "ioRegion: " << ioRegion << std::endl;
imageIO->SetIORegion( ioRegion );
void* buffer = new unsigned char[imageIO->GetImageSizeInBytes()];
imageIO->Read( buffer );
//mitk::Image::Pointer static_cast<OutputType*>(this->GetOutput())image = mitk::Image::New();
if((ndim==4) && (dimensions[3]<=1))
ndim = 3;
if((ndim==3) && (dimensions[2]<=1))
ndim = 2;
static_cast<OutputType*>(this->GetPrimaryOutput())->Initialize( MakePixelType(imageIO), ndim, dimensions );
static_cast<OutputType*>(this->GetPrimaryOutput())->SetImportChannel( buffer, 0, Image::ManageMemory );
// access direction of itk::Image and include spacing
mitk::Matrix3D matrix;
matrix.SetIdentity();
unsigned int j, itkDimMax3 = (ndim >= 3? 3 : ndim);
for ( i=0; i < itkDimMax3; ++i)
for( j=0; j < itkDimMax3; ++j )
matrix[i][j] = imageIO->GetDirection(j)[i];
// re-initialize PlaneGeometry with origin and direction
PlaneGeometry* planeGeometry = static_cast<PlaneGeometry*>
(static_cast<OutputType*>
- (this->GetPrimaryOutput())->GetSlicedGeometry(0)->GetGeometry2D(0));
+ (this->GetPrimaryOutput())->GetSlicedGeometry(0)->GetPlaneGeometry(0));
planeGeometry->SetOrigin(origin);
planeGeometry->GetIndexToWorldTransform()->SetMatrix(matrix);
// re-initialize SlicedGeometry3D
SlicedGeometry3D* slicedGeometry = static_cast<OutputType*>(this->GetPrimaryOutput())->GetSlicedGeometry(0);
slicedGeometry->InitializeEvenlySpaced(planeGeometry, static_cast<OutputType*>(this->GetPrimaryOutput())->GetDimension(2));
slicedGeometry->SetSpacing(spacing);
// re-initialize TimeGeometry
dynamic_cast<ProportionalTimeGeometry *>(static_cast<OutputType*>(this->GetPrimaryOutput())->GetTimeGeometry())->Initialize(slicedGeometry, static_cast<OutputType*>(this->GetOutput(0))->GetDimension(3));
buffer = NULL;
MITK_INFO << "number of image components: "<< static_cast<OutputType*>(this->GetPrimaryOutput())->GetPixelType().GetNumberOfComponents() << std::endl;
// READ TBSS HEADER INFORMATION
ImageType::Pointer img;
std::string ext = itksys::SystemTools::GetFilenameLastExtension(m_FileName);
ext = itksys::SystemTools::LowerCase(ext);
if (ext == ".roi")
{
typedef itk::ImageFileReader<ImageType> FileReaderType;
FileReaderType::Pointer reader = FileReaderType::New();
reader->SetFileName(this->m_FileName);
reader->SetImageIO(imageIO);
reader->Update();
img = reader->GetOutput();
static_cast<OutputType*>(this->GetPrimaryOutput())->SetImage(img);
itk::MetaDataDictionary imgMetaDictionary = img->GetMetaDataDictionary();
ReadRoiInfo(imgMetaDictionary);
}
// RESET LOCALE
try
{
MITK_INFO << " ** Changing locale back from " << setlocale(LC_ALL, NULL) << " to '" << currLocale << "'";
setlocale(LC_ALL, currLocale.c_str());
}
catch(...)
{
MITK_INFO << "Could not reset locale " << currLocale;
}
MITK_INFO << "...finished!" << std::endl;
}
catch(std::exception& e)
{
MITK_INFO << "Std::Exception while reading file!!";
MITK_INFO << e.what();
throw itk::ImageFileReaderException(__FILE__, __LINE__, e.what());
}
catch(...)
{
MITK_INFO << "Exception while reading file!!";
throw itk::ImageFileReaderException(__FILE__, __LINE__, "Sorry, an error occurred while reading the requested vessel tree file!");
}
}
void NrrdTbssRoiImageReader
::ReadRoiInfo(itk::MetaDataDictionary dict)
{
std::vector<std::string> imgMetaKeys = dict.GetKeys();
std::vector<std::string>::const_iterator itKey = imgMetaKeys.begin();
std::string metaString;
std::vector< itk::Index<3> > roi;
for (; itKey != imgMetaKeys.end(); itKey ++)
{
double x,y,z;
itk::Index<3> ix;
itk::ExposeMetaData<std::string> (dict, *itKey, metaString);
if (itKey->find("ROI_index") != std::string::npos)
{
MITK_INFO << *itKey << " ---> " << metaString;
sscanf(metaString.c_str(), "%lf %lf %lf\n", &x, &y, &z);
ix[0] = x; ix[1] = y; ix[2] = z;
roi.push_back(ix);
}
else if(itKey->find("preprocessed FA") != std::string::npos)
{
MITK_INFO << *itKey << " ---> " << metaString;
static_cast<OutputType*>(this->GetPrimaryOutput())->SetPreprocessedFA(true);
static_cast<OutputType*>(this->GetPrimaryOutput())->SetPreprocessedFAFile(metaString);
}
// Name of structure
if (itKey->find("structure") != std::string::npos)
{
MITK_INFO << *itKey << " ---> " << metaString;
static_cast<OutputType*>(this->GetPrimaryOutput())->SetStructure(metaString);
}
}
static_cast<OutputType*>(this->GetPrimaryOutput())->SetRoi(roi);
}
const char* NrrdTbssRoiImageReader
::GetFileName() const
{
return m_FileName.c_str();
}
void NrrdTbssRoiImageReader
::SetFileName(const char* aFileName)
{
m_FileName = aFileName;
}
const char* NrrdTbssRoiImageReader
::GetFilePrefix() const
{
return m_FilePrefix.c_str();
}
void NrrdTbssRoiImageReader
::SetFilePrefix(const char* aFilePrefix)
{
m_FilePrefix = aFilePrefix;
}
const char* NrrdTbssRoiImageReader
::GetFilePattern() const
{
return m_FilePattern.c_str();
}
void NrrdTbssRoiImageReader
::SetFilePattern(const char* aFilePattern)
{
m_FilePattern = aFilePattern;
}
bool NrrdTbssRoiImageReader
::CanReadFile(const std::string filename, const std::string filePrefix, const std::string filePattern)
{
// First check the extension
if( filename == "" )
return false;
// check if image is serie
if( filePattern != "" && filePrefix != "" )
return false;
std::string ext = itksys::SystemTools::GetFilenameLastExtension(filename);
ext = itksys::SystemTools::LowerCase(ext);
if (ext == ".roi")
{
itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New();
typedef itk::ImageFileReader<ImageType> FileReaderType;
FileReaderType::Pointer reader = FileReaderType::New();
reader->SetImageIO(io);
reader->SetFileName(filename);
try
{
reader->Update();
}
catch(itk::ExceptionObject e)
{
MITK_INFO << e.GetDescription();
return false;
}
return true;
}
return false;
}
} //namespace MITK
#endif
diff --git a/Modules/DiffusionImaging/Quantification/IODataStructures/TbssImages/mitkTbssImporter.cpp b/Modules/DiffusionImaging/Quantification/IODataStructures/TbssImages/mitkTbssImporter.cpp
index e9d970dc83..7fb007e593 100644
--- a/Modules/DiffusionImaging/Quantification/IODataStructures/TbssImages/mitkTbssImporter.cpp
+++ b/Modules/DiffusionImaging/Quantification/IODataStructures/TbssImages/mitkTbssImporter.cpp
@@ -1,137 +1,137 @@
/*===================================================================
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 __mitkTbssImporter_cpp
#define __mitkTbssImporter_cpp
#include "mitkTbssImporter.h"
#include <mitkPixelTypeMultiplex.h>
#include "mitkImagePixelReadAccessor.h"
namespace mitk
{
TbssImage::Pointer TbssImporter::Import()
{
mitk::TbssImage::Pointer tbssImg = mitk::TbssImage::New();
mitkPixelTypeMultiplex1( Import, m_InputVolume->GetPixelType(), tbssImg);
return tbssImg;
}
template <typename TPixel>
void TbssImporter::Import(const mitk::PixelType , mitk::TbssImage::Pointer tbssImg)
{
// read all images with all_*.nii.gz
MITK_INFO << "called import ...";
m_Data = DataImageType::New();
- mitk::Geometry3D* geo = m_InputVolume->GetGeometry();
+ mitk::BaseGeometry* geo = m_InputVolume->GetGeometry();
mitk::Vector3D spacing = geo->GetSpacing();
mitk::Point3D origin = geo->GetOrigin();
//Size size
DataImageType::SizeType dataSize;
dataSize[0] = m_InputVolume->GetDimension(0);
dataSize[1] = m_InputVolume->GetDimension(1);
dataSize[2] = m_InputVolume->GetDimension(2);
m_Data->SetRegions(dataSize);
// Set spacing
DataImageType::SpacingType dataSpacing;
dataSpacing[0] = spacing[0];
dataSpacing[1] = spacing[1];
dataSpacing[2] = spacing[2];
m_Data->SetSpacing(dataSpacing);
DataImageType::PointType dataOrigin;
dataOrigin[0] = origin[0];
dataOrigin[1] = origin[1];
dataOrigin[2] = origin[2];
m_Data->SetOrigin(dataOrigin);
//Direction must be set
DataImageType::DirectionType dir;
- const itk::Transform<ScalarType, 3, 3>* transform3D = geo->GetParametricTransform();
+ const itk::Transform<ScalarType, 3, 3>* transform3D = geo->GetIndexToWorldTransform();
itk::Transform<ScalarType,3,3>::ParametersType p = transform3D->GetParameters();
int t=0;
for(int i=0; i<3; i++)
{
for(int j=0; j<3; j++)
{
dir[i][j] = p[t]; // row-major order (where the column index varies the fastest)
t++;
}
}
m_Data->SetDirection(dir);
// Set the length to one because otherwise allocate fails. Should be changed when groups/measurements are added
m_Data->SetVectorLength(m_InputVolume->GetDimension(3));
m_Data->Allocate();
// Determine vector size of m_Data
int vecSize = m_Data->GetVectorLength();
MITK_INFO << "vecsize " <<vecSize;
try {
mitk::ImagePixelReadAccessor<TPixel,4> readTbss( m_InputVolume );
for(unsigned int i=0; i<dataSize[0]; i++)
{
MITK_INFO << "i " << i << " / " << dataSize[0];
for(unsigned int j=0; j<dataSize[1]; j++)
{
for(unsigned int k=0; k<dataSize[2]; k++)
{
itk::VariableLengthVector<float> pixel;
itk::Index<3> id;
itk::Index<4> ix;
ix[0] = id[0] = i;
ix[1] = id[1] = j;
ix[2] = id[2] = k;
pixel = m_Data->GetPixel(id);
for(int z=0; z<vecSize; z++)
{
ix[3] = z;
float value = readTbss.GetPixelByIndex(ix);
pixel.SetElement(z, value);
}
m_Data->SetPixel(id, pixel);
}
}
}
}
catch ( mitk::Exception& e )
{
MITK_ERROR << "TbssImporter::Import: No read access to tbss image: " << e.what() ;
}
tbssImg->SetGroupInfo(m_Groups);
tbssImg->SetMeasurementInfo(m_MeasurementInfo);
tbssImg->SetImage(m_Data);
tbssImg->InitializeFromVectorImage();
}
}
#endif // __mitkTbssImporter_cpp
diff --git a/Modules/Ext/Algorithms/mitkAngleCorrectByPointFilter.cpp b/Modules/Ext/Algorithms/mitkAngleCorrectByPointFilter.cpp
index 2a3acd2591..01bb587e8d 100644
--- a/Modules/Ext/Algorithms/mitkAngleCorrectByPointFilter.cpp
+++ b/Modules/Ext/Algorithms/mitkAngleCorrectByPointFilter.cpp
@@ -1,228 +1,229 @@
/*===================================================================
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 "mitkAngleCorrectByPointFilter.h"
#include "mitkIpPic.h"
#include "mitkImageTimeSelector.h"
#include "mitkProperties.h"
#include "mitkImageReadAccessor.h"
#include <mitkProportionalTimeGeometry.h>
mitk::AngleCorrectByPointFilter::AngleCorrectByPointFilter() : m_PreferTransducerPositionFromProperty(true)
{
m_Center.Fill(0);
m_TransducerPosition.Fill(0);
}
mitk::AngleCorrectByPointFilter::~AngleCorrectByPointFilter()
{
-
}
void mitk::AngleCorrectByPointFilter::GenerateOutputInformation()
{
mitk::Image::ConstPointer input = this->GetInput();
mitk::Image::Pointer output = this->GetOutput();
if ((output->IsInitialized()) && (this->GetMTime() <= m_TimeOfHeaderInitialization.GetMTime()))
return;
itkDebugMacro(<<"GenerateOutputInformation()");
unsigned int i;
unsigned int *tmpDimensions = new unsigned int[input->GetDimension()];
for(i=0;i<input->GetDimension();++i)
tmpDimensions[i]=input->GetDimension(i);
//@todo maybe we should shift the following somehow in ImageToImageFilter
mitk::PixelType scalarPType = MakeScalarPixelType<ScalarType>();
output->Initialize(scalarPType,
input->GetDimension(),
tmpDimensions,
input->GetNumberOfChannels());
output->GetSlicedGeometry()->SetSpacing(input->GetSlicedGeometry()->GetSpacing());
- //output->GetSlicedGeometry()->SetGeometry2D(mitk::Image::BuildStandardPlaneGeometry2D(output->GetSlicedGeometry(), tmpDimensions).GetPointer(), 0);
+ //output->GetSlicedGeometry()->SetPlaneGeometry(mitk::Image::BuildStandardPlanePlaneGeometry(output->GetSlicedGeometry(), tmpDimensions).GetPointer(), 0);
//output->GetSlicedGeometry()->SetEvenlySpaced();
- //set the timebounds - after SetGeometry2D, so that the already created PlaneGeometry will also receive this timebounds.
+ //set the timebounds - after SetPlaneGeometry, so that the already created PlaneGeometry will also receive this timebounds.
//@fixme!!! will not work for not evenly timed data!
- output->GetSlicedGeometry()->SetTimeBounds(input->GetSlicedGeometry()->GetTimeBounds());
ProportionalTimeGeometry::Pointer timeGeometry = ProportionalTimeGeometry::New();
timeGeometry->Initialize(output->GetSlicedGeometry(), output->GetTimeGeometry()->CountTimeSteps());
+ timeGeometry->SetFirstTimePoint(output->GetTimeGeometry()->GetMinimumTimePoint());
+ TimePointType stepDuration = input->GetTimeGeometry()->GetMaximumTimePoint(0) -input->GetTimeGeometry()->GetMinimumTimePoint(0);
+ timeGeometry->SetStepDuration(stepDuration);
output->SetTimeGeometry(timeGeometry);
output->SetPropertyList(input->GetPropertyList()->Clone());
delete [] tmpDimensions;
m_TimeOfHeaderInitialization.Modified();
}
void mitk::AngleCorrectByPointFilter::GenerateData()
{
mitk::Image::ConstPointer input = this->GetInput();
mitk::Image::Pointer output = this->GetOutput();
if(m_PreferTransducerPositionFromProperty)
{
mitk::Point3iProperty::Pointer pointProp;
pointProp = dynamic_cast<mitk::Point3iProperty*>(input->GetProperty("ORIGIN").GetPointer());
if (pointProp.IsNotNull() )
{
const itk::Point<int, 3> & p = pointProp->GetValue();
m_TransducerPosition[0] = p[0];
m_TransducerPosition[1] = p[1];
m_TransducerPosition[2] = p[2];
}
}
itkDebugMacro( << "compute angle corrected image .... " );
itkDebugMacro( << " Center[0]=" << m_Center[0] << " Center[1]=" << m_Center[1] << " Center[2]=" << m_Center[2] );
itkDebugMacro( << " TransducerPosition[0]=" << m_TransducerPosition[0] << " TransducerPosition[1]=" << m_TransducerPosition[1] << " TransducerPosition[2]=" << m_TransducerPosition[2] );
const Vector3D & spacing = input->GetSlicedGeometry()->GetSpacing();
// MITK_INFO << " in: xres=" << spacing[0] << " yres=" << spacing[1] << " zres=" << spacing[2] << std::endl;
if((spacing[0]!=spacing[1]) || (spacing[0]!=spacing[2]))
{
itkExceptionMacro("filter does not work for uninsotropic data: spacing: ("<< spacing[0] << "," << spacing[1] << "," << spacing[2] << ")");
}
Vector3D p;
Vector3D tx_direction;
Vector3D tx_position = m_TransducerPosition.GetVectorFromOrigin();
Vector3D center = m_Center.GetVectorFromOrigin();
Vector3D assumed_direction;
ScalarType &x=p[0];
ScalarType &y=p[1];
ScalarType &z=p[2];
Vector3D down;
FillVector3D(down,0.0,0.0,-1.0);
int xDim = input->GetDimension(0);
int yDim = input->GetDimension(1);
int zDim = input->GetDimension(2);
mitkIpPicDescriptor* pic_out;
pic_out = mitkIpPicNew();
pic_out->dim = 3;
pic_out->bpe = output->GetPixelType().GetBpe();
//pic_out->type = output->GetPixelType().GetType();
pic_out->n[0] = xDim;
pic_out->n[1] = yDim;
pic_out->n[2] = zDim;
pic_out->data = malloc(_mitkIpPicSize(pic_out));
//go!
mitk::ImageTimeSelector::Pointer timeSelector=mitk::ImageTimeSelector::New();
timeSelector->SetInput(input);
int nstart, nmax;
int tstart, tmax;
tstart=output->GetRequestedRegion().GetIndex(3);
nstart=output->GetRequestedRegion().GetIndex(4);
tmax=tstart+output->GetRequestedRegion().GetSize(3);
nmax=nstart+output->GetRequestedRegion().GetSize(4);
int n,t;
for(n=nstart;n<nmax;++n)//output->GetNumberOfChannels();++n)
{
timeSelector->SetChannelNr(n);
for(t=tstart;t<tmax;++t)
{
timeSelector->SetTimeNr(t);
timeSelector->Update();
typedef unsigned char InputImagePixelType;
typedef ScalarType OutputImagePixelType;
if(input->GetPixelType().GetPixelType() != itk::ImageIOBase::SCALAR ||
input->GetPixelType().GetComponentType()!= MapPixelComponentType<InputImagePixelType>::value)
{
itkExceptionMacro("only implemented for " << typeid(PixelType).name() );
}
InputImagePixelType *in;
OutputImagePixelType *out;
mitk::ImageReadAccessor tsOutAcc(timeSelector->GetOutput());
in = (InputImagePixelType *)tsOutAcc.GetData();
out = (OutputImagePixelType*)pic_out->data;
for (z=0 ; z<zDim ; ++z)
{
for (y=0; y<yDim; ++y)
{
for (x=0; x<xDim; ++x, ++in, ++out)
{
tx_direction = tx_position-p;
tx_direction.Normalize();
//are we within the acquisition cone?
// if(-tx_direction*down>vnl_math::pi_over_4)
{
assumed_direction = center-p;
assumed_direction.Normalize();
ScalarType cos_factor = tx_direction*assumed_direction;
if(fabs(cos_factor)>eps)
*out=((ScalarType)(*in)-128.0)/cos_factor;
else
*out=((ScalarType)(*in)-128.0)/eps;
}
//else
// *out=0;
}
}
}
//output->SetPicVolume(pic_out, t, n);
}
}
}
void mitk::AngleCorrectByPointFilter::GenerateInputRequestedRegion()
{
Superclass::GenerateInputRequestedRegion();
mitk::ImageToImageFilter::InputImagePointer input =
const_cast< mitk::ImageToImageFilter::InputImageType * > ( this->GetInput() );
mitk::Image::Pointer output = this->GetOutput();
Image::RegionType requestedRegion;
requestedRegion = output->GetRequestedRegion();
requestedRegion.SetIndex(0, 0);
requestedRegion.SetIndex(1, 0);
requestedRegion.SetIndex(2, 0);
//requestedRegion.SetIndex(3, 0);
//requestedRegion.SetIndex(4, 0);
requestedRegion.SetSize(0, input->GetDimension(0));
requestedRegion.SetSize(1, input->GetDimension(1));
requestedRegion.SetSize(2, input->GetDimension(2));
//requestedRegion.SetSize(3, output->GetDimension(3));
//requestedRegion.SetSize(4, output->GetNumberOfChannels());
input->SetRequestedRegion( & requestedRegion );
}
diff --git a/Modules/Ext/Algorithms/mitkCylindricToCartesianFilter.cpp b/Modules/Ext/Algorithms/mitkCylindricToCartesianFilter.cpp
index 3f2ed9cf33..45ac8276fd 100644
--- a/Modules/Ext/Algorithms/mitkCylindricToCartesianFilter.cpp
+++ b/Modules/Ext/Algorithms/mitkCylindricToCartesianFilter.cpp
@@ -1,501 +1,504 @@
/*===================================================================
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 "mitkCylindricToCartesianFilter.h"
#include "mitkImageTimeSelector.h"
#include "mitkSlicedGeometry3D.h"
#include "mitkPlaneGeometry.h"
#include "mitkProperties.h"
#include "mitkLegacyAdaptors.h"
#include <mitkIpPicTypeMultiplex.h>
#include <mitkProportionalTimeGeometry.h>
template <class T>
void _transform(mitkIpPicDescriptor *pic, mitkIpPicDescriptor *dest, float _outsideValue, float *fr, float *fphi, float *fz, short *rt, unsigned int *phit, unsigned int *zt, mitkIpPicDescriptor *coneCutOff_pic) //...t=truncated
{
T outsideValue = static_cast<T>(_outsideValue);
register float f, ft, f0, f1, f2, f3;
mitkIpInt2_t ox_size;
mitkIpInt2_t nx_size, ny_size, nz_size;
int oxy_size, nxy_size;
T* orig, *dp, *dest_start;
mitkIpInt2_t* coneCutOff=(mitkIpInt2_t*)coneCutOff_pic->data;
orig=(T*)pic->data;
ox_size=pic->n[0];
oxy_size=ox_size*pic->n[1];
nx_size=dest->n[0];
ny_size=dest->n[1];
nxy_size=nx_size*ny_size;
nz_size=dest->n[2];
/*nx_size=360;
ny_size=360;
nxy_size=nx_size*ny_size;
nz_size=256;*/
dest_start=dp=((T*)dest->data)+nxy_size*(nz_size-1);
mitkIpInt2_t y;
// int size=_mitkIpPicElements(pic);
register mitkIpInt2_t x,z;
for(y=0;y<ny_size;++y)
{
mitkIpInt2_t x_start;
register mitkIpInt2_t x_end;
int r0plusphi0=*rt;
if(r0plusphi0>=0)
{
x_start=0; x_end=nx_size;
}
else
{
x_start=-r0plusphi0; x_end=nx_size+r0plusphi0;
for(z=0;z<nz_size;++z,dp+=-nxy_size-x_start)
for(x=0;x<x_start;++x,++dp)
*dp=outsideValue;
dp+=nxy_size*nz_size; dp+=x_end;
for(z=0;z<nz_size;++z,dp+=-nxy_size-x_start)
for(x=x_end;x<nx_size;++x,++dp)
*dp=outsideValue;
dp+=nxy_size*nz_size; dp-=x_end;
fr+=x_start;
fphi+=x_start;
rt+=x_start;
phit+=x_start;
dp+=x_start;
coneCutOff+=x_start;
}
for(x=x_start;x<x_end;++x, ++fr, ++fphi, ++rt, ++phit, ++dp, ++coneCutOff)
{
f=*fr;
f3=*fphi;
f0=1-f;
f1=1-f3;
f2=f0*f3;
f0*=f1;
f1*=f;
f3*=f;
r0plusphi0=*rt+*phit;
mitkIpInt2_t z_start;
z_start=*coneCutOff;
T *op;
register unsigned int step;
unsigned int *ztp;
op=orig+*rt+*phit;
float *fzp;
for(z=0;z<z_start;++z, dp-=nxy_size)
*dp=outsideValue;
ztp=zt+z_start;
fzp=fz+z_start;
for(z=z_start;z<nz_size;++z, dp-=nxy_size)
{
step=*(ztp++);
register T *opt=op;
opt+=step;
f =*opt*f0; ++opt;
f+=*opt*f1; opt+=oxy_size; --opt;
f+=*opt*f2; ++opt;
f+=*opt*f3; opt-=oxy_size; --opt;
opt+=ox_size;
ft =*opt*f0; ++opt;
ft+=*opt*f1; opt+=oxy_size; --opt;
ft+=*opt*f2; ++opt;
ft+=*opt*f3;
*dp=(T)((1-*fzp)*f+*fzp*ft+0.5);
}
dp+=nxy_size*nz_size;
}
fr+=nx_size-x_end;
fphi+=nx_size-x_end;
rt+=nx_size-x_end;
phit+=nx_size-x_end;
dp+=nx_size-x_end;
coneCutOff+=nx_size-x_end;
}
}
void mitk::CylindricToCartesianFilter::buildTransformShortCuts(int orig_xsize, int orig_ysize, int orig_zsize, int new_xsize, mitkIpPicDescriptor * &rt_pic, mitkIpPicDescriptor * &phit_pic, mitkIpPicDescriptor * &fr_pic, mitkIpPicDescriptor * &fphi_pic, unsigned int * &zt, float * &fz)
{
--orig_zsize;
rt_pic=mitkIpPicNew();
rt_pic->type=mitkIpPicInt;
rt_pic->bpe=16;
rt_pic->dim=2;
rt_pic->n[0]=rt_pic->n[1]=new_xsize;
rt_pic->data=malloc(_mitkIpPicSize(rt_pic));
phit_pic=mitkIpPicNew();
phit_pic->type=mitkIpPicUInt;
phit_pic->bpe=32;
phit_pic->dim=2;
phit_pic->n[0]=phit_pic->n[1]=new_xsize;
phit_pic->data=malloc(_mitkIpPicSize(phit_pic));
fr_pic=mitkIpPicNew();
fr_pic->type=mitkIpPicFloat;
fr_pic->bpe=32;
fr_pic->dim=2;
fr_pic->n[0]=fr_pic->n[1]=new_xsize;
fr_pic->data=malloc(_mitkIpPicSize(fr_pic));
fphi_pic=mitkIpPicNew();
fphi_pic->type=mitkIpPicFloat;
fphi_pic->bpe=32;
fphi_pic->dim=2;
fphi_pic->n[0]=fphi_pic->n[1]=new_xsize;
fphi_pic->data=malloc(_mitkIpPicSize(fphi_pic));
mitkIpInt2_t *rtp=(mitkIpInt2_t*)rt_pic->data, *rt_xzero, rt, phit;
mitkIpUInt4_t *phitp=(mitkIpUInt4_t*)phit_pic->data;
mitkIpFloat4_t *fr=(mitkIpFloat4_t *)fr_pic->data;
mitkIpFloat4_t *fphi=(mitkIpFloat4_t *)fphi_pic->data;
mitkIpFloat4_t r, phi, scale=(double)orig_xsize/(double)new_xsize;
int x,y,xy0,xy0_orig, oxy_size, new_zsize;
oxy_size=orig_xsize*orig_ysize;
xy0=(int)(((double)new_xsize)/2+0.5);
xy0_orig=(int)(((double)orig_xsize)/2+0.5);
new_zsize=(int)(orig_ysize/scale);
// \bug y compared to x
for(y=0;y<new_xsize;++y)
{
rt_xzero=rtp; *rtp=0;
for(x=0;x<new_xsize;++x,++fr,++fphi,++rtp, ++phitp)
{
int xq=x-xy0, yq=y-xy0;
r=sqrt( (double) (xq*xq+yq*yq));
// float rtest=-(xy0-sqrt(xy0*xy0-yq*yq))-0.5;
rt=(mitkIpInt2_t)(-(xy0-sqrt((double) (xy0*xy0-yq*yq)))-0.5);/*in rt steht der Index des Endes der zu �berspringenden Punkte=>anfangen bei -rt+1!*/
// if((x>=-rt) && (x<new_xsize+rt))
{
if(y!=xy0)
r=r*(y>xy0?1.0:-1.0)*scale+xy0_orig;
else
r=r*(x>xy0?-1.0:1.0)*scale+xy0_orig;
rt=(mitkIpInt2_t)r;
int xtmp=x;
if(x>xy0)
xtmp=new_xsize-x;
if(rt<0)
{
r=rt=0;
if(xtmp>-*rt_xzero)
*rt_xzero=-xtmp;
*fr=0;
}
else
if(rt>orig_xsize-1)
{
r=rt=orig_xsize-1;
if(xtmp>-*rt_xzero)
*rt_xzero=-xtmp;
*fr=0;
}
else
*fr=r-rt;
if(*fr<0)
*fr=0;
}
// else
// *fr=0;
phi=orig_zsize-(yq==0?1:-atan((float)xq/yq)/M_PI+0.5)*orig_zsize;
phit=(mitkIpUInt4_t)phi;
*fphi=phi-phit;
*rtp=rt;
*phitp=phit*oxy_size;
}
}
zt=(unsigned int *)malloc(sizeof(unsigned int)*new_zsize);
fz=(float *)malloc(sizeof(float)*new_zsize);
float *fzp=fz;
unsigned int *ztp=zt;
int z;
float z_step=orig_ysize/(orig_ysize*((float)new_xsize)/orig_xsize);
for(z=0;z<new_zsize;++z,++fzp,++ztp)
{
*fzp=z*z_step;
*ztp=(unsigned int)*fzp;
*fzp-=*ztp;
*ztp*=orig_xsize;
}
}
void mitk::CylindricToCartesianFilter::buildConeCutOffShortCut(int orig_xsize, int orig_ysize, mitkIpPicDescriptor *rt_pic, mitkIpPicDescriptor *fr_pic, float a, float b, mitkIpPicDescriptor * &coneCutOff_pic)
{
coneCutOff_pic=mitkIpPicNew();
coneCutOff_pic->type=mitkIpPicInt;
coneCutOff_pic->bpe=16;
coneCutOff_pic->dim=2;
coneCutOff_pic->n[0]=coneCutOff_pic->n[1]=rt_pic->n[0];
coneCutOff_pic->data=malloc(_mitkIpPicSize(coneCutOff_pic));
int i, size=_mitkIpPicElements(rt_pic);
mitkIpInt2_t *rt, *ccop, ohx_size, nz_size;
mitkIpFloat4_t *fr;
a*=(float)rt_pic->n[0]/orig_xsize;
b*=(float)rt_pic->n[0]/orig_xsize;
ohx_size=orig_xsize/2;
nz_size=orig_ysize*rt_pic->n[0]/orig_xsize;
rt=(mitkIpInt2_t *)rt_pic->data; fr=(mitkIpFloat4_t*)fr_pic->data; ccop=(mitkIpInt2_t *)coneCutOff_pic->data;
for(i=0; i<size; ++i, ++rt, ++ccop)
{
register mitkIpInt2_t cco;
if(*rt<=ohx_size)
cco=(mitkIpInt2_t)(a*(*rt+*fr)+b);
else
cco=(mitkIpInt2_t)(a*(orig_xsize-(*rt+*fr))+b);
if(cco<0)
cco=0;
if(cco>=nz_size)
cco=nz_size;
*ccop=cco;
}
}
void mitk::CylindricToCartesianFilter::GenerateOutputInformation()
{
mitk::Image::Pointer output = this->GetOutput();
if ((output->IsInitialized()) && (output->GetPipelineMTime() <= m_TimeOfHeaderInitialization.GetMTime()))
return;
mitk::Image::ConstPointer input = this->GetInput();
itkDebugMacro(<<"GenerateOutputInformation()");
unsigned int i, *tmpDimensions=new unsigned int[std::max(3u,input->GetDimension())];
tmpDimensions[0]=m_TargetXSize;
if(tmpDimensions[0]==0)
tmpDimensions[0] = input->GetDimension(0);
float scale=((float)tmpDimensions[0])/input->GetDimension(0);
tmpDimensions[1] = tmpDimensions[0];
tmpDimensions[2] = (unsigned int)(scale*input->GetDimension(1));
for(i=3;i<input->GetDimension();++i)
tmpDimensions[i]=input->GetDimension(i);
output->Initialize(input->GetPixelType(),
input->GetDimension(),
tmpDimensions,
input->GetNumberOfChannels());
// initialize the spacing of the output
Vector3D spacing = input->GetSlicedGeometry()->GetSpacing();
if(input->GetDimension()>=2)
spacing[2]=spacing[1];
else
spacing[2] = 1.0;
spacing[1] = spacing[0];
spacing *= 1.0/scale;
output->GetSlicedGeometry()->SetSpacing(spacing);
mitk::Point3iProperty::Pointer pointProp;
pointProp = dynamic_cast<mitk::Point3iProperty*>(input->GetProperty("ORIGIN").GetPointer());
if (pointProp.IsNotNull() )
{
itk::Point<int, 3> tp = pointProp->GetValue();
tp[2] = (int)(tmpDimensions[2]-tp[1] * scale-1);
tp[0] = tmpDimensions[0]/2;
tp[1] = tmpDimensions[0]/2;
mitk::Point3iProperty::Pointer pointProp = mitk::Point3iProperty::New(tp);
output->SetProperty("ORIGIN", pointProp);
}
delete [] tmpDimensions;
- //output->GetSlicedGeometry()->SetGeometry2D(mitk::Image::BuildStandardPlaneGeometry2D(output->GetSlicedGeometry(), tmpDimensions).GetPointer(), 0);
- //set the timebounds - after SetGeometry2D, so that the already created PlaneGeometry will also receive this timebounds.
+ //output->GetSlicedGeometry()->SetPlaneGeometry(mitk::Image::BuildStandardPlanePlaneGeometry(output->GetSlicedGeometry(), tmpDimensions).GetPointer(), 0);
+ //set the timebounds - after SetPlaneGeometry, so that the already created PlaneGeometry will also receive this timebounds.
//@fixme!!! will not work for not evenly timed data!
- output->GetSlicedGeometry()->SetTimeBounds(input->GetSlicedGeometry()->GetTimeBounds());
ProportionalTimeGeometry::Pointer timeGeometry = ProportionalTimeGeometry::New();
timeGeometry->Initialize(output->GetSlicedGeometry(), output->GetTimeGeometry()->CountTimeSteps());
+ timeGeometry->Initialize(output->GetSlicedGeometry(), output->GetTimeGeometry()->CountTimeSteps());
+ timeGeometry->SetFirstTimePoint(input->GetTimeGeometry()->GetMinimumTimePoint());
+ TimePointType stepDuration = input->GetTimeGeometry()->GetMaximumTimePoint(0) -input->GetTimeGeometry()->GetMinimumTimePoint(0);
+ timeGeometry->SetStepDuration(stepDuration);
output->SetTimeGeometry(timeGeometry);
output->SetPropertyList(input->GetPropertyList()->Clone());
m_TimeOfHeaderInitialization.Modified();
}
void mitk::CylindricToCartesianFilter::GenerateData()
{
mitk::Image::ConstPointer input = this->GetInput();
mitk::Image::Pointer output = this->GetOutput();
mitk::ImageTimeSelector::Pointer timeSelector=mitk::ImageTimeSelector::New();
timeSelector->SetInput(input);
mitkIpPicDescriptor* pic_transformed=NULL;
pic_transformed = mitkIpPicNew();
pic_transformed->dim=3;
pic_transformed->bpe = output->GetPixelType().GetBpe();
//pic_transformed->type = output->GetPixelType().GetType();
pic_transformed->n[0] = output->GetDimension(0);
pic_transformed->n[1] = output->GetDimension(1);
pic_transformed->n[2] = output->GetDimension(2);
pic_transformed->data=malloc(_mitkIpPicSize(pic_transformed));
int nstart, nmax;
int tstart, tmax;
tstart=output->GetRequestedRegion().GetIndex(3);
nstart=output->GetRequestedRegion().GetIndex(4);
tmax=tstart+output->GetRequestedRegion().GetSize(3);
nmax=nstart+output->GetRequestedRegion().GetSize(4);
if(zt==NULL)
{
timeSelector->SetChannelNr(nstart);
timeSelector->SetTimeNr(tstart);
buildTransformShortCuts(input->GetDimension(0),input->GetDimension(1), input->GetDimension(2), output->GetDimension(0), rt_pic, phit_pic, fr_pic, fphi_pic, zt, fz);
// query the line limiting the sector
a=b=0;
mitk::FloatProperty::Pointer prop;
prop = dynamic_cast<mitk::FloatProperty*>(input->GetProperty("SECTOR LIMITING LINE SLOPE").GetPointer());
if (prop.IsNotNull() )
a = prop->GetValue();
prop = dynamic_cast<mitk::FloatProperty*>(input->GetProperty("SECTOR LIMITING LINE OFFSET").GetPointer());
if (prop.IsNotNull() )
b = prop->GetValue();
buildConeCutOffShortCut(input->GetDimension(0),input->GetDimension(1), rt_pic, fr_pic, a, b, coneCutOff_pic);
// mitkIpPicPut("C:\\temp\\rt_90.pic",rt_pic);
//mitkIpPicPut("C:\\temp\\coneCutOff.pic", coneCutOff_pic);
}
int n,t;
for(n=nstart;n<nmax;++n)//output->GetNumberOfChannels();++n)
{
timeSelector->SetChannelNr(n);
for(t=tstart;t<tmax;++t)
{
timeSelector->SetTimeNr(t);
timeSelector->Update();
// Cast to pic descriptor for the timeSelector image
mitkIpPicDescriptor* timeSelectorPic = mitkIpPicNew();
mitk::ImageWriteAccessor imageAccess(timeSelector->GetOutput());
CastToIpPicDescriptor( timeSelector->GetOutput(), &imageAccess, timeSelectorPic );
_mitkIpPicFreeTags(pic_transformed->info->tags_head);
pic_transformed->info->tags_head = _mitkIpPicCloneTags(timeSelectorPic->info->tags_head);
if(input->GetDimension(2)>1)
{
mitkIpPicTypeMultiplex9(_transform, timeSelectorPic , pic_transformed, m_OutsideValue, (float*)fr_pic->data, (float*)fphi_pic->data, fz, (short *)rt_pic->data, (unsigned int *)phit_pic->data, zt, coneCutOff_pic);
// mitkIpPicPut("1trf.pic",pic_transformed);
}
else
{
mitkIpPicDescriptor *doubleSlice = mitkIpPicCopyHeader( timeSelectorPic , NULL);
doubleSlice->dim=3;
doubleSlice->n[2]=2;
doubleSlice->data=malloc(_mitkIpPicSize(doubleSlice));
memcpy(doubleSlice->data, timeSelectorPic->data, _mitkIpPicSize(doubleSlice)/2);
mitkIpPicTypeMultiplex9(_transform, doubleSlice, pic_transformed, m_OutsideValue, (float*)fr_pic->data, (float*)fphi_pic->data, fz, (short *)rt_pic->data, (unsigned int *)phit_pic->data, zt, coneCutOff_pic);
mitkIpPicFree(doubleSlice);
}
output->SetVolume(pic_transformed->data, t, n);
}
}
//mitkIpPicPut("outzzzzzzzz.pic",pic_transformed);
mitkIpPicFree(pic_transformed);
m_TimeOfHeaderInitialization.Modified();
}
mitk::CylindricToCartesianFilter::CylindricToCartesianFilter()
: m_OutsideValue(0.0), m_TargetXSize(0)
{
rt_pic = NULL; phit_pic = NULL; fr_pic = NULL; fphi_pic = NULL; coneCutOff_pic = NULL;
zt = NULL; fz = NULL;
a=b=0.0;
}
mitk::CylindricToCartesianFilter::~CylindricToCartesianFilter()
{
if(rt_pic!=NULL) mitkIpPicFree(rt_pic);
if(phit_pic!=NULL) mitkIpPicFree(phit_pic);
if(fr_pic!=NULL) mitkIpPicFree(fr_pic);
if(fphi_pic!=NULL) mitkIpPicFree(fphi_pic);
if(coneCutOff_pic!=NULL) mitkIpPicFree(coneCutOff_pic);
if(zt != NULL) free(zt);
if(fz != NULL) free (fz);
}
void mitk::CylindricToCartesianFilter::GenerateInputRequestedRegion()
{
Superclass::GenerateInputRequestedRegion();
mitk::ImageToImageFilter::InputImagePointer input =
const_cast< mitk::ImageToImageFilter::InputImageType * > ( this->GetInput() );
mitk::Image::Pointer output = this->GetOutput();
Image::RegionType requestedRegion;
requestedRegion = output->GetRequestedRegion();
requestedRegion.SetIndex(0, 0);
requestedRegion.SetIndex(1, 0);
requestedRegion.SetIndex(2, 0);
requestedRegion.SetSize(0, input->GetDimension(0));
requestedRegion.SetSize(1, input->GetDimension(1));
requestedRegion.SetSize(2, input->GetDimension(2));
input->SetRequestedRegion( & requestedRegion );
}
diff --git a/Modules/Ext/Algorithms/mitkInterpolateLinesFilter.cpp b/Modules/Ext/Algorithms/mitkInterpolateLinesFilter.cpp
index f6fb1c3fb7..0a124c1776 100644
--- a/Modules/Ext/Algorithms/mitkInterpolateLinesFilter.cpp
+++ b/Modules/Ext/Algorithms/mitkInterpolateLinesFilter.cpp
@@ -1,211 +1,211 @@
/*===================================================================
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 "mitkInterpolateLinesFilter.h"
#include "mitkMesh.h"
#include "mitkSurface.h"
#include <vtkPolyData.h>
#include <vtkPoints.h>
#include <vtkCellArray.h>
#include <vtkCardinalSpline.h>
#include <vector>
mitk::InterpolateLinesFilter::InterpolateLinesFilter()
: m_SplineResolution(10), m_GeometryForInterpolation(NULL), m_Length(0.0)
{
m_SpX=vtkCardinalSpline::New();
m_SpY=vtkCardinalSpline::New();
m_SpZ=vtkCardinalSpline::New();
}
mitk::InterpolateLinesFilter::~InterpolateLinesFilter()
{
m_SpX->Delete();
m_SpY->Delete();
m_SpZ->Delete();
}
void mitk::InterpolateLinesFilter::GenerateOutputInformation()
{
mitk::Mesh::ConstPointer input = this->GetInput();
mitk::Surface::Pointer output = this->GetOutput(0);
itkDebugMacro(<<"GenerateOutputInformation()");
if(input.IsNull()) return;
if(m_GeometryForInterpolation.IsNotNull())
- output->SetGeometry(static_cast<Geometry3D*>(m_GeometryForInterpolation->Clone().GetPointer()));
+ output->SetGeometry(static_cast<BaseGeometry*>(m_GeometryForInterpolation->Clone().GetPointer()));
else
- output->SetGeometry(static_cast<Geometry3D*>(input->GetGeometry()->Clone().GetPointer()));
+ output->SetGeometry(static_cast<BaseGeometry*>(input->GetGeometry()->Clone().GetPointer()));
}
void mitk::InterpolateLinesFilter::GenerateData()
{
mitk::Mesh::ConstPointer input = this->GetInput();
mitk::Surface::Pointer output = this->GetOutput(0);
vtkPolyData *polyData = vtkPolyData::New();
vtkPoints *points = vtkPoints::New();
vtkCellArray *cellarray = vtkCellArray::New();
mitk::Mesh::PointType thisPoint;
m_Length = 0.0;
//iterate through all cells and build tubes
Mesh::ConstCellIterator cellIt, cellEnd;
cellEnd = input->GetMesh()->GetCells()->End();
for( cellIt = input->GetMesh()->GetCells()->Begin(); cellIt != cellEnd; ++cellIt )
{
if(((*cellIt->Value()).GetType()==mitk::Mesh::CellType::POLYGON_CELL)
&& ((*cellIt->Value()).GetNumberOfPoints()>=2))
BuildPointAndVectorList(*cellIt->Value(), points, cellarray);
}
polyData->SetPoints( points );
points->Delete();
polyData->SetLines( cellarray );
cellarray->Delete();
output->SetVtkPolyData(polyData);
polyData->Delete();
}
void mitk::InterpolateLinesFilter::BuildPointAndVectorList(mitk::Mesh::CellType& cell, vtkPoints* points, vtkCellArray* cellarray)
{
const mitk::Mesh* input = GetInput();
Mesh::PointIdIterator ptIt;
Mesh::PointIdIterator ptEnd;
ptEnd = cell.PointIdsEnd();
Point3D pt;
int i, size=cell.GetNumberOfPoints();
int closed_loop_pre_load=0;//m_SplineResolution;
if(m_GeometryForInterpolation.IsNull())
{
//when the contour is closed: first point insert behind two last points for smooth crossing
ptIt = ptEnd; ptIt-=closed_loop_pre_load+1;
for(i=0;i<closed_loop_pre_load;++i, ++ptIt)
{
pt = input->GetPoint(*ptIt);
m_SpX->AddPoint(i, pt[0]); m_SpY->AddPoint(i, pt[1]); m_SpZ->AddPoint(i, pt[2]);
}
//insert points
for(ptIt = cell.PointIdsBegin();i<size+closed_loop_pre_load;++i, ++ptIt)
{
pt = input->GetPoint(*ptIt);
m_SpX->AddPoint(i, pt[0]); m_SpY->AddPoint(i, pt[1]); m_SpZ->AddPoint(i, pt[2]);
}
//when the contour is closed: after the last point insert two first points for smooth crossing
int j;
for(j=0,ptIt = cell.PointIdsBegin();j<closed_loop_pre_load;++j,++i, ++ptIt)
{
pt = input->GetPoint(*ptIt);
m_SpX->AddPoint(i, pt[0]); m_SpY->AddPoint(i, pt[1]); m_SpZ->AddPoint(i, pt[2]);
}
//bool first = true;
Point3D lastPt, firstPt;
Vector3D vec;
float t, step=1.0f/m_SplineResolution;
size=(size-1)*m_SplineResolution;
i=closed_loop_pre_load;
cellarray->InsertNextCell(size);
for(t=closed_loop_pre_load;i<size+closed_loop_pre_load;++i, t+=step)
{
float pt[3];
FillVector3D(pt, m_SpX->Evaluate(t), m_SpY->Evaluate(t), m_SpZ->Evaluate(t));
cellarray->InsertCellPoint(points->InsertNextPoint(pt));
}
}
else //m_GeometryForInterpolation!=NULL
{
Point2D pt2d;
//when the contour is closed: before the first point insert two last points for smooth crossing
ptIt = ptEnd; ptIt-=closed_loop_pre_load+1;
for(i=0;i<closed_loop_pre_load;++i, ++ptIt)
{
m_GeometryForInterpolation->Map(input->GetPoint(*ptIt), pt2d);
m_SpX->AddPoint(i, pt2d[0]); m_SpY->AddPoint(i, pt2d[1]);
}
//insert points
for(ptIt = cell.PointIdsBegin();i<size+closed_loop_pre_load;++i, ++ptIt)
{
m_GeometryForInterpolation->Map(input->GetPoint(*ptIt), pt2d);
m_SpX->AddPoint(i, pt2d[0]); m_SpY->AddPoint(i, pt2d[1]);
}
//when the contour is closed: after the last point insert two first points for smooth crossing
int j;
for(j=0,ptIt = cell.PointIdsBegin();j<closed_loop_pre_load;++j,++i, ++ptIt)
{
m_GeometryForInterpolation->Map(input->GetPoint(*ptIt), pt2d);
m_SpX->AddPoint(i, pt2d[0]); m_SpY->AddPoint(i, pt2d[1]);
}
bool first = true;
Point3D lastPt; lastPt.Fill(0);
Vector3D vec;
float t, step=1.0f/m_SplineResolution;
size=(size-1)*m_SplineResolution;
i=closed_loop_pre_load;
cellarray->InsertNextCell(size);
for(t=closed_loop_pre_load;i<size+closed_loop_pre_load;++i, t+=step)
{
pt2d[0] = m_SpX->Evaluate(t); pt2d[1] = m_SpY->Evaluate(t);
m_GeometryForInterpolation->Map(pt2d, pt);
if(first==false)
{
vec=pt-lastPt;
m_Length+=vec.GetNorm();
}
first=false;
float pvtk[3];
itk2vtk(pt, pvtk);
cellarray->InsertCellPoint(points->InsertNextPoint(pvtk));
lastPt = pt;
}
}
}
const mitk::Mesh *mitk::InterpolateLinesFilter::GetInput(void)
{
if (this->GetNumberOfInputs() < 1)
{
return 0;
}
return static_cast<const mitk::Mesh * >
(this->ProcessObject::GetInput(0) );
}
void mitk::InterpolateLinesFilter::SetInput(const mitk::Mesh *input)
{
// Process object is not const-correct so the const_cast is required here
this->ProcessObject::SetNthInput(0,
const_cast< mitk::Mesh * >( input ) );
}
diff --git a/Modules/Ext/Algorithms/mitkInterpolateLinesFilter.h b/Modules/Ext/Algorithms/mitkInterpolateLinesFilter.h
index bc93ec7a27..c4936fcc75 100644
--- a/Modules/Ext/Algorithms/mitkInterpolateLinesFilter.h
+++ b/Modules/Ext/Algorithms/mitkInterpolateLinesFilter.h
@@ -1,105 +1,105 @@
/*===================================================================
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 MITKINTERPOLATELINESFILTER_H_HEADER_INCLUDED_C10B22CD
#define MITKINTERPOLATELINESFILTER_H_HEADER_INCLUDED_C10B22CD
#include "mitkCommon.h"
#include "MitkExtExports.h"
#include "mitkSurfaceSource.h"
#include "mitkMesh.h"
-#include "mitkGeometry2D.h"
+#include "mitkPlaneGeometry.h"
class vtkPolyData;
class vtkPoints;
class vtkCardinalSpline;
class vtkPoints;
class vtkCellArray;
namespace mitk {
//##Documentation
//## @brief Interpolate additional points on lines
//##
-//## If a Geometry2D is set (by SetGeometryForInterpolation),
-//## we do an interpolation in the 2D-space of the Geometry2D:
+//## If a PlaneGeometry is set (by SetGeometryForInterpolation),
+//## we do an interpolation in the 2D-space of the PlaneGeometry:
//## Map two neighboring original points on
-//## the Geometry2D, resulting in two 2D-points, interpolate
+//## the PlaneGeometry, resulting in two 2D-points, interpolate
//## in 2D between them, and map them back via the
-//## Geometry2D in the 3D-world.
+//## PlaneGeometry in the 3D-world.
//## @ingroup Process
class MitkExt_EXPORT InterpolateLinesFilter : public SurfaceSource
{
public:
mitkClassMacro(InterpolateLinesFilter, SurfaceSource);
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
virtual void GenerateOutputInformation();
virtual void GenerateData();
const mitk::Mesh *GetInput(void);
virtual void SetInput(const mitk::Mesh *image);
//##Documentation
//## @brief Get spline resolution
//##
itkGetMacro(SplineResolution, unsigned int);
//##Documentation
//## @brief Set spline resolution
//##
itkSetMacro(SplineResolution, unsigned int);
//##Documentation
//## @brief Get/set geometry for interpolation
//##
//## If this is set (not NULL), we do an interpolation in the
- //## 2D-space of the Geometry2D: Map two neighboring original
- //## points on the Geometry2D, resulting in two 2D-points,
+ //## 2D-space of the PlaneGeometry: Map two neighboring original
+ //## points on the PlaneGeometry, resulting in two 2D-points,
//## interpolate in 2D between them, and map them back via the
- //## Geometry2D in the 3D-world.
- itkGetConstObjectMacro(GeometryForInterpolation, mitk::Geometry2D);
- itkSetObjectMacro(GeometryForInterpolation, mitk::Geometry2D);
+ //## PlaneGeometry in the 3D-world.
+ itkGetConstObjectMacro(GeometryForInterpolation, mitk::PlaneGeometry);
+ itkSetObjectMacro(GeometryForInterpolation, mitk::PlaneGeometry);
//##Documentation
//## @brief Get the overall length of the interpolated lines
//##
//## @warning valid only after Update()
itkGetMacro(Length, ScalarType);
protected:
InterpolateLinesFilter();
virtual ~InterpolateLinesFilter();
void BuildPointAndVectorList(mitk::Mesh::CellType& cell, vtkPoints* points, vtkCellArray* cellarray);
//##Documentation
//## @brief Spline resolution of created Surface
//##
unsigned int m_SplineResolution;
- mitk::Geometry2D::Pointer m_GeometryForInterpolation;
+ mitk::PlaneGeometry::Pointer m_GeometryForInterpolation;
vtkCardinalSpline *m_SpX, *m_SpY, *m_SpZ;
ScalarType m_Length;
};
} // namespace mitk
#endif /* MITKINTERPOLATELINESFILTER_H_HEADER_INCLUDED_C10B22CD */
diff --git a/Modules/Ext/Algorithms/mitkPlaneCutFilter.cpp b/Modules/Ext/Algorithms/mitkPlaneCutFilter.cpp
index 5dfc52cb4a..2efbca082f 100644
--- a/Modules/Ext/Algorithms/mitkPlaneCutFilter.cpp
+++ b/Modules/Ext/Algorithms/mitkPlaneCutFilter.cpp
@@ -1,260 +1,260 @@
/*===================================================================
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 "mitkPlaneCutFilter.h"
#include "mitkImageReadAccessor.h"
#include <mitkImageAccessByItk.h>
#include <mitkLine.h>
#define roundf(x) ((x - floor(x)) > 0.5f ? ceil(x) : floor(x))
void mitk::PlaneCutFilter::GenerateData()
{
if (!this->m_Plane)
{
return;
}
InputImageType *input = const_cast<InputImageType*>(this->GetInput());
if (!input)
{
return;
}
//Allocate output.
OutputImageType *output = this->GetOutput();
mitk::ImageReadAccessor inputAcc(input);
output->Initialize(input);
output->SetImportVolume(const_cast<void*>(inputAcc.GetData()));
//Do the intersection.
AccessByItk_2(output, _computeIntersection, this->m_Plane, input->GetGeometry());
}
mitk::PlaneCutFilter::PlaneCutFilter()
: m_BackgroundLevel(0.0f), m_Plane(0), m_FillMode(FILL)
{
}
mitk::PlaneCutFilter::~PlaneCutFilter()
{
}
template <typename TPixel, unsigned int VImageDimension>
-void mitk::PlaneCutFilter::_computeIntersection(itk::Image<TPixel, VImageDimension> *image, const PlaneGeometry *plane, const Geometry3D *geometry)
+void mitk::PlaneCutFilter::_computeIntersection(itk::Image<TPixel, VImageDimension> *image, const PlaneGeometry *plane, const BaseGeometry *geometry)
{
typedef itk::Image<TPixel, VImageDimension> ImageType;
const typename ImageType::RegionType &image_region = image->GetLargestPossibleRegion();
const typename ImageType::SizeValueType
max_x = image_region.GetSize(0ul),
max_y = image_region.GetSize(1ul),
max_z = image_region.GetSize(2ul),
img_size = max_x * max_y;
TPixel *data = image->GetBufferPointer();
Point3D p1, p2;
//TODO: Better solution required!
TPixel casted_background_level = static_cast<TPixel>(this->m_BackgroundLevel);
p1[0] = 0;
p2[0] = max_x - 1ul;
if (FILL == this->m_FillMode)
{
for (unsigned long z = 0ul; z < max_z; ++z)
{
p1[2] = z;
p2[2] = z;
for (unsigned long y = 0ul; y < max_y; ++y)
{
p1[1] = y;
p2[1] = y;
Point3D p1_t, p2_t;
geometry->IndexToWorld(p1, p1_t);
geometry->IndexToWorld(p2, p2_t);
if (plane->IsAbove(p1_t))
{
if (plane->IsAbove(p2_t))
{
if (0.0f == this->m_BackgroundLevel)
{
memset(&data[(y * max_x) + (z * img_size)], 0, max_x * sizeof(TPixel));
}
else
{
TPixel *subdata = &data[(y * max_x) + (z * img_size)];
for (unsigned long x = 0; x < max_x; ++x)
{
subdata[x] = casted_background_level;
}
}
}
else
{
Point3D intersection;
Line3D line;
line.SetPoints(p1_t, p2_t);
plane->IntersectionPoint(line, intersection);
geometry->WorldToIndex(intersection, intersection);
if (0.0f == this->m_BackgroundLevel)
{
memset(&data[(y * max_x) + (z * img_size)], 0, (static_cast<unsigned long>(roundf(intersection[0])) + 1u) * sizeof(TPixel));
}
else
{
TPixel *subdata = &data[(y * max_x) + (z * img_size)];
const unsigned long x_size = static_cast<unsigned long>(roundf(intersection[0])) + 1u;
for (unsigned long x = 0; x < x_size; ++x)
{
subdata[x] = casted_background_level;
}
}
}
}
else if (plane->IsAbove(p2_t))
{
Point3D intersection;
Line3D line;
line.SetPoints(p1_t, p2_t);
plane->IntersectionPoint(line, intersection);
geometry->WorldToIndex(intersection, intersection);
if (0.0f == this->m_BackgroundLevel)
{
unsigned long x = static_cast<unsigned long>(roundf(intersection[0]));
memset(&data[x + (y * max_x) + (z * img_size)], 0, (max_x - x) * sizeof(TPixel));
}
else
{
unsigned long x = static_cast<unsigned long>(roundf(intersection[0]));
TPixel *subdata = &data[x + (y * max_x) + (z * img_size)];
const unsigned long x_size = max_x - x;
for (x = 0; x < x_size; ++x)
{
subdata[x] = casted_background_level;
}
}
}
}
}
}
else
{
for (unsigned long z = 0ul; z < max_z; ++z)
{
p1[2] = z;
p2[2] = z;
for (unsigned long y = 0ul; y < max_y; ++y)
{
p1[1] = y;
p2[1] = y;
Point3D p1_t, p2_t;
geometry->IndexToWorld(p1, p1_t);
geometry->IndexToWorld(p2, p2_t);
if (!plane->IsAbove(p1_t))
{
if (!plane->IsAbove(p2_t))
{
if (0.0f == this->m_BackgroundLevel)
{
memset(&data[(y * max_x) + (z * img_size)], 0, max_x * sizeof(TPixel));
}
else
{
TPixel *subdata = &data[(y * max_x) + (z * img_size)];
for (unsigned long x = 0; x < max_x; ++x)
{
subdata[x] = casted_background_level;
}
}
}
else
{
Point3D intersection;
Line3D line;
line.SetPoints(p1_t, p2_t);
plane->IntersectionPoint(line, intersection);
geometry->WorldToIndex(intersection, intersection);
if (0.0f == this->m_BackgroundLevel)
{
memset(&data[(y * max_x) + (z * img_size)], 0, (static_cast<unsigned long>(roundf(intersection[0])) + 1u) * sizeof(TPixel));
}
else
{
TPixel *subdata = &data[(y * max_x) + (z * img_size)];
const unsigned long x_size = static_cast<unsigned long>(roundf(intersection[0])) + 1u;
for (unsigned long x = 0; x < x_size; ++x)
{
subdata[x] = casted_background_level;
}
}
}
}
else if (!plane->IsAbove(p2_t))
{
Point3D intersection;
Line3D line;
line.SetPoints(p1_t, p2_t);
plane->IntersectionPoint(line, intersection);
geometry->WorldToIndex(intersection, intersection);
if (0.0f == this->m_BackgroundLevel)
{
unsigned long x = static_cast<unsigned long>(roundf(intersection[0]));
memset(&data[x + (y * max_x) + (z * img_size)], 0, (max_x - x) * sizeof(TPixel));
}
else
{
unsigned long x = static_cast<unsigned long>(roundf(intersection[0]));
TPixel *subdata = &data[x + (y * max_x) + (z * img_size)];
const unsigned long x_size = max_x - x;
for (x = 0; x < x_size; ++x)
{
subdata[x] = casted_background_level;
}
}
}
}
}
}
}
diff --git a/Modules/Ext/Algorithms/mitkPlaneCutFilter.h b/Modules/Ext/Algorithms/mitkPlaneCutFilter.h
index d93843c41a..345b8e75a4 100644
--- a/Modules/Ext/Algorithms/mitkPlaneCutFilter.h
+++ b/Modules/Ext/Algorithms/mitkPlaneCutFilter.h
@@ -1,77 +1,77 @@
/*===================================================================
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 PLANECUTFILTER_H_HEADER_INCLUDED_C1F48A22
#define PLANECUTFILTER_H_HEADER_INCLUDED_C1F48A22
#include "mitkCommon.h"
#include "MitkExtExports.h"
#include "mitkImageToImageFilter.h"
#include "mitkPlaneGeometry.h"
namespace itk
{
template <class TPixel, unsigned int VImageDimension> class ITK_EXPORT Image;
}
namespace mitk {
/**
\brief Filter to cut an image with a plane.
Everything in the direction of the normal
of the planes (if fill mode is set to "FILL") will be set to a specified value.
*/
class MitkExt_EXPORT PlaneCutFilter : public ImageToImageFilter
{
public:
mitkClassMacro(PlaneCutFilter, ImageToImageFilter);
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
typedef enum {FILL, FILL_INVERSE} FillMode;
//##Documentation
//## @brief Set background grey level
itkSetMacro(BackgroundLevel, float);
itkGetMacro(BackgroundLevel, float);
itkSetEnumMacro(FillMode, FillMode);
itkGetEnumMacro(FillMode, FillMode);
itkSetObjectMacro(Plane, const PlaneGeometry);
itkGetObjectMacro(Plane, const PlaneGeometry);
protected:
float m_BackgroundLevel;
PlaneGeometry::ConstPointer m_Plane;
FillMode m_FillMode;
PlaneCutFilter();
~PlaneCutFilter();
virtual void GenerateData();
template <typename TPixel, unsigned int VImageDimension>
- void _computeIntersection(itk::Image<TPixel, VImageDimension> *itkImage, const PlaneGeometry *plane, const Geometry3D *geometry);
+ void _computeIntersection(itk::Image<TPixel, VImageDimension> *itkImage, const PlaneGeometry *plane, const BaseGeometry *geometry);
};
} // namespace mitk
#endif /* PLANECUTFILTER_H_HEADER_INCLUDED_C1F48A22 */
diff --git a/Modules/Ext/Algorithms/mitkPlanesPerpendicularToLinesFilter.cpp b/Modules/Ext/Algorithms/mitkPlanesPerpendicularToLinesFilter.cpp
index 26b8115c35..2f95d42e41 100644
--- a/Modules/Ext/Algorithms/mitkPlanesPerpendicularToLinesFilter.cpp
+++ b/Modules/Ext/Algorithms/mitkPlanesPerpendicularToLinesFilter.cpp
@@ -1,212 +1,212 @@
/*===================================================================
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 "mitkPlanesPerpendicularToLinesFilter.h"
#include <vnl/vnl_cross.h>
#include <vnl/vnl_quaternion.h>
#include <vnl/vnl_quaternion.txx>
mitk::PlanesPerpendicularToLinesFilter::PlanesPerpendicularToLinesFilter()
: m_Plane(NULL), m_UseAllPoints(false), m_CreatedGeometries(NULL), normal(3), targetRight(3)
{
m_CreatedGeometries = mitk::SlicedGeometry3D::New();
}
mitk::PlanesPerpendicularToLinesFilter::~PlanesPerpendicularToLinesFilter()
{
}
void mitk::PlanesPerpendicularToLinesFilter::GenerateOutputInformation()
{
mitk::Mesh::ConstPointer input = this->GetInput();
mitk::GeometryData::Pointer output = this->GetOutput();
itkDebugMacro(<<"GenerateOutputInformation()");
if(input.IsNull()) return;
output->SetGeometry(m_CreatedGeometries);
}
void mitk::PlanesPerpendicularToLinesFilter::CreatePlane(const mitk::Point3D& curr)
{
int j;
for(j=0;j<3;++j)
normal[j] = last[j]-curr[j]; //@todo globally define normal direction of display xxx
normal.normalize();
down = vnl_cross_3d(normal, targetRight);
down.normalize();
right = vnl_cross_3d(down, normal);
right.normalize();
itk2vtk(last.GetVnlVector()-right*halfWidthInMM-down*halfHeightInMM, origin);
right *= targetSpacing[0];
down *= targetSpacing[1];
normal *= targetSpacing[2];
mitk::Matrix3D matrix;
matrix.GetVnlMatrix().set_column(0, right);
matrix.GetVnlMatrix().set_column(1, down);
matrix.GetVnlMatrix().set_column(2, normal);
PlaneGeometry::Pointer plane = PlaneGeometry::New();
plane->GetIndexToWorldTransform()->SetMatrix(matrix);
plane->SetOrigin(origin);
plane->SetBounds(bounds);
planes.push_back(plane);
last = curr;
}
void mitk::PlanesPerpendicularToLinesFilter::GenerateData()
{
mitk::Mesh::ConstPointer input = this->GetInput();
mitk::GeometryData::Pointer output = this->GetOutput();
if(m_Plane.IsNotNull())
{
targetRight = m_Plane->GetMatrixColumn(0);
targetSpacing = m_Plane->GetSpacing();
bounds = m_Plane->GetBoundingBox()->GetBounds();
halfWidthInMM = m_Plane->GetExtentInMM(0)*0.5;
halfHeightInMM = m_Plane->GetExtentInMM(1)*0.5;
}
else
{
FillVector3D(targetRight, 1.0, 0.0, 0.0);
targetSpacing.Fill(1.0);
halfWidthInMM=halfHeightInMM=100.0;
ScalarType stdBounds[6] = {0.0, 2.0*halfWidthInMM, 0.0, 2.0*halfHeightInMM, 0.0, 0.0};
bounds = stdBounds;
}
if(m_UseAllPoints==false)
{
int i, size;
//iterate through all cells and build planes
Mesh::ConstCellIterator cellIt, cellEnd;
cellEnd = input->GetMesh()->GetCells()->End();
for( cellIt = input->GetMesh()->GetCells()->Begin(); cellIt != cellEnd; ++cellIt )
{
Mesh::CellType& cell = *cellIt->Value();
Mesh::PointIdIterator ptIt, ptEnd;
ptEnd = cell.PointIdsEnd();
size=cell.GetNumberOfPoints();
if(size<=1)
continue;
ptIt = cell.PointIdsBegin();
last = input->GetPoint(*ptIt);
++ptIt;
for(i=1;i<size;++i, ++ptIt)
{
CreatePlane(input->GetPoint(*ptIt));
}
}
}
else //m_UseAllPoints==true
{
//iterate through all points and build planes
mitk::PointSet::PointsConstIterator it, pend = input->GetPointSet()->GetPoints()->End();
it=input->GetPointSet()->GetPoints()->Begin();
last = it.Value();
++it;
for(;it!=pend;++it)
{
CreatePlane(it.Value());
}
}
if(planes.size()>0)
{
//initialize sliced-geometry for the number of created planes
m_CreatedGeometries->InitializeSlicedGeometry(planes.size()+1);
//set last plane at last point with same normal as the one before the last
PlaneGeometry::Pointer plane = static_cast<PlaneGeometry*>((*planes.rbegin())->Clone().GetPointer());
itk2vtk(last.GetVnlVector()-right*halfWidthInMM-down*halfHeightInMM, origin);
plane->SetOrigin(origin);
- m_CreatedGeometries->SetGeometry2D(plane, planes.size());
+ m_CreatedGeometries->SetPlaneGeometry(plane, planes.size());
//add all planes to sliced-geometry
int s;
for(s=0; planes.empty()==false; planes.pop_front(), ++s)
{
- m_CreatedGeometries->SetGeometry2D(planes.front(), s);
+ m_CreatedGeometries->SetPlaneGeometry(planes.front(), s);
}
m_CreatedGeometries->SetEvenlySpaced(false);
if(m_FrameGeometry.IsNotNull())
{
m_CreatedGeometries->SetIndexToWorldTransform(m_FrameGeometry->GetIndexToWorldTransform());
m_CreatedGeometries->SetBounds(m_FrameGeometry->GetBounds());
m_CreatedGeometries->SetReferenceGeometry(m_FrameGeometry);
}
}
output->SetGeometry(m_CreatedGeometries);
}
void mitk::PlanesPerpendicularToLinesFilter::SetPlane(const mitk::PlaneGeometry* aPlane)
{
if(aPlane!=NULL)
{
m_Plane = static_cast<mitk::PlaneGeometry*>(aPlane->Clone().GetPointer());
}
else
{
if(m_Plane.IsNull())
return;
m_Plane=NULL;
}
Modified();
}
const mitk::Mesh *mitk::PlanesPerpendicularToLinesFilter::GetInput(void)
{
if (this->GetNumberOfInputs() < 1)
{
return 0;
}
return static_cast<const mitk::Mesh * >
(this->ProcessObject::GetInput(0) );
}
void mitk::PlanesPerpendicularToLinesFilter::SetInput(const mitk::Mesh *input)
{
// Process object is not const-correct so the const_cast is required here
this->ProcessObject::SetNthInput(0,
const_cast< mitk::Mesh * >( input ) );
}
-void mitk::PlanesPerpendicularToLinesFilter::SetFrameGeometry(const mitk::Geometry3D* frameGeometry)
+void mitk::PlanesPerpendicularToLinesFilter::SetFrameGeometry(const mitk::BaseGeometry* frameGeometry)
{
if((frameGeometry != NULL) && (frameGeometry->IsValid()))
{
- m_FrameGeometry = static_cast<mitk::Geometry3D*>(frameGeometry->Clone().GetPointer());
+ m_FrameGeometry = static_cast<mitk::BaseGeometry*>(frameGeometry->Clone().GetPointer());
}
else
{
m_FrameGeometry = NULL;
}
}
diff --git a/Modules/Ext/Algorithms/mitkPlanesPerpendicularToLinesFilter.h b/Modules/Ext/Algorithms/mitkPlanesPerpendicularToLinesFilter.h
index baddeb243c..f213ea24e1 100644
--- a/Modules/Ext/Algorithms/mitkPlanesPerpendicularToLinesFilter.h
+++ b/Modules/Ext/Algorithms/mitkPlanesPerpendicularToLinesFilter.h
@@ -1,145 +1,145 @@
/*===================================================================
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 MITKPLANESPERPENDICULARTOLINES_H_HEADER_INCLUDED_C10B22CD
#define MITKPLANESPERPENDICULARTOLINES_H_HEADER_INCLUDED_C10B22CD
#include "mitkGeometryDataSource.h"
#include "MitkExtExports.h"
#include "mitkMesh.h"
#include "mitkGeometryData.h"
#include "mitkPlaneGeometry.h"
#include "mitkSlicedGeometry3D.h"
namespace mitk {
//##Documentation
//## @brief Create Planes perpendicular to lines contained in a Mesh. The planes data is generated as one SlicedGeometry3D data.
//## To create the planes as input a
//## mitk::mesh (for example a pointSet) and as geometry hint a geometry (for example from the original image) must be given.
//##
//## mitk::Mesh::Pointer mesh = mitk::Mesh::New();
//## mesh->SetMesh(pointSet->GetPointSet());
//## mitk::Image* currentImage = dynamic_cast<mitk::Image*> (myDataStorage->GetNamedNode(IMAGE)->GetData());
//## const mitk::Geometry3D* imagegeometry = currentImage->GetUpdatedGeometry();
//## mitk::PlanesPerpendicularToLinesFilter::Pointer perpendicularPlanes = mitk::PlanesPerpendicularToLinesFilter::New();
//## perpendicularPlanes->SetInput(mesh);
//## perpendicularPlanes->SetUseAllPoints(true);
//## perpendicularPlanes->SetFrameGeometry(imagegeometry);
//## perpendicularPlanes->Update();
//##
-//## To get one single plane out of these use SlicedGeometry3D->GetGeometry2D(int slicenumber).
+//## To get one single plane out of these use SlicedGeometry3D->GetPlaneGeometry(int slicenumber).
//## @ingroup Process
class MitkExt_EXPORT PlanesPerpendicularToLinesFilter : public GeometryDataSource
{
public:
mitkClassMacro(PlanesPerpendicularToLinesFilter, GeometryDataSource);
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
virtual void GenerateOutputInformation();
virtual void GenerateData();
const mitk::Mesh *GetInput(void);
//## @brief Set the input mesh that is used to create the planes.
virtual void SetInput(const mitk::Mesh *image);
//##Documentation
//## @brief Set plane to be used as an example of the planes to move
//## along the lines in the input mesh.
//##
//## The size and spacing are copied from the plane. The in-plane
//## orientation (right-vector) of the created planes are set as
//## parallel as possible to the orientation (right-vector) of the
//## the plane set using this method.
//## @note The PlaneGeometry is cloned, @em not linked/referenced.
virtual void SetPlane(const mitk::PlaneGeometry* aPlane);
//##Documentation
//## @brief Set if all points in the mesh should be interpreted as
//## one long line.
//##
//## Cells are not used in this mode, but all points in the order
//## of their indices form the line.
//## Default is @a false.
itkGetConstMacro(UseAllPoints, bool);
//##Documentation
//## @brief Set if all points of the mesh shall be used (true) or the cells (false)
//## Default is @a false.
itkSetMacro(UseAllPoints, bool);
itkBooleanMacro(UseAllPoints);
//##Documentation
//## @brief Set an explicit frame of the created sliced geometry
//##
//## Set an explicit framegeometry for the created sliced geometry. This framegeometry is
//## used as geometry for all created planes.
//## Uses the IndexToWorldTransform and bounding box of the
//## provided geometry.
//## \sa CalculateFrameGeometry
- virtual void SetFrameGeometry(const mitk::Geometry3D* frameGeometry);
+ virtual void SetFrameGeometry(const mitk::BaseGeometry* frameGeometry);
protected:
PlanesPerpendicularToLinesFilter();
virtual ~PlanesPerpendicularToLinesFilter();
//## @brief Creates the plane at point curr
//##
//## Creates the plane at point curr. To create this plane, the last point must
//## must be renowned.
//## \sa SetPlane
void CreatePlane(const Point3D& curr);
//## @brief Plane to be used as an example of the planes to move
//## along the lines in the input mesh.
//##
//## The size and spacing are copied from the m_Plane. The in-plane
//## orientation (right-vector) of the created planes are set as
//## parallel as possible to the orientation (right-vector) of m_Plane.
//## \sa SetPlane
mitk::PlaneGeometry::Pointer m_Plane;
bool m_UseAllPoints;
//##Documentation
//## @brief SlicedGeometry3D containing the created planes
//##
SlicedGeometry3D::Pointer m_CreatedGeometries;
- mitk::Geometry3D::Pointer m_FrameGeometry;
+ mitk::BaseGeometry::Pointer m_FrameGeometry;
private:
std::deque<mitk::PlaneGeometry::Pointer> planes;
Point3D last;
VnlVector normal;
VnlVector right, down;
VnlVector targetRight;
Vector3D targetSpacing;
ScalarType halfWidthInMM, halfHeightInMM;
- mitk::Geometry3D::BoundsArrayType bounds;
+ mitk::BaseGeometry::BoundsArrayType bounds;
Point3D origin;
};
} // namespace mitk
#endif /* MITKPLANESPERPENDICULARTOLINES_H_HEADER_INCLUDED_C10B22CD */
diff --git a/Modules/Ext/Algorithms/mitkPointSetToCurvedGeometryFilter.cpp b/Modules/Ext/Algorithms/mitkPointSetToCurvedGeometryFilter.cpp
index a753331438..5b0941bdf6 100644
--- a/Modules/Ext/Algorithms/mitkPointSetToCurvedGeometryFilter.cpp
+++ b/Modules/Ext/Algorithms/mitkPointSetToCurvedGeometryFilter.cpp
@@ -1,165 +1,165 @@
/*===================================================================
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 "mitkPointSetToCurvedGeometryFilter.h"
#include "mitkThinPlateSplineCurvedGeometry.h"
#include "mitkPlaneGeometry.h"
#include "mitkImage.h"
#include "mitkDataNode.h"
#include "mitkGeometryData.h"
-#include "mitkGeometry2DData.h"
+#include "mitkPlaneGeometryData.h"
#include "mitkProperties.h"
#include "itkMesh.h"
#include "itkPointSet.h"
mitk::PointSetToCurvedGeometryFilter::PointSetToCurvedGeometryFilter()
{
m_ProjectionMode = YZPlane;
m_PCAPlaneCalculator = mitk::PlaneFit::New();
m_ImageToBeMapped = NULL;
m_Sigma = 1000;
- mitk::Geometry2DData::Pointer output = static_cast<mitk::Geometry2DData*> ( this->MakeOutput ( 0 ).GetPointer() );
+ mitk::PlaneGeometryData::Pointer output = static_cast<mitk::PlaneGeometryData*> ( this->MakeOutput ( 0 ).GetPointer() );
output->Initialize();
Superclass::SetNumberOfRequiredOutputs ( 1 );
Superclass::SetNthOutput ( 0, output.GetPointer() );
}
mitk::PointSetToCurvedGeometryFilter::~PointSetToCurvedGeometryFilter()
{}
void mitk::PointSetToCurvedGeometryFilter::GenerateOutputInformation()
{
mitk::PointSet::ConstPointer input = this->GetInput();
- mitk::Geometry2DData::Pointer output = dynamic_cast<mitk::Geometry2DData*> ( this->GetOutput() );
+ mitk::PlaneGeometryData::Pointer output = dynamic_cast<mitk::PlaneGeometryData*> ( this->GetOutput() );
if ( input.IsNull() )
itkGenericExceptionMacro ( "Input point set is NULL!" );
if ( input->GetTimeGeometry()->CountTimeSteps() != 1 )
itkWarningMacro ( "More than one time step is not yet supported!" );
if ( output.IsNull() )
itkGenericExceptionMacro ( "Output is NULL!" );
if ( m_ImageToBeMapped.IsNull() )
itkGenericExceptionMacro ( "Image to be mapped is NULL!" );
bool update = false;
- if ( output->GetGeometry() == NULL || output->GetGeometry2D() == NULL || output->GetTimeGeometry() == NULL )
+ if ( output->GetGeometry() == NULL || output->GetPlaneGeometry() == NULL || output->GetTimeGeometry() == NULL )
update = true;
if ( ( ! update ) && ( output->GetTimeGeometry()->CountTimeSteps() != input->GetTimeGeometry()->CountTimeSteps() ) )
update = true;
if ( update )
{
mitk::ThinPlateSplineCurvedGeometry::Pointer curvedGeometry = mitk::ThinPlateSplineCurvedGeometry::New();
output->SetGeometry(curvedGeometry);
}
}
void mitk::PointSetToCurvedGeometryFilter::GenerateData()
{
mitk::PointSet::ConstPointer input = this->GetInput();
mitk::GeometryData::Pointer output = this->GetOutput();
//
// check preconditions
//
if ( input.IsNull() )
itkGenericExceptionMacro ( "Input point set is NULL!" );
if ( output.IsNull() )
itkGenericExceptionMacro ( "output geometry data is NULL!" );
if ( output->GetTimeGeometry() == NULL )
itkGenericExceptionMacro ( "Output time sliced geometry is NULL!" );
if ( output->GetTimeGeometry()->GetGeometryForTimeStep ( 0 ).IsNull() )
itkGenericExceptionMacro ( "Output geometry3d is NULL!" );
mitk::ThinPlateSplineCurvedGeometry::Pointer curvedGeometry = dynamic_cast<mitk::ThinPlateSplineCurvedGeometry*> ( output->GetTimeGeometry()->GetGeometryForTimeStep( 0 ).GetPointer() );
if ( curvedGeometry.IsNull() )
itkGenericExceptionMacro ( "Output geometry3d is not an instance of mitk::ThinPlateSPlineCurvedGeometry!" );
if ( m_ImageToBeMapped.IsNull() )
itkGenericExceptionMacro ( "Image to be mapped is NULL!" );
//
// initialize members if needed
//
if ( m_XYPlane.IsNull() || m_XZPlane.IsNull() || m_YZPlane.IsNull() )
{
m_ImageToBeMapped->UpdateOutputInformation();
- const mitk::Geometry3D* imageGeometry = m_ImageToBeMapped->GetUpdatedGeometry();
+ const mitk::BaseGeometry* imageGeometry = m_ImageToBeMapped->GetUpdatedGeometry();
imageGeometry = m_ImageToBeMapped->GetUpdatedGeometry();
m_XYPlane = mitk::PlaneGeometry::New();
m_XZPlane = mitk::PlaneGeometry::New();
m_YZPlane = mitk::PlaneGeometry::New();
m_XYPlane->InitializeStandardPlane ( imageGeometry, mitk::PlaneGeometry::Axial );
m_YZPlane->InitializeStandardPlane ( imageGeometry, mitk::PlaneGeometry::Sagittal );
m_XZPlane->InitializeStandardPlane ( imageGeometry, mitk::PlaneGeometry::Frontal );
}
if ( m_PlaneLandmarkProjector.IsNull() )
{
m_PlaneLandmarkProjector = mitk::PlaneLandmarkProjector::New();
m_SphereLandmarkProjector = mitk::SphereLandmarkProjector::New();
}
//
// set up geometry according to the current settings
//
if ( m_ProjectionMode == Sphere )
{
curvedGeometry->SetLandmarkProjector ( m_SphereLandmarkProjector );
}
else
{
if ( m_ProjectionMode == XYPlane )
m_PlaneLandmarkProjector->SetProjectionPlane ( m_XYPlane );
else if ( m_ProjectionMode == XZPlane )
m_PlaneLandmarkProjector->SetProjectionPlane ( m_XZPlane );
else if ( m_ProjectionMode == YZPlane )
m_PlaneLandmarkProjector->SetProjectionPlane ( m_YZPlane );
else if ( m_ProjectionMode == PCAPlane )
{
itkExceptionMacro ( "PCAPlane not yet implemented!" );
m_PCAPlaneCalculator->SetInput ( input );
m_PCAPlaneCalculator->Update();
m_PlaneLandmarkProjector->SetProjectionPlane ( dynamic_cast<mitk::PlaneGeometry*> ( m_PCAPlaneCalculator->GetOutput() ) );
}
else
itkExceptionMacro ( "Unknown projection mode" );
curvedGeometry->SetLandmarkProjector ( m_PlaneLandmarkProjector );
}
//curvedGeometry->SetReferenceGeometry( m_ImageToBeMapped->GetGeometry() );
curvedGeometry->SetTargetLandmarks ( input->GetPointSet ( 0 )->GetPoints() );
curvedGeometry->SetSigma ( m_Sigma );
curvedGeometry->ComputeGeometry();
curvedGeometry->SetOversampling ( 1.0 );
}
void mitk::PointSetToCurvedGeometryFilter::SetDefaultCurvedGeometryProperties ( mitk::DataNode* node )
{
if ( node == NULL )
{
itkGenericOutputMacro ( "Warning: node is NULL!" );
return;
}
node->SetIntProperty ( "xresolution", 50 );
node->SetIntProperty ( "yresolution", 50 );
node->SetProperty ( "name", mitk::StringProperty::New ( "Curved Plane" ) );
// exclude extent of this plane when calculating DataStorage bounding box
node->SetProperty ( "includeInBoundingBox", mitk::BoolProperty::New ( false ) );
}
diff --git a/Modules/Ext/Algorithms/mitkPolygonToRingFilter.cpp b/Modules/Ext/Algorithms/mitkPolygonToRingFilter.cpp
index d6d8fa0c06..8fc7b9f744 100644
--- a/Modules/Ext/Algorithms/mitkPolygonToRingFilter.cpp
+++ b/Modules/Ext/Algorithms/mitkPolygonToRingFilter.cpp
@@ -1,341 +1,341 @@
/*===================================================================
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 "mitkPolygonToRingFilter.h"
#include "mitkMesh.h"
#include "mitkSurface.h"
#include "mitkPlaneGeometry.h"
#include <vnl/vnl_cross.h>
#include <vnl/vnl_quaternion.h>
#include <vnl/vnl_quaternion.txx>
#include <vtkPolyData.h>
#include <vtkPoints.h>
#include <vtkCellArray.h>
#include <vtkCardinalSpline.h>
#include <vector>
mitk::PolygonToRingFilter::PolygonToRingFilter()
: m_RingRadius(3.5f), m_RingResolution(30), m_SplineResolution(20)
{
m_SplineX = vtkCardinalSpline::New();
m_SplineY = vtkCardinalSpline::New();
m_SplineZ = vtkCardinalSpline::New();
}
mitk::PolygonToRingFilter::~PolygonToRingFilter()
{
m_SplineX->Delete();
m_SplineY->Delete();
m_SplineZ->Delete();
}
void mitk::PolygonToRingFilter::GenerateOutputInformation()
{
mitk::Mesh::ConstPointer input = this->GetInput();
mitk::Surface::Pointer output = this->GetOutput(0);
itkDebugMacro(<<"GenerateOutputInformation()");
if(input.IsNull()) return;
- output->SetGeometry(static_cast<Geometry3D*>(input->GetGeometry()->Clone().GetPointer()));
+ output->SetGeometry(static_cast<BaseGeometry*>(input->GetGeometry()->Clone().GetPointer()));
output->Expand( input->GetPointSetSeriesSize() );
}
void mitk::PolygonToRingFilter::GenerateData()
{
mitk::Mesh::ConstPointer input = this->GetInput();
mitk::Surface::Pointer output = this->GetOutput(0);
unsigned int t;
for ( t = 0; t < input->GetPointSetSeriesSize(); ++t )
{
vtkPolyData *polyData = vtkPolyData::New();
vtkPoints *vPoints = vtkPoints::New();
vtkCellArray *polys = vtkCellArray::New();
mitk::Mesh::PointType thisPoint;
// iterate through all cells and build tubes
Mesh::ConstCellIterator cellIt, cellEnd;
cellEnd = input->GetMesh( t )->GetCells()->End();
for ( cellIt = input->GetMesh( t )->GetCells()->Begin();
cellIt != cellEnd;
++cellIt )
{
m_PointList.clear();
m_VectorList.clear();
this->BuildPointAndVectorList(
*cellIt->Value(), m_PointList, m_VectorList, t );
this->BuildVtkTube( vPoints, polys, m_PointList, m_VectorList );
}
polyData->SetPoints( vPoints );
vPoints->Delete();
polyData->SetPolys( polys );
polys->Delete();
output->SetVtkPolyData( polyData, t );
polyData->Delete();
}
}
//sl: last star
//sc: current star
//idmax: Id of the current star ray (sc), which matchs proberly to the first ray of the last star (sl).
//last_p: center of the last star
//cur_p: center of the current star
void mitk::PolygonToRingFilter::DrawCyl(vtkPoints *vPoints, vtkCellArray *polys,
VectorListType &sl, VectorListType &sc, int idmax, Point3D & last_p, Point3D & cur_p)
{
unsigned int i;
//now we finished:sl0 will be connected with sc->at(idmax)
VectorListType::iterator slit=sl.begin(), scit=sc.begin(), scend=sc.end();
scit+=idmax;
Point3D a,b;
Point3D a_first,b_first;
int a_firstID = 0, b_firstID = 0;
vtkIdType front[4];
for(i=0;i<m_RingResolution;++i)
{
VnlVector v0,v1,v2,v3,normal;
v0=a.GetVnlVector(); v1=b.GetVnlVector();
a=last_p+*slit*m_RingRadius; b=cur_p+*scit*m_RingRadius;
v2=b.GetVnlVector(); v3=a.GetVnlVector();
normal=vnl_cross_3d(v1-v0,v3-v0);
if(i!=0)
{
front[3]=vPoints->InsertNextPoint(v0[0],v0[1],v0[2]);
front[2]=vPoints->InsertNextPoint(v1[0],v1[1],v1[2]);
front[1]=vPoints->InsertNextPoint(v2[0],v2[1],v2[2]);
front[0]=vPoints->InsertNextPoint(v3[0],v3[1],v3[2]);
polys->InsertNextCell( (vtkIdType) 4, front );
if(i==1)
{
a_firstID=front[3]; b_firstID=front[2]; //continue;
}
}
++slit; ++scit; if(scit==scend) scit=sc.begin();
}
front[3]=front[0];
front[2]=front[1];
front[1]=b_firstID;
front[0]=a_firstID;
polys->InsertNextCell( 4, front );
}
void mitk::PolygonToRingFilter::BuildVtkTube(vtkPoints *vPoints, vtkCellArray *polys, PointListType& ptList, VectorListType& vecList)
{
PointListType::iterator pit = ptList.begin(), pend = ptList.end();
VectorListType::iterator vit = vecList.begin();
Vector3D axis, last_v, next_v, s;
Point3D cur_p,last_p;
//lists for the star
VectorListType *sl, *sc, *swp, sfirst, buf1, buf2;
sl=&buf1; sc=&buf2;
Vector3D a,b;
Matrix3D m;
//Initialization for the first point
//alternative1:
// last_v=*(vl.getLast()); next_v=*vit.current(); axis=last_v+next_v; s.cross(last_v,next_v); s.normalize();
//alternative2:
// last_v=*(vl.getLast()); next_v=*vit.current(); s.cross(last_v,next_v); s.normalize();
// axis=next_v-last_v; axis.normalize(); aa.set(s, M_PI/2.0); m.set(aa); m.transform(&axis);
//alternative3:
last_v=vecList.back(); next_v=*vit; s.SetVnlVector( vnl_cross_3d(last_v.GetVnlVector(),next_v.GetVnlVector()) ); s.Normalize();
a=last_v; b=next_v; a.Normalize(); b.Normalize(); axis=a+b; axis.Normalize();
//build the star at the first point
m = vnl_quaternion<mitk::ScalarType>(axis.GetVnlVector(),2*vnl_math::pi/(double)m_RingResolution).rotation_matrix_transpose();
unsigned int i;
for(i=0;i<m_RingResolution;++i)
{
sfirst.push_back(s);
s=m*s;
}
*sl=sfirst;
last_p=*pit;
++pit; ++vit;
//mainloop for all points
for ( ; pit != pend; ++pit, ++vit )
{
// cur_p=*pit.current(); last_v=next_v; next_v=*vit.current(); axis=last_v+next_v; s.cross(last_v,next_v); s.normalize();
cur_p=*pit; last_v=next_v; next_v=*vit; s.SetVnlVector( vnl_cross_3d(last_v.GetVnlVector(),next_v.GetVnlVector()) ); s.Normalize();
// axis=next_v-last_v; axis.normalize(); aa.set(s, M_PI/2.0); m.set(aa); m.transform(&axis);
a=last_v; b=next_v; a.Normalize(); b.Normalize(); axis=a+b; axis.Normalize();
//build new star sc(currentStar) during searching for a start point for the new star
double max=0; int idmax=0; Vector3D sl0=*(sl->begin());
m = vnl_quaternion<mitk::ScalarType>(axis.GetVnlVector(),2*vnl_math::pi/(double)m_RingResolution).rotation_matrix_transpose();
for(i=0;i<m_RingResolution;++i)
{
sc->push_back(s);
double tmp=s*sl0;
if(tmp>max)
{
max=tmp;
idmax=i;
}
s=m*s;
}
//sl: last star
//sc: current star
//idmax: Id of the current star ray (sc), which matchs proberly to the first ray of the last star (sl).
//last_p: center of the last star
//cur_p: center of the current star
DrawCyl(vPoints, polys, *sl, *sc, idmax, last_p, cur_p);
//Crossover to the next
last_p=cur_p;
swp=sl; sl=sc; sc=swp; sc->clear();
}
//calcutate idmax for connection:
double max=0; int idmax=0; Vector3D sl0=*(sl->begin());
for(i=0;i<m_RingResolution;++i)
{
s=sfirst[i];
double tmp=s*sl0;
if(tmp>max)
{
max=tmp;
idmax=i;
}
}
cur_p=*ptList.begin();
DrawCyl(vPoints, polys, *sl, sfirst, idmax, last_p, cur_p);
}
void
mitk::PolygonToRingFilter
::BuildPointAndVectorList( mitk::Mesh::CellType& cell,
PointListType& ptList, VectorListType& vecList, int timeStep )
{
// This method constructs a spline from the given point list and retrieves
// a number of interpolated points from it to form a ring-like structure.
//
// To make the spline "closed", the end point is connected to the start
// point. For ensuring smoothness at the start-end-point transition, the
// (intrinsically non-circular) spline array is extended on both sides
// by wrapping a number of points from the respective other side.
//
// The used VTK filters do principally support this kind of "closed" spline,
// but it does not produce results as consistent as with the method used
// here. Also, the spline class of VTK 4.4 has only poor support for
// arbitrary parametric coordinates (t values in vtkSpline). VTK 5.0 has
// better support, and also provides a new class vtkParametricSpline for
// directly calculating 3D splines.
// Remove points from previous call of this method
m_SplineX->RemoveAllPoints();
m_SplineY->RemoveAllPoints();
m_SplineZ->RemoveAllPoints();
int numberOfPoints = cell.GetNumberOfPoints();
Mesh::PointType inputPoint;
double t, tStart(0), tEnd(0);
// Add input points to the spline and assign each the parametric value t
// derived from the point euclidean distances.
int i;
Mesh::PointIdIterator pit = cell.PointIdsEnd() - 3;
for ( i = -3, t = 0.0; i < numberOfPoints + 3; ++i )
{
if ( i == 0 ) { tStart = t; }
if ( i == numberOfPoints ) { tEnd = t; }
inputPoint = this->GetInput()->GetPoint( *pit, timeStep );
m_SplineX->AddPoint( t, inputPoint[0] );
m_SplineY->AddPoint( t, inputPoint[1] );
m_SplineZ->AddPoint( t, inputPoint[2] );
++pit;
if ( pit == cell.PointIdsEnd() )
{
pit = cell.PointIdsBegin();
}
t += inputPoint.EuclideanDistanceTo(
this->GetInput()->GetPoint( *pit, timeStep ) );
}
// Evaluate the spline for the desired number of points
// (number of input points) * (spline resolution)
Point3D point, firstPoint, lastPoint;
firstPoint.Fill(0);
lastPoint.Fill(0);
int numberOfSegments = numberOfPoints * m_SplineResolution;
double step = (tEnd - tStart) / numberOfSegments;
for ( i = 0, t = tStart; i < numberOfSegments; ++i, t += step )
{
FillVector3D( point,
m_SplineX->Evaluate(t), m_SplineY->Evaluate(t), m_SplineZ->Evaluate(t)
);
ptList.push_back( point );
if ( i == 0 )
{
firstPoint = point;
}
else
{
vecList.push_back( point - lastPoint );
}
lastPoint = point;
}
vecList.push_back( firstPoint - lastPoint );
}
const mitk::Mesh *mitk::PolygonToRingFilter::GetInput(void)
{
if (this->GetNumberOfInputs() < 1)
{
return 0;
}
return static_cast<const mitk::Mesh * >
(this->ProcessObject::GetInput(0) );
}
void mitk::PolygonToRingFilter::SetInput(const mitk::Mesh *input)
{
// Process object is not const-correct so the const_cast is required here
this->ProcessObject::SetNthInput(0,
const_cast< mitk::Mesh * >( input ) );
}
diff --git a/Modules/Ext/Algorithms/mitkProbeFilter.cpp b/Modules/Ext/Algorithms/mitkProbeFilter.cpp
index f3c6416b1f..c54135875e 100644
--- a/Modules/Ext/Algorithms/mitkProbeFilter.cpp
+++ b/Modules/Ext/Algorithms/mitkProbeFilter.cpp
@@ -1,213 +1,214 @@
/*===================================================================
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 "mitkProbeFilter.h"
#include "mitkSurface.h"
#include "mitkImage.h"
#include <vtkProbeFilter.h>
#include <itkImageRegion.h>
#include <vtkDataSet.h>
#include <vtkPolyData.h>
#include <vtkImageData.h>
mitk::ProbeFilter::ProbeFilter()
{
-
}
mitk::ProbeFilter::~ProbeFilter()
{
-
}
const mitk::Surface *mitk::ProbeFilter::GetInput(void)
{
if (this->GetNumberOfInputs() < 1)
{
return 0;
}
return static_cast< const mitk::Surface * >(this->ProcessObject::GetInput(0) );
}
const mitk::Image *mitk::ProbeFilter::GetSource(void)
{
return static_cast< const mitk::Image * >(this->ProcessObject::GetInput(1));
}
void mitk::ProbeFilter::SetInput(const mitk::Surface *input)
{
this->ProcessObject::SetNthInput( 0, const_cast< mitk::Surface * >( input ) );
}
void mitk::ProbeFilter::SetSource(const mitk::Image *source)
{
this->ProcessObject::SetNthInput( 1, const_cast< mitk::Image * >( source ) );
}
void mitk::ProbeFilter::GenerateOutputInformation()
{
mitk::Surface::ConstPointer input = this->GetInput();
mitk::Image::ConstPointer source = this->GetSource();
mitk::Surface::Pointer output = this->GetOutput();
if(input.IsNull()) return;
if(source.IsNull()) return;
if(input->GetGeometry()==NULL) return;
if(source->GetGeometry()==NULL) return;
if( (input->GetTimeGeometry()->CountTimeSteps()==1) && (source->GetTimeGeometry()->CountTimeSteps()>1) )
{
- Geometry3D::Pointer geometry3D = Geometry3D::New();
+ Geometry3D::Pointer geo3D = Geometry3D::New();
+ BaseGeometry::Pointer geometry3D = dynamic_cast<BaseGeometry*>(geo3D.GetPointer());
geometry3D->Initialize();
geometry3D->SetBounds(source->GetTimeGeometry()->GetBoundsInWorld());
- geometry3D->SetTimeBounds(source->GetTimeGeometry()->GetGeometryForTimeStep(0)->GetTimeBounds());
ProportionalTimeGeometry::Pointer outputTimeGeometry = ProportionalTimeGeometry::New();
outputTimeGeometry->Initialize(geometry3D, source->GetTimeGeometry()->CountTimeSteps());
+ outputTimeGeometry->SetFirstTimePoint(source->GetTimeGeometry()->GetMinimumTimePoint());
+ TimePointType stepDuration = source->GetTimeGeometry()->GetMaximumTimePoint(0) - source->GetTimeGeometry()->GetMinimumTimePoint(0);
+ outputTimeGeometry->SetStepDuration(stepDuration);
output->Expand(outputTimeGeometry->CountTimeSteps());
output->SetTimeGeometry( outputTimeGeometry );
}
else
- output->SetGeometry( static_cast<Geometry3D*>(input->GetGeometry()->Clone().GetPointer()) );
+ output->SetGeometry( static_cast<BaseGeometry*>(input->GetGeometry()->Clone().GetPointer()) );
itkDebugMacro(<<"GenerateOutputInformation()");
}
void mitk::ProbeFilter::GenerateData()
{
mitk::Surface *input = const_cast< mitk::Surface * >(this->GetInput());
mitk::Image *source = const_cast< mitk::Image * >(this->GetSource());
mitk::Surface::Pointer output = this->GetOutput();
itkDebugMacro(<<"Generating Data");
if(output.IsNull())
{
itkDebugMacro(<<"Output is NULL.");
return;
}
mitk::Surface::RegionType outputRegion = output->GetRequestedRegion();
const TimeGeometry *outputTimeGeometry = output->GetTimeGeometry();
const TimeGeometry *inputTimeGeometry = input->GetTimeGeometry();
const TimeGeometry *sourceTimeGeometry = source->GetTimeGeometry();
TimePointType timeInMS;
int timestep=0;
int tstart, tmax;
tstart=outputRegion.GetIndex(3);
tmax=tstart+outputRegion.GetSize(3);
int t;
for(t=tstart;t<tmax;++t)
{
timeInMS = outputTimeGeometry->TimeStepToTimePoint( t );
vtkProbeFilter* probe = vtkProbeFilter::New();
timestep = inputTimeGeometry->TimePointToTimeStep( timeInMS );
probe->SetInputData( input->GetVtkPolyData(timestep) );
timestep = sourceTimeGeometry->TimePointToTimeStep( timeInMS );
probe->SetSourceData( source->GetVtkImageData(timestep) );
output->SetVtkPolyData( probe->GetPolyDataOutput(), t );
probe->Update();
probe->Delete();
}
}
void mitk::ProbeFilter::GenerateInputRequestedRegion()
{
Superclass::GenerateInputRequestedRegion();
mitk::Surface *input = const_cast< mitk::Surface * >( this->GetInput() );
mitk::Image *source = const_cast< mitk::Image * >( this->GetSource() );
if(input==NULL) return;
if(source==NULL) return;
mitk::Surface::Pointer output = this->GetOutput();
mitk::Surface::RegionType outputRegion = output->GetRequestedRegion();
const TimeGeometry *outputTimeGeometry = output->GetTimeGeometry();
mitk::Surface::RegionType inputSurfaceRegion = outputRegion;
Image::RegionType sourceImageRegion = source->GetLargestPossibleRegion();
if(outputRegion.GetSize(3)<1)
{
mitk::Surface::RegionType::SizeType surfacesize;
surfacesize.Fill(0);
inputSurfaceRegion.SetSize(surfacesize);
input->SetRequestedRegion( &inputSurfaceRegion );
mitk::Image::RegionType::SizeType imagesize;
imagesize.Fill(0);
sourceImageRegion.SetSize(imagesize);
source->SetRequestedRegion( &sourceImageRegion );
return;
}
//create and set input requested region for the input surface
const TimeGeometry *inputTimeGeometry = input->GetTimeGeometry();
ScalarType timeInMS;
int timestep=0;
// convert the start-index-time of output in start-index-time of input via millisecond-time
timeInMS = outputTimeGeometry->TimeStepToTimePoint(outputRegion.GetIndex(3));
timestep = inputTimeGeometry->TimePointToTimeStep( timeInMS );
if( ( timeInMS > ScalarTypeNumericTraits::NonpositiveMin() ) && ( inputTimeGeometry->IsValidTimeStep( timestep ) ) )
inputSurfaceRegion.SetIndex( 3, timestep );
else
inputSurfaceRegion.SetIndex( 3, 0 );
// convert the end-index-time of output in end-index-time of input via millisecond-time
timeInMS = outputTimeGeometry->TimeStepToTimePoint(outputRegion.GetIndex(3)+outputRegion.GetSize(3)-1);
timestep = inputTimeGeometry->TimePointToTimeStep( timeInMS );
if( ( timeInMS > ScalarTypeNumericTraits::NonpositiveMin() ) && ( outputTimeGeometry->IsValidTimeStep( timestep ) ) )
inputSurfaceRegion.SetSize( 3, timestep - inputSurfaceRegion.GetIndex(3) + 1 );
else
inputSurfaceRegion.SetSize( 3, 1 );
input->SetRequestedRegion( &inputSurfaceRegion );
//create and set input requested region for the source image
const TimeGeometry *sourceTimeGeometry = source->GetTimeGeometry();
// convert the start-index-time of output in start-index-time of source via millisecond-time
timeInMS = outputTimeGeometry->TimeStepToTimePoint(outputRegion.GetIndex(3));
timestep = sourceTimeGeometry->TimePointToTimeStep( timeInMS );
if( ( timeInMS > ScalarTypeNumericTraits::NonpositiveMin() ) && ( sourceTimeGeometry->IsValidTimeStep( timestep ) ) )
sourceImageRegion.SetIndex( 3, timestep );
else
sourceImageRegion.SetIndex( 3, 0 );
// convert the end-index-time of output in end-index-time of source via millisecond-time
timeInMS = outputTimeGeometry->TimeStepToTimePoint(outputRegion.GetIndex(3)+outputRegion.GetSize(3)-1);
timestep = sourceTimeGeometry->TimePointToTimeStep( timeInMS );
if( ( timeInMS > ScalarTypeNumericTraits::NonpositiveMin() ) && ( outputTimeGeometry->IsValidTimeStep( timestep ) ) )
sourceImageRegion.SetSize( 3, timestep - sourceImageRegion.GetIndex(3) + 1 );
else
sourceImageRegion.SetSize( 3, 1 );
sourceImageRegion.SetIndex( 4, 0 );
sourceImageRegion.SetSize( 4, 1 );
source->SetRequestedRegion( &sourceImageRegion );
}
diff --git a/Modules/Ext/IO/mitkParRecFileReader.cpp b/Modules/Ext/IO/mitkParRecFileReader.cpp
index c2d98807a4..045064e54d 100644
--- a/Modules/Ext/IO/mitkParRecFileReader.cpp
+++ b/Modules/Ext/IO/mitkParRecFileReader.cpp
@@ -1,292 +1,292 @@
/*===================================================================
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 "mitkParRecFileReader.h"
#include <itkImageFileReader.h>
#ifdef __GNUC__
#define stricmp strcasecmp
#endif
void mitk::ParRecFileReader::GenerateOutputInformation()
{
mitk::Image::Pointer output = this->GetOutput();
if ((output->IsInitialized()) && (this->GetMTime() <= m_ReadHeaderTime.GetMTime()))
return;
itkDebugMacro(<<"Reading PAR file for GenerateOutputInformation()" << m_FileName);
// Check to see if we can read the file given the name or prefix
//
if ( m_FileName == "" && m_FilePrefix == "" )
{
throw itk::ImageFileReaderException(__FILE__, __LINE__, "One of FileName or FilePrefix must be non-empty");
}
m_RecFileName = "";
if( m_FileName != "")
{
int extPos=m_FileName.find_last_of(".");
if(extPos>=-1)
{
const char *ext=m_FileName.c_str()+extPos+1;
if(stricmp(ext,"par")==0)
m_RecFileName = m_FileName.substr(0,extPos);
else
m_RecFileName = m_FileName;
}
else
m_RecFileName = m_FileName;
m_RecFileName.append(".rec");
bool headerRead = false;
bool signedCharType = true;
unsigned int dimension=0;
unsigned int dimensions[4]={0,0,1,1};
float sliceThickness=0.0;
float sliceGap=0.0;
float sliceSpacing=0.0;
mitk::Vector3D thickness; thickness.Fill(1.0);
mitk::Vector3D gap; gap.Fill(0.0);
mitk::Vector3D spacing;
FILE *f;
f=fopen(m_FileName.c_str(), "r");
if(f!=NULL)
{
while(!feof(f))
{
char s[300], *p;
char* ignored = fgets(s,200,f);
++ignored;
if(strstr(s,"Max. number of cardiac phases"))
{
p=strchr(s,':')+1;
dimensions[3]=atoi(p);
if(dimensions[3]>1)
dimension=4;
}
else
if(strstr(s,"Max. number of slices/locations"))
{
p=strchr(s,':')+1;
dimensions[2]=atoi(p);
if(dimension==0)
{
if(dimensions[2]>1)
dimension=3;
else
dimension=2;
}
}
else
if(strstr(s,"Image pixel size"))
{
p=strchr(s,':')+1;
int bpe=atoi(p);
if(bpe!=8)
signedCharType = false;
}
else
if(strstr(s,"Recon resolution"))
{
p=s+strcspn(s,"0123456789");
sscanf(p,"%u %u", dimensions, dimensions+1);
}
else
if(strstr(s,"FOV (ap,fh,rl) [mm]"))
{
p=s+strcspn(s,"0123456789");
char *oldLocale = setlocale(LC_ALL, 0);
sscanf(p,"%f %f %f", &thickness[0], &thickness[1], &thickness[2]);
setlocale(LC_ALL, oldLocale);
}
else
if(strstr(s,"Slice thickness [mm]"))
{
p=s+strcspn(s,"0123456789");
char *oldLocale = setlocale(LC_ALL, 0);
sscanf(p,"%f", &sliceThickness);
setlocale(LC_ALL, oldLocale);
}
else
if(strstr(s,"Slice gap [mm]"))
{
p=s+strcspn(s,"-0123456789");
char *oldLocale = setlocale(LC_ALL, 0);
sscanf(p,"%f", &sliceGap);
setlocale(LC_ALL, oldLocale);
}
}
fclose(f);
//C:\home\ivo\data\coronaries\ucsf-wholeheart-2.par
sliceSpacing = sliceThickness+sliceGap;
if((dimension>0) && (dimensions[0]>0) && (dimensions[1]>0) && (sliceThickness>0) && (sliceSpacing>0))
{
headerRead = true;
if(fabs(thickness[0]/dimensions[2]-sliceSpacing)<0.0001)
thickness[0]=thickness[1];
else
if(fabs(thickness[1]/dimensions[2]-sliceSpacing)<0.0001)
thickness[1]=thickness[0];
thickness[2]=sliceSpacing;
thickness[0]/=dimensions[0];
thickness[1]/=dimensions[1];
spacing=thickness+gap;
}
}
if( headerRead == false)
{
itk::ImageFileReaderException e(__FILE__, __LINE__);
std::ostringstream msg;
msg << " Could not read file "
<< m_FileName.c_str();
e.SetDescription(msg.str().c_str());
throw e;
return;
}
// define types
mitk::PixelType SCType = mitk::MakeScalarPixelType<signed char>();
mitk::PixelType SSType = mitk::MakeScalarPixelType<signed short>();
if( signedCharType )
output->Initialize(SCType, dimension, dimensions);
else
output->Initialize(SSType, dimension, dimensions);
output->GetSlicedGeometry()->SetSpacing(spacing);
- //output->GetSlicedGeometry()->SetGeometry2D(mitk::Image::BuildStandardPlaneGeometry2D(output->GetSlicedGeometry(), dimensions).GetPointer(), 0);
+ //output->GetSlicedGeometry()->SetPlaneGeometry(mitk::Image::BuildStandardPlanePlaneGeometry(output->GetSlicedGeometry(), dimensions).GetPointer(), 0);
output->GetSlicedGeometry()->SetEvenlySpaced();
}
m_ReadHeaderTime.Modified();
}
void mitk::ParRecFileReader::GenerateData()
{
mitk::Image::Pointer output = this->GetOutput();
// Check to see if we can read the file given the name or prefix
//
if ( m_RecFileName == "" )
{
throw itk::ImageFileReaderException(__FILE__, __LINE__, "FileName for rec-file empty");
}
if( m_RecFileName != "")
{
FILE *f = fopen(m_RecFileName.c_str(), "r");
if(f==NULL)
{
throw itk::ImageFileReaderException(__FILE__, __LINE__, "Could not open rec-file.");
}
int zstart, zmax;
int tstart, tmax;
zstart=output->GetRequestedRegion().GetIndex(2);
tstart=output->GetRequestedRegion().GetIndex(3);
zmax=zstart+output->GetRequestedRegion().GetSize(2);
tmax=tstart+output->GetRequestedRegion().GetSize(3);
int sliceSize=output->GetDimension(0)*output->GetDimension(1)*output->GetPixelType().GetBpe()/8;
void *data = malloc(sliceSize);
bool ignore4Dtopogram=false;
{
int slicePlusTimeSize=output->GetDimension(0)*output->GetDimension(1)*output->GetDimension(3)*output->GetPixelType().GetBpe()/8;
if(output->GetDimension(3)>1)
ignore4Dtopogram=true;
int z,t;
for(t=tstart;t<tmax;++t)
for(z=zstart;z<zmax;++z)
{
if(ignore4Dtopogram)
fseek(f,slicePlusTimeSize*z+(sliceSize+1)*t,SEEK_SET);
else
fseek(f,slicePlusTimeSize*z+sliceSize*t,SEEK_SET);
size_t ignored = fread(data, sliceSize, 1, f);
++ignored;
output->SetSlice(data,z,t,0);
}
}
//else
//{
// for(;z<zmax;++z)
// {
// fseek(f,sliceSize*z,SEEK_SET);
// fread(data, sliceSize, 1, f);
// output->SetSlice(data,z,0,0);
// }
//}
free(data);
fclose(f);
}
}
bool mitk::ParRecFileReader::CanReadFile(const std::string filename, const std::string /*filePrefix*/, const std::string /*filePattern*/)
{
// First check the extension
if( filename == "" )
{
//MITK_INFO<<"No filename specified."<<std::endl;
return false;
}
bool extensionFound = false;
std::string::size_type PARPos = filename.rfind(".par");
if ((PARPos != std::string::npos)
&& (PARPos == filename.length() - 4))
{
extensionFound = true;
}
PARPos = filename.rfind(".PAR");
if ((PARPos != std::string::npos)
&& (PARPos == filename.length() - 4))
{
extensionFound = true;
}
if( !extensionFound )
{
//MITK_INFO<<"The filename extension is not recognized."<<std::endl;
return false;
}
return true;
}
mitk::ParRecFileReader::ParRecFileReader()
: m_FileName(""), m_FilePrefix(""), m_FilePattern("")
{
}
mitk::ParRecFileReader::~ParRecFileReader()
{
}
diff --git a/Modules/Ext/IO/mitkUnstructuredGridVtkWriter.txx b/Modules/Ext/IO/mitkUnstructuredGridVtkWriter.txx
index c4890229c4..46eb319ee5 100644
--- a/Modules/Ext/IO/mitkUnstructuredGridVtkWriter.txx
+++ b/Modules/Ext/IO/mitkUnstructuredGridVtkWriter.txx
@@ -1,205 +1,203 @@
/*===================================================================
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 _MITK_UNSTRUCTURED_GRID_VTKWRITER_TXX_
#define _MITK_UNSTRUCTURED_GRID_VTKWRITER_TXX_
#include <itkLightObject.h>
#include <vtkUnstructuredGrid.h>
#include <vtkLinearTransform.h>
#include <vtkTransformFilter.h>
#include <vtkUnstructuredGridWriter.h>
#include <vtkXMLUnstructuredGridWriter.h>
#include <vtkXMLPUnstructuredGridWriter.h>
#include <sstream>
#include <sys/stat.h>
#include <sys/types.h>
#include <stdio.h>
namespace mitk {
template<class VTKWRITER>
UnstructuredGridVtkWriter<VTKWRITER>::UnstructuredGridVtkWriter()
: m_Success(false)
{
this->SetNumberOfRequiredInputs(1);
}
template<class VTKWRITER>
UnstructuredGridVtkWriter<VTKWRITER>::~UnstructuredGridVtkWriter()
{
}
template<class VTKWRITER>
void UnstructuredGridVtkWriter<VTKWRITER>::GenerateData()
{
m_Success = false;
if ( m_FileName == "" )
{
itkWarningMacro( << "Sorry, filename has not been set!" );
return ;
}
mitk::UnstructuredGrid::Pointer input = const_cast<mitk::UnstructuredGrid*>(this->GetInput());
if (input.IsNull())
{
itkWarningMacro( << "Sorry, input to mitk::UnstructuredGridVtkWriter is NULL");
return;
}
VTKWRITER* unstructuredGridWriter = VTKWRITER::New();
vtkTransformFilter* transformPointSet = vtkTransformFilter::New();
vtkUnstructuredGrid * unstructuredGrid;
- Geometry3D* geometry;
+ BaseGeometry* geometry;
if(input->GetTimeGeometry()->CountTimeSteps()>1)
{
int t, timesteps;
timesteps = input->GetTimeGeometry()->CountTimeSteps();
for(t = 0; t < timesteps; ++t)
{
std::ostringstream filename;
geometry = input->GetGeometry(t);
if(input->GetTimeGeometry()->IsValidTimeStep(t))
{
- const mitk::TimeBounds& timebounds = geometry->GetTimeBounds();
+ const mitk::TimeBounds& timebounds = input->GetTimeGeometry()->GetTimeBounds(t);
filename << m_FileName.c_str() << "_S" << std::setprecision(0) << timebounds[0] << "_E" << std::setprecision(0) << timebounds[1] << "_T" << t << GetDefaultExtension();
}
else
{
itkWarningMacro(<<"Error on write: TimeGeometry invalid of unstructured grid " << filename.str() << ".");
filename << m_FileName.c_str() << "_T" << t << GetDefaultExtension();
}
- geometry->TransferItkToVtkTransform();
transformPointSet->SetInputData(input->GetVtkUnstructuredGrid(t));
transformPointSet->SetTransform(geometry->GetVtkTransform());
transformPointSet->UpdateWholeExtent();
unstructuredGrid = static_cast<vtkUnstructuredGrid*>(transformPointSet->GetOutput());
unstructuredGridWriter->SetFileName(filename.str().c_str());
unstructuredGridWriter->SetInputData(unstructuredGrid);
ExecuteWrite( unstructuredGridWriter );
}
}
else
{
geometry = input->GetGeometry();
- geometry->TransferItkToVtkTransform();
transformPointSet->SetInputData(input->GetVtkUnstructuredGrid());
transformPointSet->SetTransform(geometry->GetVtkTransform());
transformPointSet->UpdateWholeExtent();
unstructuredGrid = static_cast<vtkUnstructuredGrid*>(transformPointSet->GetOutput());
unstructuredGridWriter->SetFileName(m_FileName.c_str());
unstructuredGridWriter->SetInputData(unstructuredGrid);
ExecuteWrite( unstructuredGridWriter );
}
transformPointSet->Delete();
unstructuredGridWriter->Delete();
m_Success = true;
}
template<class VTKWRITER>
void UnstructuredGridVtkWriter<VTKWRITER>::ExecuteWrite( VTKWRITER* vtkWriter )
{
struct stat fileStatus;
time_t timeBefore=0;
if (!stat(vtkWriter->GetFileName(), &fileStatus))
{
timeBefore = fileStatus.st_mtime;
}
if (!vtkWriter->Write())
{
itkExceptionMacro( << "Error during unstructured grid writing.");
}
// check if file can be written because vtkWriter doesn't check that
if (stat(vtkWriter->GetFileName(), &fileStatus) || (timeBefore == fileStatus.st_mtime))
{
itkExceptionMacro(<<"Error during unstructured grid writing: file could not be written");
}
}
template<class VTKWRITER>
void UnstructuredGridVtkWriter<VTKWRITER>::SetInput(BaseData *input)
{
this->ProcessObject::SetNthInput(0, input);
}
template<class VTKWRITER>
const UnstructuredGrid* UnstructuredGridVtkWriter<VTKWRITER>::GetInput()
{
if (this->GetNumberOfInputs() < 1)
{
return 0;
}
else
{
return dynamic_cast<UnstructuredGrid*>(this->ProcessObject::GetInput(0));
}
}
template<class VTKWRITER>
bool UnstructuredGridVtkWriter<VTKWRITER>::CanWriteBaseDataType(BaseData::Pointer data)
{
return (dynamic_cast<mitk::UnstructuredGrid*>(data.GetPointer()) != 0);
}
template<class VTKWRITER>
void UnstructuredGridVtkWriter<VTKWRITER>::DoWrite(BaseData::Pointer data)
{
if (CanWriteBaseDataType(data))
{
this->SetInput(dynamic_cast<mitk::UnstructuredGrid*>(data.GetPointer()));
this->Update();
}
}
template<class VTKWRITER>
std::vector<std::string> UnstructuredGridVtkWriter<VTKWRITER>::GetPossibleFileExtensions()
{
throw std::exception(); // no specialization available!
}
template<class VTKWRITER>
const char* UnstructuredGridVtkWriter<VTKWRITER>::GetDefaultFilename()
{
throw std::exception(); // no specialization available!
}
template<class VTKWRITER>
const char* UnstructuredGridVtkWriter<VTKWRITER>::GetFileDialogPattern()
{
throw std::exception(); // no specialization available!
}
template<class VTKWRITER>
const char* UnstructuredGridVtkWriter<VTKWRITER>::GetDefaultExtension()
{
throw std::exception(); // no specialization available!
}
}
#endif
diff --git a/Modules/Ext/Interactions/mitkAffineInteractor3D.cpp b/Modules/Ext/Interactions/mitkAffineInteractor3D.cpp
index c34ddabfe4..0c0f25130e 100644
--- a/Modules/Ext/Interactions/mitkAffineInteractor3D.cpp
+++ b/Modules/Ext/Interactions/mitkAffineInteractor3D.cpp
@@ -1,488 +1,489 @@
/*===================================================================
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 "mitkAffineInteractor3D.h"
#include "mitkPointOperation.h"
#include "mitkPositionEvent.h"
#include "mitkStatusBar.h"
#include "mitkDataNode.h"
#include "mitkInteractionConst.h"
#include "mitkAction.h"
#include "mitkStateEvent.h"
#include "mitkOperationEvent.h"
#include "mitkUndoController.h"
#include "mitkStateMachineFactory.h"
#include "mitkStateTransitionOperation.h"
#include "mitkBaseRenderer.h"
#include "mitkRenderingManager.h"
#include "mitkRotationOperation.h"
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyle.h>
#include <vtkRenderer.h>
#include <vtkCamera.h>
#include <vtkPoints.h>
#include <vtkPointData.h>
#include <vtkDataArray.h>
namespace mitk
{
//how precise must the user pick the point
//default value
AffineInteractor3D
::AffineInteractor3D(const char * type, DataNode* dataNode, int /* n */ )
: Interactor( type, dataNode ),
m_Precision( 6.5 ),
m_InteractionMode( INTERACTION_MODE_TRANSLATION )
{
- m_OriginalGeometry = Geometry3D::New();
+ Geometry3D::Pointer geo3D = Geometry3D::New();
+ m_OriginalGeometry = dynamic_cast<BaseGeometry*>(geo3D.GetPointer());
// Initialize vector arithmetic
m_ObjectNormal[0] = 0.0;
m_ObjectNormal[1] = 0.0;
m_ObjectNormal[2] = 1.0;
}
AffineInteractor3D::~AffineInteractor3D()
{
}
void AffineInteractor3D::SetInteractionMode( unsigned int interactionMode )
{
m_InteractionMode = interactionMode;
}
void AffineInteractor3D::SetInteractionModeToTranslation()
{
m_InteractionMode = INTERACTION_MODE_TRANSLATION;
}
void AffineInteractor3D::SetInteractionModeToRotation()
{
m_InteractionMode = INTERACTION_MODE_ROTATION;
}
unsigned int AffineInteractor3D::GetInteractionMode() const
{
return m_InteractionMode;
}
void AffineInteractor3D::SetPrecision( ScalarType precision )
{
m_Precision = precision;
}
// Overwritten since this class can handle it better!
float AffineInteractor3D
::CanHandleEvent(StateEvent const* stateEvent) const
{
float returnValue = 0.5;
// If it is a key event that can be handled in the current state,
// then return 0.5
DisplayPositionEvent const *disPosEvent =
dynamic_cast <const DisplayPositionEvent *> (stateEvent->GetEvent());
// Key event handling:
if (disPosEvent == NULL)
{
// Check if the current state has a transition waiting for that key event.
if (this->GetCurrentState()->GetTransition(stateEvent->GetId())!=NULL)
{
return 0.5;
}
else
{
return 0.0;
}
}
//on MouseMove do nothing!
//if (stateEvent->GetEvent()->GetType() == Type_MouseMove)
//{
// return 0.0;
//}
//if the event can be understood and if there is a transition waiting for that event
if (this->GetCurrentState()->GetTransition(stateEvent->GetId())!=NULL)
{
returnValue = 0.5;//it can be understood
}
//int timeStep = disPosEvent->GetSender()->GetTimeStep();
//CurveModel *curveModel = dynamic_cast<CurveModel *>(
// m_DataNode->GetData() );
//if ( curveModel != NULL )
//{
- // // Get the Geometry2D of the window the user interacts with (for 2D point
+ // // Get the PlaneGeometry of the window the user interacts with (for 2D point
// // projection)
// BaseRenderer *renderer = stateEvent->GetEvent()->GetSender();
- // const Geometry2D *projectionPlane = renderer->GetCurrentWorldGeometry2D();
+ // const PlaneGeometry *projectionPlane = renderer->GetCurrentWorldPlaneGeometry();
// // For reading on the points, Ids etc
// //CurveModel::PointSetType *pointSet = curveModel->GetPointSet( timeStep );
// //if ( pointSet == NULL )
// //{
// // return 0.0;
// //}
//}
return returnValue;
}
bool AffineInteractor3D
::ExecuteAction( Action *action, StateEvent const *stateEvent )
{
bool ok = false;
// Get data object
BaseData *data = m_DataNode->GetData();
if ( data == NULL )
{
MITK_ERROR << "No data object present!";
return ok;
}
// Get Event and extract renderer
const Event *event = stateEvent->GetEvent();
BaseRenderer *renderer = NULL;
vtkRenderWindow *renderWindow = NULL;
vtkRenderWindowInteractor *renderWindowInteractor = NULL;
vtkRenderer *currentVtkRenderer = NULL;
vtkCamera *camera = NULL;
if ( event != NULL )
{
renderer = event->GetSender();
if ( renderer != NULL )
{
renderWindow = renderer->GetRenderWindow();
if ( renderWindow != NULL )
{
renderWindowInteractor = renderWindow->GetInteractor();
if ( renderWindowInteractor != NULL )
{
currentVtkRenderer = renderWindowInteractor
->GetInteractorStyle()->GetCurrentRenderer();
if ( currentVtkRenderer != NULL )
{
camera = currentVtkRenderer->GetActiveCamera();
}
}
}
}
}
// Check if we have a DisplayPositionEvent
const DisplayPositionEvent *dpe =
dynamic_cast< const DisplayPositionEvent * >( stateEvent->GetEvent() );
if ( dpe != NULL )
{
m_CurrentPickedPoint = dpe->GetWorldPosition();
m_CurrentPickedDisplayPoint = dpe->GetDisplayPosition();
}
// Get the timestep to also support 3D+t
int timeStep = 0;
ScalarType timeInMS = 0.0;
if ( renderer != NULL )
{
timeStep = renderer->GetTimeStep( data );
timeInMS = renderer->GetTime();
}
// If data is an mitk::Surface, extract it
Surface *surface = dynamic_cast< Surface * >( data );
vtkPolyData *polyData = NULL;
if ( surface != NULL )
{
polyData = surface->GetVtkPolyData( timeStep );
// Extract surface normal from surface (if existent, otherwise use default)
vtkPointData *pointData = polyData->GetPointData();
if ( pointData != NULL )
{
vtkDataArray *normal = polyData->GetPointData()->GetVectors( "planeNormal" );
if ( normal != NULL )
{
m_ObjectNormal[0] = normal->GetComponent( 0, 0 );
m_ObjectNormal[1] = normal->GetComponent( 0, 1 );
m_ObjectNormal[2] = normal->GetComponent( 0, 2 );
}
}
}
// Get geometry object
m_Geometry = data->GetGeometry( timeStep );
// Make sure that the data (if time-resolved) has enough entries;
// if not, create the required extra ones (empty)
data->Expand( timeStep+1 );
switch (action->GetActionId())
{
case AcDONOTHING:
ok = true;
break;
case AcCHECKOBJECT:
{
// Re-enable VTK interactor (may have been disabled previously)
if ( renderWindowInteractor != NULL )
{
renderWindowInteractor->Enable();
}
// Check if we have a DisplayPositionEvent
const DisplayPositionEvent *dpe =
dynamic_cast< const DisplayPositionEvent * >( stateEvent->GetEvent() );
if ( dpe == NULL )
{
ok = true;
break;
}
// Check if an object is present at the current mouse position
DataNode *pickedNode = dpe->GetPickedObjectNode();
StateEvent *newStateEvent;
if ( pickedNode == m_DataNode )
{
// Yes: object will be selected
newStateEvent = new StateEvent( EIDYES );
}
else
{
// No: back to start state
newStateEvent = new StateEvent( EIDNO );
}
this->HandleEvent( newStateEvent );
ok = true;
break;
}
case AcDESELECTOBJECT:
{
// Color object white
m_DataNode->SetColor( 1.0, 1.0, 1.0 );
RenderingManager::GetInstance()->RequestUpdateAll();
// Colorize surface / wireframe as inactive
this->ColorizeSurface( polyData,
m_CurrentPickedPoint, -1.0 );
ok = true;
break;
}
case AcSELECTPICKEDOBJECT:
{
// Color object red
m_DataNode->SetColor( 1.0, 0.0, 0.0 );
RenderingManager::GetInstance()->RequestUpdateAll();
// Colorize surface / wireframe dependend on distance from picked point
this->ColorizeSurface( polyData,
m_CurrentPickedPoint, 0.0 );
ok = true;
break;
}
case AcINITMOVE:
{
// Disable VTK interactor until MITK interaction has been completed
if ( renderWindowInteractor != NULL )
{
renderWindowInteractor->Disable();
}
// Check if we have a DisplayPositionEvent
const DisplayPositionEvent *dpe =
dynamic_cast< const DisplayPositionEvent * >( stateEvent->GetEvent() );
if ( dpe == NULL )
{
ok = true;
break;
}
//DataNode *pickedNode = dpe->GetPickedObjectNode();
m_InitialPickedPoint = m_CurrentPickedPoint;
m_InitialPickedDisplayPoint = m_CurrentPickedDisplayPoint;
if ( currentVtkRenderer != NULL )
{
vtkInteractorObserver::ComputeDisplayToWorld(
currentVtkRenderer,
m_InitialPickedDisplayPoint[0],
m_InitialPickedDisplayPoint[1],
0.0, //m_InitialInteractionPickedPoint[2],
m_InitialPickedPointWorld );
}
// Make deep copy of current Geometry3D of the plane
data->UpdateOutputInformation(); // make sure that the Geometry is up-to-date
- m_OriginalGeometry = static_cast< Geometry3D * >(
+ m_OriginalGeometry = static_cast< BaseGeometry * >(
data->GetGeometry( timeStep )->Clone().GetPointer() );
ok = true;
break;
}
case AcMOVE:
{
// Check if we have a DisplayPositionEvent
const DisplayPositionEvent *dpe =
dynamic_cast< const DisplayPositionEvent * >( stateEvent->GetEvent() );
if ( dpe == NULL )
{
ok = true;
break;
}
if ( currentVtkRenderer != NULL )
{
vtkInteractorObserver::ComputeDisplayToWorld(
currentVtkRenderer,
m_CurrentPickedDisplayPoint[0],
m_CurrentPickedDisplayPoint[1],
0.0, //m_InitialInteractionPickedPoint[2],
m_CurrentPickedPointWorld );
}
Vector3D interactionMove;
interactionMove[0] = m_CurrentPickedPointWorld[0] - m_InitialPickedPointWorld[0];
interactionMove[1] = m_CurrentPickedPointWorld[1] - m_InitialPickedPointWorld[1];
interactionMove[2] = m_CurrentPickedPointWorld[2] - m_InitialPickedPointWorld[2];
if ( m_InteractionMode == INTERACTION_MODE_TRANSLATION )
{
Point3D origin = m_OriginalGeometry->GetOrigin();
Vector3D transformedObjectNormal;
data->GetGeometry( timeStep )->IndexToWorld(
m_ObjectNormal, transformedObjectNormal );
data->GetGeometry( timeStep )->SetOrigin(
origin + transformedObjectNormal * (interactionMove * transformedObjectNormal) );
}
else if ( m_InteractionMode == INTERACTION_MODE_ROTATION )
{
if ( camera )
{
double vpn[3];
camera->GetViewPlaneNormal( vpn );
Vector3D viewPlaneNormal;
viewPlaneNormal[0] = vpn[0];
viewPlaneNormal[1] = vpn[1];
viewPlaneNormal[2] = vpn[2];
Vector3D rotationAxis =
itk::CrossProduct( viewPlaneNormal, interactionMove );
rotationAxis.Normalize();
int *size = currentVtkRenderer->GetSize();
double l2 =
(m_CurrentPickedDisplayPoint[0] - m_InitialPickedDisplayPoint[0]) *
(m_CurrentPickedDisplayPoint[0] - m_InitialPickedDisplayPoint[0]) +
(m_CurrentPickedDisplayPoint[1] - m_InitialPickedDisplayPoint[1]) *
(m_CurrentPickedDisplayPoint[1] - m_InitialPickedDisplayPoint[1]);
double rotationAngle = 360.0 * sqrt(l2/(size[0]*size[0]+size[1]*size[1]));
// Use center of data bounding box as center of rotation
Point3D rotationCenter = m_OriginalGeometry->GetCenter();;
// Reset current Geometry3D to original state (pre-interaction) and
// apply rotation
RotationOperation op( OpROTATE, rotationCenter, rotationAxis, rotationAngle );
- Geometry3D::Pointer newGeometry = static_cast< Geometry3D * >(
+ BaseGeometry::Pointer newGeometry = static_cast< BaseGeometry * >(
m_OriginalGeometry->Clone().GetPointer() );
newGeometry->ExecuteOperation( &op );
data->SetClonedGeometry(newGeometry, timeStep);
}
}
RenderingManager::GetInstance()->RequestUpdateAll();
ok = true;
break;
}
default:
return Superclass::ExecuteAction( action, stateEvent );
}
return ok;
}
bool AffineInteractor3D::ColorizeSurface( vtkPolyData *polyData,
const Point3D & /*pickedPoint*/, double scalar )
{
if ( polyData == NULL )
{
return false;
}
//vtkPoints *points = polyData->GetPoints();
vtkPointData *pointData = polyData->GetPointData();
if ( pointData == NULL )
{
return false;
}
vtkDataArray *scalars = pointData->GetScalars();
if ( scalars == NULL )
{
return false;
}
for ( unsigned int i = 0; i < pointData->GetNumberOfTuples(); ++i )
{
scalars->SetComponent( i, 0, scalar );
}
polyData->Modified();
pointData->Update();
return true;
}
} // namespace
diff --git a/Modules/Ext/Interactions/mitkAffineInteractor3D.h b/Modules/Ext/Interactions/mitkAffineInteractor3D.h
index 761d480f6f..58b5b317a6 100644
--- a/Modules/Ext/Interactions/mitkAffineInteractor3D.h
+++ b/Modules/Ext/Interactions/mitkAffineInteractor3D.h
@@ -1,117 +1,117 @@
/*===================================================================
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 MITKAFFINEINTERACTOR3D_H_HEADER_INCLUDED
#define MITKAFFINEINTERACTOR3D_H_HEADER_INCLUDED
#include "mitkInteractor.h"
#include "MitkExtExports.h"
#include "mitkCommon.h"
#include "mitkSurface.h"
#include <vtkPolyData.h>
#include <vtkType.h>
namespace mitk
{
class DataNode;
/**
* \brief Affine interaction with objects in 3D windows.
*
* NOTE: The interaction mechanism is similar to that of vtkPlaneWidget
*
* \ingroup Interaction
* \deprecatedSince{2013_12} mitk::AffineInteractor is deprecated. Use mitk::AffineDataInteractor instead.
*/
class MitkExt_EXPORT AffineInteractor3D : public Interactor
{
public:
enum { INTERACTION_MODE_TRANSLATION, INTERACTION_MODE_ROTATION };
mitkClassMacro(AffineInteractor3D, Interactor);
mitkNewMacro3Param(Self, const char *, DataNode *, int);
mitkNewMacro2Param(Self, const char *, DataNode *);
void SetInteractionMode( unsigned int interactionMode );
void SetInteractionModeToTranslation();
void SetInteractionModeToRotation();
unsigned int GetInteractionMode() const;
/** \brief Sets the amount of precision */
void SetPrecision( ScalarType precision );
/**
* \brief calculates how good the data, this statemachine handles, is hit
* by the event.
*
* overwritten, cause we don't look at the boundingbox, we look at each point
*/
virtual float CanHandleEvent(StateEvent const *stateEvent) const;
protected:
/**
* \brief Constructor with Param n for limited Set of Points
*
* if no n is set, then the number of points is unlimited*
*/
DEPRECATED(AffineInteractor3D(const char *type,
DataNode *dataNode, int n = -1));
/**
* \brief Default Destructor
**/
virtual ~AffineInteractor3D();
virtual bool ExecuteAction( Action* action,
mitk::StateEvent const* stateEvent );
bool ColorizeSurface( vtkPolyData *polyData, const Point3D &pickedPoint,
double scalar = 0.0 );
private:
/** \brief to store the value of precision to pick a point */
ScalarType m_Precision;
bool m_InteractionMode;
Point3D m_InitialPickedPoint;
Point2D m_InitialPickedDisplayPoint;
double m_InitialPickedPointWorld[4];
Point3D m_CurrentPickedPoint;
Point2D m_CurrentPickedDisplayPoint;
double m_CurrentPickedPointWorld[4];
- Geometry3D::Pointer m_Geometry;
+ BaseGeometry::Pointer m_Geometry;
- Geometry3D::Pointer m_OriginalGeometry;
+ BaseGeometry::Pointer m_OriginalGeometry;
Vector3D m_ObjectNormal;
};
}
#endif /* MITKAFFINEINTERACTOR3D_H_HEADER_INCLUDED */
diff --git a/Modules/Ext/Interactions/mitkSurfaceDeformationInteractor3D.cpp b/Modules/Ext/Interactions/mitkSurfaceDeformationInteractor3D.cpp
index 749af5cc05..f385279407 100644
--- a/Modules/Ext/Interactions/mitkSurfaceDeformationInteractor3D.cpp
+++ b/Modules/Ext/Interactions/mitkSurfaceDeformationInteractor3D.cpp
@@ -1,498 +1,498 @@
/*===================================================================
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 "mitkSurfaceDeformationInteractor3D.h"
#include "mitkPointOperation.h"
#include "mitkDisplayPositionEvent.h"
#include "mitkWheelEvent.h"
#include "mitkStatusBar.h"
#include "mitkDataNode.h"
#include "mitkInteractionConst.h"
#include "mitkAction.h"
#include "mitkStateEvent.h"
#include "mitkOperationEvent.h"
#include "mitkUndoController.h"
#include "mitkStateMachineFactory.h"
#include "mitkStateTransitionOperation.h"
#include "mitkBaseRenderer.h"
#include "mitkRenderingManager.h"
#include "mitkSurface.h"
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyle.h>
#include <vtkPolyData.h>
#include <vtkPointData.h>
#include <vtkDataArray.h>
#include <vtkPointData.h>
#include <vtkDataArray.h>
//how precise must the user pick the point
//default value
mitk::SurfaceDeformationInteractor3D
::SurfaceDeformationInteractor3D(const char * type, DataNode* dataNode, int /* n */ )
: Interactor( type, dataNode ),
m_Precision( 6.5 ),
m_PickedSurfaceNode( NULL ),
m_PickedSurface( NULL ),
m_GaussSigma( 30.0 )
{
m_OriginalPolyData = vtkPolyData::New();
// Initialize vector arithmetic
m_ObjectNormal[0] = 0.0;
m_ObjectNormal[1] = 0.0;
m_ObjectNormal[2] = 1.0;
}
mitk::SurfaceDeformationInteractor3D::~SurfaceDeformationInteractor3D()
{
m_OriginalPolyData->Delete();
}
void mitk::SurfaceDeformationInteractor3D::SetPrecision( mitk::ScalarType precision )
{
m_Precision = precision;
}
// Overwritten since this class can handle it better!
float mitk::SurfaceDeformationInteractor3D
::CanHandleEvent(StateEvent const* stateEvent) const
{
float returnValue = 0.5;
// If it is a key event that can be handled in the current state,
// then return 0.5
mitk::DisplayPositionEvent const *disPosEvent =
dynamic_cast <const mitk::DisplayPositionEvent *> (stateEvent->GetEvent());
// Key event handling:
if (disPosEvent == NULL)
{
// Check if the current state has a transition waiting for that key event.
if (this->GetCurrentState()->GetTransition(stateEvent->GetId())!=NULL)
{
return 0.5;
}
else
{
return 0.0;
}
}
//on MouseMove do nothing!
//if (stateEvent->GetEvent()->GetType() == mitk::Type_MouseMove)
//{
// return 0.0;
//}
//if the event can be understood and if there is a transition waiting for that event
if (this->GetCurrentState()->GetTransition(stateEvent->GetId())!=NULL)
{
returnValue = 0.5;//it can be understood
}
//int timeStep = disPosEvent->GetSender()->GetTimeStep();
//mitk::CurveModel *curveModel = dynamic_cast<mitk::CurveModel *>(
// m_DataNode->GetData() );
//if ( curveModel != NULL )
//{
- // // Get the Geometry2D of the window the user interacts with (for 2D point
+ // // Get the PlaneGeometry of the window the user interacts with (for 2D point
// // projection)
// mitk::BaseRenderer *renderer = stateEvent->GetEvent()->GetSender();
- // const Geometry2D *projectionPlane = renderer->GetCurrentWorldGeometry2D();
+ // const PlaneGeometry *projectionPlane = renderer->GetCurrentWorldPlaneGeometry();
// // For reading on the points, Ids etc
// //mitk::CurveModel::PointSetType *pointSet = curveModel->GetPointSet( timeStep );
// //if ( pointSet == NULL )
// //{
// // return 0.0;
// //}
//}
return returnValue;
}
bool mitk::SurfaceDeformationInteractor3D
::ExecuteAction( Action *action, mitk::StateEvent const *stateEvent )
{
bool ok = false;
// Get data object
mitk::BaseData *data = m_DataNode->GetData();
if ( data == NULL )
{
MITK_ERROR << "No data object present!";
return ok;
}
// Get mitk::Event and extract renderer
const mitk::Event *event = stateEvent->GetEvent();
mitk::BaseRenderer *renderer = NULL;
vtkRenderWindow *renderWindow = NULL;
vtkRenderWindowInteractor *renderWindowInteractor = NULL;
if ( event != NULL )
{
renderer = event->GetSender();
if ( renderer != NULL )
{
renderWindow = renderer->GetRenderWindow();
if ( renderWindow != NULL )
{
renderWindowInteractor = renderWindow->GetInteractor();
}
}
}
// Check if we have a DisplayPositionEvent
const mitk::DisplayPositionEvent *dpe =
dynamic_cast< const mitk::DisplayPositionEvent * >( stateEvent->GetEvent() );
if ( dpe != NULL )
{
m_PickedSurfaceNode = dpe->GetPickedObjectNode();
m_CurrentPickedPoint = dpe->GetWorldPosition();
m_CurrentPickedDisplayPoint = dpe->GetDisplayPosition();
}
// Get the timestep to also support 3D+t
int timeStep = 0;
mitk::ScalarType timeInMS = 0.0;
if ( renderer != NULL )
{
timeStep = renderer->GetTimeStep( data );
timeInMS = renderer->GetTime();
}
// Extract surface
m_Surface = dynamic_cast< Surface * >( data );
if ( m_Surface != NULL )
{
m_PolyData = m_Surface->GetVtkPolyData( timeStep );
}
else
{
m_PolyData = NULL;
}
// Extract surface normal from surface (if existent, otherwise use default)
vtkPointData *pointData = m_PolyData->GetPointData();
if ( pointData != NULL )
{
vtkDataArray *normal = m_PolyData->GetPointData()->GetVectors( "planeNormal" );
if ( normal != NULL )
{
m_ObjectNormal[0] = normal->GetComponent( 0, 0 );
m_ObjectNormal[1] = normal->GetComponent( 0, 1 );
m_ObjectNormal[2] = normal->GetComponent( 0, 2 );
}
}
// Get geometry object
m_Geometry = data->GetGeometry( timeStep );
// Make sure that the data (if time-resolved) has enough entries;
// if not, create the required extra ones (empty)
data->Expand( timeStep+1 );
switch (action->GetActionId())
{
case AcDONOTHING:
ok = true;
break;
case AcCHECKOBJECT:
{
// Check if an object is present at the current mouse position
m_PickedSurface = NULL;
m_PickedPolyData = NULL;
if ( m_PickedSurfaceNode != NULL )
{
m_PickedSurface = dynamic_cast< mitk::Surface * >( m_PickedSurfaceNode->GetData() );
if ( m_PickedSurface != NULL )
{
m_PickedPolyData = m_PickedSurface->GetVtkPolyData( timeStep );
}
}
mitk::StateEvent *newStateEvent;
if ( (m_PickedSurfaceNode == m_DataNode) && (m_PickedSurface != NULL) )
{
// Yes: object will be selected
newStateEvent = new mitk::StateEvent( EIDYES );
// Disable VTK interactor until MITK interaction has been completed
if ( renderWindowInteractor != NULL )
{
renderWindowInteractor->Disable();
}
}
else
{
// No: back to start state
newStateEvent = new mitk::StateEvent( EIDNO );
// Re-enable VTK interactor (may have been disabled previously)
if ( renderWindowInteractor != NULL )
{
renderWindowInteractor->Enable();
}
}
this->HandleEvent( newStateEvent );
// Colorized surface at current picked position
m_SurfaceColorizationCenter = m_CurrentPickedPoint;
ok = true;
break;
}
case AcDESELECTOBJECT:
{
// Color object white
m_DataNode->SetColor( 1.0, 1.0, 1.0 );
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
// Colorize surface / wireframe as inactive
this->ColorizeSurface( m_PolyData,
m_SurfaceColorizationCenter, COLORIZATION_CONSTANT, -1.0 );
ok = true;
break;
}
case AcSELECTPICKEDOBJECT:
{
// Color object red
m_DataNode->SetColor( 1.0, 0.0, 0.0 );
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
// Colorize surface / wireframe dependend on distance from picked point
this->ColorizeSurface( m_PolyData,
m_SurfaceColorizationCenter, COLORIZATION_GAUSS );
ok = true;
break;
}
case AcINITMOVE:
{
// Store current picked point
m_InitialPickedPoint = m_CurrentPickedPoint;
m_InitialPickedDisplayPoint = m_CurrentPickedDisplayPoint;
if ( renderWindowInteractor != NULL )
{
vtkInteractorObserver::ComputeDisplayToWorld(
renderWindowInteractor->GetInteractorStyle()->GetCurrentRenderer(),
m_InitialPickedDisplayPoint[0],
m_InitialPickedDisplayPoint[1],
0.0, //m_InitialInteractionPickedPoint[2],
m_InitialPickedPointWorld );
}
// Make deep copy of vtkPolyData interacted on
m_OriginalPolyData->DeepCopy( m_PolyData );
ok = true;
break;
}
case AcMOVE:
{
if ( renderWindowInteractor != NULL )
{
vtkInteractorObserver::ComputeDisplayToWorld(
renderWindowInteractor->GetInteractorStyle()->GetCurrentRenderer(),
m_CurrentPickedDisplayPoint[0],
m_CurrentPickedDisplayPoint[1],
0.0, //m_InitialInteractionPickedPoint[2],
m_CurrentPickedPointWorld );
}
// Calculate mouse move in 3D space
mitk::Vector3D interactionMove;
interactionMove[0] = m_CurrentPickedPointWorld[0] - m_InitialPickedPointWorld[0];
interactionMove[1] = m_CurrentPickedPointWorld[1] - m_InitialPickedPointWorld[1];
interactionMove[2] = m_CurrentPickedPointWorld[2] - m_InitialPickedPointWorld[2];
// Transform mouse move into geometry space
data->UpdateOutputInformation(); // make sure that the Geometry is up-to-date
mitk::Point3D origin; origin.Fill( 0.0 );
mitk::Vector3D interactionMoveIndex;
m_Geometry->WorldToIndex( interactionMove, interactionMoveIndex );
// Get picked point and transform into local coordinates
mitk::Point3D pickedPoint;
m_Geometry->WorldToIndex( m_InitialPickedPoint, pickedPoint );
mitk::Vector3D v1 = pickedPoint.GetVectorFromOrigin();
mitk::Vector3D v2 = m_ObjectNormal * (interactionMoveIndex * m_ObjectNormal);
vtkPoints *originalPoints = m_OriginalPolyData->GetPoints();
vtkPoints *deformedPoints = m_PolyData->GetPoints();
double denom = m_GaussSigma * m_GaussSigma * 2;
double point[3];
for ( unsigned int i = 0; i < deformedPoints->GetNumberOfPoints(); ++i )
{
// Get original point
double *originalPoint = originalPoints->GetPoint( i );
mitk::Vector3D v0;
v0[0] = originalPoint[0];
v0[1] = originalPoint[1];
v0[2] = originalPoint[2];
// Calculate distance of this point from line through picked point
double d = itk::CrossProduct( m_ObjectNormal, (v1 - v0) ).GetNorm();
mitk::Vector3D t = v2 * exp( - d * d / denom );
point[0] = originalPoint[0] + t[0];
point[1] = originalPoint[1] + t[1];
point[2] = originalPoint[2] + t[2];
deformedPoints->SetPoint( i, point );
}
// Make sure that surface is colorized at initial picked position
// as long as we are in deformation state
m_SurfaceColorizationCenter = m_InitialPickedPoint;
m_PolyData->Modified();
m_Surface->Modified();
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
ok = false;
break;
}
case AcMODIFY:
{
// Check if we have an mitk::WheelEvent
const mitk::WheelEvent *we =
dynamic_cast< const mitk::WheelEvent * >( stateEvent->GetEvent() );
if ( we == NULL )
{
ok = true;
break;
}
m_GaussSigma += (double) (we->GetDelta()) / 20;;
if ( m_GaussSigma < 10.0 )
{
m_GaussSigma = 10.0;
}
else if ( m_GaussSigma > 128.0 )
{
m_GaussSigma = 128.0;
}
// Colorize surface / wireframe dependend on sigma and distance from picked point
this->ColorizeSurface( m_PolyData,
m_SurfaceColorizationCenter, COLORIZATION_GAUSS );
mitk::RenderingManager::GetInstance()->RequestUpdateAll(
mitk::RenderingManager::REQUEST_UPDATE_3DWINDOWS );
ok = true;
break;
}
default:
return Superclass::ExecuteAction( action, stateEvent );
}
return ok;
}
bool mitk::SurfaceDeformationInteractor3D::ColorizeSurface( vtkPolyData *polyData,
const Point3D &pickedPoint, int mode, double scalar )
{
if ( polyData == NULL )
{
return false;
}
vtkPoints *points = polyData->GetPoints();
vtkPointData *pointData = polyData->GetPointData();
if ( pointData == NULL )
{
return false;
}
vtkDataArray *scalars = pointData->GetScalars();
if ( scalars == NULL )
{
return false;
}
if ( mode == COLORIZATION_GAUSS )
{
// Get picked point and transform into local coordinates
mitk::Point3D localPickedPoint;
m_Geometry->WorldToIndex( pickedPoint, localPickedPoint );
mitk::Vector3D v1 = localPickedPoint.GetVectorFromOrigin();
double denom = m_GaussSigma * m_GaussSigma * 2;
for ( unsigned int i = 0; i < points->GetNumberOfPoints(); ++i )
{
// Get original point
double *point = points->GetPoint( i );
mitk::Vector3D v0;
v0[0] = point[0];
v0[1] = point[1];
v0[2] = point[2];
// Calculate distance of this point from line through picked point
double d = itk::CrossProduct( m_ObjectNormal, (v1 - v0) ).GetNorm();
double t = exp( - d * d / denom );
scalars->SetComponent( i, 0, t );
}
}
else if ( mode == COLORIZATION_CONSTANT )
{
for ( unsigned int i = 0; i < pointData->GetNumberOfTuples(); ++i )
{
scalars->SetComponent( i, 0, scalar );
}
}
polyData->Modified();
pointData->Update();
return true;
}
diff --git a/Modules/Ext/Interactions/mitkSurfaceDeformationInteractor3D.h b/Modules/Ext/Interactions/mitkSurfaceDeformationInteractor3D.h
index d31c0faabc..b61be85aeb 100644
--- a/Modules/Ext/Interactions/mitkSurfaceDeformationInteractor3D.h
+++ b/Modules/Ext/Interactions/mitkSurfaceDeformationInteractor3D.h
@@ -1,122 +1,122 @@
/*===================================================================
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 MITKSURFACEDEFORMATIONINTERACTOR3D_H_HEADER_INCLUDED
#define MITKSURFACEDEFORMATIONINTERACTOR3D_H_HEADER_INCLUDED
#include "mitkInteractor.h"
#include "MitkExtExports.h"
#include "mitkCommon.h"
#include <vtkType.h>
class vtkPolyData;
namespace mitk
{
class DataNode;
class Surface;
/**
* \brief Affine interaction with objects in 3D windows.
*
* NOTE: The interaction mechanism is similar to that of vtkPlaneWidget
*
* \ingroup Interaction
*/
class MitkExt_EXPORT SurfaceDeformationInteractor3D : public Interactor
{
public:
mitkClassMacro(SurfaceDeformationInteractor3D, Interactor);
mitkNewMacro3Param(Self, const char *, DataNode *, int);
mitkNewMacro2Param(Self, const char *, DataNode *);
/** \brief Sets the amount of precision */
void SetPrecision( ScalarType precision );
/**
* \brief calculates how good the data, this statemachine handles, is hit
* by the event.
*
* overwritten, cause we don't look at the boundingbox, we look at each point
*/
virtual float CanHandleEvent(StateEvent const *stateEvent) const;
protected:
/**
* \brief Constructor with Param n for limited Set of Points
*
* if no n is set, then the number of points is unlimited*
*/
SurfaceDeformationInteractor3D(const char *type,
DataNode *dataNode, int n = -1);
/**
* \brief Default Destructor
**/
virtual ~SurfaceDeformationInteractor3D();
virtual bool ExecuteAction( Action* action,
mitk::StateEvent const* stateEvent );
enum
{
COLORIZATION_GAUSS,
COLORIZATION_CONSTANT
};
bool ColorizeSurface( vtkPolyData *polyData, const Point3D &pickedPoint,
int mode, double scalar = 0.0 );
private:
/** \brief to store the value of precision to pick a point */
ScalarType m_Precision;
Point3D m_InitialPickedPoint;
Point2D m_InitialPickedDisplayPoint;
double m_InitialPickedPointWorld[4];
Point3D m_CurrentPickedPoint;
Point2D m_CurrentPickedDisplayPoint;
double m_CurrentPickedPointWorld[4];
Point3D m_SurfaceColorizationCenter;
Vector3D m_ObjectNormal;
- Geometry3D::Pointer m_Geometry;
+ BaseGeometry::Pointer m_Geometry;
Surface *m_Surface;
vtkPolyData *m_PolyData;
DataNode *m_PickedSurfaceNode;
Surface *m_PickedSurface;
vtkPolyData *m_PickedPolyData;
vtkPolyData *m_OriginalPolyData;
double m_GaussSigma;
};
}
#endif /* MITKSURFACEDEFORMATIONINTERACTOR3D_H_HEADER_INCLUDED */
diff --git a/Modules/Ext/Testing/mitkPlaneFitTest.cpp b/Modules/Ext/Testing/mitkPlaneFitTest.cpp
index 986d00ab27..2b038c967c 100644
--- a/Modules/Ext/Testing/mitkPlaneFitTest.cpp
+++ b/Modules/Ext/Testing/mitkPlaneFitTest.cpp
@@ -1,97 +1,98 @@
/*===================================================================
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 <mitkPlaneFit.h>
#include <mitkPointSet.h>
-#include <mitkGeometry2D.h>
+#include <mitkPlaneGeometry.h>
#include <mitkVector.h>
#include <mitkGeometryData.h>
#include <fstream>
int mitkPlaneFitTest(int, char*[] )
{
//float bounds[]={0.0f,10.0f,0.0f,10.0f,0.0f,5.0f};
mitk::PlaneFit::Pointer PlaneFit = mitk::PlaneFit::New();
mitk::PointSet::Pointer PointSet = mitk::PointSet::New();
- mitk::Geometry3D::Pointer Geometry3D = mitk::Geometry3D::New();
+ mitk::PlaneGeometry::Pointer planeGeo= mitk::PlaneGeometry::New();
+ mitk::BaseGeometry::Pointer BaseGeometry = dynamic_cast<mitk::PlaneGeometry*>(planeGeo.GetPointer());
mitk::Point3D Point;
//first without any point, then incrementally add points within thre points there will be a plane geometry
std::cout <<"Start PlaneFitTest "<<std::endl;
for(int position=0; position<6; position++)
{
//add a point directly
mitk::FillVector3D(Point, (float) position , (float) position * 1.5 , 2.5);
PointSet->GetPointSet()->GetPoints()->InsertElement(position, Point);
}
//Set Input
PlaneFit->SetInput(PointSet);
const mitk::PointSet* testPointSet = PlaneFit->GetInput();
std::cout<<" Size test of Input Method: ";
if( testPointSet->GetSize() == PointSet->GetSize() )
{
std::cout<<"[PASSED]"<<std::endl;
}
else
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
//Test Centroid
std::cout << " Testing centroid calculaation: ";
PlaneFit->Update();
const mitk::Point3D &centroid = PlaneFit->GetCentroid();
mitk::Point3D expectedCentroid;
expectedCentroid[0]=2.5;
expectedCentroid[1]=3.75;
expectedCentroid[2]=2.5;
if ( centroid == expectedCentroid )
{
std::cout<<"[PASSED]"<<std::endl;
}
else
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
//Test PlaneGeometry
std::cout << " Test PlaneGeometry: ";
- mitk::Geometry2D* Geometry2D = dynamic_cast<mitk::Geometry2D*>( PlaneFit->GetOutput()->GetGeometry());
- if( Geometry2D )
+ mitk::PlaneGeometry* PlaneGeometry = dynamic_cast<mitk::PlaneGeometry*>( PlaneFit->GetOutput()->GetGeometry());
+ if( PlaneGeometry )
{
std::cout<<"[PASSED]"<<std::endl;
}
else
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[TEST DONE]"<<std::endl;
return EXIT_SUCCESS;
}
diff --git a/Modules/IGT/Rendering/mitkNavigationDataObjectVisualizationFilter.cpp b/Modules/IGT/Rendering/mitkNavigationDataObjectVisualizationFilter.cpp
index a1501ec1c5..a91b986cf8 100644
--- a/Modules/IGT/Rendering/mitkNavigationDataObjectVisualizationFilter.cpp
+++ b/Modules/IGT/Rendering/mitkNavigationDataObjectVisualizationFilter.cpp
@@ -1,247 +1,246 @@
/*===================================================================
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 "mitkNavigationDataObjectVisualizationFilter.h"
#include "mitkDataStorage.h"
mitk::NavigationDataObjectVisualizationFilter::NavigationDataObjectVisualizationFilter()
: NavigationDataToNavigationDataFilter(),
m_RepresentationList(), m_TransformPosition(), m_TransformOrientation(), m_RotationMode(RotationStandard)
{
}
mitk::NavigationDataObjectVisualizationFilter::~NavigationDataObjectVisualizationFilter()
{
m_RepresentationList.clear();
m_OffsetList.clear();
}
const mitk::BaseData* mitk::NavigationDataObjectVisualizationFilter::GetRepresentationObject(unsigned int idx)
{
RepresentationPointerMap::const_iterator iter = m_RepresentationList.find(idx);
if (iter != m_RepresentationList.end())
return iter->second;
return NULL;
}
mitk::AffineTransform3D::Pointer mitk::NavigationDataObjectVisualizationFilter::GetOffset(int index)
{
OffsetPointerMap::const_iterator iter = m_OffsetList.find(index);
if (iter != m_OffsetList.end())
return iter->second;
return NULL;
}
void mitk::NavigationDataObjectVisualizationFilter::SetRepresentationObject(unsigned int idx, BaseData* data)
{
m_RepresentationList[idx] = RepresentationPointer(data);
}
void mitk::NavigationDataObjectVisualizationFilter::SetOffset(int index, mitk::AffineTransform3D::Pointer offset)
{
m_OffsetList[index] = offset;
}
void mitk::NavigationDataObjectVisualizationFilter::SetRotationMode(RotationMode r)
{
m_RotationMode = r;
}
void mitk::NavigationDataObjectVisualizationFilter::GenerateData()
{
/*get each input, lookup the associated BaseData and transfer the data*/
DataObjectPointerArray inputs = this->GetInputs(); //get all inputs
for (unsigned int index=0; index < inputs.size(); index++)
{
//get the needed variables
const mitk::NavigationData* nd = this->GetInput(index);
assert(nd);
mitk::NavigationData* output = this->GetOutput(index);
assert(output);
//check if the data is valid
if (!nd->IsDataValid())
{
output->SetDataValid(false);
continue;
}
output->Graft(nd); // copy all information from input to output
const mitk::BaseData* data = this->GetRepresentationObject(index);
if (data == NULL)
{
MITK_WARN << "No BaseData associated with input " << index;
continue;
}
//get the transform from data
mitk::AffineTransform3D::Pointer affineTransform = data->GetGeometry()->GetIndexToWorldTransform();
if (affineTransform.IsNull())
{
MITK_WARN << "AffineTransform IndexToWorldTransform not initialized!";
continue;
}
//check for offset
mitk::AffineTransform3D::Pointer offset = this->GetOffset(index);
//store the current scaling to set it after transformation
mitk::Vector3D spacing = data->GetGeometry()->GetSpacing();
//clear spacing of data to be able to set it again afterwards
ScalarType scale[] = {1.0, 1.0, 1.0};
data->GetGeometry()->SetSpacing(scale);
/*now bring quaternion to affineTransform by using vnl_Quaternion*/
affineTransform->SetIdentity();
if (this->GetTransformOrientation(index) == true)
{
mitk::NavigationData::OrientationType orientation = nd->GetOrientation();
/* because of an itk bug, the transform can not be calculated with float data type.
To use it in the mitk geometry classes, it has to be transfered to mitk::ScalarType which is float */
static AffineTransform3D::MatrixType m;
//convert quaternion to rotation matrix depending on the rotation mode
if(m_RotationMode == RotationStandard)
{
//calculate the transform from the quaternions
static itk::QuaternionRigidTransform<double>::Pointer quatTransform = itk::QuaternionRigidTransform<double>::New();
// convert mitk::ScalarType quaternion to double quaternion because of itk bug
vnl_quaternion<double> doubleQuaternion(orientation.x(), orientation.y(), orientation.z(), orientation.r());
quatTransform->SetIdentity();
quatTransform->SetRotation(doubleQuaternion);
quatTransform->Modified();
mitk::TransferMatrix(quatTransform->GetMatrix(), m);
}
else if(m_RotationMode == RotationTransposed)
{
vnl_matrix_fixed<mitk::ScalarType,3,3> rot = orientation.rotation_matrix_transpose();
for(int i=0; i<3; i++) for (int j=0; j<3; j++) m[i][j] = rot[i][j];
}
affineTransform->SetMatrix(m);
}
if (this->GetTransformPosition(index) == true)
{
///*set the offset by convert from itkPoint to itkVector and setting offset of transform*/
mitk::Vector3D pos;
pos.SetVnlVector(nd->GetPosition().GetVnlVector());
affineTransform->SetOffset(pos);
}
affineTransform->Modified();
//set the transform to data
if(offset.IsNotNull()) //first use offset if there is one.
{
mitk::AffineTransform3D::Pointer overallTransform = mitk::AffineTransform3D::New();
overallTransform->SetIdentity();
overallTransform->Compose(offset);
overallTransform->Compose(affineTransform);
data->GetGeometry()->SetIndexToWorldTransform(overallTransform);
}
else
{
data->GetGeometry()->SetIndexToWorldTransform(affineTransform);
}
//set the original spacing to keep scaling of the geometrical object
data->GetGeometry()->SetSpacing(spacing);
- data->GetGeometry()->TransferItkToVtkTransform(); // update VTK Transform for rendering too
data->GetGeometry()->Modified();
data->Modified();
output->SetDataValid(true); // operation was successful, therefore data of output is valid.
}
}
void mitk::NavigationDataObjectVisualizationFilter::SetTransformPosition( unsigned int index, bool applyTransform )
{
itkDebugMacro("setting TransformPosition for index " << index << " to " << applyTransform);
BooleanInputMap::const_iterator it = this->m_TransformPosition.find(index);
if ((it != this->m_TransformPosition.end()) && (it->second == applyTransform))
return;
this->m_TransformPosition[index] = applyTransform;
this->Modified();
}
bool mitk::NavigationDataObjectVisualizationFilter::GetTransformPosition( unsigned int index ) const
{
itkDebugMacro("returning TransformPosition for index " << index);
BooleanInputMap::const_iterator it = this->m_TransformPosition.find(index);
if (it != this->m_TransformPosition.end())
return it->second;
else
return true; // default to true
}
void mitk::NavigationDataObjectVisualizationFilter::TransformPositionOn( unsigned int index )
{
this->SetTransformPosition(index, true);
}
void mitk::NavigationDataObjectVisualizationFilter::TransformPositionOff( unsigned int index )
{
this->SetTransformPosition(index, false);
}
void mitk::NavigationDataObjectVisualizationFilter::SetTransformOrientation( unsigned int index, bool applyTransform )
{
itkDebugMacro("setting TransformOrientation for index " << index << " to " << applyTransform);
BooleanInputMap::const_iterator it = this->m_TransformOrientation.find(index);
if ((it != this->m_TransformOrientation.end()) && (it->second == applyTransform))
return;
this->m_TransformOrientation[index] = applyTransform;
this->Modified(); \
}
bool mitk::NavigationDataObjectVisualizationFilter::GetTransformOrientation( unsigned int index ) const
{
itkDebugMacro("returning TransformOrientation for index " << index);
BooleanInputMap::const_iterator it = this->m_TransformOrientation.find(index);
if (it != this->m_TransformOrientation.end())
return it->second;
else
return true; // default to true
}
void mitk::NavigationDataObjectVisualizationFilter::TransformOrientationOn( unsigned int index )
{
this->SetTransformOrientation(index, true);
}
void mitk::NavigationDataObjectVisualizationFilter::TransformOrientationOff( unsigned int index )
{
this->SetTransformOrientation(index, false);
}
diff --git a/Modules/IGT/Tutorial/mitkIGTTutorialStep2.cpp b/Modules/IGT/Tutorial/mitkIGTTutorialStep2.cpp
index f3a0f1be24..1f80ef16aa 100644
--- a/Modules/IGT/Tutorial/mitkIGTTutorialStep2.cpp
+++ b/Modules/IGT/Tutorial/mitkIGTTutorialStep2.cpp
@@ -1,156 +1,156 @@
/*===================================================================
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 <mitkVirtualTrackingDevice.h>
#include <mitkNavigationData.h>
#include <mitkTrackingDeviceSource.h>
#include <mitkNavigationDataObjectVisualizationFilter.h>
#include <mitkStandaloneDataStorage.h>
#include <mitkDataNode.h>
#include <mitkCone.h>
#include <mitkCylinder.h>
#include <mitkRenderWindow.h>
#include <mitkGlobalInteraction.h>
#include <itksys/SystemTools.hxx>
/**
* \brief This tutorial shows how to compose navigation datas. Therefore we render two objects.
* The first object is a cone that is tracked. The second object is a cylinder at a fixed position
* relative to the cone. At the end of the tracking, the cylinder is moved to its new relative position
* according to the last output of the tracking device.
* In addition to IGT tutorial step 1, the objects are added to a datastorage. Furthermore, a renderwindow
* is used for visual output.
*/
int main(int argc, char* argv[])
{
// Before rendering, global interaction must be initialized
mitk::GlobalInteraction::GetInstance()->Initialize("global");
//General code rendering the data in a renderwindow. See MITK Tutorial Step1 for more details.
mitk::StandaloneDataStorage::Pointer dataStorage = mitk::StandaloneDataStorage::New();
mitk::RenderWindow::Pointer renderWindow = mitk::RenderWindow::New();
mitk::DataNode::Pointer dataNode = mitk::DataNode::New();
//Here, we want a 3D renderwindow
renderWindow->GetRenderer()->SetMapperID(mitk::BaseRenderer::Standard3D);
renderWindow->GetVtkRenderWindow()->SetSize( 500, 500 );
renderWindow->GetRenderer()->Resize( 500, 500);
//Connect datastorage and renderwindow
renderWindow->GetRenderer()->SetDataStorage(dataStorage);
// --------------begin of moving object code -------------------------- //
//Virtual tracking device to generate random positions
mitk::VirtualTrackingDevice::Pointer tracker = mitk::VirtualTrackingDevice::New();
//Bounds (within the random numbers are generated) must be set before the tools are added
double bound = 10.0;
mitk::ScalarType bounds[] = {-bound, bound, -bound, bound, -bound, bound};
tracker->SetBounds(bounds);
tracker->AddTool("tool1");
//Tracking device source to get the data
mitk::TrackingDeviceSource::Pointer source = mitk::TrackingDeviceSource::New();
source->SetTrackingDevice(tracker);
source->Connect();
//Cone representation for rendering of the moving object
mitk::Cone::Pointer cone = mitk::Cone::New();
dataNode->SetData(cone);
dataNode->SetName("My tracked object");
dataNode->SetColor(0.0, 1.0, 1.0);
dataStorage->Add(dataNode);
//Filter for rendering the cone at correct postion and orientation
mitk::NavigationDataObjectVisualizationFilter::Pointer visualizer = mitk::NavigationDataObjectVisualizationFilter::New();
visualizer->SetInput(0, source->GetOutput());
visualizer->SetRepresentationObject(0, cone);
source->StartTracking();
// --------------end of moving object code -------------------------- //
// --------------begin of fixed object code ------------------------- //
//Cylinder representation for rendering of the fixed object
mitk::DataNode::Pointer cylinderNode = mitk::DataNode::New();
mitk::Cylinder::Pointer cylinder = mitk::Cylinder::New();
cylinderNode->SetData(cylinder);
cylinderNode->SetName("My fixed object");
cylinderNode->SetColor(1.0, 0.0, 0.0);
dataStorage->Add(cylinderNode);
//Define a rotation and a translation for the fixed object
mitk::Matrix3D rotationMatrix;
rotationMatrix.SetIdentity();
double alpha = 0.3;
rotationMatrix[1][1] = cos(alpha);
rotationMatrix[1][2] = -sin(alpha);
rotationMatrix[2][1] = sin(alpha);
rotationMatrix[2][2] = cos(alpha);
mitk::Vector3D offset;
offset.Fill(5.0);
//Add rotation and translation to affine transform
mitk::AffineTransform3D::Pointer affineTransform3D = mitk::AffineTransform3D::New();
affineTransform3D->SetOffset(offset);
affineTransform3D->SetMatrix(rotationMatrix);
//apply rotation and translation
mitk::NavigationData::Pointer fixedNavigationData = mitk::NavigationData::New(affineTransform3D);
cylinder->GetGeometry()->SetIndexToWorldTransform(fixedNavigationData->GetAffineTransform3D());
// --------------end of fixed object code ------------------------- //
// Global reinit with the bounds of the virtual tracking device
mitk::TimeGeometry::Pointer timeGeometry = dataStorage->ComputeBoundingGeometry3D(dataStorage->GetAll());
- mitk::Geometry3D::Pointer geometry = timeGeometry->GetGeometryForTimeStep(0);
+ mitk::BaseGeometry::Pointer geometry = timeGeometry->GetGeometryForTimeStep(0);
geometry->SetBounds(bounds);
mitk::RenderingManager::GetInstance()->InitializeViews( geometry );
//Generate and render 75 time steps to move the tracked object
for(int i=0; i < 75; ++i)
{
//Update the cone position
visualizer->Update();
//Update rendering
renderWindow->GetVtkRenderWindow()->Render();
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
MITK_INFO << "Position " << source->GetOutput()->GetPosition();
//Slight delay for the random numbers
itksys::SystemTools::Delay(100);
}
//Stop the tracking device and disconnect it
//The tracking is done, now we want to move the fixed object to its correct relative position regarding the tracked object.
source->StopTracking();
source->Disconnect();
//Now the tracking is finished and we can use the transformation to move
//the fixed object to its correct position relative to the new position
//of the moving/tracked object. Therefore, we compose the navigation datas.
fixedNavigationData->Compose(source->GetOutput(), false);
//Update the transformation matrix of the cylinder
cylinder->GetGeometry()->SetIndexToWorldTransform(fixedNavigationData->GetAffineTransform3D());
//Update the rendering
renderWindow->GetVtkRenderWindow()->Render();
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
//Wait a little before closing the renderwindow
itksys::SystemTools::Delay(2000);
}
diff --git a/Modules/IGTUI/Qmitk/QmitkInteractiveTransformationWidget.cpp b/Modules/IGTUI/Qmitk/QmitkInteractiveTransformationWidget.cpp
index 982c315ee8..bdd930bfd1 100644
--- a/Modules/IGTUI/Qmitk/QmitkInteractiveTransformationWidget.cpp
+++ b/Modules/IGTUI/Qmitk/QmitkInteractiveTransformationWidget.cpp
@@ -1,288 +1,288 @@
/*===================================================================
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 "QmitkInteractiveTransformationWidget.h"
// mitk includes
#include "mitkRenderingManager.h"
#include "mitkNavigationData.h"
// vtk includes
#include "vtkMatrix4x4.h"
#include "vtkLinearTransform.h"
const std::string QmitkInteractiveTransformationWidget::VIEW_ID = "org.mitk.views.interactivetransformationwidget";
QmitkInteractiveTransformationWidget::QmitkInteractiveTransformationWidget(QWidget* parent, Qt::WindowFlags f)
: QWidget(parent, f), m_Geometry(NULL), m_ResetGeometry(NULL), m_Controls(NULL)
{
CreateQtPartControl(this);
CreateConnections();
m_TranslationVector.Fill(0.0f);
m_RotateSliderPos.Fill(0.0f);
}
QmitkInteractiveTransformationWidget::~QmitkInteractiveTransformationWidget()
{
}
void QmitkInteractiveTransformationWidget::CreateQtPartControl(QWidget *parent)
{
if (!m_Controls)
{
// create GUI widgets
m_Controls = new Ui::QmitkInteractiveTransformationWidgetControls;
m_Controls->setupUi(parent);
}
}
void QmitkInteractiveTransformationWidget::CreateConnections()
{
if ( m_Controls )
{
// translations
connect( (QObject*)(m_Controls->m_XTransSlider), SIGNAL(valueChanged(int)), this, SLOT(OnXTranslationValueChanged(int)) );
connect( (QObject*)(m_Controls->m_XTransSpinBox), SIGNAL(valueChanged(int)), this, SLOT(OnXTranslationValueChanged(int)) );
connect( (QObject*)(m_Controls->m_YTransSlider), SIGNAL(valueChanged(int)), this, SLOT(OnYTranslationValueChanged(int)) );
connect( (QObject*)(m_Controls->m_YTransSpinBox), SIGNAL(valueChanged(int)), this, SLOT(OnYTranslationValueChanged(int)) );
connect( (QObject*)(m_Controls->m_ZTransSlider), SIGNAL(valueChanged(int)), this, SLOT(OnZTranslationValueChanged(int)) );
connect( (QObject*)(m_Controls->m_ZTransSpinBox), SIGNAL(valueChanged(int)), this, SLOT(OnZTranslationValueChanged(int)) );
// rotations
connect( (QObject*)(m_Controls->m_XRotSlider), SIGNAL(valueChanged(int)), this, SLOT(OnXRotationValueChanged(int)) );
connect( (QObject*)(m_Controls->m_XRotSpinBox), SIGNAL(valueChanged(int)), this, SLOT(OnXRotationValueChanged(int)) );
connect( (QObject*)(m_Controls->m_YRotSlider), SIGNAL(valueChanged(int)), this, SLOT(OnYRotationValueChanged(int)) );
connect( (QObject*)(m_Controls->m_YRotSpinBox), SIGNAL(valueChanged(int)), this, SLOT(OnYRotationValueChanged(int)) );
connect( (QObject*)(m_Controls->m_ZRotSlider), SIGNAL(valueChanged(int)), this, SLOT(OnZRotationValueChanged(int)) );
connect( (QObject*)(m_Controls->m_ZRotSpinBox), SIGNAL(valueChanged(int)), this, SLOT(OnZRotationValueChanged(int)) );
connect( (QObject*)(m_Controls->m_ResetPB), SIGNAL(clicked()), this, SLOT(OnResetGeometry()) );
connect( (QObject*)(m_Controls->m_UseManipulatedToolTipPB), SIGNAL(clicked()), this, SLOT(OnApplyManipulatedToolTip()) );
}
}
-void QmitkInteractiveTransformationWidget::SetGeometry( mitk::Geometry3D::Pointer geometry, mitk::Geometry3D::Pointer defaultValues )
+void QmitkInteractiveTransformationWidget::SetGeometry( mitk::BaseGeometry::Pointer geometry, mitk::BaseGeometry::Pointer defaultValues )
{
m_Geometry = geometry;
- m_ResetGeometry = geometry->Clone();
+ itk::LightObject::Pointer lopointer = geometry->Clone();
+ m_ResetGeometry = dynamic_cast<mitk::BaseGeometry*>(lopointer.GetPointer());
//set default values
if (defaultValues.IsNotNull())
{
//first: some conversion
mitk::NavigationData::Pointer transformConversionHelper = mitk::NavigationData::New(defaultValues->GetIndexToWorldTransform());
double eulerAlphaDegrees = transformConversionHelper->GetOrientation().rotation_euler_angles()[0] / vnl_math::pi * 180;
double eulerBetaDegrees = transformConversionHelper->GetOrientation().rotation_euler_angles()[1] / vnl_math::pi * 180;
double eulerGammaDegrees = transformConversionHelper->GetOrientation().rotation_euler_angles()[2] / vnl_math::pi * 180;
//set translation
OnXTranslationValueChanged(defaultValues->GetIndexToWorldTransform()->GetOffset()[0]);
OnYTranslationValueChanged(defaultValues->GetIndexToWorldTransform()->GetOffset()[1]);
OnZTranslationValueChanged(defaultValues->GetIndexToWorldTransform()->GetOffset()[2]);
//set rotation
OnXRotationValueChanged(eulerAlphaDegrees);
OnYRotationValueChanged(eulerBetaDegrees);
OnZRotationValueChanged(eulerGammaDegrees);
}
else
{
//reset everything
OnXTranslationValueChanged(0);
OnYTranslationValueChanged(0);
OnZTranslationValueChanged(0);
OnXRotationValueChanged(0);
OnYRotationValueChanged(0);
OnZRotationValueChanged(0);
}
}
-mitk::Geometry3D::Pointer QmitkInteractiveTransformationWidget::GetGeometry()
+mitk::BaseGeometry::Pointer QmitkInteractiveTransformationWidget::GetGeometry()
{
return m_Geometry;
}
/////////////////////////////////////////////////////////////////////////////////////////////
// Section to allow interactive positioning of the moving surface
/////////////////////////////////////////////////////////////////////////////////////////////
void QmitkInteractiveTransformationWidget::OnXTranslationValueChanged( int v )
{
mitk::Vector3D translationParams;
translationParams[0] = v;
translationParams[1] = m_Controls->m_YTransSlider->value();
translationParams[2] = m_Controls->m_ZTransSlider->value();
SetSliderX(v);
this->Translate(translationParams);
}
void QmitkInteractiveTransformationWidget::SetSliderX(int v)
{
m_Controls->m_XTransSlider->setValue(v);
m_Controls->m_XTransSpinBox->setValue(v);
}
void QmitkInteractiveTransformationWidget::OnYTranslationValueChanged( int v )
{
mitk::Vector3D translationParams;
translationParams[0] = m_Controls->m_XTransSlider->value();
translationParams[1] = v;
translationParams[2] = m_Controls->m_ZTransSlider->value();
SetSliderY(v);
this->Translate(translationParams);
}
void QmitkInteractiveTransformationWidget::SetSliderY(int v)
{
m_Controls->m_YTransSlider->setValue(v);
m_Controls->m_YTransSpinBox->setValue(v);
}
void QmitkInteractiveTransformationWidget::OnZTranslationValueChanged( int v )
{
mitk::Vector3D translationParams;
translationParams[0] = m_Controls->m_XTransSlider->value();
translationParams[1] = m_Controls->m_YTransSlider->value();
translationParams[2] = v;
SetSliderZ(v);
this->Translate(translationParams);
}
void QmitkInteractiveTransformationWidget::SetSliderZ(int v)
{
m_Controls->m_ZTransSlider->setValue(v);
m_Controls->m_ZTransSpinBox->setValue(v);
}
void QmitkInteractiveTransformationWidget::Translate( mitk::Vector3D translateVector)
{
mitk::Vector3D translateVec;
// transform the translation vector
translateVec[0] = translateVector[0] - m_TranslationVector[0];
translateVec[1] = translateVector[1] - m_TranslationVector[1];
translateVec[2] = translateVector[2] - m_TranslationVector[2];
// set the new translation vector to member variable
m_TranslationVector[0] = translateVector[0];
m_TranslationVector[1] = translateVector[1];
m_TranslationVector[2] = translateVector[2];
m_Geometry->Translate( translateVec );
qApp->processEvents();
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkInteractiveTransformationWidget::OnXRotationValueChanged( int v )
{
mitk::Vector3D rotationParams;
rotationParams[0] = v;
rotationParams[1] = m_Controls->m_YRotSlider->value();
rotationParams[2] = m_Controls->m_ZRotSlider->value();
m_Controls->m_XRotSlider->setValue(v);
m_Controls->m_XRotSpinBox->setValue(v);
this->Rotate(rotationParams);
}
void QmitkInteractiveTransformationWidget::OnYRotationValueChanged( int v )
{
mitk::Vector3D rotationParams;
rotationParams[0] = m_Controls->m_XRotSlider->value();
rotationParams[1] = v;
rotationParams[2] = m_Controls->m_ZRotSlider->value();
m_Controls->m_YRotSlider->setValue(v);
m_Controls->m_YRotSpinBox->setValue(v);
this->Rotate(rotationParams);
}
void QmitkInteractiveTransformationWidget::OnZRotationValueChanged( int v )
{
mitk::Vector3D rotationParams;
rotationParams[0]=m_Controls->m_XRotSlider->value();
rotationParams[1]=m_Controls->m_YRotSlider->value();
rotationParams[2]=v;
m_Controls->m_ZRotSlider->setValue(v);
m_Controls->m_ZRotSpinBox->setValue(v);
this->Rotate(rotationParams);
}
void QmitkInteractiveTransformationWidget::Rotate(mitk::Vector3D rotateVector)
{
//0: from degrees to radians
double radianX = rotateVector[0] * vnl_math::pi / 180;
double radianY = rotateVector[1] * vnl_math::pi / 180;
double radianZ = rotateVector[2] * vnl_math::pi / 180;
//1: from euler angles to quaternion
mitk::Quaternion rotation(radianX,radianY,radianZ);
//2: Conversion to navigation data / transform
mitk::NavigationData::Pointer rotationTransform = mitk::NavigationData::New();
rotationTransform->SetOrientation(rotation);
//3: Apply transform
//also remember old transform, but without rotation, because rotation is completely stored in the sliders
mitk::NavigationData::Pointer oldTransform = mitk::NavigationData::New(m_Geometry->GetIndexToWorldTransform());
mitk::Quaternion identity(0,0,0,1);
oldTransform->SetOrientation(identity);
//compose old transform with the new one
rotationTransform->Compose(oldTransform);
//and apply it...
m_Geometry->SetIndexToWorldTransform(rotationTransform->GetAffineTransform3D());
qApp->processEvents();
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkInteractiveTransformationWidget::OnResetGeometry()
{
m_Controls->m_XRotSlider->setValue(0);
m_Controls->m_YRotSlider->setValue(0);
m_Controls->m_ZRotSlider->setValue(0);
m_Controls->m_XRotSpinBox->setValue(0);
m_Controls->m_YRotSpinBox->setValue(0);
m_Controls->m_ZRotSpinBox->setValue(0);
m_Controls->m_XTransSlider->setValue(0);
m_Controls->m_YTransSlider->setValue(0);
m_Controls->m_ZTransSlider->setValue(0);
m_Controls->m_XTransSpinBox->setValue(0);
m_Controls->m_YTransSpinBox->setValue(0);
m_Controls->m_ZTransSpinBox->setValue(0);
qApp->processEvents();
// reset the input to its initial state.
- m_ResetGeometry->TransferItkToVtkTransform();
m_Geometry->SetIdentity();
m_Geometry->Compose(m_ResetGeometry->GetVtkTransform()->GetMatrix());
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkInteractiveTransformationWidget::OnApplyManipulatedToolTip()
{
emit ApplyManipulatedToolTip();
}
\ No newline at end of file
diff --git a/Modules/IGTUI/Qmitk/QmitkInteractiveTransformationWidget.h b/Modules/IGTUI/Qmitk/QmitkInteractiveTransformationWidget.h
index faec37487e..7b9cc00790 100644
--- a/Modules/IGTUI/Qmitk/QmitkInteractiveTransformationWidget.h
+++ b/Modules/IGTUI/Qmitk/QmitkInteractiveTransformationWidget.h
@@ -1,94 +1,94 @@
/*===================================================================
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 QmitkInteractiveTransformationWidget_H
#define QmitkInteractiveTransformationWidget_H
//QT headers
#include <QWidget>
//Mitk headers
#include "MitkIGTUIExports.h"
#include "mitkVector.h"
#include "mitkGeometry3D.h"
//ui header
#include "ui_QmitkInteractiveTransformationWidgetControls.h"
/** Documentation:
* \brief An object of this class offers an UI to create a widget to access the advance tool creation options.
*
*
* \ingroup IGTUI
*/
class MitkIGTUI_EXPORT QmitkInteractiveTransformationWidget : public QWidget
{
Q_OBJECT
public:
static const std::string VIEW_ID;
QmitkInteractiveTransformationWidget(QWidget* parent = 0, Qt::WindowFlags f = 0);
~QmitkInteractiveTransformationWidget();
/** Sets the geometry which will be modified by this widget. Default values may be
* provided by the second variable. These values will be applied to the geometry
* in the beginning and the UI will also hold these values.
*/
- void SetGeometry(mitk::Geometry3D::Pointer geometry, mitk::Geometry3D::Pointer defaultValues = NULL);
+ void SetGeometry(mitk::BaseGeometry::Pointer geometry, mitk::BaseGeometry::Pointer defaultValues = NULL);
- mitk::Geometry3D::Pointer GetGeometry();
+ mitk::BaseGeometry::Pointer GetGeometry();
protected slots:
void OnZTranslationValueChanged( int v );
void OnYTranslationValueChanged( int v );
void OnXTranslationValueChanged( int v );
void OnZRotationValueChanged( int v );
void OnYRotationValueChanged( int v );
void OnXRotationValueChanged( int v );
void OnResetGeometry();
void OnApplyManipulatedToolTip();
signals:
void ApplyManipulatedToolTip();
protected:
virtual void CreateConnections();
virtual void CreateQtPartControl(QWidget *parent);
void SetSliderX(int v);
void SetSliderY(int v);
void SetSliderZ(int v);
/*! \brief Method performs the translation.
\params translateVector New translation to be combine with geometry. */
void Translate( mitk::Vector3D translateVector);
/*! \brief Method performs the rotation.
\params rotateVector New rotation to be combined with geometry. */
void Rotate(mitk::Vector3D rotateVector);
// Member variables
Ui::QmitkInteractiveTransformationWidgetControls* m_Controls;
- mitk::Geometry3D::Pointer m_Geometry; ///< \brief Initial geometry that is manipulated
- mitk::Geometry3D::Pointer m_ResetGeometry; ///< \brief Lifeline to reset to the initial geometry
+ mitk::BaseGeometry::Pointer m_Geometry; ///< \brief Initial geometry that is manipulated
+ mitk::BaseGeometry::Pointer m_ResetGeometry; ///< \brief Lifeline to reset to the initial geometry
mitk::Vector3D m_TranslationVector; ///< \brief Accumulated translation vector
mitk::Vector3D m_RotateSliderPos; ///< \brief Accumulated rotation vector (holds degree around x,y,z direction)
};
#endif // QmitkInteractiveTransformationWidget_H
diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationAdvancedWidget.cpp b/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationAdvancedWidget.cpp
index 8aa0fb3cc8..84168dd8ce 100644
--- a/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationAdvancedWidget.cpp
+++ b/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationAdvancedWidget.cpp
@@ -1,204 +1,204 @@
/*===================================================================
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 "QmitkNavigationToolCreationAdvancedWidget.h"
#include "QmitkNavigationToolCreationWidget.h"
// mitk includes
#include <mitkRenderingManager.h>
#include <mitkNodePredicateNot.h>
#include <mitkNodePredicateProperty.h>
// vtk includes
#include <vtkSphereSource.h>
#include <vtkConeSource.h>
const std::string QmitkNavigationToolCreationAdvancedWidget::VIEW_ID = "org.mitk.views.navigationtoolcreationadvancedwidget";
QmitkNavigationToolCreationAdvancedWidget::QmitkNavigationToolCreationAdvancedWidget(QWidget* parent, Qt::WindowFlags f)
: QDialog(parent, f), m_Controls(NULL), m_DataStorage(NULL), m_ToolTipSurface(NULL), m_ManipulatedToolTip(NULL),
m_SurfaceNodeName("")
{
CreateQtPartControl(this);
CreateConnections();
}
QmitkNavigationToolCreationAdvancedWidget::~QmitkNavigationToolCreationAdvancedWidget()
{
}
void QmitkNavigationToolCreationAdvancedWidget::CreateQtPartControl(QWidget *parent)
{
if (!m_Controls)
{
// create GUI widgets
m_Controls = new Ui::QmitkNavigationToolCreationAdvancedWidgetControls;
m_Controls->setupUi(parent);
}
}
void QmitkNavigationToolCreationAdvancedWidget::CreateConnections()
{
if ( m_Controls )
{
connect( (QObject*)(this), SIGNAL(finished(int)), this, SLOT(OnClose()));
connect( (QObject*)(m_Controls->m_InteractiveTransformation), SIGNAL(ApplyManipulatedToolTip()), this, SLOT(OnApplyManipulatedToolTip()));
}
}
void QmitkNavigationToolCreationAdvancedWidget::OnClose()
{
//clean the data storage
if(m_DataStorage->Exists(m_DataStorage->GetNamedNode("StandardToolTip")))
{
m_DataStorage->Remove(m_DataStorage->GetNamedNode("StandardToolTip"));
}
if(m_DataStorage.IsNotNull() && m_DataStorage->Exists(m_DataStorage->GetNamedNode("ManipulatedToolTip")))
{
m_DataStorage->Remove(m_DataStorage->GetNamedNode("ManipulatedToolTip"));
}
emit DialogCloseRequested();
}
void QmitkNavigationToolCreationAdvancedWidget::SetDataStorage( mitk::DataStorage::Pointer dataStorage )
{
m_DataStorage = dataStorage;
}
void QmitkNavigationToolCreationAdvancedWidget::ReInitialize()
{
if (m_DataStorage.IsNull()) return;
//reset some variables
m_ManipulatedToolTip = NULL;
m_ToolTipSurface = NULL;
m_SurfaceNodeName = "";
- mitk::Geometry3D::Pointer emptyGeo = mitk::Geometry3D::New();
+ mitk::BaseGeometry::Pointer emptyGeo = mitk::Geometry3D::New();
m_Controls->m_InteractiveTransformation->SetGeometry(emptyGeo,emptyGeo);
//call initialization method
this->RetrieveAndInitializeDataForTooltipManipulation();
//care for new data nodes
mitk::DataNode::Pointer manipulatedTipNode = NULL;
if(!m_DataStorage->Exists(m_DataStorage->GetNamedNode("ManipulatedToolTip")))
{
manipulatedTipNode = mitk::DataNode::New();
manipulatedTipNode->SetData(m_ManipulatedToolTip);
manipulatedTipNode->SetName("ManipulatedToolTip");
manipulatedTipNode->SetColor(1.0, 0.0, 0.0);
manipulatedTipNode->SetOpacity(0.5);
m_DataStorage->Add(manipulatedTipNode);
}
else
{
manipulatedTipNode = m_DataStorage->GetNamedNode("ManipulatedToolTip");
manipulatedTipNode->SetData(m_ManipulatedToolTip);
}
// reinit the views with the new nodes
mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(m_DataStorage);
}
void QmitkNavigationToolCreationAdvancedWidget::RetrieveAndInitializeDataForTooltipManipulation()
{
// we need the tooltip surface (point or stl)
emit RetrieveDataForManualToolTipManipulation();
if(m_ToolTipSurface.IsNotNull())
{
mitk::DataNode::Pointer toolTipNode = NULL;
if(m_SurfaceNodeName.empty())
{
m_SurfaceNodeName = "StandardToolTip";
}
if(!m_DataStorage->Exists(m_DataStorage->GetNamedNode(m_SurfaceNodeName)))
{
toolTipNode = mitk::DataNode::New();
toolTipNode->SetName(m_SurfaceNodeName);
toolTipNode->SetData(m_ToolTipSurface);
m_DataStorage->Add(toolTipNode);
}
else
{
toolTipNode = m_DataStorage->GetNamedNode(m_SurfaceNodeName);
toolTipNode->SetData(m_ToolTipSurface);
}
m_ManipulatedToolTip = m_ToolTipSurface->Clone();
- mitk::Geometry3D::Pointer defaultGeo = mitk::Geometry3D::New();
+ mitk::BaseGeometry::Pointer defaultGeo = mitk::Geometry3D::New();
defaultGeo->SetIndexToWorldTransform(m_DefaultToolTip);
m_Controls->m_InteractiveTransformation->SetGeometry(m_ManipulatedToolTip->GetGeometry(),defaultGeo);
}
else
{
mitkThrow() << "No tooltip surface specified, operation aborted";
}
}
void QmitkNavigationToolCreationAdvancedWidget::SetDefaultTooltip(mitk::AffineTransform3D::Pointer defaultToolTip)
{
m_DefaultToolTip = defaultToolTip;
}
void QmitkNavigationToolCreationAdvancedWidget::SetToolTipSurface( bool cone, mitk::DataNode::Pointer node /*= NULL*/ )
{
m_ToolTipSurface = NULL;
if(cone)
{
m_ToolTipSurface = mitk::Surface::New();
vtkConeSource *vtkData = vtkConeSource::New();
vtkData->SetAngle(5.0);
vtkData->SetResolution(50);
vtkData->SetHeight(6.0f);
vtkData->SetRadius(2.0f);
vtkData->SetCenter(0.0, 0.0, 0.0);
vtkData->Update();
m_ToolTipSurface->SetVtkPolyData(vtkData->GetOutput());
vtkData->Delete();
m_SurfaceNodeName ="";
}
else if(!cone && node.IsNotNull())
{
m_ToolTipSurface = dynamic_cast<mitk::Surface*>(node->GetData());
m_SurfaceNodeName = node->GetName();
}
}
void QmitkNavigationToolCreationAdvancedWidget::OnApplyManipulatedToolTip()
{
//save manipulated surface object, which holds the tooltip as geometry
m_ManipulatedToolTip = dynamic_cast<mitk::Surface*>(m_DataStorage->GetNamedNode("ManipulatedToolTip")->GetData()->Clone().GetPointer());
//then close the window
OnClose();
}
mitk::AffineTransform3D::Pointer QmitkNavigationToolCreationAdvancedWidget::GetManipulatedToolTip()
{
mitk::AffineTransform3D::Pointer returnValue = mitk::AffineTransform3D::New();
if (m_ManipulatedToolTip.IsNotNull()) returnValue = m_ManipulatedToolTip->GetGeometry()->GetIndexToWorldTransform();
else returnValue->SetIdentity();
return returnValue;
}
diff --git a/Modules/IOExt/Internal/mitkParRecFileReader.cpp b/Modules/IOExt/Internal/mitkParRecFileReader.cpp
index 7b387b0cca..efcec5aeba 100644
--- a/Modules/IOExt/Internal/mitkParRecFileReader.cpp
+++ b/Modules/IOExt/Internal/mitkParRecFileReader.cpp
@@ -1,292 +1,292 @@
/*===================================================================
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 "mitkParRecFileReader.h"
#include <itkImageFileReader.h>
#ifdef __GNUC__
#define stricmp strcasecmp
#endif
void mitk::ParRecFileReader::GenerateOutputInformation()
{
mitk::Image::Pointer output = this->GetOutput();
if ((output->IsInitialized()) && (this->GetMTime() <= m_ReadHeaderTime.GetMTime()))
return;
itkDebugMacro(<<"Reading PAR file for GenerateOutputInformation()" << m_FileName);
// Check to see if we can read the file given the name or prefix
//
if ( m_FileName == "" && m_FilePrefix == "" )
{
throw itk::ImageFileReaderException(__FILE__, __LINE__, "One of FileName or FilePrefix must be non-empty");
}
m_RecFileName = "";
if( m_FileName != "")
{
int extPos=m_FileName.find_last_of(".");
if(extPos>=-1)
{
const char *ext=m_FileName.c_str()+extPos+1;
if(stricmp(ext,"par")==0)
m_RecFileName = m_FileName.substr(0,extPos);
else
m_RecFileName = m_FileName;
}
else
m_RecFileName = m_FileName;
m_RecFileName.append(".rec");
bool headerRead = false;
bool signedCharType = true;
unsigned int dimension=0;
unsigned int dimensions[4]={0,0,1,1};
float sliceThickness=0.0;
float sliceGap=0.0;
float sliceSpacing=0.0;
mitk::Vector3D thickness; thickness.Fill(1.0);
mitk::Vector3D gap; gap.Fill(0.0);
mitk::Vector3D spacing;
FILE *f;
f=fopen(m_FileName.c_str(), "r");
if(f!=NULL)
{
while(!feof(f))
{
char s[300], *p;
char* ignored = fgets(s,200,f);
++ignored;
if(strstr(s,"Max. number of cardiac phases"))
{
p=strchr(s,':')+1;
dimensions[3]=atoi(p);
if(dimensions[3]>1)
dimension=4;
}
else
if(strstr(s,"Max. number of slices/locations"))
{
p=strchr(s,':')+1;
dimensions[2]=atoi(p);
if(dimension==0)
{
if(dimensions[2]>1)
dimension=3;
else
dimension=2;
}
}
else
if(strstr(s,"Image pixel size"))
{
p=strchr(s,':')+1;
int bpe=atoi(p);
if(bpe!=8)
signedCharType = false;
}
else
if(strstr(s,"Recon resolution"))
{
p=s+strcspn(s,"0123456789");
sscanf(p,"%u %u", dimensions, dimensions+1);
}
else
if(strstr(s,"FOV (ap,fh,rl) [mm]"))
{
p=s+strcspn(s,"0123456789");
char *oldLocale = setlocale(LC_ALL, 0);
sscanf(p,"%lf %lf %lf", &thickness[0], &thickness[1], &thickness[2]);
setlocale(LC_ALL, oldLocale);
}
else
if(strstr(s,"Slice thickness [mm]"))
{
p=s+strcspn(s,"0123456789");
char *oldLocale = setlocale(LC_ALL, 0);
sscanf(p,"%f", &sliceThickness);
setlocale(LC_ALL, oldLocale);
}
else
if(strstr(s,"Slice gap [mm]"))
{
p=s+strcspn(s,"-0123456789");
char *oldLocale = setlocale(LC_ALL, 0);
sscanf(p,"%f", &sliceGap);
setlocale(LC_ALL, oldLocale);
}
}
fclose(f);
//C:\home\ivo\data\coronaries\ucsf-wholeheart-2.par
sliceSpacing = sliceThickness+sliceGap;
if((dimension>0) && (dimensions[0]>0) && (dimensions[1]>0) && (sliceThickness>0) && (sliceSpacing>0))
{
headerRead = true;
if(fabs(thickness[0]/dimensions[2]-sliceSpacing)<0.0001)
thickness[0]=thickness[1];
else
if(fabs(thickness[1]/dimensions[2]-sliceSpacing)<0.0001)
thickness[1]=thickness[0];
thickness[2]=sliceSpacing;
thickness[0]/=dimensions[0];
thickness[1]/=dimensions[1];
spacing=thickness+gap;
}
}
if( headerRead == false)
{
itk::ImageFileReaderException e(__FILE__, __LINE__);
std::ostringstream msg;
msg << " Could not read file "
<< m_FileName.c_str();
e.SetDescription(msg.str().c_str());
throw e;
return;
}
// define types
mitk::PixelType SCType = mitk::MakeScalarPixelType<signed char>();
mitk::PixelType SSType = mitk::MakeScalarPixelType<signed short>();
if( signedCharType )
output->Initialize(SCType, dimension, dimensions);
else
output->Initialize(SSType, dimension, dimensions);
output->GetSlicedGeometry()->SetSpacing(spacing);
- //output->GetSlicedGeometry()->SetGeometry2D(mitk::Image::BuildStandardPlaneGeometry2D(output->GetSlicedGeometry(), dimensions).GetPointer(), 0);
+ //output->GetSlicedGeometry()->SetPlaneGeometry(mitk::Image::BuildStandardPlanePlaneGeometry(output->GetSlicedGeometry(), dimensions).GetPointer(), 0);
output->GetSlicedGeometry()->SetEvenlySpaced();
}
m_ReadHeaderTime.Modified();
}
void mitk::ParRecFileReader::GenerateData()
{
mitk::Image::Pointer output = this->GetOutput();
// Check to see if we can read the file given the name or prefix
//
if ( m_RecFileName == "" )
{
throw itk::ImageFileReaderException(__FILE__, __LINE__, "FileName for rec-file empty");
}
if( m_RecFileName != "")
{
FILE *f = fopen(m_RecFileName.c_str(), "r");
if(f==NULL)
{
throw itk::ImageFileReaderException(__FILE__, __LINE__, "Could not open rec-file.");
}
int zstart, zmax;
int tstart, tmax;
zstart=output->GetRequestedRegion().GetIndex(2);
tstart=output->GetRequestedRegion().GetIndex(3);
zmax=zstart+output->GetRequestedRegion().GetSize(2);
tmax=tstart+output->GetRequestedRegion().GetSize(3);
int sliceSize=output->GetDimension(0)*output->GetDimension(1)*output->GetPixelType().GetBpe()/8;
void *data = malloc(sliceSize);
bool ignore4Dtopogram=false;
{
int slicePlusTimeSize=output->GetDimension(0)*output->GetDimension(1)*output->GetDimension(3)*output->GetPixelType().GetBpe()/8;
if(output->GetDimension(3)>1)
ignore4Dtopogram=true;
int z,t;
for(t=tstart;t<tmax;++t)
for(z=zstart;z<zmax;++z)
{
if(ignore4Dtopogram)
fseek(f,slicePlusTimeSize*z+(sliceSize+1)*t,SEEK_SET);
else
fseek(f,slicePlusTimeSize*z+sliceSize*t,SEEK_SET);
size_t ignored = fread(data, sliceSize, 1, f);
++ignored;
output->SetSlice(data,z,t,0);
}
}
//else
//{
// for(;z<zmax;++z)
// {
// fseek(f,sliceSize*z,SEEK_SET);
// fread(data, sliceSize, 1, f);
// output->SetSlice(data,z,0,0);
// }
//}
free(data);
fclose(f);
}
}
bool mitk::ParRecFileReader::CanReadFile(const std::string filename, const std::string /*filePrefix*/, const std::string /*filePattern*/)
{
// First check the extension
if( filename == "" )
{
//MITK_INFO<<"No filename specified."<<std::endl;
return false;
}
bool extensionFound = false;
std::string::size_type PARPos = filename.rfind(".par");
if ((PARPos != std::string::npos)
&& (PARPos == filename.length() - 4))
{
extensionFound = true;
}
PARPos = filename.rfind(".PAR");
if ((PARPos != std::string::npos)
&& (PARPos == filename.length() - 4))
{
extensionFound = true;
}
if( !extensionFound )
{
//MITK_INFO<<"The filename extension is not recognized."<<std::endl;
return false;
}
return true;
}
mitk::ParRecFileReader::ParRecFileReader()
: m_FileName(""), m_FilePrefix(""), m_FilePattern("")
{
}
mitk::ParRecFileReader::~ParRecFileReader()
{
}
diff --git a/Modules/IOExt/Internal/mitkUnstructuredGridVtkWriter.txx b/Modules/IOExt/Internal/mitkUnstructuredGridVtkWriter.txx
index c4890229c4..46eb319ee5 100644
--- a/Modules/IOExt/Internal/mitkUnstructuredGridVtkWriter.txx
+++ b/Modules/IOExt/Internal/mitkUnstructuredGridVtkWriter.txx
@@ -1,205 +1,203 @@
/*===================================================================
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 _MITK_UNSTRUCTURED_GRID_VTKWRITER_TXX_
#define _MITK_UNSTRUCTURED_GRID_VTKWRITER_TXX_
#include <itkLightObject.h>
#include <vtkUnstructuredGrid.h>
#include <vtkLinearTransform.h>
#include <vtkTransformFilter.h>
#include <vtkUnstructuredGridWriter.h>
#include <vtkXMLUnstructuredGridWriter.h>
#include <vtkXMLPUnstructuredGridWriter.h>
#include <sstream>
#include <sys/stat.h>
#include <sys/types.h>
#include <stdio.h>
namespace mitk {
template<class VTKWRITER>
UnstructuredGridVtkWriter<VTKWRITER>::UnstructuredGridVtkWriter()
: m_Success(false)
{
this->SetNumberOfRequiredInputs(1);
}
template<class VTKWRITER>
UnstructuredGridVtkWriter<VTKWRITER>::~UnstructuredGridVtkWriter()
{
}
template<class VTKWRITER>
void UnstructuredGridVtkWriter<VTKWRITER>::GenerateData()
{
m_Success = false;
if ( m_FileName == "" )
{
itkWarningMacro( << "Sorry, filename has not been set!" );
return ;
}
mitk::UnstructuredGrid::Pointer input = const_cast<mitk::UnstructuredGrid*>(this->GetInput());
if (input.IsNull())
{
itkWarningMacro( << "Sorry, input to mitk::UnstructuredGridVtkWriter is NULL");
return;
}
VTKWRITER* unstructuredGridWriter = VTKWRITER::New();
vtkTransformFilter* transformPointSet = vtkTransformFilter::New();
vtkUnstructuredGrid * unstructuredGrid;
- Geometry3D* geometry;
+ BaseGeometry* geometry;
if(input->GetTimeGeometry()->CountTimeSteps()>1)
{
int t, timesteps;
timesteps = input->GetTimeGeometry()->CountTimeSteps();
for(t = 0; t < timesteps; ++t)
{
std::ostringstream filename;
geometry = input->GetGeometry(t);
if(input->GetTimeGeometry()->IsValidTimeStep(t))
{
- const mitk::TimeBounds& timebounds = geometry->GetTimeBounds();
+ const mitk::TimeBounds& timebounds = input->GetTimeGeometry()->GetTimeBounds(t);
filename << m_FileName.c_str() << "_S" << std::setprecision(0) << timebounds[0] << "_E" << std::setprecision(0) << timebounds[1] << "_T" << t << GetDefaultExtension();
}
else
{
itkWarningMacro(<<"Error on write: TimeGeometry invalid of unstructured grid " << filename.str() << ".");
filename << m_FileName.c_str() << "_T" << t << GetDefaultExtension();
}
- geometry->TransferItkToVtkTransform();
transformPointSet->SetInputData(input->GetVtkUnstructuredGrid(t));
transformPointSet->SetTransform(geometry->GetVtkTransform());
transformPointSet->UpdateWholeExtent();
unstructuredGrid = static_cast<vtkUnstructuredGrid*>(transformPointSet->GetOutput());
unstructuredGridWriter->SetFileName(filename.str().c_str());
unstructuredGridWriter->SetInputData(unstructuredGrid);
ExecuteWrite( unstructuredGridWriter );
}
}
else
{
geometry = input->GetGeometry();
- geometry->TransferItkToVtkTransform();
transformPointSet->SetInputData(input->GetVtkUnstructuredGrid());
transformPointSet->SetTransform(geometry->GetVtkTransform());
transformPointSet->UpdateWholeExtent();
unstructuredGrid = static_cast<vtkUnstructuredGrid*>(transformPointSet->GetOutput());
unstructuredGridWriter->SetFileName(m_FileName.c_str());
unstructuredGridWriter->SetInputData(unstructuredGrid);
ExecuteWrite( unstructuredGridWriter );
}
transformPointSet->Delete();
unstructuredGridWriter->Delete();
m_Success = true;
}
template<class VTKWRITER>
void UnstructuredGridVtkWriter<VTKWRITER>::ExecuteWrite( VTKWRITER* vtkWriter )
{
struct stat fileStatus;
time_t timeBefore=0;
if (!stat(vtkWriter->GetFileName(), &fileStatus))
{
timeBefore = fileStatus.st_mtime;
}
if (!vtkWriter->Write())
{
itkExceptionMacro( << "Error during unstructured grid writing.");
}
// check if file can be written because vtkWriter doesn't check that
if (stat(vtkWriter->GetFileName(), &fileStatus) || (timeBefore == fileStatus.st_mtime))
{
itkExceptionMacro(<<"Error during unstructured grid writing: file could not be written");
}
}
template<class VTKWRITER>
void UnstructuredGridVtkWriter<VTKWRITER>::SetInput(BaseData *input)
{
this->ProcessObject::SetNthInput(0, input);
}
template<class VTKWRITER>
const UnstructuredGrid* UnstructuredGridVtkWriter<VTKWRITER>::GetInput()
{
if (this->GetNumberOfInputs() < 1)
{
return 0;
}
else
{
return dynamic_cast<UnstructuredGrid*>(this->ProcessObject::GetInput(0));
}
}
template<class VTKWRITER>
bool UnstructuredGridVtkWriter<VTKWRITER>::CanWriteBaseDataType(BaseData::Pointer data)
{
return (dynamic_cast<mitk::UnstructuredGrid*>(data.GetPointer()) != 0);
}
template<class VTKWRITER>
void UnstructuredGridVtkWriter<VTKWRITER>::DoWrite(BaseData::Pointer data)
{
if (CanWriteBaseDataType(data))
{
this->SetInput(dynamic_cast<mitk::UnstructuredGrid*>(data.GetPointer()));
this->Update();
}
}
template<class VTKWRITER>
std::vector<std::string> UnstructuredGridVtkWriter<VTKWRITER>::GetPossibleFileExtensions()
{
throw std::exception(); // no specialization available!
}
template<class VTKWRITER>
const char* UnstructuredGridVtkWriter<VTKWRITER>::GetDefaultFilename()
{
throw std::exception(); // no specialization available!
}
template<class VTKWRITER>
const char* UnstructuredGridVtkWriter<VTKWRITER>::GetFileDialogPattern()
{
throw std::exception(); // no specialization available!
}
template<class VTKWRITER>
const char* UnstructuredGridVtkWriter<VTKWRITER>::GetDefaultExtension()
{
throw std::exception(); // no specialization available!
}
}
#endif
diff --git a/Modules/ImageExtraction/mitkExtractDirectedPlaneImageFilter.cpp b/Modules/ImageExtraction/mitkExtractDirectedPlaneImageFilter.cpp
index 25caecd178..27bc33dfc4 100644
--- a/Modules/ImageExtraction/mitkExtractDirectedPlaneImageFilter.cpp
+++ b/Modules/ImageExtraction/mitkExtractDirectedPlaneImageFilter.cpp
@@ -1,490 +1,481 @@
/*===================================================================
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 "mitkExtractDirectedPlaneImageFilter.h"
#include "mitkAbstractTransformGeometry.h"
//#include "mitkImageMapperGL2D.h"
#include <mitkProperties.h>
#include <mitkDataNode.h>
#include <mitkDataNodeFactory.h>
#include <mitkResliceMethodProperty.h>
#include "vtkMitkThickSlicesFilter.h"
#include <vtkTransform.h>
#include <vtkGeneralTransform.h>
#include <vtkImageData.h>
#include <vtkImageChangeInformation.h>
#include <vtkPoints.h>
#include <vtkSmartPointer.h>
#include <vtkTransform.h>
mitk::ExtractDirectedPlaneImageFilter::ExtractDirectedPlaneImageFilter()
: m_WorldGeometry(NULL)
{
MITK_WARN << "Class ExtractDirectedPlaneImageFilter is deprecated! Use ExtractSliceFilter instead.";
m_Reslicer = vtkImageReslice::New();
m_TargetTimestep = 0;
m_InPlaneResampleExtentByGeometry = true;
m_ResliceInterpolationProperty = NULL;//VtkResliceInterpolationProperty::New(); //TODO initial with value
m_ThickSlicesMode = 0;
m_ThickSlicesNum = 1;
}
mitk::ExtractDirectedPlaneImageFilter::~ExtractDirectedPlaneImageFilter()
{
if(m_ResliceInterpolationProperty!=NULL)m_ResliceInterpolationProperty->Delete();
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 TimeGeometry *inputTimeGeometry = input->GetTimeGeometry();
if ( ( inputTimeGeometry == NULL )
|| ( inputTimeGeometry->CountTimeSteps() == 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->TimePointToTimeStep( time );
- }
- }
- else timestep = m_TargetTimestep;
+ unsigned int timestep = m_TargetTimestep;
if ( inputTimeGeometry->IsValidTimeStep( timestep ) == false )
{
itkWarningMacro(<<"This is not a valid timestep: "<<timestep);
return;
}
// check if there is something to display.
if ( ! input->IsVolumeSet( timestep ) )
{
itkWarningMacro(<<"No volume data existent at given timestep "<<timestep);
return;
}
Image::RegionType requestedRegion = input->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"<<timestep);
return;
}
double 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;
assert( input->GetTimeGeometry() == inputTimeGeometry );
// take transform of input image into account
- Geometry3D* inputGeometry = inputTimeGeometry->GetGeometryForTimeStep( timestep );
+ BaseGeometry* inputGeometry = inputTimeGeometry->GetGeometryForTimeStep( timestep );
if ( inputGeometry == NULL )
{
itkWarningMacro(<<"There is no Geometry3D at given timestep "<<timestep);
return;
}
ScalarType mmPerPixel[2];
// Bounds information for reslicing (only required if reference geometry
// is present)
double bounds[6];
bool boundsInitialized = false;
for ( int i = 0; i < 6; ++i )
{
bounds[i] = 0.0;
}
Vector2D extent; extent.Fill( 0.0 );
// Do we have a simple PlaneGeometry?
if ( dynamic_cast< const PlaneGeometry * >( 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)
+ // Set background level to TRANSLUCENT (see PlaneGeometryDataVtkMapper3D)
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)
+ // boundary artifacts (see PlaneGeometryDataVtkMapper3D)
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;
}
vtkSmartPointer<vtkImageChangeInformation> unitSpacingImageFilter = vtkImageChangeInformation::New() ;
unitSpacingImageFilter->SetOutputSpacing( 1.0, 1.0, 1.0 );
unitSpacingImageFilter->SetInputData( inputData );
m_Reslicer->SetInputConnection( unitSpacingImageFilter->GetOutputPort() );
//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.GetVnlVector(), cosines );
// direction of the Y-axis of the sampled result
vnl2vtk( bottom.GetVnlVector(), cosines + 3 );
// normal of the plane
vnl2vtk( normal.GetVnlVector(), cosines + 6 );
m_Reslicer->SetResliceAxesDirectionCosines( cosines );
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();
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(input->GetPixelType(), 2, dimensions );
resultImage->SetSpacing( spacingVector );
}
void mitk::ExtractDirectedPlaneImageFilter::GenerateOutputInformation()
{
Superclass::GenerateOutputInformation();
}
bool mitk::ExtractDirectedPlaneImageFilter
-::CalculateClippedPlaneBounds( const Geometry3D *boundingGeometry,
+::CalculateClippedPlaneBounds( const BaseGeometry *boundingGeometry,
const PlaneGeometry *planeGeometry, double *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();
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();
+ const mitk::Vector3D planeSpacing = planeGeometry->GetSpacing();
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,
double *bounds )
{
double point1[3];
double 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;
}
diff --git a/Modules/ImageExtraction/mitkExtractDirectedPlaneImageFilter.h b/Modules/ImageExtraction/mitkExtractDirectedPlaneImageFilter.h
index 7f08422153..0214e06b7f 100644
--- a/Modules/ImageExtraction/mitkExtractDirectedPlaneImageFilter.h
+++ b/Modules/ImageExtraction/mitkExtractDirectedPlaneImageFilter.h
@@ -1,125 +1,125 @@
/*===================================================================
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 mitkExtractDirectedPlaneImageFilter_h_Included
#define mitkExtractDirectedPlaneImageFilter_h_Included
#include <MitkImageExtractionExports.h>
#include "mitkImageToImageFilter.h"
#include "vtkImageReslice.h"
#include "mitkVtkResliceInterpolationProperty.h"
#define setMacro(name,type) \
virtual void Set##name (type _arg) \
{ \
if (this->m_##name != _arg) \
{ \
this->m_##name = _arg; \
} \
}
#define getMacro(name,type) \
virtual type Get##name () \
{ \
return m_##name; \
}
class vtkPoints;
namespace mitk
{
/**
\deprecated This class is deprecated. Use mitk::ExtractSliceFilter instead.
\sa ExtractSliceFilter
\brief Extracts a 2D slice of arbitrary geometry from a 3D or 4D image.
\sa mitkImageMapper2D
\ingroup ImageToImageFilter
This class takes a 3D or 4D mitk::Image as input and tries to extract one slice from it.
This slice can be arbitrary oriented in space. The 2D slice is resliced by a
vtk::ResliceImage filter if not perpendicular to the input image.
The world geometry of the plane to be extracted image must be given as an input
to the filter in order to correctly calculate world coordinates of the extracted slice.
Setting a timestep from which the plane should be extracted is optional.
Output will not be set if there was a problem extracting the desired slice.
Last contributor: $Author: T. Schwarz$
*/
class MitkImageExtraction_EXPORT ExtractDirectedPlaneImageFilter : public ImageToImageFilter
{
public:
mitkClassMacro(ExtractDirectedPlaneImageFilter, ImageToImageFilter);
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
- itkSetMacro( WorldGeometry, Geometry2D* );
+ itkSetMacro( WorldGeometry, PlaneGeometry* );
// The Reslicer is accessible to configure the desired interpolation;
// (See vtk::ImageReslice class for documentation).
// Misusage is at your own risk...
itkGetMacro( Reslicer, vtkImageReslice* );
// The target timestep in a 4D image from which the 2D plane is supposed
// to be extracted.
itkSetMacro( TargetTimestep, unsigned int );
itkGetMacro( TargetTimestep, unsigned int );
itkSetMacro( InPlaneResampleExtentByGeometry, bool );
itkGetMacro( InPlaneResampleExtentByGeometry, bool );
setMacro( ResliceInterpolationProperty, VtkResliceInterpolationProperty* );
itkGetMacro( ResliceInterpolationProperty, VtkResliceInterpolationProperty* );
setMacro( IsMapperMode, bool );
getMacro( IsMapperMode, bool );
protected:
ExtractDirectedPlaneImageFilter(); // purposely hidden
virtual ~ExtractDirectedPlaneImageFilter();
virtual void GenerateData();
virtual void GenerateOutputInformation();
- bool CalculateClippedPlaneBounds( const Geometry3D *boundingGeometry,
+ bool CalculateClippedPlaneBounds( const BaseGeometry *boundingGeometry,
const PlaneGeometry *planeGeometry, double *bounds );
bool LineIntersectZero( vtkPoints *points, int p1, int p2,
double *bounds );
- const Geometry2D* m_WorldGeometry;
+ const PlaneGeometry* m_WorldGeometry;
vtkImageReslice * m_Reslicer;
unsigned int m_TargetTimestep;
bool m_InPlaneResampleExtentByGeometry;
int m_ThickSlicesMode;
int m_ThickSlicesNum;
bool m_IsMapperMode;
VtkResliceInterpolationProperty* m_ResliceInterpolationProperty;
};
} // namespace mitk
#endif // mitkExtractDirectedPlaneImageFilter_h_Included
diff --git a/Modules/ImageExtraction/mitkExtractDirectedPlaneImageFilterNew.cpp b/Modules/ImageExtraction/mitkExtractDirectedPlaneImageFilterNew.cpp
index 3c92d1308b..9447cf64cc 100644
--- a/Modules/ImageExtraction/mitkExtractDirectedPlaneImageFilterNew.cpp
+++ b/Modules/ImageExtraction/mitkExtractDirectedPlaneImageFilterNew.cpp
@@ -1,297 +1,285 @@
/*===================================================================
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 "mitkExtractDirectedPlaneImageFilterNew.h"
#include "mitkImageCast.h"
#include "mitkImageTimeSelector.h"
#include "itkImageRegionIterator.h"
#include <mitkImageAccessByItk.h>
mitk::ExtractDirectedPlaneImageFilterNew::ExtractDirectedPlaneImageFilterNew()
-:m_CurrentWorldGeometry2D(NULL),
-m_ActualInputTimestep(-1)
+:m_CurrentWorldPlaneGeometry(NULL),
+m_ActualInputTimestep(0)
{
MITK_WARN << "Class ExtractDirectedPlaneImageFilterNew is deprecated! Use ExtractSliceFilter instead.";
}
mitk::ExtractDirectedPlaneImageFilterNew::~ExtractDirectedPlaneImageFilterNew()
{
}
void mitk::ExtractDirectedPlaneImageFilterNew::GenerateData(){
-
mitk::Image::ConstPointer inputImage = ImageToImageFilter::GetInput(0);
if ( !inputImage )
{
MITK_ERROR << "mitk::ExtractDirectedPlaneImageFilterNew: No input available. Please set the input!" << std::endl;
itkExceptionMacro("mitk::ExtractDirectedPlaneImageFilterNew: No input available. Please set the input!");
return;
}
m_ImageGeometry = inputImage->GetGeometry();
//If no timestep is set, the lowest given will be selected
const mitk::TimeGeometry* inputTimeGeometry = this->GetInput()->GetTimeGeometry();
- if ( m_ActualInputTimestep == -1)
- {
- ScalarType time = m_CurrentWorldGeometry2D->GetTimeBounds()[0];
- if ( time > ScalarTypeNumericTraits::NonpositiveMin() )
- {
- m_ActualInputTimestep = inputTimeGeometry->TimePointToTimeStep( time );
- }
- }
if ( inputImage->GetDimension() > 4 || inputImage->GetDimension() < 2)
{
MITK_ERROR << "mitk::ExtractDirectedPlaneImageFilterNew:GenerateData works only with 3D and 3D+t images, sorry." << std::endl;
itkExceptionMacro("mitk::ExtractDirectedPlaneImageFilterNew works only with 3D and 3D+t images, sorry.");
return;
}
else if ( inputImage->GetDimension() == 4 )
{
mitk::ImageTimeSelector::Pointer timeselector = mitk::ImageTimeSelector::New();
timeselector->SetInput( inputImage );
timeselector->SetTimeNr( m_ActualInputTimestep );
timeselector->UpdateLargestPossibleRegion();
inputImage = timeselector->GetOutput();
}
else if ( inputImage->GetDimension() == 2)
{
mitk::Image::Pointer resultImage = ImageToImageFilter::GetOutput();
resultImage = const_cast<mitk::Image*>( inputImage.GetPointer() );
ImageToImageFilter::SetNthOutput( 0, resultImage);
return;
}
- if ( !m_CurrentWorldGeometry2D )
+ if ( !m_CurrentWorldPlaneGeometry )
{
- MITK_ERROR<< "mitk::ExtractDirectedPlaneImageFilterNew::GenerateData has no CurrentWorldGeometry2D set" << std::endl;
+ MITK_ERROR<< "mitk::ExtractDirectedPlaneImageFilterNew::GenerateData has no CurrentWorldPlaneGeometry set" << std::endl;
return;
}
AccessFixedDimensionByItk( inputImage, ItkSliceExtraction, 3 );
-
}//Generate Data
void mitk::ExtractDirectedPlaneImageFilterNew::GenerateOutputInformation ()
{
Superclass::GenerateOutputInformation();
}
/*
* The desired slice is extracted by filling the image`s corresponding pixel values in an empty 2 dimensional itk::Image
* Therefor the itk image`s extent in pixel (in each direction) is doubled and its spacing (also in each direction) is divided by two
* (similar to the shannon theorem).
*/
template<typename TPixel, unsigned int VImageDimension>
void mitk::ExtractDirectedPlaneImageFilterNew::ItkSliceExtraction (itk::Image<TPixel, VImageDimension>* inputImage)
{
typedef itk::Image<TPixel, VImageDimension> InputImageType;
typedef itk::Image<TPixel, VImageDimension-1> SliceImageType;
typedef itk::ImageRegionConstIterator< SliceImageType > SliceIterator;
//Creating an itk::Image that represents the sampled slice
typename SliceImageType::Pointer resultSlice = SliceImageType::New();
typename SliceImageType::IndexType start;
start[0] = 0;
start[1] = 0;
- Point3D origin = m_CurrentWorldGeometry2D->GetOrigin();
- Vector3D right = m_CurrentWorldGeometry2D->GetAxisVector(0);
- Vector3D bottom = m_CurrentWorldGeometry2D->GetAxisVector(1);
+ Point3D origin = m_CurrentWorldPlaneGeometry->GetOrigin();
+ Vector3D right = m_CurrentWorldPlaneGeometry->GetAxisVector(0);
+ Vector3D bottom = m_CurrentWorldPlaneGeometry->GetAxisVector(1);
//Calculation the sample-spacing, i.e the half of the smallest spacing existing in the original image
Vector3D newPixelSpacing = m_ImageGeometry->GetSpacing();
float minSpacing = newPixelSpacing[0];
for (unsigned int i = 1; i < newPixelSpacing.Size(); i++)
{
if (newPixelSpacing[i] < minSpacing )
{
minSpacing = newPixelSpacing[i];
}
}
newPixelSpacing[0] = 0.5*minSpacing;
newPixelSpacing[1] = 0.5*minSpacing;
newPixelSpacing[2] = 0.5*minSpacing;
float pixelSpacing[2];
pixelSpacing[0] = newPixelSpacing[0];
pixelSpacing[1] = newPixelSpacing[1];
//Calculating the size of the sampled slice
typename SliceImageType::SizeType size;
Vector2D extentInMM;
- extentInMM[0] = m_CurrentWorldGeometry2D->GetExtentInMM(0);
- extentInMM[1] = m_CurrentWorldGeometry2D->GetExtentInMM(1);
+ extentInMM[0] = m_CurrentWorldPlaneGeometry->GetExtentInMM(0);
+ extentInMM[1] = m_CurrentWorldPlaneGeometry->GetExtentInMM(1);
//The maximum extent is the lenght of the diagonal of the considered plane
double maxExtent = sqrt(extentInMM[0]*extentInMM[0]+extentInMM[1]*extentInMM[1]);
unsigned int xTranlation = (maxExtent-extentInMM[0]);
unsigned int yTranlation = (maxExtent-extentInMM[1]);
size[0] = (maxExtent+xTranlation)/newPixelSpacing[0];
size[1] = (maxExtent+yTranlation)/newPixelSpacing[1];
//Creating an ImageRegion Object
typename SliceImageType::RegionType region;
region.SetSize( size );
region.SetIndex( start );
//Defining the image`s extent and origin by passing the region to it and allocating memory for it
resultSlice->SetRegions( region );
resultSlice->SetSpacing( pixelSpacing );
resultSlice->Allocate();
/*
* Here we create an new geometry so that the transformations are calculated correctly (our resulting slice has a different bounding box and spacing)
* The original current worldgeometry must be cloned because we have to keep the directions of the axis vector which represents the rotation
*/
right.Normalize();
bottom.Normalize();
//Here we translate the origin to adapt the new geometry to the previous calculated extent
origin[0] -= xTranlation*right[0]+yTranlation*bottom[0];
origin[1] -= xTranlation*right[1]+yTranlation*bottom[1];
origin[2] -= xTranlation*right[2]+yTranlation*bottom[2];
//Putting it together for the new geometry
- mitk::Geometry3D::Pointer newSliceGeometryTest = dynamic_cast<Geometry3D*>(m_CurrentWorldGeometry2D->Clone().GetPointer());
+ mitk::BaseGeometry::Pointer newSliceGeometryTest = dynamic_cast<BaseGeometry*>(m_CurrentWorldPlaneGeometry->Clone().GetPointer());
newSliceGeometryTest->ChangeImageGeometryConsideringOriginOffset(true);
//Workaround because of BUG (#6505)
- newSliceGeometryTest->GetIndexToWorldTransform()->SetMatrix(m_CurrentWorldGeometry2D->GetIndexToWorldTransform()->GetMatrix());
+ newSliceGeometryTest->GetIndexToWorldTransform()->SetMatrix(m_CurrentWorldPlaneGeometry->GetIndexToWorldTransform()->GetMatrix());
//Workaround end
newSliceGeometryTest->SetOrigin(origin);
ScalarType bounds[6]={0, static_cast<ScalarType>(size[0]), 0, static_cast<ScalarType>(size[1]), 0, 1};
newSliceGeometryTest->SetBounds(bounds);
newSliceGeometryTest->SetSpacing(newPixelSpacing);
newSliceGeometryTest->Modified();
//Workaround because of BUG (#6505)
itk::MatrixOffsetTransformBase<mitk::ScalarType,3,3>::MatrixType tempTransform = newSliceGeometryTest->GetIndexToWorldTransform()->GetMatrix();
//Workaround end
/*
* Now we iterate over the recently created slice.
* For each slice - pixel we check whether there is an according
* pixel in the input - image which can be set in the slice.
* In this way a slice is sampled out of the input - image regrading to the given PlaneGeometry
*/
Point3D currentSliceIndexPointIn2D;
Point3D currentImageWorldPointIn3D;
typename InputImageType::IndexType inputIndex;
SliceIterator sliceIterator ( resultSlice, resultSlice->GetLargestPossibleRegion() );
sliceIterator.GoToBegin();
while ( !sliceIterator.IsAtEnd() )
{
/*
* Here we add 0.5 to to assure that the indices are correctly transformed.
* (Because of the 0.5er Bug)
*/
currentSliceIndexPointIn2D[0] = sliceIterator.GetIndex()[0]+0.5;
currentSliceIndexPointIn2D[1] = sliceIterator.GetIndex()[1]+0.5;
currentSliceIndexPointIn2D[2] = 0;
newSliceGeometryTest->IndexToWorld( currentSliceIndexPointIn2D, currentImageWorldPointIn3D );
m_ImageGeometry->WorldToIndex( currentImageWorldPointIn3D, inputIndex);
if ( m_ImageGeometry->IsIndexInside( inputIndex ))
{
-
resultSlice->SetPixel( sliceIterator.GetIndex(), inputImage->GetPixel(inputIndex) );
-
}
else
{
resultSlice->SetPixel( sliceIterator.GetIndex(), 0);
}
++sliceIterator;
}
Image::Pointer resultImage = ImageToImageFilter::GetOutput();
GrabItkImageMemory(resultSlice, resultImage, NULL, false);
resultImage->SetClonedGeometry(newSliceGeometryTest);
//Workaround because of BUG (#6505)
resultImage->GetGeometry()->GetIndexToWorldTransform()->SetMatrix(tempTransform);
//Workaround end
}
///**TEST** May ba a little bit more efficient but doesn`t already work/
//right.Normalize();
//bottom.Normalize();
//Point3D currentImagePointIn3D = origin /*+ bottom*newPixelSpacing*/;
//unsigned int columns ( 0 );
/**ENDE**/
/****TEST***/
//SliceImageType::IndexType index = sliceIterator.GetIndex();
//if ( columns == (extentInPixel[0]) )
//{
//If we are at the end of a row, then we have to go to the beginning of the next row
//currentImagePointIn3D = origin;
//currentImagePointIn3D += newPixelSpacing[1]*bottom*index[1];
//columns = 0;
//m_ImageGeometry->WorldToIndex(currentImagePointIn3D, inputIndex);
//}
//else
//{
////
//if ( columns != 0 )
//{
//currentImagePointIn3D += newPixelSpacing[0]*right;
//}
//m_ImageGeometry->WorldToIndex(currentImagePointIn3D, inputIndex);
//}
//if ( m_ImageGeometry->IsIndexInside( inputIndex ))
//{
//resultSlice->SetPixel( sliceIterator.GetIndex(), inputImage->GetPixel(inputIndex) );
//}
//else if (currentImagePointIn3D == origin)
//{
//Point3D temp;
//temp[0] = bottom[0]*newPixelSpacing[0]*0.5;
//temp[1] = bottom[1]*newPixelSpacing[1]*0.5;
//temp[2] = bottom[2]*newPixelSpacing[2]*0.5;
//origin[0] += temp[0];
//origin[1] += temp[1];
//origin[2] += temp[2];
//currentImagePointIn3D = origin;
//m_ImageGeometry->WorldToIndex(currentImagePointIn3D, inputIndex);
//if ( m_ImageGeometry->IsIndexInside( inputIndex ))
//{
//resultSlice->SetPixel( sliceIterator.GetIndex(), inputImage->GetPixel(inputIndex) );
//}
//}
/****TEST ENDE****/
diff --git a/Modules/ImageExtraction/mitkExtractDirectedPlaneImageFilterNew.h b/Modules/ImageExtraction/mitkExtractDirectedPlaneImageFilterNew.h
index e6d0b03a7d..0fb8bfdf05 100644
--- a/Modules/ImageExtraction/mitkExtractDirectedPlaneImageFilterNew.h
+++ b/Modules/ImageExtraction/mitkExtractDirectedPlaneImageFilterNew.h
@@ -1,97 +1,98 @@
/*===================================================================
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 mitkExtractDirectedPlaneImageFilterNew_h_Included
#define mitkExtractDirectedPlaneImageFilterNew_h_Included
#include <MitkImageExtractionExports.h>
#include "mitkImageToImageFilter.h"
#include "itkImage.h"
#include "mitkITKImageImport.h"
namespace mitk {
-
-/**
+ /**
\deprecated This class is deprecated. Use mitk::ExtractSliceFilter instead.
\sa ExtractSliceFilter
\brief A filter that can extract a 2D slice from a 3D or 4D image especially if the image`s axes are rotated
\sa ContourTool
\sa SegTool2D
\sa ExtractImageFilter
\sa OverwriteSliceImageFilter
\sa OverwriteDirectedPlaneImageFilter
\ingroup Process
\ingroup Reliver
There is a separate page describing the general design of QmitkInteractiveSegmentation: \ref QmitkSegmentationTechnicalPage
This class takes an 3D or 4D mitk::Image as input and extracts a slice from it. If you work with a 4D image as input you have to specify the
desired timestep at which the slice shall be extracted, otherwise the lowest given timestep is selected by default.
The special feature of this filter is, that the planes of the input image can be rotated in any way. To assure a proper extraction you have to
- set the currentWorldGeometry2D with you can obtain from the BaseRenderer, respectively the positionEvent send by the renderer.
+ set the currentWorldPlaneGeometry with you can obtain from the BaseRenderer, respectively the positionEvent send by the renderer.
The output will not be set if there was a problem with the input image
$Author: fetzer $
-*/
-class MitkImageExtraction_EXPORT ExtractDirectedPlaneImageFilterNew : public ImageToImageFilter
-{
-
-public:
+ */
+ class MitkImageExtraction_EXPORT ExtractDirectedPlaneImageFilterNew : public ImageToImageFilter
+ {
+ public:
mitkClassMacro(ExtractDirectedPlaneImageFilterNew, ImageToImageFilter);
itkFactorylessNewMacro(Self)
- itkCloneMacro(Self)
+ itkCloneMacro(Self)
- /**
+ /**
\brief Set macro for the current worldgeometry
\a Parameter The current wordgeometry that describes the position (rotation, translation)
- of the plane (and therefore the slice to be extracted) in our 3D(+t) image
+ of the plane (and therefore the slice to be extracted) in our 3D(+t) image
+ */
+ itkSetMacro(CurrentWorldPlaneGeometry, BaseGeometry* );
+ /**
+ * \deprecatedSince{2014_06} Please use SetCurrentWorldPlaneGeometry
*/
- itkSetMacro(CurrentWorldGeometry2D, Geometry3D* );
+ DEPRECATED(void SetCurrentWorldGeometry2D(BaseGeometry* geo){SetCurrentWorldPlaneGeometry(geo);};)
- itkSetMacro(ImageGeometry, Geometry3D* );
+ itkSetMacro(ImageGeometry, BaseGeometry* );
/**
- \brief Set macro for the current timestep
+ \brief Set macro for the current timestep
- \a Parameter The timestep of the image from which the slice shall be extracted
+ \a Parameter The timestep of the image from which the slice shall be extracted
*/
itkSetMacro(ActualInputTimestep, int);
-protected:
+ protected:
ExtractDirectedPlaneImageFilterNew();
virtual ~ExtractDirectedPlaneImageFilterNew();
virtual void GenerateData();
virtual void GenerateOutputInformation();
-private:
- const Geometry3D* m_CurrentWorldGeometry2D;
- const Geometry3D* m_ImageGeometry;
+ private:
+ const BaseGeometry* m_CurrentWorldPlaneGeometry;
+ const BaseGeometry* m_ImageGeometry;
int m_ActualInputTimestep;
template<typename TPixel, unsigned int VImageDimension>
void ItkSliceExtraction (itk::Image<TPixel, VImageDimension>* inputImage);
-};
-
+ };
}//namespace
#endif
diff --git a/Modules/ImageExtraction/mitkExtractImageFilter.cpp b/Modules/ImageExtraction/mitkExtractImageFilter.cpp
index 0941ec8e99..913bad4399 100644
--- a/Modules/ImageExtraction/mitkExtractImageFilter.cpp
+++ b/Modules/ImageExtraction/mitkExtractImageFilter.cpp
@@ -1,265 +1,265 @@
/*===================================================================
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 "mitkExtractImageFilter.h"
#include "mitkImageCast.h"
#include "mitkPlaneGeometry.h"
#include "mitkITKImageImport.h"
#include "mitkImageTimeSelector.h"
#include <itkExtractImageFilter.h>
#include <mitkImageAccessByItk.h>
mitk::ExtractImageFilter::ExtractImageFilter()
:m_SliceIndex(0),
m_SliceDimension(0),
m_TimeStep(0),
m_DirectionCollapseToStrategy( DIRECTIONCOLLAPSETOGUESS )
{
MITK_WARN << "Class ExtractImageFilter is deprecated! Use ExtractSliceFilter instead.";
}
mitk::ExtractImageFilter::~ExtractImageFilter()
{
}
void mitk::ExtractImageFilter::GenerateData()
{
Image::ConstPointer input = ImageToImageFilter::GetInput(0);
if ( (input->GetDimension() > 4) || (input->GetDimension() < 2) )
{
MITK_ERROR << "mitk::ExtractImageFilter:GenerateData works only with 3D and 3D+t images, sorry." << std::endl;
itkExceptionMacro("mitk::ExtractImageFilter works only with 3D and 3D+t images, sorry.");
return;
}
else if (input->GetDimension() == 4)
{
mitk::ImageTimeSelector::Pointer timeSelector = ImageTimeSelector::New();
timeSelector->SetInput( input );
timeSelector->SetTimeNr( m_TimeStep );
timeSelector->UpdateLargestPossibleRegion();
input = timeSelector->GetOutput();
}
else if (input->GetDimension() == 2)
{
Image::Pointer resultImage = ImageToImageFilter::GetOutput();
resultImage = const_cast<Image*>(input.GetPointer());
ImageToImageFilter::SetNthOutput( 0, resultImage );
return;
}
if ( m_SliceDimension >= input->GetDimension() )
{
MITK_ERROR << "mitk::ExtractImageFilter:GenerateData m_SliceDimension == " << m_SliceDimension << " makes no sense with an " << input->GetDimension() << "D image." << std::endl;
itkExceptionMacro("This is not a sensible value for m_SliceDimension.");
return;
}
AccessFixedDimensionByItk( input, ItkImageProcessing, 3 );
// set a nice geometry for display and point transformations
- Geometry3D* inputImageGeometry = ImageToImageFilter::GetInput(0)->GetGeometry();
+ BaseGeometry* inputImageGeometry = ImageToImageFilter::GetInput(0)->GetGeometry();
if (!inputImageGeometry)
{
MITK_ERROR << "In ExtractImageFilter::ItkImageProcessing: Input image has no geometry!" << std::endl;
return;
}
PlaneGeometry::PlaneOrientation orientation = PlaneGeometry::Axial;
switch ( m_SliceDimension )
{
default:
case 2:
orientation = PlaneGeometry::Axial;
break;
case 1:
orientation = PlaneGeometry::Frontal;
break;
case 0:
orientation = PlaneGeometry::Sagittal;
break;
}
PlaneGeometry::Pointer planeGeometry = PlaneGeometry::New();
planeGeometry->InitializeStandardPlane( inputImageGeometry, orientation, (ScalarType)m_SliceIndex, true, false );
Image::Pointer resultImage = ImageToImageFilter::GetOutput();
planeGeometry->ChangeImageGeometryConsideringOriginOffset(true);
resultImage->SetGeometry( planeGeometry );
}
template<typename TPixel, unsigned int VImageDimension>
void mitk::ExtractImageFilter::ItkImageProcessing( itk::Image<TPixel,VImageDimension>* itkImage )
{
// use the itk::ExtractImageFilter to get a 2D image
typedef itk::Image< TPixel, VImageDimension > ImageType3D;
typedef itk::Image< TPixel, VImageDimension-1 > ImageType2D;
typedef itk::ExtractImageFilter<ImageType3D, ImageType2D> ExtractImageFilterType;
typename ImageType3D::RegionType inSliceRegion = itkImage->GetLargestPossibleRegion();
inSliceRegion.SetSize( m_SliceDimension, 0 );
typename ExtractImageFilterType::Pointer sliceExtractor = ExtractImageFilterType::New();
typename ExtractImageFilterType::DIRECTIONCOLLAPSESTRATEGY collapseStrategy;
switch( m_DirectionCollapseToStrategy )
{
case DIRECTIONCOLLAPSETOUNKOWN:
collapseStrategy = ExtractImageFilterType::DIRECTIONCOLLAPSETOUNKOWN;
break;
case DIRECTIONCOLLAPSETOIDENTITY:
collapseStrategy = ExtractImageFilterType::DIRECTIONCOLLAPSETOIDENTITY;
break;
case DIRECTIONCOLLAPSETOSUBMATRIX:
collapseStrategy = ExtractImageFilterType::DIRECTIONCOLLAPSETOSUBMATRIX;
break;
case DIRECTIONCOLLAPSETOGUESS:
default:
collapseStrategy = ExtractImageFilterType::DIRECTIONCOLLAPSETOGUESS;
break;
}
sliceExtractor->SetDirectionCollapseToStrategy( collapseStrategy );
sliceExtractor->SetInput( itkImage );
inSliceRegion.SetIndex( m_SliceDimension, m_SliceIndex );
sliceExtractor->SetExtractionRegion( inSliceRegion );
// calculate the output
sliceExtractor->UpdateLargestPossibleRegion();
typename ImageType2D::Pointer slice = sliceExtractor->GetOutput();
// re-import to MITK
Image::Pointer resultImage = ImageToImageFilter::GetOutput();
GrabItkImageMemory(slice, resultImage, NULL, false);
}
/*
* What is the input requested region that is required to produce the output
* requested region? By default, the largest possible region is always
* required but this is overridden in many subclasses. For instance, for an
* image processing filter where an output pixel is a simple function of an
* input pixel, the input requested region will be set to the output
* requested region. For an image processing filter where an output pixel is
* a function of the pixels in a neighborhood of an input pixel, then the
* input requested region will need to be larger than the output requested
* region (to avoid introducing artificial boundary conditions). This
* function should never request an input region that is outside the the
* input largest possible region (i.e. implementations of this method should
* crop the input requested region at the boundaries of the input largest
* possible region).
*/
void mitk::ExtractImageFilter::GenerateInputRequestedRegion()
{
Superclass::GenerateInputRequestedRegion();
ImageToImageFilter::InputImagePointer input = const_cast< ImageToImageFilter::InputImageType* > ( this->GetInput() );
Image::Pointer output = this->GetOutput();
if (input->GetDimension() == 2)
{
input->SetRequestedRegionToLargestPossibleRegion();
return;
}
Image::RegionType requestedRegion;
requestedRegion = output->GetRequestedRegion();
requestedRegion.SetIndex(0, 0);
requestedRegion.SetIndex(1, 0);
requestedRegion.SetIndex(2, 0);
requestedRegion.SetSize(0, input->GetDimension(0));
requestedRegion.SetSize(1, input->GetDimension(1));
requestedRegion.SetSize(2, input->GetDimension(2));
requestedRegion.SetIndex( m_SliceDimension, m_SliceIndex ); // only one slice needed
requestedRegion.SetSize( m_SliceDimension, 1 );
input->SetRequestedRegion( &requestedRegion );
}
/*
* Generate the information decribing the output data. The default
* implementation of this method will copy information from the input to the
* output. A filter may override this method if its output will have different
* information than its input. For instance, a filter that shrinks an image will
* need to provide an implementation for this method that changes the spacing of
* the pixels. Such filters should call their superclass' implementation of this
* method prior to changing the information values they need (i.e.
* GenerateOutputInformation() should call
* Superclass::GenerateOutputInformation() prior to changing the information.
*/
void mitk::ExtractImageFilter::GenerateOutputInformation()
{
Image::Pointer output = this->GetOutput();
Image::ConstPointer input = this->GetInput();
if (input.IsNull()) return;
if ( m_SliceDimension >= input->GetDimension() && input->GetDimension() != 2 )
{
MITK_ERROR << "mitk::ExtractImageFilter:GenerateOutputInformation m_SliceDimension == " << m_SliceDimension << " makes no sense with an " << input->GetDimension() << "D image." << std::endl;
itkExceptionMacro("This is not a sensible value for m_SliceDimension.");
return;
}
unsigned int sliceDimension( m_SliceDimension );
if ( input->GetDimension() == 2)
{
sliceDimension = 2;
}
unsigned int tmpDimensions[2];
switch ( sliceDimension )
{
default:
case 2:
// orientation = PlaneGeometry::Axial;
tmpDimensions[0] = input->GetDimension(0);
tmpDimensions[1] = input->GetDimension(1);
break;
case 1:
// orientation = PlaneGeometry::Frontal;
tmpDimensions[0] = input->GetDimension(0);
tmpDimensions[1] = input->GetDimension(2);
break;
case 0:
// orientation = PlaneGeometry::Sagittal;
tmpDimensions[0] = input->GetDimension(1);
tmpDimensions[1] = input->GetDimension(2);
break;
}
output->Initialize(input->GetPixelType(), 2, tmpDimensions, 1 /*input->GetNumberOfChannels()*/);
// initialize the spacing of the output
/*
Vector3D spacing = input->GetSlicedGeometry()->GetSpacing();
if(input->GetDimension()>=2)
spacing[2]=spacing[1];
else
spacing[2] = 1.0;
output->GetSlicedGeometry()->SetSpacing(spacing);
*/
output->SetPropertyList(input->GetPropertyList()->Clone());
}
diff --git a/Modules/ImageStatistics/Testing/mitkImageStatisticsCalculatorTest.cpp b/Modules/ImageStatistics/Testing/mitkImageStatisticsCalculatorTest.cpp
index 9f57aa9705..33168ae0e9 100644
--- a/Modules/ImageStatistics/Testing/mitkImageStatisticsCalculatorTest.cpp
+++ b/Modules/ImageStatistics/Testing/mitkImageStatisticsCalculatorTest.cpp
@@ -1,409 +1,409 @@
/*===================================================================
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 "mitkTestFixture.h"
#include "mitkTestingMacros.h"
#include "mitkImageStatisticsCalculator.h"
#include "mitkPlanarPolygon.h"
#include "mitkDicomSeriesReader.h"
/**
* \brief Test class for mitkImageStatisticsCalculator
*
* This test covers:
* - instantiation of an ImageStatisticsCalculator class
* - correctness of statistics when using PlanarFigures for masking
*/
class mitkImageStatisticsCalculatorTestSuite : public mitk::TestFixture
{
CPPUNIT_TEST_SUITE(mitkImageStatisticsCalculatorTestSuite);
MITK_TEST(TestUninitializedImage);
MITK_TEST(TestCase1);
MITK_TEST(TestCase2);
MITK_TEST(TestCase3);
MITK_TEST(TestCase4);
MITK_TEST(TestCase5);
MITK_TEST(TestCase6);
MITK_TEST(TestCase7);
MITK_TEST(TestCase8);
MITK_TEST(TestCase9);
MITK_TEST(TestCase10);
MITK_TEST(TestCase11);
MITK_TEST(TestCase12);
CPPUNIT_TEST_SUITE_END();
public:
void setUp();
void TestUninitializedImage();
void TestCase1();
void TestCase2();
void TestCase3();
void TestCase4();
void TestCase5();
void TestCase6();
void TestCase7();
void TestCase8();
void TestCase9();
void TestCase10();
void TestCase11();
void TestCase12();
private:
mitk::Image::Pointer m_Image;
- mitk::Geometry2D::Pointer m_Geometry;
+ mitk::PlaneGeometry::Pointer m_Geometry;
// calculate statistics for the given image and planarpolygon
const mitk::ImageStatisticsCalculator::Statistics ComputeStatistics( mitk::Image::Pointer image,
mitk::PlanarFigure::Pointer polygon );
void VerifyStatistics(const mitk::ImageStatisticsCalculator::Statistics& stats,
double testMean, double testSD);
};
void mitkImageStatisticsCalculatorTestSuite::setUp()
{
std::string filename = this->GetTestDataFilePath("ImageStatistics/testimage.dcm");
if (filename.empty())
{
MITK_TEST_FAILED_MSG( << "Could not find test file" )
}
mitk::DicomSeriesReader::StringContainer file;
file.push_back( filename );
mitk::DicomSeriesReader* reader = new mitk::DicomSeriesReader;
mitk::DataNode::Pointer node = reader->LoadDicomSeries( file, false, false );
m_Image = dynamic_cast<mitk::Image*>( node->GetData() );
MITK_TEST_CONDITION_REQUIRED( m_Image.IsNotNull(), "Loading test image" )
- m_Geometry = m_Image->GetSlicedGeometry()->GetGeometry2D(0);
+ m_Geometry = m_Image->GetSlicedGeometry()->GetPlaneGeometry(0);
MITK_TEST_CONDITION_REQUIRED( m_Geometry.IsNotNull(), "Getting image geometry" )
}
void mitkImageStatisticsCalculatorTestSuite::TestCase1()
{
/*****************************
* one whole white pixel
* -> mean of 255 expected
******************************/
mitk::PlanarPolygon::Pointer figure1 = mitk::PlanarPolygon::New();
- figure1->SetGeometry2D( m_Geometry );
+ figure1->SetPlaneGeometry( m_Geometry );
mitk::Point2D pnt1; pnt1[0] = 10.5 ; pnt1[1] = 3.5;
figure1->PlaceFigure( pnt1 );
mitk::Point2D pnt2; pnt2[0] = 9.5; pnt2[1] = 3.5;
figure1->SetControlPoint( 1, pnt2, true );
mitk::Point2D pnt3; pnt3[0] = 9.5; pnt3[1] = 4.5;
figure1->SetControlPoint( 2, pnt3, true );
mitk::Point2D pnt4; pnt4[0] = 10.5; pnt4[1] = 4.5;
figure1->SetControlPoint( 3, pnt4, true );
figure1->GetPolyLine(0);
this->VerifyStatistics(ComputeStatistics(m_Image, figure1.GetPointer()), 255.0, 0.0);
}
void mitkImageStatisticsCalculatorTestSuite::TestCase2()
{
/*****************************
* half pixel in x-direction (white)
* -> mean of 255 expected
******************************/
mitk::PlanarPolygon::Pointer figure1 = mitk::PlanarPolygon::New();
- figure1->SetGeometry2D( m_Geometry );
+ figure1->SetPlaneGeometry( m_Geometry );
mitk::Point2D pnt1; pnt1[0] = 10.0 ; pnt1[1] = 3.5;
figure1->PlaceFigure( pnt1 );
mitk::Point2D pnt2; pnt2[0] = 9.5; pnt2[1] = 3.5;
figure1->SetControlPoint( 1, pnt2, true );
mitk::Point2D pnt3; pnt3[0] = 9.5; pnt3[1] = 4.5;
figure1->SetControlPoint( 2, pnt3, true );
mitk::Point2D pnt4; pnt4[0] = 10.0; pnt4[1] = 4.5;
figure1->SetControlPoint( 3, pnt4, true );
figure1->GetPolyLine(0);
this->VerifyStatistics(ComputeStatistics(m_Image, figure1.GetPointer()), 255.0, 0.0);
}
void mitkImageStatisticsCalculatorTestSuite::TestCase3()
{
/*****************************
* half pixel in diagonal-direction (white)
* -> mean of 255 expected
******************************/
mitk::PlanarPolygon::Pointer figure1 = mitk::PlanarPolygon::New();
- figure1->SetGeometry2D( m_Geometry );
+ figure1->SetPlaneGeometry( m_Geometry );
mitk::Point2D pnt1; pnt1[0] = 10.5 ; pnt1[1] = 3.5;
figure1->PlaceFigure( pnt1 );
mitk::Point2D pnt2; pnt2[0] = 9.5; pnt2[1] = 3.5;
figure1->SetControlPoint( 1, pnt2, true );
mitk::Point2D pnt3; pnt3[0] = 9.5; pnt3[1] = 4.5;
figure1->SetControlPoint( 2, pnt3, true );
figure1->GetPolyLine(0);
this->VerifyStatistics(ComputeStatistics(m_Image, figure1.GetPointer()), 255.0, 0.0);
}
void mitkImageStatisticsCalculatorTestSuite::TestCase4()
{
/*****************************
* one pixel (white) + 2 half pixels (white) + 1 half pixel (black)
* -> mean of 191.25 expected
******************************/
mitk::PlanarPolygon::Pointer figure1 = mitk::PlanarPolygon::New();
- figure1->SetGeometry2D( m_Geometry );
+ figure1->SetPlaneGeometry( m_Geometry );
mitk::Point2D pnt1; pnt1[0] = 1.1; pnt1[1] = 1.1;
figure1->PlaceFigure( pnt1 );
mitk::Point2D pnt2; pnt2[0] = 2.0; pnt2[1] = 2.0;
figure1->SetControlPoint( 1, pnt2, true );
mitk::Point2D pnt3; pnt3[0] = 3.0; pnt3[1] = 1.0;
figure1->SetControlPoint( 2, pnt3, true );
mitk::Point2D pnt4; pnt4[0] = 2.0; pnt4[1] = 0.0;
figure1->SetControlPoint( 3, pnt4, true );
figure1->GetPolyLine(0);
this->VerifyStatistics(ComputeStatistics(m_Image, figure1.GetPointer()), 191.25, 127.5);
}
void mitkImageStatisticsCalculatorTestSuite::TestCase5()
{
/*****************************
* whole pixel (white) + half pixel (gray) in x-direction
* -> mean of 191.5 expected
******************************/
mitk::PlanarPolygon::Pointer figure1 = mitk::PlanarPolygon::New();
- figure1->SetGeometry2D( m_Geometry );
+ figure1->SetPlaneGeometry( m_Geometry );
mitk::Point2D pnt1; pnt1[0] = 11.0; pnt1[1] = 3.5;
figure1->PlaceFigure( pnt1 );
mitk::Point2D pnt2; pnt2[0] = 9.5; pnt2[1] = 3.5;
figure1->SetControlPoint( 1, pnt2, true );
mitk::Point2D pnt3; pnt3[0] = 9.5; pnt3[1] = 4.5;
figure1->SetControlPoint( 2, pnt3, true );
mitk::Point2D pnt4; pnt4[0] = 11.0; pnt4[1] = 4.5;
figure1->SetControlPoint( 3, pnt4, true );
figure1->GetPolyLine(0);
this->VerifyStatistics(ComputeStatistics(m_Image, figure1.GetPointer()), 191.50, 89.80);
}
void mitkImageStatisticsCalculatorTestSuite::TestCase6()
{
/*****************************
* quarter pixel (black) + whole pixel (white) + half pixel (gray) in x-direction
* -> mean of 191.5 expected
******************************/
mitk::PlanarPolygon::Pointer figure1 = mitk::PlanarPolygon::New();
- figure1->SetGeometry2D( m_Geometry );
+ figure1->SetPlaneGeometry( m_Geometry );
mitk::Point2D pnt1; pnt1[0] = 11.0; pnt1[1] = 3.5;
figure1->PlaceFigure( pnt1 );
mitk::Point2D pnt2; pnt2[0] = 9.25; pnt2[1] = 3.5;
figure1->SetControlPoint( 1, pnt2, true );
mitk::Point2D pnt3; pnt3[0] = 9.25; pnt3[1] = 4.5;
figure1->SetControlPoint( 2, pnt3, true );
mitk::Point2D pnt4; pnt4[0] = 11.0; pnt4[1] = 4.5;
figure1->SetControlPoint( 3, pnt4, true );
figure1->GetPolyLine(0);
this->VerifyStatistics(ComputeStatistics(m_Image, figure1.GetPointer()), 191.5, 89.80);
}
void mitkImageStatisticsCalculatorTestSuite::TestCase7()
{
/*****************************
* half pixel (black) + whole pixel (white) + half pixel (gray) in x-direction
* -> mean of 127.66 expected
******************************/
mitk::PlanarPolygon::Pointer figure1 = mitk::PlanarPolygon::New();
- figure1->SetGeometry2D( m_Geometry );
+ figure1->SetPlaneGeometry( m_Geometry );
mitk::Point2D pnt1; pnt1[0] = 11.0; pnt1[1] = 3.5;
figure1->PlaceFigure( pnt1 );
mitk::Point2D pnt2; pnt2[0] = 9.0; pnt2[1] = 3.5;
figure1->SetControlPoint( 1, pnt2, true );
mitk::Point2D pnt3; pnt3[0] = 9.0; pnt3[1] = 4.0;
figure1->SetControlPoint( 2, pnt3, true );
mitk::Point2D pnt4; pnt4[0] = 11.0; pnt4[1] = 4.0;
figure1->SetControlPoint( 3, pnt4, true );
figure1->GetPolyLine(0);
this->VerifyStatistics(ComputeStatistics(m_Image, figure1.GetPointer()), 127.66, 127.5);
}
void mitkImageStatisticsCalculatorTestSuite::TestCase8()
{
/*****************************
* whole pixel (gray)
* -> mean of 128 expected
******************************/
mitk::PlanarPolygon::Pointer figure2 = mitk::PlanarPolygon::New();
- figure2->SetGeometry2D( m_Geometry );
+ figure2->SetPlaneGeometry( m_Geometry );
mitk::Point2D pnt1; pnt1[0] = 11.5; pnt1[1] = 10.5;
figure2->PlaceFigure( pnt1 );
mitk::Point2D pnt2; pnt2[0] = 11.5; pnt2[1] = 11.5;
figure2->SetControlPoint( 1, pnt2, true );
mitk::Point2D pnt3; pnt3[0] = 12.5; pnt3[1] = 11.5;
figure2->SetControlPoint( 2, pnt3, true );
mitk::Point2D pnt4; pnt4[0] = 12.5; pnt4[1] = 10.5;
figure2->SetControlPoint( 3, pnt4, true );
figure2->GetPolyLine(0);
this->VerifyStatistics(ComputeStatistics(m_Image, figure2.GetPointer()), 128.0, 0.0);
}
void mitkImageStatisticsCalculatorTestSuite::TestCase9()
{
/*****************************
* whole pixel (gray) + half pixel (white) in y-direction
* -> mean of 191.5 expected
******************************/
mitk::PlanarPolygon::Pointer figure2 = mitk::PlanarPolygon::New();
- figure2->SetGeometry2D( m_Geometry );
+ figure2->SetPlaneGeometry( m_Geometry );
mitk::Point2D pnt1; pnt1[0] = 11.5; pnt1[1] = 10.5;
figure2->PlaceFigure( pnt1 );
mitk::Point2D pnt2; pnt2[0] = 11.5; pnt2[1] = 12.0;
figure2->SetControlPoint( 1, pnt2, true );
mitk::Point2D pnt3; pnt3[0] = 12.5; pnt3[1] = 12.0;
figure2->SetControlPoint( 2, pnt3, true );
mitk::Point2D pnt4; pnt4[0] = 12.5; pnt4[1] = 10.5;
figure2->SetControlPoint( 3, pnt4, true );
figure2->GetPolyLine(0);
this->VerifyStatistics(ComputeStatistics(m_Image, figure2.GetPointer()), 191.5, 89.80);
}
void mitkImageStatisticsCalculatorTestSuite::TestCase10()
{
/*****************************
* 2 whole pixel (white) + 2 whole pixel (black) in y-direction
* -> mean of 127.66 expected
******************************/
mitk::PlanarPolygon::Pointer figure2 = mitk::PlanarPolygon::New();
- figure2->SetGeometry2D( m_Geometry );
+ figure2->SetPlaneGeometry( m_Geometry );
mitk::Point2D pnt1; pnt1[0] = 11.5; pnt1[1] = 10.5;
figure2->PlaceFigure( pnt1 );
mitk::Point2D pnt2; pnt2[0] = 11.5; pnt2[1] = 13.5;
figure2->SetControlPoint( 1, pnt2, true );
mitk::Point2D pnt3; pnt3[0] = 12.5; pnt3[1] = 13.5;
figure2->SetControlPoint( 2, pnt3, true );
mitk::Point2D pnt4; pnt4[0] = 12.5; pnt4[1] = 10.5;
figure2->SetControlPoint( 3, pnt4, true );
figure2->GetPolyLine(0);
this->VerifyStatistics(ComputeStatistics(m_Image, figure2.GetPointer()), 127.66, 127.5);
}
void mitkImageStatisticsCalculatorTestSuite::TestCase11()
{
/*****************************
* 9 whole pixels (white) + 3 half pixels (white)
* + 3 whole pixel (black) [ + 3 slightly less than half pixels (black)]
* -> mean of 204.0 expected
******************************/
mitk::PlanarPolygon::Pointer figure2 = mitk::PlanarPolygon::New();
- figure2->SetGeometry2D( m_Geometry );
+ figure2->SetPlaneGeometry( m_Geometry );
mitk::Point2D pnt1; pnt1[0] = 0.5; pnt1[1] = 0.5;
figure2->PlaceFigure( pnt1 );
mitk::Point2D pnt2; pnt2[0] = 3.5; pnt2[1] = 3.5;
figure2->SetControlPoint( 1, pnt2, true );
mitk::Point2D pnt3; pnt3[0] = 8.4999; pnt3[1] = 3.5;
figure2->SetControlPoint( 2, pnt3, true );
mitk::Point2D pnt4; pnt4[0] = 5.4999; pnt4[1] = 0.5;
figure2->SetControlPoint( 3, pnt4, true );
figure2->GetPolyLine(0);
this->VerifyStatistics(ComputeStatistics(m_Image, figure2.GetPointer()), 204.0, 105.58 );
}
void mitkImageStatisticsCalculatorTestSuite::TestCase12()
{
/*****************************
* half pixel (white) + whole pixel (white) + half pixel (black)
* -> mean of 212.66 expected
******************************/
mitk::PlanarPolygon::Pointer figure2 = mitk::PlanarPolygon::New();
- figure2->SetGeometry2D( m_Geometry );
+ figure2->SetPlaneGeometry( m_Geometry );
mitk::Point2D pnt1; pnt1[0] = 9.5; pnt1[1] = 0.5;
figure2->PlaceFigure( pnt1 );
mitk::Point2D pnt2; pnt2[0] = 9.5; pnt2[1] = 2.5;
figure2->SetControlPoint( 1, pnt2, true );
mitk::Point2D pnt3; pnt3[0] = 11.5; pnt3[1] = 2.5;
figure2->SetControlPoint( 2, pnt3, true );
figure2->GetPolyLine(0);
this->VerifyStatistics(ComputeStatistics(m_Image, figure2.GetPointer()), 212.66, 73.32);
}
const mitk::ImageStatisticsCalculator::Statistics
mitkImageStatisticsCalculatorTestSuite::ComputeStatistics( mitk::Image::Pointer image, mitk::PlanarFigure::Pointer polygon )
{
mitk::ImageStatisticsCalculator::Pointer statisticsCalculator = mitk::ImageStatisticsCalculator::New();
statisticsCalculator->SetImage( image );
statisticsCalculator->SetMaskingModeToPlanarFigure();
statisticsCalculator->SetPlanarFigure( polygon );
statisticsCalculator->ComputeStatistics();
return statisticsCalculator->GetStatistics();
}
void mitkImageStatisticsCalculatorTestSuite::VerifyStatistics(const mitk::ImageStatisticsCalculator::Statistics& stats,
double testMean, double testSD)
{
int tmpMean = stats.Mean * 100;
double calculatedMean = tmpMean / 100.0;
MITK_TEST_CONDITION( calculatedMean == testMean,
"Calculated mean grayvalue '" << calculatedMean <<
"' is equal to the desired value '" << testMean << "'" );
int tmpSD = stats.Sigma * 100;
double calculatedSD = tmpSD / 100.0;
MITK_TEST_CONDITION( calculatedSD == testSD,
"Calculated grayvalue sd '" << calculatedSD <<
"' is equal to the desired value '" << testSD <<"'" );
}
void mitkImageStatisticsCalculatorTestSuite::TestUninitializedImage()
{
/*****************************
* loading uninitialized image to datastorage
******************************/
MITK_TEST_FOR_EXCEPTION_BEGIN(mitk::Exception)
mitk::Image::Pointer image = mitk::Image::New();
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData(image);
mitk::ImageStatisticsCalculator::Pointer is = mitk::ImageStatisticsCalculator::New();
is->ComputeStatistics();
MITK_TEST_FOR_EXCEPTION_END(mitk::Exception)
}
MITK_TEST_SUITE_REGISTRATION(mitkImageStatisticsCalculator)
diff --git a/Modules/ImageStatistics/mitkImageStatisticsCalculator.cpp b/Modules/ImageStatistics/mitkImageStatisticsCalculator.cpp
index eeb94cfbf4..8f25857b47 100644
--- a/Modules/ImageStatistics/mitkImageStatisticsCalculator.cpp
+++ b/Modules/ImageStatistics/mitkImageStatisticsCalculator.cpp
@@ -1,1291 +1,1290 @@
/*===================================================================
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 "mitkImageStatisticsCalculator.h"
#include "mitkImageAccessByItk.h"
#include "mitkImageCast.h"
#include "mitkExtractImageFilter.h"
#include <itkScalarImageToHistogramGenerator.h>
#include <itkChangeInformationImageFilter.h>
#include <itkExtractImageFilter.h>
#include <itkMinimumMaximumImageCalculator.h>
#include <itkStatisticsImageFilter.h>
#include <itkLabelStatisticsImageFilter.h>
#include <itkMaskImageFilter.h>
#include <itkImageFileWriter.h>
#include <itkRescaleIntensityImageFilter.h>
#include <itkCastImageFilter.h>
#include <itkImageFileWriter.h>
#include <itkVTKImageImport.h>
#include <itkVTKImageExport.h>
#include <itkImageDuplicator.h>
#include <vtkPoints.h>
#include <vtkCellArray.h>
#include <vtkPolyData.h>
#include <vtkLinearExtrusionFilter.h>
#include <vtkPolyDataToImageStencil.h>
#include <vtkImageStencil.h>
#include <vtkImageImport.h>
#include <vtkImageExport.h>
#include <vtkImageData.h>
#include <vtkLassoStencilSource.h>
#include <vtkMetaImageWriter.h>
#include <list>
#include <exception>
namespace mitk
{
ImageStatisticsCalculator::ImageStatisticsCalculator()
: m_MaskingMode( MASKING_MODE_NONE ),
m_MaskingModeChanged( false ),
m_IgnorePixelValue(0.0),
m_DoIgnorePixelValue(false),
m_IgnorePixelValueChanged(false),
m_PlanarFigureAxis (0),
m_PlanarFigureSlice (0),
m_PlanarFigureCoordinate0 (0),
m_PlanarFigureCoordinate1 (0),
m_HistogramBinSize(1)
{
m_EmptyHistogram = HistogramType::New();
m_EmptyHistogram->SetMeasurementVectorSize(1);
HistogramType::SizeType histogramSize(1);
histogramSize.Fill( 256 );
m_EmptyHistogram->Initialize( histogramSize );
m_EmptyStatistics.Reset();
}
ImageStatisticsCalculator::~ImageStatisticsCalculator()
{
}
void ImageStatisticsCalculator::SetImage( const mitk::Image *image )
{
if ( m_Image != image )
{
m_Image = image;
this->Modified();
unsigned int numberOfTimeSteps = image->GetTimeSteps();
// Initialize vectors to time-size of this image
m_ImageHistogramVector.resize( numberOfTimeSteps );
m_MaskedImageHistogramVector.resize( numberOfTimeSteps );
m_PlanarFigureHistogramVector.resize( numberOfTimeSteps );
m_ImageStatisticsVector.resize( numberOfTimeSteps );
m_MaskedImageStatisticsVector.resize( numberOfTimeSteps );
m_PlanarFigureStatisticsVector.resize( numberOfTimeSteps );
m_ImageStatisticsTimeStampVector.resize( numberOfTimeSteps );
m_MaskedImageStatisticsTimeStampVector.resize( numberOfTimeSteps );
m_PlanarFigureStatisticsTimeStampVector.resize( numberOfTimeSteps );
m_ImageStatisticsCalculationTriggerVector.resize( numberOfTimeSteps );
m_MaskedImageStatisticsCalculationTriggerVector.resize( numberOfTimeSteps );
m_PlanarFigureStatisticsCalculationTriggerVector.resize( numberOfTimeSteps );
for ( unsigned int t = 0; t < image->GetTimeSteps(); ++t )
{
m_ImageStatisticsTimeStampVector[t].Modified();
m_ImageStatisticsCalculationTriggerVector[t] = true;
}
}
}
void ImageStatisticsCalculator::SetImageMask( const mitk::Image *imageMask )
{
if ( m_Image.IsNull() )
{
itkExceptionMacro( << "Image needs to be set first!" );
}
if ( m_ImageMask != imageMask )
{
m_ImageMask = imageMask;
this->Modified();
for ( unsigned int t = 0; t < m_Image->GetTimeSteps(); ++t )
{
m_MaskedImageStatisticsTimeStampVector[t].Modified();
m_MaskedImageStatisticsCalculationTriggerVector[t] = true;
}
}
}
void ImageStatisticsCalculator::SetPlanarFigure( mitk::PlanarFigure *planarFigure )
{
if ( m_Image.IsNull() )
{
itkExceptionMacro( << "Image needs to be set first!" );
}
if ( m_PlanarFigure != planarFigure )
{
m_PlanarFigure = planarFigure;
this->Modified();
for ( unsigned int t = 0; t < m_Image->GetTimeSteps(); ++t )
{
m_PlanarFigureStatisticsTimeStampVector[t].Modified();
m_PlanarFigureStatisticsCalculationTriggerVector[t] = true;
}
}
}
void ImageStatisticsCalculator::SetMaskingMode( unsigned int mode )
{
if ( m_MaskingMode != mode )
{
m_MaskingMode = mode;
m_MaskingModeChanged = true;
this->Modified();
}
}
void ImageStatisticsCalculator::SetMaskingModeToNone()
{
if ( m_MaskingMode != MASKING_MODE_NONE )
{
m_MaskingMode = MASKING_MODE_NONE;
m_MaskingModeChanged = true;
this->Modified();
}
}
void ImageStatisticsCalculator::SetMaskingModeToImage()
{
if ( m_MaskingMode != MASKING_MODE_IMAGE )
{
m_MaskingMode = MASKING_MODE_IMAGE;
m_MaskingModeChanged = true;
this->Modified();
}
}
void ImageStatisticsCalculator::SetMaskingModeToPlanarFigure()
{
if ( m_MaskingMode != MASKING_MODE_PLANARFIGURE )
{
m_MaskingMode = MASKING_MODE_PLANARFIGURE;
m_MaskingModeChanged = true;
this->Modified();
}
}
void ImageStatisticsCalculator::SetIgnorePixelValue(double value)
{
if ( m_IgnorePixelValue != value )
{
m_IgnorePixelValue = value;
if(m_DoIgnorePixelValue)
{
m_IgnorePixelValueChanged = true;
}
this->Modified();
}
}
double ImageStatisticsCalculator::GetIgnorePixelValue()
{
return m_IgnorePixelValue;
}
void ImageStatisticsCalculator::SetDoIgnorePixelValue(bool value)
{
if ( m_DoIgnorePixelValue != value )
{
m_DoIgnorePixelValue = value;
m_IgnorePixelValueChanged = true;
this->Modified();
}
}
bool ImageStatisticsCalculator::GetDoIgnorePixelValue()
{
return m_DoIgnorePixelValue;
}
void ImageStatisticsCalculator::SetHistogramBinSize(unsigned int size)
{
this->m_HistogramBinSize = size;
}
unsigned int ImageStatisticsCalculator::GetHistogramBinSize()
{
return this->m_HistogramBinSize;
}
bool ImageStatisticsCalculator::ComputeStatistics( unsigned int timeStep )
{
if (m_Image.IsNull() )
{
mitkThrow() << "Image not set!";
}
if (!m_Image->IsInitialized())
{
mitkThrow() << "Image not initialized!";
}
if ( m_Image->GetReferenceCount() == 1 )
{
// Image no longer valid; we are the only ones to still hold a reference on it
return false;
}
if ( timeStep >= m_Image->GetTimeSteps() )
{
throw std::runtime_error( "Error: invalid time step!" );
}
// If a mask was set but we are the only ones to still hold a reference on
// it, delete it.
if ( m_ImageMask.IsNotNull() && (m_ImageMask->GetReferenceCount() == 1) )
{
m_ImageMask = NULL;
}
// Check if statistics is already up-to-date
unsigned long imageMTime = m_ImageStatisticsTimeStampVector[timeStep].GetMTime();
unsigned long maskedImageMTime = m_MaskedImageStatisticsTimeStampVector[timeStep].GetMTime();
unsigned long planarFigureMTime = m_PlanarFigureStatisticsTimeStampVector[timeStep].GetMTime();
bool imageStatisticsCalculationTrigger = m_ImageStatisticsCalculationTriggerVector[timeStep];
bool maskedImageStatisticsCalculationTrigger = m_MaskedImageStatisticsCalculationTriggerVector[timeStep];
bool planarFigureStatisticsCalculationTrigger = m_PlanarFigureStatisticsCalculationTriggerVector[timeStep];
if ( !m_IgnorePixelValueChanged
&& ((m_MaskingMode != MASKING_MODE_NONE) || (imageMTime > m_Image->GetMTime() && !imageStatisticsCalculationTrigger))
&& ((m_MaskingMode != MASKING_MODE_IMAGE) || (maskedImageMTime > m_ImageMask->GetMTime() && !maskedImageStatisticsCalculationTrigger))
&& ((m_MaskingMode != MASKING_MODE_PLANARFIGURE) || (planarFigureMTime > m_PlanarFigure->GetMTime() && !planarFigureStatisticsCalculationTrigger)) )
{
// Statistics is up to date!
if ( m_MaskingModeChanged )
{
m_MaskingModeChanged = false;
return true;
}
else
{
return false;
}
}
// Reset state changed flag
m_MaskingModeChanged = false;
m_IgnorePixelValueChanged = false;
// Depending on masking mode, extract and/or generate the required image
// and mask data from the user input
this->ExtractImageAndMask( timeStep );
StatisticsContainer *statisticsContainer;
HistogramContainer *histogramContainer;
switch ( m_MaskingMode )
{
case MASKING_MODE_NONE:
default:
if(!m_DoIgnorePixelValue)
{
statisticsContainer = &m_ImageStatisticsVector[timeStep];
histogramContainer = &m_ImageHistogramVector[timeStep];
m_ImageStatisticsTimeStampVector[timeStep].Modified();
m_ImageStatisticsCalculationTriggerVector[timeStep] = false;
}
else
{
statisticsContainer = &m_MaskedImageStatisticsVector[timeStep];
histogramContainer = &m_MaskedImageHistogramVector[timeStep];
m_MaskedImageStatisticsTimeStampVector[timeStep].Modified();
m_MaskedImageStatisticsCalculationTriggerVector[timeStep] = false;
}
break;
case MASKING_MODE_IMAGE:
statisticsContainer = &m_MaskedImageStatisticsVector[timeStep];
histogramContainer = &m_MaskedImageHistogramVector[timeStep];
m_MaskedImageStatisticsTimeStampVector[timeStep].Modified();
m_MaskedImageStatisticsCalculationTriggerVector[timeStep] = false;
break;
case MASKING_MODE_PLANARFIGURE:
statisticsContainer = &m_PlanarFigureStatisticsVector[timeStep];
histogramContainer = &m_PlanarFigureHistogramVector[timeStep];
m_PlanarFigureStatisticsTimeStampVector[timeStep].Modified();
m_PlanarFigureStatisticsCalculationTriggerVector[timeStep] = false;
break;
}
// Calculate statistics and histogram(s)
if ( m_InternalImage->GetDimension() == 3 )
{
if ( m_MaskingMode == MASKING_MODE_NONE && !m_DoIgnorePixelValue )
{
AccessFixedDimensionByItk_2(
m_InternalImage,
InternalCalculateStatisticsUnmasked,
3,
statisticsContainer,
histogramContainer );
}
else
{
AccessFixedDimensionByItk_3(
m_InternalImage,
InternalCalculateStatisticsMasked,
3,
m_InternalImageMask3D.GetPointer(),
statisticsContainer,
histogramContainer );
}
}
else if ( m_InternalImage->GetDimension() == 2 )
{
if ( m_MaskingMode == MASKING_MODE_NONE && !m_DoIgnorePixelValue )
{
AccessFixedDimensionByItk_2(
m_InternalImage,
InternalCalculateStatisticsUnmasked,
2,
statisticsContainer,
histogramContainer );
}
else
{
AccessFixedDimensionByItk_3(
m_InternalImage,
InternalCalculateStatisticsMasked,
2,
m_InternalImageMask2D.GetPointer(),
statisticsContainer,
histogramContainer );
}
}
else
{
MITK_ERROR << "ImageStatistics: Image dimension not supported!";
}
// Release unused image smart pointers to free memory
m_InternalImage = mitk::Image::ConstPointer();
m_InternalImageMask3D = MaskImage3DType::Pointer();
m_InternalImageMask2D = MaskImage2DType::Pointer();
return true;
}
const ImageStatisticsCalculator::HistogramType *
ImageStatisticsCalculator::GetHistogram( unsigned int timeStep, unsigned int label ) const
{
if ( m_Image.IsNull() || (timeStep >= m_Image->GetTimeSteps()) )
{
return NULL;
}
switch ( m_MaskingMode )
{
case MASKING_MODE_NONE:
default:
{
if(m_DoIgnorePixelValue)
return m_MaskedImageHistogramVector[timeStep][label];
return m_ImageHistogramVector[timeStep][label];
}
case MASKING_MODE_IMAGE:
return m_MaskedImageHistogramVector[timeStep][label];
case MASKING_MODE_PLANARFIGURE:
return m_PlanarFigureHistogramVector[timeStep][label];
}
}
const ImageStatisticsCalculator::HistogramContainer &
ImageStatisticsCalculator::GetHistogramVector( unsigned int timeStep ) const
{
if ( m_Image.IsNull() || (timeStep >= m_Image->GetTimeSteps()) )
{
return m_EmptyHistogramContainer;
}
switch ( m_MaskingMode )
{
case MASKING_MODE_NONE:
default:
{
if(m_DoIgnorePixelValue)
return m_MaskedImageHistogramVector[timeStep];
return m_ImageHistogramVector[timeStep];
}
case MASKING_MODE_IMAGE:
return m_MaskedImageHistogramVector[timeStep];
case MASKING_MODE_PLANARFIGURE:
return m_PlanarFigureHistogramVector[timeStep];
}
}
const ImageStatisticsCalculator::Statistics &
ImageStatisticsCalculator::GetStatistics( unsigned int timeStep, unsigned int label ) const
{
if ( m_Image.IsNull() || (timeStep >= m_Image->GetTimeSteps()) )
{
return m_EmptyStatistics;
}
switch ( m_MaskingMode )
{
case MASKING_MODE_NONE:
default:
{
if(m_DoIgnorePixelValue)
return m_MaskedImageStatisticsVector[timeStep][label];
return m_ImageStatisticsVector[timeStep][label];
}
case MASKING_MODE_IMAGE:
return m_MaskedImageStatisticsVector[timeStep][label];
case MASKING_MODE_PLANARFIGURE:
return m_PlanarFigureStatisticsVector[timeStep][label];
}
}
const ImageStatisticsCalculator::StatisticsContainer &
ImageStatisticsCalculator::GetStatisticsVector( unsigned int timeStep ) const
{
if ( m_Image.IsNull() || (timeStep >= m_Image->GetTimeSteps()) )
{
return m_EmptyStatisticsContainer;
}
switch ( m_MaskingMode )
{
case MASKING_MODE_NONE:
default:
{
if(m_DoIgnorePixelValue)
return m_MaskedImageStatisticsVector[timeStep];
return m_ImageStatisticsVector[timeStep];
}
case MASKING_MODE_IMAGE:
return m_MaskedImageStatisticsVector[timeStep];
case MASKING_MODE_PLANARFIGURE:
return m_PlanarFigureStatisticsVector[timeStep];
}
}
void ImageStatisticsCalculator::ExtractImageAndMask( unsigned int timeStep )
{
if ( m_Image.IsNull() )
{
throw std::runtime_error( "Error: image empty!" );
}
if ( timeStep >= m_Image->GetTimeSteps() )
{
throw std::runtime_error( "Error: invalid time step!" );
}
ImageTimeSelector::Pointer imageTimeSelector = ImageTimeSelector::New();
imageTimeSelector->SetInput( m_Image );
imageTimeSelector->SetTimeNr( timeStep );
imageTimeSelector->UpdateLargestPossibleRegion();
mitk::Image *timeSliceImage = imageTimeSelector->GetOutput();
switch ( m_MaskingMode )
{
case MASKING_MODE_NONE:
{
m_InternalImage = timeSliceImage;
m_InternalImageMask2D = NULL;
m_InternalImageMask3D = NULL;
if(m_DoIgnorePixelValue)
{
if( m_InternalImage->GetDimension() == 3 )
{
if(itk::ImageIOBase::USHORT != timeSliceImage->GetPixelType().GetComponentType())
CastToItkImage( timeSliceImage, m_InternalImageMask3D );
else
CastToItkImage( timeSliceImage->Clone(), m_InternalImageMask3D );
m_InternalImageMask3D->FillBuffer(1);
}
if( m_InternalImage->GetDimension() == 2 )
{
if(itk::ImageIOBase::USHORT != timeSliceImage->GetPixelType().GetComponentType())
CastToItkImage( timeSliceImage, m_InternalImageMask2D );
else
CastToItkImage( timeSliceImage->Clone(), m_InternalImageMask2D );
m_InternalImageMask2D->FillBuffer(1);
}
}
break;
}
case MASKING_MODE_IMAGE:
{
if ( m_ImageMask.IsNotNull() && (m_ImageMask->GetReferenceCount() > 1) )
{
if ( timeStep >= m_ImageMask->GetTimeSteps() )
{
// Use the last mask time step in case the current time step is bigger than the total
// number of mask time steps.
// It makes more sense setting this to the last mask time step than to 0.
// For instance if you have a mask with 2 time steps and an image with 5:
// If time step 0 is selected, the mask will use time step 0.
// If time step 1 is selected, the mask will use time step 1.
// If time step 2+ is selected, the mask will use time step 1.
// If you have a mask with only one time step instead, this will always default to 0.
timeStep = m_ImageMask->GetTimeSteps() - 1;
}
ImageTimeSelector::Pointer maskedImageTimeSelector = ImageTimeSelector::New();
maskedImageTimeSelector->SetInput( m_ImageMask );
maskedImageTimeSelector->SetTimeNr( timeStep );
maskedImageTimeSelector->UpdateLargestPossibleRegion();
mitk::Image *timeSliceMaskedImage = maskedImageTimeSelector->GetOutput();
m_InternalImage = timeSliceImage;
CastToItkImage( timeSliceMaskedImage, m_InternalImageMask3D );
}
else
{
throw std::runtime_error( "Error: image mask empty!" );
}
break;
}
case MASKING_MODE_PLANARFIGURE:
{
m_InternalImageMask2D = NULL;
if ( m_PlanarFigure.IsNull() )
{
throw std::runtime_error( "Error: planar figure empty!" );
}
if ( !m_PlanarFigure->IsClosed() )
{
throw std::runtime_error( "Masking not possible for non-closed figures" );
}
- const Geometry3D *imageGeometry = timeSliceImage->GetGeometry();
+ const BaseGeometry *imageGeometry = timeSliceImage->GetGeometry();
if ( imageGeometry == NULL )
{
throw std::runtime_error( "Image geometry invalid!" );
}
- const Geometry2D *planarFigureGeometry2D = m_PlanarFigure->GetGeometry2D();
- if ( planarFigureGeometry2D == NULL )
+ const PlaneGeometry *planarFigurePlaneGeometry = m_PlanarFigure->GetPlaneGeometry();
+ if ( planarFigurePlaneGeometry == NULL )
{
throw std::runtime_error( "Planar-Figure not yet initialized!" );
}
const PlaneGeometry *planarFigureGeometry =
- dynamic_cast< const PlaneGeometry * >( planarFigureGeometry2D );
+ dynamic_cast< const PlaneGeometry * >( planarFigurePlaneGeometry );
if ( planarFigureGeometry == NULL )
{
throw std::runtime_error( "Non-planar planar figures not supported!" );
}
// Find principal direction of PlanarFigure in input image
unsigned int axis;
if ( !this->GetPrincipalAxis( imageGeometry,
planarFigureGeometry->GetNormal(), axis ) )
{
throw std::runtime_error( "Non-aligned planar figures not supported!" );
}
m_PlanarFigureAxis = axis;
// Find slice number corresponding to PlanarFigure in input image
MaskImage3DType::IndexType index;
imageGeometry->WorldToIndex( planarFigureGeometry->GetOrigin(), index );
unsigned int slice = index[axis];
m_PlanarFigureSlice = slice;
// Extract slice with given position and direction from image
unsigned int dimension = timeSliceImage->GetDimension();
if (dimension != 2)
{
ExtractImageFilter::Pointer imageExtractor = ExtractImageFilter::New();
imageExtractor->SetInput( timeSliceImage );
imageExtractor->SetSliceDimension( axis );
imageExtractor->SetSliceIndex( slice );
imageExtractor->Update();
m_InternalImage = imageExtractor->GetOutput();
}
else
{
m_InternalImage = timeSliceImage;
}
// Compute mask from PlanarFigure
AccessFixedDimensionByItk_1(
m_InternalImage,
InternalCalculateMaskFromPlanarFigure,
2, axis );
}
}
if(m_DoIgnorePixelValue)
{
if ( m_InternalImage->GetDimension() == 3 )
{
AccessFixedDimensionByItk_1(
m_InternalImage,
InternalMaskIgnoredPixels,
3,
m_InternalImageMask3D.GetPointer() );
}
else if ( m_InternalImage->GetDimension() == 2 )
{
AccessFixedDimensionByItk_1(
m_InternalImage,
InternalMaskIgnoredPixels,
2,
m_InternalImageMask2D.GetPointer() );
}
}
}
bool ImageStatisticsCalculator::GetPrincipalAxis(
- const Geometry3D *geometry, Vector3D vector,
+ const BaseGeometry *geometry, Vector3D vector,
unsigned int &axis )
{
vector.Normalize();
for ( unsigned int i = 0; i < 3; ++i )
{
Vector3D axisVector = geometry->GetAxisVector( i );
axisVector.Normalize();
if ( fabs( fabs( axisVector * vector ) - 1.0) < mitk::eps )
{
axis = i;
return true;
}
}
return false;
}
template < typename TPixel, unsigned int VImageDimension >
void ImageStatisticsCalculator::InternalCalculateStatisticsUnmasked(
const itk::Image< TPixel, VImageDimension > *image,
StatisticsContainer *statisticsContainer,
HistogramContainer* histogramContainer )
{
typedef itk::Image< TPixel, VImageDimension > ImageType;
typedef itk::Image< unsigned short, VImageDimension > MaskImageType;
typedef typename ImageType::IndexType IndexType;
typedef itk::Statistics::ScalarImageToHistogramGenerator< ImageType >
HistogramGeneratorType;
statisticsContainer->clear();
histogramContainer->clear();
// Progress listening...
typedef itk::SimpleMemberCommand< ImageStatisticsCalculator > ITKCommandType;
ITKCommandType::Pointer progressListener;
progressListener = ITKCommandType::New();
progressListener->SetCallbackFunction( this,
&ImageStatisticsCalculator::UnmaskedStatisticsProgressUpdate );
// Issue 100 artificial progress events since ScalarIMageToHistogramGenerator
// does not (yet?) support progress reporting
this->InvokeEvent( itk::StartEvent() );
for ( unsigned int i = 0; i < 100; ++i )
{
this->UnmaskedStatisticsProgressUpdate();
}
// Calculate statistics (separate filter)
typedef itk::StatisticsImageFilter< ImageType > StatisticsFilterType;
typename StatisticsFilterType::Pointer statisticsFilter = StatisticsFilterType::New();
statisticsFilter->SetInput( image );
unsigned long observerTag = statisticsFilter->AddObserver( itk::ProgressEvent(), progressListener );
statisticsFilter->Update();
statisticsFilter->RemoveObserver( observerTag );
this->InvokeEvent( itk::EndEvent() );
// Calculate minimum and maximum
typedef itk::MinimumMaximumImageCalculator< ImageType > MinMaxFilterType;
typename MinMaxFilterType::Pointer minMaxFilter = MinMaxFilterType::New();
minMaxFilter->SetImage( image );
unsigned long observerTag2 = minMaxFilter->AddObserver( itk::ProgressEvent(), progressListener );
minMaxFilter->Compute();
minMaxFilter->RemoveObserver( observerTag2 );
this->InvokeEvent( itk::EndEvent() );
Statistics statistics; statistics.Reset();
statistics.Label = 1;
statistics.N = image->GetBufferedRegion().GetNumberOfPixels();
statistics.Min = statisticsFilter->GetMinimum();
statistics.Max = statisticsFilter->GetMaximum();
statistics.Mean = statisticsFilter->GetMean();
statistics.Median = 0.0;
statistics.Sigma = statisticsFilter->GetSigma();
statistics.RMS = sqrt( statistics.Mean * statistics.Mean + statistics.Sigma * statistics.Sigma );
statistics.MinIndex.set_size(image->GetImageDimension());
statistics.MaxIndex.set_size(image->GetImageDimension());
for (unsigned int i=0; i<statistics.MaxIndex.size(); i++)
{
statistics.MaxIndex[i] = minMaxFilter->GetIndexOfMaximum()[i];
statistics.MinIndex[i] = minMaxFilter->GetIndexOfMinimum()[i];
}
statisticsContainer->push_back( statistics );
// Calculate histogram
unsigned int numberOfBins = std::floor( ( (statistics.Max - statistics.Min + 1) / m_HistogramBinSize) + 0.5 );
typename HistogramGeneratorType::Pointer histogramGenerator = HistogramGeneratorType::New();
histogramGenerator->SetInput( image );
histogramGenerator->SetMarginalScale( 100 );
histogramGenerator->SetNumberOfBins( numberOfBins );
histogramGenerator->SetHistogramMin( statistics.Min );
histogramGenerator->SetHistogramMax( statistics.Max );
histogramGenerator->Compute();
histogramContainer->push_back( histogramGenerator->GetOutput() );
}
template < typename TPixel, unsigned int VImageDimension >
void ImageStatisticsCalculator::InternalMaskIgnoredPixels(
const itk::Image< TPixel, VImageDimension > *image,
itk::Image< unsigned short, VImageDimension > *maskImage )
{
typedef itk::Image< TPixel, VImageDimension > ImageType;
typedef itk::Image< unsigned short, VImageDimension > MaskImageType;
itk::ImageRegionIterator<MaskImageType>
itmask(maskImage, maskImage->GetLargestPossibleRegion());
itk::ImageRegionConstIterator<ImageType>
itimage(image, image->GetLargestPossibleRegion());
itmask.GoToBegin();
itimage.GoToBegin();
while( !itmask.IsAtEnd() )
{
if(m_IgnorePixelValue == itimage.Get())
{
itmask.Set(0);
}
++itmask;
++itimage;
}
}
template < typename TPixel, unsigned int VImageDimension >
void ImageStatisticsCalculator::InternalCalculateStatisticsMasked(
const itk::Image< TPixel, VImageDimension > *image,
itk::Image< unsigned short, VImageDimension > *maskImage,
StatisticsContainer* statisticsContainer,
HistogramContainer* histogramContainer )
{
typedef itk::Image< TPixel, VImageDimension > ImageType;
typedef itk::Image< unsigned short, VImageDimension > MaskImageType;
typedef typename ImageType::IndexType IndexType;
typedef typename ImageType::PointType PointType;
typedef typename ImageType::SpacingType SpacingType;
typedef itk::LabelStatisticsImageFilter< ImageType, MaskImageType > LabelStatisticsFilterType;
typedef itk::ChangeInformationImageFilter< MaskImageType > ChangeInformationFilterType;
typedef itk::ExtractImageFilter< ImageType, ImageType > ExtractImageFilterType;
statisticsContainer->clear();
histogramContainer->clear();
// Make sure that mask is set
if ( maskImage == NULL )
{
itkExceptionMacro( << "Mask image needs to be set!" );
}
// Make sure that spacing of mask and image are the same
SpacingType imageSpacing = image->GetSpacing();
SpacingType maskSpacing = maskImage->GetSpacing();
PointType zeroPoint; zeroPoint.Fill( 0.0 );
if ( (zeroPoint + imageSpacing).SquaredEuclideanDistanceTo( (zeroPoint + maskSpacing) ) > mitk::eps )
{
itkExceptionMacro( << "Mask needs to have same spacing as image! (Image spacing: " << imageSpacing << "; Mask spacing: " << maskSpacing << ")" );
}
// Make sure that orientation of mask and image are the same
typedef typename ImageType::DirectionType DirectionType;
DirectionType imageDirection = image->GetDirection();
DirectionType maskDirection = maskImage->GetDirection();
for( int i = 0; i < imageDirection.ColumnDimensions; ++i )
{
for( int j = 0; j < imageDirection.ColumnDimensions; ++j )
{
double differenceDirection = imageDirection[i][j] - maskDirection[i][j];
if ( fabs( differenceDirection ) > mitk::eps )
{
itkExceptionMacro( << "Mask needs to have same direction as image! (Image direction: " << imageDirection << "; Mask direction: " << maskDirection << ")" );
}
}
}
// Make sure that the voxels of mask and image are correctly "aligned", i.e., voxel boundaries are the same in both images
PointType imageOrigin = image->GetOrigin();
PointType maskOrigin = maskImage->GetOrigin();
long offset[ImageType::ImageDimension];
typedef itk::ContinuousIndex<double, VImageDimension> ContinousIndexType;
ContinousIndexType maskOriginContinousIndex, imageOriginContinousIndex;
image->TransformPhysicalPointToContinuousIndex(maskOrigin, maskOriginContinousIndex);
image->TransformPhysicalPointToContinuousIndex(imageOrigin, imageOriginContinousIndex);
for ( unsigned int i = 0; i < ImageType::ImageDimension; ++i )
{
double misalignment = maskOriginContinousIndex[i] - floor( maskOriginContinousIndex[i] + 0.5 );
if ( fabs( misalignment ) > mitk::eps )
{
itkExceptionMacro( << "Pixels/voxels of mask and image are not sufficiently aligned! (Misalignment: " << misalignment << ")" );
}
double indexCoordDistance = maskOriginContinousIndex[i] - imageOriginContinousIndex[i];
offset[i] = (int) indexCoordDistance + image->GetBufferedRegion().GetIndex()[i];
}
// Adapt the origin and region (index/size) of the mask so that the origin of both are the same
typename ChangeInformationFilterType::Pointer adaptMaskFilter;
adaptMaskFilter = ChangeInformationFilterType::New();
adaptMaskFilter->ChangeOriginOn();
adaptMaskFilter->ChangeRegionOn();
adaptMaskFilter->SetInput( maskImage );
adaptMaskFilter->SetOutputOrigin( image->GetOrigin() );
adaptMaskFilter->SetOutputOffset( offset );
adaptMaskFilter->Update();
typename MaskImageType::Pointer adaptedMaskImage = adaptMaskFilter->GetOutput();
// Make sure that mask region is contained within image region
if ( !image->GetLargestPossibleRegion().IsInside( adaptedMaskImage->GetLargestPossibleRegion() ) )
{
itkExceptionMacro( << "Mask region needs to be inside of image region! (Image region: "
<< image->GetLargestPossibleRegion() << "; Mask region: " << adaptedMaskImage->GetLargestPossibleRegion() << ")" );
}
// If mask region is smaller than image region, extract the sub-sampled region from the original image
typename ImageType::SizeType imageSize = image->GetBufferedRegion().GetSize();
typename ImageType::SizeType maskSize = maskImage->GetBufferedRegion().GetSize();
bool maskSmallerImage = false;
for ( unsigned int i = 0; i < ImageType::ImageDimension; ++i )
{
if ( maskSize[i] < imageSize[i] )
{
maskSmallerImage = true;
}
}
typename ImageType::ConstPointer adaptedImage;
if ( maskSmallerImage )
{
typename ExtractImageFilterType::Pointer extractImageFilter = ExtractImageFilterType::New();
extractImageFilter->SetInput( image );
extractImageFilter->SetExtractionRegion( adaptedMaskImage->GetBufferedRegion() );
extractImageFilter->Update();
adaptedImage = extractImageFilter->GetOutput();
}
else
{
adaptedImage = image;
}
// Initialize Filter
typedef itk::StatisticsImageFilter< ImageType > StatisticsFilterType;
typename StatisticsFilterType::Pointer statisticsFilter = StatisticsFilterType::New();
statisticsFilter->SetInput( adaptedImage );
statisticsFilter->Update();
int numberOfBins = std::floor( ( (statisticsFilter->GetMaximum() - statisticsFilter->GetMinimum() + 1) / m_HistogramBinSize) + 0.5 );
typename LabelStatisticsFilterType::Pointer labelStatisticsFilter;
labelStatisticsFilter = LabelStatisticsFilterType::New();
labelStatisticsFilter->SetInput( adaptedImage );
labelStatisticsFilter->SetLabelInput( adaptedMaskImage );
labelStatisticsFilter->UseHistogramsOn();
labelStatisticsFilter->SetHistogramParameters( numberOfBins, statisticsFilter->GetMinimum(), statisticsFilter->GetMaximum() );
// Add progress listening
typedef itk::SimpleMemberCommand< ImageStatisticsCalculator > ITKCommandType;
ITKCommandType::Pointer progressListener;
progressListener = ITKCommandType::New();
progressListener->SetCallbackFunction( this,
&ImageStatisticsCalculator::MaskedStatisticsProgressUpdate );
unsigned long observerTag = labelStatisticsFilter->AddObserver(
itk::ProgressEvent(), progressListener );
// Execute filter
this->InvokeEvent( itk::StartEvent() );
// Make sure that only the mask region is considered (otherwise, if the mask region is smaller
// than the image region, the Update() would result in an exception).
labelStatisticsFilter->GetOutput()->SetRequestedRegion( adaptedMaskImage->GetLargestPossibleRegion() );
// Execute the filter
labelStatisticsFilter->Update();
this->InvokeEvent( itk::EndEvent() );
labelStatisticsFilter->RemoveObserver( observerTag );
// Find all relevant labels of mask (other than 0)
std::list< int > relevantLabels;
bool maskNonEmpty = false;
unsigned int i;
for ( i = 1; i < 4096; ++i )
{
if ( labelStatisticsFilter->HasLabel( i ) )
{
relevantLabels.push_back( i );
maskNonEmpty = true;
}
}
if ( maskNonEmpty )
{
std::list< int >::iterator it;
for ( it = relevantLabels.begin(), i = 0;
it != relevantLabels.end();
++it, ++i )
{
histogramContainer->push_back( HistogramType::ConstPointer( labelStatisticsFilter->GetHistogram( (*it) ) ) );
Statistics statistics;
statistics.Label = (*it);
statistics.N = labelStatisticsFilter->GetCount( *it );
statistics.Min = labelStatisticsFilter->GetMinimum( *it );
statistics.Max = labelStatisticsFilter->GetMaximum( *it );
statistics.Mean = labelStatisticsFilter->GetMean( *it );
statistics.Median = labelStatisticsFilter->GetMedian( *it );
statistics.Sigma = labelStatisticsFilter->GetSigma( *it );
statistics.RMS = sqrt( statistics.Mean * statistics.Mean
+ statistics.Sigma * statistics.Sigma );
// restrict image to mask area for min/max index calculation
typedef itk::MaskImageFilter< ImageType, MaskImageType, ImageType > MaskImageFilterType;
typename MaskImageFilterType::Pointer masker = MaskImageFilterType::New();
masker->SetOutsideValue( (statistics.Min+statistics.Max)/2 );
masker->SetInput1(adaptedImage);
masker->SetInput2(adaptedMaskImage);
masker->Update();
// get index of minimum and maximum
typedef itk::MinimumMaximumImageCalculator< ImageType > MinMaxFilterType;
typename MinMaxFilterType::Pointer minMaxFilter = MinMaxFilterType::New();
minMaxFilter->SetImage( masker->GetOutput() );
unsigned long observerTag2 = minMaxFilter->AddObserver( itk::ProgressEvent(), progressListener );
minMaxFilter->Compute();
minMaxFilter->RemoveObserver( observerTag2 );
this->InvokeEvent( itk::EndEvent() );
statistics.MinIndex.set_size(adaptedImage->GetImageDimension());
statistics.MaxIndex.set_size(adaptedImage->GetImageDimension());
typename MinMaxFilterType::IndexType tempMaxIndex = minMaxFilter->GetIndexOfMaximum();
typename MinMaxFilterType::IndexType tempMinIndex = minMaxFilter->GetIndexOfMinimum();
// FIX BUG 14644
//If a PlanarFigure is used for segmentation the
//adaptedImage is a single slice (2D). Adding the
// 3. dimension.
if (m_MaskingMode == MASKING_MODE_PLANARFIGURE && m_Image->GetDimension()==3)
{
statistics.MaxIndex.set_size(m_Image->GetDimension());
statistics.MaxIndex[m_PlanarFigureCoordinate0]=tempMaxIndex[0];
statistics.MaxIndex[m_PlanarFigureCoordinate1]=tempMaxIndex[1];
statistics.MaxIndex[m_PlanarFigureAxis]=m_PlanarFigureSlice;
statistics.MinIndex.set_size(m_Image->GetDimension());
statistics.MinIndex[m_PlanarFigureCoordinate0]=tempMinIndex[0];
statistics.MinIndex[m_PlanarFigureCoordinate1]=tempMinIndex[1];
statistics.MinIndex[m_PlanarFigureAxis]=m_PlanarFigureSlice;
} else
{
for (unsigned int i = 0; i<statistics.MaxIndex.size(); i++)
{
statistics.MaxIndex[i] = tempMaxIndex[i];
statistics.MinIndex[i] = tempMinIndex[i];
}
}
// FIX END
statisticsContainer->push_back( statistics );
}
}
else
{
histogramContainer->push_back( HistogramType::ConstPointer( m_EmptyHistogram ) );
statisticsContainer->push_back( Statistics() );
}
}
template < typename TPixel, unsigned int VImageDimension >
void ImageStatisticsCalculator::InternalCalculateMaskFromPlanarFigure(
const itk::Image< TPixel, VImageDimension > *image, unsigned int axis )
{
typedef itk::Image< TPixel, VImageDimension > ImageType;
typedef itk::CastImageFilter< ImageType, MaskImage2DType > CastFilterType;
// Generate mask image as new image with same header as input image and
// initialize with "1".
typename CastFilterType::Pointer castFilter = CastFilterType::New();
castFilter->SetInput( image );
castFilter->Update();
castFilter->GetOutput()->FillBuffer( 1 );
// all PolylinePoints of the PlanarFigure are stored in a vtkPoints object.
// These points are used by the vtkLassoStencilSource to create
// a vtkImageStencil.
- const mitk::Geometry2D *planarFigureGeometry2D = m_PlanarFigure->GetGeometry2D();
+ const mitk::PlaneGeometry *planarFigurePlaneGeometry = m_PlanarFigure->GetPlaneGeometry();
const typename PlanarFigure::PolyLineType planarFigurePolyline = m_PlanarFigure->GetPolyLine( 0 );
-
+ const mitk::BaseGeometry *imageGeometry3D = m_Image->GetGeometry( 0 );
// If there is a second poly line in a closed planar figure, treat it as a hole.
PlanarFigure::PolyLineType planarFigureHolePolyline;
if (m_PlanarFigure->GetPolyLinesSize() == 2)
planarFigureHolePolyline = m_PlanarFigure->GetPolyLine(1);
- const mitk::Geometry3D *imageGeometry3D = m_Image->GetGeometry( 0 );
// Determine x- and y-dimensions depending on principal axis
int i0, i1;
switch ( axis )
{
case 0:
i0 = 1;
i1 = 2;
break;
case 1:
i0 = 0;
i1 = 2;
break;
case 2:
default:
i0 = 0;
i1 = 1;
break;
}
m_PlanarFigureCoordinate0= i0;
m_PlanarFigureCoordinate1= i1;
// store the polyline contour as vtkPoints object
bool outOfBounds = false;
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
typename PlanarFigure::PolyLineType::const_iterator it;
for ( it = planarFigurePolyline.begin();
it != planarFigurePolyline.end();
++it )
{
Point3D point3D;
// Convert 2D point back to the local index coordinates of the selected
// image
- planarFigureGeometry2D->Map( *it, point3D );
+ planarFigurePlaneGeometry->Map( *it, point3D );
// Polygons (partially) outside of the image bounds can not be processed
// further due to a bug in vtkPolyDataToImageStencil
if ( !imageGeometry3D->IsInside( point3D ) )
{
outOfBounds = true;
}
imageGeometry3D->WorldToIndex( point3D, point3D );
points->InsertNextPoint( point3D[i0], point3D[i1], 0 );
}
vtkSmartPointer<vtkPoints> holePoints = NULL;
if (!planarFigureHolePolyline.empty())
{
holePoints = vtkSmartPointer<vtkPoints>::New();
Point3D point3D;
PlanarFigure::PolyLineType::const_iterator end = planarFigureHolePolyline.end();
for (it = planarFigureHolePolyline.begin(); it != end; ++it)
{
- planarFigureGeometry2D->Map(*it, point3D);
+ planarFigurePlaneGeometry->Map(*it, point3D);
imageGeometry3D->WorldToIndex(point3D, point3D);
holePoints->InsertNextPoint(point3D[i0], point3D[i1], 0);
}
}
// mark a malformed 2D planar figure ( i.e. area = 0 ) as out of bounds
// this can happen when all control points of a rectangle lie on the same line = two of the three extents are zero
double bounds[6] = {0, 0, 0, 0, 0, 0};
points->GetBounds( bounds );
bool extent_x = (fabs(bounds[0] - bounds[1])) < mitk::eps;
bool extent_y = (fabs(bounds[2] - bounds[3])) < mitk::eps;
bool extent_z = (fabs(bounds[4] - bounds[5])) < mitk::eps;
// throw an exception if a closed planar figure is deformed, i.e. has only one non-zero extent
if ( m_PlanarFigure->IsClosed() &&
((extent_x && extent_y) || (extent_x && extent_z) || (extent_y && extent_z)))
{
mitkThrow() << "Figure has a zero area and cannot be used for masking.";
}
if ( outOfBounds )
{
throw std::runtime_error( "Figure at least partially outside of image bounds!" );
}
// create a vtkLassoStencilSource and set the points of the Polygon
vtkSmartPointer<vtkLassoStencilSource> lassoStencil = vtkSmartPointer<vtkLassoStencilSource>::New();
lassoStencil->SetShapeToPolygon();
lassoStencil->SetPoints( points );
vtkSmartPointer<vtkLassoStencilSource> holeLassoStencil = NULL;
if (holePoints.GetPointer() != NULL)
{
holeLassoStencil = vtkSmartPointer<vtkLassoStencilSource>::New();
holeLassoStencil->SetShapeToPolygon();
holeLassoStencil->SetPoints(holePoints);
}
// Export from ITK to VTK (to use a VTK filter)
typedef itk::VTKImageImport< MaskImage2DType > ImageImportType;
typedef itk::VTKImageExport< MaskImage2DType > ImageExportType;
typename ImageExportType::Pointer itkExporter = ImageExportType::New();
itkExporter->SetInput( castFilter->GetOutput() );
vtkSmartPointer<vtkImageImport> vtkImporter = vtkSmartPointer<vtkImageImport>::New();
this->ConnectPipelines( itkExporter, vtkImporter );
// Apply the generated image stencil to the input image
vtkSmartPointer<vtkImageStencil> imageStencilFilter = vtkSmartPointer<vtkImageStencil>::New();
imageStencilFilter->SetInputConnection( vtkImporter->GetOutputPort() );
imageStencilFilter->SetStencilConnection(lassoStencil->GetOutputPort());
imageStencilFilter->ReverseStencilOff();
imageStencilFilter->SetBackgroundValue( 0 );
imageStencilFilter->Update();
vtkSmartPointer<vtkImageStencil> holeStencilFilter = NULL;
if (holeLassoStencil.GetPointer() != NULL)
{
holeStencilFilter = vtkSmartPointer<vtkImageStencil>::New();
holeStencilFilter->SetInputConnection(imageStencilFilter->GetOutputPort());
holeStencilFilter->SetStencilConnection(holeLassoStencil->GetOutputPort());
holeStencilFilter->ReverseStencilOn();
holeStencilFilter->SetBackgroundValue(0);
holeStencilFilter->Update();
}
// Export from VTK back to ITK
vtkSmartPointer<vtkImageExport> vtkExporter = vtkSmartPointer<vtkImageExport>::New();
vtkExporter->SetInputConnection( holeStencilFilter.GetPointer() == NULL
? imageStencilFilter->GetOutputPort()
: holeStencilFilter->GetOutputPort());
vtkExporter->Update();
typename ImageImportType::Pointer itkImporter = ImageImportType::New();
this->ConnectPipelines( vtkExporter, itkImporter );
itkImporter->Update();
typedef itk::ImageDuplicator< ImageImportType::OutputImageType > DuplicatorType;
DuplicatorType::Pointer duplicator = DuplicatorType::New();
duplicator->SetInputImage( itkImporter->GetOutput() );
duplicator->Update();
// Store mask
m_InternalImageMask2D = duplicator->GetOutput();
}
void ImageStatisticsCalculator::UnmaskedStatisticsProgressUpdate()
{
// Need to throw away every second progress event to reach a final count of
// 100 since two consecutive filters are used in this case
static int updateCounter = 0;
if ( updateCounter++ % 2 == 0 )
{
this->InvokeEvent( itk::ProgressEvent() );
}
}
void ImageStatisticsCalculator::MaskedStatisticsProgressUpdate()
{
this->InvokeEvent( itk::ProgressEvent() );
}
}
diff --git a/Modules/ImageStatistics/mitkImageStatisticsCalculator.h b/Modules/ImageStatistics/mitkImageStatisticsCalculator.h
index 741c03d3fa..eb15be01ce 100644
--- a/Modules/ImageStatistics/mitkImageStatisticsCalculator.h
+++ b/Modules/ImageStatistics/mitkImageStatisticsCalculator.h
@@ -1,342 +1,342 @@
/*===================================================================
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 _MITK_IMAGESTATISTICSCALCULATOR_H
#define _MITK_IMAGESTATISTICSCALCULATOR_H
#include <itkObject.h>
#include "MitkImageStatisticsExports.h"
#include <itkImage.h>
#include <itkTimeStamp.h>
#ifndef __itkHistogram_h
#include <itkHistogram.h>
#endif
#include "mitkImage.h"
#include "mitkImageTimeSelector.h"
#include "mitkPlanarFigure.h"
#include <vtkSmartPointer.h>
namespace mitk
{
/**
* \brief Class for calculating statistics and histogram for an (optionally
* masked) image.
*
* Images can be masked by either a label image (of the same dimensions as
* the original image) or by a closed mitk::PlanarFigure, e.g. a circle or
* polygon. When masking with a planar figure, the slice corresponding to the
* plane containing the figure is extracted and then clipped with contour
* defined by the figure. Planar figures need to be aligned along the main axes
* of the image (axial, sagittal, coronal). Planar figures on arbitrary
* rotated planes are not supported.
*
* For each operating mode (no masking, masking by image, masking by planar
* figure), the calculated statistics and histogram are cached so that, when
* switching back and forth between operation modes without modifying mask or
* image, the information doesn't need to be recalculated.
*
* Note: currently time-resolved and multi-channel pictures are not properly
* supported.
*/
class MitkImageStatistics_EXPORT ImageStatisticsCalculator : public itk::Object
{
public:
enum
{
MASKING_MODE_NONE = 0,
MASKING_MODE_IMAGE,
MASKING_MODE_PLANARFIGURE
};
typedef itk::Statistics::Histogram<double> HistogramType;
typedef HistogramType::ConstIterator HistogramConstIteratorType;
struct Statistics
{
Statistics()
{
Reset();
}
int Label;
unsigned int N;
double Min;
double Max;
double Mean;
double Median;
double Variance;
double Sigma;
double RMS;
vnl_vector< int > MinIndex;
vnl_vector< int > MaxIndex;
void Reset()
{
Label = 0;
N = 0;
Min = 0.0;
Max = 0.0;
Mean = 0.0;
Median = 0.0;
Variance = 0.0;
Sigma = 0.0;
RMS = 0.0;
}
};
typedef std::vector< HistogramType::ConstPointer > HistogramContainer;
typedef std::vector< Statistics > StatisticsContainer;
mitkClassMacro( ImageStatisticsCalculator, itk::Object );
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** \brief Set image from which to compute statistics. */
void SetImage( const mitk::Image *image );
/** \brief Set image for masking. */
void SetImageMask( const mitk::Image *imageMask );
/** \brief Set planar figure for masking. */
void SetPlanarFigure( mitk::PlanarFigure *planarFigure );
/** \brief Set/Get operation mode for masking */
void SetMaskingMode( unsigned int mode );
/** \brief Set/Get operation mode for masking */
itkGetMacro( MaskingMode, unsigned int );
/** \brief Set/Get operation mode for masking */
void SetMaskingModeToNone();
/** \brief Set/Get operation mode for masking */
void SetMaskingModeToImage();
/** \brief Set/Get operation mode for masking */
void SetMaskingModeToPlanarFigure();
/** \brief Set a pixel value for pixels that will be ignored in the statistics */
void SetIgnorePixelValue(double value);
/** \brief Get the pixel value for pixels that will be ignored in the statistics */
double GetIgnorePixelValue();
/** \brief Set wether a pixel value should be ignored in the statistics */
void SetDoIgnorePixelValue(bool doit);
/** \brief Get wether a pixel value will be ignored in the statistics */
bool GetDoIgnorePixelValue();
/** \brief Set bin size for histogram resolution.*/
void SetHistogramBinSize( unsigned int size);
/** \brief Get bin size for histogram resolution.*/
unsigned int GetHistogramBinSize();
/** \brief Compute statistics (together with histogram) for the current
* masking mode.
*
* Computation is not executed if statistics is already up to date. In this
* case, false is returned; otherwise, true.*/
virtual bool ComputeStatistics( unsigned int timeStep = 0 );
/** \brief Retrieve the histogram depending on the current masking mode.
*
* \param label The label for which to retrieve the histogram in multi-label situations (ascending order).
*/
const HistogramType *GetHistogram( unsigned int timeStep = 0, unsigned int label = 0 ) const;
/** \brief Retrieve the histogram depending on the current masking mode (for all image labels. */
const HistogramContainer &GetHistogramVector( unsigned int timeStep = 0 ) const;
/** \brief Retrieve statistics depending on the current masking mode.
*
* \param label The label for which to retrieve the statistics in multi-label situations (ascending order).
*/
const Statistics &GetStatistics( unsigned int timeStep = 0, unsigned int label = 0 ) const;
/** \brief Retrieve statistics depending on the current masking mode (for all image labels). */
const StatisticsContainer &GetStatisticsVector( unsigned int timeStep = 0 ) const;
protected:
typedef std::vector< HistogramContainer > HistogramVector;
typedef std::vector< StatisticsContainer > StatisticsVector;
typedef std::vector< itk::TimeStamp > TimeStampVectorType;
typedef std::vector< bool > BoolVectorType;
typedef itk::Image< unsigned short, 3 > MaskImage3DType;
typedef itk::Image< unsigned short, 2 > MaskImage2DType;
ImageStatisticsCalculator();
virtual ~ImageStatisticsCalculator();
/** \brief Depending on the masking mode, the image and mask from which to
* calculate statistics is extracted from the original input image and mask
* data.
*
* For example, a when using a PlanarFigure as mask, the 2D image slice
* corresponding to the PlanarFigure will be extracted from the original
* image. If masking is disabled, the original image is simply passed
* through. */
void ExtractImageAndMask( unsigned int timeStep = 0 );
/** \brief If the passed vector matches any of the three principal axes
* of the passed geometry, the ínteger value corresponding to the axis
* is set and true is returned. */
- bool GetPrincipalAxis( const Geometry3D *geometry, Vector3D vector,
+ bool GetPrincipalAxis( const BaseGeometry *geometry, Vector3D vector,
unsigned int &axis );
template < typename TPixel, unsigned int VImageDimension >
void InternalCalculateStatisticsUnmasked(
const itk::Image< TPixel, VImageDimension > *image,
StatisticsContainer* statisticsContainer,
HistogramContainer *histogramContainer );
template < typename TPixel, unsigned int VImageDimension >
void InternalCalculateStatisticsMasked(
const itk::Image< TPixel, VImageDimension > *image,
itk::Image< unsigned short, VImageDimension > *maskImage,
StatisticsContainer* statisticsContainer,
HistogramContainer* histogramContainer );
template < typename TPixel, unsigned int VImageDimension >
void InternalCalculateMaskFromPlanarFigure(
const itk::Image< TPixel, VImageDimension > *image, unsigned int axis );
template < typename TPixel, unsigned int VImageDimension >
void InternalMaskIgnoredPixels(
const itk::Image< TPixel, VImageDimension > *image,
itk::Image< unsigned short, VImageDimension > *maskImage );
/** Connection from ITK to VTK */
template <typename ITK_Exporter, typename VTK_Importer>
void ConnectPipelines(ITK_Exporter exporter, vtkSmartPointer<VTK_Importer> importer)
{
importer->SetUpdateInformationCallback(exporter->GetUpdateInformationCallback());
importer->SetPipelineModifiedCallback(exporter->GetPipelineModifiedCallback());
importer->SetWholeExtentCallback(exporter->GetWholeExtentCallback());
importer->SetSpacingCallback(exporter->GetSpacingCallback());
importer->SetOriginCallback(exporter->GetOriginCallback());
importer->SetScalarTypeCallback(exporter->GetScalarTypeCallback());
importer->SetNumberOfComponentsCallback(exporter->GetNumberOfComponentsCallback());
importer->SetPropagateUpdateExtentCallback(exporter->GetPropagateUpdateExtentCallback());
importer->SetUpdateDataCallback(exporter->GetUpdateDataCallback());
importer->SetDataExtentCallback(exporter->GetDataExtentCallback());
importer->SetBufferPointerCallback(exporter->GetBufferPointerCallback());
importer->SetCallbackUserData(exporter->GetCallbackUserData());
}
/** Connection from VTK to ITK */
template <typename VTK_Exporter, typename ITK_Importer>
void ConnectPipelines(vtkSmartPointer<VTK_Exporter> exporter, ITK_Importer importer)
{
importer->SetUpdateInformationCallback(exporter->GetUpdateInformationCallback());
importer->SetPipelineModifiedCallback(exporter->GetPipelineModifiedCallback());
importer->SetWholeExtentCallback(exporter->GetWholeExtentCallback());
importer->SetSpacingCallback(exporter->GetSpacingCallback());
importer->SetOriginCallback(exporter->GetOriginCallback());
importer->SetScalarTypeCallback(exporter->GetScalarTypeCallback());
importer->SetNumberOfComponentsCallback(exporter->GetNumberOfComponentsCallback());
importer->SetPropagateUpdateExtentCallback(exporter->GetPropagateUpdateExtentCallback());
importer->SetUpdateDataCallback(exporter->GetUpdateDataCallback());
importer->SetDataExtentCallback(exporter->GetDataExtentCallback());
importer->SetBufferPointerCallback(exporter->GetBufferPointerCallback());
importer->SetCallbackUserData(exporter->GetCallbackUserData());
}
void UnmaskedStatisticsProgressUpdate();
void MaskedStatisticsProgressUpdate();
/** m_Image contains the input image (e.g. 2D, 3D, 3D+t)*/
mitk::Image::ConstPointer m_Image;
mitk::Image::ConstPointer m_ImageMask;
mitk::PlanarFigure::Pointer m_PlanarFigure;
HistogramVector m_ImageHistogramVector;
HistogramVector m_MaskedImageHistogramVector;
HistogramVector m_PlanarFigureHistogramVector;
HistogramType::Pointer m_EmptyHistogram;
HistogramContainer m_EmptyHistogramContainer;
StatisticsVector m_ImageStatisticsVector;
StatisticsVector m_MaskedImageStatisticsVector;
StatisticsVector m_PlanarFigureStatisticsVector;
Statistics m_EmptyStatistics;
StatisticsContainer m_EmptyStatisticsContainer;
unsigned int m_MaskingMode;
bool m_MaskingModeChanged;
/** m_InternalImage contains a image volume at one time step (e.g. 2D, 3D)*/
mitk::Image::ConstPointer m_InternalImage;
MaskImage3DType::Pointer m_InternalImageMask3D;
MaskImage2DType::Pointer m_InternalImageMask2D;
TimeStampVectorType m_ImageStatisticsTimeStampVector;
TimeStampVectorType m_MaskedImageStatisticsTimeStampVector;
TimeStampVectorType m_PlanarFigureStatisticsTimeStampVector;
BoolVectorType m_ImageStatisticsCalculationTriggerVector;
BoolVectorType m_MaskedImageStatisticsCalculationTriggerVector;
BoolVectorType m_PlanarFigureStatisticsCalculationTriggerVector;
double m_IgnorePixelValue;
bool m_DoIgnorePixelValue;
bool m_IgnorePixelValueChanged;
unsigned int m_PlanarFigureAxis; // Normal axis for PlanarFigure
unsigned int m_PlanarFigureSlice; // Slice which contains PlanarFigure
int m_PlanarFigureCoordinate0; // First plane-axis for PlanarFigure
int m_PlanarFigureCoordinate1; // Second plane-axis for PlanarFigure
unsigned int m_HistogramBinSize; ///Bin size for histogram resoluion.
};
}
#endif // #define _MITK_IMAGESTATISTICSCALCULATOR_H
diff --git a/Modules/ImageStatistics/mitkIntensityProfile.cpp b/Modules/ImageStatistics/mitkIntensityProfile.cpp
index b5fa201dda..74090ec057 100644
--- a/Modules/ImageStatistics/mitkIntensityProfile.cpp
+++ b/Modules/ImageStatistics/mitkIntensityProfile.cpp
@@ -1,337 +1,337 @@
/*===================================================================
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 <itkLinearInterpolateImageFunction.h>
#include <itkNearestNeighborInterpolateImageFunction.h>
#include <itkPolyLineParametricPath.h>
#include <itkWindowedSincInterpolateImageFunction.h>
#include <mitkImageAccessByItk.h>
#include <mitkImagePixelReadAccessor.h>
#include <mitkPixelTypeMultiplex.h>
#include "mitkIntensityProfile.h"
using namespace mitk;
template <class T>
static void ReadPixel(const PixelType&, Image::Pointer image, const Index3D& index, ScalarType* returnValue)
{
switch (image->GetDimension())
{
case 2:
{
ImagePixelReadAccessor<T, 2> readAccess(image, image->GetSliceData(0));
*returnValue = readAccess.GetPixelByIndex(reinterpret_cast<const itk::Index<2>&>(index));
break;
}
case 3:
{
ImagePixelReadAccessor<T, 3> readAccess(image, image->GetVolumeData(0));
*returnValue = readAccess.GetPixelByIndex(index);
break;
}
default:
*returnValue = 0;
break;
}
}
static IntensityProfile::Pointer ComputeIntensityProfile(Image::Pointer image, itk::PolyLineParametricPath<3>::Pointer path)
{
IntensityProfile::Pointer intensityProfile = IntensityProfile::New();
itk::PolyLineParametricPath<3>::InputType input = path->StartOfInput();
- Geometry3D* imageGeometry = image->GetGeometry();
+ BaseGeometry* imageGeometry = image->GetGeometry();
const PixelType pixelType = image->GetPixelType();
IntensityProfile::MeasurementVectorType measurementVector;
itk::PolyLineParametricPath<3>::OffsetType offset;
Point3D worldPoint;
Index3D index;
do
{
imageGeometry->IndexToWorld(path->Evaluate(input), worldPoint);
imageGeometry->WorldToIndex(worldPoint, index);
mitkPixelTypeMultiplex3(ReadPixel, pixelType, image, index, measurementVector.GetDataPointer());
intensityProfile->PushBack(measurementVector);
offset = path->IncrementInput(input);
} while ((offset[0] | offset[1] | offset[2]) != 0);
return intensityProfile;
}
template <class TInputImage>
static typename itk::InterpolateImageFunction<TInputImage>::Pointer CreateInterpolateImageFunction(InterpolateImageFunction::Enum interpolator)
{
switch (interpolator)
{
case InterpolateImageFunction::NearestNeighbor:
return itk::NearestNeighborInterpolateImageFunction<TInputImage>::New().GetPointer();
case InterpolateImageFunction::Linear:
return itk::LinearInterpolateImageFunction<TInputImage>::New().GetPointer();
case InterpolateImageFunction::WindowedSinc_Blackman_3:
return itk::WindowedSincInterpolateImageFunction<TInputImage, 3, itk::Function::BlackmanWindowFunction<3> >::New().GetPointer();
case InterpolateImageFunction::WindowedSinc_Blackman_4:
return itk::WindowedSincInterpolateImageFunction<TInputImage, 4, itk::Function::BlackmanWindowFunction<4> >::New().GetPointer();
case InterpolateImageFunction::WindowedSinc_Blackman_5:
return itk::WindowedSincInterpolateImageFunction<TInputImage, 5, itk::Function::BlackmanWindowFunction<5> >::New().GetPointer();
case InterpolateImageFunction::WindowedSinc_Cosine_3:
return itk::WindowedSincInterpolateImageFunction<TInputImage, 3, itk::Function::CosineWindowFunction<3> >::New().GetPointer();
case InterpolateImageFunction::WindowedSinc_Cosine_4:
return itk::WindowedSincInterpolateImageFunction<TInputImage, 4, itk::Function::CosineWindowFunction<4> >::New().GetPointer();
case InterpolateImageFunction::WindowedSinc_Cosine_5:
return itk::WindowedSincInterpolateImageFunction<TInputImage, 5, itk::Function::CosineWindowFunction<5> >::New().GetPointer();
case InterpolateImageFunction::WindowedSinc_Hamming_3:
return itk::WindowedSincInterpolateImageFunction<TInputImage, 3, itk::Function::HammingWindowFunction<3> >::New().GetPointer();
case InterpolateImageFunction::WindowedSinc_Hamming_4:
return itk::WindowedSincInterpolateImageFunction<TInputImage, 4, itk::Function::HammingWindowFunction<4> >::New().GetPointer();
case InterpolateImageFunction::WindowedSinc_Hamming_5:
return itk::WindowedSincInterpolateImageFunction<TInputImage, 5, itk::Function::HammingWindowFunction<5> >::New().GetPointer();
case InterpolateImageFunction::WindowedSinc_Lanczos_3:
return itk::WindowedSincInterpolateImageFunction<TInputImage, 3, itk::Function::LanczosWindowFunction<3> >::New().GetPointer();
case InterpolateImageFunction::WindowedSinc_Lanczos_4:
return itk::WindowedSincInterpolateImageFunction<TInputImage, 4, itk::Function::LanczosWindowFunction<4> >::New().GetPointer();
case InterpolateImageFunction::WindowedSinc_Lanczos_5:
return itk::WindowedSincInterpolateImageFunction<TInputImage, 5, itk::Function::LanczosWindowFunction<5> >::New().GetPointer();
case InterpolateImageFunction::WindowedSinc_Welch_3:
return itk::WindowedSincInterpolateImageFunction<TInputImage, 3, itk::Function::WelchWindowFunction<3> >::New().GetPointer();
case InterpolateImageFunction::WindowedSinc_Welch_4:
return itk::WindowedSincInterpolateImageFunction<TInputImage, 4, itk::Function::WelchWindowFunction<4> >::New().GetPointer();
case InterpolateImageFunction::WindowedSinc_Welch_5:
return itk::WindowedSincInterpolateImageFunction<TInputImage, 5, itk::Function::WelchWindowFunction<5> >::New().GetPointer();
default:
return itk::NearestNeighborInterpolateImageFunction<TInputImage>::New().GetPointer();
}
}
template <class TPixel, unsigned int VImageDimension>
static void ComputeIntensityProfile(itk::Image<TPixel, VImageDimension>* image, itk::PolyLineParametricPath<3>::Pointer path, unsigned int numSamples, InterpolateImageFunction::Enum interpolator, IntensityProfile::Pointer intensityProfile)
{
typename itk::InterpolateImageFunction<itk::Image<TPixel, VImageDimension> >::Pointer interpolateImageFunction = CreateInterpolateImageFunction<itk::Image<TPixel, VImageDimension> >(interpolator);
interpolateImageFunction->SetInputImage(image);
const itk::PolyLineParametricPath<3>::InputType startOfInput = path->StartOfInput();
const itk::PolyLineParametricPath<3>::InputType delta = 1.0 / (numSamples - 1);
IntensityProfile::MeasurementVectorType measurementVector;
for (unsigned int i = 0; i < numSamples; ++i)
{
measurementVector[0] = interpolateImageFunction->EvaluateAtContinuousIndex(path->Evaluate(startOfInput + i * delta));
intensityProfile->PushBack(measurementVector);
}
}
static IntensityProfile::Pointer ComputeIntensityProfile(Image::Pointer image, itk::PolyLineParametricPath<3>::Pointer path, unsigned int numSamples, InterpolateImageFunction::Enum interpolator)
{
IntensityProfile::Pointer intensityProfile = IntensityProfile::New();
AccessFixedDimensionByItk_n(image, ComputeIntensityProfile, 3, (path, numSamples, interpolator, intensityProfile));
return intensityProfile;
}
class AddPolyLineElementToPath
{
public:
- AddPolyLineElementToPath(const Geometry2D* planarFigureGeometry, const Geometry3D* imageGeometry, itk::PolyLineParametricPath<3>::Pointer path)
+ AddPolyLineElementToPath(const PlaneGeometry* planarFigureGeometry, const BaseGeometry* imageGeometry, itk::PolyLineParametricPath<3>::Pointer path)
: m_PlanarFigureGeometry(planarFigureGeometry),
m_ImageGeometry(imageGeometry),
m_Path(path)
{
}
void operator()(const PlanarFigure::PolyLineElement& polyLineElement)
{
m_PlanarFigureGeometry->Map(polyLineElement, m_WorldPoint);
m_ImageGeometry->WorldToIndex(m_WorldPoint, m_ContinuousIndexPoint);
m_Vertex.CastFrom(m_ContinuousIndexPoint);
m_Path->AddVertex(m_Vertex);
}
private:
- const Geometry2D* m_PlanarFigureGeometry;
- const Geometry3D* m_ImageGeometry;
+ const PlaneGeometry* m_PlanarFigureGeometry;
+ const BaseGeometry* m_ImageGeometry;
itk::PolyLineParametricPath<3>::Pointer m_Path;
Point3D m_WorldPoint;
Point3D m_ContinuousIndexPoint;
itk::PolyLineParametricPath<3>::ContinuousIndexType m_Vertex;
};
-static itk::PolyLineParametricPath<3>::Pointer CreatePathFromPlanarFigure(Geometry3D* imageGeometry, PlanarFigure* planarFigure)
+static itk::PolyLineParametricPath<3>::Pointer CreatePathFromPlanarFigure(BaseGeometry* imageGeometry, PlanarFigure* planarFigure)
{
itk::PolyLineParametricPath<3>::Pointer path = itk::PolyLineParametricPath<3>::New();
const PlanarFigure::PolyLineType polyLine = planarFigure->GetPolyLine(0);
std::for_each(polyLine.begin(), polyLine.end(),
- AddPolyLineElementToPath(planarFigure->GetGeometry2D(), imageGeometry, path));
+ AddPolyLineElementToPath(planarFigure->GetPlaneGeometry(), imageGeometry, path));
return path;
}
-static void AddPointToPath(const Geometry3D* imageGeometry, const Point3D& point, itk::PolyLineParametricPath<3>::Pointer path)
+static void AddPointToPath(const BaseGeometry* imageGeometry, const Point3D& point, itk::PolyLineParametricPath<3>::Pointer path)
{
Point3D continuousIndexPoint;
imageGeometry->WorldToIndex(point, continuousIndexPoint);
itk::PolyLineParametricPath<3>::ContinuousIndexType vertex;
vertex.CastFrom(continuousIndexPoint);
path->AddVertex(vertex);
}
-static itk::PolyLineParametricPath<3>::Pointer CreatePathFromPoints(Geometry3D* imageGeometry, const Point3D& startPoint, const Point3D& endPoint)
+static itk::PolyLineParametricPath<3>::Pointer CreatePathFromPoints(BaseGeometry* imageGeometry, const Point3D& startPoint, const Point3D& endPoint)
{
itk::PolyLineParametricPath<3>::Pointer path = itk::PolyLineParametricPath<3>::New();
AddPointToPath(imageGeometry, startPoint, path);
AddPointToPath(imageGeometry, endPoint, path);
return path;
}
IntensityProfile::Pointer mitk::ComputeIntensityProfile(Image::Pointer image, PlanarFigure::Pointer planarFigure)
{
return ::ComputeIntensityProfile(image, CreatePathFromPlanarFigure(image->GetGeometry(), planarFigure));
}
IntensityProfile::Pointer mitk::ComputeIntensityProfile(Image::Pointer image, PlanarLine::Pointer planarLine, unsigned int numSamples, InterpolateImageFunction::Enum interpolator)
{
return ::ComputeIntensityProfile(image, CreatePathFromPlanarFigure(image->GetGeometry(), planarLine.GetPointer()), numSamples, interpolator);
}
IntensityProfile::Pointer mitk::ComputeIntensityProfile(Image::Pointer image, const Point3D& startPoint, const Point3D& endPoint, unsigned int numSamples, InterpolateImageFunction::Enum interpolator)
{
return ::ComputeIntensityProfile(image, CreatePathFromPoints(image->GetGeometry(), startPoint, endPoint), numSamples, interpolator);
}
IntensityProfile::InstanceIdentifier mitk::ComputeGlobalMaximum(IntensityProfile::Pointer intensityProfile)
{
IntensityProfile::MeasurementType max = -vcl_numeric_limits<IntensityProfile::MeasurementType>::max();
IntensityProfile::InstanceIdentifier maxIndex = 0;
IntensityProfile::ConstIterator end = intensityProfile->End();
IntensityProfile::MeasurementType measurement;
for (IntensityProfile::ConstIterator it = intensityProfile->Begin(); it != end; ++it)
{
measurement = it.GetMeasurementVector()[0];
if (measurement > max)
{
max = measurement;
maxIndex = it.GetInstanceIdentifier();
}
}
return maxIndex;
}
IntensityProfile::InstanceIdentifier mitk::ComputeGlobalMinimum(IntensityProfile::Pointer intensityProfile)
{
IntensityProfile::MeasurementType min = vcl_numeric_limits<IntensityProfile::MeasurementType>::max();
IntensityProfile::InstanceIdentifier minIndex = 0;
IntensityProfile::ConstIterator end = intensityProfile->End();
IntensityProfile::MeasurementType measurement;
for (IntensityProfile::ConstIterator it = intensityProfile->Begin(); it != end; ++it)
{
measurement = it.GetMeasurementVector()[0];
if (measurement < min)
{
min = measurement;
minIndex = it.GetInstanceIdentifier();
}
}
return minIndex;
}
IntensityProfile::InstanceIdentifier mitk::ComputeCenterOfMaximumArea(IntensityProfile::Pointer intensityProfile, IntensityProfile::InstanceIdentifier radius)
{
const IntensityProfile::MeasurementType min = intensityProfile->GetMeasurementVector(ComputeGlobalMinimum(intensityProfile))[0];
const IntensityProfile::InstanceIdentifier areaWidth = 1 + 2 * radius;
IntensityProfile::MeasurementType maxArea = 0;
for (IntensityProfile::InstanceIdentifier i = 0; i < areaWidth; ++i)
maxArea += intensityProfile->GetMeasurementVector(i)[0] - min;
const IntensityProfile::InstanceIdentifier lastIndex = intensityProfile->Size() - areaWidth;
IntensityProfile::InstanceIdentifier centerOfMaxArea = radius;
IntensityProfile::MeasurementType area = maxArea;
for (IntensityProfile::InstanceIdentifier i = 1; i <= lastIndex; ++i)
{
area += intensityProfile->GetMeasurementVector(i + areaWidth - 1)[0] - min;
area -= intensityProfile->GetMeasurementVector(i - 1)[0] - min;
if (area > maxArea)
{
maxArea = area;
centerOfMaxArea = i + radius; // TODO: If multiple areas in the neighborhood have the same intensity chose the middle one instead of the first one.
}
}
return centerOfMaxArea;
}
std::vector<IntensityProfile::MeasurementType> mitk::CreateVectorFromIntensityProfile(IntensityProfile::Pointer intensityProfile)
{
std::vector<IntensityProfile::MeasurementType> result;
result.reserve(intensityProfile->Size());
IntensityProfile::ConstIterator end = intensityProfile->End();
for (IntensityProfile::ConstIterator it = intensityProfile->Begin(); it != end; ++it)
result.push_back(it.GetMeasurementVector()[0]);
return result;
}
IntensityProfile::Pointer mitk::CreateIntensityProfileFromVector(const std::vector<IntensityProfile::MeasurementType>& vector)
{
const IntensityProfile::InstanceIdentifier size = vector.size();
IntensityProfile::Pointer result = IntensityProfile::New();
result->Resize(size);
for (IntensityProfile::InstanceIdentifier i = 0; i < size; ++i)
result->SetMeasurement(i, 0, vector[i]);
return result;
}
diff --git a/Modules/IpPicSupport/Testing/mitkPicFileReaderTest.cpp b/Modules/IpPicSupport/Testing/mitkPicFileReaderTest.cpp
index 01cda35ab7..2a2c879816 100644
--- a/Modules/IpPicSupport/Testing/mitkPicFileReaderTest.cpp
+++ b/Modules/IpPicSupport/Testing/mitkPicFileReaderTest.cpp
@@ -1,189 +1,186 @@
/*===================================================================
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 "mitkTestingMacros.h"
#include "mitkImage.h"
#include "mitkPicFileReader.h"
#include "mitkPicHelper.h"
#include "mitkSlicedGeometry3D.h"
#include <itksys/SystemTools.hxx>
#include <itkImageFileReader.h>
#include <mitkTimeGeometry.h>
#include <fstream>
int mitkPicFileReaderTest(int argc, char* argv[])
{
MITK_TEST_BEGIN(mitkPicFileReaderTest)
if(argc>=1)
{
if(itksys::SystemTools::FileLength(argv[1]) == 0)
{
-
mitk::PicFileReader::Pointer emptyFileReader = mitk::PicFileReader::New();
emptyFileReader->SetFileName(argv[1]);
MITK_TEST_FOR_EXCEPTION(itk::ImageFileReaderException,emptyFileReader->Update());
}
else
{
-
-
//independently read header of pic file
mitkIpPicDescriptor *picheader=NULL;
if(itksys::SystemTools::LowerCase(itksys::SystemTools::GetFilenameExtension(argv[1])).find(".pic")!=std::string::npos)
{
picheader = mitkIpPicGetHeader(argv[1], NULL);
}
if(picheader==NULL)
{
std::cout<<"file not found/not a pic-file - test not applied [PASSED]"<<std::endl;
std::cout<<"[TEST DONE]"<<std::endl;
return EXIT_SUCCESS;
}
mitkIpPicGetTags(argv[1], picheader);
//Read pic-Image from file
mitk::PicFileReader::Pointer reader = mitk::PicFileReader::New();
reader->SetFileName(argv[1]);
reader->Update();
std::cout << "Testing IsInitialized(): ";
if(reader->GetOutput()->IsInitialized()==false)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing IsSliceSet(): ";
if(reader->GetOutput()->IsSliceSet(0)==false)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing availability of geometry: ";
if(reader->GetOutput()->GetGeometry()==NULL)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing type of geometry (TimeGeometry expected): ";
mitk::TimeGeometry* timeGeometry;
timeGeometry = reader->GetOutput()->GetTimeGeometry();
if(timeGeometry==NULL)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing availability of first geometry contained in the TimeGeometry: ";
if(timeGeometry->GetGeometryForTimeStep(0).IsNull())
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing type of first geometry contained in the TimeGeometry (SlicedGeometry3D expected): ";
mitk::SlicedGeometry3D* slicedgeometry;
slicedgeometry = dynamic_cast<mitk::SlicedGeometry3D*>(timeGeometry->GetGeometryForTimeStep(0).GetPointer());
if(slicedgeometry==NULL)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing availability of first geometry contained in the SlicedGeometry3D: ";
- mitk::Geometry2D* geometry2d = slicedgeometry->GetGeometry2D(0);
+ mitk::PlaneGeometry* geometry2d = slicedgeometry->GetPlaneGeometry(0);
if(geometry2d==NULL)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing extent in units of first geometry contained in the SlicedGeometry3D: ";
if((fabs(geometry2d->GetExtent(0)-picheader->n[0])>mitk::eps) || (fabs(geometry2d->GetExtent(1)-picheader->n[1])>mitk::eps))
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing extent in units of image of SlicedGeometry3D: ";
if((fabs(slicedgeometry->GetExtent(0)-picheader->n[0])>mitk::eps) || (fabs(slicedgeometry->GetExtent(1)-picheader->n[1])>mitk::eps)
|| (picheader->dim>2 && (fabs(slicedgeometry->GetExtent(2)-picheader->n[2])>mitk::eps))
)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
std::cout << "Testing consistency of spacing from matrix and stored spacing in the first SlicedGeometry3D: ";
mitk::Vector3D spacing;
spacing[0] = slicedgeometry->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(0).two_norm();
spacing[1] = slicedgeometry->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(1).two_norm();
spacing[2] = slicedgeometry->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(2).two_norm();
mitk::Vector3D readspacing=slicedgeometry->GetSpacing();
mitk::Vector3D dist = spacing-readspacing;
if(dist.GetSquaredNorm()>mitk::eps)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
//independently read the overall spacing
spacing.Fill(1);
mitk::PicHelper::GetSpacing(picheader, spacing);
std::cout << "Testing correct reading of overall spacing stored in the first SlicedGeometry3D: ";
dist = spacing-readspacing;
if(dist.GetSquaredNorm()>mitk::eps)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
if(picheader->dim==4)
{
std::cout << "4D dataset: Testing that timebounds are not infinite: ";
- if((slicedgeometry->GetTimeBounds()[0] == mitk::ScalarTypeNumericTraits::NonpositiveMin()) &&
- (slicedgeometry->GetTimeBounds()[1] == mitk::ScalarTypeNumericTraits::max())
+ if((timeGeometry->GetTimeBounds(0)[0] == mitk::ScalarTypeNumericTraits::NonpositiveMin()) &&
+ (timeGeometry->GetTimeBounds(0)[1] == mitk::ScalarTypeNumericTraits::max())
)
{
std::cout<<"[FAILED]"<<std::endl;
return EXIT_FAILURE;
}
std::cout<<"[PASSED]"<<std::endl;
}
mitkIpPicFree(picheader);
}
}
MITK_TEST_END();
}
diff --git a/Modules/IpPicSupport/mitkPicHelper.cpp b/Modules/IpPicSupport/mitkPicHelper.cpp
index 0907e2aeba..04a27fb3f8 100644
--- a/Modules/IpPicSupport/mitkPicHelper.cpp
+++ b/Modules/IpPicSupport/mitkPicHelper.cpp
@@ -1,296 +1,284 @@
/*===================================================================
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 "mitkConfig.h"
#include "mitkPicHelper.h"
#include "mitkSlicedGeometry3D.h"
#include "mitkPlaneGeometry.h"
#ifdef HAVE_IPDICOM
#include "ipDicom/ipDicom.h"
#endif /* HAVE_IPDICOM */
bool mitk::PicHelper::GetSpacing(const mitkIpPicDescriptor* aPic, Vector3D & spacing)
{
mitkIpPicDescriptor* pic = const_cast<mitkIpPicDescriptor*>(aPic);
mitkIpPicTSV_t *tsv;
bool pixelSize = false;
tsv = mitkIpPicQueryTag( pic, "REAL PIXEL SIZE" );
if(tsv==NULL)
{
tsv = mitkIpPicQueryTag( pic, "PIXEL SIZE" );
pixelSize = true;
}
if(tsv)
{
bool tagFound = false;
if((tsv->dim*tsv->n[0]>=3) && (tsv->type==mitkIpPicFloat))
{
if(tsv->bpe==32)
{
FillVector3D(spacing,((mitkIpFloat4_t*)tsv->value)[0], ((mitkIpFloat4_t*)tsv->value)[1],((mitkIpFloat4_t*)tsv->value)[2]);
tagFound = true;
}
else
if(tsv->bpe==64)
{
FillVector3D(spacing,((mitkIpFloat8_t*)tsv->value)[0], ((mitkIpFloat8_t*)tsv->value)[1],((mitkIpFloat8_t*)tsv->value)[2]);
tagFound = true;
}
}
if(tagFound && pixelSize)
{
tsv = mitkIpPicQueryTag( pic, "PIXEL SPACING" );
if(tsv)
{
mitk::ScalarType zSpacing = 0;
if((tsv->dim*tsv->n[0]>=3) && (tsv->type==mitkIpPicFloat))
{
if(tsv->bpe==32)
{
zSpacing = ((mitkIpFloat4_t*)tsv->value)[2];
}
else
if(tsv->bpe==64)
{
zSpacing = ((mitkIpFloat8_t*)tsv->value)[2];
}
if(zSpacing != 0)
{
spacing[2] = zSpacing;
}
}
}
}
if(tagFound) return true;
}
#ifdef HAVE_IPDICOM
tsv = mitkIpPicQueryTag( pic, "SOURCE HEADER" );
if( tsv )
{
void *data;
mitkIpUInt4_t len;
mitkIpFloat8_t spacing_z = 0;
mitkIpFloat8_t thickness = 1;
mitkIpFloat8_t fx = 1;
mitkIpFloat8_t fy = 1;
bool ok=false;
if( dicomFindElement( (unsigned char *) tsv->value, 0x0018, 0x0088, &data, &len ) )
{
ok=true;
sscanf( (char *) data, "%lf", &spacing_z );
// itkGenericOutputMacro( "spacing: " << spacing_z << " mm");
}
if( dicomFindElement( (unsigned char *) tsv->value, 0x0018, 0x0050, &data, &len ) )
{
ok=true;
sscanf( (char *) data, "%lf", &thickness );
// itkGenericOutputMacro( "thickness: " << thickness << " mm");
if( thickness == 0 )
thickness = 1;
}
if( dicomFindElement( (unsigned char *) tsv->value, 0x0028, 0x0030, &data, &len )
&& len>0 && ((char *)data)[0] )
{
sscanf( (char *) data, "%lf\\%lf", &fy, &fx ); // row / column value
// itkGenericOutputMacro( "fx, fy: " << fx << "/" << fy << " mm");
}
else
ok=false;
if(ok)
FillVector3D(spacing, fx, fy,( spacing_z > 0 ? spacing_z : thickness));
return ok;
}
#endif /* HAVE_IPDICOM */
if(spacing[0]<=0 || spacing[1]<=0 || spacing[2]<=0)
{
itkGenericOutputMacro(<< "illegal spacing by pic tag: " << spacing << ". Setting spacing to (1,1,1).");
spacing.Fill(1);
}
return false;
}
bool mitk::PicHelper::GetTimeSpacing(const mitkIpPicDescriptor* aPic, float& timeSpacing)
{
-
mitkIpPicDescriptor* pic = const_cast<mitkIpPicDescriptor*>(aPic);
mitkIpPicTSV_t *tsv;
tsv = mitkIpPicQueryTag( pic, "PIXEL SIZE" );
if(tsv)
{
timeSpacing = ((mitkIpFloat4_t*)tsv->value)[3];
if( timeSpacing <=0 ) timeSpacing = 1;
}
else timeSpacing = 1;
return true;
}
bool mitk::PicHelper::SetSpacing(const mitkIpPicDescriptor* aPic, SlicedGeometry3D* slicedgeometry)
{
mitkIpPicDescriptor* pic = const_cast<mitkIpPicDescriptor*>(aPic);
Vector3D spacing(slicedgeometry->GetSpacing());
mitkIpPicTSV_t *tsv;
if ( (tsv = mitkIpPicQueryTag( pic, "REAL PIXEL SIZES" )) != NULL)
{
int count = tsv->n[1];
float* value = (float*) tsv->value;
mitk::Vector3D pixelSize;
spacing.Fill(0);
for ( int s=0; s < count; s++ )
{
pixelSize[0] = (ScalarType) *value++;
pixelSize[1] = (ScalarType) *value++;
pixelSize[2] = (ScalarType) *value++;
spacing += pixelSize;
}
spacing *= 1.0f/count;
slicedgeometry->SetSpacing(spacing);
itkGenericOutputMacro(<< "the slices are inhomogeneous" );
}
else
if(GetSpacing(pic, spacing))
{
slicedgeometry->SetSpacing(spacing);
return true;
}
return false;
}
void mitk::PicHelper::InitializeEvenlySpaced(const mitkIpPicDescriptor* pic, unsigned int slices, SlicedGeometry3D* slicedgeometry)
{
assert(pic!=NULL);
assert(slicedgeometry!=NULL);
mitk::PlaneGeometry::Pointer planegeometry=mitk::PlaneGeometry::New();
mitkIpPicTSV_t *geometryTag;
if ( (geometryTag = mitkIpPicQueryTag( const_cast<mitkIpPicDescriptor*>(pic), "ISG" )) != NULL)
{
mitk::Point3D origin;
mitk::Vector3D rightVector;
mitk::Vector3D downVector;
mitk::Vector3D spacing;
mitk::vtk2itk(((float*)geometryTag->value+0), origin);
mitk::vtk2itk(((float*)geometryTag->value+3), rightVector);
mitk::vtk2itk(((float*)geometryTag->value+6), downVector);
mitk::vtk2itk(((float*)geometryTag->value+9), spacing);
mitk::PlaneGeometry::Pointer planegeometry = PlaneGeometry::New();
planegeometry->InitializeStandardPlane(pic->n[0], pic->n[1], rightVector, downVector, &spacing);
planegeometry->SetOrigin(origin);
slicedgeometry->InitializeEvenlySpaced(planegeometry, slices);
}
else
{
Vector3D spacing;
spacing.Fill(1);
GetSpacing(pic, spacing);
planegeometry->InitializeStandardPlane(pic->n[0], pic->n[1], spacing);
slicedgeometry->InitializeEvenlySpaced(planegeometry, spacing[2], slices);
}
-
- if(pic->dim>=4)
- {
- float ts = 0;
- GetTimeSpacing(pic, ts);
- TimeBounds timebounds;
- timebounds[0] = 0.0;
- timebounds[1] = ts;
- slicedgeometry->SetTimeBounds(timebounds);
- }
}
-bool mitk::PicHelper::SetGeometry2D(const mitkIpPicDescriptor* aPic, int s, SlicedGeometry3D* slicedgeometry)
+bool mitk::PicHelper::SetPlaneGeometry(const mitkIpPicDescriptor* aPic, int s, SlicedGeometry3D* slicedgeometry)
{
mitkIpPicDescriptor* pic = const_cast<mitkIpPicDescriptor*>(aPic);
if((pic!=NULL) && (slicedgeometry->IsValidSlice(s)))
{
//construct standard view
mitk::Point3D origin;
mitk::Vector3D rightDV, bottomDV;
mitkIpPicTSV_t *tsv;
if ( (tsv = mitkIpPicQueryTag( pic, "REAL PIXEL SIZES" )) != NULL)
{
unsigned int count = (unsigned int) tsv->n[1];
float* value = (float*) tsv->value;
mitk::Vector3D pixelSize;
ScalarType zPosition = 0.0f;
if(s >= 0)
{
if(count < (unsigned int) s)
return false;
count = s;
}
else
{
if(count < slicedgeometry->GetSlices())
return false;
count = slicedgeometry->GetSlices();
}
unsigned int slice;
for (slice=0; slice < count; ++slice )
{
pixelSize[0] = (ScalarType) *value++;
pixelSize[1] = (ScalarType) *value++;
pixelSize[2] = (ScalarType) *value++;
zPosition += pixelSize[2] / 2.0f; // first half slice thickness
if((s==-1) || (slice== (unsigned int) s))
{
Vector3D spacing;
spacing = pixelSize;
FillVector3D(origin, 0, 0, zPosition);
FillVector3D(rightDV, pic->n[0], 0, 0);
FillVector3D(bottomDV, 0, pic->n[1], 0);
mitk::PlaneGeometry::Pointer planegeometry=mitk::PlaneGeometry::New();
planegeometry->InitializeStandardPlane(pic->n[0], pic->n[1], rightDV.GetVnlVector(), bottomDV.GetVnlVector(), &spacing);
planegeometry->SetOrigin(origin);
- slicedgeometry->SetGeometry2D(planegeometry, s);
+ slicedgeometry->SetPlaneGeometry(planegeometry, s);
}
zPosition += pixelSize[2] / 2.0f; // second half slice thickness
}
-
}
else
{
FillVector3D(origin,0,0,s); slicedgeometry->IndexToWorld(origin, origin);
FillVector3D(rightDV,pic->n[0],0,0);
FillVector3D(bottomDV,0,pic->n[1],0);
mitk::PlaneGeometry::Pointer planegeometry=mitk::PlaneGeometry::New();
planegeometry->InitializeStandardPlane(pic->n[0], pic->n[1], rightDV.GetVnlVector(), bottomDV.GetVnlVector(), &slicedgeometry->GetSpacing());
planegeometry->SetOrigin(origin);
- slicedgeometry->SetGeometry2D(planegeometry, s);
+ slicedgeometry->SetPlaneGeometry(planegeometry, s);
}
return true;
}
return false;
}
diff --git a/Modules/IpPicSupport/mitkPicHelper.h b/Modules/IpPicSupport/mitkPicHelper.h
index 11a18b6d1c..98bd3928cb 100644
--- a/Modules/IpPicSupport/mitkPicHelper.h
+++ b/Modules/IpPicSupport/mitkPicHelper.h
@@ -1,52 +1,57 @@
/*===================================================================
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 MITKPICHELPER_H_HEADER_INCLUDED_C1F4DAB4
#define MITKPICHELPER_H_HEADER_INCLUDED_C1F4DAB4
#include <MitkIpPicSupportExports.h>
#include "mitkVector.h"
#include <mitkIpPic.h>
+#include <mitkCommon.h>
namespace mitk {
class SlicedGeometry3D;
//##Documentation
//## @brief Internal class for managing references on sub-images
//## @ingroup Data
class MitkIpPicSupport_EXPORT PicHelper
{
public:
static const char *GetNameOfClass() { return "PicHelper"; }
static bool GetSpacing(const mitkIpPicDescriptor* pic, Vector3D & spacing);
static bool SetSpacing(const mitkIpPicDescriptor* pic, SlicedGeometry3D* slicedgeometry);
static bool GetTimeSpacing(const mitkIpPicDescriptor* pic, float& timeSpacing);
static void InitializeEvenlySpaced(const mitkIpPicDescriptor* pic, unsigned int slices, SlicedGeometry3D* slicedgeometry);
- static bool SetGeometry2D(const mitkIpPicDescriptor* pic, int s, SlicedGeometry3D* slicedgeometry);
+ static bool SetPlaneGeometry(const mitkIpPicDescriptor* pic, int s, SlicedGeometry3D* slicedgeometry);
+ /**
+ * \deprecatedSince{2014_06} Please use SetPlaneGeometry
+ */
+ DEPRECATED(static bool SetGeometry2D(const mitkIpPicDescriptor* pic, int s, SlicedGeometry3D* slicedgeometry){return SetPlaneGeometry(pic,s,slicedgeometry);};)
};
} // namespace mitk
#endif /* MITKPICHELPER_H_HEADER_INCLUDED_C1F4DAB4 */
diff --git a/Modules/IpPicSupportIO/Internal/mitkPicHelper.cpp b/Modules/IpPicSupportIO/Internal/mitkPicHelper.cpp
index 0907e2aeba..04a27fb3f8 100644
--- a/Modules/IpPicSupportIO/Internal/mitkPicHelper.cpp
+++ b/Modules/IpPicSupportIO/Internal/mitkPicHelper.cpp
@@ -1,296 +1,284 @@
/*===================================================================
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 "mitkConfig.h"
#include "mitkPicHelper.h"
#include "mitkSlicedGeometry3D.h"
#include "mitkPlaneGeometry.h"
#ifdef HAVE_IPDICOM
#include "ipDicom/ipDicom.h"
#endif /* HAVE_IPDICOM */
bool mitk::PicHelper::GetSpacing(const mitkIpPicDescriptor* aPic, Vector3D & spacing)
{
mitkIpPicDescriptor* pic = const_cast<mitkIpPicDescriptor*>(aPic);
mitkIpPicTSV_t *tsv;
bool pixelSize = false;
tsv = mitkIpPicQueryTag( pic, "REAL PIXEL SIZE" );
if(tsv==NULL)
{
tsv = mitkIpPicQueryTag( pic, "PIXEL SIZE" );
pixelSize = true;
}
if(tsv)
{
bool tagFound = false;
if((tsv->dim*tsv->n[0]>=3) && (tsv->type==mitkIpPicFloat))
{
if(tsv->bpe==32)
{
FillVector3D(spacing,((mitkIpFloat4_t*)tsv->value)[0], ((mitkIpFloat4_t*)tsv->value)[1],((mitkIpFloat4_t*)tsv->value)[2]);
tagFound = true;
}
else
if(tsv->bpe==64)
{
FillVector3D(spacing,((mitkIpFloat8_t*)tsv->value)[0], ((mitkIpFloat8_t*)tsv->value)[1],((mitkIpFloat8_t*)tsv->value)[2]);
tagFound = true;
}
}
if(tagFound && pixelSize)
{
tsv = mitkIpPicQueryTag( pic, "PIXEL SPACING" );
if(tsv)
{
mitk::ScalarType zSpacing = 0;
if((tsv->dim*tsv->n[0]>=3) && (tsv->type==mitkIpPicFloat))
{
if(tsv->bpe==32)
{
zSpacing = ((mitkIpFloat4_t*)tsv->value)[2];
}
else
if(tsv->bpe==64)
{
zSpacing = ((mitkIpFloat8_t*)tsv->value)[2];
}
if(zSpacing != 0)
{
spacing[2] = zSpacing;
}
}
}
}
if(tagFound) return true;
}
#ifdef HAVE_IPDICOM
tsv = mitkIpPicQueryTag( pic, "SOURCE HEADER" );
if( tsv )
{
void *data;
mitkIpUInt4_t len;
mitkIpFloat8_t spacing_z = 0;
mitkIpFloat8_t thickness = 1;
mitkIpFloat8_t fx = 1;
mitkIpFloat8_t fy = 1;
bool ok=false;
if( dicomFindElement( (unsigned char *) tsv->value, 0x0018, 0x0088, &data, &len ) )
{
ok=true;
sscanf( (char *) data, "%lf", &spacing_z );
// itkGenericOutputMacro( "spacing: " << spacing_z << " mm");
}
if( dicomFindElement( (unsigned char *) tsv->value, 0x0018, 0x0050, &data, &len ) )
{
ok=true;
sscanf( (char *) data, "%lf", &thickness );
// itkGenericOutputMacro( "thickness: " << thickness << " mm");
if( thickness == 0 )
thickness = 1;
}
if( dicomFindElement( (unsigned char *) tsv->value, 0x0028, 0x0030, &data, &len )
&& len>0 && ((char *)data)[0] )
{
sscanf( (char *) data, "%lf\\%lf", &fy, &fx ); // row / column value
// itkGenericOutputMacro( "fx, fy: " << fx << "/" << fy << " mm");
}
else
ok=false;
if(ok)
FillVector3D(spacing, fx, fy,( spacing_z > 0 ? spacing_z : thickness));
return ok;
}
#endif /* HAVE_IPDICOM */
if(spacing[0]<=0 || spacing[1]<=0 || spacing[2]<=0)
{
itkGenericOutputMacro(<< "illegal spacing by pic tag: " << spacing << ". Setting spacing to (1,1,1).");
spacing.Fill(1);
}
return false;
}
bool mitk::PicHelper::GetTimeSpacing(const mitkIpPicDescriptor* aPic, float& timeSpacing)
{
-
mitkIpPicDescriptor* pic = const_cast<mitkIpPicDescriptor*>(aPic);
mitkIpPicTSV_t *tsv;
tsv = mitkIpPicQueryTag( pic, "PIXEL SIZE" );
if(tsv)
{
timeSpacing = ((mitkIpFloat4_t*)tsv->value)[3];
if( timeSpacing <=0 ) timeSpacing = 1;
}
else timeSpacing = 1;
return true;
}
bool mitk::PicHelper::SetSpacing(const mitkIpPicDescriptor* aPic, SlicedGeometry3D* slicedgeometry)
{
mitkIpPicDescriptor* pic = const_cast<mitkIpPicDescriptor*>(aPic);
Vector3D spacing(slicedgeometry->GetSpacing());
mitkIpPicTSV_t *tsv;
if ( (tsv = mitkIpPicQueryTag( pic, "REAL PIXEL SIZES" )) != NULL)
{
int count = tsv->n[1];
float* value = (float*) tsv->value;
mitk::Vector3D pixelSize;
spacing.Fill(0);
for ( int s=0; s < count; s++ )
{
pixelSize[0] = (ScalarType) *value++;
pixelSize[1] = (ScalarType) *value++;
pixelSize[2] = (ScalarType) *value++;
spacing += pixelSize;
}
spacing *= 1.0f/count;
slicedgeometry->SetSpacing(spacing);
itkGenericOutputMacro(<< "the slices are inhomogeneous" );
}
else
if(GetSpacing(pic, spacing))
{
slicedgeometry->SetSpacing(spacing);
return true;
}
return false;
}
void mitk::PicHelper::InitializeEvenlySpaced(const mitkIpPicDescriptor* pic, unsigned int slices, SlicedGeometry3D* slicedgeometry)
{
assert(pic!=NULL);
assert(slicedgeometry!=NULL);
mitk::PlaneGeometry::Pointer planegeometry=mitk::PlaneGeometry::New();
mitkIpPicTSV_t *geometryTag;
if ( (geometryTag = mitkIpPicQueryTag( const_cast<mitkIpPicDescriptor*>(pic), "ISG" )) != NULL)
{
mitk::Point3D origin;
mitk::Vector3D rightVector;
mitk::Vector3D downVector;
mitk::Vector3D spacing;
mitk::vtk2itk(((float*)geometryTag->value+0), origin);
mitk::vtk2itk(((float*)geometryTag->value+3), rightVector);
mitk::vtk2itk(((float*)geometryTag->value+6), downVector);
mitk::vtk2itk(((float*)geometryTag->value+9), spacing);
mitk::PlaneGeometry::Pointer planegeometry = PlaneGeometry::New();
planegeometry->InitializeStandardPlane(pic->n[0], pic->n[1], rightVector, downVector, &spacing);
planegeometry->SetOrigin(origin);
slicedgeometry->InitializeEvenlySpaced(planegeometry, slices);
}
else
{
Vector3D spacing;
spacing.Fill(1);
GetSpacing(pic, spacing);
planegeometry->InitializeStandardPlane(pic->n[0], pic->n[1], spacing);
slicedgeometry->InitializeEvenlySpaced(planegeometry, spacing[2], slices);
}
-
- if(pic->dim>=4)
- {
- float ts = 0;
- GetTimeSpacing(pic, ts);
- TimeBounds timebounds;
- timebounds[0] = 0.0;
- timebounds[1] = ts;
- slicedgeometry->SetTimeBounds(timebounds);
- }
}
-bool mitk::PicHelper::SetGeometry2D(const mitkIpPicDescriptor* aPic, int s, SlicedGeometry3D* slicedgeometry)
+bool mitk::PicHelper::SetPlaneGeometry(const mitkIpPicDescriptor* aPic, int s, SlicedGeometry3D* slicedgeometry)
{
mitkIpPicDescriptor* pic = const_cast<mitkIpPicDescriptor*>(aPic);
if((pic!=NULL) && (slicedgeometry->IsValidSlice(s)))
{
//construct standard view
mitk::Point3D origin;
mitk::Vector3D rightDV, bottomDV;
mitkIpPicTSV_t *tsv;
if ( (tsv = mitkIpPicQueryTag( pic, "REAL PIXEL SIZES" )) != NULL)
{
unsigned int count = (unsigned int) tsv->n[1];
float* value = (float*) tsv->value;
mitk::Vector3D pixelSize;
ScalarType zPosition = 0.0f;
if(s >= 0)
{
if(count < (unsigned int) s)
return false;
count = s;
}
else
{
if(count < slicedgeometry->GetSlices())
return false;
count = slicedgeometry->GetSlices();
}
unsigned int slice;
for (slice=0; slice < count; ++slice )
{
pixelSize[0] = (ScalarType) *value++;
pixelSize[1] = (ScalarType) *value++;
pixelSize[2] = (ScalarType) *value++;
zPosition += pixelSize[2] / 2.0f; // first half slice thickness
if((s==-1) || (slice== (unsigned int) s))
{
Vector3D spacing;
spacing = pixelSize;
FillVector3D(origin, 0, 0, zPosition);
FillVector3D(rightDV, pic->n[0], 0, 0);
FillVector3D(bottomDV, 0, pic->n[1], 0);
mitk::PlaneGeometry::Pointer planegeometry=mitk::PlaneGeometry::New();
planegeometry->InitializeStandardPlane(pic->n[0], pic->n[1], rightDV.GetVnlVector(), bottomDV.GetVnlVector(), &spacing);
planegeometry->SetOrigin(origin);
- slicedgeometry->SetGeometry2D(planegeometry, s);
+ slicedgeometry->SetPlaneGeometry(planegeometry, s);
}
zPosition += pixelSize[2] / 2.0f; // second half slice thickness
}
-
}
else
{
FillVector3D(origin,0,0,s); slicedgeometry->IndexToWorld(origin, origin);
FillVector3D(rightDV,pic->n[0],0,0);
FillVector3D(bottomDV,0,pic->n[1],0);
mitk::PlaneGeometry::Pointer planegeometry=mitk::PlaneGeometry::New();
planegeometry->InitializeStandardPlane(pic->n[0], pic->n[1], rightDV.GetVnlVector(), bottomDV.GetVnlVector(), &slicedgeometry->GetSpacing());
planegeometry->SetOrigin(origin);
- slicedgeometry->SetGeometry2D(planegeometry, s);
+ slicedgeometry->SetPlaneGeometry(planegeometry, s);
}
return true;
}
return false;
}
diff --git a/Modules/IpPicSupportIO/Internal/mitkPicHelper.h b/Modules/IpPicSupportIO/Internal/mitkPicHelper.h
index a7fe95264b..51dde565be 100644
--- a/Modules/IpPicSupportIO/Internal/mitkPicHelper.h
+++ b/Modules/IpPicSupportIO/Internal/mitkPicHelper.h
@@ -1,50 +1,56 @@
/*===================================================================
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 MITKPICHELPER_H_HEADER_INCLUDED_C1F4DAB4
#define MITKPICHELPER_H_HEADER_INCLUDED_C1F4DAB4
#include "mitkVector.h"
#include <mitkIpPic.h>
+#include <mitkCommon.h>
namespace mitk {
class SlicedGeometry3D;
//##Documentation
//## @brief Internal class for managing references on sub-images
class PicHelper
{
public:
static const char *GetNameOfClass() { return "PicHelper"; }
static bool GetSpacing(const mitkIpPicDescriptor* pic, Vector3D & spacing);
static bool SetSpacing(const mitkIpPicDescriptor* pic, SlicedGeometry3D* slicedgeometry);
static bool GetTimeSpacing(const mitkIpPicDescriptor* pic, float& timeSpacing);
static void InitializeEvenlySpaced(const mitkIpPicDescriptor* pic, unsigned int slices, SlicedGeometry3D* slicedgeometry);
- static bool SetGeometry2D(const mitkIpPicDescriptor* pic, int s, SlicedGeometry3D* slicedgeometry);
+ static bool SetPlaneGeometry(const mitkIpPicDescriptor* pic, int s, SlicedGeometry3D* slicedgeometry);
+ /**
+ * \deprecatedSince{2014_06} Please use SetPlaneGeometry
+ */
+ DEPRECATED(static bool SetGeometry2D(const mitkIpPicDescriptor* pic, int s, SlicedGeometry3D* slicedgeometry){return SetPlaneGeometry(pic,s,slicedgeometry);};);
+
};
} // namespace mitk
#endif /* MITKPICHELPER_H_HEADER_INCLUDED_C1F4DAB4 */
diff --git a/Modules/MapperExt/mitkMeshMapper2D.cpp b/Modules/MapperExt/mitkMeshMapper2D.cpp
index b45d997d1e..b2cbd1fb4d 100644
--- a/Modules/MapperExt/mitkMeshMapper2D.cpp
+++ b/Modules/MapperExt/mitkMeshMapper2D.cpp
@@ -1,481 +1,478 @@
/*===================================================================
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 "mitkMeshMapper2D.h"
#include "mitkMesh.h"
#include "mitkBaseRenderer.h"
#include "mitkPlaneGeometry.h"
#include "mitkColorProperty.h"
#include "mitkProperties.h"
#include "mitkLine.h"
#include "mitkGL.h"
#include <vtkLinearTransform.h>
#include <algorithm>
const float selectedColor[]={1.0,0.0,0.6}; //for selected!
mitk::MeshMapper2D::MeshMapper2D()
{
}
mitk::MeshMapper2D::~MeshMapper2D()
{
}
const mitk::Mesh *mitk::MeshMapper2D::GetInput(void)
{
return static_cast<const mitk::Mesh * > ( GetDataNode()->GetData() );
}
// Return whether a point is "smaller" than the second
static bool point3DSmaller( const mitk::Point3D& elem1, const mitk::Point3D& elem2 )
{
if(elem1[0]!=elem2[0])
return elem1[0] < elem2[0];
if(elem1[1]!=elem2[1])
return elem1[1] < elem2[1];
return elem1[2] < elem2[2];
}
void mitk::MeshMapper2D::Paint( mitk::BaseRenderer *renderer )
{
-
bool visible = true;
GetDataNode()->GetVisibility(visible, renderer, "visible");
if(!visible) return;
// @FIXME: Logik fuer update
bool updateNeccesary = true;
if (updateNeccesary)
{
//aus GenerateData
mitk::Mesh::Pointer input = const_cast<mitk::Mesh*>(this->GetInput());
// Get the TimeGeometry of the input object
const TimeGeometry* inputTimeGeometry = input->GetTimeGeometry();
if (( inputTimeGeometry == NULL ) || ( inputTimeGeometry->CountTimeSteps() == 0 ) )
{
return;
}
//
// get the world time
//
- const Geometry2D* worldGeometry = renderer->GetCurrentWorldGeometry2D();
- assert( worldGeometry != NULL );
- ScalarType time = worldGeometry->GetTimeBounds()[ 0 ];
+ ScalarType time = renderer->GetTime();
//
// convert the world time in time steps of the input object
//
int timeStep=0;
if ( time > ScalarTypeNumericTraits::NonpositiveMin() )
timeStep = inputTimeGeometry->TimePointToTimeStep( time );
if ( inputTimeGeometry->IsValidTimeStep( timeStep ) == false )
{
return;
}
mitk::Mesh::MeshType::Pointer itkMesh = input->GetMesh( timeStep );
if ( itkMesh.GetPointer() == NULL)
{
return;
}
mitk::DisplayGeometry::Pointer displayGeometry = renderer->GetDisplayGeometry();
assert(displayGeometry.IsNotNull());
- const PlaneGeometry* worldplanegeometry = dynamic_cast<const PlaneGeometry*>(renderer->GetCurrentWorldGeometry2D());
+ const PlaneGeometry* worldplanegeometry = dynamic_cast<const PlaneGeometry*>(renderer->GetCurrentWorldPlaneGeometry());
//apply color and opacity read from the PropertyList
ApplyColorAndOpacityProperties(renderer);
vtkLinearTransform* transform = GetDataNode()->GetVtkTransform();
//List of the Points
Mesh::DataType::PointsContainerConstIterator it, end;
it=itkMesh->GetPoints()->Begin();
end=itkMesh ->GetPoints()->End();
//iterator on the additional data of each point
Mesh::PointDataIterator dataIt;//, dataEnd;
dataIt=itkMesh->GetPointData()->Begin();
//for switching back to old color after using selected color
float unselectedColor[4];
glGetFloatv(GL_CURRENT_COLOR,unselectedColor);
while(it!=end)
{
mitk::Point3D p, projected_p;
float vtkp[3];
itk2vtk(it->Value(), vtkp);
transform->TransformPoint(vtkp, vtkp);
vtk2itk(vtkp,p);
displayGeometry->Project(p, projected_p);
Vector3D diff=p-projected_p;
if(diff.GetSquaredNorm()<4.0)
{
Point2D pt2d, tmp;
displayGeometry->Map(projected_p, pt2d);
displayGeometry->WorldToDisplay(pt2d, pt2d);
Vector2D horz,vert;
horz[0]=5; horz[1]=0;
vert[0]=0; vert[1]=5;
//check if the point is to be marked as selected
if (dataIt->Value().selected)
{
horz[0]=8;
vert[1]=8;
glColor3f(selectedColor[0],selectedColor[1],selectedColor[2]);//red
switch (dataIt->Value().pointSpec)
{
case PTSTART:
{
//a quad
glBegin (GL_LINE_LOOP);
tmp=pt2d-horz+vert; glVertex2dv(&tmp[0]);
tmp=pt2d+horz+vert; glVertex2dv(&tmp[0]);
tmp=pt2d+horz-vert; glVertex2dv(&tmp[0]);
tmp=pt2d-horz-vert; glVertex2dv(&tmp[0]);
glEnd ();
}
break;
case PTUNDEFINED:
{
//a diamond around the point
glBegin (GL_LINE_LOOP);
tmp=pt2d-horz; glVertex2dv(&tmp[0]);
tmp=pt2d+vert; glVertex2dv(&tmp[0]);
tmp=pt2d+horz; glVertex2dv(&tmp[0]);
tmp=pt2d-vert; glVertex2dv(&tmp[0]);
glEnd ();
}
break;
default:
break;
}//switch
//the actual point
glBegin (GL_POINTS);
tmp=pt2d; glVertex2dv(&tmp[0]);
glEnd ();
}
else //if not selected
{
glColor3f(unselectedColor[0],unselectedColor[1],unselectedColor[2]);
switch (dataIt->Value().pointSpec)
{
case PTSTART:
{
//a quad
glBegin (GL_LINE_LOOP);
tmp=pt2d-horz+vert; glVertex2dv(&tmp[0]);
tmp=pt2d+horz+vert; glVertex2dv(&tmp[0]);
tmp=pt2d+horz-vert; glVertex2dv(&tmp[0]);
tmp=pt2d-horz-vert; glVertex2dv(&tmp[0]);
glEnd ();
}
case PTUNDEFINED:
{
//drawing crosses
glBegin (GL_LINES);
tmp=pt2d-horz; glVertex2dv(&tmp[0]);
tmp=pt2d+horz; glVertex2dv(&tmp[0]);
tmp=pt2d-vert; glVertex2dv(&tmp[0]);
tmp=pt2d+vert; glVertex2dv(&tmp[0]);
glEnd ();
}
default:
{
break;
}
}//switch
}//else
}
++it;
++dataIt;
}
//now connect the lines inbetween
mitk::Mesh::PointType thisPoint; thisPoint.Fill(0);
Point2D *firstOfCell = NULL;
Point2D *lastPoint = NULL;
unsigned int lastPointId = 0;
bool lineSelected = false;
Point3D firstOfCell3D;
Point3D lastPoint3D;
bool first;
mitk::Line<mitk::ScalarType> line;
std::vector<mitk::Point3D> intersectionPoints;
double t;
//iterate through all cells and then iterate through all indexes of points in that cell
Mesh::CellIterator cellIt, cellEnd;
Mesh::CellDataIterator cellDataIt;//, cellDataEnd;
Mesh::PointIdIterator cellIdIt, cellIdEnd;
cellIt = itkMesh->GetCells()->Begin();
cellEnd = itkMesh->GetCells()->End();
cellDataIt = itkMesh->GetCellData()->Begin();
while (cellIt != cellEnd)
{
unsigned int numOfPointsInCell = cellIt->Value()->GetNumberOfPoints();
if (numOfPointsInCell>1)
{
//iterate through all id's in the cell
cellIdIt = cellIt->Value()->PointIdsBegin();
cellIdEnd = cellIt->Value()->PointIdsEnd();
firstOfCell3D = input->GetPoint(*cellIdIt,timeStep);
intersectionPoints.clear();
intersectionPoints.reserve(numOfPointsInCell);
first = true;
while(cellIdIt != cellIdEnd)
{
lastPoint3D = thisPoint;
thisPoint = input->GetPoint(*cellIdIt,timeStep);
//search in data (vector<> selectedLines) if the index of the point is set. if so, then the line is selected.
lineSelected = false;
Mesh::SelectedLinesType selectedLines = cellDataIt->Value().selectedLines;
//a line between 1(lastPoint) and 2(pt2d) has the Id 1, so look for the Id of lastPoint
//since we only start, if we have more than one point in the cell, lastPointId is initiated with 0
Mesh::SelectedLinesIter position = std::find(selectedLines.begin(), selectedLines.end(), lastPointId);
if (position != selectedLines.end())
{
lineSelected = true;
}
mitk::Point3D p, projected_p;
float vtkp[3];
itk2vtk(thisPoint, vtkp);
transform->TransformPoint(vtkp, vtkp);
vtk2itk(vtkp,p);
displayGeometry->Project(p, projected_p);
Vector3D diff=p-projected_p;
if(diff.GetSquaredNorm()<4.0)
{
Point2D pt2d, tmp;
displayGeometry->Map(projected_p, pt2d);
displayGeometry->WorldToDisplay(pt2d, pt2d);
if (lastPoint == NULL)
{
//set the first point in the cell. This point in needed to close the polygon
firstOfCell = new Point2D;
*firstOfCell = pt2d;
lastPoint = new Point2D;
*lastPoint = pt2d;
lastPointId = *cellIdIt;
}
else
{
if (lineSelected)
{
glColor3f(selectedColor[0],selectedColor[1],selectedColor[2]);//red
//a line from lastPoint to thisPoint
glBegin (GL_LINES);
glVertex2dv(&(*lastPoint)[0]);
glVertex2dv(&pt2d[0]);
glEnd ();
}
else //if not selected
{
glColor3f(unselectedColor[0],unselectedColor[1],unselectedColor[2]);
//drawing crosses
glBegin (GL_LINES);
glVertex2dv(&(*lastPoint)[0]);
glVertex2dv(&pt2d[0]);
glEnd ();
}
//to draw the line to the next in iteration step
*lastPoint = pt2d;
//and to search for the selection state of the line
lastPointId = *cellIdIt;
}//if..else
}//if <4.0
//fill off-plane polygon part 1
if((!first) && (worldplanegeometry!=NULL))
{
line.SetPoints(lastPoint3D, thisPoint);
if(worldplanegeometry->IntersectionPointParam(line, t) &&
((t>=0) && (t<=1))
)
{
intersectionPoints.push_back(line.GetPoint(t));
}
}
++cellIdIt;
first=false;
}//while cellIdIter
//closed polygon?
if ( cellDataIt->Value().closed )
{
//close the polygon if needed
if( firstOfCell != NULL )
{
lineSelected = false;
Mesh::SelectedLinesType selectedLines = cellDataIt->Value().selectedLines;
Mesh::SelectedLinesIter position = std::find(selectedLines.begin(), selectedLines.end(), lastPointId);
if (position != selectedLines.end())//found the index
{
glColor3f(selectedColor[0],selectedColor[1],selectedColor[2]);//red
//a line from lastPoint to firstPoint
glBegin (GL_LINES);
glVertex2dv(&(*lastPoint)[0]);
glVertex2dv(&(*firstOfCell)[0]);
glEnd ();
}
else
{
glColor3f(unselectedColor[0],unselectedColor[1],unselectedColor[2]);
glBegin (GL_LINES);
glVertex2dv(&(*lastPoint)[0]);
glVertex2dv(&(*firstOfCell)[0]);
glEnd ();
}
}
}//if closed
//Axis-aligned bounding box(AABB) around the cell if selected and set in Property
bool showBoundingBox;
if (dynamic_cast<mitk::BoolProperty *>(this->GetDataNode()->GetProperty("showBoundingBox")) == NULL)
showBoundingBox = false;
else
showBoundingBox = dynamic_cast<mitk::BoolProperty *>(this->GetDataNode()->GetProperty("showBoundingBox"))->GetValue();
if(showBoundingBox)
{
if (cellDataIt->Value().selected)
{
mitk::Mesh::DataType::BoundingBoxPointer aABB = input->GetBoundingBoxFromCell(cellIt->Index());
if (aABB.IsNotNull())
{
mitk::Mesh::PointType min, max;
min = aABB->GetMinimum();
max = aABB->GetMaximum();
//project to the displayed geometry
Point2D min2D, max2D;
Point3D p, projected_p;
float vtkp[3];
itk2vtk(min, vtkp);
transform->TransformPoint(vtkp, vtkp);
vtk2itk(vtkp,p);
displayGeometry->Project(p, projected_p);
displayGeometry->Map(projected_p, min2D);
displayGeometry->WorldToDisplay(min2D, min2D);
itk2vtk(max, vtkp);
transform->TransformPoint(vtkp, vtkp);
vtk2itk(vtkp,p);
displayGeometry->Project(p, projected_p);
Vector3D diff=p-projected_p;
if(diff.GetSquaredNorm()<4.0)
{
displayGeometry->Map(projected_p, max2D);
displayGeometry->WorldToDisplay(max2D, max2D);
//draw the BoundingBox
glColor3f(selectedColor[0],selectedColor[1],selectedColor[2]);//red
//a line from lastPoint to firstPoint
glBegin(GL_LINE_LOOP);
glVertex2f(min2D[0], min2D[1]);
glVertex2f(min2D[0], max2D[1]);
glVertex2f(max2D[0], max2D[1]);
glVertex2f(max2D[0], min2D[1]);
glEnd();
}//draw bounding-box
}//bounding-box exists
}//cell selected
}//show bounding-box
//fill off-plane polygon part 2
if(worldplanegeometry!=NULL)
{
//consider line from last to first
line.SetPoints(thisPoint, firstOfCell3D);
if(worldplanegeometry->IntersectionPointParam(line, t) &&
((t>=0) && (t<=1))
)
{
intersectionPoints.push_back(line.GetPoint(t));
}
std::sort(intersectionPoints.begin(), intersectionPoints.end(), point3DSmaller);
std::vector<mitk::Point3D>::iterator it, end;
end=intersectionPoints.end();
if((intersectionPoints.size()%2)!=0)
{
--end; //ensure even number of intersection-points
}
double p[2];
Point3D pt3d;
Point2D pt2d;
for ( it = intersectionPoints.begin( ); it != end; ++it )
{
glBegin (GL_LINES);
displayGeometry->Map(*it, pt2d); displayGeometry->WorldToDisplay(pt2d, pt2d);
p[0] = pt2d[0]; p[1] = pt2d[1]; glVertex2dv(p);
++it;
displayGeometry->Map(*it, pt2d); displayGeometry->WorldToDisplay(pt2d, pt2d);
p[0] = pt2d[0]; p[1] = pt2d[1]; glVertex2dv(p);
glEnd ();
}
if(it!=intersectionPoints.end())
{
glBegin (GL_LINES);
displayGeometry->Map(*it, pt2d); displayGeometry->WorldToDisplay(pt2d, pt2d);
p[0] = pt2d[0]; p[1] = pt2d[1]; glVertex2dv(p);
p[0] = pt2d[0]; p[1] = pt2d[1]; glVertex2dv(p);
glEnd ();
}
}//fill off-plane polygon part 2
}//if numOfPointsInCell>1
delete firstOfCell;
delete lastPoint;
lastPoint = NULL;
firstOfCell = NULL;
lastPointId = 0;
++cellIt;
++cellDataIt;
}
}
}
diff --git a/Modules/MapperExt/mitkUnstructuredGridMapper2D.cpp b/Modules/MapperExt/mitkUnstructuredGridMapper2D.cpp
index 1cd6675f7c..8442ff18f3 100644
--- a/Modules/MapperExt/mitkUnstructuredGridMapper2D.cpp
+++ b/Modules/MapperExt/mitkUnstructuredGridMapper2D.cpp
@@ -1,574 +1,574 @@
/*===================================================================
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 "mitkUnstructuredGridMapper2D.h"
#include "mitkBaseRenderer.h"
#include "mitkPlaneGeometry.h"
#include "mitkUnstructuredGrid.h"
#include "mitkTransferFunction.h"
#include "mitkTransferFunctionProperty.h"
#include "mitkColorProperty.h"
#include "mitkVtkScalarModeProperty.h"
#include "mitkProperties.h"
#include "mitkAbstractTransformGeometry.h"
#include "mitkVtkMapper3D.h"
#include <vtkUnstructuredGrid.h>
#include <vtkPlane.h>
#include <vtkCellArray.h>
#include <vtkLookupTable.h>
#include <vtkPointData.h>
#include <vtkCellData.h>
#include <vtkLinearTransform.h>
#include <vtkVolume.h>
#include <vtkAssembly.h>
#include <vtkVolumeProperty.h>
#include <vtkAbstractMapper3D.h>
#include <vtkAbstractVolumeMapper.h>
#include <vtkScalarsToColors.h>
#include <vtkPiecewiseFunction.h>
#include <vtkColorTransferFunction.h>
#include <vtkProp3DCollection.h>
#include "Internal/vtkPointSetSlicer.h"
void mitk::UnstructuredGridMapper2D::GenerateDataForRenderer( mitk::BaseRenderer* renderer )
{
BaseLocalStorage *ls = m_LSH.GetLocalStorage(renderer);
bool needGenerateData = ls->IsGenerateDataRequired( renderer, this, GetDataNode() );
if(needGenerateData)
{
ls->UpdateGenerateDataTime();
mitk::DataNode::ConstPointer node = this->GetDataNode();
if ( node.IsNull() )
return;
if (!node->GetProperty(m_ScalarMode, "scalar mode"))
{
m_ScalarMode = mitk::VtkScalarModeProperty::New(0);
}
if (!node->GetProperty(m_ScalarVisibility, "scalar visibility"))
{
m_ScalarVisibility = mitk::BoolProperty::New(true);
}
if (!node->GetProperty(m_Outline, "outline polygons"))
{
m_Outline = mitk::BoolProperty::New(false);
}
if (!node->GetProperty(m_Color, "color"))
{
m_Color = mitk::ColorProperty::New(1.0f, 1.0f, 1.0f);
}
if (!node->GetProperty(m_LineWidth, "line width"))
{
m_LineWidth = mitk::IntProperty::New(1);
}
}
mitk::BaseData::Pointer input = const_cast<mitk::BaseData*>( GetDataNode()->GetData() );
assert( input );
input->Update();
if (m_VtkPointSet) m_VtkPointSet->UnRegister(0);
m_VtkPointSet = this->GetVtkPointSet(renderer);
assert(m_VtkPointSet);
m_VtkPointSet->Register(0);
if (m_ScalarVisibility->GetValue())
{
mitk::DataNode::ConstPointer node = this->GetDataNode();
mitk::TransferFunctionProperty::Pointer transferFuncProp;
node->GetProperty(transferFuncProp, "TransferFunction", renderer);
if (transferFuncProp.IsNotNull())
{
mitk::TransferFunction::Pointer tf = transferFuncProp->GetValue();
if (m_ScalarsToColors) m_ScalarsToColors->UnRegister(0);
m_ScalarsToColors = static_cast<vtkScalarsToColors*>(tf->GetColorTransferFunction());
m_ScalarsToColors->Register(0);
if (m_ScalarsToOpacity) m_ScalarsToOpacity->UnRegister(0);
m_ScalarsToOpacity = tf->GetScalarOpacityFunction();
m_ScalarsToOpacity->Register(0);
}
else
{
if (m_ScalarsToColors) m_ScalarsToColors->UnRegister(0);
m_ScalarsToColors = this->GetVtkLUT(renderer);
assert(m_ScalarsToColors);
m_ScalarsToColors->Register(0);
float opacity;
node->GetOpacity(opacity, renderer);
if (m_ScalarsToOpacity) m_ScalarsToOpacity->UnRegister(0);
m_ScalarsToOpacity = vtkPiecewiseFunction::New();
double range[2];
m_VtkPointSet->GetScalarRange(range);
m_ScalarsToOpacity->AddSegment(range[0], opacity, range[1], opacity);
}
}
}
void mitk::UnstructuredGridMapper2D::Paint( mitk::BaseRenderer* renderer )
{
bool visible = true;
GetDataNode()->GetVisibility(visible, renderer, "visible");
if(!visible) return;
vtkLinearTransform * vtktransform = GetDataNode()->GetVtkTransform();
vtkLinearTransform * inversetransform = vtktransform->GetLinearInverse();
- Geometry2D::ConstPointer worldGeometry = renderer->GetCurrentWorldGeometry2D();
+ PlaneGeometry::ConstPointer worldGeometry = renderer->GetCurrentWorldPlaneGeometry();
PlaneGeometry::ConstPointer worldPlaneGeometry = dynamic_cast<const PlaneGeometry*>( worldGeometry.GetPointer() );
Point3D point;
Vector3D normal;
if(worldPlaneGeometry.IsNotNull())
{
// set up vtkPlane according to worldGeometry
point=worldPlaneGeometry->GetOrigin();
normal=worldPlaneGeometry->GetNormal(); normal.Normalize();
m_Plane->SetTransform((vtkAbstractTransform*)NULL);
}
else
{
//@FIXME: does not work correctly. Does m_Plane->SetTransform really transforms a "plane plane" into a "curved plane"?
return;
- AbstractTransformGeometry::ConstPointer worldAbstractGeometry = dynamic_cast<const AbstractTransformGeometry*>(renderer->GetCurrentWorldGeometry2D());
+ AbstractTransformGeometry::ConstPointer worldAbstractGeometry = dynamic_cast<const AbstractTransformGeometry*>(renderer->GetCurrentWorldPlaneGeometry());
if(worldAbstractGeometry.IsNotNull())
{
// set up vtkPlane according to worldGeometry
point=const_cast<mitk::BoundingBox*>(worldAbstractGeometry->GetParametricBoundingBox())->GetMinimum();
FillVector3D(normal, 0, 0, 1);
m_Plane->SetTransform(worldAbstractGeometry->GetVtkAbstractTransform()->GetInverse());
}
else
return;
}
double vp[ 3 ], vnormal[ 3 ];
vnl2vtk(point.GetVnlVector(), vp);
vnl2vtk(normal.GetVnlVector(), vnormal);
//normally, we would need to transform the surface and cut the transformed surface with the cutter.
//This might be quite slow. Thus, the idea is, to perform an inverse transform of the plane instead.
//@todo It probably does not work for scaling operations yet:scaling operations have to be
//dealed with after the cut is performed by scaling the contour.
inversetransform->TransformPoint( vp, vp );
inversetransform->TransformNormalAtPoint( vp, vnormal, vnormal );
m_Plane->SetOrigin( vp );
m_Plane->SetNormal( vnormal );
// set data into cutter
m_Slicer->SetInputData( m_VtkPointSet );
// m_Cutter->GenerateCutScalarsOff();
// m_Cutter->SetSortByToSortByCell();
// calculate the cut
m_Slicer->Update();
// fetch geometry
mitk::DisplayGeometry::Pointer displayGeometry = renderer->GetDisplayGeometry();
assert( displayGeometry );
// float toGL=displayGeometry->GetSizeInDisplayUnits()[1];
//apply color and opacity read from the PropertyList
ApplyColorAndOpacityProperties( renderer );
// traverse the cut contour
vtkPolyData * contour = m_Slicer->GetOutput();
vtkPoints *vpoints = contour->GetPoints();
vtkCellArray *vlines = contour->GetLines();
vtkCellArray *vpolys = contour->GetPolys();
vtkPointData *vpointdata = contour->GetPointData();
vtkDataArray* vscalars = vpointdata->GetScalars();
vtkCellData *vcelldata = contour->GetCellData();
vtkDataArray* vcellscalars = vcelldata->GetScalars();
const int numberOfLines = contour->GetNumberOfLines();
const int numberOfPolys = contour->GetNumberOfPolys();
const bool useCellData = m_ScalarMode->GetVtkScalarMode() == VTK_SCALAR_MODE_DEFAULT ||
m_ScalarMode->GetVtkScalarMode() == VTK_SCALAR_MODE_USE_CELL_DATA;
const bool usePointData = m_ScalarMode->GetVtkScalarMode() == VTK_SCALAR_MODE_USE_POINT_DATA;
Point3D p;
Point2D p2d;
vlines->InitTraversal();
vpolys->InitTraversal();
mitk::Color outlineColor = m_Color->GetColor();
glLineWidth((float)m_LineWidth->GetValue());
for (int i = 0;i < numberOfLines;++i )
{
vtkIdType *cell(0);
vtkIdType cellSize(0);
vlines->GetNextCell( cellSize, cell );
float rgba[4] = {outlineColor[0], outlineColor[1], outlineColor[2], 1.0f};
if (m_ScalarVisibility->GetValue() && vcellscalars)
{
if ( useCellData )
{ // color each cell according to cell data
double scalar = vcellscalars->GetComponent( i, 0 );
double rgb[3] = { 1.0f, 1.0f, 1.0f };
m_ScalarsToColors->GetColor(scalar, rgb);
rgba[0] = (float)rgb[0];
rgba[1] = (float)rgb[1];
rgba[2] = (float)rgb[2];
rgba[3] = (float)m_ScalarsToOpacity->GetValue(scalar);
}
else if ( usePointData )
{
double scalar = vscalars->GetComponent( i, 0 );
double rgb[3] = { 1.0f, 1.0f, 1.0f };
m_ScalarsToColors->GetColor(scalar, rgb);
rgba[0] = (float)rgb[0];
rgba[1] = (float)rgb[1];
rgba[2] = (float)rgb[2];
rgba[3] = (float)m_ScalarsToOpacity->GetValue(scalar);
}
}
glColor4fv( rgba );
glBegin ( GL_LINE_LOOP );
for ( int j = 0;j < cellSize;++j )
{
vpoints->GetPoint( cell[ j ], vp );
//take transformation via vtktransform into account
vtktransform->TransformPoint( vp, vp );
vtk2itk( vp, p );
//convert 3D point (in mm) to 2D point on slice (also in mm)
worldGeometry->Map( p, p2d );
//convert point (until now mm and in worldcoordinates) to display coordinates (units )
displayGeometry->WorldToDisplay( p2d, p2d );
//convert display coordinates ( (0,0) is top-left ) in GL coordinates ( (0,0) is bottom-left )
//p2d[1]=toGL-p2d[1];
//add the current vertex to the line
glVertex2f( p2d[0], p2d[1] );
}
glEnd ();
}
bool polyOutline = m_Outline->GetValue();
bool scalarVisibility = m_ScalarVisibility->GetValue();
// cache the transformed points
// a fixed size array is way faster than 'new'
// slices through 3d cells usually do not generated
// polygons with more than 6 vertices
const int maxPolySize = 10;
Point2D* cachedPoints = new Point2D[maxPolySize*numberOfPolys];
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// only draw polygons if there are cell scalars
// or the outline property is set to true
if (scalarVisibility && vcellscalars)
{
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
for (int i = 0;i < numberOfPolys;++i )
{
vtkIdType *cell(0);
vtkIdType cellSize(0);
vpolys->GetNextCell( cellSize, cell );
float rgba[4] = {1.0f, 1.0f, 1.0f, 0};
if (scalarVisibility && vcellscalars)
{
if ( useCellData )
{ // color each cell according to cell data
double scalar = vcellscalars->GetComponent( i+numberOfLines, 0 );
double rgb[3] = { 1.0f, 1.0f, 1.0f };
m_ScalarsToColors->GetColor(scalar, rgb);
rgba[0] = (float)rgb[0];
rgba[1] = (float)rgb[1];
rgba[2] = (float)rgb[2];
rgba[3] = (float)m_ScalarsToOpacity->GetValue(scalar);
}
else if ( usePointData )
{
double scalar = vscalars->GetComponent( i, 0 );
double rgb[3] = { 1.0f, 1.0f, 1.0f };
m_ScalarsToColors->GetColor(scalar, rgb);
rgba[0] = (float)rgb[0];
rgba[1] = (float)rgb[1];
rgba[2] = (float)rgb[2];
rgba[3] = (float)m_ScalarsToOpacity->GetValue(scalar);
}
}
glColor4fv( rgba );
glBegin( GL_POLYGON );
for (int j = 0; j < cellSize; ++j)
{
vpoints->GetPoint( cell[ j ], vp );
//take transformation via vtktransform into account
vtktransform->TransformPoint( vp, vp );
vtk2itk( vp, p );
//convert 3D point (in mm) to 2D point on slice (also in mm)
worldGeometry->Map( p, p2d );
//convert point (until now mm and in worldcoordinates) to display coordinates (units )
displayGeometry->WorldToDisplay( p2d, p2d );
//convert display coordinates ( (0,0) is top-left ) in GL coordinates ( (0,0) is bottom-left )
//p2d[1]=toGL-p2d[1];
cachedPoints[i*10+j][0] = p2d[0];
cachedPoints[i*10+j][1] = p2d[1];
//add the current vertex to the line
glVertex2f( p2d[0], p2d[1] );
}
glEnd();
}
if (polyOutline)
{
vpolys->InitTraversal();
glColor4f(outlineColor[0], outlineColor[1], outlineColor[2], 1.0f);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
for (int i = 0;i < numberOfPolys;++i)
{
vtkIdType *cell(0);
vtkIdType cellSize(0);
vpolys->GetNextCell( cellSize, cell );
glBegin( GL_POLYGON );
//glPolygonOffset(1.0, 1.0);
for (int j = 0; j < cellSize; ++j)
{
//add the current vertex to the line
glVertex2f( cachedPoints[i*10+j][0], cachedPoints[i*10+j][1] );
}
glEnd();
}
}
}
glDisable(GL_BLEND);
delete cachedPoints;
}
vtkAbstractMapper3D*
mitk::UnstructuredGridMapper2D
::GetVtkAbstractMapper3D(mitk::BaseRenderer * renderer)
{
//MITK_INFO << "GETVTKABSTRACTMAPPER3D\n";
mitk::DataNode::ConstPointer node = this->GetDataNode();
if ( node.IsNull() )
return 0;
mitk::VtkMapper::Pointer mitkMapper = dynamic_cast< mitk::VtkMapper* > ( node->GetMapper( 2 ) );
if ( mitkMapper.IsNull() )
{
return 0;
}
mitkMapper->Update(renderer);
vtkAssembly* assembly = dynamic_cast<vtkAssembly*>(mitkMapper->GetVtkProp(renderer));
if (assembly)
{
vtkProp3DCollection* collection = assembly->GetParts();
collection->InitTraversal();
vtkProp3D* prop3d = 0;
do
{
prop3d = collection->GetNextProp3D();
vtkActor* actor = dynamic_cast<vtkActor*>( prop3d );
if (actor)
{
return dynamic_cast<vtkAbstractMapper3D*>( actor->GetMapper() );
}
vtkVolume* volume = dynamic_cast<vtkVolume*>( prop3d );
if (volume)
{
return dynamic_cast<vtkAbstractMapper3D*>( volume->GetMapper() );
}
} while (prop3d != collection->GetLastProp3D());
}
else
{
vtkActor* actor = dynamic_cast<vtkActor*>( mitkMapper->GetVtkProp(renderer) );
if (actor)
{
return dynamic_cast<vtkAbstractMapper3D*>( actor->GetMapper() );
}
vtkVolume* volume = dynamic_cast<vtkVolume*>( mitkMapper->GetVtkProp(renderer) );
if (volume)
{
return dynamic_cast<vtkAbstractMapper3D*>( volume->GetMapper() );
}
}
return 0;
}
vtkPointSet*
mitk::UnstructuredGridMapper2D
::GetVtkPointSet(mitk::BaseRenderer* renderer)
{
//MITK_INFO << "GETVTKPOINTSET\n";
vtkAbstractMapper3D * abstractMapper = GetVtkAbstractMapper3D(renderer);
if ( abstractMapper == 0 )
{
// try to get data from the node
mitk::DataNode::ConstPointer node = this->GetDataNode();
if ( node.IsNull() )
return 0;
mitk::BaseData::Pointer data = node->GetData();
mitk::UnstructuredGrid::Pointer grid = dynamic_cast<mitk::UnstructuredGrid*>(data.GetPointer());
if (!grid.IsNull())
return static_cast<vtkPointSet*>(grid->GetVtkUnstructuredGrid());
return 0;
}
else
{
vtkMapper* mapper = dynamic_cast<vtkMapper*>(abstractMapper);
if (mapper)
{
return dynamic_cast<vtkPointSet*>(mapper->GetInput());
}
vtkAbstractVolumeMapper* volMapper = dynamic_cast<vtkAbstractVolumeMapper*>(abstractMapper);
if (volMapper)
{
return dynamic_cast<vtkPointSet*>(volMapper->GetDataSetInput());
}
}
return 0;
}
vtkScalarsToColors* mitk::UnstructuredGridMapper2D::GetVtkLUT(mitk::BaseRenderer* renderer)
{
//MITK_INFO << "GETVTKLUT\n";
vtkMapper * mapper = dynamic_cast<vtkMapper*>(GetVtkAbstractMapper3D(renderer));
if (mapper)
return mapper->GetLookupTable();
else
{
mitk::DataNode::ConstPointer node = this->GetDataNode();
if ( node.IsNull() )
return 0;
mitk::VtkMapper::Pointer mitkMapper = dynamic_cast< mitk::VtkMapper* > ( node->GetMapper( 2 ) );
if ( mitkMapper.IsNull() )
{
//MITK_INFO << "mitkMapper is null\n";
return 0;
}
mitkMapper->Update(renderer);
vtkVolume* volume = dynamic_cast<vtkVolume*>( mitkMapper->GetVtkProp(renderer) );
if (volume)
{
//MITK_INFO << "found volume prop\n";
return static_cast<vtkScalarsToColors*>(volume->GetProperty()->GetRGBTransferFunction());
}
vtkAssembly* assembly = dynamic_cast<vtkAssembly*>(mitkMapper->GetVtkProp(renderer));
if (assembly)
{
//MITK_INFO << "found assembly prop\n";
mitk::TransferFunctionProperty::Pointer transferFuncProp;
node->GetProperty(transferFuncProp, "TransferFunction", 0);
if (transferFuncProp.IsNotNull())
{
MITK_INFO << "return colortransferfunction\n";
return static_cast<vtkScalarsToColors*>(transferFuncProp->GetValue()->GetColorTransferFunction());
}
}
return 0;
}
}
bool mitk::UnstructuredGridMapper2D::IsConvertibleToVtkPointSet(mitk::BaseRenderer * renderer)
{
return ( GetVtkPointSet(renderer) != 0 );
}
mitk::UnstructuredGridMapper2D::UnstructuredGridMapper2D()
{
m_Plane = vtkPlane::New();
m_Slicer = vtkPointSetSlicer::New();
m_Slicer->SetSlicePlane( m_Plane );
m_ScalarsToColors = 0;
m_ScalarsToOpacity = 0;
m_VtkPointSet = 0;
//m_LUT = vtkLookupTable::New();
//m_LUT->SetTableRange( 0, 255 );
//m_LUT->SetNumberOfColors( 255 );
//m_LUT->SetRampToLinear ();
//m_LUT->Build();
}
mitk::UnstructuredGridMapper2D::~UnstructuredGridMapper2D()
{
m_Slicer->Delete();
m_Plane->Delete();
if (m_ScalarsToOpacity != 0) m_ScalarsToOpacity->UnRegister(0);
if (m_ScalarsToColors != 0) m_ScalarsToColors->UnRegister(0);
if (m_VtkPointSet != 0) m_VtkPointSet->UnRegister(0);
}
diff --git a/Modules/MapperExt/mitkVectorImageMapper2D.cpp b/Modules/MapperExt/mitkVectorImageMapper2D.cpp
index 52914b27df..72d4c4853f 100644
--- a/Modules/MapperExt/mitkVectorImageMapper2D.cpp
+++ b/Modules/MapperExt/mitkVectorImageMapper2D.cpp
@@ -1,538 +1,531 @@
/*===================================================================
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 "mitkVectorImageMapper2D.h"
//vtk related includes
#include <vtkPlane.h>
#include <vtkLookupTable.h>
#include <vtkScalarsToColors.h>
#include <vtkImageReslice.h>
#include <vtkPolyData.h>
#include <vtkGlyph2D.h>
#include <vtkGlyphSource2D.h>
#include <vtkPolyData.h>
#include <vtkPolyDataMapper.h>
#include <vtkPoints.h>
#include <vtkCellArray.h>
#include <vtkFloatArray.h>
#include <vtkPointData.h>
#include <vtkCellData.h>
#include <vtkDataArray.h>
#include <vtkMath.h>
#include <vtkLinearTransform.h>
#include <vtkMatrixToLinearTransform.h>
#include <vtkLookupTable.h>
#include <vtkScalarsToColors.h>
#include <vtkTransform.h>
#include <vtkImageData.h>
#include <vtkDataSetWriter.h>
#include <vtkMaskedGlyph3D.h>
#include <vtkMaskedGlyph2D.h>
#include <vtkMatrix4x4.h>
#include <vtkCutter.h>
#include <vtkPlane.h>
#include <vtkIndent.h>
#include <vtkDataObject.h>
#include <fstream>
//mitk related includes
#include "mitkGL.h"
#include "mitkBaseRenderer.h"
#include "mitkColorProperty.h"
#include "mitkProperties.h"
#include "mitkAbstractTransformGeometry.h"
#include <mitkLookupTableProperty.h>
const mitk::Image * mitk::VectorImageMapper2D::GetInput( void )
{
if ( m_Image.IsNotNull() )
return m_Image;
else
return dynamic_cast<const mitk::Image*>( GetDataNode()->GetData() );
}
void mitk::VectorImageMapper2D::Paint( mitk::BaseRenderer * renderer )
{
//std::cout << "2d vector mapping..." << std::endl;
bool visible = true;
GetDataNode()->GetVisibility(visible, renderer, "visible");
if ( !visible )
return ;
mitk::Image::Pointer input = const_cast<mitk::Image*>( this->GetInput() );
if ( input.IsNull() )
return ;
- mitk::PlaneGeometry::Pointer worldPlaneGeometry2D = dynamic_cast< mitk::PlaneGeometry*>( const_cast<mitk::Geometry2D*>( renderer->GetCurrentWorldGeometry2D() ) );
- assert( worldPlaneGeometry2D.IsNotNull() );
+ mitk::PlaneGeometry::Pointer worldPlanePlaneGeometry = dynamic_cast< mitk::PlaneGeometry*>( const_cast<mitk::PlaneGeometry*>( renderer->GetCurrentWorldPlaneGeometry() ) );
+ assert( worldPlanePlaneGeometry.IsNotNull() );
vtkImageData* vtkImage = input->GetVtkImageData( this->GetCurrentTimeStep( input, renderer ) );
//
// set up the cutter orientation according to the current geometry of
// the renderers plane
//
Point3D point;
Vector3D normal;
- Geometry2D::ConstPointer worldGeometry = renderer->GetCurrentWorldGeometry2D();
+ PlaneGeometry::ConstPointer worldGeometry = renderer->GetCurrentWorldPlaneGeometry();
PlaneGeometry::ConstPointer worldPlaneGeometry = dynamic_cast<const PlaneGeometry*>( worldGeometry.GetPointer() );
if ( worldPlaneGeometry.IsNotNull() )
{
// set up vtkPlane according to worldGeometry
point = worldPlaneGeometry->GetOrigin();
normal = worldPlaneGeometry->GetNormal(); normal.Normalize();
m_Plane->SetTransform( (vtkAbstractTransform*)NULL );
}
else
{
itkWarningMacro( << "worldPlaneGeometry is NULL!" );
return ;
}
double vp[ 3 ], vp_slice[ 3 ], vnormal[ 3 ];
vnl2vtk( point.GetVnlVector(), vp );
vnl2vtk( normal.GetVnlVector(), vnormal );
//std::cout << "Origin: " << vp[0] <<" "<< vp[1] <<" "<< vp[2] << std::endl;
//std::cout << "Normal: " << vnormal[0] <<" "<< vnormal[1] <<" "<< vnormal[2] << std::endl;
//normally, we would need to transform the surface and cut the transformed surface with the cutter.
//This might be quite slow. Thus, the idea is, to perform an inverse transform of the plane instead.
//@todo It probably does not work for scaling operations yet:scaling operations have to be
//dealed with after the cut is performed by scaling the contour.
vtkLinearTransform * vtktransform = GetDataNode() ->GetVtkTransform();
vtkTransform* world2vtk = vtkTransform::New();
world2vtk->Identity();
world2vtk->Concatenate(vtktransform->GetLinearInverse());
double myscale[3];
world2vtk->GetScale(myscale);
world2vtk->PostMultiply();
world2vtk->Scale(1/myscale[0],1/myscale[1],1/myscale[2]);
world2vtk->TransformPoint( vp, vp );
world2vtk->TransformNormalAtPoint( vp, vnormal, vnormal );
world2vtk->Delete();
// 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];
vtkImage->GetDimensions(dims);
double spac[3];
vtkImage->GetSpacing(spac);
vp_slice[0] = vp[0];
vp_slice[1] = vp[1];
vp_slice[2] = vp[2];
if(fabs(vnormal[0]) > fabs(vnormal[1]) && fabs(vnormal[0]) > fabs(vnormal[2]) )
{
if(fabs(vp_slice[0]/spac[0]) < 0.4)
vp_slice[0] = 0.4*spac[0];
if(fabs(vp_slice[0]/spac[0]) > (dims[0]-1)-0.4)
vp_slice[0] = ((dims[0]-1)-0.4)*spac[0];
vnormal[1] = 0;
vnormal[2] = 0;
}
if(fabs(vnormal[1]) > fabs(vnormal[0]) && fabs(vnormal[1]) > fabs(vnormal[2]) )
{
if(fabs(vp_slice[1]/spac[1]) < 0.4)
vp_slice[1] = 0.4*spac[1];
if(fabs(vp_slice[1]/spac[1]) > (dims[1]-1)-0.4)
vp_slice[1] = ((dims[1]-1)-0.4)*spac[1];
vnormal[0] = 0;
vnormal[2] = 0;
}
if(fabs(vnormal[2]) > fabs(vnormal[1]) && fabs(vnormal[2]) > fabs(vnormal[0]) )
{
if(fabs(vp_slice[2]/spac[2]) < 0.4)
vp_slice[2] = 0.4*spac[2];
if(fabs(vp_slice[2]/spac[2]) > (dims[2]-1)-0.4)
vp_slice[2] = ((dims[2]-1)-0.4)*spac[2];
vnormal[0] = 0;
vnormal[1] = 0;
}
m_Plane->SetOrigin( vp_slice );
m_Plane->SetNormal( vnormal );
vtkPolyData* cuttedPlane;
if(!( (dims[0] == 1 && vnormal[0] != 0) ||
(dims[1] == 1 && vnormal[1] != 0) ||
(dims[2] == 1 && vnormal[2] != 0) ))
{
m_Cutter->SetCutFunction( m_Plane );
m_Cutter->SetInputData( vtkImage );
m_Cutter->GenerateCutScalarsOff();//!
m_Cutter->Update();
cuttedPlane = m_Cutter->GetOutput();
}
else
{
// cutting of a 2D-Volume does not work,
// so we have to build up our own polydata object
cuttedPlane = vtkPolyData::New();
vtkPoints* points = vtkPoints::New();
points->SetNumberOfPoints(vtkImage->GetNumberOfPoints());
for(int i=0; i<vtkImage->GetNumberOfPoints(); i++)
points->SetPoint(i, vtkImage->GetPoint(i));
cuttedPlane->SetPoints(points);
vtkFloatArray* pointdata = vtkFloatArray::New();
int comps = vtkImage->GetPointData()->GetScalars()->GetNumberOfComponents();
pointdata->SetNumberOfComponents(comps);
int tuples = vtkImage->GetPointData()->GetScalars()->GetNumberOfTuples();
pointdata->SetNumberOfTuples(tuples);
for(int i=0; i<tuples; i++)
pointdata->SetTuple(i,vtkImage->GetPointData()->GetScalars()->GetTuple(i));
pointdata->SetName( "vector" );
cuttedPlane->GetPointData()->AddArray(pointdata);
}
if ( cuttedPlane->GetNumberOfPoints() != 0)
{
//
// make sure, that we have point data with more than 1 component (as vectors)
//
vtkPointData * pointData = cuttedPlane->GetPointData();
if ( pointData == NULL )
{
itkWarningMacro( << "no point data associated with cutters result!" );
return ;
}
if ( pointData->GetNumberOfArrays() == 0 )
{
itkWarningMacro( << "point data returned by cutter doesn't have any arrays associated!" );
return ;
}
else if ( pointData->GetArray(0)->GetNumberOfComponents() <= 1)
{
itkWarningMacro( << "number of components <= 1!" );
return;
}
else if ( pointData->GetArrayName( 0 ) == NULL )
{
pointData->GetArray( 0 ) ->SetName( "vector" );
//std::cout << "array name = vectors now" << std::endl;
}
//std::cout << " projecting..."<< std::endl;
//
// constrain the vectors to lie on the plane, which means to remove the vector component,
// which is orthogonal to the plane.
//
vtkIdType numPoints, pointId;
numPoints = cuttedPlane->GetNumberOfPoints();
vtkDataArray* inVectors = cuttedPlane->GetPointData()->GetVectors( "vector" );
assert( inVectors != NULL );
vtkFloatArray* vectorMagnitudes = vtkFloatArray::New();
vectorMagnitudes->SetName("vectorMagnitudes");
vectorMagnitudes->SetNumberOfComponents(1);
vectorMagnitudes->SetNumberOfValues(numPoints);
vectorMagnitudes->SetNumberOfTuples(numPoints);
double inVector[ 3 ], outVector[3], wnormal[3]; //, tmpVector[ 3 ], outVector[ 3 ];
double k = 0.0;
vnl2vtk( normal.GetVnlVector(), wnormal );
vtkMath::Normalize( wnormal );
bool normalizeVecs;
m_DataNode->GetBoolProperty( "NormalizeVecs", normalizeVecs );
for ( pointId = 0; pointId < numPoints; ++pointId )
{
inVectors->GetTuple( pointId, inVector );
if(normalizeVecs)
{
vnl_vector<double> tmp(3);
vtk2vnl(inVector, tmp);
tmp.normalize();
vnl2vtk(tmp, inVector);
}
k = vtkMath::Dot( wnormal, inVector );
// Remove non orthogonal component.
outVector[ 0 ] = inVector[ 0 ] - ( wnormal[ 0 ] * k );
outVector[ 1 ] = inVector[ 1 ] - ( wnormal[ 1 ] * k );
outVector[ 2 ] = inVector[ 2 ] - ( wnormal[ 2 ] * k );
inVectors->SetTuple( pointId, outVector );
// ?? this was set to norm(inVector) before, but outVector made more sense to me
vectorMagnitudes->SetValue( pointId, vtkMath::Norm( outVector ) );
//std::cout << "method old: " << inVector[0] <<", " << inVector[1] << ", "<<inVector[2] << ", method new: " << outVector[0] << ", "<< outVector[1] << ", "<< outVector[2] << std::endl;
}
pointData->AddArray(vectorMagnitudes);
pointData->CopyAllOn();
//pointData->PrintSelf(std::cout, vtkIndent(4));
//std::cout << " ...done!"<< std::endl;
//std::cout << " glyphing..."<< std::endl;
// call glyph2D to generate 2D glyphs for each of the
// vectors
vtkGlyphSource2D* glyphSource = vtkGlyphSource2D::New();
//glyphSource->SetGlyphTypeToDash();
glyphSource->DashOn();
//glyphSource->SetScale( 0.1 );
//glyphSource->SetScale2( .5 );
//glyphSource->SetCenter( 0.5, 0.5, 0.5 );
glyphSource->CrossOff();
//glyphSource->FilledOff();
//glyphSource->Update();
double spacing[3];
vtkImage->GetSpacing(spacing);
double min = spacing[0];
min = min > spacing[1] ? spacing[1] : min;
min = min > spacing[2] ? spacing[2] : min;
float scale = 1;
mitk::FloatProperty::Pointer mitkScaleProp = dynamic_cast<mitk::FloatProperty*>(GetDataNode()->GetProperty("Scale"));
if (mitkScaleProp.IsNotNull())
{
scale = mitkScaleProp->GetValue();
}
vtkMaskedGlyph3D* glyphGenerator = vtkMaskedGlyph3D::New();
glyphGenerator->SetSourceData(glyphSource->GetOutput() );
glyphGenerator->SetInput(cuttedPlane);
glyphGenerator->SetInputArrayToProcess (1, 0,0, vtkDataObject::FIELD_ASSOCIATION_POINTS , "vector");
glyphGenerator->SetVectorModeToUseVector();
glyphGenerator->OrientOn();
glyphGenerator->SetScaleFactor( min*scale );
glyphGenerator->SetUseMaskPoints( true );
glyphGenerator->SetRandomMode( true );
glyphGenerator->SetMaximumNumberOfPoints( 128*128 );
glyphGenerator->Update();
/*
vtkLookupTable* vtkLut = NULL;
mitk::LookupTableProperty::Pointer mitkLutProp = dynamic_cast<mitk::LookupTableProperty*>(GetDataNode()->GetProperty("LookupTable"));
if (mitkLutProp.IsNotNull())
{
vtkLut = mitkLutProp->GetLookupTable()->GetVtkLookupTable();
}
*/
mitk::Color color;
mitk::ColorProperty::Pointer mitkColorProp = dynamic_cast<mitk::ColorProperty*>(GetDataNode()->GetProperty("color"));
if (mitkColorProp.IsNotNull())
{
color = mitkColorProp->GetColor();
}
else
{
color.SetRed(0);
color.SetBlue(1);
color.SetGreen(0);
}
float lwidth = 1;
mitk::FloatProperty::Pointer mitkLWidthProp = dynamic_cast<mitk::FloatProperty*>(GetDataNode()->GetProperty("LineWidth"));
if (mitkLWidthProp.IsNotNull())
{
lwidth = mitkLWidthProp->GetValue();
}
vtkTransform* trafo = vtkTransform::New();
trafo->Identity();
trafo->Concatenate(vtktransform);
trafo->PreMultiply();
double myscale[3];
trafo->GetScale(myscale);
trafo->Scale(1/myscale[0],1/myscale[1],1/myscale[2]);
- this->PaintCells( glyphGenerator->GetOutput(), renderer->GetCurrentWorldGeometry2D(), renderer->GetDisplayGeometry(), trafo, renderer, NULL/*vtkLut*/, color, lwidth, spacing );
+ this->PaintCells( glyphGenerator->GetOutput(), renderer->GetCurrentWorldPlaneGeometry(), renderer->GetDisplayGeometry(), trafo, renderer, NULL/*vtkLut*/, color, lwidth, spacing );
vectorMagnitudes->Delete();
glyphSource->Delete();
glyphGenerator->Delete();
trafo->Delete();
}
else
{
std::cout << " no points cutted!"<< std::endl;
}
//std::cout << "...done!" << std::endl;
}
-void mitk::VectorImageMapper2D::PaintCells( vtkPolyData* glyphs, const Geometry2D* worldGeometry, const DisplayGeometry* displayGeometry, vtkLinearTransform* vtktransform, mitk::BaseRenderer* /*renderer*/, vtkScalarsToColors *lut, mitk::Color color, float lwidth, double *spacing )
+void mitk::VectorImageMapper2D::PaintCells( vtkPolyData* glyphs, const PlaneGeometry* worldGeometry, const DisplayGeometry* displayGeometry, vtkLinearTransform* vtktransform, mitk::BaseRenderer* /*renderer*/, vtkScalarsToColors *lut, mitk::Color color, float lwidth, double *spacing )
{
-
vtkPoints * points = glyphs->GetPoints();
vtkPointData * vpointdata = glyphs->GetPointData();
vtkDataArray* vpointscalars = vpointdata->GetArray("vectorMagnitudes");
//vtkDataArray* vpointpositions = vpointdata->GetArray("pointPositions");
assert(vpointscalars != NULL);
//std::cout << " Scalars range 2d:" << vpointscalars->GetRange()[0] << " " << vpointscalars->GetRange()[0] << std::endl;
Point3D p;
Point2D p2d;
vtkIdList* idList;
vtkCell* cell;
double offset[3];
for (unsigned int i = 0; i < 3; ++i)
{
offset[i] = 0;
}
vtkIdType numCells = glyphs->GetNumberOfCells();
for ( vtkIdType cellId = 0; cellId < numCells; ++cellId )
{
double vp[ 3 ];
cell = glyphs->GetCell( cellId );
idList = cell->GetPointIds();
int numPoints = idList->GetNumberOfIds();
if(numPoints == 1)
{
//take transformation via vtktransform into account
double pos[ 3 ],vp_raster[3];
points->GetPoint( idList->GetId( 0 ), vp );
vp_raster[0] = vtkMath::Round(vp[0]/spacing[0])*spacing[0];
vp_raster[1] = vtkMath::Round(vp[1]/spacing[1])*spacing[1];
vp_raster[2] = vtkMath::Round(vp[2]/spacing[2])*spacing[2];
vtktransform->TransformPoint( vp_raster, pos );
offset[0] = pos[0] - vp[0];
offset[1] = pos[1] - vp[1];
offset[2] = pos[2] - vp[2];
}
else
{
glLineWidth(lwidth);
glBegin ( GL_LINE_LOOP );
for ( int pointNr = 0; pointNr < numPoints ;++pointNr )
{
points->GetPoint( idList->GetId( pointNr ), vp );
vp[0] = vp[0] + offset[0];
vp[1] = vp[1] + offset[1];
vp[2] = vp[2] + offset[2];
double tmp[ 3 ];
vtktransform->TransformPoint( vp,tmp );
vtk2itk( vp, p );
//convert 3D point (in mm) to 2D point on slice (also in mm)
worldGeometry->Map( p, p2d );
//convert point (until now mm and in worldcoordinates) to display coordinates (units )
displayGeometry->WorldToDisplay( p2d, p2d );
if ( lut != NULL )
{
// color each point according to point data
double * color;
if ( vpointscalars != NULL )
{
vpointscalars->GetComponent( pointNr, 0 );
color = lut->GetColor( vpointscalars->GetComponent( idList->GetId( pointNr ), 0 ) );
glColor3f( color[ 0 ], color[ 1 ], color[ 2 ] );
}
}
else
{
glColor3f( color.GetRed(), color.GetGreen(), color.GetBlue() );
}
//std::cout << idList->GetId( pointNr )<< ": " << p2d[0]<< " "<< p2d[1] << std::endl;
//draw the line
glVertex2f( p2d[ 0 ], p2d[ 1 ] );
-
-
-
}
glEnd ();
}
}
}
mitk::VectorImageMapper2D::VectorImageMapper2D()
{
m_LUT = NULL;
m_Plane = vtkPlane::New();
m_Cutter = vtkCutter::New();
m_Cutter->SetCutFunction( m_Plane );
m_Cutter->GenerateValues( 1, 0, 1 );
}
mitk::VectorImageMapper2D::~VectorImageMapper2D()
{
if ( m_LUT != NULL )
m_LUT->Delete();
if ( m_Plane != NULL )
m_Plane->Delete();
if ( m_Cutter != NULL )
m_Cutter->Delete();
}
int mitk::VectorImageMapper2D::GetCurrentTimeStep( mitk::BaseData* data, mitk::BaseRenderer* renderer )
{
//
// get the TimeGeometry of the input object
//
const TimeGeometry * dataTimeGeometry = data->GetUpdatedTimeGeometry();
if ( ( dataTimeGeometry == NULL ) || ( dataTimeGeometry->CountTimeSteps() == 0 ) )
{
itkWarningMacro( << "The given object is missing a mitk::TimeGeometry, or the number of time steps is 0!" );
return 0;
}
//
// get the world time
//
- Geometry2D::ConstPointer worldGeometry = renderer->GetCurrentWorldGeometry2D();
- assert( worldGeometry.IsNotNull() );
- ScalarType time = worldGeometry->GetTimeBounds() [ 0 ];
-
+ ScalarType time = renderer->GetTime();
//
// convert the world time to time steps of the input object
//
int timestep = 0;
if ( time > ScalarTypeNumericTraits::NonpositiveMin() )
timestep = dataTimeGeometry->TimePointToTimeStep( time );
if ( dataTimeGeometry->IsValidTimeStep( timestep ) == false )
{
itkWarningMacro( << timestep << " is not a valid time of the given data object!" );
return 0;
}
return timestep;
}
diff --git a/Modules/MapperExt/mitkVectorImageMapper2D.h b/Modules/MapperExt/mitkVectorImageMapper2D.h
index 59e4816bd5..0d2fe6945a 100644
--- a/Modules/MapperExt/mitkVectorImageMapper2D.h
+++ b/Modules/MapperExt/mitkVectorImageMapper2D.h
@@ -1,94 +1,94 @@
/*===================================================================
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 _MITK_VECTOR_IMAGE_MAPPER_2D__H_
#define _MITK_VECTOR_IMAGE_MAPPER_2D__H_
#include "MitkMapperExtExports.h"
#include "mitkCommon.h"
#include "mitkGLMapper.h"
#include "mitkImage.h"
class vtkLookupTable;
class vtkScalarsToColors;
class vtkImageReslice;
class vtkPolyData;
class vtkGlyph2D;
class vtkPlane;
class vtkCutter;
namespace mitk
{
class BaseRenderer;
-class Geometry2D;
+class PlaneGeometry;
class DisplayGeometry;
class MitkMapperExt_EXPORT VectorImageMapper2D : public GLMapper
{
public:
mitkClassMacro( VectorImageMapper2D, GLMapper );
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
typedef double vtkScalarType;
/**
* @returns the image held by the associated with the mapper or the image
* which has been explicitly set by SetImage(...)
*/
const mitk::Image * GetInput( void );
virtual void Paint( mitk::BaseRenderer * renderer );
/**
* Explicitly set an vector image. This image will be used for
* rendering instead of the image returned by GetData()
*/
itkSetConstObjectMacro( Image, mitk::Image );
/**
* Get the explicitly set image
* @returns NULL if no Image has been set instead of GetData();
*/
itkGetConstObjectMacro( Image, mitk::Image );
- virtual void PaintCells( vtkPolyData* contour, const Geometry2D* worldGeometry, const DisplayGeometry* displayGeometry, vtkLinearTransform* vtktransform, BaseRenderer* renderer, vtkScalarsToColors *lut, mitk::Color color, float lwidth, double *spacing );
+ virtual void PaintCells( vtkPolyData* contour, const PlaneGeometry* worldGeometry, const DisplayGeometry* displayGeometry, vtkLinearTransform* vtktransform, BaseRenderer* renderer, vtkScalarsToColors *lut, mitk::Color color, float lwidth, double *spacing );
protected:
int GetCurrentTimeStep( mitk::BaseData* data, mitk::BaseRenderer* renderer );
VectorImageMapper2D();
virtual ~VectorImageMapper2D();
mitk::Image::ConstPointer m_Image;
vtkLookupTable *m_LUT;
vtkPlane* m_Plane;
vtkCutter* m_Cutter;
};
} // namespace mitk
#endif
diff --git a/Modules/OpenCL/mitkOclImage.cpp b/Modules/OpenCL/mitkOclImage.cpp
index 230c92334f..8095672d89 100644
--- a/Modules/OpenCL/mitkOclImage.cpp
+++ b/Modules/OpenCL/mitkOclImage.cpp
@@ -1,350 +1,350 @@
/*===================================================================
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 "mitkOclImage.h"
#include "mitkImageDataItem.h"
#include "mitkCommon.h"
#include "mitkLogMacros.h"
#include "mitkOclUtils.h"
#include <mitkImageReadAccessor.h>
#include <fstream>
mitk::OclImage::OclImage() : m_gpuImage(NULL), m_context(NULL), m_bufferSize(0), m_gpuModified(false), m_cpuModified(false),
m_Image(NULL), m_dim(0), m_Dims(NULL), m_BpE(1), m_formatSupported(false)
{
}
mitk::OclImage::~OclImage()
{
MITK_INFO << "OclImage Destructor";
//release GMEM Image buffer
if (m_gpuImage) clReleaseMemObject(m_gpuImage);
}
cl_mem mitk::OclImage::CreateGPUImage(unsigned int _wi, unsigned int _he, unsigned int _de,
unsigned int _bpp)
{
MITK_INFO << "CreateGPUImage call with: BPP=" << _bpp;
this->m_Dims = new unsigned int[MAX_DIMS];
m_Dims[0] = _wi;
m_Dims[1] = _he;
m_Dims[2] = _de;
for (unsigned int i=3; i<MAX_DIMS; i++)
m_Dims[i] = 1;
m_bufferSize = _wi * _he * _de;
m_BpE = _bpp;
us::ServiceReference<OclResourceService> ref = GetModuleContext()->GetServiceReference<OclResourceService>();
OclResourceService* resources = GetModuleContext()->GetService<OclResourceService>(ref);
cl_context gpuContext = resources->GetContext();
int clErr;
m_gpuImage = clCreateBuffer( gpuContext, CL_MEM_READ_WRITE, m_bufferSize * m_BpE, NULL, &clErr);
CHECK_OCL_ERR(clErr);
return m_gpuImage;
}
void mitk::OclImage::InitializeByMitkImage(mitk::Image::Pointer _image)
{
this->m_Image = _image;
this->m_cpuModified = true;
this->m_gpuModified = false;
this->m_gpuImage = NULL;
// compute the size of the GMEM buffer
this->m_dim = this->m_Image->GetDimension();
this->m_Dims = this->m_Image->GetDimensions();
MITK_INFO << "Image: " << this->m_Dims[0] <<"x"<< this->m_Dims[1] <<"x"<< this->m_Dims[2];
// get the dimensions
this->m_bufferSize = 1;
for (unsigned int i=0; i<this->m_dim; i++)
{
this->m_bufferSize *= this->m_Dims[i];
}
// multiply by sizeof(PixelType)
this->m_BpE = ( this->m_Image->GetPixelType().GetBpe() / 8);
}
bool mitk::OclImage::IsModified(int _type)
{
if (_type) return m_cpuModified;
else return m_gpuModified;
}
void mitk::OclImage::Modified(int _type)
{
// defines... GPU: 0, CPU: 1
m_cpuModified = _type;
m_gpuModified = !_type;
}
int mitk::OclImage::TransferDataToGPU(cl_command_queue gpuComQueue)
{
cl_int clErr = 0;
// check whether an image present
if (!m_Image->IsInitialized()){
MITK_ERROR("ocl.Image") << "(mitk) Image not initialized!\n";
return -1;
}
// there is a need for copy only if RAM-Data newer then GMEM data
if (m_cpuModified)
{
//check the buffer
if(m_gpuImage == NULL)
{
clErr = this->AllocateGPUImage();
}
if (m_Image->IsInitialized() &&
(clErr == CL_SUCCESS))
{
const size_t origin[3] = {0, 0, 0};
const size_t region[3] = {m_Dims[0], m_Dims[1], m_Dims[2]};
if( this->m_formatSupported )
{
mitk::ImageReadAccessor accessor(m_Image);
clErr = clEnqueueWriteImage( gpuComQueue, m_gpuImage, CL_TRUE, origin, region, 0, 0, accessor.GetData(), 0, NULL, NULL);
}
else
{
MITK_ERROR << "Selected image format currently not supported...";
}
CHECK_OCL_ERR(clErr);
}
m_gpuModified = true;
}
return clErr;
}
cl_int mitk::OclImage::AllocateGPUImage()
{
cl_int clErr = 0;
us::ServiceReference<OclResourceService> ref = GetModuleContext()->GetServiceReference<OclResourceService>();
OclResourceService* resources = GetModuleContext()->GetService<OclResourceService>(ref);
cl_context gpuContext = resources->GetContext();
// initialize both proposed and supported format variables to same value
this->m_proposedFormat = this->ConvertPixelTypeToOCLFormat();
this->m_supportedFormat = this->m_proposedFormat;
// test the current format for HW support
this->m_formatSupported = resources->GetIsFormatSupported( &(this->m_supportedFormat) );
// create an transfer kernel object in case the proposed format is not supported
if( !(this->m_formatSupported) )
{
MITK_ERROR << "Original format not supported on the installed graphics card.";
return -1;
}
// create new buffer
if( this->m_dim > 2)
{
//Create a 3D Image
m_gpuImage = clCreateImage3D(gpuContext, CL_MEM_READ_ONLY, &m_supportedFormat, *(m_Dims), *(m_Dims+1), *(m_Dims+2), 0, 0, NULL, &clErr);
}
else
{
//Create a 2D Image
m_gpuImage = clCreateImage2D(gpuContext, CL_MEM_READ_ONLY, &m_supportedFormat, *(m_Dims), *(m_Dims+1), 0, NULL, &clErr);
}
CHECK_OCL_ERR(clErr);
return clErr;
}
cl_mem mitk::OclImage::GetGPUImage(cl_command_queue gpuComQueue)
{
// clGetMemObjectInfo()
cl_mem_object_type memInfo;
cl_int clErr = 0;
// query image object info only if already initialized
if( this->m_gpuImage )
{
clErr = clGetMemObjectInfo(this->m_gpuImage, CL_MEM_TYPE, sizeof(cl_mem_object_type), &memInfo, NULL );
CHECK_OCL_ERR(clErr);
}
MITK_INFO << "Querying info for object, recieving: " << memInfo;
// test if m_gpuImage CL_MEM_IMAGE_2/3D
// if not, copy buffer to image
if (memInfo == CL_MEM_OBJECT_BUFFER)
{
MITK_WARN << " Passed oclImage is a buffer-object, creating image";
//hold a copy of the buffer gmem pointer
cl_mem tempBuffer = this->m_gpuImage;
const size_t origin[3] = {0, 0, 0};
size_t region[3] = {this->m_Dims[0], this->m_Dims[1], 1};
clErr = this->AllocateGPUImage();
this->m_dim = 3;
//copy last data to the image data
clErr = clEnqueueCopyBufferToImage( gpuComQueue, tempBuffer, m_gpuImage, 0, origin, region, 0, NULL, NULL);
CHECK_OCL_ERR(clErr);
//release pointer
clReleaseMemObject(tempBuffer);
}
return m_gpuImage;
}
void mitk::OclImage::SetPixelType(const cl_image_format *_image)
{
this->m_proposedFormat.image_channel_data_type = _image->image_channel_data_type;
this->m_proposedFormat.image_channel_order = _image->image_channel_order;
}
void* mitk::OclImage::TransferDataToCPU(cl_command_queue gpuComQueue)
{
cl_int clErr = 0;
// if image created on GPU, needs to create mitk::Image
if( m_Image.IsNull() ){
MITK_INFO << "Image not initialized, creating new one.";
m_Image = mitk::Image::New();
}
// check buffersize/image size
char* data = new char[m_bufferSize * m_BpE];
// debug info
oclPrintMemObjectInfo( m_gpuImage );
clErr = clEnqueueReadBuffer( gpuComQueue, m_gpuImage, CL_FALSE, 0, m_bufferSize * m_BpE, data ,0, NULL, NULL);
CHECK_OCL_ERR(clErr);
clFlush( gpuComQueue );
// the cpu data is same as gpu
this->m_gpuModified = false;
return (void*) data;
}
cl_image_format mitk::OclImage::ConvertPixelTypeToOCLFormat()
{
cl_image_format texFormat;
//single channel Gray-Valued Images
texFormat.image_channel_order = CL_R;
MITK_INFO << "Class own value: " << this->m_BpE;
switch ( this->m_BpE )
{
case 1:
texFormat.image_channel_data_type = CL_UNSIGNED_INT8;
MITK_INFO<< "PixelType: UCHAR => CLFormat: [CL_UNORM_INT8, CL_R]";
break;
case 2:
texFormat.image_channel_data_type = CL_SIGNED_INT16;
// texFormat.image_channel_order = CL_R;
MITK_INFO<< "PixelType: SHORT => CLFormat: [CL_SIGNED_INT16, CL_R]";
break;
case 4:
texFormat.image_channel_data_type = CL_FLOAT;
MITK_INFO<< "Choosing CL_FLOAT";
break;
default:
texFormat.image_channel_data_type = CL_UNORM_INT8;
texFormat.image_channel_order = CL_RG;
MITK_INFO<< "Choosing (default) short: 2-Channel UCHAR";
break;
}
return texFormat;
}
int mitk::OclImage::GetDimension(int idx) const
{
if (this->m_dim > idx)
{
return m_Dims[idx];
}
else
{
MITK_WARN << "Trying to access non-existing dimension.";
return 1;
}
}
void mitk::OclImage::SetDimensions(unsigned int* Dims)
{
m_Dims = Dims;
}
void mitk::OclImage::SetDimension(unsigned short dim)
{
m_dim = dim;
}
float mitk::OclImage::GetSpacing(int idx)
{
if (this->m_dim > idx)
{
- const float* imSpacing = m_Image->GetSlicedGeometry()->GetFloatSpacing();
+ const mitk::Vector3D imSpacing = m_Image->GetSlicedGeometry()->GetSpacing();
return imSpacing[idx];
}
else
{
MITK_WARN << "Trying to access non-existing dimension.";
return 1;
}
}
void mitk::OclImage::InitializeMITKImage()
{
this->m_Image = mitk::Image::New();
}
void mitk::OclImage::GetOffset(float* _imOffset) const
{
itk::Vector<float, 3> result2;
result2.Fill(0.0f);
result2 = this->m_Image->GetGeometry()->GetIndexToWorldTransform()->GetOffset();
_imOffset[0] = result2[0];
_imOffset[1] = result2[1];
_imOffset[2] = result2[2];
}
\ No newline at end of file
diff --git a/Modules/PlanarFigure/Algorithms/mitkExtrudePlanarFigureFilter.cpp b/Modules/PlanarFigure/Algorithms/mitkExtrudePlanarFigureFilter.cpp
index 8ada2bdc35..76bf5b8197 100644
--- a/Modules/PlanarFigure/Algorithms/mitkExtrudePlanarFigureFilter.cpp
+++ b/Modules/PlanarFigure/Algorithms/mitkExtrudePlanarFigureFilter.cpp
@@ -1,323 +1,323 @@
/*===================================================================
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 "mitkPlanarFigure.h"
#include <mitkExtrudePlanarFigureFilter.h>
#include <mitkPlaneGeometry.h>
#include <mitkSurface.h>
#include <vtkCellArray.h>
#include <vtkPolyData.h>
#include <vtkPolyDataNormals.h>
#include <vtkPoints.h>
#include <vtkSmartPointer.h>
static mitk::Point2D GetCenterPoint(const mitk::PlanarFigure::PolyLineType& polyLine)
{
mitk::Point2D centerPoint;
centerPoint[0] = 0;
centerPoint[1] = 0;
mitk::PlanarFigure::PolyLineType::const_iterator polyLineEnd = polyLine.end();
for (mitk::PlanarFigure::PolyLineType::const_iterator polyLineIter = polyLine.begin(); polyLineIter != polyLineEnd; ++polyLineIter)
{
centerPoint[0] += static_cast<mitk::Point2D>(*polyLineIter)[0];
centerPoint[1] += static_cast<mitk::Point2D>(*polyLineIter)[1];
}
size_t numPoints = polyLine.size();
centerPoint[0] /= numPoints;
centerPoint[1] /= numPoints;
return centerPoint;
}
static mitk::Point2D GetCenterPoint(mitk::PlanarFigure* planarFigure)
{
mitk::Point2D centerPoint;
centerPoint[0] = 0;
centerPoint[1] = 0;
size_t numPolyLines = planarFigure->GetPolyLinesSize();
for (size_t i = 0; i < numPolyLines; ++i)
{
mitk::Point2D polyLineCenterPoint = GetCenterPoint(planarFigure->GetPolyLine(i));
centerPoint[0] += polyLineCenterPoint[0];
centerPoint[1] += polyLineCenterPoint[1];
}
centerPoint[0] /= numPolyLines;
centerPoint[1] /= numPolyLines;
return centerPoint;
}
static mitk::Vector3D GetBendDirection(const mitk::PlaneGeometry* planeGeometry, const mitk::Point2D& centerPoint2d, const mitk::Vector2D& bendDirection2d)
{
mitk::Point2D point2d = centerPoint2d + bendDirection2d;
mitk::Point3D point3d;
planeGeometry->Map(point2d, point3d);
mitk::Point3D centerPoint3d;
planeGeometry->Map(centerPoint2d, centerPoint3d);
mitk::Vector3D bendDirection3d = point3d - centerPoint3d;
bendDirection3d.Normalize();
return bendDirection3d;
}
mitk::ExtrudePlanarFigureFilter::ExtrudePlanarFigureFilter()
: m_Length(1),
m_NumberOfSegments(1),
m_TwistAngle(0),
m_BendAngle(0),
m_FlipDirection(false),
m_FlipNormals(false)
{
m_BendDirection[0] = 0;
m_BendDirection[1] = 0;
this->SetNumberOfRequiredInputs(1);
this->SetNumberOfRequiredOutputs(1);
this->SetNthOutput(0, this->MakeOutput(0));
}
mitk::ExtrudePlanarFigureFilter::~ExtrudePlanarFigureFilter()
{
}
void mitk::ExtrudePlanarFigureFilter::GenerateData()
{
typedef PlanarFigure::PolyLineType PolyLine;
typedef PolyLine::const_iterator PolyLineConstIter;
if (m_Length <= 0)
mitkThrow() << "Length is not positive!";
if (m_NumberOfSegments == 0)
mitkThrow() << "Number of segments is zero!";
if (m_BendAngle != 0 && m_BendDirection[0] == 0 && m_BendDirection[1] == 0)
mitkThrow() << "Bend direction is zero-length vector!";
PlanarFigure* input = dynamic_cast<PlanarFigure*>(this->GetPrimaryInput());
if (input == NULL)
mitkThrow() << "Primary input is not a planar figure!";
size_t numPolyLines = input->GetPolyLinesSize();
if (numPolyLines == 0)
mitkThrow() << "Primary input does not contain any poly lines!";
- const PlaneGeometry* planeGeometry = dynamic_cast<const PlaneGeometry*>(input->GetGeometry2D());
+ const PlaneGeometry* planeGeometry = dynamic_cast<const PlaneGeometry*>(input->GetPlaneGeometry());
if (planeGeometry == NULL)
mitkThrow() << "Could not get plane geometry from primary input!";
Vector3D planeNormal = planeGeometry->GetNormal();
planeNormal.Normalize();
Point2D centerPoint2d = GetCenterPoint(input);
Point3D centerPoint3d;
planeGeometry->Map(centerPoint2d, centerPoint3d);
Vector3D bendDirection3d = m_BendAngle != 0
? ::GetBendDirection(planeGeometry, centerPoint2d, m_BendDirection)
: Vector3D();
ScalarType radius = m_Length * (360 / m_BendAngle) / (2 * vnl_math::pi);
Vector3D scaledBendDirection3d = bendDirection3d * radius;
Vector3D bendAxis = itk::CrossProduct(planeNormal, bendDirection3d);
bendAxis.Normalize();
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkCellArray> cells = vtkSmartPointer<vtkCellArray>::New();
vtkIdType baseIndex = 0;
for (size_t i = 0; i < numPolyLines; ++i)
{
PolyLine polyLine = input->GetPolyLine(i);
size_t numPoints = polyLine.size();
if (numPoints < 2)
mitkThrow() << "Poly line " << i << " of primary input consists of less than two points!";
std::vector<mitk::Point3D> crossSection;
PolyLineConstIter polyLineEnd = polyLine.end();
for (PolyLineConstIter polyLineIter = polyLine.begin(); polyLineIter != polyLineEnd; ++polyLineIter)
{
Point3D point;
planeGeometry->Map(*polyLineIter, point);
crossSection.push_back(point);
}
ScalarType segmentLength = m_Length / m_NumberOfSegments;
Vector3D translation = planeNormal * segmentLength;
bool bend = std::abs(m_BendAngle) > mitk::eps;
bool twist = std::abs(m_TwistAngle) > mitk::eps;
ScalarType twistAngle = twist
? m_TwistAngle / m_NumberOfSegments * vnl_math::pi / 180
: 0;
ScalarType bendAngle = bend
? m_BendAngle / m_NumberOfSegments * vnl_math::pi / 180
: 0;
if (m_FlipDirection)
{
translation *= -1;
bendAngle *= -1;
}
for (size_t k = 0; k < numPoints; ++k)
points->InsertNextPoint(crossSection[k].GetDataPointer());
for (size_t j = 1; j <= m_NumberOfSegments; ++j)
{
mitk::AffineTransform3D::Pointer transform = mitk::AffineTransform3D::New();
if (bend || twist)
transform->Translate(centerPoint3d.GetVectorFromOrigin(), true);
if (bend)
{
transform->Translate(scaledBendDirection3d, true);
transform->Rotate3D(bendAxis, bendAngle * j, true);
transform->Translate(-scaledBendDirection3d, true);
}
else
{
transform->Translate(translation * j, true);
}
if (twist)
transform->Rotate3D(planeNormal, twistAngle * j, true);
if (bend || twist)
transform->Translate(-centerPoint3d.GetVectorFromOrigin(), true);
for (size_t k = 0; k < numPoints; ++k)
{
mitk::Point3D transformedPoint = transform->TransformPoint(crossSection[k]);
points->InsertNextPoint(transformedPoint.GetDataPointer());
}
}
for (size_t j = 0; j < m_NumberOfSegments; ++j)
{
for (size_t k = 1; k < numPoints; ++k)
{
vtkIdType cell[3];
cell[0] = baseIndex + j * numPoints + (k - 1);
cell[1] = baseIndex + (j + 1) * numPoints + (k - 1);
cell[2] = baseIndex + j * numPoints + k;
cells->InsertNextCell(3, cell);
cell[0] = cell[1];
cell[1] = baseIndex + (j + 1) * numPoints + k;
cells->InsertNextCell(3, cell);
}
if (input->IsClosed() && numPoints > 2)
{
vtkIdType cell[3];
cell[0] = baseIndex + j * numPoints + (numPoints - 1);
cell[1] = baseIndex + (j + 1) * numPoints + (numPoints - 1);
cell[2] = baseIndex + j * numPoints;
cells->InsertNextCell(3, cell);
cell[0] = cell[1];
cell[1] = baseIndex + (j + 1) * numPoints;
cells->InsertNextCell(3, cell);
}
}
baseIndex += points->GetNumberOfPoints();
}
vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New();
polyData->SetPoints(points);
polyData->SetPolys(cells);
vtkSmartPointer<vtkPolyDataNormals> polyDataNormals = vtkSmartPointer<vtkPolyDataNormals>::New();
polyDataNormals->SetFlipNormals(m_FlipNormals);
polyDataNormals->SetInputData(polyData);
polyDataNormals->SplittingOff();
polyDataNormals->Update();
Surface* output = static_cast<Surface*>(this->GetPrimaryOutput());
output->SetVtkPolyData(polyDataNormals->GetOutput());
}
void mitk::ExtrudePlanarFigureFilter::GenerateOutputInformation()
{
}
itk::ProcessObject::DataObjectPointer mitk::ExtrudePlanarFigureFilter::MakeOutput(DataObjectPointerArraySizeType idx)
{
return idx == 0
? Surface::New().GetPointer()
: NULL;
}
itk::ProcessObject::DataObjectPointer mitk::ExtrudePlanarFigureFilter::MakeOutput(const DataObjectIdentifierType& name)
{
return this->IsIndexedOutputName(name)
? this->MakeOutput(this->MakeIndexFromOutputName(name))
: NULL;
}
void mitk::ExtrudePlanarFigureFilter::PrintSelf(std::ostream& os, itk::Indent indent) const
{
Superclass::PrintSelf(os, indent);
os << indent << "Length: " << m_Length << std::endl;
os << indent << "Number of Segments: " << m_NumberOfSegments << std::endl;
os << indent << "Twist Angle: " << m_TwistAngle << std::endl;
os << indent << "Bend Angle: " << m_BendAngle << std::endl;
os << indent << "Bend Direction: " << m_BendDirection << std::endl;
os << indent << "Flip Normals: " << m_FlipNormals << std::endl;
}
void mitk::ExtrudePlanarFigureFilter::SetInput(PlanarFigure* planarFigure)
{
this->SetPrimaryInput(planarFigure);
}
mitk::Surface* mitk::ExtrudePlanarFigureFilter::GetOutput()
{
return static_cast<Surface*>(this->GetPrimaryOutput());
}
diff --git a/Modules/PlanarFigure/DataManagement/mitkPlanarAngle.cpp b/Modules/PlanarFigure/DataManagement/mitkPlanarAngle.cpp
index 4ad9310b33..338f9b7023 100644
--- a/Modules/PlanarFigure/DataManagement/mitkPlanarAngle.cpp
+++ b/Modules/PlanarFigure/DataManagement/mitkPlanarAngle.cpp
@@ -1,171 +1,171 @@
/*===================================================================
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 "mitkPlanarAngle.h"
-#include "mitkGeometry2D.h"
+#include "mitkPlaneGeometry.h"
mitk::PlanarAngle::PlanarAngle()
: FEATURE_ID_ANGLE( this->AddFeature( "Angle", "deg" ) )
{
// Start with two control points
this->ResetNumberOfControlPoints( 2 );
this->SetNumberOfPolyLines(1);
this->SetNumberOfHelperPolyLines(1);
m_HelperPolyLinesToBePainted->InsertElement( 0, false );
}
mitk::PlanarAngle::~PlanarAngle()
{
}
void mitk::PlanarAngle::GeneratePolyLine()
{
this->ClearPolyLines();
for ( unsigned int i=0; i<this->GetNumberOfControlPoints(); i++ )
this->AppendPointToPolyLine(0, this->GetControlPoint(i));
}
void mitk::PlanarAngle::GenerateHelperPolyLine(double mmPerDisplayUnit, unsigned int displayHeight)
{
// Generate helper-poly-line for angle
if ( this->GetNumberOfControlPoints() < 3)
{
m_HelperPolyLinesToBePainted->SetElement(0, false);
return; //We do not need to draw an angle as there are no two arms yet
}
this->ClearHelperPolyLines();
const Point2D centerPoint = this->GetControlPoint( 1 );
const Point2D boundaryPointOne = this->GetControlPoint( 0 );
const Point2D boundaryPointTwo = this->GetControlPoint( 2 );
double radius = centerPoint.EuclideanDistanceTo( boundaryPointOne );
if ( radius > centerPoint.EuclideanDistanceTo( boundaryPointTwo ) )
{
radius = centerPoint.EuclideanDistanceTo( boundaryPointTwo );
}
//Fixed size radius depending on screen size for the angle
double nonScalingRadius = displayHeight * mmPerDisplayUnit * 0.05;
if (nonScalingRadius > radius)
{
m_HelperPolyLinesToBePainted->SetElement(0, false);
return; //if the arc has a radius that is longer than the shortest arm it should not be painted
}
m_HelperPolyLinesToBePainted->SetElement(0, true);
radius = nonScalingRadius;
double angle = this->GetQuantity( FEATURE_ID_ANGLE );
//Determine from which arm the angle should be drawn
Vector2D v0 = boundaryPointOne - centerPoint;
Vector2D v1 = boundaryPointTwo - centerPoint;
Vector2D v2;
v2[0] = 1.0;
v2[1] = 0.0;
v0[0] = v0[0] * cos( 0.001 ) - v0[1] * sin( 0.001 ); //rotate one arm a bit
v0[1] = v0[0] * sin( 0.001 ) + v0[1] * cos( 0.001 );
v0.Normalize();
v1.Normalize();
double testAngle = acos( v0 * v1 );
//if the rotated arm is closer to the other arm than before it is the one from which we start drawing
//else we start drawing from the other arm (we want to draw in the mathematically positive direction)
if( angle > testAngle )
{
v1[0] = v0[0] * cos( -0.001 ) - v0[1] * sin( -0.001 );
v1[1] = v0[0] * sin( -0.001 ) + v0[1] * cos( -0.001 );
//We determine if the arm is mathematically forward or backward
//assuming we rotate between -pi and pi
if ( acos( v0 * v2 ) > acos ( v1 * v2 ))
{
testAngle = acos( v1 * v2 );
}
else
{
testAngle = -acos( v1 * v2 );
}
}
else
{
v0[0] = v1[0] * cos( -0.001 ) - v1[1] * sin( -0.001 );
v0[1] = v1[0] * sin( -0.001 ) + v1[1] * cos( -0.001 );
//We determine if the arm is mathematically forward or backward
//assuming we rotate between -pi and pi
if ( acos( v0 * v2 ) < acos ( v1 * v2 ))
{
testAngle = acos( v1 * v2 );
}
else
{
testAngle = -acos( v1 * v2 );
}
}
// Generate poly-line with 16 segments
for ( int t = 0; t < 16; ++t )
{
double alpha = (double) t * angle / 15.0 + testAngle;
Point2D polyLinePoint;
polyLinePoint[0] = centerPoint[0] + radius * cos( alpha );
polyLinePoint[1] = centerPoint[1] + radius * sin( alpha );
this->AppendPointToHelperPolyLine(0, polyLinePoint);
}
}
void mitk::PlanarAngle::EvaluateFeaturesInternal()
{
if ( this->GetNumberOfControlPoints() < 3 )
{
// Angle not yet complete.
return;
}
// Calculate angle between lines
const Point2D &p0 = this->GetControlPoint( 0 );
const Point2D &p1 = this->GetControlPoint( 1 );
const Point2D &p2 = this->GetControlPoint( 2 );
Vector2D v0 = p1 - p0;
Vector2D v1 = p1 - p2;
v0.Normalize();
v1.Normalize();
double angle = acos( v0 * v1 );
this->SetQuantity( FEATURE_ID_ANGLE, angle );
}
void mitk::PlanarAngle::PrintSelf( std::ostream& os, itk::Indent indent) const
{
Superclass::PrintSelf( os, indent );
}
diff --git a/Modules/PlanarFigure/DataManagement/mitkPlanarAngle.h b/Modules/PlanarFigure/DataManagement/mitkPlanarAngle.h
index ffe49c49bf..9ed5435fed 100644
--- a/Modules/PlanarFigure/DataManagement/mitkPlanarAngle.h
+++ b/Modules/PlanarFigure/DataManagement/mitkPlanarAngle.h
@@ -1,88 +1,88 @@
/*===================================================================
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 _MITK_PLANAR_ANGLE_H_
#define _MITK_PLANAR_ANGLE_H_
#include "mitkPlanarFigure.h"
#include <MitkPlanarFigureExports.h>
namespace mitk
{
-class Geometry2D;
+class PlaneGeometry;
/**
* \brief Implementation of PlanarFigure to display an angle
* through three control points
*/
class MitkPlanarFigure_EXPORT PlanarAngle : public PlanarFigure
{
public:
mitkClassMacro( PlanarAngle, PlanarFigure );
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
public:
// Feature identifiers
const unsigned int FEATURE_ID_ANGLE;
/** \brief Place figure in its minimal configuration (a point at least)
* onto the given 2D geometry.
*
* Must be implemented in sub-classes.
*/
//virtual void Initialize();
/** \brief Angle has 3 control points per definition. */
unsigned int GetMinimumNumberOfControlPoints() const
{
return 3;
}
/** \brief Angle has 3 control points per definition. */
unsigned int GetMaximumNumberOfControlPoints() const
{
return 3;
}
protected:
PlanarAngle();
virtual ~PlanarAngle();
mitkCloneMacro(Self);
/** \brief Generates the poly-line representation of the planar figure. */
virtual void GeneratePolyLine();
/** \brief Generates the poly-lines that should be drawn the same size regardless of zoom.*/
virtual void GenerateHelperPolyLine(double mmPerDisplayUnit, unsigned int displayHeight);
/** \brief Calculates feature quantities of the planar figure. */
virtual void EvaluateFeaturesInternal();
virtual void PrintSelf( std::ostream &os, itk::Indent indent ) const;
private:
};
} // namespace mitk
#endif //_MITK_PLANAR_ANGLE_H_
diff --git a/Modules/PlanarFigure/DataManagement/mitkPlanarArrow.cpp b/Modules/PlanarFigure/DataManagement/mitkPlanarArrow.cpp
index 896807d286..6849893664 100644
--- a/Modules/PlanarFigure/DataManagement/mitkPlanarArrow.cpp
+++ b/Modules/PlanarFigure/DataManagement/mitkPlanarArrow.cpp
@@ -1,117 +1,117 @@
/*===================================================================
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 "mitkPlanarArrow.h"
-#include "mitkGeometry2D.h"
+#include "mitkPlaneGeometry.h"
mitk::PlanarArrow::PlanarArrow()
: FEATURE_ID_LENGTH( this->AddFeature( "Length", "mm" ) )
{
// Directed arrow has two control points
this->ResetNumberOfControlPoints( 2 );
m_ArrowTipScaleFactor = -1.0;
this->SetNumberOfPolyLines( 1 );
this->SetNumberOfHelperPolyLines( 2 );
// Create helper polyline object (for drawing the orthogonal orientation line)
m_HelperPolyLinesToBePainted->InsertElement( 0, false );
m_HelperPolyLinesToBePainted->InsertElement( 1, false );
}
mitk::PlanarArrow::~PlanarArrow()
{
}
void mitk::PlanarArrow::GeneratePolyLine()
{
this->ClearPolyLines();
this->AppendPointToPolyLine(0, this->GetControlPoint(0));
this->AppendPointToPolyLine(0, this->GetControlPoint(1));
}
void mitk::PlanarArrow::GenerateHelperPolyLine(double mmPerDisplayUnit, unsigned int displayHeight)
{
// Generate helper polyline (orientation line orthogonal to first line)
// if the third control point is currently being set
if ( this->GetNumberOfControlPoints() != 2 )
{
m_HelperPolyLinesToBePainted->SetElement( 0, false );
m_HelperPolyLinesToBePainted->SetElement( 1, false );
return;
}
this->ClearHelperPolyLines();
m_HelperPolyLinesToBePainted->SetElement( 0, true );
m_HelperPolyLinesToBePainted->SetElement( 1, true );
//Fixed size depending on screen size for the angle
float scaleFactor = 0.015;
if ( m_ArrowTipScaleFactor > 0.0 )
{
scaleFactor = m_ArrowTipScaleFactor;
}
double nonScalingLength = displayHeight * mmPerDisplayUnit * scaleFactor;
// Calculate arrow peak
const Point2D p1 = this->GetControlPoint( 0 );
const Point2D p2 = this->GetControlPoint( 1 );
Vector2D n1 = p1 - p2;
n1.Normalize();
double degrees = 100.0;
Vector2D temp;
temp[0] = n1[0] * cos(degrees) - n1[1] * sin(degrees);
temp[1] = n1[0] * sin(degrees) + n1[1] * cos(degrees);
Vector2D temp2;
temp2[0] = n1[0] * cos(-degrees) - n1[1] * sin(-degrees);
temp2[1] = n1[0] * sin(-degrees) + n1[1] * cos(-degrees);
this->AppendPointToHelperPolyLine(0, p1);
this->AppendPointToHelperPolyLine(0, p1 - temp * nonScalingLength);
this->AppendPointToHelperPolyLine(1, p1);
this->AppendPointToHelperPolyLine(1, p1 - temp2 * nonScalingLength);
}
void mitk::PlanarArrow::EvaluateFeaturesInternal()
{
// Calculate line length
const Point3D &p0 = this->GetWorldControlPoint( 0 );
const Point3D &p1 = this->GetWorldControlPoint( 1 );
double length = p0.EuclideanDistanceTo( p1 );
this->SetQuantity( FEATURE_ID_LENGTH, length );
}
void mitk::PlanarArrow::PrintSelf( std::ostream& os, itk::Indent indent) const
{
Superclass::PrintSelf( os, indent );
}
void mitk::PlanarArrow::SetArrowTipScaleFactor( float scale )
{
m_ArrowTipScaleFactor = scale;
}
diff --git a/Modules/PlanarFigure/DataManagement/mitkPlanarArrow.h b/Modules/PlanarFigure/DataManagement/mitkPlanarArrow.h
index 62e04bbd28..c0a517da91 100644
--- a/Modules/PlanarFigure/DataManagement/mitkPlanarArrow.h
+++ b/Modules/PlanarFigure/DataManagement/mitkPlanarArrow.h
@@ -1,97 +1,97 @@
/*===================================================================
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 _MITK_PLANAR_ARROW_H_
#define _MITK_PLANAR_ARROW_H_
#include "mitkPlanarFigure.h"
#include <MitkPlanarFigureExports.h>
namespace mitk
{
-class Geometry2D;
+class PlaneGeometry;
/**
* \brief Implementation of PlanarFigure representing an arrow
* through two control points
*/
class MitkPlanarFigure_EXPORT PlanarArrow : public PlanarFigure
{
public:
mitkClassMacro( PlanarArrow, PlanarFigure );
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** \brief Place figure in its minimal configuration (a point at least)
* onto the given 2D geometry.
*
* Must be implemented in sub-classes.
*/
//virtual void Initialize();
/** \brief Line has 2 control points per definition. */
unsigned int GetMinimumNumberOfControlPoints() const
{
return 2;
}
/** \brief Line has 2 control points per definition. */
unsigned int GetMaximumNumberOfControlPoints() const
{
return 2;
}
void SetArrowTipScaleFactor( float scale );
protected:
PlanarArrow();
virtual ~PlanarArrow();
mitkCloneMacro(Self);
/** \brief Generates the poly-line representation of the planar figure. */
virtual void GeneratePolyLine();
/** \brief Generates the poly-lines that should be drawn the same size regardless of zoom.*/
virtual void GenerateHelperPolyLine(double mmPerDisplayUnit, unsigned int displayHeight);
/** \brief Calculates feature quantities of the planar figure. */
virtual void EvaluateFeaturesInternal();
virtual void PrintSelf( std::ostream &os, itk::Indent indent ) const;
// Feature identifiers
const unsigned int FEATURE_ID_LENGTH;
// ScaleFactor defining size of helper-lines in relation to display size
float m_ArrowTipScaleFactor;
private:
};
} // namespace mitk
#endif //_MITK_PLANAR_ARROW_H_
diff --git a/Modules/PlanarFigure/DataManagement/mitkPlanarCircle.cpp b/Modules/PlanarFigure/DataManagement/mitkPlanarCircle.cpp
index ae44fc627d..717df35bef 100644
--- a/Modules/PlanarFigure/DataManagement/mitkPlanarCircle.cpp
+++ b/Modules/PlanarFigure/DataManagement/mitkPlanarCircle.cpp
@@ -1,165 +1,165 @@
/*===================================================================
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 "mitkPlanarCircle.h"
-#include "mitkGeometry2D.h"
+#include "mitkPlaneGeometry.h"
#include "mitkProperties.h"
mitk::PlanarCircle::PlanarCircle()
: FEATURE_ID_RADIUS( this->AddFeature( "Radius", "mm" ) ),
FEATURE_ID_DIAMETER( this->AddFeature( "Diameter", "mm" ) ),
FEATURE_ID_AREA( this->AddFeature( "Area", "mm2" ) ),
m_MinRadius(0),
m_MaxRadius(100),
m_MinMaxRadiusContraintsActive(false)
{
// Circle has two control points
this->ResetNumberOfControlPoints( 2 );
this->SetNumberOfPolyLines( 1 );
this->SetProperty( "closed", mitk::BoolProperty::New(true) );
}
mitk::PlanarCircle::~PlanarCircle()
{
}
bool mitk::PlanarCircle::SetControlPoint( unsigned int index, const Point2D &point, bool /*createIfDoesNotExist*/ )
{
// moving center point
if(index == 0)
{
const Point2D &centerPoint = GetControlPoint( 0 );
Point2D boundaryPoint = GetControlPoint( 1 );
vnl_vector<ScalarType> vec = (point.GetVnlVector() - centerPoint.GetVnlVector());
boundaryPoint[0] += vec[0];
boundaryPoint[1] += vec[1];
PlanarFigure::SetControlPoint( 0, point );
PlanarFigure::SetControlPoint( 1, boundaryPoint );
return true;
}
else if ( index == 1 )
{
PlanarFigure::SetControlPoint( index, point );
return true;
}
return false;
}
mitk::Point2D mitk::PlanarCircle::ApplyControlPointConstraints(unsigned int index, const Point2D &point)
{
- if ( this->GetGeometry2D() == NULL )
+ if ( this->GetPlaneGeometry() == NULL )
{
return point;
}
Point2D indexPoint;
- this->GetGeometry2D()->WorldToIndex( point, indexPoint );
+ this->GetPlaneGeometry()->WorldToIndex( point, indexPoint );
- BoundingBox::BoundsArrayType bounds = this->GetGeometry2D()->GetBounds();
+ BoundingBox::BoundsArrayType bounds = this->GetPlaneGeometry()->GetBounds();
if ( indexPoint[0] < bounds[0] ) { indexPoint[0] = bounds[0]; }
if ( indexPoint[0] > bounds[1] ) { indexPoint[0] = bounds[1]; }
if ( indexPoint[1] < bounds[2] ) { indexPoint[1] = bounds[2]; }
if ( indexPoint[1] > bounds[3] ) { indexPoint[1] = bounds[3]; }
Point2D constrainedPoint;
- this->GetGeometry2D()->IndexToWorld( indexPoint, constrainedPoint );
+ this->GetPlaneGeometry()->IndexToWorld( indexPoint, constrainedPoint );
if(m_MinMaxRadiusContraintsActive)
{
if( index != 0)
{
const Point2D &centerPoint = this->GetControlPoint(0);
double euclideanDinstanceFromCenterToPoint1 = centerPoint.EuclideanDistanceTo(point);
Vector2D vectorProjectedPoint;
vectorProjectedPoint = point - centerPoint;
vectorProjectedPoint.Normalize();
if( euclideanDinstanceFromCenterToPoint1 > m_MaxRadius )
{
vectorProjectedPoint *= m_MaxRadius;
constrainedPoint = centerPoint;
constrainedPoint += vectorProjectedPoint;
}
else if( euclideanDinstanceFromCenterToPoint1 < m_MinRadius )
{
vectorProjectedPoint *= m_MinRadius;
constrainedPoint = centerPoint;
constrainedPoint += vectorProjectedPoint;
}
}
}
return constrainedPoint;
}
void mitk::PlanarCircle::GeneratePolyLine()
{
// TODO: start circle at specified boundary point...
// clear the PolyLine-Contrainer, it will be reconstructed soon enough...
this->ClearPolyLines();
const Point2D &centerPoint = GetControlPoint( 0 );
const Point2D &boundaryPoint = GetControlPoint( 1 );
double radius = centerPoint.EuclideanDistanceTo( boundaryPoint );
// Generate poly-line with 64 segments
for ( int t = 0; t < 64; ++t )
{
double alpha = (double) t * vnl_math::pi / 32.0;
// construct the new polyline point ...
Point2D polyLinePoint;
polyLinePoint[0] = centerPoint[0] + radius * cos( alpha );
polyLinePoint[1] = centerPoint[1] + radius * sin( alpha );
// ... and append it to the PolyLine.
// No extending supported here, so we can set the index of the PolyLineElement to '0'
this->AppendPointToPolyLine(0, polyLinePoint);
}
}
void mitk::PlanarCircle::GenerateHelperPolyLine(double /*mmPerDisplayUnit*/, unsigned int /*displayHeight*/)
{
// A circle does not require a helper object
}
void mitk::PlanarCircle::EvaluateFeaturesInternal()
{
// Calculate circle radius and area
const Point3D &p0 = this->GetWorldControlPoint( 0 );
const Point3D &p1 = this->GetWorldControlPoint( 1 );
double radius = p0.EuclideanDistanceTo( p1 );
double area = vnl_math::pi * radius * radius;
this->SetQuantity( FEATURE_ID_RADIUS, radius );
this->SetQuantity( FEATURE_ID_DIAMETER, 2*radius );
this->SetQuantity( FEATURE_ID_AREA, area );
}
void mitk::PlanarCircle::PrintSelf( std::ostream& os, itk::Indent indent) const
{
Superclass::PrintSelf( os, indent );
}
diff --git a/Modules/PlanarFigure/DataManagement/mitkPlanarCircle.h b/Modules/PlanarFigure/DataManagement/mitkPlanarCircle.h
index 2e6e9b124e..bea636e3e6 100644
--- a/Modules/PlanarFigure/DataManagement/mitkPlanarCircle.h
+++ b/Modules/PlanarFigure/DataManagement/mitkPlanarCircle.h
@@ -1,135 +1,135 @@
/*===================================================================
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 _MITK_PLANAR_CIRCLE_H_
#define _MITK_PLANAR_CIRCLE_H_
#include "mitkPlanarFigure.h"
#include <MitkPlanarFigureExports.h>
namespace mitk
{
-class Geometry2D;
+class PlaneGeometry;
/**
* \brief Implementation of PlanarFigure representing a circle
* through two control points
*/
class MitkPlanarFigure_EXPORT PlanarCircle : public PlanarFigure
{
public:
mitkClassMacro( PlanarCircle, PlanarFigure );
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** \brief Place figure in its minimal configuration (a point at least)
* onto the given 2D geometry.
*
* Must be implemented in sub-classes.
*/
//virtual void Initialize();
bool SetControlPoint( unsigned int index, const Point2D &point, bool createIfDoesNotExist = false );
/** \brief Circle has 2 control points per definition. */
unsigned int GetMinimumNumberOfControlPoints() const
{
return 2;
}
/** \brief Circle has 2 control points per definition. */
unsigned int GetMaximumNumberOfControlPoints() const
{
return 2;
}
/** \brief Sets the minimum radius
*/
void SetMinimumRadius( double radius )
{
m_MinRadius = radius;
}
/** \brief Gets the minimum radius
*/
double GetMinimumRadius()
{
return m_MinRadius;
}
/** \brief Sets the maximum radius
*/
void SetMaximumRadius( double radius )
{
m_MaxRadius = radius;
}
/** \brief Gets the minimum radius
*/
double GetMaximumRadius()
{
return m_MaxRadius;
}
void ActivateMinMaxRadiusContstraints( bool active )
{
m_MinMaxRadiusContraintsActive = active;
}
protected:
PlanarCircle();
virtual ~PlanarCircle();
mitkCloneMacro(Self);
/** \brief Generates the poly-line representation of the planar figure. */
virtual void GeneratePolyLine();
/** \brief Generates the poly-lines that should be drawn the same size regardless of zoom.*/
virtual void GenerateHelperPolyLine(double mmPerDisplayUnit, unsigned int displayHeight);
/** \brief Spatially constrain control points of second (orthogonal) line */
virtual Point2D ApplyControlPointConstraints( unsigned int index, const Point2D& point );
/** \brief Calculates feature quantities of the planar figure. */
virtual void EvaluateFeaturesInternal();
virtual void PrintSelf( std::ostream &os, itk::Indent indent ) const;
// Feature identifiers
const unsigned int FEATURE_ID_RADIUS;
const unsigned int FEATURE_ID_DIAMETER;
const unsigned int FEATURE_ID_AREA;
//Member variables:
double m_MinRadius;
double m_MaxRadius;
bool m_MinMaxRadiusContraintsActive;
private:
};
} // namespace mitk
#endif //_MITK_PLANAR_CIRCLE_H_
diff --git a/Modules/PlanarFigure/DataManagement/mitkPlanarCross.cpp b/Modules/PlanarFigure/DataManagement/mitkPlanarCross.cpp
index 5f202fc289..98045a3501 100644
--- a/Modules/PlanarFigure/DataManagement/mitkPlanarCross.cpp
+++ b/Modules/PlanarFigure/DataManagement/mitkPlanarCross.cpp
@@ -1,344 +1,344 @@
/*===================================================================
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 "mitkPlanarCross.h"
-#include "mitkGeometry2D.h"
+#include "mitkPlaneGeometry.h"
#include "mitkProperties.h"
mitk::PlanarCross::PlanarCross()
: FEATURE_ID_LONGESTDIAMETER( this->AddFeature( "Longest Axis", "mm" ) ),
FEATURE_ID_SHORTAXISDIAMETER( this->AddFeature( "Short Axis", "mm" ) )
{
// Cross has two control points at the beginning
this->ResetNumberOfControlPoints( 2 );
// Create property for SingleLineMode (default: false)
this->SetProperty( "SingleLineMode", mitk::BoolProperty::New( false ) );
// Create helper polyline object (for drawing the orthogonal orientation line)
this->SetNumberOfHelperPolyLines( 1 );
m_HelperPolyLinesToBePainted->InsertElement( 0, false );
}
mitk::PlanarCross::~PlanarCross()
{
}
void mitk::PlanarCross::SetSingleLineMode( bool singleLineMode )
{
this->SetProperty( "SingleLineMode", mitk::BoolProperty::New( singleLineMode ) );
this->Modified();
}
bool mitk::PlanarCross::GetSingleLineMode() const
{
mitk::BoolProperty* singleLineMode = dynamic_cast< mitk::BoolProperty* >(
this->GetProperty( "SingleLineMode" ).GetPointer() );
if ( singleLineMode != NULL )
{
return singleLineMode->GetValue();
}
return false;
}
bool mitk::PlanarCross::ResetOnPointSelect()
{
if ( this->GetSingleLineMode() )
{
// In single line mode --> nothing to reset
return false;
}
switch ( m_SelectedControlPoint )
{
default:
// Nothing selected --> nothing to reset
return false;
case 0:
{
// Control point 0 selected: exchange points 0 and 1
Point2D tmpPoint = this->GetControlPoint( 0 );
this->SetControlPoint( 0, this->GetControlPoint( 1 ) );
this->SetControlPoint( 1, tmpPoint );
// FALLS THROUGH!
}
case 1:
{
// Control point 0 or 1 selected: reset number of control points to two
this->ResetNumberOfControlPoints( 2 );
this->SelectControlPoint( 1 );
return true;
}
case 2:
{
// Control point 2 selected: replace point 0 with point 3 and point 1 with point 2
this->SetControlPoint( 0, this->GetControlPoint( 3 ) );
this->SetControlPoint( 1, this->GetControlPoint( 2 ) );
// Adjust selected control point, reset number of control points to two
this->ResetNumberOfControlPoints( 2 );
this->SelectControlPoint( 1 );
return true;
}
case 3:
{
// Control point 3 selected: replace point 0 with point 2 and point 1 with point 3
this->SetControlPoint( 0, this->GetControlPoint( 2 ) );
this->SetControlPoint( 1, this->GetControlPoint( 3 ) );
// Adjust selected control point, reset number of control points to two
this->ResetNumberOfControlPoints( 2 );
this->SelectControlPoint( 1 );
return true;
}
}
}
unsigned int mitk::PlanarCross::GetNumberOfFeatures() const
{
if ( this->GetSingleLineMode() || (this->GetNumberOfControlPoints() < 4) )
{
return 1;
}
else
{
return 2;
}
}
mitk::Point2D mitk::PlanarCross::ApplyControlPointConstraints( unsigned int index, const Point2D& point )
{
// Apply spatial constraints from superclass and from this class until the resulting constrained
// point converges. Although not an optimal implementation, this iterative approach
// helps to respect both constraints from the superclass and from this class. Without this,
// situations may occur where control points are constrained by the superclass, but again
// moved out of the superclass bounds by the subclass, or vice versa.
unsigned int count = 0; // ensures stop of approach if point does not converge in reasonable time
Point2D confinedPoint = point;
Point2D superclassConfinedPoint;
do
{
superclassConfinedPoint = Superclass::ApplyControlPointConstraints( index, confinedPoint );
confinedPoint = this->InternalApplyControlPointConstraints( index, superclassConfinedPoint );
++count;
} while ( (confinedPoint.EuclideanDistanceTo( superclassConfinedPoint ) > mitk::eps)
&& (count < 32) );
return confinedPoint;
}
mitk::Point2D mitk::PlanarCross::InternalApplyControlPointConstraints( unsigned int index, const Point2D& point )
{
// Apply constraints depending on current interaction state
switch ( index )
{
case 2:
{
// Check if 3rd control point is outside of the range (2D area) defined by the first
// line (via the first two control points); if it is outside, clip it to the bounds
const Point2D p1 = this->GetControlPoint( 0 );
const Point2D p2 = this->GetControlPoint( 1 );
Vector2D n1 = p2 - p1;
n1.Normalize();
Vector2D v1 = point - p1;
double dotProduct = n1 * v1;
Point2D crossPoint = p1 + n1 * dotProduct;;
Vector2D crossVector = point - crossPoint;
if ( dotProduct < 0.0 )
{
// Out-of-bounds on the left: clip point to left boundary
return (p1 + crossVector);
}
else if ( dotProduct > p2.EuclideanDistanceTo( p1 ) )
{
// Out-of-bounds on the right: clip point to right boundary
return (p2 + crossVector);
}
else
{
// Pass back original point
return point;
}
}
case 3:
{
// Constrain 4th control point so that with the 3rd control point it forms
// a line orthogonal to the first line (constraint 1); the 4th control point
// must lie on the opposite side of the line defined by the first two control
// points than the 3rd control point (constraint 2)
const Point2D p1 = this->GetControlPoint( 0 );
const Point2D p2 = this->GetControlPoint( 1 );
const Point2D p3 = this->GetControlPoint( 2 );
// Calculate distance of original point from orthogonal line the corrected
// point should lie on to project the point onto this line
Vector2D n1 = p2 - p1;
n1.Normalize();
Vector2D v1 = point - p3;
double dotProduct1 = n1 * v1;
Point2D pointOnLine = point - n1 * dotProduct1;
// Project new point onto line [p1, p2]
Vector2D v2 = pointOnLine - p1;
double dotProduct2 = n1 * v2;
Point2D crossingPoint = p1 + n1 * dotProduct2;
// Determine whether the projected point on the line, or the crossing point should be
// used (according to the second constraint in the comment above)
if ( (pointOnLine.SquaredEuclideanDistanceTo( p3 ) > crossingPoint.SquaredEuclideanDistanceTo( p3 ))
&& (pointOnLine.SquaredEuclideanDistanceTo( p3 ) > pointOnLine.SquaredEuclideanDistanceTo( crossingPoint )) )
{
return pointOnLine;
}
else
{
return crossingPoint;
}
}
default:
return point;
}
}
void mitk::PlanarCross::GeneratePolyLine()
{
this->SetNumberOfPolyLines(1);
this->ClearPolyLines();
if (this->GetNumberOfControlPoints() > 2)
this->SetNumberOfPolyLines( 2 );
for (unsigned int i = 0; i < this->GetNumberOfControlPoints(); ++i)
{
if (i < 2)
this->AppendPointToPolyLine(0, this->GetControlPoint(i));
if (i > 1)
this->AppendPointToPolyLine(1, this->GetControlPoint(i));
}
}
void mitk::PlanarCross::GenerateHelperPolyLine(double /*mmPerDisplayUnit*/, unsigned int /*displayHeight*/)
{
// Generate helper polyline (orientation line orthogonal to first line)
// if the third control point is currently being set
if ( this->GetNumberOfControlPoints() != 3 )
{
m_HelperPolyLinesToBePainted->SetElement( 0, false );
return;
}
m_HelperPolyLinesToBePainted->SetElement( 0, true );
this->ClearHelperPolyLines();
// Calculate cross point of first line (p1 to p2) and orthogonal line through
// the third control point (p3)
const Point2D p1 = this->GetControlPoint( 0 );
const Point2D p2 = this->GetControlPoint( 1 );
const Point2D p3 = this->GetControlPoint( 2 );
Vector2D n1 = p2 - p1;
n1.Normalize();
Vector2D v1 = p3 - p1;
Point2D crossPoint = p1 + n1 * (n1 * v1);
Vector2D v2 = crossPoint - p3;
if ( v2.GetNorm() < 1.0 )
{
// If third point is on the first line, draw orthogonal "infinite" line
// through cross point on line
Vector2D v0;
v0[0] = n1[1];
v0[1] = -n1[0];
this->AppendPointToHelperPolyLine(0, p3 - v0 * 10000.0);
this->AppendPointToHelperPolyLine(0, p3 + v0 * 10000.0);
}
else
{
// Else, draw orthogonal line starting from third point and crossing the
// first line, open-ended only on the other side
this->AppendPointToHelperPolyLine(0, p3);
this->AppendPointToHelperPolyLine(0, p3 + v2 * 10000.0);
}
}
void mitk::PlanarCross::EvaluateFeaturesInternal()
{
// Calculate length of first line
const Point3D &p0 = this->GetWorldControlPoint( 0 );
const Point3D &p1 = this->GetWorldControlPoint( 1 );
double l1 = p0.EuclideanDistanceTo( p1 );
// Calculate length of second line
double l2 = 0.0;
if ( !this->GetSingleLineMode() && (this->GetNumberOfControlPoints() > 3) )
{
const Point3D &p2 = this->GetWorldControlPoint( 2 );
const Point3D &p3 = this->GetWorldControlPoint( 3 );
l2 = p2.EuclideanDistanceTo( p3 );
}
double longestDiameter;
double shortAxisDiameter;
if ( l1 > l2 )
{
longestDiameter = l1;
shortAxisDiameter = l2;
}
else
{
longestDiameter = l2;
shortAxisDiameter = l1;
}
this->SetQuantity( FEATURE_ID_LONGESTDIAMETER, longestDiameter );
this->SetQuantity( FEATURE_ID_SHORTAXISDIAMETER, shortAxisDiameter );
}
void mitk::PlanarCross::PrintSelf( std::ostream& os, itk::Indent indent) const
{
Superclass::PrintSelf( os, indent );
}
diff --git a/Modules/PlanarFigure/DataManagement/mitkPlanarCross.h b/Modules/PlanarFigure/DataManagement/mitkPlanarCross.h
index 499f08d213..217ed8c5ac 100644
--- a/Modules/PlanarFigure/DataManagement/mitkPlanarCross.h
+++ b/Modules/PlanarFigure/DataManagement/mitkPlanarCross.h
@@ -1,132 +1,132 @@
/*===================================================================
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 _MITK_PLANAR_CROSS_H_
#define _MITK_PLANAR_CROSS_H_
#include "mitkPlanarFigure.h"
#include <MitkPlanarFigureExports.h>
namespace mitk
{
-class Geometry2D;
+class PlaneGeometry;
/**
* \brief Implementation of PlanarFigure modeling a cross with two orthogonal lines
* on a plane.
*
* The cross consists of two two orthogonal lines, which are defined by four control points
* lying on a plane. The two control points of the first line are freely placable within
* the bounds of the underlying 2D geometry, while the two control points of the second line
* are ensured to meet the following constraints:
*
* 1.) The lines must be orthogonal to each other
* 2.) The second line must lie within the 2D area defined by the first line
* 3.) The two lines must intersect (at least with their boundaries)
*
* When placing the second line interactively, a graphical helper polyline is provided to the
* user to indicate the position and orthogonal orientation of the line if it would be placed
* at the current mouse position.
*
* When modifying one of the lines by interactively moving its control points, the respective
* other line is deleted and the user is prompted to draw it again.
*
* The class provide a special mode for drawing single lines (SingleLineModeOn/Off); in this
* case, interaction stops after the first line has been placed.
*
* The class provides the lengths of both lines via the "feature" interface, ordered by size.
*
* \sa PlanarFigureMapper2D
*/
class MitkPlanarFigure_EXPORT PlanarCross : public PlanarFigure
{
public:
mitkClassMacro( PlanarCross, PlanarFigure );
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** \brief Indicates whether the PlanarFigure shall represent only a single line instead of an
* orthogonal cross. */
void SetSingleLineMode( bool singleLineMode );
/** \brief Indicates whether the PlanarFigure shall represent only a single line instead of an
* orthogonal cross. */
bool GetSingleLineMode() const;
/** \brief Indicates whether the PlanarFigure shall represent only a single line instead of an
* orthogonal cross. */
itkBooleanMacro( SingleLineMode ); // No need to reimplement; calls SetSingleLineMode()
/** \brief PlanarCross has either two or four control points, depending on the operation mode. */
unsigned int GetMinimumNumberOfControlPoints() const
{
return this->GetSingleLineMode() ? 2 : 4;
}
/** \brief PlanarCross has either two or four control points, depending on the operation mode. */
unsigned int GetMaximumNumberOfControlPoints() const
{
return this->GetSingleLineMode() ? 2 : 4;
}
/** \brief The cross shall be reset to a single line when a control point is selected. */
virtual bool ResetOnPointSelect();
/** \brief Returns the number of features available for this PlanarCross (1 or 2). */
virtual unsigned int GetNumberOfFeatures() const;
protected:
PlanarCross();
virtual ~PlanarCross();
mitkCloneMacro(Self);
/** \brief Spatially constrain control points of second (orthogonal) line */
virtual Point2D ApplyControlPointConstraints( unsigned int index, const Point2D& point );
/** \brief Generates the poly-line representation of the planar figure. */
virtual void GeneratePolyLine();
/** \brief Generates the poly-lines that should be drawn the same size regardless of zoom.*/
virtual void GenerateHelperPolyLine(double mmPerDisplayUnit, unsigned int displayHeight);
/** \brief Calculates feature quantities of the planar figure. */
virtual void EvaluateFeaturesInternal();
virtual void PrintSelf( std::ostream &os, itk::Indent indent ) const;
// Feature identifiers
const unsigned int FEATURE_ID_LONGESTDIAMETER;
const unsigned int FEATURE_ID_SHORTAXISDIAMETER;
private:
/** Internal method for applying spatial constraints. */
virtual Point2D InternalApplyControlPointConstraints( unsigned int index, const Point2D& point );
};
} // namespace mitk
#endif //_MITK_PLANAR_CROSS_H_
diff --git a/Modules/PlanarFigure/DataManagement/mitkPlanarEllipse.cpp b/Modules/PlanarFigure/DataManagement/mitkPlanarEllipse.cpp
index 730ada4928..49ddb0f02d 100644
--- a/Modules/PlanarFigure/DataManagement/mitkPlanarEllipse.cpp
+++ b/Modules/PlanarFigure/DataManagement/mitkPlanarEllipse.cpp
@@ -1,280 +1,280 @@
/*===================================================================
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 <algorithm>
#include "mitkPlanarEllipse.h"
-#include "mitkGeometry2D.h"
+#include "mitkPlaneGeometry.h"
#include "mitkProperties.h"
#include <algorithm>
mitk::PlanarEllipse::PlanarEllipse()
: FEATURE_ID_MAJOR_AXIS(Superclass::AddFeature("Major Axis", "mm")),
FEATURE_ID_MINOR_AXIS(Superclass::AddFeature("Minor Axis", "mm")),
m_MinRadius(0),
m_MaxRadius(100),
m_MinMaxRadiusContraintsActive(false),
m_TreatAsCircle(true)
{
// Ellipse has three control points
this->ResetNumberOfControlPoints( 4 );
this->SetNumberOfPolyLines( 2 );
this->SetProperty( "closed", mitk::BoolProperty::New(true) );
}
mitk::PlanarEllipse::~PlanarEllipse()
{
}
bool mitk::PlanarEllipse::SetControlPoint( unsigned int index, const Point2D &point, bool createIfDoesNotExist )
{
if(index == 0) // moving center point and control points accordingly
{
const Point2D &centerPoint = GetControlPoint( 0 );
Point2D boundaryPoint1 = GetControlPoint( 1 );
Point2D boundaryPoint2 = GetControlPoint( 2 );
Point2D boundaryPoint3 = GetControlPoint( 3 );
vnl_vector<ScalarType> vec = (point.GetVnlVector() - centerPoint.GetVnlVector());
boundaryPoint1[0] += vec[0];
boundaryPoint1[1] += vec[1];
boundaryPoint2[0] += vec[0];
boundaryPoint2[1] += vec[1];
boundaryPoint3[0] += vec[0];
boundaryPoint3[1] += vec[1];
PlanarFigure::SetControlPoint( 0, point, createIfDoesNotExist );
PlanarFigure::SetControlPoint( 1, boundaryPoint1, createIfDoesNotExist );
PlanarFigure::SetControlPoint( 2, boundaryPoint2, createIfDoesNotExist );
PlanarFigure::SetControlPoint( 3, boundaryPoint3, createIfDoesNotExist );
return true;
}
else if (index < 3)
{
PlanarFigure::SetControlPoint( index, point, createIfDoesNotExist );
int otherIndex = index+1;
if (otherIndex > 2)
otherIndex = 1;
const Point2D &centerPoint = GetControlPoint( 0 );
Point2D otherPoint = GetControlPoint( otherIndex );
Point2D point3 = GetControlPoint( 3 );
Vector2D vec1 = point - centerPoint;
Vector2D vec2;
if (index == 1 && m_TreatAsCircle )
{
float x = vec1[0];
vec2[0] = vec1[1];
vec2[1] = x;
if (index==1)
vec2[0] *= -1;
else
vec2[1] *= -1;
otherPoint = centerPoint+vec2;
PlanarFigure::SetControlPoint( otherIndex, otherPoint, createIfDoesNotExist );
float r = centerPoint.EuclideanDistanceTo(otherPoint);
// adjust additional third control point
Point2D p3 = this->GetControlPoint(3);
Vector2D vec3;
vec3[0] = p3[0]-centerPoint[0];
vec3[1] = p3[1]-centerPoint[1];
if (vec3[0]!=0 || vec3[1]!=0)
{
vec3.Normalize();
vec3 *= r;
}
else
{
vec3[0] = r;
vec3[1] = 0;
}
point3 = centerPoint + vec3;
PlanarFigure::SetControlPoint( 3, point3, createIfDoesNotExist );
}
else if ( vec1.GetNorm() > 0 )
{
float r = centerPoint.EuclideanDistanceTo(otherPoint);
float x = vec1[0];
vec2[0] = vec1[1];
vec2[1] = x;
if (index==1)
vec2[0] *= -1;
else
vec2[1] *= -1;
vec2.Normalize(); vec2 *= r;
if ( vec2.GetNorm() > 0 )
{
otherPoint = centerPoint+vec2;
PlanarFigure::SetControlPoint( otherIndex, otherPoint, createIfDoesNotExist );
}
// adjust third control point
Vector2D vec3 = point3 - centerPoint; vec3.Normalize();
double r1 = centerPoint.EuclideanDistanceTo( GetControlPoint( 1 ) );
double r2 = centerPoint.EuclideanDistanceTo( GetControlPoint( 2 ) );
Point2D newPoint = centerPoint + vec3*std::max(r1, r2);
PlanarFigure::SetControlPoint( 3, newPoint, createIfDoesNotExist );
m_TreatAsCircle = false;
}
return true;
}
else if (index == 3)
{
Point2D centerPoint = GetControlPoint( 0 );
Vector2D vec3 = point - centerPoint; vec3.Normalize();
double r1 = centerPoint.EuclideanDistanceTo( GetControlPoint( 1 ) );
double r2 = centerPoint.EuclideanDistanceTo( GetControlPoint( 2 ) );
Point2D newPoint = centerPoint + vec3*std::max(r1, r2);
PlanarFigure::SetControlPoint( index, newPoint, createIfDoesNotExist );
m_TreatAsCircle = false;
return true;
}
return false;
}
void mitk::PlanarEllipse::PlaceFigure( const mitk::Point2D &point )
{
PlanarFigure::PlaceFigure( point );
m_SelectedControlPoint = 1;
}
mitk::Point2D mitk::PlanarEllipse::ApplyControlPointConstraints(unsigned int index, const Point2D &point)
{
return point;
Point2D indexPoint;
- this->GetGeometry2D()->WorldToIndex( point, indexPoint );
+ this->GetPlaneGeometry()->WorldToIndex( point, indexPoint );
- BoundingBox::BoundsArrayType bounds = this->GetGeometry2D()->GetBounds();
+ BoundingBox::BoundsArrayType bounds = this->GetPlaneGeometry()->GetBounds();
if ( indexPoint[0] < bounds[0] ) { indexPoint[0] = bounds[0]; }
if ( indexPoint[0] > bounds[1] ) { indexPoint[0] = bounds[1]; }
if ( indexPoint[1] < bounds[2] ) { indexPoint[1] = bounds[2]; }
if ( indexPoint[1] > bounds[3] ) { indexPoint[1] = bounds[3]; }
Point2D constrainedPoint;
- this->GetGeometry2D()->IndexToWorld( indexPoint, constrainedPoint );
+ this->GetPlaneGeometry()->IndexToWorld( indexPoint, constrainedPoint );
if(m_MinMaxRadiusContraintsActive)
{
if( index != 0)
{
const Point2D &centerPoint = this->GetControlPoint(0);
double euclideanDinstanceFromCenterToPoint1 = centerPoint.EuclideanDistanceTo(point);
Vector2D vectorProjectedPoint;
vectorProjectedPoint = point - centerPoint;
vectorProjectedPoint.Normalize();
if( euclideanDinstanceFromCenterToPoint1 > m_MaxRadius )
{
vectorProjectedPoint *= m_MaxRadius;
constrainedPoint = centerPoint;
constrainedPoint += vectorProjectedPoint;
}
else if( euclideanDinstanceFromCenterToPoint1 < m_MinRadius )
{
vectorProjectedPoint *= m_MinRadius;
constrainedPoint = centerPoint;
constrainedPoint += vectorProjectedPoint;
}
}
}
return constrainedPoint;
}
void mitk::PlanarEllipse::GeneratePolyLine()
{
// clear the PolyLine-Contrainer, it will be reconstructed soon enough...
this->ClearPolyLines();
const Point2D &centerPoint = GetControlPoint( 0 );
const Point2D &boundaryPoint1 = GetControlPoint( 1 );
const Point2D &boundaryPoint2 = GetControlPoint( 2 );
Vector2D dir = boundaryPoint1 - centerPoint; dir.Normalize();
vnl_matrix_fixed<float, 2, 2> rot;
// differentiate between clockwise and counterclockwise rotation
int start = 0;
int end = 64;
if (dir[1]<0)
{
dir[0] = -dir[0];
start = -32;
end = 32;
}
// construct rotation matrix to align ellipse with control point vector
rot[0][0] = dir[0];
rot[1][1] = rot[0][0];
rot[1][0] = sin(acos(rot[0][0]));
rot[0][1] = -rot[1][0];
double radius1 = centerPoint.EuclideanDistanceTo( boundaryPoint1 );
double radius2 = centerPoint.EuclideanDistanceTo( boundaryPoint2 );
// Generate poly-line with 64 segments
for ( int t = start; t < end; ++t )
{
double alpha = (double) t * vnl_math::pi / 32.0;
// construct the new polyline point ...
vnl_vector_fixed< float, 2 > vec;
vec[0] = radius1 * cos( alpha );
vec[1] = radius2 * sin( alpha );
vec = rot*vec;
Point2D polyLinePoint;
polyLinePoint[0] = centerPoint[0] + vec[0];
polyLinePoint[1] = centerPoint[1] + vec[1];
// ... and append it to the PolyLine.
// No extending supported here, so we can set the index of the PolyLineElement to '0'
this->AppendPointToPolyLine(0, polyLinePoint);
}
this->AppendPointToPolyLine(1, centerPoint);
this->AppendPointToPolyLine(1, this->GetControlPoint(3));
}
void mitk::PlanarEllipse::GenerateHelperPolyLine(double /*mmPerDisplayUnit*/, unsigned int /*displayHeight*/)
{
// A circle does not require a helper object
}
void mitk::PlanarEllipse::EvaluateFeaturesInternal()
{
Point2D centerPoint = this->GetControlPoint(0);
this->SetQuantity(FEATURE_ID_MAJOR_AXIS, 2 * centerPoint.EuclideanDistanceTo(this->GetControlPoint(1)));
this->SetQuantity(FEATURE_ID_MINOR_AXIS, 2 * centerPoint.EuclideanDistanceTo(this->GetControlPoint(2)));
}
void mitk::PlanarEllipse::PrintSelf( std::ostream& os, itk::Indent indent) const
{
Superclass::PrintSelf( os, indent );
}
diff --git a/Modules/PlanarFigure/DataManagement/mitkPlanarEllipse.h b/Modules/PlanarFigure/DataManagement/mitkPlanarEllipse.h
index 88c033c55c..ea900bf835 100644
--- a/Modules/PlanarFigure/DataManagement/mitkPlanarEllipse.h
+++ b/Modules/PlanarFigure/DataManagement/mitkPlanarEllipse.h
@@ -1,140 +1,140 @@
/*===================================================================
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 _MITK_PLANAR_ELLIPSE_H_
#define _MITK_PLANAR_ELLIPSE_H_
#include "mitkPlanarFigure.h"
#include <MitkPlanarFigureExports.h>
namespace mitk
{
-class Geometry2D;
+class PlaneGeometry;
/**
* \brief Implementation of PlanarFigure representing a circle
* through two control points
*/
class MitkPlanarFigure_EXPORT PlanarEllipse : public PlanarFigure
{
public:
mitkClassMacro( PlanarEllipse, PlanarFigure )
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** \brief Place figure in its minimal configuration (a point at least)
* onto the given 2D geometry.
*
* Must be implemented in sub-classes.
*/
virtual void PlaceFigure( const Point2D &point );
bool SetControlPoint( unsigned int index, const Point2D &point, bool createIfDoesNotExist = true );
/** \brief Ellipse has 3 control points per definition. */
unsigned int GetMinimumNumberOfControlPoints() const
{
return 4;
}
/** \brief Ellipse has 3 control points per definition. */
unsigned int GetMaximumNumberOfControlPoints() const
{
return 4;
}
/** \brief Sets the minimum radius
*/
void SetMinimumRadius( double radius )
{
m_MinRadius = radius;
}
/** \brief Gets the minimum radius
*/
double GetMinimumRadius()
{
return m_MinRadius;
}
/** \brief Sets the maximum radius
*/
void SetMaximumRadius( double radius )
{
m_MaxRadius = radius;
}
/** \brief Gets the minimum radius
*/
double GetMaximumRadius()
{
return m_MaxRadius;
}
void ActivateMinMaxRadiusContstraints( bool active )
{
m_MinMaxRadiusContraintsActive = active;
}
/** \brief Treat ellipse as circle (equal radii)
*/
void SetTreatAsCircle( bool active )
{
m_TreatAsCircle = active;
}
const unsigned int FEATURE_ID_MAJOR_AXIS;
const unsigned int FEATURE_ID_MINOR_AXIS;
protected:
PlanarEllipse();
virtual ~PlanarEllipse();
mitkCloneMacro(Self);
/** \brief Generates the poly-line representation of the planar figure. */
virtual void GeneratePolyLine();
/** \brief Generates the poly-lines that should be drawn the same size regardless of zoom.*/
virtual void GenerateHelperPolyLine(double mmPerDisplayUnit, unsigned int displayHeight);
/** \brief Spatially constrain control points of second (orthogonal) line */
virtual Point2D ApplyControlPointConstraints( unsigned int index, const Point2D& point );
/** \brief Calculates feature quantities of the planar figure. */
virtual void EvaluateFeaturesInternal();
virtual void PrintSelf( std::ostream &os, itk::Indent indent ) const;
//Member variables:
double m_MinRadius;
double m_MaxRadius;
bool m_MinMaxRadiusContraintsActive;
bool m_TreatAsCircle;
private:
};
} // namespace mitk
#endif //_MITK_PLANAR_ELLIPSE_H_
diff --git a/Modules/PlanarFigure/DataManagement/mitkPlanarFigure.cpp b/Modules/PlanarFigure/DataManagement/mitkPlanarFigure.cpp
index f475cbf53b..2b4fdbbbb0 100644
--- a/Modules/PlanarFigure/DataManagement/mitkPlanarFigure.cpp
+++ b/Modules/PlanarFigure/DataManagement/mitkPlanarFigure.cpp
@@ -1,789 +1,780 @@
/*===================================================================
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 "mitkPlanarFigure.h"
-#include <mitkGeometry2D.h>
+#include "mitkPlaneGeometry.h"
#include <mitkProperties.h>
#include <mitkProportionalTimeGeometry.h>
#include <algorithm>
#ifdef __GNUC__
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#elif __clang__
# pragma clang diagnostic ignored "-Wdeprecated-declarations"
#elif _MSC_VER
# pragma warning (push)
# pragma warning (disable: 4996)
#endif
mitk::PlanarFigure::PolyLineElement::PolyLineElement(Point2D point, int index)
: Point(point),
Index(index)
{
}
mitk::PlanarFigure::PolyLineElement::PolyLineElement(const Point2D& point)
: Point(point),
Index(-1)
{
}
mitk::PlanarFigure::PolyLineElement::PolyLineElement(const PolyLineElement &other)
: Point(other.Point),
Index(other.Index)
{
}
mitk::PlanarFigure::PolyLineElement& mitk::PlanarFigure::PolyLineElement::operator=(const PolyLineElement &other)
{
if (this != &other)
{
Point = other.Point;
Index = other.Index;
}
return *this;
}
mitk::PlanarFigure::PolyLineElement::operator mitk::Point2D&()
{
return Point;
}
mitk::PlanarFigure::PolyLineElement::operator const mitk::Point2D&() const
{
return Point;
}
mitk::PlanarFigure::PlanarFigure()
: m_SelectedControlPoint( -1 ),
m_PreviewControlPointVisible( false ),
m_FigurePlaced( false ),
- m_Geometry2D( NULL ),
+ m_PlaneGeometry( NULL ),
m_PolyLineUpToDate(false),
m_HelperLinesUpToDate(false),
m_FeaturesUpToDate(false),
m_FeaturesMTime( 0 )
{
-
-
m_HelperPolyLinesToBePainted = BoolContainerType::New();
m_DisplaySize.first = 0.0;
m_DisplaySize.second = 0;
this->SetProperty( "closed", mitk::BoolProperty::New( false ) );
// Currently only single-time-step geometries are supported
this->InitializeTimeGeometry( 1 );
}
mitk::PlanarFigure::~PlanarFigure()
{
}
mitk::PlanarFigure::PlanarFigure(const Self& other)
: BaseData(other),
m_ControlPoints(other.m_ControlPoints),
m_NumberOfControlPoints(other.m_NumberOfControlPoints),
m_SelectedControlPoint(other.m_SelectedControlPoint),
m_PolyLines(other.m_PolyLines),
m_HelperPolyLines(other.m_HelperPolyLines),
m_HelperPolyLinesToBePainted(other.m_HelperPolyLinesToBePainted->Clone()),
m_PreviewControlPoint(other.m_PreviewControlPoint),
m_PreviewControlPointVisible(other.m_PreviewControlPointVisible),
m_FigurePlaced(other.m_FigurePlaced),
- m_Geometry2D(other.m_Geometry2D), // do not clone since SetGeometry2D() doesn't clone either
+ m_PlaneGeometry(other.m_PlaneGeometry), // do not clone since SetPlaneGeometry() doesn't clone either
m_PolyLineUpToDate(other.m_PolyLineUpToDate),
m_HelperLinesUpToDate(other.m_HelperLinesUpToDate),
m_FeaturesUpToDate(other.m_FeaturesUpToDate),
m_Features(other.m_Features),
m_FeaturesMTime(other.m_FeaturesMTime),
m_DisplaySize(other.m_DisplaySize)
{
}
-void mitk::PlanarFigure::SetGeometry2D( mitk::Geometry2D *geometry )
+void mitk::PlanarFigure::SetPlaneGeometry( mitk::PlaneGeometry *geometry )
{
this->SetGeometry( geometry );
- m_Geometry2D = dynamic_cast<Geometry2D *>(GetGeometry(0));//geometry;
+ m_PlaneGeometry = dynamic_cast<PlaneGeometry *>(GetGeometry(0));//geometry;
}
-const mitk::Geometry2D *mitk::PlanarFigure::GetGeometry2D() const
+const mitk::PlaneGeometry *mitk::PlanarFigure::GetPlaneGeometry() const
{
- return m_Geometry2D;
+ return m_PlaneGeometry;
}
bool mitk::PlanarFigure::IsClosed() const
{
mitk::BoolProperty* closed = dynamic_cast< mitk::BoolProperty* >( this->GetProperty( "closed" ).GetPointer() );
if ( closed != NULL )
{
return closed->GetValue();
}
return false;
}
void mitk::PlanarFigure::PlaceFigure( const mitk::Point2D& point )
{
for ( unsigned int i = 0; i < this->GetNumberOfControlPoints(); ++i )
{
m_ControlPoints.push_back( this->ApplyControlPointConstraints( i, point ) );
}
m_FigurePlaced = true;
m_SelectedControlPoint = 1;
}
bool mitk::PlanarFigure::AddControlPoint( const mitk::Point2D& point, int position )
{
// if we already have the maximum number of control points, do nothing
if ( m_NumberOfControlPoints < this->GetMaximumNumberOfControlPoints() )
{
// if position has not been defined or position would be the last control point, just append the new one
// we also append a new point if we click onto the line between the first two control-points if the second control-point is selected
// -> special case for PlanarCross
if ( position == -1 || position > (int)m_NumberOfControlPoints-1 || (position == 1 && m_SelectedControlPoint == 2) )
{
if ( m_ControlPoints.size() > this->GetMaximumNumberOfControlPoints()-1 )
{
// get rid of deprecated control points in the list. This is necessary
// as ::ResetNumberOfControlPoints() only sets the member, does not resize the list!
m_ControlPoints.resize( this->GetNumberOfControlPoints() );
}
m_ControlPoints.push_back( this->ApplyControlPointConstraints( m_NumberOfControlPoints, point ) );
m_SelectedControlPoint = m_NumberOfControlPoints;
}
else
{
// insert the point at the given position and set it as selected point
ControlPointListType::iterator iter = m_ControlPoints.begin() + position;
m_ControlPoints.insert( iter, this->ApplyControlPointConstraints( position, point ) );
for( unsigned int i = 0; i < m_ControlPoints.size(); ++i )
{
if( point == m_ControlPoints.at(i) )
{
m_SelectedControlPoint = i;
}
}
}
// polylines & helperpolylines need to be repainted
m_PolyLineUpToDate = false;
m_HelperLinesUpToDate = false;
m_FeaturesUpToDate = false;
// one control point more
++m_NumberOfControlPoints;
return true;
}
else
{
return false;
}
}
bool mitk::PlanarFigure::SetControlPoint( unsigned int index, const Point2D& point, bool createIfDoesNotExist )
{
bool controlPointSetCorrectly = false;
if (createIfDoesNotExist)
{
if ( m_NumberOfControlPoints <= index )
{
m_ControlPoints.push_back( this->ApplyControlPointConstraints( index, point ) );
m_NumberOfControlPoints++;
}
else
{
m_ControlPoints.at( index ) = this->ApplyControlPointConstraints( index, point );
}
controlPointSetCorrectly = true;
}
else if ( index < m_NumberOfControlPoints )
{
m_ControlPoints.at( index ) = this->ApplyControlPointConstraints( index, point );
controlPointSetCorrectly = true;
}
else
{
return false;
}
if ( controlPointSetCorrectly )
{
m_PolyLineUpToDate = false;
m_HelperLinesUpToDate = false;
m_FeaturesUpToDate = false;
}
return controlPointSetCorrectly;
}
bool mitk::PlanarFigure::SetCurrentControlPoint( const Point2D& point )
{
if ( (m_SelectedControlPoint < 0) || (m_SelectedControlPoint >= (int)m_NumberOfControlPoints) )
{
return false;
}
return this->SetControlPoint(m_SelectedControlPoint, point, false);
}
unsigned int mitk::PlanarFigure::GetNumberOfControlPoints() const
{
return m_NumberOfControlPoints;
}
bool mitk::PlanarFigure::SelectControlPoint( unsigned int index )
{
if ( index < this->GetNumberOfControlPoints() )
{
m_SelectedControlPoint = index;
return true;
}
else
{
return false;
}
}
bool mitk::PlanarFigure::DeselectControlPoint()
{
bool wasSelected = ( m_SelectedControlPoint != -1);
m_SelectedControlPoint = -1;
return wasSelected;
}
void mitk::PlanarFigure::SetPreviewControlPoint( const Point2D& point )
{
m_PreviewControlPoint = point;
m_PreviewControlPointVisible = true;
}
void mitk::PlanarFigure::ResetPreviewContolPoint()
{
m_PreviewControlPointVisible = false;
}
mitk::Point2D mitk::PlanarFigure::GetPreviewControlPoint()
{
return m_PreviewControlPoint;
}
bool mitk::PlanarFigure::IsPreviewControlPointVisible()
{
return m_PreviewControlPointVisible;
}
mitk::Point2D mitk::PlanarFigure::GetControlPoint( unsigned int index ) const
{
if ( index < m_NumberOfControlPoints )
{
return m_ControlPoints.at( index );
}
itkExceptionMacro( << "GetControlPoint(): Invalid index!" );
}
mitk::Point3D mitk::PlanarFigure::GetWorldControlPoint( unsigned int index ) const
{
Point3D point3D;
- if ( (m_Geometry2D != NULL) && (index < m_NumberOfControlPoints) )
+ if ( (m_PlaneGeometry != NULL) && (index < m_NumberOfControlPoints) )
{
- m_Geometry2D->Map( m_ControlPoints.at( index ), point3D );
+ m_PlaneGeometry->Map( m_ControlPoints.at( index ), point3D );
return point3D;
}
itkExceptionMacro( << "GetWorldControlPoint(): Invalid index!" );
}
const mitk::PlanarFigure::PolyLineType
mitk::PlanarFigure::GetPolyLine(unsigned int index)
{
mitk::PlanarFigure::PolyLineType polyLine;
if ( index > m_PolyLines.size() || !m_PolyLineUpToDate )
{
this->GeneratePolyLine();
m_PolyLineUpToDate = true;
}
return m_PolyLines.at( index );;
}
const mitk::PlanarFigure::PolyLineType
mitk::PlanarFigure::GetPolyLine(unsigned int index) const
{
return m_PolyLines.at( index );
}
void mitk::PlanarFigure::ClearPolyLines()
{
for ( std::vector<PolyLineType>::size_type i=0; i<m_PolyLines.size(); i++ )
{
m_PolyLines.at( i ).clear();
}
m_PolyLineUpToDate = false;
}
const mitk::PlanarFigure::PolyLineType mitk::PlanarFigure::GetHelperPolyLine( unsigned int index,
double mmPerDisplayUnit,
unsigned int displayHeight )
{
mitk::PlanarFigure::PolyLineType helperPolyLine;
if ( index < m_HelperPolyLines.size() )
{
// m_HelperLinesUpToDate does not cover changes in zoom-level, so we have to check previous values of the
// two parameters as well
if ( !m_HelperLinesUpToDate || m_DisplaySize.first != mmPerDisplayUnit || m_DisplaySize.second != displayHeight )
{
this->GenerateHelperPolyLine(mmPerDisplayUnit, displayHeight);
m_HelperLinesUpToDate = true;
// store these parameters to be able to check next time if somebody zoomed in or out
m_DisplaySize.first = mmPerDisplayUnit;
m_DisplaySize.second = displayHeight;
}
helperPolyLine = m_HelperPolyLines.at(index);
}
return helperPolyLine;
}
void mitk::PlanarFigure::ClearHelperPolyLines()
{
for ( std::vector<PolyLineType>::size_type i=0; i<m_HelperPolyLines.size(); i++ )
{
m_HelperPolyLines.at(i).clear();
}
m_HelperLinesUpToDate = false;
}
/** \brief Returns the number of features available for this PlanarFigure
* (such as, radius, area, ...). */
unsigned int mitk::PlanarFigure::GetNumberOfFeatures() const
{
return m_Features.size();
}
const char *mitk::PlanarFigure::GetFeatureName( unsigned int index ) const
{
if ( index < m_Features.size() )
{
return m_Features[index].Name.c_str();
}
else
{
return NULL;
}
}
const char *mitk::PlanarFigure::GetFeatureUnit( unsigned int index ) const
{
if ( index < m_Features.size() )
{
return m_Features[index].Unit.c_str();
}
else
{
return NULL;
}
}
double mitk::PlanarFigure::GetQuantity( unsigned int index ) const
{
if ( index < m_Features.size() )
{
return m_Features[index].Quantity;
}
else
{
return 0.0;
}
}
bool mitk::PlanarFigure::IsFeatureActive( unsigned int index ) const
{
if ( index < m_Features.size() )
{
return m_Features[index].Active;
}
else
{
return false;
}
}
bool mitk::PlanarFigure::IsFeatureVisible( unsigned int index ) const
{
if ( index < m_Features.size() )
{
return m_Features[index].Visible;
}
else
{
return false;
}
}
void mitk::PlanarFigure::SetFeatureVisible( unsigned int index, bool visible )
{
if ( index < m_Features.size() )
{
m_Features[index].Visible = visible;
}
}
void mitk::PlanarFigure::EvaluateFeatures()
{
if ( !m_FeaturesUpToDate || !m_PolyLineUpToDate )
{
if ( !m_PolyLineUpToDate )
{
this->GeneratePolyLine();
}
this->EvaluateFeaturesInternal();
m_FeaturesUpToDate = true;
}
}
void mitk::PlanarFigure::UpdateOutputInformation()
{
- // Bounds are NOT calculated here, since the Geometry2D defines a fixed
+ // Bounds are NOT calculated here, since the PlaneGeometry defines a fixed
// frame (= bounds) for the planar figure.
Superclass::UpdateOutputInformation();
this->GetTimeGeometry()->Update();
}
void mitk::PlanarFigure::SetRequestedRegionToLargestPossibleRegion()
{
}
bool mitk::PlanarFigure::RequestedRegionIsOutsideOfTheBufferedRegion()
{
return false;
}
bool mitk::PlanarFigure::VerifyRequestedRegion()
{
return true;
}
void mitk::PlanarFigure::SetRequestedRegion(const itk::DataObject * /*data*/ )
{
-
}
void mitk::PlanarFigure::ResetNumberOfControlPoints( int numberOfControlPoints )
{
// DO NOT resize the list here, will cause crash!!
m_NumberOfControlPoints = numberOfControlPoints;
}
mitk::Point2D mitk::PlanarFigure::ApplyControlPointConstraints( unsigned int /*index*/, const Point2D& point )
{
- if ( m_Geometry2D == NULL )
+ if ( m_PlaneGeometry == NULL )
{
return point;
}
Point2D indexPoint;
- m_Geometry2D->WorldToIndex( point, indexPoint );
+ m_PlaneGeometry->WorldToIndex( point, indexPoint );
- BoundingBox::BoundsArrayType bounds = m_Geometry2D->GetBounds();
+ BoundingBox::BoundsArrayType bounds = m_PlaneGeometry->GetBounds();
if ( indexPoint[0] < bounds[0] ) { indexPoint[0] = bounds[0]; }
if ( indexPoint[0] > bounds[1] ) { indexPoint[0] = bounds[1]; }
if ( indexPoint[1] < bounds[2] ) { indexPoint[1] = bounds[2]; }
if ( indexPoint[1] > bounds[3] ) { indexPoint[1] = bounds[3]; }
Point2D constrainedPoint;
- m_Geometry2D->IndexToWorld( indexPoint, constrainedPoint );
+ m_PlaneGeometry->IndexToWorld( indexPoint, constrainedPoint );
return constrainedPoint;
}
unsigned int mitk::PlanarFigure::AddFeature( const char *featureName, const char *unitName )
{
unsigned int index = m_Features.size();
Feature newFeature( featureName, unitName );
m_Features.push_back( newFeature );
return index;
}
void mitk::PlanarFigure::SetFeatureName( unsigned int index, const char *featureName )
{
if ( index < m_Features.size() )
{
m_Features[index].Name = featureName;
}
}
void mitk::PlanarFigure::SetFeatureUnit( unsigned int index, const char *unitName )
{
if ( index < m_Features.size() )
{
m_Features[index].Unit = unitName;
}
}
void mitk::PlanarFigure::SetQuantity( unsigned int index, double quantity )
{
if ( index < m_Features.size() )
{
m_Features[index].Quantity = quantity;
}
}
void mitk::PlanarFigure::ActivateFeature( unsigned int index )
{
if ( index < m_Features.size() )
{
m_Features[index].Active = true;
}
}
void mitk::PlanarFigure::DeactivateFeature( unsigned int index )
{
if ( index < m_Features.size() )
{
m_Features[index].Active = false;
}
}
void mitk::PlanarFigure::InitializeTimeGeometry( unsigned int timeSteps )
{
- mitk::Geometry2D::Pointer geometry2D = mitk::Geometry2D::New();
+ mitk::PlaneGeometry::Pointer geometry2D = mitk::PlaneGeometry::New();
geometry2D->Initialize();
- if ( timeSteps > 1 )
- {
- mitk::ScalarType timeBounds[] = {0.0, 1.0};
- geometry2D->SetTimeBounds( timeBounds );
- }
-
// The geometry is propagated automatically to all time steps,
// if EvenlyTimed is true...
ProportionalTimeGeometry::Pointer timeGeometry = ProportionalTimeGeometry::New();
timeGeometry->Initialize(geometry2D, timeSteps);
SetTimeGeometry(timeGeometry);
}
void mitk::PlanarFigure::PrintSelf( std::ostream& os, itk::Indent indent) const
{
Superclass::PrintSelf( os, indent );
os << indent << this->GetNameOfClass() << ":\n";
if (this->IsClosed())
os << indent << "This figure is closed\n";
else
os << indent << "This figure is not closed\n";
os << indent << "Minimum number of control points: " << this->GetMinimumNumberOfControlPoints() << std::endl;
os << indent << "Maximum number of control points: " << this->GetMaximumNumberOfControlPoints() << std::endl;
os << indent << "Current number of control points: " << this->GetNumberOfControlPoints() << std::endl;
os << indent << "Control points:" << std::endl;
for ( unsigned int i = 0; i < this->GetNumberOfControlPoints(); ++i )
{
//os << indent.GetNextIndent() << i << ": " << m_ControlPoints->ElementAt( i ) << std::endl;
os << indent.GetNextIndent() << i << ": " << m_ControlPoints.at( i ) << std::endl;
}
os << indent << "Geometry:\n";
- this->GetGeometry2D()->Print(os, indent.GetNextIndent());
+ this->GetPlaneGeometry()->Print(os, indent.GetNextIndent());
}
unsigned short mitk::PlanarFigure::GetPolyLinesSize()
{
if ( !m_PolyLineUpToDate )
{
this->GeneratePolyLine();
m_PolyLineUpToDate = true;
}
return m_PolyLines.size();
}
unsigned short mitk::PlanarFigure::GetHelperPolyLinesSize()
{
return m_HelperPolyLines.size();
}
bool mitk::PlanarFigure::IsHelperToBePainted(unsigned int index)
{
return m_HelperPolyLinesToBePainted->GetElement( index );
}
bool mitk::PlanarFigure::ResetOnPointSelect()
{
return false;
}
void mitk::PlanarFigure::RemoveControlPoint( unsigned int index )
{
if ( index > m_ControlPoints.size() )
return;
if ( (m_ControlPoints.size() -1) < this->GetMinimumNumberOfControlPoints() )
return;
ControlPointListType::iterator iter;
iter = m_ControlPoints.begin() + index;
m_ControlPoints.erase( iter );
m_PolyLineUpToDate = false;
m_HelperLinesUpToDate = false;
m_FeaturesUpToDate = false;
--m_NumberOfControlPoints;
}
void mitk::PlanarFigure::RemoveLastControlPoint()
{
RemoveControlPoint( m_ControlPoints.size()-1 );
}
void mitk::PlanarFigure::DeepCopy(Self::Pointer oldFigure)
{
//DeepCopy only same types of planar figures
//Notice to get typeid polymorph you have to use the *operator
if(typeid(*oldFigure) != typeid(*this))
{
itkExceptionMacro( << "DeepCopy(): Inconsistent type of source (" << typeid(*oldFigure).name() << ") and destination figure (" << typeid(*this).name() << ")!" );
return;
}
m_ControlPoints.clear();
this->ClearPolyLines();
this->ClearHelperPolyLines();
// clone base data members
SetPropertyList(oldFigure->GetPropertyList()->Clone());
/// deep copy members
m_FigurePlaced = oldFigure->m_FigurePlaced;
m_SelectedControlPoint = oldFigure->m_SelectedControlPoint;
m_FeaturesMTime = oldFigure->m_FeaturesMTime;
m_Features = oldFigure->m_Features;
m_NumberOfControlPoints = oldFigure->m_NumberOfControlPoints;
//copy geometry 2D of planar figure
- Geometry2D::Pointer affineGeometry = oldFigure->m_Geometry2D->Clone();
- SetGeometry2D(affineGeometry.GetPointer());
+ PlaneGeometry::Pointer affineGeometry = oldFigure->m_PlaneGeometry->Clone();
+ SetPlaneGeometry(affineGeometry.GetPointer());
for(unsigned long index=0; index < oldFigure->GetNumberOfControlPoints(); index++)
{
m_ControlPoints.push_back( oldFigure->GetControlPoint( index ));
}
//After setting the control points we can generate the polylines
this->GeneratePolyLine();
}
void mitk::PlanarFigure::SetNumberOfPolyLines( unsigned int numberOfPolyLines )
{
m_PolyLines.resize(numberOfPolyLines);
}
void mitk::PlanarFigure::SetNumberOfHelperPolyLines( unsigned int numberOfHerlperPolyLines )
{
m_HelperPolyLines.resize(numberOfHerlperPolyLines);
}
void mitk::PlanarFigure::AppendPointToPolyLine( unsigned int index, PolyLineElement element )
{
if ( index < m_PolyLines.size() )
{
if(element.Index == -1)
element.Index = m_PolyLines[index].size();
m_PolyLines[index].push_back(element);
m_PolyLineUpToDate = false;
}
else
{
MITK_ERROR << "Tried to add point to PolyLine " << index+1 << ", although only " << m_PolyLines.size() << " exists";
}
}
void mitk::PlanarFigure::AppendPointToHelperPolyLine( unsigned int index, PolyLineElement element )
{
if ( index < m_HelperPolyLines.size() )
{
if(element.Index == -1)
element.Index = m_HelperPolyLines[index].size();
m_HelperPolyLines[index].push_back(element);
m_HelperLinesUpToDate = false;
}
else
{
MITK_ERROR << "Tried to add point to HelperPolyLine " << index+1 << ", although only " << m_HelperPolyLines.size() << " exists";
}
}
#ifdef __GNUC__
# pragma GCC diagnostic error "-Wdeprecated-declarations"
#elif __clang__
# pragma clang diagnostic error "-Wdeprecated-declarations"
#elif _MSC_VER
# pragma warning (pop)
#endif
diff --git a/Modules/PlanarFigure/DataManagement/mitkPlanarFigure.h b/Modules/PlanarFigure/DataManagement/mitkPlanarFigure.h
index 6078ce0061..1bf4fe062a 100644
--- a/Modules/PlanarFigure/DataManagement/mitkPlanarFigure.h
+++ b/Modules/PlanarFigure/DataManagement/mitkPlanarFigure.h
@@ -1,426 +1,434 @@
/*===================================================================
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 _MITK_PLANAR_FIGURE_H_
#define _MITK_PLANAR_FIGURE_H_
#include <MitkPlanarFigureExports.h>
#include "mitkBaseData.h"
#include "mitkCommon.h"
#include <deque>
namespace mitk
{
-class Geometry2D;
+class PlaneGeometry;
/**
* \brief Base-class for geometric planar (2D) figures, such as
* lines, circles, rectangles, polygons, etc.
*
* \warning Currently does not support time-resolved data handling
*
* Behavior and appearance of PlanarFigures are controlled by various properties; for a detailed
* list of appearance properties see mitk::PlanarFigureMapper2D
*
* The following properties control general PlanarFigure behavior:
*
* <ul>
* <li>"selected": true if the planar figure is selected
* <li>"planarfigure.ishovering": true if the mouse "hovers" over the planar figure
* <li>"planarfigure.iseditable": true if the planar figure can be edited (otherwise,
* it can only be picked/selected, but its control points cannot be edited); default is true
* <li>"planarfigure.isextendable": true if new control points can be inserted into the list of control points;
* default is false
* </ul>
*
*
* TODO: Implement local 2D transform (including center of rotation...)
*
*/
class MitkPlanarFigure_EXPORT PlanarFigure : public BaseData
{
public:
mitkClassMacro( PlanarFigure, BaseData )
itkCloneMacro( Self )
/** \brief Treat as Point2D by implicitly using conversion operators.
*
* \deprecatedSince{2014_06} "struct PolyLineElement {...};" will be changed to "typedef Point2D PolyLineElement;".
*/
struct MitkPlanarFigure_EXPORT PolyLineElement
{
DEPRECATED(PolyLineElement(Point2D point, int index));
PolyLineElement(const Point2D& point);
PolyLineElement(const PolyLineElement &other);
PolyLineElement& operator=(const PolyLineElement &other);
operator Point2D&();
operator const Point2D&() const;
DEPRECATED(Point2D Point);
DEPRECATED(int Index);
};
typedef itk::VectorContainer< unsigned long, bool> BoolContainerType;
typedef std::deque< Point2D > ControlPointListType;
typedef std::vector< PolyLineElement > PolyLineType;
/** \brief Sets the 2D geometry on which this figure will be placed.
*
* In most cases, this is a Geometry already owned by another object, e.g.
* describing the slice of the image on which measurements will be
* performed.
*/
- virtual void SetGeometry2D( mitk::Geometry2D *geometry );
+ virtual void SetPlaneGeometry( mitk::PlaneGeometry *geometry );
+ /**
+ * \deprecatedSince{2014_06} Please use SetPlaneGeometry
+ */
+ DEPRECATED(void SetGeometry2D(PlaneGeometry* geo){SetPlaneGeometry(geo);};)
/** \brief Returns (previously set) 2D geometry of this figure. */
- virtual const Geometry2D *GetGeometry2D() const;
+ virtual const PlaneGeometry *GetPlaneGeometry() const;
+ /**
+ * \deprecatedSince{2014_06} Please use GetPlaneGeometry
+ */
+ DEPRECATED(const PlaneGeometry* GetGeometry2D(){return GetPlaneGeometry();};)
/** \brief True if the planar figure is closed.
*
* Default is false. The "closed" boolean property must be set in sub-classes. */
virtual bool IsClosed() const;
/** \brief True if the planar figure has been placed (and can be
* displayed/interacted with). */
virtual bool IsPlaced() const { return m_FigurePlaced; };
/** \brief Place figure at the given point (in 2D index coordinates) onto
* the given 2D geometry.
*
* By default, the first two control points of the figure are set to the
* passed point. Further points can be set via AddControlPoint(), if the
* current number of control points is below the maximum number of control
* points.
*
* Can be re-implemented in sub-classes as needed.
*/
virtual void PlaceFigure( const Point2D& point );
/**
* \brief Adds / inserts new control-points
*
* This method adds a new control-point with the coordinates defined by point at the given index.
* If 'index' == -1 or index is greater than the number of control-points the new point is appended
* to the back of the list of control points.
* If a control-point already exists for 'index', an additional point is inserted at that position.
* It is not possible to add more points if the maximum number of control-points (GetMaximumNumberOfControlPoints())
* has been reached.
*/
virtual bool AddControlPoint( const Point2D& point, int index = -1 );
virtual bool SetControlPoint( unsigned int index, const Point2D& point, bool createIfDoesNotExist = false);
virtual bool SetCurrentControlPoint( const Point2D& point );
/** \brief Returns the current number of 2D control points defining this figure. */
unsigned int GetNumberOfControlPoints() const;
/** \brief Returns the minimum number of control points needed to represent
* this figure.
*
* Must be implemented in sub-classes.
*/
virtual unsigned int GetMinimumNumberOfControlPoints() const = 0;
/** \brief Returns the maximum number of control points allowed for
* this figure (e.g. 3 for triangles).
*
* Must be implemented in sub-classes.
*/
virtual unsigned int GetMaximumNumberOfControlPoints() const = 0;
/** \brief Selects currently active control points. */
virtual bool SelectControlPoint( unsigned int index );
/** \brief Deselect control point; no control point active. */
virtual bool DeselectControlPoint();
/** \brief Return currently selected control point. */
virtual int GetSelectedControlPoint() const { return m_SelectedControlPoint; }
/** \brief Returns specified control point in 2D world coordinates. */
Point2D GetControlPoint( unsigned int index ) const;
/** \brief Returns specified control point in world coordinates. */
Point3D GetWorldControlPoint( unsigned int index ) const;
/** \brief Returns the polyline representing the planar figure
* (for rendering, measurements, etc.). */
const PolyLineType GetPolyLine(unsigned int index);
/** \brief Returns the polyline representing the planar figure
* (for rendering, measurments, etc.). */
const PolyLineType GetPolyLine(unsigned int index) const;
/** \brief Returns the polyline that should be drawn the same size at every scale
* (for text, angles, etc.). */
const PolyLineType GetHelperPolyLine( unsigned int index, double mmPerDisplayUnit, unsigned int displayHeight );
/** \brief Sets the position of the PreviewControlPoint. Automatically sets it visible.*/
void SetPreviewControlPoint( const Point2D& point );
/** \brief Marks the PreviewControlPoint as invisible.*/
void ResetPreviewContolPoint();
/** \brief Returns whether or not the PreviewControlPoint is visible.*/
bool IsPreviewControlPointVisible();
/** \brief Returns the coordinates of the PreviewControlPoint. */
Point2D GetPreviewControlPoint();
/** \brief Returns the number of features available for this PlanarFigure
* (such as, radius, area, ...). */
virtual unsigned int GetNumberOfFeatures() const;
/** \brief Returns the name (identifier) of the specified features. */
const char *GetFeatureName( unsigned int index ) const;
/** \brief Returns the physical unit of the specified features. */
const char *GetFeatureUnit( unsigned int index ) const;
/** Returns quantity of the specified feature (e.g., length, radius,
* area, ... ) */
double GetQuantity( unsigned int index ) const;
/** \brief Returns true if the feature with the specified index exists and
* is active (an inactive feature may e.g. be the area of a non-closed
* polygon. */
bool IsFeatureActive( unsigned int index ) const;
/** \brief Returns true if the feature with the specified index exists and is set visible */
bool IsFeatureVisible( unsigned int index ) const;
/** \brief Defines if the feature with the specified index will be shown as an
* overlay in the RenderWindow */
void SetFeatureVisible( unsigned int index, bool visible );
/** \brief Calculates quantities of all features of this planar figure. */
virtual void EvaluateFeatures();
/** \brief Intherited from parent */
virtual void UpdateOutputInformation();
/** \brief Intherited from parent */
virtual void SetRequestedRegionToLargestPossibleRegion();
/** \brief Intherited from parent */
virtual bool RequestedRegionIsOutsideOfTheBufferedRegion();
/** \brief Intherited from parent */
virtual bool VerifyRequestedRegion();
/** \brief Intherited from parent */
virtual void SetRequestedRegion( const itk::DataObject *data);
/** \brief Returns the current number of polylines */
virtual unsigned short GetPolyLinesSize();
/** \brief Returns the current number of helperpolylines */
virtual unsigned short GetHelperPolyLinesSize();
/** \brief Returns whether a helper polyline should be painted or not */
virtual bool IsHelperToBePainted(unsigned int index);
/** \brief Returns true if the planar figure is reset to "add points" mode
* when a point is selected.
*
* Default return value is false. Subclasses can overwrite this method and
* execute any reset / initialization statements required. */
virtual bool ResetOnPointSelect();
/** \brief removes the point with the given index from the list of controlpoints. */
virtual void RemoveControlPoint( unsigned int index );
/** \brief Removes last control point */
virtual void RemoveLastControlPoint();
/** \brief Copies contents and state of a figre provided as parameter to the current object.
*
* Requires a matching type of both figures.
*
* \note Deprecated, use Clone() instead.
*/
DEPRECATED(void DeepCopy(Self::Pointer oldFigure));
/** \brief Allow sub-classes to apply constraints on control points.
*
* Sub-classes can define spatial constraints to certain control points by
* overwriting this method and returning a constrained point. By default,
* the points are constrained by the image bounds. */
virtual Point2D ApplyControlPointConstraints( unsigned int /*index*/, const Point2D& point );
protected:
PlanarFigure();
virtual ~PlanarFigure();
PlanarFigure(const Self& other);
/** \brief Set the initial number of control points of the planar figure */
void ResetNumberOfControlPoints( int numberOfControlPoints );
/** Adds feature (e.g., circumference, radius, angle, ...) to feature vector
* of a planar figure object and returns integer ID for the feature element.
* Should be called in sub-class constructors. */
virtual unsigned int AddFeature( const char *featureName, const char *unitName );
/** Sets the name of the specified feature. INTERNAL METHOD. */
void SetFeatureName( unsigned int index, const char *featureName );
/** Sets the physical unit of the specified feature. INTERNAL METHOD. */
void SetFeatureUnit( unsigned int index, const char *unitName );
/** Sets quantity of the specified feature. INTERNAL METHOD. */
void SetQuantity( unsigned int index, double quantity );
/** Sets the specified feature as active. INTERAL METHOD. */
void ActivateFeature( unsigned int index );
/** Sets the specified feature as active. INTERAL METHOD. */
void DeactivateFeature( unsigned int index );
/** \brief Generates the poly-line representation of the planar figure.
* Must be implemented in sub-classes. */
virtual void GeneratePolyLine() = 0;
/** \brief Generates the poly-lines that should be drawn the same size regardless of zoom.
* Must be implemented in sub-classes. */
virtual void GenerateHelperPolyLine(double mmPerDisplayUnit, unsigned int displayHeight) = 0;
/** \brief Calculates quantities of all features of this planar figure.
* Must be implemented in sub-classes. */
virtual void EvaluateFeaturesInternal() = 0;
/** \brief Initializes the TimeGeometry describing the (time-resolved)
- * geometry of this figure. Note that each time step holds one Geometry2D.
+ * geometry of this figure. Note that each time step holds one PlaneGeometry.
*/
virtual void InitializeTimeGeometry( unsigned int timeSteps = 1 );
/** \brief defines the number of PolyLines that will be available */
void SetNumberOfPolyLines( unsigned int numberOfPolyLines );
/** \brief Append a point to the PolyLine # index */
void AppendPointToPolyLine( unsigned int index, PolyLineElement element );
/** \brief clears the list of PolyLines. Call before re-calculating a new Polyline. */
void ClearPolyLines();
/** \brief defines the number of HelperPolyLines that will be available */
void SetNumberOfHelperPolyLines( unsigned int numberOfHelperPolyLines );
/** \brief Append a point to the HelperPolyLine # index */
void AppendPointToHelperPolyLine( unsigned int index, PolyLineElement element );
/** \brief clears the list of HelperPolyLines. Call before re-calculating a new HelperPolyline. */
void ClearHelperPolyLines();
virtual void PrintSelf( std::ostream& os, itk::Indent indent ) const;
ControlPointListType m_ControlPoints;
unsigned int m_NumberOfControlPoints;
// Currently selected control point; -1 means no point selected
int m_SelectedControlPoint;
std::vector<PolyLineType> m_PolyLines;
std::vector<PolyLineType> m_HelperPolyLines;
BoolContainerType::Pointer m_HelperPolyLinesToBePainted;
// this point is used to store the coordiantes an additional 'ControlPoint' that is rendered
// when the mouse cursor is above the figure (and not a control-point) and when the
// property 'planarfigure.isextendable' is set to true
Point2D m_PreviewControlPoint;
bool m_PreviewControlPointVisible;
bool m_FigurePlaced;
private:
// not implemented to prevent PlanarFigure::New() calls which would create an itk::Object.
static Pointer New();
struct Feature
{
Feature( const char *name, const char *unit )
: Name( name ), Unit( unit ), Quantity( 0.0 ), Active( true ), Visible( true )
{
}
std::string Name;
std::string Unit;
double Quantity;
bool Active;
bool Visible;
};
virtual itk::LightObject::Pointer InternalClone() const = 0;
- Geometry2D *m_Geometry2D;
+ PlaneGeometry *m_PlaneGeometry;
bool m_PolyLineUpToDate;
bool m_HelperLinesUpToDate;
bool m_FeaturesUpToDate;
// Vector of features available for this geometric figure
typedef std::vector< Feature > FeatureVectorType;
FeatureVectorType m_Features;
unsigned long m_FeaturesMTime;
// this pair is used to store the mmInDisplayUnits (m_DisplaySize.first) and the displayHeight (m_DisplaySize.second)
// that the helperPolyLines have been calculated for.
// It's used to determine whether or not GetHelperPolyLine() needs to recalculate the HelperPolyLines.
std::pair<double, unsigned int> m_DisplaySize;
};
} // namespace mitk
#endif //_MITK_PLANAR_FIGURE_H_
diff --git a/Modules/PlanarFigure/DataManagement/mitkPlanarFourPointAngle.cpp b/Modules/PlanarFigure/DataManagement/mitkPlanarFourPointAngle.cpp
index 0aa9aee2e1..ddd3d8c262 100644
--- a/Modules/PlanarFigure/DataManagement/mitkPlanarFourPointAngle.cpp
+++ b/Modules/PlanarFigure/DataManagement/mitkPlanarFourPointAngle.cpp
@@ -1,79 +1,79 @@
/*===================================================================
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 "mitkPlanarFourPointAngle.h"
-#include "mitkGeometry2D.h"
+#include "mitkPlaneGeometry.h"
mitk::PlanarFourPointAngle::PlanarFourPointAngle()
: FEATURE_ID_ANGLE( this->AddFeature( "Angle", "deg" ) )
{
// Four point angle has two control points
this->ResetNumberOfControlPoints( 2 );
this->SetNumberOfPolyLines( 2 );
}
mitk::PlanarFourPointAngle::~PlanarFourPointAngle()
{
}
void mitk::PlanarFourPointAngle::GeneratePolyLine()
{
this->ClearPolyLines();
for (unsigned int i = 0; i < this->GetNumberOfControlPoints(); ++i)
this->AppendPointToPolyLine(i / 2, this->GetControlPoint(i));
}
void mitk::PlanarFourPointAngle::GenerateHelperPolyLine(double /*mmPerDisplayUnit*/, unsigned int /*displayHeight*/)
{
// Generate helper-poly-line for an four point angle
// Need to discuss a sensible implementation
}
void mitk::PlanarFourPointAngle::EvaluateFeaturesInternal()
{
if ( this->GetNumberOfControlPoints() < 4 )
{
// Angle not yet complete.
return;
}
// Calculate angle between lines
const Point2D &p0 = this->GetControlPoint( 0 );
const Point2D &p1 = this->GetControlPoint( 1 );
const Point2D &p2 = this->GetControlPoint( 2 );
const Point2D &p3 = this->GetControlPoint( 3 );
Vector2D v0 = p1 - p0;
Vector2D v1 = p3 - p2;
v0.Normalize();
v1.Normalize();
double angle = acos( v0 * v1 );
this->SetQuantity( FEATURE_ID_ANGLE, angle );
}
void mitk::PlanarFourPointAngle::PrintSelf( std::ostream& os, itk::Indent indent) const
{
Superclass::PrintSelf( os, indent );
}
diff --git a/Modules/PlanarFigure/DataManagement/mitkPlanarFourPointAngle.h b/Modules/PlanarFigure/DataManagement/mitkPlanarFourPointAngle.h
index 8915346fd6..b485beb721 100644
--- a/Modules/PlanarFigure/DataManagement/mitkPlanarFourPointAngle.h
+++ b/Modules/PlanarFigure/DataManagement/mitkPlanarFourPointAngle.h
@@ -1,93 +1,93 @@
/*===================================================================
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 _MITK_PLANAR_FOURPOINTANGLE_H_
#define _MITK_PLANAR_FOURPOINTANGLE_H_
#include "mitkPlanarFigure.h"
#include <MitkPlanarFigureExports.h>
namespace mitk
{
-class Geometry2D;
+class PlaneGeometry;
/**
* \brief Implementation of PlanarFigure representing a four point
* angle, which is defined by two non-intersecting lines in 2D. Each of those lines
* is defined by two control points.
*/
class MitkPlanarFigure_EXPORT PlanarFourPointAngle : public PlanarFigure
{
public:
mitkClassMacro( PlanarFourPointAngle, PlanarFigure );
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
public:
// Feature identifiers
const unsigned int FEATURE_ID_ANGLE;
/** \brief Place figure in its minimal configuration (a point at least)
* onto the given 2D geometry.
*
* Must be implemented in sub-classes.
*/
//virtual void Initialize();
/** \brief Four point angle has 4 control points per definition. */
unsigned int GetMinimumNumberOfControlPoints() const
{
return 4;
}
/** \brief Four point angle has 4 control points per definition. */
unsigned int GetMaximumNumberOfControlPoints() const
{
return 4;
}
protected:
PlanarFourPointAngle();
virtual ~PlanarFourPointAngle();
mitkCloneMacro(Self);
/** \brief Generates the poly-line representation of the planar figure. */
virtual void GeneratePolyLine();
/** \brief Generates the poly-lines that should be drawn the same size regardless of zoom.*/
virtual void GenerateHelperPolyLine(double mmPerDisplayUnit, unsigned int displayHeight);
/** \brief Calculates feature quantities of the planar figure. */
virtual void EvaluateFeaturesInternal();
virtual void PrintSelf( std::ostream &os, itk::Indent indent ) const;
private:
};
} // namespace mitk
#endif //_MITK_PLANAR_FOURPOINTANGLE_H_
diff --git a/Modules/PlanarFigure/DataManagement/mitkPlanarLine.cpp b/Modules/PlanarFigure/DataManagement/mitkPlanarLine.cpp
index 75f3c3d7e6..a534089a6a 100644
--- a/Modules/PlanarFigure/DataManagement/mitkPlanarLine.cpp
+++ b/Modules/PlanarFigure/DataManagement/mitkPlanarLine.cpp
@@ -1,65 +1,65 @@
/*===================================================================
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 "mitkPlanarLine.h"
-#include "mitkGeometry2D.h"
+#include "mitkPlaneGeometry.h"
mitk::PlanarLine::PlanarLine()
: FEATURE_ID_LENGTH( this->AddFeature( "Length", "mm" ) )
{
// Line has two control points
this->ResetNumberOfControlPoints( 2 );
this->SetNumberOfPolyLines( 1 );
}
mitk::PlanarLine::~PlanarLine()
{
}
void mitk::PlanarLine::GeneratePolyLine()
{
this->ClearPolyLines();
this->AppendPointToPolyLine(0, this->GetControlPoint(0));
this->AppendPointToPolyLine(0, this->GetControlPoint(1));
}
void mitk::PlanarLine::GenerateHelperPolyLine(double /*mmPerDisplayUnit*/, unsigned int /*displayHeight*/)
{
// A line does not require a helper object
}
void mitk::PlanarLine::EvaluateFeaturesInternal()
{
// Calculate line length
const Point3D &p0 = this->GetWorldControlPoint( 0 );
const Point3D &p1 = this->GetWorldControlPoint( 1 );
double length = p0.EuclideanDistanceTo( p1 );
this->SetQuantity( FEATURE_ID_LENGTH, length );
}
void mitk::PlanarLine::PrintSelf( std::ostream& os, itk::Indent indent) const
{
Superclass::PrintSelf( os, indent );
}
diff --git a/Modules/PlanarFigure/DataManagement/mitkPlanarLine.h b/Modules/PlanarFigure/DataManagement/mitkPlanarLine.h
index 2f3e41a22d..09732fcef3 100644
--- a/Modules/PlanarFigure/DataManagement/mitkPlanarLine.h
+++ b/Modules/PlanarFigure/DataManagement/mitkPlanarLine.h
@@ -1,93 +1,93 @@
/*===================================================================
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 _MITK_PLANAR_LINE_H_
#define _MITK_PLANAR_LINE_H_
#include "mitkPlanarFigure.h"
#include <MitkPlanarFigureExports.h>
namespace mitk
{
-class Geometry2D;
+class PlaneGeometry;
/**
* \brief Implementation of PlanarFigure representing a line
* through two control points
*/
class MitkPlanarFigure_EXPORT PlanarLine : public PlanarFigure
{
public:
mitkClassMacro( PlanarLine, PlanarFigure );
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** \brief Place figure in its minimal configuration (a point at least)
* onto the given 2D geometry.
*
* Must be implemented in sub-classes.
*/
//virtual void Initialize();
/** \brief Line has 2 control points per definition. */
unsigned int GetMinimumNumberOfControlPoints() const
{
return 2;
}
/** \brief Line has 2 control points per definition. */
unsigned int GetMaximumNumberOfControlPoints() const
{
return 2;
}
protected:
PlanarLine();
virtual ~PlanarLine();
mitkCloneMacro(Self);
/** \brief Generates the poly-line representation of the planar figure. */
virtual void GeneratePolyLine();
/** \brief Generates the poly-lines that should be drawn the same size regardless of zoom.*/
virtual void GenerateHelperPolyLine(double mmPerDisplayUnit, unsigned int displayHeight);
/** \brief Calculates feature quantities of the planar figure. */
virtual void EvaluateFeaturesInternal();
virtual void PrintSelf( std::ostream &os, itk::Indent indent ) const;
// Feature identifiers
const unsigned int FEATURE_ID_LENGTH;
private:
};
} // namespace mitk
#endif //_MITK_PLANAR_LINE_H_
diff --git a/Modules/PlanarFigure/DataManagement/mitkPlanarPolygon.cpp b/Modules/PlanarFigure/DataManagement/mitkPlanarPolygon.cpp
index be81602ce0..669d952f3f 100644
--- a/Modules/PlanarFigure/DataManagement/mitkPlanarPolygon.cpp
+++ b/Modules/PlanarFigure/DataManagement/mitkPlanarPolygon.cpp
@@ -1,274 +1,274 @@
/*===================================================================
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 "mitkPlanarPolygon.h"
-#include "mitkGeometry2D.h"
+#include "mitkPlaneGeometry.h"
#include "mitkProperties.h"
// stl related includes
#include <algorithm>
mitk::PlanarPolygon::PlanarPolygon()
: FEATURE_ID_CIRCUMFERENCE( this->AddFeature( "Circumference", "mm" ) ),
FEATURE_ID_AREA( this->AddFeature( "Area", "mm2" ) )
{
// Polygon has at least two control points
this->ResetNumberOfControlPoints( 2 );
this->SetNumberOfPolyLines( 1 );
// Polygon is closed by default
this->SetProperty( "closed", mitk::BoolProperty::New( true ) );
this->SetProperty( "subdivision", mitk::BoolProperty::New( false ) );
}
mitk::PlanarPolygon::~PlanarPolygon()
{
}
void mitk::PlanarPolygon::SetClosed( bool closed )
{
this->SetProperty( "closed", mitk::BoolProperty::New( closed ) );
if ( !closed )
{
// For non-closed polygons: use "Length" as feature name; disable area
this->SetFeatureName( FEATURE_ID_CIRCUMFERENCE, "Length" );
this->DeactivateFeature( FEATURE_ID_AREA );
}
else
{
// For closed polygons: use "Circumference" as feature name; enable area
this->SetFeatureName( FEATURE_ID_CIRCUMFERENCE, "Circumference" );
this->ActivateFeature( FEATURE_ID_AREA );
}
this->Modified();
}
void mitk::PlanarPolygon::GeneratePolyLine()
{
this->ClearPolyLines();
for (ControlPointListType::size_type i = 0; i < m_ControlPoints.size(); ++i)
this->AppendPointToPolyLine(0, this->GetControlPoint(i));
}
void mitk::PlanarPolygon::GenerateHelperPolyLine(double /*mmPerDisplayUnit*/, unsigned int /*displayHeight*/)
{
// A polygon does not require helper objects
}
void mitk::PlanarPolygon::EvaluateFeaturesInternal()
{
// Calculate circumference
double circumference = 0.0;
unsigned int i,j;
PolyLineType polyLine = m_PolyLines[0];
if(polyLine.empty())
return;
for ( i = 0; i <(polyLine.size()-1); ++i )
{
circumference += static_cast<Point2D>(polyLine[i]).EuclideanDistanceTo(
static_cast<Point2D>(polyLine[i + 1]) );
}
if ( this->IsClosed() )
{
circumference += static_cast<Point2D>(polyLine[i]).EuclideanDistanceTo(
static_cast<Point2D>(polyLine.front()) );
}
this->SetQuantity( FEATURE_ID_CIRCUMFERENCE, circumference );
// Calculate polygon area (if closed)
double area = 0.0;
bool intersection = false;
- if ( this->IsClosed() && (this->GetGeometry2D() != NULL) )
+ if ( this->IsClosed() && (this->GetPlaneGeometry() != NULL) )
{
// does PlanarPolygon overlap/intersect itself?
unsigned int numberOfPoints = polyLine.size();
if( numberOfPoints >= 4)
{
for ( i = 0; i < (numberOfPoints - 1); ++i )
{
// line 1
Point2D p0 = polyLine[i];
Point2D p1 = polyLine[i + 1];
// check for intersection with all other lines
for (j = i+1; j < (numberOfPoints - 1); ++j )
{
Point2D p2 = polyLine[j];
Point2D p3 = polyLine[j + 1];
intersection = CheckForLineIntersection(p0,p1,p2,p3);
if (intersection) break;
}
if (intersection) break; // only because the inner loop might have changed "intersection"
// last line from p_x to p_0
Point2D p2 = polyLine.front();
Point2D p3 = polyLine.back();
intersection = CheckForLineIntersection(p0,p1,p2,p3);
if (intersection) break;
}
}
// calculate area
for ( i = 0; i < polyLine.size(); ++i )
{
Point2D p0 = polyLine[i];
Point2D p1 = polyLine[ (i + 1) % polyLine.size() ];
area += p0[0] * p1[1] - p1[0] * p0[1];
}
area /= 2.0;
}
// set area if appropiate (i.e. closed and not intersected)
if(this->IsClosed() && !intersection)
{
SetQuantity( FEATURE_ID_AREA, fabs( area ) );
this->ActivateFeature( FEATURE_ID_AREA );
}
else
{
SetQuantity( FEATURE_ID_AREA, 0 );
this->DeactivateFeature( FEATURE_ID_AREA );
}
}
void mitk::PlanarPolygon::PrintSelf( std::ostream& os, itk::Indent indent) const
{
Superclass::PrintSelf( os, indent );
if (this->IsClosed())
os << indent << "Polygon is closed\n";
else
os << indent << "Polygon is not closed\n";
}
// based on
// http://flassari.is/2008/11/line-line-intersection-in-cplusplus/
bool mitk::PlanarPolygon::CheckForLineIntersection( const mitk::Point2D& p1, const mitk::Point2D& p2, const mitk::Point2D& p3, const mitk::Point2D& p4, Point2D& intersection ) const
{
// do not check for intersections with control points
if(p1 == p2 || p1 == p3 || p1 == p4 ||
p2 == p3 || p2 == p4 ||
p3 == p4)
return false;
// Store the values for fast access and easy
// equations-to-code conversion
double x1 = p1[0], x2 = p2[0], x3 = p3[0], x4 = p4[0];
double y1 = p1[1], y2 = p2[1], y3 = p3[1], y4 = p4[1];
double d = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
// If d is zero, there is no intersection
//if (d < mitk::eps) return false;
if (d == 0) return false;
// Get the x and y
double pre = (x1*y2 - y1*x2);
double post = (x3*y4 - y3*x4);
double x = ( pre * (x3 - x4) - (x1 - x2) * post ) / d;
double y = ( pre * (y3 - y4) - (y1 - y2) * post ) / d;
double tolerance = 0.001;
// Check if the x coordinates are within both lines, including tolerance
if ( x < ( std::min(x1, x2) - tolerance )
|| x > ( std::max(x1, x2) + tolerance )
|| x < ( std::min(x3, x4) - tolerance )
|| x > ( std::max(x3, x4) + tolerance )
)
{
return false;
}
// Check if the y coordinates are within both lines, including tolerance
if ( y < ( std::min(y1, y2) - tolerance )
|| y > ( std::max(y1, y2) + tolerance )
|| y < ( std::min(y3, y4) - tolerance )
|| y > ( std::max(y3, y4) + tolerance )
)
{
return false;
}
// point of intersection
Point2D ret; ret[0] = x; ret[1] = y;
intersection = ret;
return true;
}
bool mitk::PlanarPolygon::CheckForLineIntersection( const mitk::Point2D& p1, const mitk::Point2D& p2, const mitk::Point2D& p3, const mitk::Point2D& p4 ) const
{
mitk::Point2D intersection;
return mitk::PlanarPolygon::CheckForLineIntersection( p1, p2, p3, p4, intersection );
}
std::vector<mitk::Point2D> mitk::PlanarPolygon::CheckForLineIntersection( const mitk::Point2D& p1, const mitk::Point2D& p2 ) const
{
std::vector<mitk::Point2D> intersectionList;
ControlPointListType polyLinePoints;
PolyLineType tempList = m_PolyLines[0];
PolyLineType::iterator iter;
for( iter = tempList.begin(); iter != tempList.end(); ++iter )
{
polyLinePoints.push_back(*iter);
}
for ( ControlPointListType::size_type i=0; i<polyLinePoints.size()-1; i++ )
{
mitk::Point2D pnt1 = polyLinePoints[i];
mitk::Point2D pnt2 = polyLinePoints[i+1];
mitk::Point2D intersection;
if ( mitk::PlanarPolygon::CheckForLineIntersection( p1, p2, pnt1, pnt2, intersection ) )
{
intersectionList.push_back( intersection );
}
}
if ( this->IsClosed() )
{
mitk::Point2D intersection, lastControlPoint, firstControlPoint;
lastControlPoint = polyLinePoints.back();
firstControlPoint = polyLinePoints.front();
if ( mitk::PlanarPolygon::CheckForLineIntersection( lastControlPoint,
firstControlPoint, p1, p2, intersection ) )
{
intersectionList.push_back( intersection );
}
}
return intersectionList;
}
diff --git a/Modules/PlanarFigure/DataManagement/mitkPlanarPolygon.h b/Modules/PlanarFigure/DataManagement/mitkPlanarPolygon.h
index 7963fc0732..fa5c0c19b4 100644
--- a/Modules/PlanarFigure/DataManagement/mitkPlanarPolygon.h
+++ b/Modules/PlanarFigure/DataManagement/mitkPlanarPolygon.h
@@ -1,103 +1,103 @@
/*===================================================================
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 _MITK_PLANAR_POLYGON_H_
#define _MITK_PLANAR_POLYGON_H_
#include "mitkPlanarFigure.h"
#include <MitkPlanarFigureExports.h>
namespace mitk
{
-class Geometry2D;
+class PlaneGeometry;
/**
* \brief Implementation of PlanarFigure representing a polygon
* with two or more control points
*/
class MitkPlanarFigure_EXPORT PlanarPolygon : public PlanarFigure
{
public:
mitkClassMacro( PlanarPolygon, PlanarFigure );
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** \brief Set whether the polygon should be closed between first and last control point or not. */
virtual void SetClosed( bool closed );
itkBooleanMacro( Closed ); // Calls SetClosed(); no need to re-implement
/** \brief Place figure in its minimal configuration (a point at least)
* onto the given 2D geometry.
*
* Must be implemented in sub-classes.
*/
//virtual void Initialize();
/** \brief Polygon has 3 control points per definition. */
unsigned int GetMinimumNumberOfControlPoints() const
{
return 3;
}
/** \brief Polygon maximum number of control points is principally not limited. */
unsigned int GetMaximumNumberOfControlPoints() const
{
return 1000;
}
std::vector<mitk::Point2D> CheckForLineIntersection( const Point2D& p1, const Point2D& p2 ) const;
protected:
PlanarPolygon();
virtual ~PlanarPolygon();
mitkCloneMacro(Self);
/** \brief Generates the poly-line representation of the planar figure. */
virtual void GeneratePolyLine();
/** \brief Generates the poly-lines that should be drawn the same size regardless of zoom.*/
virtual void GenerateHelperPolyLine(double mmPerDisplayUnit, unsigned int displayHeight);
/** \brief Calculates feature quantities of the planar figure. */
virtual void EvaluateFeaturesInternal();
bool CheckForLineIntersection(const mitk::Point2D& p1, const mitk::Point2D& p2, const mitk::Point2D& p3, const mitk::Point2D& p4, Point2D& intersection) const ;
bool CheckForLineIntersection( const mitk::Point2D& p1, const mitk::Point2D& p2, const mitk::Point2D& p3, const mitk::Point2D& p4 ) const;
virtual void PrintSelf( std::ostream &os, itk::Indent indent ) const;
const unsigned int FEATURE_ID_CIRCUMFERENCE;
const unsigned int FEATURE_ID_AREA;
private:
};
} // namespace mitk
#endif //_MITK_PLANAR_POLYGON_H_
diff --git a/Modules/PlanarFigure/DataManagement/mitkPlanarRectangle.cpp b/Modules/PlanarFigure/DataManagement/mitkPlanarRectangle.cpp
index cfafc5ad35..cc7169ece3 100644
--- a/Modules/PlanarFigure/DataManagement/mitkPlanarRectangle.cpp
+++ b/Modules/PlanarFigure/DataManagement/mitkPlanarRectangle.cpp
@@ -1,146 +1,146 @@
/*===================================================================
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 "mitkProperties.h"
#include "mitkPlanarRectangle.h"
-#include "mitkGeometry2D.h"
+#include "mitkPlaneGeometry.h"
mitk::PlanarRectangle::PlanarRectangle()
: FEATURE_ID_CIRCUMFERENCE( this->AddFeature( "Circumference", "mm" ) ),
FEATURE_ID_AREA( this->AddFeature( "Area", "mm2" ) )
{
// Rectangle has four control points
this->ResetNumberOfControlPoints( 4 );
this->SetProperty( "closed", mitk::BoolProperty::New(true) );
this->SetNumberOfPolyLines( 1 );
}
mitk::PlanarRectangle::~PlanarRectangle()
{
}
bool mitk::PlanarRectangle::SetControlPoint( unsigned int index, const Point2D &point, bool createIfDoesNotExist )
{
// heres the deal with the rectangle:
// when a point is moved all corresponding corner points are moved with him
// e.g. if the lower right point (index=3) is moved the upper right point (index=1)
// is moved in the same x direction
// and the lower left point (index=2) is moved in the same y direction
// the upper left point (index=0) is left untouched
bool set = PlanarFigure::SetControlPoint( index, point, createIfDoesNotExist );
if(set)
{
// can be made better ...
unsigned int horizontalCorrespondingPointIndex = 1;
unsigned int verticalCorrespondingPointIndex = 3;
if(index == 1)
{
horizontalCorrespondingPointIndex = 0;
verticalCorrespondingPointIndex = 2;
}
else if(index == 2)
{
horizontalCorrespondingPointIndex = 3;
verticalCorrespondingPointIndex = 1;
}
else if(index == 3)
{
horizontalCorrespondingPointIndex = 2;
verticalCorrespondingPointIndex = 0;
}
Point2D verticalCorrespondingPoint = GetControlPoint( verticalCorrespondingPointIndex );
verticalCorrespondingPoint[0] = point[0];
PlanarFigure::SetControlPoint( verticalCorrespondingPointIndex, verticalCorrespondingPoint );
Point2D horizontalCorrespondingPoint = GetControlPoint( horizontalCorrespondingPointIndex );
horizontalCorrespondingPoint[1] = point[1];
PlanarFigure::SetControlPoint( horizontalCorrespondingPointIndex, horizontalCorrespondingPoint );
}
return set;
}
void mitk::PlanarRectangle::PlaceFigure( const mitk::Point2D &point )
{
PlanarFigure::PlaceFigure( point );
m_SelectedControlPoint = 3;
}
void mitk::PlanarRectangle::GeneratePolyLine()
{
this->ClearPolyLines();
for (unsigned int i = 0; i < this->GetNumberOfControlPoints(); ++i)
this->AppendPointToPolyLine(0, this->GetControlPoint(i));
}
void mitk::PlanarRectangle::GenerateHelperPolyLine(double /*mmPerDisplayUnit*/, unsigned int /*displayHeight*/)
{
// A polygon does not require helper objects
}
void mitk::PlanarRectangle::EvaluateFeaturesInternal()
{
// Calculate circumference
double circumference = 0.0;
unsigned int i;
for ( i = 0; i < this->GetNumberOfControlPoints(); ++i )
{
circumference += this->GetWorldControlPoint( i ).EuclideanDistanceTo(
this->GetWorldControlPoint( (i + 1) % this->GetNumberOfControlPoints() ) );
}
this->SetQuantity( FEATURE_ID_CIRCUMFERENCE, circumference );
// Calculate rectangle area (well, done a bit clumsy...)
double area = 0.0;
- if ( this->GetGeometry2D() != NULL )
+ if ( this->GetPlaneGeometry() != NULL )
{
for ( i = 0; i < this->GetNumberOfControlPoints(); ++i )
{
Point2D p0 = this->GetControlPoint( i );
Point2D p1 = this->GetControlPoint( (i + 1) % this->GetNumberOfControlPoints() );
area += p0[0] * p1[1] - p1[0] * p0[1];
}
area /= 2.0;
}
this->SetQuantity( FEATURE_ID_AREA, fabs(area) );
}
void mitk::PlanarRectangle::PrintSelf( std::ostream& os, itk::Indent indent) const
{
Superclass::PrintSelf( os, indent );
os << indent << "Number of control points: " << this->GetNumberOfControlPoints() << std::endl;
os << indent << "Control points:" << std::endl;
for ( unsigned int i = 0; i < this->GetNumberOfControlPoints(); ++i )
{
os << indent << indent << i << ": " <<GetControlPoint( i ) << std::endl;
}
}
diff --git a/Modules/PlanarFigure/DataManagement/mitkPlanarRectangle.h b/Modules/PlanarFigure/DataManagement/mitkPlanarRectangle.h
index 78b10503f7..2943a626c5 100644
--- a/Modules/PlanarFigure/DataManagement/mitkPlanarRectangle.h
+++ b/Modules/PlanarFigure/DataManagement/mitkPlanarRectangle.h
@@ -1,93 +1,93 @@
/*===================================================================
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 _MITK_PLANAR_RECTANGLE_H_
#define _MITK_PLANAR_RECTANGLE_H_
#include "mitkPlanarPolygon.h"
#include <MitkPlanarFigureExports.h>
namespace mitk
{
-class Geometry2D;
+class PlaneGeometry;
/**
* \brief Implementation of PlanarFigure representing a polygon
* with two or more control points
*/
class MitkPlanarFigure_EXPORT PlanarRectangle : public PlanarFigure
{
public:
mitkClassMacro( PlanarRectangle, PlanarFigure );
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** \brief Place figure in its minimal configuration (a point at least)
* onto the given 2D geometry.
*
* Must be implemented in sub-classes.
*/
//virtual void Initialize();
virtual void PlaceFigure( const Point2D &point );
/** \brief Polygon has 2 control points per definition. */
virtual unsigned int GetMinimumNumberOfControlPoints() const
{
return 4;
}
/** \brief Polygon maximum number of control points is principally not limited. */
virtual unsigned int GetMaximumNumberOfControlPoints() const
{
return 4;
}
virtual bool SetControlPoint( unsigned int index, const Point2D &point, bool createIfDoesNotExist = false);
protected:
PlanarRectangle();
virtual ~PlanarRectangle();
mitkCloneMacro(Self);
/** \brief Generates the poly-line representation of the planar figure. */
virtual void GeneratePolyLine();
/** \brief Generates the poly-lines that should be drawn the same size regardless of zoom.*/
virtual void GenerateHelperPolyLine(double mmPerDisplayUnit, unsigned int displayHeight);
/** \brief Calculates feature quantities of the planar figure. */
virtual void EvaluateFeaturesInternal();
virtual void PrintSelf( std::ostream &os, itk::Indent indent ) const;
const unsigned int FEATURE_ID_CIRCUMFERENCE;
const unsigned int FEATURE_ID_AREA;
private:
};
} // namespace mitk
#endif //_MITK_PLANAR_POLYGON_H_
diff --git a/Modules/PlanarFigure/DataManagement/mitkPlanarSubdivisionPolygon.cpp b/Modules/PlanarFigure/DataManagement/mitkPlanarSubdivisionPolygon.cpp
index 08c9948cef..db3ac6657b 100644
--- a/Modules/PlanarFigure/DataManagement/mitkPlanarSubdivisionPolygon.cpp
+++ b/Modules/PlanarFigure/DataManagement/mitkPlanarSubdivisionPolygon.cpp
@@ -1,132 +1,132 @@
/*===================================================================
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 "mitkPlanarSubdivisionPolygon.h"
-#include "mitkGeometry2D.h"
+#include "mitkPlaneGeometry.h"
#include "mitkProperties.h"
// stl related includes
#include <algorithm>
mitk::PlanarSubdivisionPolygon::PlanarSubdivisionPolygon():
m_TensionParameter(0.0625),
m_SubdivisionRounds(5)
{
// Polygon is subdivision (in contrast to parent class PlanarPolygon
this->SetProperty( "closed", mitk::BoolProperty::New( true ) );
this->SetProperty( "subdivision", mitk::BoolProperty::New( true ) );
// Other properties are inherited / already initialized by parent class PlanarPolygon
}
mitk::PlanarSubdivisionPolygon::~PlanarSubdivisionPolygon()
{
}
void mitk::PlanarSubdivisionPolygon::GeneratePolyLine()
{
this->ClearPolyLines();
ControlPointListType subdivisionPoints;
ControlPointListType newSubdivisionPoints;
subdivisionPoints.clear();
subdivisionPoints = m_ControlPoints;
if( m_ControlPoints.size() >= GetMinimumNumberOfControlPoints() )
{
for( unsigned int i=0; i < GetSubdivisionRounds(); i++ )
{
// Indices
unsigned int index, indexPrev, indexNext, indexNextNext;
unsigned int numberOfPoints = subdivisionPoints.size();
Point2D newPoint;
// Keep cycling our array indices forward until they wrap around at the end
for ( index = 0; index < numberOfPoints; ++index )
{
// Create new subdivision point according to formula
// p_new = (0.5 + tension) * (p_here + p_next) - tension * (p_prev + p_nextnext)
indexPrev = (numberOfPoints + index - 1) % numberOfPoints;
indexNext = (index + 1) % numberOfPoints;
indexNextNext = (index + 2) % numberOfPoints;
newPoint[0] = (0.5 + GetTensionParameter()) * (double)( subdivisionPoints[index][0] + subdivisionPoints[indexNext][0] )
- GetTensionParameter() * (double)( subdivisionPoints[indexPrev][0] + subdivisionPoints[indexNextNext][0]);
newPoint[1] = (0.5 + GetTensionParameter()) * (double)( subdivisionPoints[index][1] + subdivisionPoints[indexNext][1] )
- GetTensionParameter() * (double)( subdivisionPoints[indexPrev][1] + subdivisionPoints[indexNextNext][1]);
newSubdivisionPoints.push_back( newPoint );
}
ControlPointListType mergedSubdivisionPoints;
ControlPointListType::iterator it, itNew;
for ( it = subdivisionPoints.begin() , itNew = newSubdivisionPoints.begin();
it != subdivisionPoints.end();
++it, ++itNew )
{
mergedSubdivisionPoints.push_back( *it );
mergedSubdivisionPoints.push_back( *itNew );
}
subdivisionPoints = mergedSubdivisionPoints;
newSubdivisionPoints.clear();
}
}
bool isInitiallyPlaced = this->GetProperty("initiallyplaced");
unsigned int i;
ControlPointListType::iterator it;
for ( it = subdivisionPoints.begin(), i = 0;
it != subdivisionPoints.end();
++it, ++i )
{
// Determine the index of the control point FOLLOWING this poly-line element
// (this is needed by PlanarFigureInteractor to insert new points at the correct position,
// namely BEFORE the next control point)
unsigned int nextIndex;
if ( i == 0 )
{
// For the FIRST polyline point, use the index of the LAST control point
// (it will used to check if the mouse is near the very last polyline element)
nextIndex = m_ControlPoints.size() - 1;
}
else
{
// For all other polyline points, use the index of the control point succeeding it
// (for polyline points lying on control points, the index of the previous control point
// is used)
nextIndex = (((i - 1) >> this->GetSubdivisionRounds()) + 1) % m_ControlPoints.size();
if(!isInitiallyPlaced && nextIndex > m_ControlPoints.size()-2)
{
PolyLineElement elem( m_ControlPoints[m_ControlPoints.size()-1], nextIndex );
this->AppendPointToPolyLine( 0, elem );
break;
}
}
PolyLineElement elem( *it, nextIndex );
this->AppendPointToPolyLine( 0, elem );
}
subdivisionPoints.clear();
}
diff --git a/Modules/PlanarFigure/DataManagement/mitkPlanarSubdivisionPolygon.h b/Modules/PlanarFigure/DataManagement/mitkPlanarSubdivisionPolygon.h
index 65714615b4..9d086cb88c 100644
--- a/Modules/PlanarFigure/DataManagement/mitkPlanarSubdivisionPolygon.h
+++ b/Modules/PlanarFigure/DataManagement/mitkPlanarSubdivisionPolygon.h
@@ -1,107 +1,107 @@
/*===================================================================
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 _MITK_PLANAR_SUBDIVISION_POLYGON_H_
#define _MITK_PLANAR_SUBDIVISION_POLYGON_H_
#include "mitkPlanarFigure.h"
#include <MitkPlanarFigureExports.h>
#include "mitkPlanarPolygon.h"
namespace mitk
{
-class Geometry2D;
+class PlaneGeometry;
/**
* \brief Implementation of PlanarFigure representing a polygon
* with two or more control points
*/
class MitkPlanarFigure_EXPORT PlanarSubdivisionPolygon : public PlanarPolygon
{
public:
mitkClassMacro( PlanarSubdivisionPolygon, PlanarFigure );
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** \brief Subdivision Polygon has 3 control points per definition. */
unsigned int GetMinimumNumberOfControlPoints() const
{
return 3;
}
/** \brief Polygon maximum number of control points is principally not limited. */
unsigned int GetMaximumNumberOfControlPoints() const
{
return 1000;
}
/** \brief How many times should we generate a round of subdivisions? */
unsigned int GetSubdivisionRounds() const
{
return m_SubdivisionRounds;
}
void SetSubdivisionRounds( int subdivisionRounds )
{
m_SubdivisionRounds = subdivisionRounds;
}
/** \brief Parameter w_tension defines the tension.
* the higher w_tension, the lower the "tension" on points.
* Rule: 0 < w_tension < 0.1
* 0.0625 (1 / 16) seems to be a good value.
*/
float GetTensionParameter() const
{
return m_TensionParameter;
}
void SetTensionParameter(float tensionParameter )
{
m_TensionParameter = tensionParameter;
}
std::vector<mitk::Point2D> CheckForLineIntersection( const Point2D& p1, const Point2D& p2 ) const;
void IncreaseSubdivisions();
void DecreaseSubdivisions();
protected:
PlanarSubdivisionPolygon();
virtual ~PlanarSubdivisionPolygon();
mitkCloneMacro(Self);
/** \brief Generates the poly-line representation of the planar figure. */
virtual void GeneratePolyLine();
float m_TensionParameter;
int m_SubdivisionRounds;
private:
};
} // namespace mitk
#endif //_MITK_PLANAR_SUBDIVISION_POLYGON_H_
diff --git a/Modules/PlanarFigure/IO/mitkPlanarFigureReader.cpp b/Modules/PlanarFigure/IO/mitkPlanarFigureReader.cpp
index a4d2000bf8..c6e75220ae 100644
--- a/Modules/PlanarFigure/IO/mitkPlanarFigureReader.cpp
+++ b/Modules/PlanarFigure/IO/mitkPlanarFigureReader.cpp
@@ -1,444 +1,444 @@
/*===================================================================
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 "mitkPlanarFigureReader.h"
#include "mitkPlanarAngle.h"
#include "mitkPlanarCircle.h"
#include "mitkPlanarLine.h"
#include "mitkPlanarArrow.h"
#include "mitkPlanarCross.h"
#include "mitkPlanarFourPointAngle.h"
#include "mitkPlanarPolygon.h"
#include "mitkPlanarSubdivisionPolygon.h"
#include "mitkPlanarRectangle.h"
#include "mitkPlaneGeometry.h"
#include "mitkPlanarEllipse.h"
#include "mitkPlanarDoubleEllipse.h"
#include "mitkPlanarBezierCurve.h"
#include "mitkBasePropertySerializer.h"
#include <tinyxml.h>
#include <itksys/SystemTools.hxx>
mitk::PlanarFigureReader::PlanarFigureReader() : PlanarFigureSource(), FileReader(),
m_FileName(""), m_FilePrefix(""), m_FilePattern(""), m_Success(false)
{
this->SetNumberOfRequiredOutputs(1);
this->SetNumberOfIndexedOutputs(1);
this->SetNthOutput(0, this->MakeOutput(0));
m_CanReadFromMemory = true;
//this->Modified();
//this->GetOutput()->Modified();
//this->GetOutput()->ReleaseData();
}
mitk::PlanarFigureReader::~PlanarFigureReader()
{}
void mitk::PlanarFigureReader::GenerateData()
{
m_Success = false;
this->SetNumberOfIndexedOutputs(0); // reset all outputs, we add new ones depending on the file content
TiXmlDocument document;
if(m_ReadFromMemory)
{
if(m_MemoryBuffer == NULL || m_MemorySize == 0)
{
//check
itkWarningMacro( << "Sorry, memory buffer has not been set!" );
return;
}
if(m_MemoryBuffer[ m_MemorySize - 1 ] == '\0')
{
document.Parse(m_MemoryBuffer);
}
else
{
char * tmpArray = new char[(int)m_MemorySize+1];
tmpArray[m_MemorySize] = '\0';
memcpy(tmpArray,m_MemoryBuffer,m_MemorySize);
document.Parse(m_MemoryBuffer);
delete [] tmpArray;
}
}
else
{
if (m_FileName.empty())
{
itkWarningMacro( << "Sorry, filename has not been set!" );
return;
}
if (this->CanReadFile( m_FileName.c_str()) == false)
{
itkWarningMacro( << "Sorry, can't read file " << m_FileName << "!" );
return;
}
if (!document.LoadFile(m_FileName))
{
MITK_ERROR << "Could not open/read/parse " << m_FileName << ". TinyXML reports: '" << document.ErrorDesc() << "'. "
<< "The error occurred in row " << document.ErrorRow() << ", column " << document.ErrorCol() << ".";
return;
}
}
int fileVersion = 1;
TiXmlElement* versionObject = document.FirstChildElement("Version");
if (versionObject != NULL)
{
if ( versionObject->QueryIntAttribute( "FileVersion", &fileVersion ) != TIXML_SUCCESS )
{
MITK_WARN << m_FileName << " does not contain version information! Trying version 1 format." << std::endl;
}
}
else
{
MITK_WARN << m_FileName << " does not contain version information! Trying version 1 format." << std::endl;
}
if (fileVersion != 1) // add file version selection and version specific file parsing here, if newer file versions are created
{
MITK_WARN << "File version > 1 is not supported by this reader.";
return;
}
/* file version 1 reader code */
for( TiXmlElement* pfElement = document.FirstChildElement("PlanarFigure");
pfElement != NULL;
pfElement = pfElement->NextSiblingElement("PlanarFigure") )
{
if (pfElement == NULL)
continue;
std::string type = pfElement->Attribute("type");
mitk::PlanarFigure::Pointer planarFigure = NULL;
if (type == "PlanarAngle")
{
planarFigure = mitk::PlanarAngle::New();
}
else if (type == "PlanarCircle")
{
planarFigure = mitk::PlanarCircle::New();
}
else if (type == "PlanarEllipse")
{
planarFigure = mitk::PlanarEllipse::New();
}
else if (type == "PlanarCross")
{
planarFigure = mitk::PlanarCross::New();
}
else if (type == "PlanarFourPointAngle")
{
planarFigure = mitk::PlanarFourPointAngle::New();
}
else if (type == "PlanarLine")
{
planarFigure = mitk::PlanarLine::New();
}
else if (type == "PlanarPolygon")
{
planarFigure = mitk::PlanarPolygon::New();
}
else if (type == "PlanarSubdivisionPolygon")
{
planarFigure = mitk::PlanarSubdivisionPolygon::New();
}
else if (type == "PlanarRectangle")
{
planarFigure = mitk::PlanarRectangle::New();
}
else if (type == "PlanarArrow")
{
planarFigure = mitk::PlanarArrow::New();
}
else if (type == "PlanarDoubleEllipse")
{
planarFigure = mitk::PlanarDoubleEllipse::New();
}
else if (type == "PlanarBezierCurve")
{
planarFigure = mitk::PlanarBezierCurve::New();
}
else
{
// unknown type
MITK_WARN << "encountered unknown planar figure type '" << type << "'. Skipping this element.";
continue;
}
// Read properties of the planar figure
for( TiXmlElement* propertyElement = pfElement->FirstChildElement("property");
propertyElement != NULL;
propertyElement = propertyElement->NextSiblingElement("property") )
{
const char* keya = propertyElement->Attribute("key");
std::string key( keya ? keya : "");
const char* typea = propertyElement->Attribute("type");
std::string type( typea ? typea : "");
// hand propertyElement to specific reader
std::stringstream propertyDeserializerClassName;
propertyDeserializerClassName << type << "Serializer";
std::list<itk::LightObject::Pointer> readers =
itk::ObjectFactoryBase::CreateAllInstance(propertyDeserializerClassName.str().c_str());
if (readers.size() < 1)
{
MITK_ERROR << "No property reader found for " << type;
}
if (readers.size() > 1)
{
MITK_WARN << "Multiple property readers found for " << type << ". Using arbitrary first one.";
}
for ( std::list<itk::LightObject::Pointer>::iterator iter = readers.begin();
iter != readers.end();
++iter )
{
if (BasePropertySerializer* reader = dynamic_cast<BasePropertySerializer*>( iter->GetPointer() ) )
{
BaseProperty::Pointer property = reader->Deserialize( propertyElement->FirstChildElement() );
if (property.IsNotNull())
{
planarFigure->GetPropertyList()->ReplaceProperty(key, property);
}
else
{
MITK_ERROR << "There were errors while loading property '" << key << "' of type " << type << ". Your data may be corrupted";
}
break;
}
}
}
// If we load a planarFigure, it has definitely been placed correctly.
// If we do not set this property here, we cannot load old planarFigures
// without messing up the interaction (PF-Interactor needs this property.
planarFigure->GetPropertyList()->SetBoolProperty( "initiallyplaced", true );
// Read geometry of containing plane
TiXmlElement* geoElement = pfElement->FirstChildElement("Geometry");
if (geoElement != NULL)
{
try
{
// Create plane geometry
mitk::PlaneGeometry::Pointer planeGeo = mitk::PlaneGeometry::New();
// Extract and set plane transform parameters
DoubleList transformList = this->GetDoubleAttributeListFromXMLNode( geoElement->FirstChildElement( "transformParam" ), "param", 12 );
- typedef mitk::Geometry3D::TransformType TransformType;
+ typedef mitk::BaseGeometry::TransformType TransformType;
TransformType::ParametersType parameters;
parameters.SetSize( 12 );
unsigned int i;
DoubleList::iterator it;
for ( it = transformList.begin(), i = 0;
it != transformList.end();
++it, ++i )
{
parameters.SetElement( i, *it );
}
- typedef mitk::Geometry3D::TransformType TransformType;
+ typedef mitk::BaseGeometry::TransformType TransformType;
TransformType::Pointer affineGeometry = TransformType::New();
affineGeometry->SetParameters( parameters );
planeGeo->SetIndexToWorldTransform( affineGeometry );
// Extract and set plane bounds
DoubleList boundsList = this->GetDoubleAttributeListFromXMLNode( geoElement->FirstChildElement( "boundsParam" ), "bound", 6 );
- typedef mitk::Geometry3D::BoundsArrayType BoundsArrayType;
+ typedef mitk::BaseGeometry::BoundsArrayType BoundsArrayType;
BoundsArrayType bounds;
for ( it = boundsList.begin(), i = 0;
it != boundsList.end();
++it, ++i )
{
bounds[i] = *it;
}
planeGeo->SetBounds( bounds );
// Extract and set spacing and origin
Vector3D spacing = this->GetVectorFromXMLNode(geoElement->FirstChildElement("Spacing"));
planeGeo->SetSpacing( spacing );
Point3D origin = this->GetPointFromXMLNode(geoElement->FirstChildElement("Origin"));
planeGeo->SetOrigin( origin );
- planarFigure->SetGeometry2D(planeGeo);
+ planarFigure->SetPlaneGeometry(planeGeo);
}
catch (...)
{
}
}
TiXmlElement* cpElement = pfElement->FirstChildElement("ControlPoints");
bool first = true;
if (cpElement != NULL)
for( TiXmlElement* vertElement = cpElement->FirstChildElement("Vertex"); vertElement != NULL; vertElement = vertElement->NextSiblingElement("Vertex"))
{
if (vertElement == NULL)
continue;
int id = 0;
mitk::Point2D::ValueType x = 0.0;
mitk::Point2D::ValueType y = 0.0;
if (vertElement->QueryIntAttribute("id", &id) == TIXML_WRONG_TYPE)
return; // TODO: can we do a better error handling?
if (vertElement->QueryDoubleAttribute("x", &x) == TIXML_WRONG_TYPE)
return; // TODO: can we do a better error handling?
if (vertElement->QueryDoubleAttribute("y", &y) == TIXML_WRONG_TYPE)
return; // TODO: can we do a better error handling?
Point2D p;
p.SetElement(0, x);
p.SetElement(1, y);
if (first == true) // needed to set m_FigurePlaced to true
{
planarFigure->PlaceFigure(p);
first = false;
}
planarFigure->SetControlPoint(id, p, true);
}
// Calculate feature quantities of this PlanarFigure
planarFigure->EvaluateFeatures();
// Make sure that no control point is currently selected
planarFigure->DeselectControlPoint();
// \TODO: what about m_FigurePlaced and m_SelectedControlPoint ??
this->SetNthOutput( this->GetNumberOfOutputs(), planarFigure ); // add planarFigure as new output of this filter
}
m_Success = true;
}
mitk::Point3D mitk::PlanarFigureReader::GetPointFromXMLNode(TiXmlElement* e)
{
if (e == NULL)
throw std::invalid_argument("node invalid"); // TODO: can we do a better error handling?
mitk::Point3D point;
mitk::ScalarType p(-1.0);
if (e->QueryDoubleAttribute("x", &p) == TIXML_WRONG_TYPE)
throw std::invalid_argument("node malformatted"); // TODO: can we do a better error handling?
point.SetElement(0, p);
if (e->QueryDoubleAttribute("y", &p) == TIXML_WRONG_TYPE)
throw std::invalid_argument("node malformatted"); // TODO: can we do a better error handling?
point.SetElement(1, p);
if (e->QueryDoubleAttribute("z", &p) == TIXML_WRONG_TYPE)
throw std::invalid_argument("node malformatted"); // TODO: can we do a better error handling?
point.SetElement(2, p);
return point;
}
mitk::Vector3D mitk::PlanarFigureReader::GetVectorFromXMLNode(TiXmlElement* e)
{
if (e == NULL)
throw std::invalid_argument("node invalid"); // TODO: can we do a better error handling?
mitk::Vector3D vector;
mitk::ScalarType p(-1.0);
if (e->QueryDoubleAttribute("x", &p) == TIXML_WRONG_TYPE)
throw std::invalid_argument("node malformatted"); // TODO: can we do a better error handling?
vector.SetElement(0, p);
if (e->QueryDoubleAttribute("y", &p) == TIXML_WRONG_TYPE)
throw std::invalid_argument("node malformatted"); // TODO: can we do a better error handling?
vector.SetElement(1, p);
if (e->QueryDoubleAttribute("z", &p) == TIXML_WRONG_TYPE)
throw std::invalid_argument("node malformatted"); // TODO: can we do a better error handling?
vector.SetElement(2, p);
return vector;
}
mitk::PlanarFigureReader::DoubleList
mitk::PlanarFigureReader::GetDoubleAttributeListFromXMLNode(TiXmlElement* e, const char *attributeNameBase, unsigned int count)
{
DoubleList list;
if (e == NULL)
throw std::invalid_argument("node invalid"); // TODO: can we do a better error handling?
for ( unsigned int i = 0; i < count; ++i )
{
mitk::ScalarType p(-1.0);
std::stringstream attributeName;
attributeName << attributeNameBase << i;
if (e->QueryDoubleAttribute( attributeName.str().c_str(), &p ) == TIXML_WRONG_TYPE)
throw std::invalid_argument("node malformatted"); // TODO: can we do a better error handling?
list.push_back( p );
}
return list;
}
void mitk::PlanarFigureReader::GenerateOutputInformation()
{
}
int mitk::PlanarFigureReader::CanReadFile ( const char *name )
{
if (std::string(name).empty())
return false;
return (itksys::SystemTools::LowerCase(itksys::SystemTools::GetFilenameLastExtension(name)) == ".pf"); //assume, we can read all .pf files
//TiXmlDocument document(name);
//if (document.LoadFile() == false)
// return false;
//return (document.FirstChildElement("PlanarFigure") != NULL);
}
bool mitk::PlanarFigureReader::CanReadFile(const std::string filename, const std::string, const std::string)
{
if (filename.empty())
return false;
return (itksys::SystemTools::LowerCase(itksys::SystemTools::GetFilenameLastExtension(filename)) == ".pf"); //assume, we can read all .pf files
//TiXmlDocument document(filename);
//if (document.LoadFile() == false)
// return false;
//return (document.FirstChildElement("PlanarFigure") != NULL);
}
void mitk::PlanarFigureReader::ResizeOutputs( const unsigned int& num )
{
unsigned int prevNum = this->GetNumberOfOutputs();
this->SetNumberOfIndexedOutputs( num );
for ( unsigned int i = prevNum; i < num; ++i )
{
this->SetNthOutput( i, this->MakeOutput( i ).GetPointer() );
}
}
diff --git a/Modules/PlanarFigure/IO/mitkPlanarFigureWriter.cpp b/Modules/PlanarFigure/IO/mitkPlanarFigureWriter.cpp
index a73ec3029b..ad636be211 100644
--- a/Modules/PlanarFigure/IO/mitkPlanarFigureWriter.cpp
+++ b/Modules/PlanarFigure/IO/mitkPlanarFigureWriter.cpp
@@ -1,303 +1,303 @@
/*===================================================================
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 "mitkPlanarFigureWriter.h"
#include "mitkBasePropertySerializer.h"
#include "mitkPlaneGeometry.h"
#include <tinyxml.h>
mitk::PlanarFigureWriter::PlanarFigureWriter()
: m_FileName(""), m_FilePrefix(""), m_FilePattern(""), m_Extension(".pf"),
m_MimeType("application/MITK.PlanarFigure"), m_Success(false)
{
this->SetNumberOfRequiredInputs( 1 );
this->SetNumberOfIndexedOutputs( 0 );
//this->SetNthOutput( 0, mitk::PlanarFigure::New().GetPointer() );
m_CanWriteToMemory = true;
}
mitk::PlanarFigureWriter::~PlanarFigureWriter()
{}
void mitk::PlanarFigureWriter::GenerateData()
{
m_Success = false;
if (!m_WriteToMemory && m_FileName.empty())
{
MITK_ERROR << "Could not write planar figures. File name is invalid";
throw std::invalid_argument("file name is empty");
}
TiXmlDocument document;
TiXmlDeclaration* decl = new TiXmlDeclaration( "1.0", "", "" ); // TODO what to write here? encoding? etc....
document.LinkEndChild( decl );
TiXmlElement* version = new TiXmlElement("Version");
version->SetAttribute("Writer", __FILE__ );
version->SetAttribute("CVSRevision", "$Revision: 17055 $" );
version->SetAttribute("FileVersion", 1 );
document.LinkEndChild(version);
/* create xml element for each input */
for ( unsigned int i = 0 ; i < this->GetNumberOfInputs(); ++i )
{
// Create root element for this PlanarFigure
InputType::Pointer pf = this->GetInput( i );
if (pf.IsNull())
continue;
TiXmlElement* pfElement = new TiXmlElement("PlanarFigure");
pfElement->SetAttribute("type", pf->GetNameOfClass());
document.LinkEndChild(pfElement);
if ( pf->GetNumberOfControlPoints() == 0 )
continue;
//PlanarFigure::VertexContainerType* vertices = pf->GetControlPoints();
//if (vertices == NULL)
// continue;
// Serialize property list of PlanarFigure
mitk::PropertyList::Pointer propertyList = pf->GetPropertyList();
mitk::PropertyList::PropertyMap::const_iterator it;
for ( it = propertyList->GetMap()->begin(); it != propertyList->GetMap()->end(); ++it )
{
// Create seralizer for this property
const mitk::BaseProperty* prop = it->second;
std::string serializerName = std::string( prop->GetNameOfClass() ) + "Serializer";
std::list< itk::LightObject::Pointer > allSerializers = itk::ObjectFactoryBase::CreateAllInstance(
serializerName.c_str() );
if ( allSerializers.size() != 1 )
{
// No or too many serializer(s) found, skip this property
continue;
}
mitk::BasePropertySerializer* serializer = dynamic_cast< mitk::BasePropertySerializer* >(
allSerializers.begin()->GetPointer() );
if ( serializer == NULL )
{
// Serializer not valid; skip this property
}
TiXmlElement* keyElement = new TiXmlElement( "property" );
keyElement->SetAttribute( "key", it->first );
keyElement->SetAttribute( "type", prop->GetNameOfClass() );
serializer->SetProperty( prop );
TiXmlElement* valueElement = NULL;
try
{
valueElement = serializer->Serialize();
}
catch (...)
{
}
if ( valueElement == NULL )
{
// Serialization failed; skip this property
continue;
}
// Add value to property element
keyElement->LinkEndChild( valueElement );
// Append serialized property to property list
pfElement->LinkEndChild( keyElement );
}
// Serialize control points of PlanarFigure
TiXmlElement* controlPointsElement = new TiXmlElement("ControlPoints");
pfElement->LinkEndChild(controlPointsElement);
for (unsigned int i = 0; i < pf->GetNumberOfControlPoints(); i++)
{
TiXmlElement* vElement = new TiXmlElement("Vertex");
vElement->SetAttribute("id", i);
vElement->SetDoubleAttribute("x", pf->GetControlPoint(i)[0]);
vElement->SetDoubleAttribute("y", pf->GetControlPoint(i)[1]);
controlPointsElement->LinkEndChild(vElement);
}
TiXmlElement* geoElement = new TiXmlElement("Geometry");
- const PlaneGeometry* planeGeo = dynamic_cast<const PlaneGeometry*>(pf->GetGeometry2D());
+ const PlaneGeometry* planeGeo = dynamic_cast<const PlaneGeometry*>(pf->GetPlaneGeometry());
if (planeGeo != NULL)
{
// Write parameters of IndexToWorldTransform of the PlaneGeometry
typedef mitk::Geometry3D::TransformType TransformType;
const TransformType* affineGeometry = planeGeo->GetIndexToWorldTransform();
const TransformType::ParametersType& parameters = affineGeometry->GetParameters();
TiXmlElement* vElement = new TiXmlElement( "transformParam" );
for ( unsigned int i = 0; i < affineGeometry->GetNumberOfParameters(); ++i )
{
std::stringstream paramName;
paramName << "param" << i;
vElement->SetDoubleAttribute( paramName.str().c_str(), parameters.GetElement( i ) );
}
geoElement->LinkEndChild( vElement );
// Write bounds of the PlaneGeometry
typedef mitk::Geometry3D::BoundsArrayType BoundsArrayType;
const BoundsArrayType& bounds = planeGeo->GetBounds();
vElement = new TiXmlElement( "boundsParam" );
for ( unsigned int i = 0; i < 6; ++i )
{
std::stringstream boundName;
boundName << "bound" << i;
vElement->SetDoubleAttribute( boundName.str().c_str(), bounds.GetElement( i ) );
}
geoElement->LinkEndChild( vElement );
// Write spacing and origin of the PlaneGeometry
Vector3D spacing = planeGeo->GetSpacing();
Point3D origin = planeGeo->GetOrigin();
geoElement->LinkEndChild(this->CreateXMLVectorElement("Spacing", spacing));
geoElement->LinkEndChild(this->CreateXMLVectorElement("Origin", origin));
pfElement->LinkEndChild(geoElement);
}
}
if(m_WriteToMemory)
{
// Declare a printer
TiXmlPrinter printer;
// attach it to the document you want to convert in to a std::string
document.Accept(&printer);
// Create memory buffer and print tinyxmldocument there...
m_MemoryBufferSize = printer.Size() + 1;
m_MemoryBuffer = new char[m_MemoryBufferSize];
strcpy(m_MemoryBuffer,printer.CStr());
}
else
{
if (document.SaveFile( m_FileName) == false)
{
MITK_ERROR << "Could not write planar figures to " << m_FileName << "\nTinyXML reports '" << document.ErrorDesc() << "'";
throw std::ios_base::failure("Error during writing of planar figure xml file.");
}
}
m_Success = true;
}
void mitk::PlanarFigureWriter::ReleaseMemory()
{
if(m_MemoryBuffer != NULL)
{
delete [] m_MemoryBuffer;
}
}
TiXmlElement* mitk::PlanarFigureWriter::CreateXMLVectorElement(const char* name, itk::FixedArray<mitk::ScalarType, 3> v)
{
TiXmlElement* vElement = new TiXmlElement(name);
vElement->SetDoubleAttribute("x", v.GetElement(0));
vElement->SetDoubleAttribute("y", v.GetElement(1));
vElement->SetDoubleAttribute("z", v.GetElement(2));
return vElement;
}
void mitk::PlanarFigureWriter::ResizeInputs( const unsigned int& num )
{
//unsigned int prevNum = this->GetNumberOfInputs();
this->SetNumberOfIndexedInputs( num );
//for ( unsigned int i = prevNum; i < num; ++i )
//{
// this->SetNthInput( i, mitk::PlanarFigure::New().GetPointer() );
//}
}
void mitk::PlanarFigureWriter::SetInput( InputType* PlanarFigure )
{
this->ProcessObject::SetNthInput( 0, PlanarFigure );
}
void mitk::PlanarFigureWriter::SetInput( const unsigned int& id, InputType* PlanarFigure )
{
if ( id >= this->GetNumberOfInputs() )
this->ResizeInputs( id + 1 );
this->ProcessObject::SetNthInput( id, PlanarFigure );
}
mitk::PlanarFigure* mitk::PlanarFigureWriter::GetInput()
{
if ( this->GetNumberOfInputs() < 1 )
return NULL;
else
return dynamic_cast<InputType*> ( this->GetInput( 0 ) );
}
mitk::PlanarFigure* mitk::PlanarFigureWriter::GetInput( const unsigned int& num )
{
return dynamic_cast<InputType*> ( this->ProcessObject::GetInput( num ) );
}
bool mitk::PlanarFigureWriter::CanWriteDataType( DataNode* input )
{
if ( input == NULL )
return false;
mitk::BaseData* data = input->GetData();
if ( data == NULL)
return false;
mitk::PlanarFigure::Pointer PlanarFigure = dynamic_cast<mitk::PlanarFigure*>( data );
if( PlanarFigure.IsNull() )
return false;
// add code for special subclasses here
return true;
}
void mitk::PlanarFigureWriter::SetInput( DataNode* input )
{
if (this->CanWriteDataType(input))
this->ProcessObject::SetNthInput( 0, dynamic_cast<mitk::PlanarFigure*>( input->GetData() ) );
}
std::string mitk::PlanarFigureWriter::GetWritenMIMEType()
{
return m_MimeType;
}
std::vector<std::string> mitk::PlanarFigureWriter::GetPossibleFileExtensions()
{
std::vector<std::string> possibleFileExtensions;
possibleFileExtensions.push_back(m_Extension);
return possibleFileExtensions;
}
std::string mitk::PlanarFigureWriter::GetFileExtension()
{
return m_Extension;
}
diff --git a/Modules/PlanarFigure/Interactions/mitkPlanarFigureInteractor.cpp b/Modules/PlanarFigure/Interactions/mitkPlanarFigureInteractor.cpp
index a4a1b3bfb0..bd8289c4b7 100644
--- a/Modules/PlanarFigure/Interactions/mitkPlanarFigureInteractor.cpp
+++ b/Modules/PlanarFigure/Interactions/mitkPlanarFigureInteractor.cpp
@@ -1,950 +1,949 @@
/*===================================================================
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.
===================================================================*/
#define PLANARFIGUREINTERACTOR_DBG MITK_DEBUG("PlanarFigureInteractor") << __LINE__ << ": "
#include "mitkPlanarFigureInteractor.h"
#include "mitkPlanarFigure.h"
#include "mitkPlanarPolygon.h"
#include "mitkInteractionPositionEvent.h"
#include "mitkInternalEvent.h"
#include "mitkBaseRenderer.h"
#include "mitkRenderingManager.h"
#include "mitkPlaneGeometry.h"
-#include "mitkGeometry2D.h"
//how precise must the user pick the point
//default value
mitk::PlanarFigureInteractor::PlanarFigureInteractor()
: DataInteractor()
, m_Precision( 6.5 )
, m_MinimumPointDistance( 25.0 )
, m_IsHovering( false )
, m_LastPointWasValid( false )
{
}
mitk::PlanarFigureInteractor::~PlanarFigureInteractor()
{
}
void mitk::PlanarFigureInteractor::ConnectActionsAndFunctions()
{
CONNECT_CONDITION("figure_is_on_current_slice", CheckFigureOnRenderingGeometry);
CONNECT_CONDITION("figure_is_placed", CheckFigurePlaced);
CONNECT_CONDITION("minimal_figure_is_finished", CheckMinimalFigureFinished);
CONNECT_CONDITION("hovering_above_figure", CheckFigureHovering);
CONNECT_CONDITION("hovering_above_point", CheckControlPointHovering);
CONNECT_CONDITION("figure_is_selected", CheckSelection);
CONNECT_CONDITION("point_is_valid", CheckPointValidity);
CONNECT_CONDITION("figure_is_finished", CheckFigureFinished);
CONNECT_CONDITION("reset_on_point_select_needed", CheckResetOnPointSelect);
CONNECT_CONDITION("points_can_be_added_or_removed", CheckFigureIsExtendable);
CONNECT_FUNCTION( "finalize_figure", FinalizeFigure);
CONNECT_FUNCTION( "hide_preview_point", HidePreviewPoint )
CONNECT_FUNCTION( "hide_control_points", HideControlPoints )
CONNECT_FUNCTION( "set_preview_point_position", SetPreviewPointPosition )
CONNECT_FUNCTION( "move_current_point", MoveCurrentPoint);
CONNECT_FUNCTION( "deselect_point", DeselectPoint);
CONNECT_FUNCTION( "add_new_point", AddPoint);
CONNECT_FUNCTION( "add_initial_point", AddInitialPoint);
CONNECT_FUNCTION( "remove_selected_point", RemoveSelectedPoint);
CONNECT_FUNCTION( "request_context_menu", RequestContextMenu);
CONNECT_FUNCTION( "select_figure", SelectFigure );
CONNECT_FUNCTION( "select_point", SelectPoint );
CONNECT_FUNCTION( "end_interaction", EndInteraction );
CONNECT_FUNCTION( "start_hovering", StartHovering )
CONNECT_FUNCTION( "end_hovering", EndHovering );
}
bool mitk::PlanarFigureInteractor::CheckFigurePlaced( const InteractionEvent* /*interactionEvent*/ )
{
mitk::PlanarFigure *planarFigure = dynamic_cast<mitk::PlanarFigure *>( GetDataNode()->GetData() );
bool isFigureFinished = false;
planarFigure->GetPropertyList()->GetBoolProperty( "initiallyplaced", isFigureFinished );
return planarFigure->IsPlaced() && isFigureFinished;
}
bool mitk::PlanarFigureInteractor::MoveCurrentPoint(StateMachineAction*, InteractionEvent* interactionEvent)
{
mitk::InteractionPositionEvent* positionEvent = dynamic_cast<mitk::InteractionPositionEvent*>( interactionEvent );
if ( positionEvent == NULL )
return false;
bool isEditable = true;
GetDataNode()->GetBoolProperty( "planarfigure.iseditable", isEditable );
mitk::PlanarFigure *planarFigure = dynamic_cast<mitk::PlanarFigure *>(
GetDataNode()->GetData() );
- mitk::Geometry2D *planarFigureGeometry =
- dynamic_cast< Geometry2D * >( planarFigure->GetGeometry( 0 ) );
+ mitk::PlaneGeometry *planarFigureGeometry =
+ dynamic_cast< PlaneGeometry * >( planarFigure->GetGeometry( 0 ) );
- // Extract point in 2D world coordinates (relative to Geometry2D of
+ // Extract point in 2D world coordinates (relative to PlaneGeometry of
// PlanarFigure)
Point2D point2D;
if ( !this->TransformPositionEventToPoint2D( positionEvent, planarFigureGeometry, point2D ) || !isEditable )
{
return false;
}
// check if the control points shall be hidden during interaction
bool hidecontrolpointsduringinteraction = false;
GetDataNode()->GetBoolProperty( "planarfigure.hidecontrolpointsduringinteraction", hidecontrolpointsduringinteraction );
// hide the control points if necessary
//interactionEvent->GetSender()->GetDataStorage()->BlockNodeModifiedEvents( true );
GetDataNode()->SetBoolProperty( "planarfigure.drawcontrolpoints", !hidecontrolpointsduringinteraction );
//interactionEvent->GetSender()->GetDataStorage()->BlockNodeModifiedEvents( false );
// Move current control point to this point
planarFigure->SetCurrentControlPoint( point2D );
// Re-evaluate features
planarFigure->EvaluateFeatures();
// Update rendered scene
interactionEvent->GetSender()->GetRenderingManager()->RequestUpdateAll();
return true;
}
bool mitk::PlanarFigureInteractor::FinalizeFigure( StateMachineAction*, InteractionEvent* interactionEvent )
{
mitk::PlanarFigure *planarFigure = dynamic_cast<mitk::PlanarFigure *>( GetDataNode()->GetData() );
planarFigure->Modified();
planarFigure->DeselectControlPoint();
planarFigure->RemoveLastControlPoint();
planarFigure->SetProperty( "initiallyplaced", mitk::BoolProperty::New( true ) );
GetDataNode()->SetBoolProperty( "planarfigure.drawcontrolpoints", true );
GetDataNode()->Modified();
planarFigure->InvokeEvent( EndPlacementPlanarFigureEvent() );
planarFigure->InvokeEvent( EndInteractionPlanarFigureEvent() );
interactionEvent->GetSender()->GetRenderingManager()->RequestUpdateAll();
return false;
}
bool mitk::PlanarFigureInteractor::EndInteraction( StateMachineAction*, InteractionEvent* interactionEvent )
{
mitk::PlanarFigure *planarFigure = dynamic_cast<mitk::PlanarFigure *>( GetDataNode()->GetData() );
GetDataNode()->SetBoolProperty( "planarfigure.drawcontrolpoints", true );
planarFigure->Modified();
planarFigure->InvokeEvent( EndInteractionPlanarFigureEvent() );
interactionEvent->GetSender()->GetRenderingManager()->RequestUpdateAll();
return false;
}
bool mitk::PlanarFigureInteractor::EndHovering( StateMachineAction*, InteractionEvent* interactionEvent )
{
mitk::PlanarFigure *planarFigure = dynamic_cast<mitk::PlanarFigure *>( GetDataNode()->GetData() );
planarFigure->ResetPreviewContolPoint();
// Invoke end-hover event once the mouse is exiting the figure area
m_IsHovering = false;
planarFigure->InvokeEvent( EndHoverPlanarFigureEvent() );
// Set bool property to indicate that planar figure is no longer in "hovering" mode
GetDataNode()->SetBoolProperty( "planarfigure.ishovering", false );
interactionEvent->GetSender()->GetRenderingManager()->RequestUpdateAll();
return false;
}
bool mitk::PlanarFigureInteractor::CheckMinimalFigureFinished( const InteractionEvent* /*interactionEvent*/ )
{
mitk::PlanarFigure *planarFigure = dynamic_cast<mitk::PlanarFigure *>( GetDataNode()->GetData() );
return ( planarFigure->GetNumberOfControlPoints() >= planarFigure->GetMinimumNumberOfControlPoints() );
}
bool mitk::PlanarFigureInteractor::CheckFigureFinished( const InteractionEvent* /*interactionEvent*/ )
{
mitk::PlanarFigure *planarFigure = dynamic_cast<mitk::PlanarFigure *>( GetDataNode()->GetData() );
return ( planarFigure->GetNumberOfControlPoints() >= planarFigure->GetMaximumNumberOfControlPoints() );
}
bool mitk::PlanarFigureInteractor::CheckFigureIsExtendable( const InteractionEvent* /*interactionEvent*/ )
{
bool isExtendable = false;
GetDataNode()->GetBoolProperty("planarfigure.isextendable", isExtendable);
return isExtendable;
}
bool mitk::PlanarFigureInteractor::DeselectPoint(StateMachineAction*, InteractionEvent* /*interactionEvent*/)
{
mitk::PlanarFigure *planarFigure = dynamic_cast<mitk::PlanarFigure *>(
GetDataNode()->GetData() );
bool wasSelected = planarFigure->DeselectControlPoint();
if ( wasSelected )
{
// Issue event so that listeners may update themselves
planarFigure->Modified();
planarFigure->InvokeEvent( EndInteractionPlanarFigureEvent() );
GetDataNode()->SetBoolProperty( "planarfigure.drawcontrolpoints", true );
// GetDataNode()->SetBoolProperty( "planarfigure.ishovering", false );
GetDataNode()->Modified();
}
return true;
}
bool mitk::PlanarFigureInteractor::AddPoint(StateMachineAction*, InteractionEvent* interactionEvent)
{
mitk::InteractionPositionEvent* positionEvent = dynamic_cast<mitk::InteractionPositionEvent*>( interactionEvent );
if ( positionEvent == NULL )
return false;
bool selected = false;
bool isEditable = true;
GetDataNode()->GetBoolProperty("selected", selected);
GetDataNode()->GetBoolProperty( "planarfigure.iseditable", isEditable );
if ( !selected || !isEditable )
{
return false;
}
mitk::PlanarFigure *planarFigure = dynamic_cast<mitk::PlanarFigure *>(
GetDataNode()->GetData() );
- mitk::Geometry2D *planarFigureGeometry =
- dynamic_cast< Geometry2D * >( planarFigure->GetGeometry( 0 ) );
+ mitk::PlaneGeometry *planarFigureGeometry =
+ dynamic_cast< PlaneGeometry * >( planarFigure->GetGeometry( 0 ) );
// If the planarFigure already has reached the maximum number
if ( planarFigure->GetNumberOfControlPoints() >= planarFigure->GetMaximumNumberOfControlPoints() )
{
return false;
}
- // Extract point in 2D world coordinates (relative to Geometry2D of
+ // Extract point in 2D world coordinates (relative to PlaneGeometry of
// PlanarFigure)
Point2D point2D, projectedPoint;
if ( !this->TransformPositionEventToPoint2D( positionEvent, planarFigureGeometry, point2D ) )
{
return false;
}
// TODO: check segment of polyline we clicked in
int nextIndex = -1;
// We only need to check which position to insert the control point
// when interacting with a PlanarPolygon. For all other types
// new control points will always be appended
/*
* Added check for "initiallyplaced" due to bug 13097:
*
* There are two possible cases in which a point can be inserted into a PlanarPolygon:
*
* 1. The figure is currently drawn -> the point will be appended at the end of the figure
* 2. A point is inserted at a userdefined position after the initial placement of the figure is finished
*
* In the second case we need to determine the proper insertion index. In the first case the index always has
* to be -1 so that the point is appended to the end.
*
* These changes are necessary because of a mac os x specific issue: If a users draws a PlanarPolygon then the
* next point to be added moves according to the mouse position. If then the user left clicks in order to add
* a point one would assume the last move position is identical to the left click position. This is actually the
* case for windows and linux but somehow NOT for mac. Because of the insertion logic of a new point in the
* PlanarFigure then for mac the wrong current selected point is determined.
*
* With this check here this problem can be avoided. However a redesign of the insertion logic should be considered
*/
bool isFigureFinished = false;
planarFigure->GetPropertyList()->GetBoolProperty( "initiallyplaced", isFigureFinished );
mitk::BaseRenderer *renderer = interactionEvent->GetSender();
- const Geometry2D *projectionPlane = renderer->GetCurrentWorldGeometry2D();
+ const PlaneGeometry *projectionPlane = renderer->GetCurrentWorldPlaneGeometry();
if ( dynamic_cast<mitk::PlanarPolygon*>( planarFigure ) && isFigureFinished)
{
nextIndex = this->IsPositionOverFigure(
positionEvent,
planarFigure,
planarFigureGeometry,
projectionPlane,
renderer->GetDisplayGeometry(),
projectedPoint
);
}
// Add point as new control point
renderer->GetDisplayGeometry()->DisplayToWorld( projectedPoint, projectedPoint );
if ( planarFigure->IsPreviewControlPointVisible() )
{
point2D = planarFigure->GetPreviewControlPoint();
}
planarFigure->AddControlPoint( point2D, nextIndex );
if ( planarFigure->IsPreviewControlPointVisible() )
{
planarFigure->SelectControlPoint( nextIndex );
planarFigure->ResetPreviewContolPoint();
}
// Re-evaluate features
planarFigure->EvaluateFeatures();
//this->LogPrintPlanarFigureQuantities( planarFigure );
// Update rendered scene
renderer->GetRenderingManager()->RequestUpdateAll();
return true;
}
bool mitk::PlanarFigureInteractor::AddInitialPoint(StateMachineAction*, InteractionEvent* interactionEvent)
{
mitk::InteractionPositionEvent* positionEvent = dynamic_cast<mitk::InteractionPositionEvent*>( interactionEvent );
if ( positionEvent == NULL )
return false;
mitk::PlanarFigure *planarFigure = dynamic_cast<mitk::PlanarFigure *>( GetDataNode()->GetData() );
mitk::BaseRenderer *renderer = interactionEvent->GetSender();
- mitk::Geometry2D *planarFigureGeometry = dynamic_cast< Geometry2D * >( planarFigure->GetGeometry( 0 ) );
+ mitk::PlaneGeometry *planarFigureGeometry = dynamic_cast< PlaneGeometry * >( planarFigure->GetGeometry( 0 ) );
// Invoke event to notify listeners that placement of this PF starts now
planarFigure->InvokeEvent( StartPlacementPlanarFigureEvent() );
- // Use Geometry2D of the renderer clicked on for this PlanarFigure
+ // Use PlaneGeometry of the renderer clicked on for this PlanarFigure
mitk::PlaneGeometry *planeGeometry = const_cast< mitk::PlaneGeometry * >(
dynamic_cast< const mitk::PlaneGeometry * >(
renderer->GetSliceNavigationController()->GetCurrentPlaneGeometry() ) );
if ( planeGeometry != NULL )
{
planarFigureGeometry = planeGeometry;
- planarFigure->SetGeometry2D( planeGeometry );
+ planarFigure->SetPlaneGeometry( planeGeometry );
}
else
{
return false;
}
- // Extract point in 2D world coordinates (relative to Geometry2D of
+ // Extract point in 2D world coordinates (relative to PlaneGeometry of
// PlanarFigure)
Point2D point2D;
if ( !this->TransformPositionEventToPoint2D( positionEvent, planarFigureGeometry, point2D ) )
{
return false;
}
// Place PlanarFigure at this point
planarFigure->PlaceFigure( point2D );
// Re-evaluate features
planarFigure->EvaluateFeatures();
//this->LogPrintPlanarFigureQuantities( planarFigure );
// Set a bool property indicating that the figure has been placed in
// the current RenderWindow. This is required so that the same render
- // window can be re-aligned to the Geometry2D of the PlanarFigure later
+ // window can be re-aligned to the PlaneGeometry of the PlanarFigure later
// on in an application.
GetDataNode()->SetBoolProperty( "PlanarFigureInitializedWindow", true, renderer );
// Update rendered scene
renderer->GetRenderingManager()->RequestUpdateAll();
return true;
}
bool mitk::PlanarFigureInteractor::StartHovering( StateMachineAction*, InteractionEvent* interactionEvent )
{
mitk::InteractionPositionEvent* positionEvent = dynamic_cast<mitk::InteractionPositionEvent*>( interactionEvent );
if ( positionEvent == NULL )
return false;
mitk::PlanarFigure *planarFigure = dynamic_cast<mitk::PlanarFigure *>( GetDataNode()->GetData() );
mitk::BaseRenderer *renderer = interactionEvent->GetSender();
if ( !m_IsHovering )
{
// Invoke hover event once when the mouse is entering the figure area
m_IsHovering = true;
planarFigure->InvokeEvent( StartHoverPlanarFigureEvent() );
// Set bool property to indicate that planar figure is currently in "hovering" mode
GetDataNode()->SetBoolProperty( "planarfigure.ishovering", true );
renderer->GetRenderingManager()->RequestUpdateAll();
}
return true;
}
bool mitk::PlanarFigureInteractor::SetPreviewPointPosition( StateMachineAction*, InteractionEvent* interactionEvent )
{
mitk::InteractionPositionEvent* positionEvent = dynamic_cast<mitk::InteractionPositionEvent*>( interactionEvent );
if ( positionEvent == NULL )
return false;
mitk::PlanarFigure *planarFigure = dynamic_cast<mitk::PlanarFigure *>( GetDataNode()->GetData() );
mitk::BaseRenderer *renderer = interactionEvent->GetSender();
planarFigure->DeselectControlPoint();
mitk::Point2D pointProjectedOntoLine = positionEvent->GetPointerPositionOnScreen();
bool selected(false);
bool isExtendable(false);
bool isEditable(true);
GetDataNode()->GetBoolProperty("selected", selected);
GetDataNode()->GetBoolProperty("planarfigure.isextendable", isExtendable);
GetDataNode()->GetBoolProperty("planarfigure.iseditable", isEditable );
if ( selected && isExtendable && isEditable )
{
renderer->GetDisplayGeometry()->DisplayToWorld( pointProjectedOntoLine, pointProjectedOntoLine );
planarFigure->SetPreviewControlPoint( pointProjectedOntoLine );
}
renderer->GetRenderingManager()->RequestUpdateAll();
return true;
}
bool mitk::PlanarFigureInteractor::HideControlPoints( StateMachineAction*, InteractionEvent* /*interactionEvent*/ )
{
GetDataNode()->SetBoolProperty( "planarfigure.drawcontrolpoints", false );
return true;
}
bool mitk::PlanarFigureInteractor::HidePreviewPoint( StateMachineAction*, InteractionEvent* interactionEvent )
{
mitk::PlanarFigure *planarFigure = dynamic_cast<mitk::PlanarFigure *>( GetDataNode()->GetData() );
planarFigure->ResetPreviewContolPoint();
mitk::BaseRenderer *renderer = interactionEvent->GetSender();
renderer->GetRenderingManager()->RequestUpdateAll();
return true;
}
bool mitk::PlanarFigureInteractor::CheckFigureHovering( const InteractionEvent* interactionEvent )
{
const mitk::InteractionPositionEvent* positionEvent = dynamic_cast<const mitk::InteractionPositionEvent*>( interactionEvent );
if ( positionEvent == NULL )
return false;
mitk::PlanarFigure *planarFigure = dynamic_cast<mitk::PlanarFigure *>( GetDataNode()->GetData() );
mitk::BaseRenderer *renderer = interactionEvent->GetSender();
- mitk::Geometry2D *planarFigureGeometry = dynamic_cast< Geometry2D * >( planarFigure->GetGeometry( 0 ) );
- const Geometry2D *projectionPlane = renderer->GetCurrentWorldGeometry2D();
+ mitk::PlaneGeometry *planarFigureGeometry = dynamic_cast< PlaneGeometry * >( planarFigure->GetGeometry( 0 ) );
+ const PlaneGeometry *projectionPlane = renderer->GetCurrentWorldPlaneGeometry();
mitk::Point2D pointProjectedOntoLine;
int previousControlPoint = this->IsPositionOverFigure( positionEvent,
planarFigure,
planarFigureGeometry,
projectionPlane,
renderer->GetDisplayGeometry(),
pointProjectedOntoLine
);
bool isHovering = (previousControlPoint != -1);
if ( isHovering )
{
return true;
}
else
{
return false;
}
return false;
}
bool mitk::PlanarFigureInteractor::CheckControlPointHovering( const InteractionEvent* interactionEvent )
{
const mitk::InteractionPositionEvent* positionEvent = dynamic_cast<const mitk::InteractionPositionEvent*>( interactionEvent );
if ( positionEvent == NULL )
return false;
mitk::PlanarFigure *planarFigure = dynamic_cast<mitk::PlanarFigure *>( GetDataNode()->GetData() );
mitk::BaseRenderer *renderer = interactionEvent->GetSender();
- mitk::Geometry2D *planarFigureGeometry = dynamic_cast< Geometry2D * >( planarFigure->GetGeometry( 0 ) );
- const Geometry2D *projectionPlane = renderer->GetCurrentWorldGeometry2D();
+ mitk::PlaneGeometry *planarFigureGeometry = dynamic_cast< PlaneGeometry * >( planarFigure->GetGeometry( 0 ) );
+ const PlaneGeometry *projectionPlane = renderer->GetCurrentWorldPlaneGeometry();
int pointIndex = -1;
pointIndex = mitk::PlanarFigureInteractor::IsPositionInsideMarker(
positionEvent,
planarFigure,
planarFigureGeometry,
projectionPlane,
renderer->GetDisplayGeometry() );
if ( pointIndex >= 0 )
{
return true;
}
else
{
return false;
}
}
bool mitk::PlanarFigureInteractor::CheckSelection( const InteractionEvent* /*interactionEvent*/ )
{
bool selected = false;
GetDataNode()->GetBoolProperty("selected", selected);
return selected;
}
bool mitk::PlanarFigureInteractor::SelectFigure( StateMachineAction*, InteractionEvent* /*interactionEvent*/ )
{
mitk::PlanarFigure *planarFigure = dynamic_cast<mitk::PlanarFigure *>( GetDataNode()->GetData() );
planarFigure->InvokeEvent( SelectPlanarFigureEvent() );
return false;
}
bool mitk::PlanarFigureInteractor::SelectPoint( StateMachineAction*, InteractionEvent* interactionEvent )
{
mitk::InteractionPositionEvent* positionEvent = dynamic_cast<mitk::InteractionPositionEvent*>( interactionEvent );
if ( positionEvent == NULL )
return false;
mitk::PlanarFigure *planarFigure = dynamic_cast<mitk::PlanarFigure *>( GetDataNode()->GetData() );
mitk::BaseRenderer *renderer = interactionEvent->GetSender();
- mitk::Geometry2D *planarFigureGeometry = dynamic_cast< Geometry2D * >( planarFigure->GetGeometry( 0 ) );
- const Geometry2D *projectionPlane = renderer->GetCurrentWorldGeometry2D();
+ mitk::PlaneGeometry *planarFigureGeometry = dynamic_cast< PlaneGeometry * >( planarFigure->GetGeometry( 0 ) );
+ const PlaneGeometry *projectionPlane = renderer->GetCurrentWorldPlaneGeometry();
int pointIndex = -1;
pointIndex = mitk::PlanarFigureInteractor::IsPositionInsideMarker(
positionEvent,
planarFigure,
planarFigureGeometry,
projectionPlane,
renderer->GetDisplayGeometry() );
if ( pointIndex >= 0 )
{
// If mouse is above control point, mark it as selected
planarFigure->SelectControlPoint( pointIndex );
}
else
{
planarFigure->DeselectControlPoint();
}
return false;
}
bool mitk::PlanarFigureInteractor::CheckPointValidity( const InteractionEvent* interactionEvent )
{
// Check if the distance of the current point to the previously set point in display coordinates
// is sufficient (if a previous point exists)
// Extract display position
const mitk::InteractionPositionEvent* positionEvent = dynamic_cast<const mitk::InteractionPositionEvent*>( interactionEvent );
if ( positionEvent == NULL )
return false;
mitk::PlanarFigure *planarFigure = dynamic_cast<mitk::PlanarFigure *>( GetDataNode()->GetData() );
m_LastPointWasValid = IsMousePositionAcceptableAsNewControlPoint( positionEvent, planarFigure );
return m_LastPointWasValid;
}
bool mitk::PlanarFigureInteractor::RemoveSelectedPoint(StateMachineAction*, InteractionEvent* interactionEvent)
{
mitk::PlanarFigure *planarFigure = dynamic_cast<mitk::PlanarFigure *>( GetDataNode()->GetData() );
mitk::BaseRenderer *renderer = interactionEvent->GetSender();
int selectedControlPoint = planarFigure->GetSelectedControlPoint();
planarFigure->RemoveControlPoint( selectedControlPoint );
// Re-evaluate features
planarFigure->EvaluateFeatures();
planarFigure->Modified();
GetDataNode()->SetBoolProperty( "planarfigure.drawcontrolpoints", true );
planarFigure->InvokeEvent( EndInteractionPlanarFigureEvent() );
renderer->GetRenderingManager()->RequestUpdateAll();
HandleEvent( mitk::InternalEvent::New( renderer, this, "Dummy-Event" ), GetDataNode() );
return true;
}
bool mitk::PlanarFigureInteractor::RequestContextMenu(StateMachineAction*, InteractionEvent* /*interactionEvent*/)
{
mitk::PlanarFigure *planarFigure = dynamic_cast<mitk::PlanarFigure *>( GetDataNode()->GetData() );
bool selected = false;
GetDataNode()->GetBoolProperty("selected", selected);
// no need to invoke this if the figure is already selected
if ( !selected )
{
planarFigure->InvokeEvent( SelectPlanarFigureEvent() );
}
planarFigure->InvokeEvent( ContextMenuPlanarFigureEvent() );
return true;
}
bool mitk::PlanarFigureInteractor::CheckResetOnPointSelect( const InteractionEvent* /*interactionEvent*/ )
{
mitk::PlanarFigure *planarFigure = dynamic_cast<mitk::PlanarFigure *>( GetDataNode()->GetData() );
// Invoke tmpEvent to notify listeners that interaction with this PF starts now
planarFigure->InvokeEvent( StartInteractionPlanarFigureEvent() );
// Reset the PlanarFigure if required
return planarFigure->ResetOnPointSelect();
}
bool mitk::PlanarFigureInteractor::CheckFigureOnRenderingGeometry( const InteractionEvent* interactionEvent )
{
const mitk::InteractionPositionEvent* posEvent = dynamic_cast<const mitk::InteractionPositionEvent*>(interactionEvent);
if ( posEvent == NULL )
return false;
mitk::Point3D worldPoint3D = posEvent->GetPositionInWorld();
mitk::PlanarFigure *planarFigure = dynamic_cast<mitk::PlanarFigure *>(
GetDataNode()->GetData() );
- mitk::Geometry2D *planarFigureGeometry2D = dynamic_cast< Geometry2D * >( planarFigure->GetGeometry( 0 ) );
+ mitk::PlaneGeometry *planarFigurePlaneGeometry = dynamic_cast< PlaneGeometry * >( planarFigure->GetGeometry( 0 ) );
- double planeThickness = planarFigureGeometry2D->GetExtentInMM( 2 );
+ double planeThickness = planarFigurePlaneGeometry->GetExtentInMM( 2 );
- if ( planarFigureGeometry2D->Distance( worldPoint3D ) > planeThickness )
+ if ( planarFigurePlaneGeometry->Distance( worldPoint3D ) > planeThickness )
{
// don't react, when interaction is too far away
return false;
}
return true;
}
void mitk::PlanarFigureInteractor::SetPrecision( mitk::ScalarType precision )
{
m_Precision = precision;
}
void mitk::PlanarFigureInteractor::SetMinimumPointDistance( ScalarType minimumDistance )
{
m_MinimumPointDistance = minimumDistance;
}
bool mitk::PlanarFigureInteractor::TransformPositionEventToPoint2D( const InteractionPositionEvent *positionEvent,
- const Geometry2D *planarFigureGeometry,
+ const PlaneGeometry *planarFigureGeometry,
Point2D &point2D )
{
mitk::Point3D worldPoint3D = positionEvent->GetPositionInWorld();
// TODO: proper handling of distance tolerance
if ( planarFigureGeometry->Distance( worldPoint3D ) > 0.1 )
{
return false;
}
// Project point onto plane of this PlanarFigure
planarFigureGeometry->Map( worldPoint3D, point2D );
return true;
}
bool mitk::PlanarFigureInteractor::TransformObjectToDisplay(
const mitk::Point2D &point2D,
mitk::Point2D &displayPoint,
- const mitk::Geometry2D *objectGeometry,
- const mitk::Geometry2D *rendererGeometry,
+ const mitk::PlaneGeometry *objectGeometry,
+ const mitk::PlaneGeometry *rendererGeometry,
const mitk::DisplayGeometry *displayGeometry ) const
{
mitk::Point3D point3D;
// Map circle point from local 2D geometry into 3D world space
objectGeometry->Map( point2D, point3D );
// TODO: proper handling of distance tolerance
if ( displayGeometry->Distance( point3D ) < 0.1 )
{
// Project 3D world point onto display geometry
rendererGeometry->Map( point3D, displayPoint );
displayGeometry->WorldToDisplay( displayPoint, displayPoint );
return true;
}
return false;
}
bool mitk::PlanarFigureInteractor::IsPointNearLine(
const mitk::Point2D& point,
const mitk::Point2D& startPoint,
const mitk::Point2D& endPoint,
mitk::Point2D& projectedPoint
) const
{
mitk::Vector2D n1 = endPoint - startPoint;
n1.Normalize();
// Determine dot products between line vector and startpoint-point / endpoint-point vectors
double l1 = n1 * (point - startPoint);
double l2 = -n1 * (point - endPoint);
// Determine projection of specified point onto line defined by start / end point
mitk::Point2D crossPoint = startPoint + n1 * l1;
projectedPoint = crossPoint;
// Point is inside encompassing rectangle IF
// - its distance to its projected point is small enough
// - it is not further outside of the line than the defined tolerance
if (((crossPoint.SquaredEuclideanDistanceTo(point) < 20.0) && (l1 > 0.0) && (l2 > 0.0))
|| endPoint.SquaredEuclideanDistanceTo(point) < 20.0
|| startPoint.SquaredEuclideanDistanceTo(point) < 20.0)
{
return true;
}
return false;
}
int mitk::PlanarFigureInteractor::IsPositionOverFigure(
const InteractionPositionEvent *positionEvent,
PlanarFigure *planarFigure,
- const Geometry2D *planarFigureGeometry,
- const Geometry2D *rendererGeometry,
+ const PlaneGeometry *planarFigureGeometry,
+ const PlaneGeometry *rendererGeometry,
const DisplayGeometry *displayGeometry,
Point2D& pointProjectedOntoLine ) const
{
mitk::Point2D displayPosition = positionEvent->GetPointerPositionOnScreen();
// Iterate over all polylines of planar figure, and check if
// any one is close to the current display position
typedef mitk::PlanarFigure::PolyLineType VertexContainerType;
Point2D polyLinePoint;
Point2D firstPolyLinePoint;
Point2D previousPolyLinePoint;
for ( unsigned short loop=0; loop<planarFigure->GetPolyLinesSize(); ++loop )
{
const VertexContainerType polyLine = planarFigure->GetPolyLine( loop );
bool firstPoint( true );
for ( VertexContainerType::const_iterator it = polyLine.begin(); it != polyLine.end(); ++it )
{
// Get plane coordinates of this point of polyline (if possible)
if ( !this->TransformObjectToDisplay( *it,
polyLinePoint,
planarFigureGeometry,
rendererGeometry,
displayGeometry )
)
{
break; // Poly line invalid (not on current 2D plane) --> skip it
}
if ( firstPoint )
{
firstPolyLinePoint = polyLinePoint;
firstPoint = false;
}
else if ( this->IsPointNearLine( displayPosition, previousPolyLinePoint, polyLinePoint, pointProjectedOntoLine ) )
{
// Point is close enough to line segment --> Return index of the segment
return std::distance(polyLine.begin(), it);
}
previousPolyLinePoint = polyLinePoint;
}
// For closed figures, also check last line segment
if ( planarFigure->IsClosed()
&& this->IsPointNearLine( displayPosition, polyLinePoint, firstPolyLinePoint, pointProjectedOntoLine ) )
{
return 0; // Return index of first control point
}
}
return -1;
}
int mitk::PlanarFigureInteractor::IsPositionInsideMarker(
const InteractionPositionEvent* positionEvent,
const PlanarFigure *planarFigure,
- const Geometry2D *planarFigureGeometry,
- const Geometry2D *rendererGeometry,
+ const PlaneGeometry *planarFigureGeometry,
+ const PlaneGeometry *rendererGeometry,
const DisplayGeometry *displayGeometry ) const
{
mitk::Point2D displayPosition = positionEvent->GetPointerPositionOnScreen();
// Iterate over all control points of planar figure, and check if
// any one is close to the current display position
mitk::Point2D displayControlPoint;
int numberOfControlPoints = planarFigure->GetNumberOfControlPoints();
for ( int i=0; i<numberOfControlPoints; i++ )
{
if ( this->TransformObjectToDisplay( planarFigure->GetControlPoint(i), displayControlPoint,
planarFigureGeometry, rendererGeometry, displayGeometry ) )
{
// TODO: variable size of markers
if ( displayPosition.SquaredEuclideanDistanceTo( displayControlPoint ) < 20.0 )
{
return i;
}
}
}
return -1;
}
void mitk::PlanarFigureInteractor::LogPrintPlanarFigureQuantities(
const PlanarFigure *planarFigure )
{
MITK_INFO << "PlanarFigure: " << planarFigure->GetNameOfClass();
for ( unsigned int i = 0; i < planarFigure->GetNumberOfFeatures(); ++i )
{
MITK_INFO << "* " << planarFigure->GetFeatureName( i ) << ": "
<< planarFigure->GetQuantity( i ) << " " << planarFigure->GetFeatureUnit( i );
}
}
bool
mitk::PlanarFigureInteractor::IsMousePositionAcceptableAsNewControlPoint(
const mitk::InteractionPositionEvent* positionEvent,
const PlanarFigure* planarFigure )
{
assert(positionEvent && planarFigure);
BaseRenderer* renderer = positionEvent->GetSender();
assert(renderer);
// Get the timestep to support 3D+t
int timeStep( renderer->GetTimeStep( planarFigure ) );
bool tooClose(false);
- const Geometry2D *renderingPlane = renderer->GetCurrentWorldGeometry2D();
+ const PlaneGeometry *renderingPlane = renderer->GetCurrentWorldPlaneGeometry();
- mitk::Geometry2D *planarFigureGeometry =
- dynamic_cast< mitk::Geometry2D * >( planarFigure->GetGeometry( timeStep ) );
+ mitk::PlaneGeometry *planarFigureGeometry =
+ dynamic_cast< mitk::PlaneGeometry * >( planarFigure->GetGeometry( timeStep ) );
Point2D point2D, correctedPoint;
// Get the point2D from the positionEvent
if ( !this->TransformPositionEventToPoint2D( positionEvent, planarFigureGeometry, point2D ) )
{
return false;
}
// apply the controlPoint constraints of the planarFigure to get the
// coordinates that would actually be used.
correctedPoint = const_cast<PlanarFigure*>( planarFigure )->ApplyControlPointConstraints( 0, point2D );
// map the 2D coordinates of the new point to world-coordinates
// and transform those to display-coordinates
mitk::Point3D newPoint3D;
planarFigureGeometry->Map( correctedPoint, newPoint3D );
mitk::Point2D newDisplayPosition;
renderingPlane->Map( newPoint3D, newDisplayPosition );
renderer->GetDisplayGeometry()->WorldToDisplay( newDisplayPosition, newDisplayPosition );
for( int i=0; i < (int)planarFigure->GetNumberOfControlPoints(); i++ )
{
if ( i != planarFigure->GetSelectedControlPoint() )
{
// Try to convert previous point to current display coordinates
mitk::Point3D previousPoint3D;
// map the 2D coordinates of the control-point to world-coordinates
planarFigureGeometry->Map( planarFigure->GetControlPoint( i ), previousPoint3D );
if ( renderer->GetDisplayGeometry()->Distance( previousPoint3D ) < 0.1 ) // ugly, but assert makes this work
{
mitk::Point2D previousDisplayPosition;
// transform the world-coordinates into display-coordinates
renderingPlane->Map( previousPoint3D, previousDisplayPosition );
renderer->GetDisplayGeometry()->WorldToDisplay( previousDisplayPosition, previousDisplayPosition );
//Calculate the distance. We use display-coordinates here to make
// the check independent of the zoom-level of the rendering scene.
double a = newDisplayPosition[0] - previousDisplayPosition[0];
double b = newDisplayPosition[1] - previousDisplayPosition[1];
// If point is to close, do not set a new point
tooClose = (a * a + b * b < m_MinimumPointDistance );
}
if ( tooClose )
return false; // abort loop early
}
}
return !tooClose; // default
}
void mitk::PlanarFigureInteractor::ConfigurationChanged()
{
mitk::PropertyList::Pointer properties = GetAttributes();
std::string precision = "";
if (properties->GetStringProperty("precision", precision))
{
m_Precision = atof(precision.c_str());
}
else
{
m_Precision = (ScalarType) 6.5;
}
std::string minPointDistance = "";
if (properties->GetStringProperty("minPointDistance", minPointDistance))
{
m_MinimumPointDistance = atof(minPointDistance.c_str());
}
else
{
m_MinimumPointDistance = (ScalarType) 25.0;
}
}
diff --git a/Modules/PlanarFigure/Interactions/mitkPlanarFigureInteractor.h b/Modules/PlanarFigure/Interactions/mitkPlanarFigureInteractor.h
index 82ef092012..f96489301a 100644
--- a/Modules/PlanarFigure/Interactions/mitkPlanarFigureInteractor.h
+++ b/Modules/PlanarFigure/Interactions/mitkPlanarFigureInteractor.h
@@ -1,205 +1,205 @@
/*===================================================================
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 MITKPLANARFIGUREINTERACTOR_H_HEADER_INCLUDED
#define MITKPLANARFIGUREINTERACTOR_H_HEADER_INCLUDED
#include <MitkPlanarFigureExports.h>
#include "mitkCommon.h"
#include "mitkVector.h"
#include "mitkDataInteractor.h"
#pragma GCC visibility push(default)
#include <itkEventObject.h>
#pragma GCC visibility pop
namespace mitk
{
class DataNode;
-class Geometry2D;
+class PlaneGeometry;
class DisplayGeometry;
class PlanarFigure;
class PositionEvent;
class BaseRenderer;
class InteractionPositionEvent;
class StateMachineAction;
#pragma GCC visibility push(default)
// Define events for PlanarFigure interaction notifications
itkEventMacro( PlanarFigureEvent, itk::AnyEvent );
itkEventMacro( StartPlacementPlanarFigureEvent, PlanarFigureEvent );
itkEventMacro( EndPlacementPlanarFigureEvent, PlanarFigureEvent );
itkEventMacro( SelectPlanarFigureEvent, PlanarFigureEvent );
itkEventMacro( StartInteractionPlanarFigureEvent, PlanarFigureEvent );
itkEventMacro( EndInteractionPlanarFigureEvent, PlanarFigureEvent );
itkEventMacro( StartHoverPlanarFigureEvent, PlanarFigureEvent );
itkEventMacro( EndHoverPlanarFigureEvent, PlanarFigureEvent );
itkEventMacro( ContextMenuPlanarFigureEvent, PlanarFigureEvent );
#pragma GCC visibility pop
/**
* \brief Interaction with mitk::PlanarFigure objects via control-points
*
* \ingroup Interaction
*/
class MitkPlanarFigure_EXPORT PlanarFigureInteractor : public DataInteractor
{
public:
mitkClassMacro(PlanarFigureInteractor, DataInteractor);
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** \brief Sets the amount of precision */
void SetPrecision( ScalarType precision );
/** \brief Sets the minimal distance between two control points. */
void SetMinimumPointDistance( ScalarType minimumDistance );
protected:
PlanarFigureInteractor();
virtual ~PlanarFigureInteractor();
virtual void ConnectActionsAndFunctions();
//////// Conditions ////////
bool CheckFigurePlaced( const InteractionEvent* interactionEvent );
bool CheckFigureHovering( const InteractionEvent* interactionEvent );
bool CheckControlPointHovering( const InteractionEvent* interactionEvent );
bool CheckSelection( const InteractionEvent* interactionEvent );
bool CheckPointValidity( const InteractionEvent* interactionEvent );
bool CheckFigureFinished( const InteractionEvent* interactionEvent );
bool CheckResetOnPointSelect( const InteractionEvent* interactionEvent );
bool CheckFigureOnRenderingGeometry( const InteractionEvent* interactionEvent );
bool CheckMinimalFigureFinished( const InteractionEvent* interactionEvent );
bool CheckFigureIsExtendable( const InteractionEvent* interactionEvent );
//////// Actions ////////
bool FinalizeFigure( StateMachineAction*, InteractionEvent* interactionEvent );
bool MoveCurrentPoint(StateMachineAction*, InteractionEvent* interactionEvent);
bool DeselectPoint(StateMachineAction*, InteractionEvent* interactionEvent);
bool AddPoint(StateMachineAction*, InteractionEvent* interactionEvent);
bool AddInitialPoint(StateMachineAction*, InteractionEvent* interactionEvent);
bool StartHovering( StateMachineAction*, InteractionEvent* interactionEvent );
bool EndHovering( StateMachineAction*, InteractionEvent* interactionEvent );
bool SetPreviewPointPosition( StateMachineAction*, InteractionEvent* interactionEvent );
bool HidePreviewPoint( StateMachineAction*, InteractionEvent* interactionEvent );
bool HideControlPoints( StateMachineAction*, InteractionEvent* interactionEvent );
bool RemoveSelectedPoint(StateMachineAction*, InteractionEvent* interactionEvent);
bool RequestContextMenu(StateMachineAction*, InteractionEvent* interactionEvent);
bool SelectFigure( StateMachineAction*, InteractionEvent* interactionEvent );
bool SelectPoint( StateMachineAction*, InteractionEvent* interactionEvent );
bool EndInteraction( StateMachineAction*, InteractionEvent* interactionEvent );
/**
\brief Used when clicking to determine if a point is too close to the previous point.
*/
bool IsMousePositionAcceptableAsNewControlPoint( const mitk::InteractionPositionEvent* positionEvent, const PlanarFigure* );
bool TransformPositionEventToPoint2D( const InteractionPositionEvent* positionEvent,
- const Geometry2D *planarFigureGeometry,
+ const PlaneGeometry *planarFigureGeometry,
Point2D &point2D );
bool TransformObjectToDisplay( const mitk::Point2D &point2D,
mitk::Point2D &displayPoint,
- const mitk::Geometry2D *objectGeometry,
- const mitk::Geometry2D *rendererGeometry,
+ const mitk::PlaneGeometry *objectGeometry,
+ const mitk::PlaneGeometry *rendererGeometry,
const mitk::DisplayGeometry *displayGeometry ) const;
/** \brief Returns true if the first specified point is in proximity of the line defined
* the other two point; false otherwise.
*
* Proximity is defined as the rectangle around the line with pre-defined distance
* from the line. */
bool IsPointNearLine( const mitk::Point2D& point,
const mitk::Point2D& startPoint, const mitk::Point2D& endPoint, mitk::Point2D& projectedPoint ) const;
/** \brief Returns true if the point contained in the passed event (in display coordinates)
* is over the planar figure (with a pre-defined tolerance range); false otherwise. */
int IsPositionOverFigure(
const InteractionPositionEvent* positionEvent,
PlanarFigure *planarFigure,
- const Geometry2D *planarFigureGeometry,
- const Geometry2D *rendererGeometry,
+ const PlaneGeometry *planarFigureGeometry,
+ const PlaneGeometry *rendererGeometry,
const DisplayGeometry *displayGeometry,
Point2D& pointProjectedOntoLine) const;
/** \brief Returns the index of the marker (control point) over which the point contained
* in the passed event (in display coordinates) currently is; -1 if the point is not over
* a marker. */
int IsPositionInsideMarker(
const InteractionPositionEvent* positionEvent,
const PlanarFigure *planarFigure,
- const Geometry2D *planarFigureGeometry,
- const Geometry2D *rendererGeometry,
+ const PlaneGeometry *planarFigureGeometry,
+ const PlaneGeometry *rendererGeometry,
const DisplayGeometry *displayGeometry ) const;
void LogPrintPlanarFigureQuantities( const PlanarFigure *planarFigure );
virtual void ConfigurationChanged();
private:
/** \brief to store the value of precision to pick a point */
ScalarType m_Precision;
/** \brief Store the minimal distance between two control points. */
ScalarType m_MinimumPointDistance;
/** \brief True if the mouse is currently hovering over the image. */
bool m_IsHovering;
bool m_LastPointWasValid;
//mitk::PlanarFigure::Pointer m_PlanarFigure;
};
}
#endif // MITKPLANARFIGUREINTERACTOR_H_HEADER_INCLUDED
diff --git a/Modules/PlanarFigure/Rendering/mitkPlanarFigureMapper2D.cpp b/Modules/PlanarFigure/Rendering/mitkPlanarFigureMapper2D.cpp
index 7dd447371a..9b0d2d6566 100644
--- a/Modules/PlanarFigure/Rendering/mitkPlanarFigureMapper2D.cpp
+++ b/Modules/PlanarFigure/Rendering/mitkPlanarFigureMapper2D.cpp
@@ -1,927 +1,923 @@
/*===================================================================
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 "mitkPlanarFigureMapper2D.h"
#include "mitkBaseRenderer.h"
#include "mitkPlaneGeometry.h"
#include "mitkColorProperty.h"
#include "mitkProperties.h"
#include "mitkGL.h"
#include "mitkVtkPropRenderer.h"
#define _USE_MATH_DEFINES
#include <math.h>
// offset which moves the planarfigures on top of the other content
// the crosshair is rendered into the z = 1 layer.
static const float PLANAR_OFFSET = 0.5f;
mitk::PlanarFigureMapper2D::PlanarFigureMapper2D()
: m_NodeModified(true)
, m_NodeModifiedObserverTag(0)
, m_NodeModifiedObserverAdded(false)
{
this->InitializeDefaultPlanarFigureProperties();
}
mitk::PlanarFigureMapper2D::~PlanarFigureMapper2D()
{
if ( m_NodeModifiedObserverAdded && GetDataNode() != NULL )
{
GetDataNode()->RemoveObserver( m_NodeModifiedObserverTag );
}
}
void mitk::PlanarFigureMapper2D::Paint( mitk::BaseRenderer *renderer )
{
bool visible = true;
GetDataNode()->GetVisibility(visible, renderer, "visible");
if ( !visible ) return;
// Get PlanarFigure from input
mitk::PlanarFigure *planarFigure = const_cast< mitk::PlanarFigure * >(
static_cast< const mitk::PlanarFigure * >( GetDataNode()->GetData() ) );
// Check if PlanarFigure has already been placed; otherwise, do nothing
if ( !planarFigure->IsPlaced() )
{
return;
}
// Get 2D geometry frame of PlanarFigure
- mitk::Geometry2D *planarFigureGeometry2D =
- dynamic_cast< Geometry2D * >( planarFigure->GetGeometry( 0 ) );
- if ( planarFigureGeometry2D == NULL )
+ mitk::PlaneGeometry *planarFigurePlaneGeometry =
+ dynamic_cast< PlaneGeometry * >( planarFigure->GetGeometry( 0 ) );
+ if ( planarFigurePlaneGeometry == NULL )
{
- MITK_ERROR << "PlanarFigure does not have valid Geometry2D!";
+ MITK_ERROR << "PlanarFigure does not have valid PlaneGeometry!";
return;
}
// Get current world 2D geometry from renderer
- const mitk::Geometry2D *rendererGeometry2D = renderer->GetCurrentWorldGeometry2D();
+ const mitk::PlaneGeometry *rendererPlaneGeometry = renderer->GetCurrentWorldPlaneGeometry();
// If the PlanarFigure geometry is a plane geometry, check if current
// world plane is parallel to and within the planar figure geometry bounds
// (otherwise, display nothing)
- mitk::PlaneGeometry *planarFigurePlaneGeometry =
- dynamic_cast< PlaneGeometry * >( planarFigureGeometry2D );
- const mitk::PlaneGeometry *rendererPlaneGeometry =
- dynamic_cast< const PlaneGeometry * >( rendererGeometry2D );
if ( (planarFigurePlaneGeometry != NULL) && (rendererPlaneGeometry != NULL) )
{
double planeThickness = planarFigurePlaneGeometry->GetExtentInMM( 2 );
if ( !planarFigurePlaneGeometry->IsParallel( rendererPlaneGeometry )
|| !(planarFigurePlaneGeometry->DistanceFromPlane(
rendererPlaneGeometry ) < planeThickness / 3.0) )
{
// Planes are not parallel or renderer plane is not within PlanarFigure
// geometry bounds --> exit
return;
}
}
else
{
// Plane is not valid (curved reformations are not possible yet)
return;
}
// Get display geometry
mitk::DisplayGeometry *displayGeometry = renderer->GetDisplayGeometry();
assert( displayGeometry != NULL );
// Apply visual appearance properties from the PropertyList
ApplyColorAndOpacityProperties( renderer );
// Enable line antialiasing
glEnable( GL_LINE_SMOOTH );
glHint( GL_LINE_SMOOTH_HINT, GL_NICEST );
glEnable(GL_DEPTH_TEST);
// Get properties from node (if present)
const mitk::DataNode* node=this->GetDataNode();
this->InitializePlanarFigurePropertiesFromDataNode( node );
PlanarFigureDisplayMode lineDisplayMode = PF_DEFAULT;
if ( m_IsSelected )
{
lineDisplayMode = PF_SELECTED;
}
else if ( m_IsHovering )
{
lineDisplayMode = PF_HOVER;
}
mitk::Point2D anchorPoint; anchorPoint[0] = 0; anchorPoint[1] = 1;
// render the actual lines of the PlanarFigure
- RenderLines(lineDisplayMode, planarFigure, anchorPoint, planarFigureGeometry2D, rendererGeometry2D, displayGeometry);
+ RenderLines(lineDisplayMode, planarFigure, anchorPoint, planarFigurePlaneGeometry, rendererPlaneGeometry, displayGeometry);
// position-offset of the annotations, is set in RenderAnnotations() and
// used in RenderQuantities()
double annotationOffset = 0.0;
//Get Global Opacity
float globalOpacity = 1.0;
node->GetFloatProperty("opacity", globalOpacity);
// draw name near the anchor point (point located on the right)
std::string name = node->GetName();
if ( m_DrawName && !name.empty() )
{
RenderAnnotations(renderer, name, anchorPoint, globalOpacity, lineDisplayMode, annotationOffset);
}
// draw feature quantities (if requested) next to the anchor point,
// but under the name (that is where 'annotationOffset' is used)
if ( m_DrawQuantities )
{
RenderQuantities(planarFigure, renderer, anchorPoint, annotationOffset, globalOpacity, lineDisplayMode);
}
if ( m_DrawControlPoints )
{
// draw the control-points
- RenderControlPoints(planarFigure, lineDisplayMode, planarFigureGeometry2D, rendererGeometry2D, displayGeometry);
+ RenderControlPoints(planarFigure, lineDisplayMode, planarFigurePlaneGeometry, rendererPlaneGeometry, displayGeometry);
}
glLineWidth( 1.0f );
}
void mitk::PlanarFigureMapper2D::PaintPolyLine(
mitk::PlanarFigure::PolyLineType vertices,
bool closed,
Point2D& anchorPoint,
- const Geometry2D* planarFigureGeometry2D,
- const Geometry2D* rendererGeometry2D,
+ const PlaneGeometry* planarFigurePlaneGeometry,
+ const PlaneGeometry* rendererPlaneGeometry,
const DisplayGeometry* displayGeometry)
{
mitk::Point2D rightMostPoint;
rightMostPoint.Fill( itk::NumericTraits<float>::min() );
// transform all vertices into Point2Ds in display-Coordinates and store them in vector
std::vector<mitk::Point2D> pointlist;
for ( PlanarFigure::PolyLineType::iterator iter = vertices.begin(); iter!=vertices.end(); iter++ )
{
// Draw this 2D point as OpenGL vertex
mitk::Point2D displayPoint;
this->TransformObjectToDisplay( *iter, displayPoint,
- planarFigureGeometry2D, rendererGeometry2D, displayGeometry );
+ planarFigurePlaneGeometry, rendererPlaneGeometry, displayGeometry );
pointlist.push_back(displayPoint);
if ( displayPoint[0] > rightMostPoint[0] )
rightMostPoint = displayPoint;
}
// now paint all the points in one run
std::vector<mitk::Point2D>::iterator pointIter;
if ( closed )
{
glBegin( GL_LINE_LOOP );
}
else
{
glBegin( GL_LINE_STRIP );
}
for ( pointIter = pointlist.begin(); pointIter!=pointlist.end(); pointIter++ )
{
glVertex3f( (*pointIter)[0], (*pointIter)[1], PLANAR_OFFSET );
}
glEnd();
anchorPoint = rightMostPoint;
}
void mitk::PlanarFigureMapper2D::DrawMainLines(
mitk::PlanarFigure* figure,
Point2D& anchorPoint,
- const Geometry2D* planarFigureGeometry2D,
- const Geometry2D* rendererGeometry2D,
+ const PlaneGeometry* planarFigurePlaneGeometry,
+ const PlaneGeometry* rendererPlaneGeometry,
const DisplayGeometry* displayGeometry)
{
unsigned short numberOfPolyLines = figure->GetPolyLinesSize();
for ( unsigned short loop=0; loop<numberOfPolyLines ; ++loop )
{
PlanarFigure::PolyLineType polyline = figure->GetPolyLine(loop);
this->PaintPolyLine( polyline,
figure->IsClosed(),
- anchorPoint, planarFigureGeometry2D,
- rendererGeometry2D, displayGeometry );
+ anchorPoint, planarFigurePlaneGeometry,
+ rendererPlaneGeometry, displayGeometry );
}
}
void mitk::PlanarFigureMapper2D::DrawHelperLines(
mitk::PlanarFigure* figure,
Point2D& anchorPoint,
- const Geometry2D* planarFigureGeometry2D,
- const Geometry2D* rendererGeometry2D,
+ const PlaneGeometry* planarFigurePlaneGeometry,
+ const PlaneGeometry* rendererPlaneGeometry,
const DisplayGeometry* displayGeometry)
{
unsigned short numberOfHelperPolyLines = figure->GetHelperPolyLinesSize();
// Draw helper objects
for ( unsigned int loop=0; loop<numberOfHelperPolyLines; ++loop )
{
const mitk::PlanarFigure::PolyLineType helperPolyLine = figure->GetHelperPolyLine(loop,
displayGeometry->GetScaleFactorMMPerDisplayUnit(),
displayGeometry->GetDisplayHeight() );
// Check if the current helper objects is to be painted
if ( !figure->IsHelperToBePainted( loop ) )
{
continue;
}
// ... and once normally above the shadow.
this->PaintPolyLine( helperPolyLine, false,
- anchorPoint, planarFigureGeometry2D,
- rendererGeometry2D, displayGeometry );
+ anchorPoint, planarFigurePlaneGeometry,
+ rendererPlaneGeometry, displayGeometry );
}
}
void mitk::PlanarFigureMapper2D::TransformObjectToDisplay(
const mitk::Point2D &point2D,
mitk::Point2D &displayPoint,
- const mitk::Geometry2D *objectGeometry,
- const mitk::Geometry2D *rendererGeometry,
+ const mitk::PlaneGeometry *objectGeometry,
+ const mitk::PlaneGeometry *rendererGeometry,
const mitk::DisplayGeometry *displayGeometry )
{
mitk::Point3D point3D;
// Map circle point from local 2D geometry into 3D world space
objectGeometry->Map( point2D, point3D );
// Project 3D world point onto display geometry
rendererGeometry->Map( point3D, displayPoint );
displayGeometry->WorldToDisplay( displayPoint, displayPoint );
}
void mitk::PlanarFigureMapper2D::DrawMarker(
const mitk::Point2D &point,
float* lineColor,
float lineOpacity,
float* markerColor,
float markerOpacity,
float lineWidth,
PlanarFigureControlPointStyleProperty::Shape shape,
- const mitk::Geometry2D *objectGeometry,
- const mitk::Geometry2D *rendererGeometry,
+ const mitk::PlaneGeometry *objectGeometry,
+ const mitk::PlaneGeometry *rendererGeometry,
const mitk::DisplayGeometry *displayGeometry )
{
mitk::Point2D displayPoint;
if ( markerOpacity == 0 && lineOpacity == 0 )
return;
this->TransformObjectToDisplay(
point, displayPoint,
objectGeometry, rendererGeometry, displayGeometry );
glColor4f( markerColor[0], markerColor[1], markerColor[2], markerOpacity );
glLineWidth( lineWidth );
switch ( shape )
{
case PlanarFigureControlPointStyleProperty::Square:
default:
{
// Paint filled square
// Disable line antialiasing (does not look nice for squares)
glDisable( GL_LINE_SMOOTH );
if ( markerOpacity > 0 )
{
glRectf(
displayPoint[0] - 4, displayPoint[1] - 4,
displayPoint[0] + 4, displayPoint[1] + 4 );
}
// Paint outline
glColor4f( lineColor[0], lineColor[1], lineColor[2], lineOpacity );
glBegin( GL_LINE_LOOP );
glVertex3f( displayPoint[0] - 4, displayPoint[1] - 4, PLANAR_OFFSET );
glVertex3f( displayPoint[0] - 4, displayPoint[1] + 4, PLANAR_OFFSET );
glVertex3f( displayPoint[0] + 4, displayPoint[1] + 4, PLANAR_OFFSET );
glVertex3f( displayPoint[0] + 4, displayPoint[1] - 4, PLANAR_OFFSET );
glEnd();
break;
}
case PlanarFigureControlPointStyleProperty::Circle:
{
float radius = 4.0;
if ( markerOpacity > 0 )
{
// Paint filled circle
glBegin( GL_POLYGON );
for ( int angle = 0; angle < 8; ++angle )
{
float angleRad = angle * (float) 3.14159 / 4.0;
float x = displayPoint[0] + radius * (float)cos( angleRad );
float y = displayPoint[1] + radius * (float)sin( angleRad );
glVertex3f(x, y, PLANAR_OFFSET);
}
glEnd();
}
// Paint outline
glColor4f( lineColor[0], lineColor[1], lineColor[2], lineOpacity );
glBegin( GL_LINE_LOOP );
for ( int angle = 0; angle < 8; ++angle )
{
float angleRad = angle * (float) 3.14159 / 4.0;
float x = displayPoint[0] + radius * (float)cos( angleRad );
float y = displayPoint[1] + radius * (float)sin( angleRad );
glVertex3f(x, y, PLANAR_OFFSET);
}
glEnd();
break;
}
} // end switch
}
void mitk::PlanarFigureMapper2D::InitializeDefaultPlanarFigureProperties()
{
m_IsSelected = false;
m_IsHovering = false;
m_DrawOutline = false;
m_DrawQuantities = false;
m_DrawShadow = false;
m_DrawControlPoints = false;
m_DrawName = true;
m_DrawDashed = false;
m_DrawHelperDashed = false;
m_ShadowWidthFactor = 1.2;
m_LineWidth = 1.0;
m_OutlineWidth = 4.0;
m_HelperlineWidth = 2.0;
m_ControlPointShape = PlanarFigureControlPointStyleProperty::Square;
this->SetColorProperty( m_LineColor, PF_DEFAULT, 1.0, 1.0, 1.0 );
this->SetFloatProperty( m_LineOpacity, PF_DEFAULT, 1.0 );
this->SetColorProperty( m_OutlineColor, PF_DEFAULT, 0.0, 0.0, 1.0 );
this->SetFloatProperty( m_OutlineOpacity, PF_DEFAULT, 1.0 );
this->SetColorProperty( m_HelperlineColor, PF_DEFAULT, 0.4, 0.8, 0.2 );
this->SetFloatProperty( m_HelperlineOpacity, PF_DEFAULT, 0.4 );
this->SetColorProperty( m_MarkerlineColor, PF_DEFAULT, 1.0, 1.0, 1.0 );
this->SetFloatProperty( m_MarkerlineOpacity, PF_DEFAULT, 1.0 );
this->SetColorProperty( m_MarkerColor, PF_DEFAULT, 1.0, 1.0, 1.0 );
this->SetFloatProperty( m_MarkerOpacity, PF_DEFAULT, 0.0 );
this->SetColorProperty( m_LineColor, PF_HOVER, 1.0, 0.7, 0.0 );
this->SetFloatProperty( m_LineOpacity, PF_HOVER, 1.0 );
this->SetColorProperty( m_OutlineColor, PF_HOVER, 0.0, 0.0, 1.0 );
this->SetFloatProperty( m_OutlineOpacity, PF_HOVER, 1.0 );
this->SetColorProperty( m_HelperlineColor, PF_HOVER, 0.4, 0.8, 0.2 );
this->SetFloatProperty( m_HelperlineOpacity, PF_HOVER, 0.4 );
this->SetColorProperty( m_MarkerlineColor, PF_HOVER, 1.0, 1.0, 1.0 );
this->SetFloatProperty( m_MarkerlineOpacity, PF_HOVER, 1.0 );
this->SetColorProperty( m_MarkerColor, PF_HOVER, 1.0, 0.6, 0.0 );
this->SetFloatProperty( m_MarkerOpacity, PF_HOVER, 0.2 );
this->SetColorProperty( m_LineColor, PF_SELECTED, 1.0, 0.0, 0.0 );
this->SetFloatProperty( m_LineOpacity, PF_SELECTED, 1.0 );
this->SetColorProperty( m_OutlineColor, PF_SELECTED, 0.0, 0.0, 1.0 );
this->SetFloatProperty( m_OutlineOpacity, PF_SELECTED, 1.0 );
this->SetColorProperty( m_HelperlineColor, PF_SELECTED, 0.4, 0.8, 0.2 );
this->SetFloatProperty( m_HelperlineOpacity, PF_SELECTED, 0.4 );
this->SetColorProperty( m_MarkerlineColor, PF_SELECTED, 1.0, 1.0, 1.0 );
this->SetFloatProperty( m_MarkerlineOpacity, PF_SELECTED, 1.0 );
this->SetColorProperty( m_MarkerColor, PF_SELECTED, 1.0, 0.6, 0.0 );
this->SetFloatProperty( m_MarkerOpacity, PF_SELECTED, 1.0 );
}
void mitk::PlanarFigureMapper2D::InitializePlanarFigurePropertiesFromDataNode( const mitk::DataNode* node )
{
if ( node == NULL )
{
return;
}
// if we have not added an observer for ModifiedEvents on the DataNode,
// we add one now.
if ( !m_NodeModifiedObserverAdded )
{
itk::SimpleMemberCommand<mitk::PlanarFigureMapper2D>::Pointer nodeModifiedCommand = itk::SimpleMemberCommand<mitk::PlanarFigureMapper2D>::New();
nodeModifiedCommand->SetCallbackFunction(this, &mitk::PlanarFigureMapper2D::OnNodeModified);
m_NodeModifiedObserverTag = node->AddObserver(itk::ModifiedEvent(), nodeModifiedCommand);
m_NodeModifiedObserverAdded = true;
}
// If the DataNode has not been modified since the last execution of
// this method, we do not run it now.
if ( !m_NodeModified )
return;
// Mark the current properties as unmodified
m_NodeModified = false;
//Get Global Opacity
float globalOpacity = 1.0;
node->GetFloatProperty("opacity", globalOpacity);
node->GetBoolProperty( "selected", m_IsSelected );
node->GetBoolProperty( "planarfigure.ishovering", m_IsHovering );
node->GetBoolProperty( "planarfigure.drawoutline", m_DrawOutline );
node->GetBoolProperty( "planarfigure.drawshadow", m_DrawShadow );
node->GetBoolProperty( "planarfigure.drawquantities", m_DrawQuantities );
node->GetBoolProperty( "planarfigure.drawcontrolpoints", m_DrawControlPoints );
node->GetBoolProperty( "planarfigure.drawname", m_DrawName );
node->GetBoolProperty( "planarfigure.drawdashed", m_DrawDashed );
node->GetBoolProperty( "planarfigure.helperline.drawdashed", m_DrawHelperDashed );
node->GetFloatProperty( "planarfigure.line.width", m_LineWidth );
node->GetFloatProperty( "planarfigure.shadow.widthmodifier", m_ShadowWidthFactor );
node->GetFloatProperty( "planarfigure.outline.width", m_OutlineWidth );
node->GetFloatProperty( "planarfigure.helperline.width", m_HelperlineWidth );
PlanarFigureControlPointStyleProperty::Pointer styleProperty =
dynamic_cast< PlanarFigureControlPointStyleProperty* >( node->GetProperty( "planarfigure.controlpointshape" ) );
if ( styleProperty.IsNotNull() )
{
m_ControlPointShape = styleProperty->GetShape();
}
//Set default color and opacity
//If property "planarfigure.default.*.color" exists, then use that color. Otherwise global "color" property is used.
if( !node->GetColor( m_LineColor[PF_DEFAULT], NULL, "planarfigure.default.line.color"))
{
node->GetColor( m_LineColor[PF_DEFAULT], NULL, "color" );
}
node->GetFloatProperty( "planarfigure.default.line.opacity", m_LineOpacity[PF_DEFAULT] );
if( !node->GetColor( m_OutlineColor[PF_DEFAULT], NULL, "planarfigure.default.outline.color"))
{
node->GetColor( m_OutlineColor[PF_DEFAULT], NULL, "color" );
}
node->GetFloatProperty( "planarfigure.default.outline.opacity", m_OutlineOpacity[PF_DEFAULT] );
if( !node->GetColor( m_HelperlineColor[PF_DEFAULT], NULL, "planarfigure.default.helperline.color"))
{
node->GetColor( m_HelperlineColor[PF_DEFAULT], NULL, "color" );
}
node->GetFloatProperty( "planarfigure.default.helperline.opacity", m_HelperlineOpacity[PF_DEFAULT] );
node->GetColor( m_MarkerlineColor[PF_DEFAULT], NULL, "planarfigure.default.markerline.color" );
node->GetFloatProperty( "planarfigure.default.markerline.opacity", m_MarkerlineOpacity[PF_DEFAULT] );
node->GetColor( m_MarkerColor[PF_DEFAULT], NULL, "planarfigure.default.marker.color" );
node->GetFloatProperty( "planarfigure.default.marker.opacity", m_MarkerOpacity[PF_DEFAULT] );
//Set hover color and opacity
node->GetColor( m_LineColor[PF_HOVER], NULL, "planarfigure.hover.line.color" );
node->GetFloatProperty( "planarfigure.hover.line.opacity", m_LineOpacity[PF_HOVER] );
node->GetColor( m_OutlineColor[PF_HOVER], NULL, "planarfigure.hover.outline.color" );
node->GetFloatProperty( "planarfigure.hover.outline.opacity", m_OutlineOpacity[PF_HOVER] );
node->GetColor( m_HelperlineColor[PF_HOVER], NULL, "planarfigure.hover.helperline.color" );
node->GetFloatProperty( "planarfigure.hover.helperline.opacity", m_HelperlineOpacity[PF_HOVER] );
node->GetColor( m_MarkerlineColor[PF_HOVER], NULL, "planarfigure.hover.markerline.color" );
node->GetFloatProperty( "planarfigure.hover.markerline.opacity", m_MarkerlineOpacity[PF_HOVER] );
node->GetColor( m_MarkerColor[PF_HOVER], NULL, "planarfigure.hover.marker.color" );
node->GetFloatProperty( "planarfigure.hover.marker.opacity", m_MarkerOpacity[PF_HOVER] );
//Set selected color and opacity
node->GetColor( m_LineColor[PF_SELECTED], NULL, "planarfigure.selected.line.color" );
node->GetFloatProperty( "planarfigure.selected.line.opacity", m_LineOpacity[PF_SELECTED] );
node->GetColor( m_OutlineColor[PF_SELECTED], NULL, "planarfigure.selected.outline.color" );
node->GetFloatProperty( "planarfigure.selected.outline.opacity", m_OutlineOpacity[PF_SELECTED] );
node->GetColor( m_HelperlineColor[PF_SELECTED], NULL, "planarfigure.selected.helperline.color" );
node->GetFloatProperty( "planarfigure.selected.helperline.opacity", m_HelperlineOpacity[PF_SELECTED] );
node->GetColor( m_MarkerlineColor[PF_SELECTED], NULL, "planarfigure.selected.markerline.color" );
node->GetFloatProperty( "planarfigure.selected.markerline.opacity", m_MarkerlineOpacity[PF_SELECTED] );
node->GetColor( m_MarkerColor[PF_SELECTED], NULL, "planarfigure.selected.marker.color" );
node->GetFloatProperty( "planarfigure.selected.marker.opacity", m_MarkerOpacity[PF_SELECTED] );
//adapt opacity values to global "opacity" property
for( unsigned int i = 0; i < PF_COUNT; ++i )
{
m_LineOpacity[i] *= globalOpacity;
m_OutlineOpacity[i] *= globalOpacity;
m_HelperlineOpacity[i] *= globalOpacity;
m_MarkerlineOpacity[i] *= globalOpacity;
m_MarkerOpacity[i] *= globalOpacity;
}
}
void mitk::PlanarFigureMapper2D::OnNodeModified()
{
m_NodeModified = true;
}
void mitk::PlanarFigureMapper2D::SetDefaultProperties( mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite )
{
node->AddProperty( "visible", mitk::BoolProperty::New(true), renderer, overwrite );
//node->SetProperty("planarfigure.iseditable",mitk::BoolProperty::New(true));
node->AddProperty("planarfigure.isextendable",mitk::BoolProperty::New(false));
//node->AddProperty( "planarfigure.ishovering", mitk::BoolProperty::New(true) );
node->AddProperty( "planarfigure.drawoutline", mitk::BoolProperty::New(false) );
//node->AddProperty( "planarfigure.drawquantities", mitk::BoolProperty::New(true) );
node->AddProperty( "planarfigure.drawshadow", mitk::BoolProperty::New(true) );
node->AddProperty( "planarfigure.drawcontrolpoints", mitk::BoolProperty::New(true) );
node->AddProperty( "planarfigure.drawname", mitk::BoolProperty::New(true) );
node->AddProperty( "planarfigure.drawdashed", mitk::BoolProperty::New(false) );
node->AddProperty( "planarfigure.helperline.drawdashed", mitk::BoolProperty::New(false) );
node->AddProperty("planarfigure.line.width", mitk::FloatProperty::New(2.0) );
node->AddProperty("planarfigure.shadow.widthmodifier", mitk::FloatProperty::New(2.0) );
node->AddProperty("planarfigure.outline.width", mitk::FloatProperty::New(2.0) );
node->AddProperty("planarfigure.helperline.width", mitk::FloatProperty::New(1.0) );
node->AddProperty( "planarfigure.default.line.opacity", mitk::FloatProperty::New(1.0) );
node->AddProperty( "planarfigure.default.outline.opacity", mitk::FloatProperty::New(1.0) );
node->AddProperty( "planarfigure.default.helperline.opacity", mitk::FloatProperty::New(1.0) );
node->AddProperty( "planarfigure.default.markerline.color", mitk::ColorProperty::New(1.0,1.0,1.0) );
node->AddProperty( "planarfigure.default.markerline.opacity", mitk::FloatProperty::New(1.0) );
node->AddProperty( "planarfigure.default.marker.color", mitk::ColorProperty::New(1.0,1.0,1.0) );
node->AddProperty( "planarfigure.default.marker.opacity",mitk::FloatProperty::New(1.0) );
node->AddProperty( "planarfigure.hover.line.color", mitk::ColorProperty::New(0.0,1.0,0.0) );
node->AddProperty( "planarfigure.hover.line.opacity", mitk::FloatProperty::New(1.0) );
node->AddProperty( "planarfigure.hover.outline.color", mitk::ColorProperty::New(0.0,1.0,0.0) );
node->AddProperty( "planarfigure.hover.outline.opacity", mitk::FloatProperty::New(1.0) );
node->AddProperty( "planarfigure.hover.helperline.color", mitk::ColorProperty::New(0.0,1.0,0.0) );
node->AddProperty( "planarfigure.hover.helperline.opacity", mitk::FloatProperty::New(1.0) );
node->AddProperty( "planarfigure.hover.markerline.color", mitk::ColorProperty::New(0.0,1.0,0.0) );
node->AddProperty( "planarfigure.hover.markerline.opacity", mitk::FloatProperty::New(1.0) );
node->AddProperty( "planarfigure.hover.marker.color", mitk::ColorProperty::New(0.0,1.0,0.0) );
node->AddProperty( "planarfigure.hover.marker.opacity", mitk::FloatProperty::New(1.0) );
node->AddProperty( "planarfigure.selected.line.color", mitk::ColorProperty::New(1.0,0.0,0.0) );
node->AddProperty( "planarfigure.selected.line.opacity",mitk::FloatProperty::New(1.0) );
node->AddProperty( "planarfigure.selected.outline.color", mitk::ColorProperty::New(1.0,0.0,0.0) );
node->AddProperty( "planarfigure.selected.outline.opacity", mitk::FloatProperty::New(1.0));
node->AddProperty( "planarfigure.selected.helperline.color", mitk::ColorProperty::New(1.0,0.0,0.0) );
node->AddProperty( "planarfigure.selected.helperline.opacity",mitk::FloatProperty::New(1.0) );
node->AddProperty( "planarfigure.selected.markerline.color", mitk::ColorProperty::New(1.0,0.0,0.0) );
node->AddProperty( "planarfigure.selected.markerline.opacity", mitk::FloatProperty::New(1.0) );
node->AddProperty( "planarfigure.selected.marker.color", mitk::ColorProperty::New(1.0,0.0,0.0) );
node->AddProperty( "planarfigure.selected.marker.opacity",mitk::FloatProperty::New(1.0));
}
void mitk::PlanarFigureMapper2D::RenderControlPoints( mitk::PlanarFigure * planarFigure,
PlanarFigureDisplayMode lineDisplayMode,
- mitk::Geometry2D * planarFigureGeometry2D,
- const mitk::Geometry2D * rendererGeometry2D,
+ mitk::PlaneGeometry * planarFigurePlaneGeometry,
+ const mitk::PlaneGeometry * rendererPlaneGeometry,
mitk::DisplayGeometry * displayGeometry )
{
bool isEditable = true;
m_DataNode->GetBoolProperty( "planarfigure.iseditable", isEditable );
PlanarFigureDisplayMode pointDisplayMode = PF_DEFAULT;
unsigned int selectedControlPointsIdx = (unsigned int) planarFigure->GetSelectedControlPoint();
unsigned int numberOfControlPoints = planarFigure->GetNumberOfControlPoints();
// Draw markers at control points (selected control point will be colored)
for ( unsigned int i = 0; i < numberOfControlPoints ; ++i )
{
// Only if planar figure is marked as editable: display markers (control points) in a
// different style if mouse is over them or they are selected
if ( isEditable )
{
if ( i == selectedControlPointsIdx )
{
pointDisplayMode = PF_SELECTED;
}
else if ( m_IsHovering && isEditable )
{
pointDisplayMode = PF_HOVER;
}
}
if ( m_MarkerOpacity[pointDisplayMode] == 0
&& m_MarkerlineOpacity[pointDisplayMode] == 0 )
{
continue;
}
if ( m_DrawOutline )
{
// draw outlines for markers as well
// linewidth for the contour is only half, as full width looks
// much too thick!
this->DrawMarker( planarFigure->GetControlPoint( i ),
m_OutlineColor[lineDisplayMode],
m_MarkerlineOpacity[pointDisplayMode],
m_OutlineColor[lineDisplayMode],
m_MarkerOpacity[pointDisplayMode],
m_OutlineWidth/2,
m_ControlPointShape,
- planarFigureGeometry2D,
- rendererGeometry2D,
+ planarFigurePlaneGeometry,
+ rendererPlaneGeometry,
displayGeometry );
}
this->DrawMarker( planarFigure->GetControlPoint( i ),
m_MarkerlineColor[pointDisplayMode],
m_MarkerlineOpacity[pointDisplayMode],
m_MarkerColor[pointDisplayMode],
m_MarkerOpacity[pointDisplayMode],
m_LineWidth,
m_ControlPointShape,
- planarFigureGeometry2D,
- rendererGeometry2D,
+ planarFigurePlaneGeometry,
+ rendererPlaneGeometry,
displayGeometry );
}
if ( planarFigure->IsPreviewControlPointVisible() )
{
this->DrawMarker( planarFigure->GetPreviewControlPoint(),
m_MarkerlineColor[PF_HOVER],
m_MarkerlineOpacity[PF_HOVER],
m_MarkerColor[PF_HOVER],
m_MarkerOpacity[PF_HOVER],
m_LineWidth,
m_ControlPointShape,
- planarFigureGeometry2D,
- rendererGeometry2D,
+ planarFigurePlaneGeometry,
+ rendererPlaneGeometry,
displayGeometry
);
}
}
void mitk::PlanarFigureMapper2D::RenderAnnotations( mitk::BaseRenderer * renderer,
std::string name,
mitk::Point2D anchorPoint,
float globalOpacity,
PlanarFigureDisplayMode lineDisplayMode,
double &annotationOffset )
{
mitk::VtkPropRenderer* openGLrenderer = dynamic_cast<mitk::VtkPropRenderer*>( renderer );
if ( openGLrenderer )
{
openGLrenderer->WriteSimpleText( name,
anchorPoint[0] + 6.0, anchorPoint[1] + 4.0,
0,
0,
0,
globalOpacity ); //this is a shadow
openGLrenderer->WriteSimpleText( name,
anchorPoint[0] + 5.0, anchorPoint[1] + 5.0,
m_LineColor[lineDisplayMode][0],
m_LineColor[lineDisplayMode][1],
m_LineColor[lineDisplayMode][2],
globalOpacity );
// If drawing is successful, add approximate height to annotation offset
annotationOffset -= 15.0;
}
}
void mitk::PlanarFigureMapper2D::RenderQuantities( mitk::PlanarFigure * planarFigure,
mitk::BaseRenderer * renderer,
mitk::Point2D anchorPoint,
double &annotationOffset,
float globalOpacity,
PlanarFigureDisplayMode lineDisplayMode )
{
std::stringstream quantityString;
quantityString.setf( ios::fixed, ios::floatfield );
quantityString.precision( 1 );
bool firstActiveFeature = true;
for ( unsigned int i = 0; i < planarFigure->GetNumberOfFeatures(); ++i )
{
if( planarFigure->IsFeatureActive(i) && planarFigure->IsFeatureVisible( i ) )
{
if ( ! firstActiveFeature )
{
quantityString << " x ";
}
quantityString << planarFigure->GetQuantity( i ) << " ";
quantityString << planarFigure->GetFeatureUnit( i );
firstActiveFeature = false;
}
}
mitk::VtkPropRenderer* openGLrenderer = dynamic_cast<mitk::VtkPropRenderer*>( renderer );
if ( openGLrenderer )
{
openGLrenderer->WriteSimpleText( quantityString.str().c_str(),
anchorPoint[0] + 6.0, anchorPoint[1] + 4.0 + annotationOffset,
0,
0,
0,
globalOpacity ); //this is a shadow
openGLrenderer->WriteSimpleText( quantityString.str().c_str(),
anchorPoint[0] + 5.0, anchorPoint[1] + 5.0 + annotationOffset,
m_LineColor[lineDisplayMode][0],
m_LineColor[lineDisplayMode][1],
m_LineColor[lineDisplayMode][2],
globalOpacity );
// If drawing is successful, add approximate height to annotation offset
annotationOffset -= 15.0;
}
}
void mitk::PlanarFigureMapper2D::RenderLines( PlanarFigureDisplayMode lineDisplayMode,
mitk::PlanarFigure * planarFigure,
mitk::Point2D &anchorPoint,
- mitk::Geometry2D * planarFigureGeometry2D,
- const mitk::Geometry2D * rendererGeometry2D,
+ mitk::PlaneGeometry * planarFigurePlaneGeometry,
+ const mitk::PlaneGeometry * rendererPlaneGeometry,
mitk::DisplayGeometry * displayGeometry )
{
glLineStipple(1, 0x00FF);
// If we want to draw an outline, we do it here
if ( m_DrawOutline )
{
float* color = m_OutlineColor[lineDisplayMode];
float opacity = m_OutlineOpacity[lineDisplayMode];
// convert to a float array that also contains opacity, faster GL
float* colorVector = new float[4];
colorVector[0] = color[0];
colorVector[1] = color[1];
colorVector[2] = color[2];
colorVector[3] = opacity;
// set the color and opacity here as it is common for all outlines
glColor4fv( colorVector );
glLineWidth(m_OutlineWidth);
if (m_DrawDashed)
glEnable(GL_LINE_STIPPLE);
else
glDisable(GL_LINE_STIPPLE);
// Draw the outline for all polylines if requested
this->DrawMainLines( planarFigure,
anchorPoint,
- planarFigureGeometry2D,
- rendererGeometry2D,
+ planarFigurePlaneGeometry,
+ rendererPlaneGeometry,
displayGeometry );
glLineWidth( m_HelperlineWidth );
if (m_DrawHelperDashed)
glEnable(GL_LINE_STIPPLE);
else
glDisable(GL_LINE_STIPPLE);
// Draw the outline for all helper objects if requested
this->DrawHelperLines( planarFigure,
anchorPoint,
- planarFigureGeometry2D,
- rendererGeometry2D,
+ planarFigurePlaneGeometry,
+ rendererPlaneGeometry,
displayGeometry );
// cleanup
delete[] colorVector;
}
// If we want to draw a shadow, we do it here
if ( m_DrawShadow )
{
// determine the shadow opacity
float opacity = m_OutlineOpacity[lineDisplayMode];
float shadowOpacity = 0.0f;
if( opacity > 0.2f )
shadowOpacity = opacity - 0.2f;
// convert to a float array that also contains opacity, faster GL
float* shadow = new float[4];
shadow[0] = 0;
shadow[1] = 0;
shadow[2] = 0;
shadow[3] = shadowOpacity;
// set the color and opacity here as it is common for all shadows
glColor4fv( shadow );
glLineWidth( m_OutlineWidth * m_ShadowWidthFactor );
if (m_DrawDashed)
glEnable(GL_LINE_STIPPLE);
else
glDisable(GL_LINE_STIPPLE);
// Draw the outline for all polylines if requested
this->DrawMainLines( planarFigure,
anchorPoint,
- planarFigureGeometry2D,
- rendererGeometry2D,
+ planarFigurePlaneGeometry,
+ rendererPlaneGeometry,
displayGeometry );
glLineWidth( m_HelperlineWidth );
if (m_DrawHelperDashed)
glEnable(GL_LINE_STIPPLE);
else
glDisable(GL_LINE_STIPPLE);
// Draw the outline for all helper objects if requested
this->DrawHelperLines( planarFigure,
anchorPoint,
- planarFigureGeometry2D,
- rendererGeometry2D,
+ planarFigurePlaneGeometry,
+ rendererPlaneGeometry,
displayGeometry );
// cleanup
delete[] shadow;
}
// set this in brackets to avoid duplicate variables in the same scope
{
float* color = m_LineColor[lineDisplayMode];
float opacity = m_LineOpacity[lineDisplayMode];
// convert to a float array that also contains opacity, faster GL
float* colorVector = new float[4];
colorVector[0] = color[0];
colorVector[1] = color[1];
colorVector[2] = color[2];
colorVector[3] = opacity;
// set the color and opacity here as it is common for all mainlines
glColor4fv( colorVector );
glLineWidth( m_LineWidth );
if (m_DrawDashed)
glEnable(GL_LINE_STIPPLE);
else
glDisable(GL_LINE_STIPPLE);
// Draw the main line for all polylines
this->DrawMainLines( planarFigure,
anchorPoint,
- planarFigureGeometry2D,
- rendererGeometry2D,
+ planarFigurePlaneGeometry,
+ rendererPlaneGeometry,
displayGeometry );
float* helperColor = m_HelperlineColor[lineDisplayMode];
float helperOpacity = m_HelperlineOpacity[lineDisplayMode];
// convert to a float array that also contains opacity, faster GL
float* helperColorVector = new float[4];
helperColorVector[0] = helperColor[0];
helperColorVector[1] = helperColor[1];
helperColorVector[2] = helperColor[2];
helperColorVector[3] = helperOpacity;
// we only set the color for the helperlines as the linewidth is unchanged
glColor4fv( helperColorVector );
glLineWidth( m_HelperlineWidth );
if (m_DrawHelperDashed)
glEnable(GL_LINE_STIPPLE);
else
glDisable(GL_LINE_STIPPLE);
// Draw helper objects
this->DrawHelperLines( planarFigure,
anchorPoint,
- planarFigureGeometry2D,
- rendererGeometry2D,
+ planarFigurePlaneGeometry,
+ rendererPlaneGeometry,
displayGeometry );
// cleanup
delete[] colorVector;
delete[] helperColorVector;
}
if ( m_DrawDashed || m_DrawHelperDashed )
glDisable(GL_LINE_STIPPLE);
}
diff --git a/Modules/PlanarFigure/Rendering/mitkPlanarFigureMapper2D.h b/Modules/PlanarFigure/Rendering/mitkPlanarFigureMapper2D.h
index fcc14dbc40..0ed01fe74e 100644
--- a/Modules/PlanarFigure/Rendering/mitkPlanarFigureMapper2D.h
+++ b/Modules/PlanarFigure/Rendering/mitkPlanarFigureMapper2D.h
@@ -1,309 +1,309 @@
/*===================================================================
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 MITK_PLANAR_FIGURE_MAPPER_2D_H_
#define MITK_PLANAR_FIGURE_MAPPER_2D_H_
#include "mitkCommon.h"
#include <MitkPlanarFigureExports.h>
#include "mitkGLMapper.h"
#include "mitkPlanarFigure.h"
#include "mitkPlanarFigureControlPointStyleProperty.h"
namespace mitk {
class BaseRenderer;
class Contour;
/**
* \brief OpenGL-based mapper to render display sub-class instances of mitk::PlanarFigure
*
* The appearance of planar figures can be configured through properties. If no properties are specified,
* default values will be used. There are four elements a planar figure consists of:
*
* <ol>
* <li>"line": the main line segments of the planar figure (note: text is drawn in the same style)
* <li>"helperline": additional line segments of planar figures, such as arrow tips, arches of angles, etc.
* <li>"outline": background which is drawn behind the lines and helperlines of the planar figure (optional)
* <li>"marker": the markers (control points) of a planar figure
* <li>"markerline": the lines by which markers (control points) are surrounded
* </ol>
*
* In the following, all appearance-related planar figure properties are listed:
*
* <ol>
* <li>General properties for the planar figure
* <ul>
* <li>"planarfigure.drawoutline": if true, the "outline" lines is drawn
* <li>"planarfigure.drawquantities": if true, the quantities (text) associated with the planar figure is drawn
* <li>"planarfigure.drawname": if true, the name specified by the dataNode is drawn
* <li>"planarfigure.drawshadow": if true, a black shadow is drawn around the planar figure
* <li>"planarfigure.controlpointshape": style of the control points (enum)
* </ul>
* <li>Line widths of planar figure elements
* <ul>
* <li>"planarfigure.line.width": width of "line" segments (float value, in mm)
* <li>"planarfigure.shadow.widthmodifier": the width of the shadow is defined by width of the "line" * this modifier
* <li>"planarfigure.outline.width": width of "outline" segments (float value, in mm)
* <li>"planarfigure.helperline.width": width of "helperline" segments (float value, in mm)
* </ul>
* <li>Color/opacity of planar figure elements in normal mode (unselected)
* <ul>
* <li>"planarfigure.default.line.color"
* <li>"planarfigure.default.line.opacity"
* <li>"planarfigure.default.outline.color"
* <li>"planarfigure.default.outline.opacity"
* <li>"planarfigure.default.helperline.color"
* <li>"planarfigure.default.helperline.opacity"
* <li>"planarfigure.default.markerline.color"
* <li>"planarfigure.default.markerline.opacity"
* <li>"planarfigure.default.marker.color"
* <li>"planarfigure.default.marker.opacity"
* </ul>
* <li>Color/opacity of planar figure elements in hover mode (mouse-over)
* <ul>
* <li>"planarfigure.hover.line.color"
* <li>"planarfigure.hover.line.opacity"
* <li>"planarfigure.hover.outline.color"
* <li>"planarfigure.hover.outline.opacity"
* <li>"planarfigure.hover.helperline.color"
* <li>"planarfigure.hover.helperline.opacity"
* <li>"planarfigure.hover.markerline.color"
* <li>"planarfigure.hover.markerline.opacity"
* <li>"planarfigure.hover.marker.color"
* <li>"planarfigure.hover.marker.opacity"
* </ul>
* <li>Color/opacity of planar figure elements in selected mode
* <ul>
* <li>"planarfigure.selected.line.color"
* <li>"planarfigure.selected.line.opacity"
* <li>"planarfigure.selected.outline.color"
* <li>"planarfigure.selected.outline.opacity"
* <li>"planarfigure.selected.helperline.color"
* <li>"planarfigure.selected.helperline.opacity"
* <li>"planarfigure.selected.markerline.color;"
* <li>"planarfigure.selected.markerline.opacity"
* <li>"planarfigure.selected.marker.color"
* <li>"planarfigure.selected.marker.opacity"
* </ul>
* </ol>
*
* \ingroup Mapper
*/
class MitkPlanarFigure_EXPORT PlanarFigureMapper2D : public GLMapper
{
public:
mitkClassMacro(PlanarFigureMapper2D, GLMapper);
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/**
* reimplemented from Baseclass
*/
virtual void Paint(BaseRenderer * renderer);
static void SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer = NULL, bool overwrite = false);
protected:
enum PlanarFigureDisplayMode
{
PF_DEFAULT = 0,
PF_HOVER = 1,
PF_SELECTED = 2,
PF_COUNT = 3 //helper variable
};
PlanarFigureMapper2D();
virtual ~PlanarFigureMapper2D();
/**
* \brief Renders all the lines defined by the PlanarFigure.
*
* This method renders all the lines that are defined by the PlanarFigure.
* That includes the mainlines and helperlines as well as their shadows
* and the outlines.
*
* This method already takes responsibility for the setting of the relevant
* openGL attributes to reduce unnecessary setting of these attributes.
* (e.g. no need to set color twice if it's the same)
*/
void RenderLines( PlanarFigureDisplayMode lineDisplayMode,
mitk::PlanarFigure * planarFigure,
mitk::Point2D &anchorPoint,
- mitk::Geometry2D * planarFigureGeometry2D,
- const mitk::Geometry2D * rendererGeometry2D,
+ mitk::PlaneGeometry * planarFigurePlaneGeometry,
+ const mitk::PlaneGeometry * rendererPlaneGeometry,
mitk::DisplayGeometry * displayGeometry );
/**
* \brief Renders the quantities of the figure below the text annotations.
*/
void RenderQuantities( mitk::PlanarFigure * planarFigure,
mitk::BaseRenderer * renderer,
mitk::Point2D anchorPoint,
double &annotationOffset,
float globalOpacity,
PlanarFigureDisplayMode lineDisplayMode );
/**
* \brief Renders the text annotations.
*/
void RenderAnnotations( mitk::BaseRenderer * renderer,
std::string name,
mitk::Point2D anchorPoint,
float globalOpacity,
PlanarFigureDisplayMode lineDisplayMode,
double &annotationOffset );
/**
* \brief Renders the control-points.
*/
void RenderControlPoints( mitk::PlanarFigure * planarFigure,
PlanarFigureDisplayMode lineDisplayMode,
- mitk::Geometry2D * planarFigureGeometry2D,
- const mitk::Geometry2D * rendererGeometry2D,
+ mitk::PlaneGeometry * planarFigurePlaneGeometry,
+ const mitk::PlaneGeometry * rendererPlaneGeometry,
mitk::DisplayGeometry * displayGeometry );
void TransformObjectToDisplay(
const mitk::Point2D &point2D,
mitk::Point2D &displayPoint,
- const mitk::Geometry2D *objectGeometry,
- const mitk::Geometry2D *rendererGeometry,
+ const mitk::PlaneGeometry *objectGeometry,
+ const mitk::PlaneGeometry *rendererGeometry,
const mitk::DisplayGeometry *displayGeometry );
void DrawMarker(
const mitk::Point2D &point,
float* lineColor,
float lineOpacity,
float* markerColor,
float markerOpacity,
float lineWidth,
PlanarFigureControlPointStyleProperty::Shape shape,
- const mitk::Geometry2D *objectGeometry,
- const mitk::Geometry2D *rendererGeometry,
+ const mitk::PlaneGeometry *objectGeometry,
+ const mitk::PlaneGeometry *rendererGeometry,
const mitk::DisplayGeometry *displayGeometry );
/**
* \brief Actually paints the polyline defined by the figure.
*/
void PaintPolyLine( mitk::PlanarFigure::PolyLineType vertices,
bool closed,
Point2D& anchorPoint,
- const Geometry2D* planarFigureGeometry2D,
- const Geometry2D* rendererGeometry2D,
+ const PlaneGeometry* planarFigurePlaneGeometry,
+ const PlaneGeometry* rendererPlaneGeometry,
const DisplayGeometry* displayGeometry);
/**
* \brief Internally used by RenderLines() to draw the mainlines using
* PaintPolyLine().
*/
void DrawMainLines( mitk::PlanarFigure* figure,
Point2D& anchorPoint,
- const Geometry2D* planarFigureGeometry2D,
- const Geometry2D* rendererGeometry2D,
+ const PlaneGeometry* planarFigurePlaneGeometry,
+ const PlaneGeometry* rendererPlaneGeometry,
const DisplayGeometry* displayGeometry) ;
/**
* \brief Internally used by RenderLines() to draw the helperlines using
* PaintPolyLine().
*/
void DrawHelperLines( mitk::PlanarFigure* figure,
Point2D& anchorPoint,
- const Geometry2D* planarFigureGeometry2D,
- const Geometry2D* rendererGeometry2D,
+ const PlaneGeometry* planarFigurePlaneGeometry,
+ const PlaneGeometry* rendererPlaneGeometry,
const DisplayGeometry* displayGeometry) ;
void InitializeDefaultPlanarFigureProperties();
void InitializePlanarFigurePropertiesFromDataNode( const mitk::DataNode* node );
void SetColorProperty( float property[3][3], PlanarFigureDisplayMode mode, float red, float green, float blue )
{
property[mode][0] = red;
property[mode][1] = green;
property[mode][2] = blue;
}
void SetFloatProperty( float* property, PlanarFigureDisplayMode mode, float value )
{
property[mode] = value;
}
/**
* \brief Callback that sets m_NodeModified to true.
*
* This method set the bool flag m_NodeModified to true. It's a callback
* that is executed when a itk::ModifiedEvet is invoked on our
* DataNode.
*/
void OnNodeModified();
private:
bool m_IsSelected;
bool m_IsHovering;
bool m_DrawOutline;
bool m_DrawQuantities;
bool m_DrawShadow;
bool m_DrawControlPoints;
bool m_DrawName;
bool m_DrawDashed;
bool m_DrawHelperDashed;
// the width of the shadow is defined as 'm_LineWidth * m_ShadowWidthFactor'
float m_LineWidth;
float m_ShadowWidthFactor;
float m_OutlineWidth;
float m_HelperlineWidth;
//float m_PointWidth;
PlanarFigureControlPointStyleProperty::Shape m_ControlPointShape;
float m_LineColor[3][3];
float m_LineOpacity[3];
float m_OutlineColor[3][3];
float m_OutlineOpacity[3];
float m_HelperlineColor[3][3];
float m_HelperlineOpacity[3];
float m_MarkerlineColor[3][3];
float m_MarkerlineOpacity[3];
float m_MarkerColor[3][3];
float m_MarkerOpacity[3];
// Bool flag that represents whether or not the DataNode has been modified.
bool m_NodeModified;
// Observer-tag for listening to itk::ModifiedEvents on the DataNode
unsigned long m_NodeModifiedObserverTag;
// Bool flag that indicates if a node modified observer was added
bool m_NodeModifiedObserverAdded;
};
} // namespace mitk
#endif /* MITK_PLANAR_FIGURE_MAPPER_2D_H_ */
diff --git a/Modules/PlanarFigure/Rendering/mitkPlanarFigureVtkMapper3D.cpp b/Modules/PlanarFigure/Rendering/mitkPlanarFigureVtkMapper3D.cpp
index dbb2c23fbd..c8b0b2a76a 100644
--- a/Modules/PlanarFigure/Rendering/mitkPlanarFigureVtkMapper3D.cpp
+++ b/Modules/PlanarFigure/Rendering/mitkPlanarFigureVtkMapper3D.cpp
@@ -1,191 +1,191 @@
/*===================================================================
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 "mitkPlanarFigureVtkMapper3D.h"
#include "mitkImage.h"
#include "mitkPlaneGeometry.h"
#include <mitkPlanarFigure.h>
#include <vtkCellArray.h>
#include <vtkIdList.h>
#include <vtkPoints.h>
#include <vtkPolyData.h>
#include <vtkPolyDataMapper.h>
#include <vtkPolyLine.h>
mitk::PlanarFigureVtkMapper3D::LocalStorage::LocalStorage()
: m_Actor(vtkSmartPointer<vtkActor>::New()),
m_LastMTime(0)
{
}
mitk::PlanarFigureVtkMapper3D::LocalStorage::~LocalStorage()
{
}
void mitk::PlanarFigureVtkMapper3D::SetDefaultProperties(DataNode*, BaseRenderer*, bool)
{
}
mitk::PlanarFigureVtkMapper3D::PlanarFigureVtkMapper3D()
{
}
mitk::PlanarFigureVtkMapper3D::~PlanarFigureVtkMapper3D()
{
}
void mitk::PlanarFigureVtkMapper3D::ApplyColorAndOpacityProperties(BaseRenderer* renderer, vtkActor* actor)
{
if (actor == NULL)
return;
mitk::DataNode* dataNode = this->GetDataNode();
if (dataNode == NULL)
return;
bool selected = false;
dataNode->GetBoolProperty("selected", selected, renderer);
float color[3];
dataNode->GetColor(color, renderer, selected ? "planarfigure.selected.line.color" : "color");
float opacity = 1.0f;
dataNode->GetOpacity(opacity, renderer);
vtkProperty* property = actor->GetProperty();
property->SetColor(color[0], color[1], color[2]);
property->SetOpacity(opacity);
}
void mitk::PlanarFigureVtkMapper3D::ApplyPlanarFigureProperties(BaseRenderer* renderer, vtkActor* actor)
{
if (actor == NULL)
return;
mitk::DataNode* dataNode = this->GetDataNode();
if (dataNode == NULL)
return;
bool render = false;
dataNode->GetBoolProperty("planarfigure.3drendering", render);
actor->SetVisibility(render);
float lineWidth = 1.0f;
dataNode->GetFloatProperty("planarfigure.line.width", lineWidth, renderer);
vtkProperty* property = actor->GetProperty();
property->SetLineWidth(lineWidth);
}
void mitk::PlanarFigureVtkMapper3D::GenerateDataForRenderer(BaseRenderer* renderer)
{
typedef PlanarFigure::PolyLineType PolyLine;
DataNode* node = this->GetDataNode();
if (node == NULL)
return;
PlanarFigure* planarFigure = dynamic_cast<PlanarFigure*>(node->GetData());
if (planarFigure == NULL || !planarFigure->IsPlaced())
return;
LocalStorage* localStorage = m_LocalStorageHandler.GetLocalStorage(renderer);
unsigned long mTime = planarFigure->GetMTime();
if (mTime > localStorage->m_LastMTime)
{
localStorage->m_LastMTime = mTime;
- const PlaneGeometry* planeGeometry = dynamic_cast<const PlaneGeometry*>(planarFigure->GetGeometry2D());
+ const PlaneGeometry* planeGeometry = dynamic_cast<const PlaneGeometry*>(planarFigure->GetPlaneGeometry());
if (planeGeometry == NULL)
return;
size_t numPolyLines = planarFigure->GetPolyLinesSize();
if (numPolyLines == 0)
return;
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkCellArray> cells = vtkSmartPointer<vtkCellArray>::New();
vtkIdType baseIndex = 0;
for (size_t i = 0; i < numPolyLines; ++i)
{
PolyLine polyLine = planarFigure->GetPolyLine(i);
vtkIdType numPoints = polyLine.size();
if (numPoints < 2)
continue;
PolyLine::const_iterator polyLineEnd = polyLine.end();
for (PolyLine::const_iterator polyLineIt = polyLine.begin(); polyLineIt != polyLineEnd; ++polyLineIt)
{
Point3D point;
planeGeometry->Map(*polyLineIt, point);
points->InsertNextPoint(point.GetDataPointer());
}
vtkSmartPointer<vtkPolyLine> line = vtkSmartPointer<vtkPolyLine>::New();
vtkIdList* pointIds = line->GetPointIds();
if (planarFigure->IsClosed() && numPoints > 2)
{
pointIds->SetNumberOfIds(numPoints + 1);
pointIds->SetId(numPoints, baseIndex);
}
else
{
pointIds->SetNumberOfIds(numPoints);
}
for (vtkIdType j = 0; j < numPoints; ++j)
pointIds->SetId(j, baseIndex + j);
cells->InsertNextCell(line);
baseIndex += points->GetNumberOfPoints();
}
vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New();
polyData->SetPoints(points);
polyData->SetLines(cells);
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputData(polyData);
localStorage->m_Actor->SetMapper(mapper);
}
this->ApplyColorAndOpacityProperties(renderer, localStorage->m_Actor);
this->ApplyPlanarFigureProperties(renderer, localStorage->m_Actor);
}
vtkProp* mitk::PlanarFigureVtkMapper3D::GetVtkProp(BaseRenderer* renderer)
{
return m_LocalStorageHandler.GetLocalStorage(renderer)->m_Actor;
}
void mitk::PlanarFigureVtkMapper3D::UpdateVtkTransform(BaseRenderer*)
{
}
diff --git a/Modules/PlanarFigure/Testing/mitkPlanarArrowTest.cpp b/Modules/PlanarFigure/Testing/mitkPlanarArrowTest.cpp
index 2b4cd73969..8482b3611e 100644
--- a/Modules/PlanarFigure/Testing/mitkPlanarArrowTest.cpp
+++ b/Modules/PlanarFigure/Testing/mitkPlanarArrowTest.cpp
@@ -1,95 +1,95 @@
/*===================================================================
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 "mitkTestingMacros.h"
#include "mitkPlanarArrow.h"
#include "mitkPlaneGeometry.h"
class mitkPlanarArrowTestClass
{
public:
static void TestPlanarArrowPlacement( mitk::PlanarArrow::Pointer PlanarArrow )
{
// Test for correct minimum number of control points in cross-mode
MITK_TEST_CONDITION( PlanarArrow->GetMinimumNumberOfControlPoints() == 2, "Minimum number of control points" );
// Test for correct maximum number of control points in cross-mode
MITK_TEST_CONDITION( PlanarArrow->GetMaximumNumberOfControlPoints() == 2, "Maximum number of control points" );
// Initial placement of PlanarArrow
mitk::Point2D p0;
p0[0] = 00.0; p0[1] = 0.0;
PlanarArrow->PlaceFigure( p0 );
// Add second control point
mitk::Point2D p1;
p1[0] = 50.0; p1[1] = 00.0;
PlanarArrow->SetControlPoint(1, p1 );
// Test for number of control points
MITK_TEST_CONDITION( PlanarArrow->GetNumberOfControlPoints() == 2, "Number of control points after placement" );
// Test for number of polylines
const mitk::PlanarFigure::PolyLineType polyLine0 = PlanarArrow->GetPolyLine( 0 );
mitk::PlanarFigure::PolyLineType::const_iterator iter = polyLine0.begin();
MITK_TEST_CONDITION( PlanarArrow->GetPolyLinesSize() == 1, "Number of polylines after placement" );
// Get polylines and check if the generated coordinates are OK
const mitk::Point2D& pp0 = *iter;
iter++;
const mitk::Point2D& pp1 = *iter;
MITK_TEST_CONDITION( (pp0 == p0) && (pp1 == p1), "Correct polyline 1" );
// Test for number of measurement features
// none yet
}
};
/**
* mitkPlanarArrowTest tests the methods and behavior of mitk::PlanarArrow with sub-tests:
*
* 1. Instantiation and basic tests
*
*/
int mitkPlanarArrowTest(int /* argc */, char* /*argv*/[])
{
// always start with this!
MITK_TEST_BEGIN("PlanarArrow")
// create PlaneGeometry on which to place the PlanarArrow
mitk::PlaneGeometry::Pointer planeGeometry = mitk::PlaneGeometry::New();
planeGeometry->InitializeStandardPlane( 100.0, 100.0 );
// **************************************************************************
// 1. Instantiation and basic tests
mitk::PlanarArrow::Pointer PlanarArrow = mitk::PlanarArrow::New();
- PlanarArrow->SetGeometry2D( planeGeometry );
+ PlanarArrow->SetPlaneGeometry( planeGeometry );
// first test: did this work?
MITK_TEST_CONDITION_REQUIRED( PlanarArrow.IsNotNull(), "Testing instantiation" );
// Test placement of PlanarArrow by control points
mitkPlanarArrowTestClass::TestPlanarArrowPlacement( PlanarArrow );
// always end with this!
MITK_TEST_END();
}
diff --git a/Modules/PlanarFigure/Testing/mitkPlanarCrossTest.cpp b/Modules/PlanarFigure/Testing/mitkPlanarCrossTest.cpp
index c9da5e9d1c..50cd628a9f 100644
--- a/Modules/PlanarFigure/Testing/mitkPlanarCrossTest.cpp
+++ b/Modules/PlanarFigure/Testing/mitkPlanarCrossTest.cpp
@@ -1,417 +1,417 @@
/*===================================================================
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 "mitkTestingMacros.h"
#include "mitkPlanarCross.h"
#include "mitkPlaneGeometry.h"
class mitkPlanarCrossTestClass
{
public:
static void TestPlanarCrossPlacement( mitk::PlanarCross::Pointer planarCross )
{
// Test for correct minimum number of control points in cross-mode
MITK_TEST_CONDITION( planarCross->GetMinimumNumberOfControlPoints() == 4, "Minimum number of control points" );
// Test for correct maximum number of control points in cross-mode
MITK_TEST_CONDITION( planarCross->GetMaximumNumberOfControlPoints() == 4, "Maximum number of control points" );
// Initial placement of PlanarCross
mitk::Point2D p0;
p0[0] = 20.0; p0[1] = 20.0;
planarCross->PlaceFigure( p0 );
// Add second control point
mitk::Point2D p1;
p1[0] = 80.0; p1[1] = 80.0;
planarCross->SetCurrentControlPoint( p1 );
// Add third control point
mitk::Point2D p2;
p2[0] = 90.0; p2[1] = 10.0;
planarCross->AddControlPoint( p2 );
// Test if helper polyline is generated
const mitk::PlanarFigure::PolyLineType helperPolyLine = planarCross->GetHelperPolyLine( 0, 1.0, 100 );
MITK_TEST_CONDITION( planarCross->GetHelperPolyLinesSize() == 1, "Number of helper polylines after placing 3 points" );
// Test if helper polyline is marked as "to be painted"
MITK_TEST_CONDITION( planarCross->IsHelperToBePainted( 0 ), "Helper line to be painted after placing 3 points" );
// Test if helper polyline is orthogonal to first line
mitk::Vector2D v0 = p1 - p0;
v0.Normalize();
// TODO: make it work again
//mitk::Vector2D hv = helperPolyLine->ElementAt( 1 ) - helperPolyLine->ElementAt( 0 );
//hv.Normalize();
//MITK_TEST_CONDITION( fabs(v0 * hv) < mitk::eps, "Helper line is orthogonal to first line" );
//// Test if helper polyline is placed correctly
//mitk::Vector2D hv1 = helperPolyLine->ElementAt( 1 ) - p2;
//hv1.Normalize();
//MITK_TEST_CONDITION( fabs(hv * hv1 - 1.0) < mitk::eps, "Helper line is aligned to third point" );
// Add fourth control point
mitk::Point2D p3;
p3[0] = 10.0; p3[1] = 90.0;
planarCross->AddControlPoint( p3 );
// Test for number of control points
MITK_TEST_CONDITION( planarCross->GetNumberOfControlPoints() == 4, "Number of control points after placement" );
// Test if PlanarFigure is closed
MITK_TEST_CONDITION( !planarCross->IsClosed(), "Is PlanarFigure closed?" );
// Test if helper polyline is no longer marked as "to be painted"
MITK_TEST_CONDITION( planarCross->IsHelperToBePainted( 0 ), "Helper line no longer to be painted after placement of all 4 points" );
// Test for number of polylines
const mitk::PlanarFigure::PolyLineType polyLine0 = planarCross->GetPolyLine( 0 );
const mitk::PlanarFigure::PolyLineType polyLine1 = planarCross->GetPolyLine( 1 );
MITK_TEST_CONDITION( planarCross->GetPolyLinesSize() == 2, "Number of polylines after placement" );
mitk::PlanarFigure::PolyLineType::const_iterator iter0 = polyLine0.begin();
mitk::PlanarFigure::PolyLineType::const_iterator iter1 = polyLine1.begin();
// Get polylines and check if the generated coordinates are OK
const mitk::Point2D& pp0 = *iter0;
iter0++;
const mitk::Point2D& pp1 = *iter0;
MITK_TEST_CONDITION( ((pp0 == p0) && (pp1 == p1))
|| ((pp0 == p1) && (pp1 == p0)), "Correct polyline 1" );
const mitk::Point2D& pp2 = *iter1;
iter1++;
const mitk::Point2D& pp3 = *iter1;
MITK_TEST_CONDITION( ((pp2 == p2) && (pp3 == p3))
|| ((pp2 == p3) && (pp3 == p2)), "Correct polyline 2" );
// Test for number of measurement features
planarCross->EvaluateFeatures();
MITK_TEST_CONDITION( planarCross->GetNumberOfFeatures() == 2, "Number of measurement features" );
// Test for correct feature evaluation
double length0 = sqrt( 80.0 * 80.0 * 2.0 );
MITK_TEST_CONDITION( fabs( planarCross->GetQuantity( 0 ) - length0) < mitk::eps, "Size of longest diameter" );
double length1 = sqrt( 60.0 * 60.0 * 2.0 );
MITK_TEST_CONDITION( fabs( planarCross->GetQuantity( 1 ) - length1) < mitk::eps, "Size of short axis diameter" );
}
static void TestPlanarCrossPlacementSingleLine(mitk::PlanarCross::Pointer planarCross)
{
// Test for correct minimum number of control points in cross-mode
MITK_TEST_CONDITION( planarCross->GetMinimumNumberOfControlPoints() == 2, "Minimum number of control points" );
// Test for correct maximum number of control points in cross-mode
MITK_TEST_CONDITION( planarCross->GetMaximumNumberOfControlPoints() == 2, "Maximum number of control points" );
// Initial placement of PlanarCross
mitk::Point2D p0;
p0[0] = 25.0; p0[1] = 10.0;
planarCross->PlaceFigure( p0 );
// Add second control point
mitk::Point2D p1;
p1[0] = 30.0; p1[1] = 60.0;
planarCross->SetCurrentControlPoint( p1 );
// Verify that no helper line is drawn
MITK_TEST_CONDITION( planarCross->IsHelperToBePainted( 0 ) == false, "No helper line to be painted in single-line mode" );
// Test for number of control points
MITK_TEST_CONDITION( planarCross->GetNumberOfControlPoints() == 2, "Number of control points after placement" );
// Test if PlanarFigure is closed
MITK_TEST_CONDITION( !planarCross->IsClosed(), "Is PlanarFigure closed?" );
// Test for number of polylines
const mitk::PlanarFigure::PolyLineType polyLine0 = planarCross->GetPolyLine( 0 );
mitk::PlanarFigure::PolyLineType::const_iterator iter = polyLine0.begin();
MITK_TEST_CONDITION( planarCross->GetPolyLinesSize() == 1, "Number of polylines after placement" );
// Get polylines and check if the generated coordinates are OK
const mitk::Point2D& pp0 = *iter;
iter++;
const mitk::Point2D& pp1 = *iter;
MITK_TEST_CONDITION( ((pp0 == p0) && (pp1 == p1))
|| ((pp0 == p1) && (pp1 == p0)), "Correct polyline 1" );
// Test for number of measurement features
planarCross->EvaluateFeatures();
MITK_TEST_CONDITION( planarCross->GetNumberOfFeatures() == 1, "Number of measurement features" );
// Test for correct feature evaluation
double length0 = sqrt( 5.0 * 5.0 + 50.0 * 50.0 );
MITK_TEST_CONDITION( fabs( planarCross->GetQuantity( 0 ) - length0) < mitk::eps, "Size of diameter" );
// Test if reset called on single-line PlanarCross returns false (nothing to reset)
MITK_TEST_CONDITION( planarCross->ResetOnPointSelect() == false, "Single-line PlanarCross should not be reset on point edit" );
}
static void TestPlanarCrossPlacementConstrained(mitk::PlanarCross::Pointer planarCross)
{
// **************************************************************************
// Place first control point out of bounds (to the left of the image bounds)
mitk::Point2D p0;
p0[0] = -20.0; p0[1] = 20.0;
planarCross->PlaceFigure( p0 );
// Test if constraint has been applied correctly
mitk::Point2D cp0 = planarCross->GetControlPoint( 0 );
MITK_TEST_CONDITION(
(fabs(cp0[0]) < mitk::eps)
&& (fabs(cp0[1] - 20.0) < mitk::eps), "Point1 placed and constrained correctly" );
// **************************************************************************
// Add second control point out of bounds (to the top of the image bounds)
mitk::Point2D p1;
p1[0] = 80.0; p1[1] = 120.0;
planarCross->SetCurrentControlPoint( p1 );
// Test if constraint has been applied correctly
mitk::Point2D cp1 = planarCross->GetControlPoint( 1 );
MITK_TEST_CONDITION(
(fabs(cp1[0] - 80.0) < mitk::eps)
&& (fabs(cp1[1] - 100.0) < mitk::eps), "Point2 placed and constrained correctly" );
// **************************************************************************
// Add third control point out of bounds (outside of channel defined by first line)
mitk::Point2D p2;
p2[0] = 100.0; p2[1] = 100.0;
planarCross->AddControlPoint( p2 );
// Test if constraint has been applied correctly (100.0, 100.0) must be projected to (90.0, 90.0)
mitk::Point2D cp2 = planarCross->GetControlPoint( 2 );
MITK_TEST_CONDITION(
(fabs(cp2[0] - 90.0) < mitk::eps)
&& (fabs(cp2[1] - 90.0) < mitk::eps), "Point3 placed and constrained correctly" );
// Move third control point (within channel defined by first line)
p2[0] = 40.0; p2[1] = 20.0;
planarCross->SetControlPoint( 2, p2 );
// Test if point is still at this position (no constrained should be applied)
cp2 = planarCross->GetControlPoint( 2 );
MITK_TEST_CONDITION(
(fabs(cp2[0] - 40.0) < mitk::eps)
&& (fabs(cp2[1] - 20.0) < mitk::eps), "Point3 moved correctly" );
// **************************************************************************
// Add fourth control point out of bounds (outside of line defined by first line and third point)
mitk::Point2D p3;
p3[0] = 20.0; p3[1] = 60.0;
planarCross->AddControlPoint( p3 );
// Test if constraint has been applied correctly (20.0, 60.0) must be projected to (10.0, 50.0)
mitk::Point2D cp3 = planarCross->GetControlPoint( 3 );
MITK_TEST_CONDITION(
(fabs(cp3[0] - 10.0) < mitk::eps)
&& (fabs(cp3[1] - 50.0) < mitk::eps), "Point4 placed and constrained correctly" );
// Move fourth control point (to a position which would result in two non-intersecting line
// without the constraint that lines have to intersect)
p3[0] = 40.0; p3[1] = 30.0;
planarCross->SetControlPoint( 3, p3 );
// Test if constrained point is on the projected intersection point of both lines (20.0/40.0)
cp3 = planarCross->GetControlPoint( 3 );
MITK_TEST_CONDITION(
(fabs(cp3[0] - 20.0) < mitk::eps)
&& (fabs(cp3[1] - 40.0) < mitk::eps), "Point4 placed and constrained correctly" );
}
static void TestPlanarCrossEdit(mitk::PlanarCross::Pointer planarCross)
{
// * point move (different points)
// --> reset
// --> test which point is where / evaluation
mitk::Point2D p0 = planarCross->GetControlPoint( 0 );
mitk::Point2D p1 = planarCross->GetControlPoint( 1 );
mitk::Point2D p2 = planarCross->GetControlPoint( 2 );
mitk::Point2D p3 = planarCross->GetControlPoint( 3 );
// **************************************************************************
// Edit control point 0
planarCross->SelectControlPoint( 0 );
// Request reset and check if it is done
MITK_TEST_CONDITION( planarCross->ResetOnPointSelect(), "Editing control point 0: Double-line PlanarCross should be reset" );
// Check number of control points
MITK_TEST_CONDITION( planarCross->GetNumberOfControlPoints() == 2, "Two control points are left" );
// Check if correct control points have been left
MITK_TEST_CONDITION(
(planarCross->GetControlPoint( 0 ).EuclideanDistanceTo( p1 ) < mitk::eps)
&& (planarCross->GetControlPoint( 1 ).EuclideanDistanceTo( p0 ) < mitk::eps),
"Reset to expected control points (p1, p0)" );
// Reset planar cross to original values
ResetPlanarCross( planarCross, p0, p1, p2, p3 );
// **************************************************************************
// Edit control point 1
planarCross->SelectControlPoint( 1 );
// Request reset and check if it is done
MITK_TEST_CONDITION( planarCross->ResetOnPointSelect(), "Editing control point 1: Double-line PlanarCross should be reset" );
// Check number of control points
MITK_TEST_CONDITION( planarCross->GetNumberOfControlPoints() == 2, "Two control points are left" );
// Check if correct control points have been left
MITK_TEST_CONDITION(
(planarCross->GetControlPoint( 0 ).EuclideanDistanceTo( p0 ) < mitk::eps)
&& (planarCross->GetControlPoint( 1 ).EuclideanDistanceTo( p1 ) < mitk::eps),
"Reset to expected control points (p0, p1)" );
// Reset planar cross to original values
ResetPlanarCross( planarCross, p0, p1, p2, p3 );
// **************************************************************************
// Edit control point 2
planarCross->SelectControlPoint( 2 );
// Request reset and check if it is done
MITK_TEST_CONDITION( planarCross->ResetOnPointSelect(), "Editing control point 2: Double-line PlanarCross should be reset" );
// Check number of control points
MITK_TEST_CONDITION( planarCross->GetNumberOfControlPoints() == 2, "Two control points are left" );
// Check if correct control points have been left
MITK_TEST_CONDITION(
(planarCross->GetControlPoint( 0 ).EuclideanDistanceTo( p3 ) < mitk::eps)
&& (planarCross->GetControlPoint( 1 ).EuclideanDistanceTo( p2 ) < mitk::eps),
"Reset to expected control points (p3, p2)" );
// Reset planar cross to original values
ResetPlanarCross( planarCross, p0, p1, p2, p3 );
// **************************************************************************
// Edit control point 3
planarCross->SelectControlPoint( 3 );
// Request reset and check if it is done
MITK_TEST_CONDITION( planarCross->ResetOnPointSelect(), "Editing control point 3: Double-line PlanarCross should be reset" );
// Check number of control points
MITK_TEST_CONDITION( planarCross->GetNumberOfControlPoints() == 2, "Two control points are left" );
// Check if correct control points have been left
MITK_TEST_CONDITION(
(planarCross->GetControlPoint( 0 ).EuclideanDistanceTo( p2 ) < mitk::eps)
&& (planarCross->GetControlPoint( 1 ).EuclideanDistanceTo( p3 ) < mitk::eps),
"Reset to expected control points (p2, p3)" );
}
static void ResetPlanarCross( mitk::PlanarCross::Pointer planarCross,
mitk::Point2D p0, mitk::Point2D p1, mitk::Point2D p2, mitk::Point2D p3 )
{
planarCross->SetControlPoint( 0, p0, true );
planarCross->SetControlPoint( 1, p1, true );
planarCross->SetControlPoint( 2, p2, true );
planarCross->SetControlPoint( 3, p3, true );
}
};
/**
* mitkPlanarCrossTest tests the methods and behavior of mitk::PlanarCross with four sub-tests:
*
* 1. Double-line mode instantiation and basic tests
* 2. Single-line mode instantiation and basic tests
* 3. Tests of application of spatial constraints for double-line mode
* 4. Tests if editing of PlanarCross works as intended
*
*/
int mitkPlanarCrossTest(int /* argc */, char* /*argv*/[])
{
// always start with this!
MITK_TEST_BEGIN("PlanarCross")
// create PlaneGeometry on which to place the PlanarCross
mitk::PlaneGeometry::Pointer planeGeometry = mitk::PlaneGeometry::New();
planeGeometry->InitializeStandardPlane( 100.0, 100.0 );
// **************************************************************************
// 1. Double-line mode instantiation and basic tests
mitk::PlanarCross::Pointer planarCross = mitk::PlanarCross::New();
- planarCross->SetGeometry2D( planeGeometry );
+ planarCross->SetPlaneGeometry( planeGeometry );
// first test: did this work?
MITK_TEST_CONDITION_REQUIRED( planarCross.IsNotNull(), "Testing instantiation" );
// test: default cross-mode (not single-line-mode)?
MITK_TEST_CONDITION_REQUIRED( !planarCross->GetSingleLineMode(), "Testing default cross mode" );
// Test placement of PlanarCross by control points
mitkPlanarCrossTestClass::TestPlanarCrossPlacement( planarCross );
// **************************************************************************
// 2. Single-line mode instantiation and basic tests
planarCross = mitk::PlanarCross::New();
planarCross->SingleLineModeOn();
- planarCross->SetGeometry2D( planeGeometry );
+ planarCross->SetPlaneGeometry( planeGeometry );
// test: single-line mode?
MITK_TEST_CONDITION_REQUIRED( planarCross->GetSingleLineMode(), "Testing activation of single-line mode" );
// Test placement of single-line PlanarCross by control points
mitkPlanarCrossTestClass::TestPlanarCrossPlacementSingleLine( planarCross );
// **************************************************************************
// 3. Tests of application of spatial constraints for double-line mode
planarCross = mitk::PlanarCross::New();
- planarCross->SetGeometry2D( planeGeometry );
+ planarCross->SetPlaneGeometry( planeGeometry );
// Test placement with various out-of-bounds control points (automatic application of
// constraints expected)
mitkPlanarCrossTestClass::TestPlanarCrossPlacementConstrained( planarCross );
// **************************************************************************
// 4. Tests if editing of PlanarCross works as intended
mitkPlanarCrossTestClass::TestPlanarCrossEdit( planarCross );
// always end with this!
MITK_TEST_END()
}
diff --git a/Modules/PlanarFigure/Testing/mitkPlanarFigureIOTest.cpp b/Modules/PlanarFigure/Testing/mitkPlanarFigureIOTest.cpp
index 880bdfe77a..a2d73f8dc9 100644
--- a/Modules/PlanarFigure/Testing/mitkPlanarFigureIOTest.cpp
+++ b/Modules/PlanarFigure/Testing/mitkPlanarFigureIOTest.cpp
@@ -1,603 +1,603 @@
/*===================================================================
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 "mitkTestingMacros.h"
#include "mitkPlanarAngle.h"
#include "mitkPlanarCircle.h"
#include "mitkPlanarCross.h"
#include "mitkPlanarFourPointAngle.h"
#include "mitkPlanarLine.h"
#include "mitkPlanarPolygon.h"
#include "mitkPlanarSubdivisionPolygon.h"
#include "mitkPlanarRectangle.h"
#include "mitkPlanarFigureWriter.h"
#include "mitkPlanarFigureReader.h"
#include "mitkPlaneGeometry.h"
#include <itksys/SystemTools.hxx>
static mitk::PlanarFigure::Pointer Clone(mitk::PlanarFigure::Pointer original)
{
return original->Clone();
}
/** \brief Helper class for testing PlanarFigure reader and writer classes. */
class PlanarFigureIOTestClass
{
public:
typedef std::list< mitk::PlanarFigure::Pointer > PlanarFigureList;
typedef std::vector< mitk::PlanarFigureWriter::Pointer > PlanarFigureToMemoryWriterList;
static PlanarFigureList CreatePlanarFigures()
{
PlanarFigureList planarFigures;
// Create PlaneGeometry on which to place the PlanarFigures
mitk::PlaneGeometry::Pointer planeGeometry = mitk::PlaneGeometry::New();
planeGeometry->InitializeStandardPlane( 100.0, 100.0 );
// Create a few sample points for PlanarFigure placement
mitk::Point2D p0; p0[0] = 20.0; p0[1] = 20.0;
mitk::Point2D p1; p1[0] = 80.0; p1[1] = 80.0;
mitk::Point2D p2; p2[0] = 90.0; p2[1] = 10.0;
mitk::Point2D p3; p3[0] = 10.0; p3[1] = 90.0;
// Create PlanarAngle
mitk::PlanarAngle::Pointer planarAngle = mitk::PlanarAngle::New();
- planarAngle->SetGeometry2D( planeGeometry );
+ planarAngle->SetPlaneGeometry( planeGeometry );
planarAngle->PlaceFigure( p0 );
planarAngle->SetCurrentControlPoint( p1 );
planarAngle->AddControlPoint( p2 );
planarAngle->GetPropertyList()->SetBoolProperty( "initiallyplaced", true );
planarFigures.push_back( planarAngle.GetPointer() );
// Create PlanarCircle
mitk::PlanarCircle::Pointer planarCircle = mitk::PlanarCircle::New();
- planarCircle->SetGeometry2D( planeGeometry );
+ planarCircle->SetPlaneGeometry( planeGeometry );
planarCircle->PlaceFigure( p0 );
planarCircle->SetCurrentControlPoint( p1 );
planarCircle->GetPropertyList()->SetBoolProperty( "initiallyplaced", true );
planarFigures.push_back( planarCircle.GetPointer() );
// Create PlanarCross
mitk::PlanarCross::Pointer planarCross = mitk::PlanarCross::New();
planarCross->SetSingleLineMode( false );
- planarCross->SetGeometry2D( planeGeometry );
+ planarCross->SetPlaneGeometry( planeGeometry );
planarCross->PlaceFigure( p0 );
planarCross->SetCurrentControlPoint( p1 );
planarCross->AddControlPoint( p2 );
planarCross->AddControlPoint( p3 );
planarCross->GetPropertyList()->SetBoolProperty( "initiallyplaced", true );
planarFigures.push_back( planarCross.GetPointer() );
// Create PlanarFourPointAngle
mitk::PlanarFourPointAngle::Pointer planarFourPointAngle = mitk::PlanarFourPointAngle::New();
- planarFourPointAngle->SetGeometry2D( planeGeometry );
+ planarFourPointAngle->SetPlaneGeometry( planeGeometry );
planarFourPointAngle->PlaceFigure( p0 );
planarFourPointAngle->SetCurrentControlPoint( p1 );
planarFourPointAngle->AddControlPoint( p2 );
planarFourPointAngle->AddControlPoint( p3 );
planarFourPointAngle->GetPropertyList()->SetBoolProperty( "initiallyplaced", true );
planarFigures.push_back( planarFourPointAngle.GetPointer() );
// Create PlanarLine
mitk::PlanarLine::Pointer planarLine = mitk::PlanarLine::New();
- planarLine->SetGeometry2D( planeGeometry );
+ planarLine->SetPlaneGeometry( planeGeometry );
planarLine->PlaceFigure( p0 );
planarLine->SetCurrentControlPoint( p1 );
planarLine->GetPropertyList()->SetBoolProperty( "initiallyplaced", true );
planarFigures.push_back( planarLine.GetPointer() );
// Create PlanarPolygon
mitk::PlanarPolygon::Pointer planarPolygon = mitk::PlanarPolygon::New();
planarPolygon->SetClosed( false );
- planarPolygon->SetGeometry2D( planeGeometry );
+ planarPolygon->SetPlaneGeometry( planeGeometry );
planarPolygon->PlaceFigure( p0 );
planarPolygon->SetCurrentControlPoint( p1 );
planarPolygon->AddControlPoint( p2 );
planarPolygon->AddControlPoint( p3 );
planarPolygon->GetPropertyList()->SetBoolProperty( "initiallyplaced", true );
planarFigures.push_back( planarPolygon.GetPointer() );
// Create PlanarSubdivisionPolygon
mitk::PlanarSubdivisionPolygon::Pointer planarSubdivisionPolygon = mitk::PlanarSubdivisionPolygon::New();
planarSubdivisionPolygon->SetClosed( false );
- planarSubdivisionPolygon->SetGeometry2D( planeGeometry );
+ planarSubdivisionPolygon->SetPlaneGeometry( planeGeometry );
planarSubdivisionPolygon->PlaceFigure( p0 );
planarSubdivisionPolygon->SetCurrentControlPoint( p1 );
planarSubdivisionPolygon->AddControlPoint( p2 );
planarSubdivisionPolygon->AddControlPoint( p3 );
planarSubdivisionPolygon->GetPropertyList()->SetBoolProperty( "initiallyplaced", true );
planarFigures.push_back( planarSubdivisionPolygon.GetPointer() );
// Create PlanarRectangle
mitk::PlanarRectangle::Pointer planarRectangle = mitk::PlanarRectangle::New();
- planarRectangle->SetGeometry2D( planeGeometry );
+ planarRectangle->SetPlaneGeometry( planeGeometry );
planarRectangle->PlaceFigure( p0 );
planarRectangle->SetCurrentControlPoint( p1 );
planarRectangle->GetPropertyList()->SetBoolProperty( "initiallyplaced", true );
planarFigures.push_back( planarRectangle.GetPointer() );
//create preciseGeometry which is using float coordinates
mitk::PlaneGeometry::Pointer preciseGeometry = mitk::PlaneGeometry::New();
mitk::Vector3D right;
right[0] = 0.0;
right[1] = 1.23456;
right[2] = 0.0;
mitk::Vector3D down;
down[0] = 1.23456;
down[1] = 0.0;
down[2] = 0.0;
mitk::Vector3D spacing;
spacing[0] = 0.0123456;
spacing[1] = 0.0123456;
spacing[2] = 1.123456;
preciseGeometry->InitializeStandardPlane( right, down, &spacing );
//convert points into the precise coordinates
mitk::Point2D p0precise; p0precise[0] = p0[0] * spacing[0]; p0precise[1] = p0[1] * spacing[1];
mitk::Point2D p1precise; p1precise[0] = p1[0] * spacing[0]; p1precise[1] = p1[1] * spacing[1];
mitk::Point2D p2precise; p2precise[0] = p2[0] * spacing[0]; p2precise[1] = p2[1] * spacing[1];
mitk::Point2D p3precise; p3precise[0] = p3[0] * spacing[0]; p3precise[1] = p3[1] * spacing[1];
//Now all PlanarFigures are create using the precise Geometry
// Create PlanarCross
mitk::PlanarCross::Pointer nochncross = mitk::PlanarCross::New();
nochncross->SetSingleLineMode( false );
- nochncross->SetGeometry2D( preciseGeometry );
+ nochncross->SetPlaneGeometry( preciseGeometry );
nochncross->PlaceFigure( p0precise );
nochncross->SetCurrentControlPoint( p1precise );
nochncross->AddControlPoint( p2precise );
nochncross->AddControlPoint( p3precise );
nochncross->GetPropertyList()->SetBoolProperty( "initiallyplaced", true );
planarFigures.push_back( nochncross.GetPointer() );
// Create PlanarAngle
mitk::PlanarAngle::Pointer planarAnglePrecise = mitk::PlanarAngle::New();
- planarAnglePrecise->SetGeometry2D( preciseGeometry );
+ planarAnglePrecise->SetPlaneGeometry( preciseGeometry );
planarAnglePrecise->PlaceFigure( p0precise );
planarAnglePrecise->SetCurrentControlPoint( p1precise );
planarAnglePrecise->AddControlPoint( p2precise );
planarAnglePrecise->GetPropertyList()->SetBoolProperty( "initiallyplaced", true );
planarFigures.push_back( planarAnglePrecise.GetPointer() );
// Create PlanarCircle
mitk::PlanarCircle::Pointer planarCirclePrecise = mitk::PlanarCircle::New();
- planarCirclePrecise->SetGeometry2D( preciseGeometry );
+ planarCirclePrecise->SetPlaneGeometry( preciseGeometry );
planarCirclePrecise->PlaceFigure( p0precise );
planarCirclePrecise->SetCurrentControlPoint( p1precise );
planarCirclePrecise->GetPropertyList()->SetBoolProperty( "initiallyplaced", true );
planarFigures.push_back( planarCirclePrecise.GetPointer() );
// Create PlanarFourPointAngle
mitk::PlanarFourPointAngle::Pointer planarFourPointAnglePrecise = mitk::PlanarFourPointAngle::New();
- planarFourPointAnglePrecise->SetGeometry2D( preciseGeometry );
+ planarFourPointAnglePrecise->SetPlaneGeometry( preciseGeometry );
planarFourPointAnglePrecise->PlaceFigure( p0precise );
planarFourPointAnglePrecise->SetCurrentControlPoint( p1precise );
planarFourPointAnglePrecise->AddControlPoint( p2precise );
planarFourPointAnglePrecise->AddControlPoint( p3precise );
planarFourPointAnglePrecise->GetPropertyList()->SetBoolProperty( "initiallyplaced", true );
planarFigures.push_back( planarFourPointAnglePrecise.GetPointer() );
// Create PlanarLine
mitk::PlanarLine::Pointer planarLinePrecise = mitk::PlanarLine::New();
- planarLinePrecise->SetGeometry2D( preciseGeometry );
+ planarLinePrecise->SetPlaneGeometry( preciseGeometry );
planarLinePrecise->PlaceFigure( p0precise );
planarLinePrecise->SetCurrentControlPoint( p1precise );
planarLinePrecise->GetPropertyList()->SetBoolProperty( "initiallyplaced", true );
planarFigures.push_back( planarLinePrecise.GetPointer() );
// Create PlanarPolygon
mitk::PlanarPolygon::Pointer planarPolygonPrecise = mitk::PlanarPolygon::New();
planarPolygonPrecise->SetClosed( false );
- planarPolygonPrecise->SetGeometry2D( preciseGeometry );
+ planarPolygonPrecise->SetPlaneGeometry( preciseGeometry );
planarPolygonPrecise->PlaceFigure( p0precise );
planarPolygonPrecise->SetCurrentControlPoint( p1precise );
planarPolygonPrecise->AddControlPoint( p2precise );
planarPolygonPrecise->AddControlPoint( p3precise );
planarPolygonPrecise->GetPropertyList()->SetBoolProperty( "initiallyplaced", true );
planarFigures.push_back( planarPolygonPrecise.GetPointer() );
// Create PlanarSubdivisionPolygon
mitk::PlanarSubdivisionPolygon::Pointer planarSubdivisionPolygonPrecise = mitk::PlanarSubdivisionPolygon::New();
planarSubdivisionPolygonPrecise->SetClosed( false );
- planarSubdivisionPolygonPrecise->SetGeometry2D( preciseGeometry );
+ planarSubdivisionPolygonPrecise->SetPlaneGeometry( preciseGeometry );
planarSubdivisionPolygonPrecise->PlaceFigure( p0precise );
planarSubdivisionPolygonPrecise->SetCurrentControlPoint( p1precise );
planarSubdivisionPolygonPrecise->AddControlPoint( p2precise );
planarSubdivisionPolygonPrecise->AddControlPoint( p3precise );
planarSubdivisionPolygonPrecise->GetPropertyList()->SetBoolProperty( "initiallyplaced", true );
planarFigures.push_back( planarSubdivisionPolygonPrecise.GetPointer() );
// Create PlanarRectangle
mitk::PlanarRectangle::Pointer planarRectanglePrecise = mitk::PlanarRectangle::New();
- planarRectanglePrecise->SetGeometry2D( preciseGeometry );
+ planarRectanglePrecise->SetPlaneGeometry( preciseGeometry );
planarRectanglePrecise->PlaceFigure( p0precise );
planarRectanglePrecise->SetCurrentControlPoint( p1precise );
planarRectanglePrecise->GetPropertyList()->SetBoolProperty( "initiallyplaced", true );
planarFigures.push_back( planarRectanglePrecise.GetPointer() );
return planarFigures;
}
static PlanarFigureList CreateDeepCopiedPlanarFigures(PlanarFigureList original)
{
PlanarFigureList copiedPlanarFigures;
PlanarFigureList::iterator it1;
for ( it1 = original.begin(); it1 != original.end(); ++it1 )
{
mitk::PlanarFigure::Pointer copiedFigure = (*it1)->Clone();
copiedPlanarFigures.push_back(copiedFigure);
}
return copiedPlanarFigures;
}
static PlanarFigureList CreateClonedPlanarFigures(PlanarFigureList original)
{
PlanarFigureList clonedPlanarFigures;
clonedPlanarFigures.resize(original.size());
std::transform(original.begin(), original.end(), clonedPlanarFigures.begin(), Clone);
return clonedPlanarFigures;
}
static void VerifyPlanarFigures( PlanarFigureList &planarFigures1, PlanarFigureList &planarFigures2 )
{
PlanarFigureList::iterator it1, it2;
int i = 0;
for ( it1 = planarFigures1.begin(); it1 != planarFigures1.end(); ++it1 )
{
bool planarFigureFound = false;
int j = 0;
for ( it2 = planarFigures2.begin(); it2 != planarFigures2.end(); ++it2 )
{
// Compare PlanarFigures (returns false if different types)
if ( ComparePlanarFigures( *it1, *it2 ) )
{
planarFigureFound = true;
}
++j;
}
// Test if (at least) on PlanarFigure of the first type was found in the second list
MITK_TEST_CONDITION_REQUIRED(
planarFigureFound,
"Testing if " << (*it1)->GetNameOfClass() << " has a counterpart " << i );
++i;
}
}
static bool ComparePlanarFigures( mitk::PlanarFigure* figure1, mitk::PlanarFigure* figure2 )
{
// Test if PlanarFigures are of same type; otherwise return
if ( strcmp( figure1->GetNameOfClass(), figure2->GetNameOfClass() ) != 0 )
{
return false;
}
if( strcmp( figure1->GetNameOfClass(), "PlanarCross" ) == 0 )
{
std::cout << "Planar Cross Found" << std::endl;
}
// Test for equal number of control points
if(figure1->GetNumberOfControlPoints() != figure2->GetNumberOfControlPoints())
{
return false;
}
// Test if all control points are equal
for ( unsigned int i = 0; i < figure1->GetNumberOfControlPoints(); ++i )
{
mitk::Point2D point1 = figure1->GetControlPoint( i );
mitk::Point2D point2 = figure2->GetControlPoint( i );
if(point1.EuclideanDistanceTo( point2 ) >= mitk::eps)
{
return false;
}
}
// Test for equal number of properties
typedef mitk::PropertyList::PropertyMap PropertyMap;
const PropertyMap* properties1 = figure1->GetPropertyList()->GetMap();
const PropertyMap* properties2 = figure2->GetPropertyList()->GetMap();
if(properties1->size() != properties2->size())
{
return false;
}
MITK_INFO << "List 1:";
for (PropertyMap::const_iterator i1 = properties1->begin(); i1 != properties1->end(); ++i1)
{
std::cout << i1->first << std::endl;
}
MITK_INFO << "List 2:";
for (PropertyMap::const_iterator i2 = properties2->begin(); i2 != properties2->end(); ++i2)
{
std::cout << i2->first << std::endl;
}
MITK_INFO << "-------";
// Test if all properties are equal
if(!std::equal( properties1->begin(), properties1->end(), properties2->begin(), PropertyMapEntryCompare() ))
{
return false;
}
// Test if Geometry is equal
- const mitk::PlaneGeometry* planeGeometry1 = dynamic_cast<const mitk::PlaneGeometry*>(figure1->GetGeometry2D());
- const mitk::PlaneGeometry* planeGeometry2 = dynamic_cast<const mitk::PlaneGeometry*>(figure2->GetGeometry2D());
+ const mitk::PlaneGeometry* planeGeometry1 = dynamic_cast<const mitk::PlaneGeometry*>(figure1->GetPlaneGeometry());
+ const mitk::PlaneGeometry* planeGeometry2 = dynamic_cast<const mitk::PlaneGeometry*>(figure2->GetPlaneGeometry());
// Test Geometry transform parameters
typedef mitk::Geometry3D::TransformType TransformType;
const TransformType* affineGeometry1 = planeGeometry1->GetIndexToWorldTransform();
const TransformType::ParametersType& parameters1 = affineGeometry1->GetParameters();
const TransformType::ParametersType& parameters2 = planeGeometry2->GetIndexToWorldTransform()->GetParameters();
for ( unsigned int i = 0; i < affineGeometry1->GetNumberOfParameters(); ++i )
{
if ( fabs(parameters1.GetElement( i ) - parameters2.GetElement( i )) >= mitk::eps )
{
return false;
}
}
// Test Geometry bounds
typedef mitk::Geometry3D::BoundsArrayType BoundsArrayType;
const BoundsArrayType& bounds1 = planeGeometry1->GetBounds();
const BoundsArrayType& bounds2 = planeGeometry2->GetBounds();
for ( unsigned int i = 0; i < 6; ++i )
{
if ( fabs(bounds1.GetElement( i ) - bounds2.GetElement( i )) >= mitk::eps )
{
return false;
};
}
// Test Geometry spacing and origin
mitk::Vector3D spacing1 = planeGeometry1->GetSpacing();
mitk::Vector3D spacing2 = planeGeometry2->GetSpacing();
if((spacing1 - spacing2).GetNorm() >= mitk::eps)
{
return false;
}
mitk::Point3D origin1 = planeGeometry1->GetOrigin();
mitk::Point3D origin2 = planeGeometry2->GetOrigin();
if(origin1.EuclideanDistanceTo( origin2 ) >= mitk::eps)
{
return false;
}
return true;
}
static void SerializePlanarFigures( PlanarFigureList &planarFigures, std::string& fileName )
{
//std::string sceneFileName = Poco::Path::temp() + /*Poco::Path::separator() +*/ "scene.zip";
std::cout << "File name: " << fileName << std::endl;
mitk::PlanarFigureWriter::Pointer writer = mitk::PlanarFigureWriter::New();
writer->SetFileName( fileName.c_str() );
unsigned int i;
PlanarFigureList::iterator it;
for ( it = planarFigures.begin(), i = 0;
it != planarFigures.end();
++it, ++i )
{
writer->SetInput( i, *it );
}
writer->Update();
MITK_TEST_CONDITION_REQUIRED(
writer->GetSuccess(),
"Testing if writing was successful");
}
static PlanarFigureList DeserializePlanarFigures( std::string& fileName)
{
// Read in the planar figures
mitk::PlanarFigureReader::Pointer reader = mitk::PlanarFigureReader::New();
reader->SetFileName( fileName.c_str() );
reader->Update();
MITK_TEST_CONDITION_REQUIRED(
reader->GetSuccess(),
"Testing if reading was successful");
// Store them in the list and return it
PlanarFigureList planarFigures;
for ( unsigned int i = 0; i < reader->GetNumberOfOutputs(); ++i )
{
mitk::PlanarFigure* figure = reader->GetOutput( i );
planarFigures.push_back( figure );
}
return planarFigures;
}
static PlanarFigureToMemoryWriterList SerializePlanarFiguresToMemoryBuffers( PlanarFigureList &planarFigures )
{
PlanarFigureToMemoryWriterList pfMemoryWriters;
unsigned int i;
PlanarFigureList::iterator it;
bool success = true;
for ( it = planarFigures.begin(), i = 0;
it != planarFigures.end();
++it, ++i )
{
mitk::PlanarFigureWriter::Pointer writer = mitk::PlanarFigureWriter::New();
writer->SetWriteToMemory( true );
writer->SetInput( *it );
writer->Update();
pfMemoryWriters.push_back(writer);
if(!writer->GetSuccess())
success = false;
}
MITK_TEST_CONDITION_REQUIRED(success, "Testing if writing to memory buffers was successful");
return pfMemoryWriters;
}
static PlanarFigureList DeserializePlanarFiguresFromMemoryBuffers( PlanarFigureToMemoryWriterList pfMemoryWriters)
{
// Store them in the list and return it
PlanarFigureList planarFigures;
bool success = true;
for ( unsigned int i = 0; i < pfMemoryWriters.size(); ++i )
{
// Read in the planar figures
mitk::PlanarFigureReader::Pointer reader = mitk::PlanarFigureReader::New();
reader->SetReadFromMemory( true );
reader->SetMemoryBuffer(pfMemoryWriters[i]->GetMemoryPointer(), pfMemoryWriters[i]->GetMemorySize());
reader->Update();
mitk::PlanarFigure* figure = reader->GetOutput( 0 );
planarFigures.push_back( figure );
if(!reader->GetSuccess())
success = false;
}
MITK_TEST_CONDITION_REQUIRED(success, "Testing if reading was successful");
return planarFigures;
}
private:
class PropertyMapEntryCompare
{
public:
bool operator()(
const mitk::PropertyList::PropertyMap::value_type &entry1,
const mitk::PropertyList::PropertyMap::value_type &entry2 )
{
MITK_INFO << "Comparing " << entry1.first << "(" << entry1.second->GetValueAsString() << ") and " << entry2.first << "(" << entry2.second->GetValueAsString() << ")";
// Compare property objects contained in the map entries (see mitk::PropertyList)
return *(entry1.second) == *(entry2.second);
}
};
}; // end test helper class
/** \brief Test for PlanarFigure reader and writer classes.
*
* The test works as follows:
*
* First, a number of PlanarFigure objects of different types are created and placed with
* various control points. These objects are the serialized to file, read again from file, and
* the retrieved objects are compared with their control points, properties, and geometry
* information to the original PlanarFigure objects.
*/
int mitkPlanarFigureIOTest(int /* argc */, char* /*argv*/[])
{
MITK_TEST_BEGIN("PlanarFigureIO");
// Create a number of PlanarFigure objects
PlanarFigureIOTestClass::PlanarFigureList originalPlanarFigures =
PlanarFigureIOTestClass::CreatePlanarFigures();
// Create a number of "deep-copied" planar figures to test the DeepCopy function (deprecated)
PlanarFigureIOTestClass::PlanarFigureList copiedPlanarFigures =
PlanarFigureIOTestClass::CreateDeepCopiedPlanarFigures(originalPlanarFigures);
PlanarFigureIOTestClass::VerifyPlanarFigures(originalPlanarFigures, copiedPlanarFigures );
// Create a number of cloned planar figures to test the Clone function
PlanarFigureIOTestClass::PlanarFigureList clonedPlanarFigures =
PlanarFigureIOTestClass::CreateClonedPlanarFigures(originalPlanarFigures);
PlanarFigureIOTestClass::VerifyPlanarFigures(originalPlanarFigures, clonedPlanarFigures );
// Write PlanarFigure objects into temp file
// tmpname
static unsigned long count = 0;
unsigned long n = count++;
std::ostringstream name;
for (int i = 0; i < 6; ++i)
{
name << char('a' + (n % 26));
n /= 26;
}
std::string myname;
myname.append(name.str());
std::string fileName = itksys::SystemTools::GetCurrentWorkingDirectory() + myname + ".pf";
PlanarFigureIOTestClass::SerializePlanarFigures( originalPlanarFigures, fileName );
// Write PlanarFigure objects to memory buffers
PlanarFigureIOTestClass::PlanarFigureToMemoryWriterList writersWithMemoryBuffers =
PlanarFigureIOTestClass::SerializePlanarFiguresToMemoryBuffers( originalPlanarFigures );
// Read PlanarFigure objects from temp file
PlanarFigureIOTestClass::PlanarFigureList retrievedPlanarFigures =
PlanarFigureIOTestClass::DeserializePlanarFigures( fileName );
// Read PlanarFigure objects from memory buffers
PlanarFigureIOTestClass::PlanarFigureList retrievedPlanarFiguresFromMemory =
PlanarFigureIOTestClass::DeserializePlanarFiguresFromMemoryBuffers( writersWithMemoryBuffers );
PlanarFigureIOTestClass::PlanarFigureToMemoryWriterList::iterator it = writersWithMemoryBuffers.begin();
while(it != writersWithMemoryBuffers.end())
{
(*it)->ReleaseMemory();
++it;
}
// Test if original and retrieved PlanarFigure objects are the same
PlanarFigureIOTestClass::VerifyPlanarFigures( originalPlanarFigures, retrievedPlanarFigures );
// Test if original and memory retrieved PlanarFigure objects are the same
PlanarFigureIOTestClass::VerifyPlanarFigures( originalPlanarFigures, retrievedPlanarFiguresFromMemory );
//empty the originalPlanarFigures
originalPlanarFigures.empty();
// Test if deep-copied and retrieved PlanarFigure objects are the same
PlanarFigureIOTestClass::VerifyPlanarFigures( copiedPlanarFigures, retrievedPlanarFigures );
MITK_TEST_END()
}
diff --git a/Modules/PlanarFigure/Testing/mitkPlanarPolygonTest.cpp b/Modules/PlanarFigure/Testing/mitkPlanarPolygonTest.cpp
index 3515933f39..4c08fd47ec 100644
--- a/Modules/PlanarFigure/Testing/mitkPlanarPolygonTest.cpp
+++ b/Modules/PlanarFigure/Testing/mitkPlanarPolygonTest.cpp
@@ -1,151 +1,151 @@
/*===================================================================
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 "mitkTestingMacros.h"
#include "mitkPlanarPolygon.h"
#include "mitkPlaneGeometry.h"
class mitkPlanarPolygonTestClass
{
public:
static void TestPlanarPolygonPlacement( mitk::PlanarPolygon::Pointer planarPolygon )
{
// Test for correct minimum number of control points in cross-mode
MITK_TEST_CONDITION( planarPolygon->GetMinimumNumberOfControlPoints() == 3, "Minimum number of control points" );
// Test for correct maximum number of control points in cross-mode
MITK_TEST_CONDITION( planarPolygon->GetMaximumNumberOfControlPoints() == 1000, "Maximum number of control points" );
// Initial placement of PlanarPolygon
mitk::Point2D p0;
p0[0] = 00.0; p0[1] = 0.0;
planarPolygon->PlaceFigure( p0 );
// Add second control point
mitk::Point2D p1;
p1[0] = 50.0; p1[1] = 00.0;
planarPolygon->SetControlPoint(1, p1 );
// Add third control point
mitk::Point2D p2;
p2[0] = 50.0; p2[1] = 50.0;
planarPolygon->AddControlPoint( p2 );
// Add fourth control point
mitk::Point2D p3;
p3[0] = 0.0; p3[1] = 50.0;
planarPolygon->AddControlPoint( p3 );
// Test for number of control points
MITK_TEST_CONDITION( planarPolygon->GetNumberOfControlPoints() == 4, "Number of control points after placement" );
// Test if PlanarFigure is closed
MITK_TEST_CONDITION( planarPolygon->IsClosed(), "planar polygon should not be closed, yet, right?" );
planarPolygon->SetClosed(true);
MITK_TEST_CONDITION( planarPolygon->IsClosed(), "planar polygon should be closed after function call, right?" );
// Test for number of polylines
const mitk::PlanarFigure::PolyLineType polyLine0 = planarPolygon->GetPolyLine( 0 );
mitk::PlanarFigure::PolyLineType::const_iterator iter = polyLine0.begin();
MITK_TEST_CONDITION( planarPolygon->GetPolyLinesSize() == 1, "Number of polylines after placement" );
// Get polylines and check if the generated coordinates are OK
const mitk::Point2D& pp0 = *iter;
++iter;
const mitk::Point2D& pp1 = *iter;
MITK_TEST_CONDITION( ((pp0 == p0) && (pp1 == p1))
|| ((pp0 == p1) && (pp1 == p0)), "Correct polyline 1" );
// Test for number of measurement features
planarPolygon->EvaluateFeatures();
MITK_TEST_CONDITION( planarPolygon->GetNumberOfFeatures() == 2, "Number of measurement features" );
// Test for correct feature evaluation
double length0 = 4 * 50.0; // circumference
MITK_TEST_CONDITION( fabs( planarPolygon->GetQuantity( 0 ) - length0) < mitk::eps, "Size of longest diameter" );
double length1 = 50.0 * 50.0 ; // area
MITK_TEST_CONDITION( fabs( planarPolygon->GetQuantity( 1 ) - length1) < mitk::eps, "Size of short axis diameter" );
}
static void TestPlanarPolygonEditing( mitk::PlanarPolygon::Pointer planarPolygon )
{
unsigned int initialNumberOfControlPoints = planarPolygon->GetNumberOfControlPoints();
mitk::Point2D pnt;
pnt[0] = 75.0; pnt[1] = 25.0;
planarPolygon->AddControlPoint( pnt);
MITK_TEST_CONDITION( planarPolygon->GetNumberOfControlPoints() == initialNumberOfControlPoints+1, "A new control-point shall be added" );
MITK_TEST_CONDITION( planarPolygon->GetControlPoint( planarPolygon->GetNumberOfControlPoints()-1 ) == pnt, "Control-point shall be added at the end." );
planarPolygon->RemoveControlPoint( 3 );
MITK_TEST_CONDITION( planarPolygon->GetNumberOfControlPoints() == initialNumberOfControlPoints, "A control-point has been removed" );
MITK_TEST_CONDITION( planarPolygon->GetControlPoint( 3 ) == pnt, "It shall be possible to remove any control-point." );
planarPolygon->RemoveControlPoint( 0 );
planarPolygon->RemoveControlPoint( 0 );
planarPolygon->RemoveControlPoint( 0 );
MITK_TEST_CONDITION( planarPolygon->GetNumberOfControlPoints() == 3, "Control-points cannot be removed if only three points remain." );
mitk::Point2D pnt1;
pnt1[0] = 33.0; pnt1[1] = 33.0;
planarPolygon->AddControlPoint( pnt1, 0 );
MITK_TEST_CONDITION( planarPolygon->GetNumberOfControlPoints() == 4, "A control-point has been added" );
MITK_TEST_CONDITION( planarPolygon->GetControlPoint( 0 ) == pnt1, "It shall be possible to insert a control-point at any position." );
}
};
/**
* mitkplanarPolygonTest tests the methods and behavior of mitk::PlanarPolygon with sub-tests:
*
* 1. Instantiation and basic tests, including feature evaluation
*
*/
int mitkPlanarPolygonTest(int /* argc */, char* /*argv*/[])
{
// always start with this!
MITK_TEST_BEGIN("planarPolygon")
// create PlaneGeometry on which to place the planarPolygon
mitk::PlaneGeometry::Pointer planeGeometry = mitk::PlaneGeometry::New();
planeGeometry->InitializeStandardPlane( 100.0, 100.0 );
// **************************************************************************
// 1. Instantiation and basic tests, including feature evaluation
mitk::PlanarPolygon::Pointer planarPolygon = mitk::PlanarPolygon::New();
- planarPolygon->SetGeometry2D( planeGeometry );
+ planarPolygon->SetPlaneGeometry( planeGeometry );
// first test: did this work?
MITK_TEST_CONDITION_REQUIRED( planarPolygon.IsNotNull(), "Testing instantiation" );
// Test placement of planarPolygon by control points
mitkPlanarPolygonTestClass::TestPlanarPolygonPlacement( planarPolygon );
mitkPlanarPolygonTestClass::TestPlanarPolygonEditing( planarPolygon );
// always end with this!
MITK_TEST_END();
}
diff --git a/Modules/PlanarFigure/Testing/mitkPlanarSubdivisionPolygonTest.cpp b/Modules/PlanarFigure/Testing/mitkPlanarSubdivisionPolygonTest.cpp
index 5c14e89c3e..8d1990729c 100644
--- a/Modules/PlanarFigure/Testing/mitkPlanarSubdivisionPolygonTest.cpp
+++ b/Modules/PlanarFigure/Testing/mitkPlanarSubdivisionPolygonTest.cpp
@@ -1,195 +1,195 @@
/*===================================================================
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 "mitkTestingMacros.h"
#include "mitkPlanarSubdivisionPolygon.h"
#include "mitkPlaneGeometry.h"
#include "mitkProperties.h"
class mitkPlanarSubdivisionPolygonTestClass
{
public:
static void TestPlanarSubdivisionPolygonPlacement( mitk::PlanarSubdivisionPolygon::Pointer planarSubdivisionPolygon )
{
// Test for correct minimum number of control points in cross-mode
MITK_TEST_CONDITION( planarSubdivisionPolygon->GetMinimumNumberOfControlPoints() == 3, "Minimum number of control points" );
// Test for correct maximum number of control points in cross-mode
MITK_TEST_CONDITION( planarSubdivisionPolygon->GetMaximumNumberOfControlPoints() == 1000, "Maximum number of control points" );
// Test for correct rounds of subdivisionPoints
MITK_TEST_CONDITION( planarSubdivisionPolygon->GetSubdivisionRounds() == 5, "Subdivision point generation depth" );
// Test for correct tension parameter
MITK_TEST_CONDITION( planarSubdivisionPolygon->GetTensionParameter() == 0.0625, "Tension parameter" );
planarSubdivisionPolygon->SetProperty( "initiallyplaced", mitk::BoolProperty::New( true ) );
// Initial placement of planarSubdivisionPolygon
mitk::Point2D p0;
p0[0] = 25.0; p0[1] = 25.0;
planarSubdivisionPolygon->PlaceFigure( p0 );
// Add second control point
mitk::Point2D p1;
p1[0] = 75.0; p1[1] = 25.0;
planarSubdivisionPolygon->SetControlPoint(1, p1 );
// Add third control point
mitk::Point2D p2;
p2[0] = 75.0; p2[1] = 75.0;
planarSubdivisionPolygon->AddControlPoint( p2 );
// Add fourth control point
mitk::Point2D p3;
p3[0] = 25.0; p3[1] = 75.0;
planarSubdivisionPolygon->AddControlPoint( p3 );
// Test for number of control points
MITK_TEST_CONDITION( planarSubdivisionPolygon->GetNumberOfControlPoints() == 4, "Number of control points after placement" );
// Test if PlanarFigure is closed
MITK_TEST_CONDITION( planarSubdivisionPolygon->IsClosed(), "Test if property 'closed' is set by default" );
// Test for number of polylines
const mitk::PlanarFigure::PolyLineType polyLine0 = planarSubdivisionPolygon->GetPolyLine( 0 );
mitk::PlanarFigure::PolyLineType::const_iterator iter = polyLine0.begin();
MITK_TEST_CONDITION( planarSubdivisionPolygon->GetPolyLinesSize() == 1, "Number of polylines after placement" );
// Test if subdivision point count is correct
MITK_TEST_CONDITION( polyLine0.size() == 128, "correct number of subdivision points for this depth level" );
// Test if control points are in correct order between subdivision points
bool correctPoint = true;
iter = polyLine0.begin();
if( static_cast<mitk::Point2D>(*iter) != p0 ){ correctPoint = false; }
advance(iter, 32);
if( static_cast<mitk::Point2D>(*iter) != p1 ){ correctPoint = false; }
advance(iter, 32);
if( static_cast<mitk::Point2D>(*iter) != p2 ){ correctPoint = false; }
advance(iter, 32);
if( static_cast<mitk::Point2D>(*iter) != p3 ){ correctPoint = false; }
MITK_TEST_CONDITION( correctPoint, "Test if control points are in correct order in polyline" );
// Test if a picked point has the correct coordinates
correctPoint = true;
mitk::Point2D testPoint;
testPoint[0] = 81.25;
testPoint[1] = 48.243;
iter = polyLine0.begin();
advance(iter, 47);
mitk::ScalarType testEps = 1E-5;
if( (static_cast<mitk::Point2D>(*iter)[0] - testPoint[0]) + (static_cast<mitk::Point2D>(*iter)[1] - testPoint[1]) > testEps ){ correctPoint = false; }
testPoint[0] = 39.624;
testPoint[1] = 19.3268;
iter = polyLine0.begin();
advance(iter, 10);
if( (static_cast<mitk::Point2D>(*iter)[0] - testPoint[0]) + (static_cast<mitk::Point2D>(*iter)[1] - testPoint[1]) > testEps ){ correctPoint = false; }
testPoint[0] = 71.2887;
testPoint[1] = 77.5248;
iter = polyLine0.begin();
advance(iter, 67);
if( (static_cast<mitk::Point2D>(*iter)[0] - testPoint[0]) + (static_cast<mitk::Point2D>(*iter)[1] - testPoint[1]) > testEps ){ correctPoint = false; }
MITK_TEST_CONDITION( correctPoint, "Test if subdivision points are calculated correctly" )
// Test for number of measurement features
/*
Does not work yet
planarSubdivisionPolygon->EvaluateFeatures();
MITK_TEST_CONDITION( planarSubdivisionPolygon->GetNumberOfFeatures() == 2, "Number of measurement features" );
// Test for correct feature evaluation
double length0 = 4 * 50.0; // circumference
MITK_TEST_CONDITION( fabs( planarSubdivisionPolygon->GetQuantity( 0 ) - length0) < mitk::eps, "Size of longest diameter" );
double length1 = 50.0 * 50.0 ; // area
MITK_TEST_CONDITION( fabs( planarSubdivisionPolygon->GetQuantity( 1 ) - length1) < mitk::eps, "Size of short axis diameter" );
*/
}
static void TestPlanarSubdivisionPolygonEditing( mitk::PlanarSubdivisionPolygon::Pointer planarSubdivisionPolygon )
{
unsigned int initialNumberOfControlPoints = planarSubdivisionPolygon->GetNumberOfControlPoints();
mitk::Point2D pnt;
pnt[0] = 75.0; pnt[1] = 25.0;
planarSubdivisionPolygon->AddControlPoint( pnt);
MITK_TEST_CONDITION( planarSubdivisionPolygon->GetNumberOfControlPoints() == initialNumberOfControlPoints+1, "A new control-point shall be added" );
MITK_TEST_CONDITION( planarSubdivisionPolygon->GetControlPoint( planarSubdivisionPolygon->GetNumberOfControlPoints()-1 ) == pnt, "Control-point shall be added at the end." );
planarSubdivisionPolygon->RemoveControlPoint( 3 );
MITK_TEST_CONDITION( planarSubdivisionPolygon->GetNumberOfControlPoints() == initialNumberOfControlPoints, "A control-point has been removed" );
MITK_TEST_CONDITION( planarSubdivisionPolygon->GetControlPoint( 3 ) == pnt, "It shall be possible to remove any control-point." );
planarSubdivisionPolygon->RemoveControlPoint( 0 );
planarSubdivisionPolygon->RemoveControlPoint( 0 );
planarSubdivisionPolygon->RemoveControlPoint( 0 );
MITK_TEST_CONDITION( planarSubdivisionPolygon->GetNumberOfControlPoints() == 3, "Control-points cannot be removed if only three points remain." );
mitk::Point2D pnt1;
pnt1[0] = 33.0; pnt1[1] = 33.0;
planarSubdivisionPolygon->AddControlPoint( pnt1, 0 );
MITK_TEST_CONDITION( planarSubdivisionPolygon->GetNumberOfControlPoints() == 4, "A control-point has been added" );
MITK_TEST_CONDITION( planarSubdivisionPolygon->GetControlPoint( 0 ) == pnt1, "It shall be possible to insert a control-point at any position." );
}
};
/**
* mitkplanarSubdivisionPolygonTest tests the methods and behavior of mitk::planarSubdivisionPolygon with sub-tests:
*
* 1. Instantiation and basic tests, including feature evaluation
*
*/
int mitkPlanarSubdivisionPolygonTest(int /* argc */, char* /*argv*/[])
{
// always start with this!
MITK_TEST_BEGIN("planarSubdivisionPolygon")
// create PlaneGeometry on which to place the planarSubdivisionPolygon
mitk::PlaneGeometry::Pointer planeGeometry = mitk::PlaneGeometry::New();
planeGeometry->InitializeStandardPlane( 100.0, 100.0 );
// **************************************************************************
// 1. Instantiation and basic tests, including feature evaluation
mitk::PlanarSubdivisionPolygon::Pointer planarSubdivisionPolygon = mitk::PlanarSubdivisionPolygon::New();
- planarSubdivisionPolygon->SetGeometry2D( planeGeometry );
+ planarSubdivisionPolygon->SetPlaneGeometry( planeGeometry );
// first test: did this work?
MITK_TEST_CONDITION_REQUIRED( planarSubdivisionPolygon.IsNotNull(), "Testing instantiation" );
// Test placement of planarSubdivisionPolygon by control points
mitkPlanarSubdivisionPolygonTestClass::TestPlanarSubdivisionPolygonPlacement( planarSubdivisionPolygon );
mitkPlanarSubdivisionPolygonTestClass::TestPlanarSubdivisionPolygonEditing( planarSubdivisionPolygon );
// always end with this!
MITK_TEST_END();
}
diff --git a/Modules/PlanarFigureSegmentation/mitkPlanarFigureSegmentationController.cpp b/Modules/PlanarFigureSegmentation/mitkPlanarFigureSegmentationController.cpp
index f242d24454..d1f8f5bf40 100644
--- a/Modules/PlanarFigureSegmentation/mitkPlanarFigureSegmentationController.cpp
+++ b/Modules/PlanarFigureSegmentation/mitkPlanarFigureSegmentationController.cpp
@@ -1,312 +1,312 @@
/*===================================================================
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 "mitkPlanarFigureSegmentationController.h"
#include "mitkSurfaceToImageFilter.h"
#include <vtkPolyData.h>
#include <vtkPoints.h>
#include <vtkPolygon.h>
#include <vtkCellArray.h>
#include <vtkSmartPointer.h>
#include <vtkImageData.h>
#include "mitkImageWriter.h"
#include "mitkSurfaceVtkWriter.h"
#include "mitkImageToSurfaceFilter.h"
#include "mitkImageAccessByItk.h"
#include "mitkImageCast.h"
mitk::PlanarFigureSegmentationController::PlanarFigureSegmentationController()
: itk::Object()
, m_ReduceFilter( NULL )
, m_NormalsFilter( NULL )
, m_DistanceImageCreator( NULL )
, m_ReferenceImage( NULL )
, m_SegmentationAsImage( NULL )
{
InitializeFilters();
}
mitk::PlanarFigureSegmentationController::~PlanarFigureSegmentationController()
{
}
void mitk::PlanarFigureSegmentationController::SetReferenceImage( mitk::Image::Pointer referenceImage )
{
m_ReferenceImage = referenceImage;
}
void mitk::PlanarFigureSegmentationController::AddPlanarFigure( mitk::PlanarFigure::Pointer planarFigure )
{
if ( planarFigure.IsNull() )
return;
bool newFigure = true;
std::size_t indexOfFigure = 0;
for( std::size_t i=0; i<m_PlanarFigureList.size(); i++ )
{
if( m_PlanarFigureList.at(i) == planarFigure )
{
indexOfFigure = i;
newFigure = false;
break;
}
}
mitk::Surface::Pointer figureAsSurface = NULL;
if ( newFigure )
{
m_PlanarFigureList.push_back( planarFigure );
figureAsSurface = this->CreateSurfaceFromPlanarFigure( planarFigure );
m_SurfaceList.push_back( figureAsSurface );
if (!m_PlanarFigureList.empty())
{
indexOfFigure = m_PlanarFigureList.size() -1 ;
}
}
else
{
figureAsSurface = this->CreateSurfaceFromPlanarFigure( planarFigure );
m_SurfaceList.at(indexOfFigure) = figureAsSurface;
}
if ( m_ReduceFilter.IsNull() )
{
InitializeFilters();
}
m_ReduceFilter->SetInput( indexOfFigure, figureAsSurface );
m_NormalsFilter->SetInput( indexOfFigure, m_ReduceFilter->GetOutput( indexOfFigure ) );
m_DistanceImageCreator->SetInput( indexOfFigure, m_NormalsFilter->GetOutput( indexOfFigure ) );
}
void mitk::PlanarFigureSegmentationController::RemovePlanarFigure( mitk::PlanarFigure::Pointer planarFigure )
{
if ( planarFigure.IsNull() )
return;
bool figureFound = false;
std::size_t indexOfFigure = 0;
for( std::size_t i=0; i<m_PlanarFigureList.size(); i++ )
{
if( m_PlanarFigureList.at(i) == planarFigure )
{
indexOfFigure = i;
figureFound = true;
break;
}
}
if ( !figureFound )
return;
// TODO: fix this! The following code had to be removed as the method
// RemoveInputs() has been removed in ITK 4
// The remaining code works correctly but is slower
if ( false && indexOfFigure == m_PlanarFigureList.size()-1 )
{
// Ff the removed figure was the last one in the list, we can simply
// remove the last input from each filter.
// m_DistanceImageCreator->RemoveInputs( m_NormalsFilter->GetOutput( indexOfFigure ) );
// m_NormalsFilter->RemoveInput( m_ReduceFilter->GetOutput( indexOfFigure ) );
// m_ReduceFilter->RemoveInput( const_cast<mitk::Surface*>(m_ReduceFilter->GetInput(indexOfFigure)) );
}
else
{
// this is not very nice! If the figure that has been removed is NOT the last
// one in the list we have to create new filters and add all remaining
// inputs again.
//
// Has to be done as the filters do not work when removing an input
// other than the last one.
// create new filters
InitializeFilters();
// and add all existing surfaces
SurfaceListType::iterator surfaceIter = m_SurfaceList.begin();
for ( surfaceIter = m_SurfaceList.begin(); surfaceIter!=m_SurfaceList.end(); surfaceIter++ )
{
m_ReduceFilter->SetInput( indexOfFigure, (*surfaceIter) );
m_NormalsFilter->SetInput( indexOfFigure, m_ReduceFilter->GetOutput( indexOfFigure ) );
m_DistanceImageCreator->SetInput( indexOfFigure, m_NormalsFilter->GetOutput( indexOfFigure ) );
}
}
PlanarFigureListType::iterator whereIter = m_PlanarFigureList.begin();
whereIter += indexOfFigure;
m_PlanarFigureList.erase( whereIter );
SurfaceListType::iterator surfaceIter = m_SurfaceList.begin();
surfaceIter += indexOfFigure;
m_SurfaceList.erase( surfaceIter );
}
template<typename TPixel, unsigned int VImageDimension>
void mitk::PlanarFigureSegmentationController::GetImageBase(itk::Image<TPixel, VImageDimension>* input, itk::ImageBase<3>::Pointer& result)
{
result = input;
}
mitk::Image::Pointer mitk::PlanarFigureSegmentationController::GetInterpolationResult()
{
m_SegmentationAsImage = NULL;
if ( m_PlanarFigureList.size() == 0 )
{
m_SegmentationAsImage = mitk::Image::New();
m_SegmentationAsImage->Initialize(mitk::MakeScalarPixelType<unsigned char>() , *m_ReferenceImage->GetTimeGeometry());
return m_SegmentationAsImage;
}
itk::ImageBase<3>::Pointer itkImage;
AccessFixedDimensionByItk_1( m_ReferenceImage.GetPointer(), GetImageBase, 3, itkImage );
m_DistanceImageCreator->SetReferenceImage( itkImage.GetPointer() );
m_ReduceFilter->Update();
m_NormalsFilter->Update();
m_DistanceImageCreator->Update();
mitk::Image::Pointer distanceImage = m_DistanceImageCreator->GetOutput();
// Cleanup the pipeline
distanceImage->DisconnectPipeline();
m_DistanceImageCreator = NULL;
m_NormalsFilter = NULL;
m_ReduceFilter = NULL;
itkImage = NULL;
// If this bool flag is true, the distanceImage will be written to the
// filesystem as nrrd-image and as surface-representation.
bool debugOutput(false);
if ( debugOutput )
{
mitk::ImageWriter::Pointer imageWriter = mitk::ImageWriter::New();
imageWriter->SetInput( distanceImage );
imageWriter->SetExtension( ".nrrd" );
imageWriter->SetFileName( "v:/DistanceImage" );
imageWriter->Update();
}
mitk::ImageToSurfaceFilter::Pointer imageToSurfaceFilter = mitk::ImageToSurfaceFilter::New();
imageToSurfaceFilter->SetInput( distanceImage );
imageToSurfaceFilter->SetThreshold( 0 );
imageToSurfaceFilter->Update();
mitk::Surface::Pointer segmentationAsSurface = imageToSurfaceFilter->GetOutput();
// Cleanup the pipeline
segmentationAsSurface->DisconnectPipeline();
imageToSurfaceFilter = NULL;
if ( debugOutput )
{
mitk::SurfaceVtkWriter<vtkPolyDataWriter>::Pointer surfaceWriter = mitk::SurfaceVtkWriter<vtkPolyDataWriter>::New();
surfaceWriter->SetInput( segmentationAsSurface );
surfaceWriter->SetExtension( ".vtk" );
surfaceWriter->SetFileName( "v:/DistanceImageAsSurface.vtk" );
surfaceWriter->Update();
}
mitk::SurfaceToImageFilter::Pointer surfaceToImageFilter = mitk::SurfaceToImageFilter::New();
surfaceToImageFilter->SetInput( segmentationAsSurface );
surfaceToImageFilter->SetImage( m_ReferenceImage );
surfaceToImageFilter->SetMakeOutputBinary(true);
surfaceToImageFilter->Update();
m_SegmentationAsImage = surfaceToImageFilter->GetOutput();
// Cleanup the pipeline
m_SegmentationAsImage->DisconnectPipeline();
return m_SegmentationAsImage;
}
mitk::Surface::Pointer mitk::PlanarFigureSegmentationController::CreateSurfaceFromPlanarFigure( mitk::PlanarFigure::Pointer figure )
{
if ( figure.IsNull() )
{
MITK_ERROR << "Given PlanarFigure is NULL. Please provide valid PlanarFigure.";
return NULL;
}
mitk::Surface::Pointer newSurface = mitk::Surface::New();
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkPolygon> polygon = vtkSmartPointer<vtkPolygon>::New();
vtkSmartPointer<vtkCellArray> cells = vtkSmartPointer<vtkCellArray>::New();
vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New();
- const mitk::Geometry2D* figureGeometry = figure->GetGeometry2D();
+ const mitk::PlaneGeometry* figureGeometry = figure->GetPlaneGeometry();
// Get the polyline
mitk::PlanarFigure::PolyLineType planarPolyLine = figure->GetPolyLine(0);
mitk::PlanarFigure::PolyLineType::iterator iter;
// iterate over the polyline, ...
int pointCounter = 0;
for( iter = planarPolyLine.begin(); iter != planarPolyLine.end(); iter++ )
{
// ... determine the world-coordinates
mitk::Point3D pointInWorldCoordiantes;
figureGeometry->Map( *iter, pointInWorldCoordiantes );
// and add them as new points to the vtkPoints
points->InsertNextPoint( pointInWorldCoordiantes[0], pointInWorldCoordiantes[1], pointInWorldCoordiantes[2] );
++pointCounter;
}
// create a polygon with the points of the polyline
polygon->GetPointIds()->SetNumberOfIds( pointCounter );
for(int i = 0; i < pointCounter; i++)
{
polygon->GetPointIds()->SetId(i,i);
}
// initialize the vtkCellArray and vtkPolyData
cells->InsertNextCell(polygon);
polyData->SetPoints(points);
polyData->SetPolys( cells );
// set the polydata to the surface
newSurface->SetVtkPolyData( polyData );
return newSurface;
}
mitk::PlanarFigureSegmentationController::PlanarFigureListType mitk::PlanarFigureSegmentationController::GetAllPlanarFigures()
{
return m_PlanarFigureList;
}
void mitk::PlanarFigureSegmentationController::InitializeFilters()
{
m_ReduceFilter = mitk::ReduceContourSetFilter::New();
m_ReduceFilter->SetReductionType(ReduceContourSetFilter::NTH_POINT);
m_ReduceFilter->SetStepSize( 10 );
m_NormalsFilter = mitk::ComputeContourSetNormalsFilter::New();
m_DistanceImageCreator = mitk::CreateDistanceImageFromSurfaceFilter::New();
}
diff --git a/Modules/QtWidgets/QmitkRenderWindowMenu.cpp b/Modules/QtWidgets/QmitkRenderWindowMenu.cpp
index 39d917aa37..ceb92c124b 100644
--- a/Modules/QtWidgets/QmitkRenderWindowMenu.cpp
+++ b/Modules/QtWidgets/QmitkRenderWindowMenu.cpp
@@ -1,1026 +1,1026 @@
/*===================================================================
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 "QmitkRenderWindowMenu.h"
#include "mitkResliceMethodProperty.h"
#include "mitkProperties.h"
#include <QHBoxLayout>
#include <QSpacerItem>
#include <QSize>
#include <QPainter>
#include<QGroupBox>
#include<QRadioButton>
#include<QAction>
#include<QLine>
#include<QLabel>
#include<QWidgetAction>
#include <QTimer>
#include "QmitkStdMultiWidget.h"
//#include"iconClose.xpm"
#include"iconFullScreen.xpm"
#include"iconCrosshairMode.xpm"
//#include"iconHoriSplit.xpm"
#include"iconSettings.xpm"
//#include"iconVertiSplit.xpm"
#include"iconLeaveFullScreen.xpm"
#include <math.h>
#ifdef QMITK_USE_EXTERNAL_RENDERWINDOW_MENU
QmitkRenderWindowMenu::QmitkRenderWindowMenu(QWidget *parent, Qt::WindowFlags f, mitk::BaseRenderer *b, QmitkStdMultiWidget* mw )
:QWidget(parent, Qt::Tool | Qt::FramelessWindowHint ),
#else
QmitkRenderWindowMenu::QmitkRenderWindowMenu(QWidget *parent, Qt::WindowFlags f, mitk::BaseRenderer *b, QmitkStdMultiWidget* mw )
:QWidget(parent,f),
#endif
m_Settings(NULL),
m_CrosshairMenu(NULL),
m_Layout(0),
m_LayoutDesign(0),
m_OldLayoutDesign(0),
m_FullScreenMode(false),
m_Entered(false),
m_Hidden(true),
m_Renderer(b),
m_MultiWidget(mw)
{
MITK_DEBUG << "creating renderwindow menu on baserenderer " << b;
//Create Menu Widget
this->CreateMenuWidget();
this->setMinimumWidth(61); //DIRTY.. If you add or remove a button, you need to change the size.
this->setMaximumWidth(61);
this->setAutoFillBackground( true );
//Else part fixes the render window menu issue on Linux bug but caused bugs on Mac OS and Windows
//for Mac OS see bug 3192
//for Windows see bug 12130
//... so Mac OS and Windows must be treated differently:
#if defined(Q_OS_MAC) || defined(_WIN32)
this->show();
this->setWindowOpacity(0.0f);
#else
this->setVisible(false);
#endif
//this->setAttribute( Qt::WA_NoSystemBackground );
//this->setBackgroundRole( QPalette::Dark );
//this->update();
//SetOpacity -- its just posible if the widget is a window.
//Windows indicates that the widget is a window, usually with a window system frame and a title bar,
//irrespective of whether the widget has a parent or not.
/*
this->setWindowFlags( Qt::Window | Qt::FramelessWindowHint);
*/
//this->setAttribute(Qt::WA_TranslucentBackground);
//this->setWindowOpacity(0.75);
currentCrosshairRotationMode = 0;
// for autorotating
m_AutoRotationTimer.setInterval( 75 );
connect( &m_AutoRotationTimer, SIGNAL(timeout()), this, SLOT(AutoRotateNextStep()) );
}
QmitkRenderWindowMenu::~QmitkRenderWindowMenu()
{
if( m_AutoRotationTimer.isActive() )
m_AutoRotationTimer.stop();
}
void QmitkRenderWindowMenu::CreateMenuWidget()
{
QHBoxLayout* layout = new QHBoxLayout(this);
layout->setAlignment( Qt::AlignRight );
layout->setContentsMargins(1,1,1,1);
QSize size( 13, 13 );
m_CrosshairMenu = new QMenu(this);
connect( m_CrosshairMenu, SIGNAL( aboutToShow() ), this, SLOT(OnCrossHairMenuAboutToShow()) );
// button for changing rotation mode
m_CrosshairModeButton = new QPushButton(this);
m_CrosshairModeButton->setMaximumSize(15, 15);
m_CrosshairModeButton->setIconSize(size);
m_CrosshairModeButton->setFlat( true );
m_CrosshairModeButton->setMenu( m_CrosshairMenu );
m_CrosshairModeButton->setIcon( QIcon( iconCrosshairMode_xpm ) );
layout->addWidget( m_CrosshairModeButton );
//fullScreenButton
m_FullScreenButton = new QPushButton(this);
m_FullScreenButton->setMaximumSize(15, 15);
m_FullScreenButton->setIconSize(size);
m_FullScreenButton->setFlat( true );
m_FullScreenButton->setIcon( QIcon( iconFullScreen_xpm ));
layout->addWidget( m_FullScreenButton );
//settingsButton
m_SettingsButton = new QPushButton(this);
m_SettingsButton->setMaximumSize(15, 15);
m_SettingsButton->setIconSize(size);
m_SettingsButton->setFlat( true );
m_SettingsButton->setIcon( QIcon( iconSettings_xpm ));
layout->addWidget( m_SettingsButton );
//Create Connections -- coming soon?
connect( m_FullScreenButton, SIGNAL( clicked(bool) ), this, SLOT(OnFullScreenButton(bool)) );
connect( m_SettingsButton, SIGNAL( clicked(bool) ), this, SLOT(OnSettingsButton(bool)) );
}
void QmitkRenderWindowMenu::CreateSettingsWidget()
{
m_Settings = new QMenu(this);
m_DefaultLayoutAction = new QAction( "standard layout", m_Settings );
m_DefaultLayoutAction->setDisabled( true );
m_2DImagesUpLayoutAction = new QAction( "2D images top, 3D bottom", m_Settings );
m_2DImagesUpLayoutAction->setDisabled( false );
m_2DImagesLeftLayoutAction = new QAction( "2D images left, 3D right", m_Settings );
m_2DImagesLeftLayoutAction->setDisabled( false );
m_Big3DLayoutAction = new QAction( "Big 3D", m_Settings );
m_Big3DLayoutAction->setDisabled( false );
m_Widget1LayoutAction = new QAction( "Axial plane", m_Settings );
m_Widget1LayoutAction->setDisabled( false );
m_Widget2LayoutAction = new QAction( "Sagittal plane", m_Settings );
m_Widget2LayoutAction->setDisabled( false );
m_Widget3LayoutAction = new QAction( "Coronal plane", m_Settings );
m_Widget3LayoutAction->setDisabled( false );
m_RowWidget3And4LayoutAction = new QAction( "Coronal top, 3D bottom", m_Settings );
m_RowWidget3And4LayoutAction->setDisabled( false );
m_ColumnWidget3And4LayoutAction = new QAction( "Coronal left, 3D right", m_Settings );
m_ColumnWidget3And4LayoutAction->setDisabled( false );
m_SmallUpperWidget2Big3and4LayoutAction = new QAction( "Sagittal top, Coronal n 3D bottom", m_Settings );
m_SmallUpperWidget2Big3and4LayoutAction->setDisabled( false );
m_2x2Dand3DWidgetLayoutAction = new QAction( "Axial n Sagittal left, 3D right", m_Settings );
m_2x2Dand3DWidgetLayoutAction->setDisabled( false );
m_Left2Dand3DRight2DLayoutAction = new QAction( "Axial n 3D left, Sagittal right", m_Settings );
m_Left2Dand3DRight2DLayoutAction->setDisabled( false );
m_Settings->addAction(m_DefaultLayoutAction);
m_Settings->addAction(m_2DImagesUpLayoutAction);
m_Settings->addAction(m_2DImagesLeftLayoutAction);
m_Settings->addAction(m_Big3DLayoutAction);
m_Settings->addAction(m_Widget1LayoutAction);
m_Settings->addAction(m_Widget2LayoutAction);
m_Settings->addAction(m_Widget3LayoutAction);
m_Settings->addAction(m_RowWidget3And4LayoutAction);
m_Settings->addAction(m_ColumnWidget3And4LayoutAction);
m_Settings->addAction(m_SmallUpperWidget2Big3and4LayoutAction);
m_Settings->addAction(m_2x2Dand3DWidgetLayoutAction);
m_Settings->addAction(m_Left2Dand3DRight2DLayoutAction);
m_Settings->setVisible( false );
connect( m_DefaultLayoutAction, SIGNAL( triggered(bool) ), this, SLOT(OnChangeLayoutToDefault(bool)) );
connect( m_2DImagesUpLayoutAction, SIGNAL( triggered(bool) ), this, SLOT(OnChangeLayoutTo2DImagesUp(bool)) );
connect( m_2DImagesLeftLayoutAction, SIGNAL( triggered(bool) ), this, SLOT(OnChangeLayoutTo2DImagesLeft(bool)) );
connect( m_Big3DLayoutAction, SIGNAL( triggered(bool) ), this, SLOT(OnChangeLayoutToBig3D(bool)) );
connect( m_Widget1LayoutAction, SIGNAL( triggered(bool) ), this, SLOT(OnChangeLayoutToWidget1(bool)) );
connect( m_Widget2LayoutAction, SIGNAL( triggered(bool) ), this, SLOT(OnChangeLayoutToWidget2(bool)) );
connect( m_Widget3LayoutAction , SIGNAL( triggered(bool) ), this, SLOT(OnChangeLayoutToWidget3(bool)) );
connect( m_RowWidget3And4LayoutAction, SIGNAL( triggered(bool) ), this, SLOT(OnChangeLayoutToRowWidget3And4(bool)) );
connect( m_ColumnWidget3And4LayoutAction, SIGNAL( triggered(bool) ), this, SLOT(OnChangeLayoutToColumnWidget3And4(bool)) );
connect( m_SmallUpperWidget2Big3and4LayoutAction, SIGNAL( triggered(bool) ), this, SLOT(OnChangeLayoutToSmallUpperWidget2Big3and4(bool)) );
connect( m_2x2Dand3DWidgetLayoutAction, SIGNAL( triggered(bool) ), this, SLOT(OnChangeLayoutTo2x2Dand3DWidget(bool)) );
connect( m_Left2Dand3DRight2DLayoutAction, SIGNAL( triggered(bool) ), this, SLOT(OnChangeLayoutToLeft2Dand3DRight2D(bool)) );
}
void QmitkRenderWindowMenu::paintEvent( QPaintEvent* /*e*/ )
{
QPainter painter(this);
QColor semiTransparentColor = Qt::black;
semiTransparentColor.setAlpha(255);
painter.fillRect(rect(), semiTransparentColor);
}
void QmitkRenderWindowMenu::SetLayoutIndex( unsigned int layoutIndex )
{
m_Layout = layoutIndex;
}
void QmitkRenderWindowMenu::HideMenu( )
{
MITK_DEBUG << "menu hideEvent";
m_Hidden = true;
if( ! m_Entered )
{
//Else part fixes the render window menu issue on Linux bug but caused bugs on Mac OS and Windows
//for Mac OS see bug 3192
//for Windows see bug 12130
//... so Mac OS and Windows must be treated differently:
#if defined(Q_OS_MAC) || defined(_WIN32)
this->setWindowOpacity(0.0f);
#else
this->setVisible(false);
#endif
}
}
void QmitkRenderWindowMenu::ShowMenu( )
{
MITK_DEBUG << "menu showMenu";
m_Hidden = false;
//Else part fixes the render window menu issue on Linux bug but caused bugs on Mac OS and Windows
//for Mac OS see bug 3192
//for Windows see bug 12130
//... so Mac OS and Windows must be treated differently:
#if defined(Q_OS_MAC) || defined(_WIN32)
this->setWindowOpacity(1.0f);
#else
this->setVisible(true);
#endif
}
void QmitkRenderWindowMenu::enterEvent( QEvent * /*e*/ )
{
MITK_DEBUG << "menu enterEvent";
m_Entered=true;
m_Hidden=false;
}
void QmitkRenderWindowMenu::DeferredHideMenu( )
{
MITK_DEBUG << "menu deferredhidemenu";
if(m_Hidden)
{
//Else part fixes the render window menu issue on Linux bug but caused bugs on Mac OS and Windows
//for Mac OS see bug 3192
//for Windows see bug 12130
//... so Mac OS and Windows must be treated differently:
#if defined(Q_OS_MAC) || defined(_WIN32)
this->setWindowOpacity(0.0f);
#else
this->setVisible(false);
#endif
}
// setVisible(false);
// setWindowOpacity(0.0f);
///hide();
}
void QmitkRenderWindowMenu::leaveEvent( QEvent * /*e*/ )
{
MITK_DEBUG << "menu leaveEvent";
smoothHide();
}
/* This method is responsible for non fluttering of
the renderWindowMenu when mouse cursor moves along the renderWindowMenu*/
void QmitkRenderWindowMenu::smoothHide()
{
MITK_DEBUG<< "menu leaveEvent";
m_Entered=false;
m_Hidden = true;
QTimer::singleShot(10,this,SLOT( DeferredHideMenu( ) ) );
}
void QmitkRenderWindowMenu::ChangeFullScreenMode( bool state )
{
this->OnFullScreenButton( state );
}
/// \brief
void QmitkRenderWindowMenu::OnFullScreenButton( bool /*checked*/ )
{
if( !m_FullScreenMode )
{
m_FullScreenMode = true;
m_OldLayoutDesign = m_LayoutDesign;
switch( m_Layout )
{
case AXIAL:
{
emit SignalChangeLayoutDesign( LAYOUT_AXIAL );
break;
}
case SAGITTAL:
{
emit SignalChangeLayoutDesign( LAYOUT_SAGITTAL );
break;
}
case CORONAL:
{
emit SignalChangeLayoutDesign( LAYOUT_CORONAL );
break;
}
case THREE_D:
{
emit SignalChangeLayoutDesign( LAYOUT_BIG3D );
break;
}
}
//Move Widget and show again
this->MoveWidgetToCorrectPos(1.0f);
//change icon
this->ChangeFullScreenIcon();
}
else
{
m_FullScreenMode = false;
emit SignalChangeLayoutDesign( m_OldLayoutDesign );
//Move Widget and show again
this->MoveWidgetToCorrectPos(1.0f);
//change icon
this->ChangeFullScreenIcon();
}
DeferredShowMenu( );
}
/// \brief
void QmitkRenderWindowMenu::OnSettingsButton( bool /*checked*/ )
{
if( m_Settings == NULL )
this->CreateSettingsWidget();
QPoint point = this->mapToGlobal( m_SettingsButton->geometry().topLeft() );
m_Settings->setVisible( true );
m_Settings->exec( point );
}
void QmitkRenderWindowMenu::OnChangeLayoutTo2DImagesUp(bool)
{
//set Full Screen Mode to false, if Layout Design was changed by the LayoutDesign_List
m_FullScreenMode = false;
this->ChangeFullScreenIcon();
m_LayoutDesign = LAYOUT_2DIMAGEUP;
emit SignalChangeLayoutDesign( LAYOUT_2DIMAGEUP );
DeferredShowMenu( );
}
void QmitkRenderWindowMenu::OnChangeLayoutTo2DImagesLeft(bool)
{
//set Full Screen Mode to false, if Layout Design was changed by the LayoutDesign_List
m_FullScreenMode = false;
this->ChangeFullScreenIcon();
m_LayoutDesign = LAYOUT_2DIMAGELEFT;
emit SignalChangeLayoutDesign( LAYOUT_2DIMAGELEFT );
DeferredShowMenu( );
}
void QmitkRenderWindowMenu::OnChangeLayoutToDefault(bool)
{
//set Full Screen Mode to false, if Layout Design was changed by the LayoutDesign_List
m_FullScreenMode = false;
this->ChangeFullScreenIcon();
m_LayoutDesign = LAYOUT_DEFAULT;
emit SignalChangeLayoutDesign( LAYOUT_DEFAULT );
DeferredShowMenu( );
}
void QmitkRenderWindowMenu::DeferredShowMenu()
{
MITK_DEBUG << "deferred show menu";
//Else part fixes the render window menu issue on Linux bug but caused bugs on Mac OS and Windows
//for Mac OS see bug 3192
//for Windows see bug 12130
//... so Mac OS and Windows must be treated differently:
#if defined(Q_OS_MAC) || defined(_WIN32)
this->setWindowOpacity(1.0f);
#else
this->setVisible(true);
#endif
}
void QmitkRenderWindowMenu::OnChangeLayoutToBig3D(bool)
{
MITK_DEBUG << "OnChangeLayoutToBig3D";
//set Full Screen Mode to false, if Layout Design was changed by the LayoutDesign_List
m_FullScreenMode = false;
this->ChangeFullScreenIcon();
m_LayoutDesign = LAYOUT_BIG3D;
emit SignalChangeLayoutDesign( LAYOUT_BIG3D );
DeferredShowMenu( );
}
void QmitkRenderWindowMenu::OnChangeLayoutToWidget1(bool)
{
//set Full Screen Mode to false, if Layout Design was changed by the LayoutDesign_List
m_FullScreenMode = false;
this->ChangeFullScreenIcon();
m_LayoutDesign = LAYOUT_AXIAL;
emit SignalChangeLayoutDesign( LAYOUT_AXIAL );
DeferredShowMenu( );
}
void QmitkRenderWindowMenu::OnChangeLayoutToWidget2(bool)
{
//set Full Screen Mode to false, if Layout Design was changed by the LayoutDesign_List
m_FullScreenMode = false;
this->ChangeFullScreenIcon();
m_LayoutDesign = LAYOUT_SAGITTAL;
emit SignalChangeLayoutDesign( LAYOUT_SAGITTAL );
DeferredShowMenu( );
}
void QmitkRenderWindowMenu::OnChangeLayoutToWidget3(bool)
{
//set Full Screen Mode to false, if Layout Design was changed by the LayoutDesign_List
m_FullScreenMode = false;
this->ChangeFullScreenIcon();
m_LayoutDesign = LAYOUT_CORONAL;
emit SignalChangeLayoutDesign( LAYOUT_CORONAL );
DeferredShowMenu( );
}
void QmitkRenderWindowMenu::OnChangeLayoutToRowWidget3And4(bool)
{
//set Full Screen Mode to false, if Layout Design was changed by the LayoutDesign_List
m_FullScreenMode = false;
this->ChangeFullScreenIcon();
m_LayoutDesign = LAYOUT_ROWWIDGET3AND4;
emit SignalChangeLayoutDesign( LAYOUT_ROWWIDGET3AND4 );
DeferredShowMenu( );
}
void QmitkRenderWindowMenu::OnChangeLayoutToColumnWidget3And4(bool)
{
//set Full Screen Mode to false, if Layout Design was changed by the LayoutDesign_List
m_FullScreenMode = false;
this->ChangeFullScreenIcon();
m_LayoutDesign = LAYOUT_COLUMNWIDGET3AND4;
emit SignalChangeLayoutDesign( LAYOUT_COLUMNWIDGET3AND4 );
DeferredShowMenu( );
}
void QmitkRenderWindowMenu::OnChangeLayoutToSmallUpperWidget2Big3and4(bool)
{
//set Full Screen Mode to false, if Layout Design was changed by the LayoutDesign_List
m_FullScreenMode = false;
this->ChangeFullScreenIcon();
m_LayoutDesign = LAYOUT_SMALLUPPERWIDGET2BIGAND4;
emit SignalChangeLayoutDesign( LAYOUT_SMALLUPPERWIDGET2BIGAND4 );
DeferredShowMenu( );
}
void QmitkRenderWindowMenu::OnChangeLayoutTo2x2Dand3DWidget(bool)
{
//set Full Screen Mode to false, if Layout Design was changed by the LayoutDesign_List
m_FullScreenMode = false;
this->ChangeFullScreenIcon();
m_LayoutDesign = LAYOUT_2X2DAND3DWIDGET;
emit SignalChangeLayoutDesign( LAYOUT_2X2DAND3DWIDGET );
DeferredShowMenu( );
}
void QmitkRenderWindowMenu::OnChangeLayoutToLeft2Dand3DRight2D(bool)
{
//set Full Screen Mode to false, if Layout Design was changed by the LayoutDesign_List
m_FullScreenMode = false;
this->ChangeFullScreenIcon();
m_LayoutDesign = LAYOUT_LEFT2DAND3DRIGHT2D;
emit SignalChangeLayoutDesign( LAYOUT_LEFT2DAND3DRIGHT2D );
DeferredShowMenu( );
}
void QmitkRenderWindowMenu::UpdateLayoutDesignList( int layoutDesignIndex )
{
m_LayoutDesign = layoutDesignIndex;
if( m_Settings == NULL )
this->CreateSettingsWidget();
switch( m_LayoutDesign )
{
case LAYOUT_DEFAULT:
{
m_DefaultLayoutAction->setEnabled(false);
m_2DImagesUpLayoutAction->setEnabled(true);
m_2DImagesLeftLayoutAction->setEnabled(true);
m_Big3DLayoutAction->setEnabled(true);
m_Widget1LayoutAction->setEnabled(true);
m_Widget2LayoutAction->setEnabled(true);
m_Widget3LayoutAction->setEnabled(true);
m_RowWidget3And4LayoutAction->setEnabled(true);
m_ColumnWidget3And4LayoutAction->setEnabled(true);
m_SmallUpperWidget2Big3and4LayoutAction->setEnabled(true);
m_2x2Dand3DWidgetLayoutAction->setEnabled(true);
m_Left2Dand3DRight2DLayoutAction->setEnabled(true);
break;
}
case LAYOUT_2DIMAGEUP:
{
m_DefaultLayoutAction->setEnabled(true);
m_2DImagesUpLayoutAction->setEnabled(false);
m_2DImagesLeftLayoutAction->setEnabled(true);
m_Big3DLayoutAction->setEnabled(true);
m_Widget1LayoutAction->setEnabled(true);
m_Widget2LayoutAction->setEnabled(true);
m_Widget3LayoutAction->setEnabled(true);
m_RowWidget3And4LayoutAction->setEnabled(true);
m_ColumnWidget3And4LayoutAction->setEnabled(true);
m_SmallUpperWidget2Big3and4LayoutAction->setEnabled(true);
m_2x2Dand3DWidgetLayoutAction->setEnabled(true);
m_Left2Dand3DRight2DLayoutAction->setEnabled(true);
break;
}
case LAYOUT_2DIMAGELEFT:
{
m_DefaultLayoutAction->setEnabled(true);
m_2DImagesUpLayoutAction->setEnabled(true);
m_2DImagesLeftLayoutAction->setEnabled(false);
m_Big3DLayoutAction->setEnabled(true);
m_Widget1LayoutAction->setEnabled(true);
m_Widget2LayoutAction->setEnabled(true);
m_Widget3LayoutAction->setEnabled(true);
m_RowWidget3And4LayoutAction->setEnabled(true);
m_ColumnWidget3And4LayoutAction->setEnabled(true);
m_SmallUpperWidget2Big3and4LayoutAction->setEnabled(true);
m_2x2Dand3DWidgetLayoutAction->setEnabled(true);
m_Left2Dand3DRight2DLayoutAction->setEnabled(true);
break;
}
case LAYOUT_BIG3D:
{
m_DefaultLayoutAction->setEnabled(true);
m_2DImagesUpLayoutAction->setEnabled(true);
m_2DImagesLeftLayoutAction->setEnabled(true);
m_Big3DLayoutAction->setEnabled(false);
m_Widget1LayoutAction->setEnabled(true);
m_Widget2LayoutAction->setEnabled(true);
m_Widget3LayoutAction->setEnabled(true);
m_RowWidget3And4LayoutAction->setEnabled(true);
m_ColumnWidget3And4LayoutAction->setEnabled(true);
m_SmallUpperWidget2Big3and4LayoutAction->setEnabled(true);
m_2x2Dand3DWidgetLayoutAction->setEnabled(true);
m_Left2Dand3DRight2DLayoutAction->setEnabled(true);
break;
}
case LAYOUT_AXIAL:
{
m_DefaultLayoutAction->setEnabled(true);
m_2DImagesUpLayoutAction->setEnabled(true);
m_2DImagesLeftLayoutAction->setEnabled(true);
m_Big3DLayoutAction->setEnabled(true);
m_Widget1LayoutAction->setEnabled(false);
m_Widget2LayoutAction->setEnabled(true);
m_Widget3LayoutAction->setEnabled(true);
m_RowWidget3And4LayoutAction->setEnabled(true);
m_ColumnWidget3And4LayoutAction->setEnabled(true);
m_SmallUpperWidget2Big3and4LayoutAction->setEnabled(true);
m_2x2Dand3DWidgetLayoutAction->setEnabled(true);
m_Left2Dand3DRight2DLayoutAction->setEnabled(true);
break;
}
case LAYOUT_SAGITTAL:
{
m_DefaultLayoutAction->setEnabled(true);
m_2DImagesUpLayoutAction->setEnabled(true);
m_2DImagesLeftLayoutAction->setEnabled(true);
m_Big3DLayoutAction->setEnabled(true);
m_Widget1LayoutAction->setEnabled(true);
m_Widget2LayoutAction->setEnabled(false);
m_Widget3LayoutAction->setEnabled(true);
m_RowWidget3And4LayoutAction->setEnabled(true);
m_ColumnWidget3And4LayoutAction->setEnabled(true);
m_SmallUpperWidget2Big3and4LayoutAction->setEnabled(true);
m_2x2Dand3DWidgetLayoutAction->setEnabled(true);
m_Left2Dand3DRight2DLayoutAction->setEnabled(true);
break;
}
case LAYOUT_CORONAL:
{
m_DefaultLayoutAction->setEnabled(true);
m_2DImagesUpLayoutAction->setEnabled(true);
m_2DImagesLeftLayoutAction->setEnabled(true);
m_Big3DLayoutAction->setEnabled(true);
m_Widget1LayoutAction->setEnabled(true);
m_Widget2LayoutAction->setEnabled(true);
m_Widget3LayoutAction->setEnabled(false);
m_RowWidget3And4LayoutAction->setEnabled(true);
m_ColumnWidget3And4LayoutAction->setEnabled(true);
m_SmallUpperWidget2Big3and4LayoutAction->setEnabled(true);
m_2x2Dand3DWidgetLayoutAction->setEnabled(true);
m_Left2Dand3DRight2DLayoutAction->setEnabled(true);
break;
}
case LAYOUT_2X2DAND3DWIDGET:
{
m_DefaultLayoutAction->setEnabled(true);
m_2DImagesUpLayoutAction->setEnabled(true);
m_2DImagesLeftLayoutAction->setEnabled(true);
m_Big3DLayoutAction->setEnabled(true);
m_Widget1LayoutAction->setEnabled(true);
m_Widget2LayoutAction->setEnabled(true);
m_Widget3LayoutAction->setEnabled(true);
m_RowWidget3And4LayoutAction->setEnabled(true);
m_ColumnWidget3And4LayoutAction->setEnabled(true);
m_SmallUpperWidget2Big3and4LayoutAction->setEnabled(true);
m_2x2Dand3DWidgetLayoutAction->setEnabled(false);
m_Left2Dand3DRight2DLayoutAction->setEnabled(true);
break;
}
case LAYOUT_ROWWIDGET3AND4:
{
m_DefaultLayoutAction->setEnabled(true);
m_2DImagesUpLayoutAction->setEnabled(true);
m_2DImagesLeftLayoutAction->setEnabled(true);
m_Big3DLayoutAction->setEnabled(true);
m_Widget1LayoutAction->setEnabled(true);
m_Widget2LayoutAction->setEnabled(true);
m_Widget3LayoutAction->setEnabled(true);
m_RowWidget3And4LayoutAction->setEnabled(false);
m_ColumnWidget3And4LayoutAction->setEnabled(true);
m_SmallUpperWidget2Big3and4LayoutAction->setEnabled(true);
m_2x2Dand3DWidgetLayoutAction->setEnabled(true);
m_Left2Dand3DRight2DLayoutAction->setEnabled(true);
break;
}
case LAYOUT_COLUMNWIDGET3AND4:
{
m_DefaultLayoutAction->setEnabled(true);
m_2DImagesUpLayoutAction->setEnabled(true);
m_2DImagesLeftLayoutAction->setEnabled(true);
m_Big3DLayoutAction->setEnabled(true);
m_Widget1LayoutAction->setEnabled(true);
m_Widget2LayoutAction->setEnabled(true);
m_Widget3LayoutAction->setEnabled(true);
m_RowWidget3And4LayoutAction->setEnabled(true);
m_ColumnWidget3And4LayoutAction->setEnabled(false);
m_SmallUpperWidget2Big3and4LayoutAction->setEnabled(true);
m_2x2Dand3DWidgetLayoutAction->setEnabled(true);
m_Left2Dand3DRight2DLayoutAction->setEnabled(true);
break;
}
case LAYOUT_SMALLUPPERWIDGET2BIGAND4:
{
m_DefaultLayoutAction->setEnabled(true);
m_2DImagesUpLayoutAction->setEnabled(true);
m_2DImagesLeftLayoutAction->setEnabled(true);
m_Big3DLayoutAction->setEnabled(true);
m_Widget1LayoutAction->setEnabled(true);
m_Widget2LayoutAction->setEnabled(true);
m_Widget3LayoutAction->setEnabled(true);
m_RowWidget3And4LayoutAction->setEnabled(true);
m_ColumnWidget3And4LayoutAction->setEnabled(true);
m_SmallUpperWidget2Big3and4LayoutAction->setEnabled(false);
m_2x2Dand3DWidgetLayoutAction->setEnabled(true);
m_Left2Dand3DRight2DLayoutAction->setEnabled(true);
break;
}
case LAYOUT_LEFT2DAND3DRIGHT2D:
{
m_DefaultLayoutAction->setEnabled(true);
m_2DImagesUpLayoutAction->setEnabled(true);
m_2DImagesLeftLayoutAction->setEnabled(true);
m_Big3DLayoutAction->setEnabled(true);
m_Widget1LayoutAction->setEnabled(true);
m_Widget2LayoutAction->setEnabled(true);
m_Widget3LayoutAction->setEnabled(true);
m_RowWidget3And4LayoutAction->setEnabled(true);
m_ColumnWidget3And4LayoutAction->setEnabled(true);
m_SmallUpperWidget2Big3and4LayoutAction->setEnabled(true);
m_2x2Dand3DWidgetLayoutAction->setEnabled(true);
m_Left2Dand3DRight2DLayoutAction->setEnabled(false);
break;
}
}
}
#ifdef QMITK_USE_EXTERNAL_RENDERWINDOW_MENU
void QmitkRenderWindowMenu::MoveWidgetToCorrectPos(float opacity)
#else
void QmitkRenderWindowMenu::MoveWidgetToCorrectPos(float /*opacity*/)
#endif
{
#ifdef QMITK_USE_EXTERNAL_RENDERWINDOW_MENU
int X=floor( double(this->parentWidget()->width() - this->width() - 8.0) );
int Y=7;
QPoint pos = this->parentWidget()->mapToGlobal( QPoint(0,0) );
this->move( X+pos.x(), Y+pos.y() );
if(opacity<0) opacity=0;
else if(opacity>1) opacity=1;
this->setWindowOpacity(opacity);
#else
int moveX= floor( double(this->parentWidget()->width() - this->width() - 4.0) );
this->move( moveX, 3 );
this->show();
#endif
}
void QmitkRenderWindowMenu::ChangeFullScreenIcon()
{
if( m_FullScreenMode )
{
const QIcon icon( iconLeaveFullScreen_xpm );
m_FullScreenButton->setIcon(icon);
}
else
{
const QIcon icon( iconFullScreen_xpm );
m_FullScreenButton->setIcon(icon);
}
}
void QmitkRenderWindowMenu::OnCrosshairRotationModeSelected(QAction* action)
{
MITK_DEBUG << "selected crosshair mode " << action->data().toInt() ;
emit ChangeCrosshairRotationMode( action->data().toInt() );
}
void QmitkRenderWindowMenu::SetCrossHairVisibility( bool state )
{
if(m_Renderer.IsNotNull())
{
mitk::DataNode *n;
if(this->m_MultiWidget)
{
n = this->m_MultiWidget->GetWidgetPlane1(); if(n) n->SetVisibility(state);
n = this->m_MultiWidget->GetWidgetPlane2(); if(n) n->SetVisibility(state);
n = this->m_MultiWidget->GetWidgetPlane3(); if(n) n->SetVisibility(state);
m_Renderer->GetRenderingManager()->RequestUpdateAll();
}
}
}
void QmitkRenderWindowMenu::OnTSNumChanged(int num)
{
MITK_DEBUG << "Thickslices num: " << num << " on renderer " << m_Renderer.GetPointer();
if(m_Renderer.IsNotNull())
{
if(num==0)
{
- m_Renderer->GetCurrentWorldGeometry2DNode()->SetProperty( "reslice.thickslices", mitk::ResliceMethodProperty::New( 0 ) );
- m_Renderer->GetCurrentWorldGeometry2DNode()->SetProperty( "reslice.thickslices.showarea", mitk::BoolProperty::New( false ) );
+ m_Renderer->GetCurrentWorldPlaneGeometryNode()->SetProperty( "reslice.thickslices", mitk::ResliceMethodProperty::New( 0 ) );
+ m_Renderer->GetCurrentWorldPlaneGeometryNode()->SetProperty( "reslice.thickslices.showarea", mitk::BoolProperty::New( false ) );
}
else
{
- m_Renderer->GetCurrentWorldGeometry2DNode()->SetProperty( "reslice.thickslices", mitk::ResliceMethodProperty::New( 1 ) );
- m_Renderer->GetCurrentWorldGeometry2DNode()->SetProperty( "reslice.thickslices.num", mitk::IntProperty::New( num ) );
- m_Renderer->GetCurrentWorldGeometry2DNode()->SetProperty( "reslice.thickslices.showarea", mitk::BoolProperty::New( num > 1 ) );
+ m_Renderer->GetCurrentWorldPlaneGeometryNode()->SetProperty( "reslice.thickslices", mitk::ResliceMethodProperty::New( 1 ) );
+ m_Renderer->GetCurrentWorldPlaneGeometryNode()->SetProperty( "reslice.thickslices.num", mitk::IntProperty::New( num ) );
+ m_Renderer->GetCurrentWorldPlaneGeometryNode()->SetProperty( "reslice.thickslices.showarea", mitk::BoolProperty::New( num > 1 ) );
}
m_TSLabel->setText(QString::number(num*2+1));
m_Renderer->SendUpdateSlice();
m_Renderer->GetRenderingManager()->RequestUpdateAll();
}
}
void QmitkRenderWindowMenu::OnCrossHairMenuAboutToShow()
{
QMenu *crosshairModesMenu = m_CrosshairMenu;
crosshairModesMenu->clear();
QAction* resetViewAction = new QAction(crosshairModesMenu);
resetViewAction->setText("Reset view");
crosshairModesMenu->addAction( resetViewAction );
connect( resetViewAction, SIGNAL(triggered()), this, SIGNAL(ResetView()));
// Show hide crosshairs
{
bool currentState = true;
if(m_Renderer.IsNotNull())
{
mitk::DataStorage *ds=m_Renderer->GetDataStorage();
mitk::DataNode *n;
if(ds)
{
n = this->m_MultiWidget->GetWidgetPlane1(); if(n) { bool v; if(n->GetVisibility(v,0)) currentState&=v; }
n = this->m_MultiWidget->GetWidgetPlane2(); if(n) { bool v; if(n->GetVisibility(v,0)) currentState&=v; }
n = this->m_MultiWidget->GetWidgetPlane3(); if(n) { bool v; if(n->GetVisibility(v,0)) currentState&=v; }
}
}
QAction* showHideCrosshairVisibilityAction = new QAction(crosshairModesMenu);
showHideCrosshairVisibilityAction->setText("Show crosshair");
showHideCrosshairVisibilityAction->setCheckable(true);
showHideCrosshairVisibilityAction->setChecked(currentState);
crosshairModesMenu->addAction( showHideCrosshairVisibilityAction );
connect( showHideCrosshairVisibilityAction, SIGNAL(toggled(bool)), this, SLOT(SetCrossHairVisibility(bool)));
}
// Rotation mode
{
QAction* rotationGroupSeparator = new QAction(crosshairModesMenu);
rotationGroupSeparator->setSeparator(true);
rotationGroupSeparator->setText("Rotation mode");
crosshairModesMenu->addAction( rotationGroupSeparator );
QActionGroup* rotationModeActionGroup = new QActionGroup(crosshairModesMenu);
rotationModeActionGroup->setExclusive(true);
QAction* noCrosshairRotation = new QAction(crosshairModesMenu);
noCrosshairRotation->setActionGroup(rotationModeActionGroup);
noCrosshairRotation->setText("No crosshair rotation");
noCrosshairRotation->setCheckable(true);
noCrosshairRotation->setChecked(currentCrosshairRotationMode==0);
noCrosshairRotation->setData( 0 );
crosshairModesMenu->addAction( noCrosshairRotation );
QAction* singleCrosshairRotation = new QAction(crosshairModesMenu);
singleCrosshairRotation->setActionGroup(rotationModeActionGroup);
singleCrosshairRotation->setText("Crosshair rotation");
singleCrosshairRotation->setCheckable(true);
singleCrosshairRotation->setChecked(currentCrosshairRotationMode==1);
singleCrosshairRotation->setData( 1 );
crosshairModesMenu->addAction( singleCrosshairRotation );
QAction* coupledCrosshairRotation = new QAction(crosshairModesMenu);
coupledCrosshairRotation->setActionGroup(rotationModeActionGroup);
coupledCrosshairRotation->setText("Coupled crosshair rotation");
coupledCrosshairRotation->setCheckable(true);
coupledCrosshairRotation->setChecked(currentCrosshairRotationMode==2);
coupledCrosshairRotation->setData( 2 );
crosshairModesMenu->addAction( coupledCrosshairRotation );
QAction* swivelMode = new QAction(crosshairModesMenu);
swivelMode->setActionGroup(rotationModeActionGroup);
swivelMode->setText("Swivel mode");
swivelMode->setCheckable(true);
swivelMode->setChecked(currentCrosshairRotationMode==3);
swivelMode->setData( 3 );
crosshairModesMenu->addAction( swivelMode );
connect( rotationModeActionGroup, SIGNAL(triggered(QAction*)), this, SLOT(OnCrosshairRotationModeSelected(QAction*)) );
}
// auto rotation support
if( m_Renderer.IsNotNull() && m_Renderer->GetMapperID() == mitk::BaseRenderer::Standard3D )
{
QAction* autoRotationGroupSeparator = new QAction(crosshairModesMenu);
autoRotationGroupSeparator->setSeparator(true);
crosshairModesMenu->addAction( autoRotationGroupSeparator );
QAction* autoRotationAction = crosshairModesMenu->addAction( "Auto Rotation" );
autoRotationAction->setCheckable(true);
autoRotationAction->setChecked( m_AutoRotationTimer.isActive() );
connect( autoRotationAction, SIGNAL(triggered()), this, SLOT(OnAutoRotationActionTriggered()) );
}
// Thickslices support
if( m_Renderer.IsNotNull() && m_Renderer->GetMapperID() == mitk::BaseRenderer::Standard2D )
{
QAction* thickSlicesGroupSeparator = new QAction(crosshairModesMenu);
thickSlicesGroupSeparator->setSeparator(true);
thickSlicesGroupSeparator->setText("ThickSlices mode");
crosshairModesMenu->addAction( thickSlicesGroupSeparator );
QActionGroup* thickSlicesActionGroup = new QActionGroup(crosshairModesMenu);
thickSlicesActionGroup->setExclusive(true);
int currentMode = 0;
{
- mitk::ResliceMethodProperty::Pointer m = dynamic_cast<mitk::ResliceMethodProperty*>(m_Renderer->GetCurrentWorldGeometry2DNode()->GetProperty( "reslice.thickslices" ));
+ mitk::ResliceMethodProperty::Pointer m = dynamic_cast<mitk::ResliceMethodProperty*>(m_Renderer->GetCurrentWorldPlaneGeometryNode()->GetProperty( "reslice.thickslices" ));
if( m.IsNotNull() )
currentMode = m->GetValueAsId();
}
int currentNum = 1;
{
- mitk::IntProperty::Pointer m = dynamic_cast<mitk::IntProperty*>(m_Renderer->GetCurrentWorldGeometry2DNode()->GetProperty( "reslice.thickslices.num" ));
+ mitk::IntProperty::Pointer m = dynamic_cast<mitk::IntProperty*>(m_Renderer->GetCurrentWorldPlaneGeometryNode()->GetProperty( "reslice.thickslices.num" ));
if( m.IsNotNull() )
{
currentNum = m->GetValue();
if(currentNum < 1) currentNum = 1;
if(currentNum > 10) currentNum = 10;
}
}
if(currentMode==0)
currentNum=0;
QSlider *m_TSSlider = new QSlider(crosshairModesMenu);
m_TSSlider->setMinimum(0);
m_TSSlider->setMaximum(9);
m_TSSlider->setValue(currentNum);
m_TSSlider->setOrientation(Qt::Horizontal);
connect( m_TSSlider, SIGNAL( valueChanged(int) ), this, SLOT( OnTSNumChanged(int) ) );
QHBoxLayout* _TSLayout = new QHBoxLayout;
_TSLayout->setContentsMargins(4,4,4,4);
_TSLayout->addWidget(new QLabel("TS: "));
_TSLayout->addWidget(m_TSSlider);
_TSLayout->addWidget(m_TSLabel=new QLabel(QString::number(currentNum*2+1),this));
QWidget* _TSWidget = new QWidget;
_TSWidget->setLayout(_TSLayout);
QWidgetAction *m_TSSliderAction = new QWidgetAction(crosshairModesMenu);
m_TSSliderAction->setDefaultWidget(_TSWidget);
crosshairModesMenu->addAction(m_TSSliderAction);
}
}
void QmitkRenderWindowMenu::NotifyNewWidgetPlanesMode( int mode )
{
currentCrosshairRotationMode = mode;
}
void QmitkRenderWindowMenu::OnAutoRotationActionTriggered()
{
if(m_AutoRotationTimer.isActive())
{
m_AutoRotationTimer.stop();
m_Renderer->GetCameraRotationController()->GetSlice()->PingPongOff();
}
else
{
m_Renderer->GetCameraRotationController()->GetSlice()->PingPongOn();
m_AutoRotationTimer.start();
}
}
void QmitkRenderWindowMenu::AutoRotateNextStep()
{
if(m_Renderer->GetCameraRotationController())
m_Renderer->GetCameraRotationController()->GetSlice()->Next();
}
diff --git a/Modules/QtWidgets/QmitkStdMultiWidget.cpp b/Modules/QtWidgets/QmitkStdMultiWidget.cpp
index 5c852d8980..c2c9b8b265 100644
--- a/Modules/QtWidgets/QmitkStdMultiWidget.cpp
+++ b/Modules/QtWidgets/QmitkStdMultiWidget.cpp
@@ -1,2200 +1,2200 @@
/*===================================================================
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.
===================================================================*/
#define SMW_INFO MITK_INFO("widget.stdmulti")
#include "QmitkStdMultiWidget.h"
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QGridLayout>
#include <qsplitter.h>
#include <QMotifStyle>
#include <QList>
#include <QMouseEvent>
#include <QTimer>
#include "mitkProperties.h"
-#include "mitkGeometry2DDataMapper2D.h"
+#include "mitkPlaneGeometryDataMapper2D.h"
#include "mitkGlobalInteraction.h"
#include "mitkDisplayInteractor.h"
#include "mitkPointSet.h"
#include "mitkPositionEvent.h"
#include "mitkStateEvent.h"
#include "mitkLine.h"
#include "mitkInteractionConst.h"
#include "mitkDataStorage.h"
#include "mitkOverlayManager.h"
#include "mitkNodePredicateBase.h"
#include "mitkNodePredicateDataType.h"
#include "mitkNodePredicateNot.h"
#include "mitkNodePredicateProperty.h"
#include "mitkStatusBar.h"
#include "mitkImage.h"
#include "mitkVtkLayerController.h"
#include <iomanip>
QmitkStdMultiWidget::QmitkStdMultiWidget(QWidget* parent, Qt::WindowFlags f, mitk::RenderingManager* renderingManager, mitk::BaseRenderer::RenderingMode::Type renderingMode)
: QWidget(parent, f),
mitkWidget1(NULL),
mitkWidget2(NULL),
mitkWidget3(NULL),
mitkWidget4(NULL),
levelWindowWidget(NULL),
QmitkStdMultiWidgetLayout(NULL),
m_Layout(LAYOUT_DEFAULT),
m_PlaneMode(PLANE_MODE_SLICING),
m_RenderingManager(renderingManager),
m_GradientBackgroundFlag(true),
m_TimeNavigationController(NULL),
m_MainSplit(NULL),
m_LayoutSplit(NULL),
m_SubSplit1(NULL),
m_SubSplit2(NULL),
mitkWidget1Container(NULL),
mitkWidget2Container(NULL),
mitkWidget3Container(NULL),
mitkWidget4Container(NULL),
m_PendingCrosshairPositionEvent(false),
m_CrosshairNavigationEnabled(false)
{
/******************************************************
* Use the global RenderingManager if none was specified
* ****************************************************/
if (m_RenderingManager == NULL)
{
m_RenderingManager = mitk::RenderingManager::GetInstance();
}
m_TimeNavigationController = m_RenderingManager->GetTimeNavigationController();
/*******************************/
//Create Widget manually
/*******************************/
//create Layouts
QmitkStdMultiWidgetLayout = new QHBoxLayout( this );
QmitkStdMultiWidgetLayout->setContentsMargins(0,0,0,0);
//Set Layout to widget
this->setLayout(QmitkStdMultiWidgetLayout);
// QmitkNavigationToolBar* toolBar = new QmitkNavigationToolBar();
// QmitkStdMultiWidgetLayout->addWidget( toolBar );
//create main splitter
m_MainSplit = new QSplitter( this );
QmitkStdMultiWidgetLayout->addWidget( m_MainSplit );
//create m_LayoutSplit and add to the mainSplit
m_LayoutSplit = new QSplitter( Qt::Vertical, m_MainSplit );
m_MainSplit->addWidget( m_LayoutSplit );
//create m_SubSplit1 and m_SubSplit2
m_SubSplit1 = new QSplitter( m_LayoutSplit );
m_SubSplit2 = new QSplitter( m_LayoutSplit );
//creae Widget Container
mitkWidget1Container = new QWidget(m_SubSplit1);
mitkWidget2Container = new QWidget(m_SubSplit1);
mitkWidget3Container = new QWidget(m_SubSplit2);
mitkWidget4Container = new QWidget(m_SubSplit2);
mitkWidget1Container->setContentsMargins(0,0,0,0);
mitkWidget2Container->setContentsMargins(0,0,0,0);
mitkWidget3Container->setContentsMargins(0,0,0,0);
mitkWidget4Container->setContentsMargins(0,0,0,0);
//create Widget Layout
QHBoxLayout *mitkWidgetLayout1 = new QHBoxLayout(mitkWidget1Container);
QHBoxLayout *mitkWidgetLayout2 = new QHBoxLayout(mitkWidget2Container);
QHBoxLayout *mitkWidgetLayout3 = new QHBoxLayout(mitkWidget3Container);
QHBoxLayout *mitkWidgetLayout4 = new QHBoxLayout(mitkWidget4Container);
mitkWidgetLayout1->setMargin(0);
mitkWidgetLayout2->setMargin(0);
mitkWidgetLayout3->setMargin(0);
mitkWidgetLayout4->setMargin(0);
//set Layout to Widget Container
mitkWidget1Container->setLayout(mitkWidgetLayout1);
mitkWidget2Container->setLayout(mitkWidgetLayout2);
mitkWidget3Container->setLayout(mitkWidgetLayout3);
mitkWidget4Container->setLayout(mitkWidgetLayout4);
//set SizePolicy
mitkWidget1Container->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
mitkWidget2Container->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
mitkWidget3Container->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
mitkWidget4Container->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
//insert Widget Container into the splitters
m_SubSplit1->addWidget( mitkWidget1Container );
m_SubSplit1->addWidget( mitkWidget2Container );
m_SubSplit2->addWidget( mitkWidget3Container );
m_SubSplit2->addWidget( mitkWidget4Container );
// m_RenderingManager->SetGlobalInteraction( mitk::GlobalInteraction::GetInstance() );
//Create RenderWindows 1
mitkWidget1 = new QmitkRenderWindow(mitkWidget1Container, "stdmulti.widget1", NULL, m_RenderingManager,renderingMode);
mitkWidget1->setMaximumSize(2000,2000);
mitkWidget1->SetLayoutIndex( AXIAL );
mitkWidgetLayout1->addWidget(mitkWidget1);
//Create RenderWindows 2
mitkWidget2 = new QmitkRenderWindow(mitkWidget2Container, "stdmulti.widget2", NULL, m_RenderingManager,renderingMode);
mitkWidget2->setMaximumSize(2000,2000);
mitkWidget2->setEnabled( TRUE );
mitkWidget2->SetLayoutIndex( SAGITTAL );
mitkWidgetLayout2->addWidget(mitkWidget2);
//Create RenderWindows 3
mitkWidget3 = new QmitkRenderWindow(mitkWidget3Container, "stdmulti.widget3", NULL, m_RenderingManager,renderingMode);
mitkWidget3->setMaximumSize(2000,2000);
mitkWidget3->SetLayoutIndex( CORONAL );
mitkWidgetLayout3->addWidget(mitkWidget3);
//Create RenderWindows 4
mitkWidget4 = new QmitkRenderWindow(mitkWidget4Container, "stdmulti.widget4", NULL, m_RenderingManager,renderingMode);
mitkWidget4->setMaximumSize(2000,2000);
mitkWidget4->SetLayoutIndex( THREE_D );
mitkWidgetLayout4->addWidget(mitkWidget4);
//create SignalSlot Connection
connect( mitkWidget1, SIGNAL( SignalLayoutDesignChanged(int) ), this, SLOT( OnLayoutDesignChanged(int) ) );
connect( mitkWidget1, SIGNAL( ResetView() ), this, SLOT( ResetCrosshair() ) );
connect( mitkWidget1, SIGNAL( ChangeCrosshairRotationMode(int) ), this, SLOT( SetWidgetPlaneMode(int) ) );
connect( this, SIGNAL(WidgetNotifyNewCrossHairMode(int)), mitkWidget1, SLOT(OnWidgetPlaneModeChanged(int)) );
connect( mitkWidget2, SIGNAL( SignalLayoutDesignChanged(int) ), this, SLOT( OnLayoutDesignChanged(int) ) );
connect( mitkWidget2, SIGNAL( ResetView() ), this, SLOT( ResetCrosshair() ) );
connect( mitkWidget2, SIGNAL( ChangeCrosshairRotationMode(int) ), this, SLOT( SetWidgetPlaneMode(int) ) );
connect( this, SIGNAL(WidgetNotifyNewCrossHairMode(int)), mitkWidget2, SLOT(OnWidgetPlaneModeChanged(int)) );
connect( mitkWidget3, SIGNAL( SignalLayoutDesignChanged(int) ), this, SLOT( OnLayoutDesignChanged(int) ) );
connect( mitkWidget3, SIGNAL( ResetView() ), this, SLOT( ResetCrosshair() ) );
connect( mitkWidget3, SIGNAL( ChangeCrosshairRotationMode(int) ), this, SLOT( SetWidgetPlaneMode(int) ) );
connect( this, SIGNAL(WidgetNotifyNewCrossHairMode(int)), mitkWidget3, SLOT(OnWidgetPlaneModeChanged(int)) );
connect( mitkWidget4, SIGNAL( SignalLayoutDesignChanged(int) ), this, SLOT( OnLayoutDesignChanged(int) ) );
connect( mitkWidget4, SIGNAL( ResetView() ), this, SLOT( ResetCrosshair() ) );
connect( mitkWidget4, SIGNAL( ChangeCrosshairRotationMode(int) ), this, SLOT( SetWidgetPlaneMode(int) ) );
connect( this, SIGNAL(WidgetNotifyNewCrossHairMode(int)), mitkWidget4, SLOT(OnWidgetPlaneModeChanged(int)) );
//Create Level Window Widget
levelWindowWidget = new QmitkLevelWindowWidget( m_MainSplit ); //this
levelWindowWidget->setObjectName(QString::fromUtf8("levelWindowWidget"));
QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
sizePolicy.setHeightForWidth(levelWindowWidget->sizePolicy().hasHeightForWidth());
levelWindowWidget->setSizePolicy(sizePolicy);
levelWindowWidget->setMaximumSize(QSize(50, 2000));
//add LevelWindow Widget to mainSplitter
m_MainSplit->addWidget( levelWindowWidget );
//show mainSplitt and add to Layout
m_MainSplit->show();
//resize Image.
this->resize( QSize(364, 477).expandedTo(minimumSizeHint()) );
//Initialize the widgets.
this->InitializeWidget();
//Activate Widget Menu
this->ActivateMenuWidget( true );
}
void QmitkStdMultiWidget::InitializeWidget()
{
m_PositionTracker = NULL;
// transfer colors in WorldGeometry-Nodes of the associated Renderer
QColor qcolor;
//float color[3] = {1.0f,1.0f,1.0f};
mitk::DataNode::Pointer planeNode;
mitk::IntProperty::Pointer layer;
// of widget 1
- planeNode = mitk::BaseRenderer::GetInstance(mitkWidget1->GetRenderWindow())->GetCurrentWorldGeometry2DNode();
+ planeNode = mitk::BaseRenderer::GetInstance(mitkWidget1->GetRenderWindow())->GetCurrentWorldPlaneGeometryNode();
planeNode->SetColor(1.0,0.0,0.0);
layer = mitk::IntProperty::New(1000);
planeNode->SetProperty("layer",layer);
// ... of widget 2
- planeNode = mitk::BaseRenderer::GetInstance(mitkWidget2->GetRenderWindow())->GetCurrentWorldGeometry2DNode();
+ planeNode = mitk::BaseRenderer::GetInstance(mitkWidget2->GetRenderWindow())->GetCurrentWorldPlaneGeometryNode();
planeNode->SetColor(0.0,1.0,0.0);
layer = mitk::IntProperty::New(1000);
planeNode->SetProperty("layer",layer);
// ... of widget 3
- planeNode = mitk::BaseRenderer::GetInstance(mitkWidget3->GetRenderWindow())->GetCurrentWorldGeometry2DNode();
+ planeNode = mitk::BaseRenderer::GetInstance(mitkWidget3->GetRenderWindow())->GetCurrentWorldPlaneGeometryNode();
planeNode->SetColor(0.0,0.0,1.0);
layer = mitk::IntProperty::New(1000);
planeNode->SetProperty("layer",layer);
// ... of widget 4
- planeNode = mitk::BaseRenderer::GetInstance(mitkWidget4->GetRenderWindow())->GetCurrentWorldGeometry2DNode();
+ planeNode = mitk::BaseRenderer::GetInstance(mitkWidget4->GetRenderWindow())->GetCurrentWorldPlaneGeometryNode();
planeNode->SetColor(1.0,1.0,0.0);
layer = mitk::IntProperty::New(1000);
planeNode->SetProperty("layer",layer);
mitk::OverlayManager::Pointer OverlayManager = mitk::OverlayManager::New();
mitk::BaseRenderer::GetInstance(mitkWidget1->GetRenderWindow())->SetOverlayManager(OverlayManager);
mitk::BaseRenderer::GetInstance(mitkWidget2->GetRenderWindow())->SetOverlayManager(OverlayManager);
mitk::BaseRenderer::GetInstance(mitkWidget3->GetRenderWindow())->SetOverlayManager(OverlayManager);
mitk::BaseRenderer::GetInstance(mitkWidget4->GetRenderWindow())->SetOverlayManager(OverlayManager);
mitk::BaseRenderer::GetInstance(mitkWidget4->GetRenderWindow())->SetMapperID(mitk::BaseRenderer::Standard3D);
// Set plane mode (slicing/rotation behavior) to slicing (default)
m_PlaneMode = PLANE_MODE_SLICING;
// Set default view directions for SNCs
mitkWidget1->GetSliceNavigationController()->SetDefaultViewDirection(
mitk::SliceNavigationController::Axial );
mitkWidget2->GetSliceNavigationController()->SetDefaultViewDirection(
mitk::SliceNavigationController::Sagittal );
mitkWidget3->GetSliceNavigationController()->SetDefaultViewDirection(
mitk::SliceNavigationController::Frontal );
mitkWidget4->GetSliceNavigationController()->SetDefaultViewDirection(
mitk::SliceNavigationController::Original );
/*************************************************/
//Write Layout Names into the viewers -- hardCoded
//Info for later:
//int view = this->GetRenderWindow1()->GetSliceNavigationController()->GetDefaultViewDirection();
//QString layoutName;
//if( view == mitk::SliceNavigationController::Axial )
// layoutName = "Axial";
//else if( view == mitk::SliceNavigationController::Sagittal )
// layoutName = "Sagittal";
//else if( view == mitk::SliceNavigationController::Frontal )
// layoutName = "Coronal";
//else if( view == mitk::SliceNavigationController::Original )
// layoutName = "Original";
//if( view >= 0 && view < 4 )
// //write LayoutName --> Viewer 3D shoudn't write the layoutName.
//Render Window 1 == axial
m_CornerAnnotaions[0].cornerText = vtkCornerAnnotation::New();
m_CornerAnnotaions[0].cornerText->SetText(0, "Axial");
m_CornerAnnotaions[0].cornerText->SetMaximumFontSize(12);
m_CornerAnnotaions[0].textProp = vtkTextProperty::New();
m_CornerAnnotaions[0].textProp->SetColor( 1.0, 0.0, 0.0 );
m_CornerAnnotaions[0].cornerText->SetTextProperty( m_CornerAnnotaions[0].textProp );
m_CornerAnnotaions[0].ren = vtkRenderer::New();
m_CornerAnnotaions[0].ren->AddActor(m_CornerAnnotaions[0].cornerText);
m_CornerAnnotaions[0].ren->InteractiveOff();
mitk::VtkLayerController::GetInstance(this->GetRenderWindow1()->GetRenderWindow())->InsertForegroundRenderer(m_CornerAnnotaions[0].ren,true);
//Render Window 2 == sagittal
m_CornerAnnotaions[1].cornerText = vtkCornerAnnotation::New();
m_CornerAnnotaions[1].cornerText->SetText(0, "Sagittal");
m_CornerAnnotaions[1].cornerText->SetMaximumFontSize(12);
m_CornerAnnotaions[1].textProp = vtkTextProperty::New();
m_CornerAnnotaions[1].textProp->SetColor( 0.0, 1.0, 0.0 );
m_CornerAnnotaions[1].cornerText->SetTextProperty( m_CornerAnnotaions[1].textProp );
m_CornerAnnotaions[1].ren = vtkRenderer::New();
m_CornerAnnotaions[1].ren->AddActor(m_CornerAnnotaions[1].cornerText);
m_CornerAnnotaions[1].ren->InteractiveOff();
mitk::VtkLayerController::GetInstance(this->GetRenderWindow2()->GetRenderWindow())->InsertForegroundRenderer(m_CornerAnnotaions[1].ren,true);
//Render Window 3 == coronal
m_CornerAnnotaions[2].cornerText = vtkCornerAnnotation::New();
m_CornerAnnotaions[2].cornerText->SetText(0, "Coronal");
m_CornerAnnotaions[2].cornerText->SetMaximumFontSize(12);
m_CornerAnnotaions[2].textProp = vtkTextProperty::New();
m_CornerAnnotaions[2].textProp->SetColor( 0.295, 0.295, 1.0 );
m_CornerAnnotaions[2].cornerText->SetTextProperty( m_CornerAnnotaions[2].textProp );
m_CornerAnnotaions[2].ren = vtkRenderer::New();
m_CornerAnnotaions[2].ren->AddActor(m_CornerAnnotaions[2].cornerText);
m_CornerAnnotaions[2].ren->InteractiveOff();
mitk::VtkLayerController::GetInstance(this->GetRenderWindow3()->GetRenderWindow())->InsertForegroundRenderer(m_CornerAnnotaions[2].ren,true);
/*************************************************/
// create a slice rotator
// m_SlicesRotator = mitk::SlicesRotator::New();
// @TODO next line causes sure memory leak
// rotator will be created nonetheless (will be switched on and off)
m_SlicesRotator = mitk::SlicesRotator::New("slices-rotator");
m_SlicesRotator->AddSliceController(
mitkWidget1->GetSliceNavigationController() );
m_SlicesRotator->AddSliceController(
mitkWidget2->GetSliceNavigationController() );
m_SlicesRotator->AddSliceController(
mitkWidget3->GetSliceNavigationController() );
// create a slice swiveller (using the same state-machine as SlicesRotator)
m_SlicesSwiveller = mitk::SlicesSwiveller::New("slices-rotator");
m_SlicesSwiveller->AddSliceController(
mitkWidget1->GetSliceNavigationController() );
m_SlicesSwiveller->AddSliceController(
mitkWidget2->GetSliceNavigationController() );
m_SlicesSwiveller->AddSliceController(
mitkWidget3->GetSliceNavigationController() );
//connect to the "time navigation controller": send time via sliceNavigationControllers
m_TimeNavigationController->ConnectGeometryTimeEvent(
mitkWidget1->GetSliceNavigationController() , false);
m_TimeNavigationController->ConnectGeometryTimeEvent(
mitkWidget2->GetSliceNavigationController() , false);
m_TimeNavigationController->ConnectGeometryTimeEvent(
mitkWidget3->GetSliceNavigationController() , false);
m_TimeNavigationController->ConnectGeometryTimeEvent(
mitkWidget4->GetSliceNavigationController() , false);
mitkWidget1->GetSliceNavigationController()
->ConnectGeometrySendEvent(mitk::BaseRenderer::GetInstance(mitkWidget4->GetRenderWindow()));
//reverse connection between sliceNavigationControllers and m_TimeNavigationController
mitkWidget1->GetSliceNavigationController()
->ConnectGeometryTimeEvent(m_TimeNavigationController, false);
mitkWidget2->GetSliceNavigationController()
->ConnectGeometryTimeEvent(m_TimeNavigationController, false);
mitkWidget3->GetSliceNavigationController()
->ConnectGeometryTimeEvent(m_TimeNavigationController, false);
mitkWidget4->GetSliceNavigationController()
->ConnectGeometryTimeEvent(m_TimeNavigationController, false);
m_MouseModeSwitcher = mitk::MouseModeSwitcher::New();
m_LastLeftClickPositionSupplier =
mitk::CoordinateSupplier::New("navigation", NULL);
mitk::GlobalInteraction::GetInstance()->AddListener(
m_LastLeftClickPositionSupplier
);
// setup gradient background
m_GradientBackground1 = mitk::GradientBackground::New();
m_GradientBackground1->SetRenderWindow(
mitkWidget1->GetRenderWindow() );
m_GradientBackground1->Disable();
m_GradientBackground2 = mitk::GradientBackground::New();
m_GradientBackground2->SetRenderWindow(
mitkWidget2->GetRenderWindow() );
m_GradientBackground2->Disable();
m_GradientBackground3 = mitk::GradientBackground::New();
m_GradientBackground3->SetRenderWindow(
mitkWidget3->GetRenderWindow() );
m_GradientBackground3->Disable();
m_GradientBackground4 = mitk::GradientBackground::New();
m_GradientBackground4->SetRenderWindow(
mitkWidget4->GetRenderWindow() );
m_GradientBackground4->SetGradientColors(0.1,0.1,0.1,0.5,0.5,0.5);
m_GradientBackground4->Enable();
// setup the department logo rendering
m_LogoRendering1 = mitk::ManufacturerLogo::New();
m_LogoRendering1->SetRenderWindow(
mitkWidget1->GetRenderWindow() );
m_LogoRendering1->Disable();
m_LogoRendering2 = mitk::ManufacturerLogo::New();
m_LogoRendering2->SetRenderWindow(
mitkWidget2->GetRenderWindow() );
m_LogoRendering2->Disable();
m_LogoRendering3 = mitk::ManufacturerLogo::New();
m_LogoRendering3->SetRenderWindow(
mitkWidget3->GetRenderWindow() );
m_LogoRendering3->Disable();
m_LogoRendering4 = mitk::ManufacturerLogo::New();
m_LogoRendering4->SetRenderWindow(
mitkWidget4->GetRenderWindow() );
m_LogoRendering4->Enable();
m_RectangleRendering1 = mitk::RenderWindowFrame::New();
m_RectangleRendering1->SetRenderWindow(
mitkWidget1->GetRenderWindow() );
m_RectangleRendering1->Enable(1.0,0.0,0.0);
m_RectangleRendering2 = mitk::RenderWindowFrame::New();
m_RectangleRendering2->SetRenderWindow(
mitkWidget2->GetRenderWindow() );
m_RectangleRendering2->Enable(0.0,1.0,0.0);
m_RectangleRendering3 = mitk::RenderWindowFrame::New();
m_RectangleRendering3->SetRenderWindow(
mitkWidget3->GetRenderWindow() );
m_RectangleRendering3->Enable(0.0,0.0,1.0);
m_RectangleRendering4 = mitk::RenderWindowFrame::New();
m_RectangleRendering4->SetRenderWindow(
mitkWidget4->GetRenderWindow() );
m_RectangleRendering4->Enable(1.0,1.0,0.0);
}
QmitkStdMultiWidget::~QmitkStdMultiWidget()
{
DisablePositionTracking();
DisableNavigationControllerEventListening();
m_TimeNavigationController->Disconnect(mitkWidget1->GetSliceNavigationController());
m_TimeNavigationController->Disconnect(mitkWidget2->GetSliceNavigationController());
m_TimeNavigationController->Disconnect(mitkWidget3->GetSliceNavigationController());
m_TimeNavigationController->Disconnect(mitkWidget4->GetSliceNavigationController());
mitk::VtkLayerController::GetInstance(this->GetRenderWindow1()->GetRenderWindow())->RemoveRenderer( m_CornerAnnotaions[0].ren );
mitk::VtkLayerController::GetInstance(this->GetRenderWindow2()->GetRenderWindow())->RemoveRenderer( m_CornerAnnotaions[1].ren );
mitk::VtkLayerController::GetInstance(this->GetRenderWindow3()->GetRenderWindow())->RemoveRenderer( m_CornerAnnotaions[2].ren );
//Delete CornerAnnotation
m_CornerAnnotaions[0].cornerText->Delete();
m_CornerAnnotaions[0].textProp->Delete();
m_CornerAnnotaions[0].ren->Delete();
m_CornerAnnotaions[1].cornerText->Delete();
m_CornerAnnotaions[1].textProp->Delete();
m_CornerAnnotaions[1].ren->Delete();
m_CornerAnnotaions[2].cornerText->Delete();
m_CornerAnnotaions[2].textProp->Delete();
m_CornerAnnotaions[2].ren->Delete();
}
void QmitkStdMultiWidget::RemovePlanesFromDataStorage()
{
if (m_PlaneNode1.IsNotNull() && m_PlaneNode2.IsNotNull() && m_PlaneNode3.IsNotNull() && m_Node.IsNotNull())
{
if(m_DataStorage.IsNotNull())
{
m_DataStorage->Remove(m_PlaneNode1);
m_DataStorage->Remove(m_PlaneNode2);
m_DataStorage->Remove(m_PlaneNode3);
m_DataStorage->Remove(m_Node);
}
}
}
void QmitkStdMultiWidget::AddPlanesToDataStorage()
{
if (m_PlaneNode1.IsNotNull() && m_PlaneNode2.IsNotNull() && m_PlaneNode3.IsNotNull() && m_Node.IsNotNull())
{
if (m_DataStorage.IsNotNull())
{
m_DataStorage->Add(m_Node);
m_DataStorage->Add(m_PlaneNode1, m_Node);
m_DataStorage->Add(m_PlaneNode2, m_Node);
m_DataStorage->Add(m_PlaneNode3, m_Node);
- static_cast<mitk::Geometry2DDataMapper2D*>(m_PlaneNode1->GetMapper(mitk::BaseRenderer::Standard2D))->SetDatastorageAndGeometryBaseNode(m_DataStorage, m_Node);
- static_cast<mitk::Geometry2DDataMapper2D*>(m_PlaneNode2->GetMapper(mitk::BaseRenderer::Standard2D))->SetDatastorageAndGeometryBaseNode(m_DataStorage, m_Node);
- static_cast<mitk::Geometry2DDataMapper2D*>(m_PlaneNode3->GetMapper(mitk::BaseRenderer::Standard2D))->SetDatastorageAndGeometryBaseNode(m_DataStorage, m_Node);
+ static_cast<mitk::PlaneGeometryDataMapper2D*>(m_PlaneNode1->GetMapper(mitk::BaseRenderer::Standard2D))->SetDatastorageAndGeometryBaseNode(m_DataStorage, m_Node);
+ static_cast<mitk::PlaneGeometryDataMapper2D*>(m_PlaneNode2->GetMapper(mitk::BaseRenderer::Standard2D))->SetDatastorageAndGeometryBaseNode(m_DataStorage, m_Node);
+ static_cast<mitk::PlaneGeometryDataMapper2D*>(m_PlaneNode3->GetMapper(mitk::BaseRenderer::Standard2D))->SetDatastorageAndGeometryBaseNode(m_DataStorage, m_Node);
}
}
}
void QmitkStdMultiWidget::changeLayoutTo2DImagesUp()
{
SMW_INFO << "changing layout to 2D images up... " << std::endl;
//Hide all Menu Widgets
this->HideAllWidgetToolbars();
delete QmitkStdMultiWidgetLayout ;
//create Main Layout
QmitkStdMultiWidgetLayout = new QHBoxLayout( this );
//Set Layout to widget
this->setLayout(QmitkStdMultiWidgetLayout);
//create main splitter
m_MainSplit = new QSplitter( this );
QmitkStdMultiWidgetLayout->addWidget( m_MainSplit );
//create m_LayoutSplit and add to the mainSplit
m_LayoutSplit = new QSplitter( Qt::Vertical, m_MainSplit );
m_MainSplit->addWidget( m_LayoutSplit );
//add LevelWindow Widget to mainSplitter
m_MainSplit->addWidget( levelWindowWidget );
//create m_SubSplit1 and m_SubSplit2
m_SubSplit1 = new QSplitter( m_LayoutSplit );
m_SubSplit2 = new QSplitter( m_LayoutSplit );
//insert Widget Container into splitter top
m_SubSplit1->addWidget( mitkWidget1Container );
m_SubSplit1->addWidget( mitkWidget2Container );
m_SubSplit1->addWidget( mitkWidget3Container );
//set SplitterSize for splitter top
QList<int> splitterSize;
splitterSize.push_back(1000);
splitterSize.push_back(1000);
splitterSize.push_back(1000);
m_SubSplit1->setSizes( splitterSize );
//insert Widget Container into splitter bottom
m_SubSplit2->addWidget( mitkWidget4Container );
//set SplitterSize for splitter m_LayoutSplit
splitterSize.clear();
splitterSize.push_back(400);
splitterSize.push_back(1000);
m_LayoutSplit->setSizes( splitterSize );
//show mainSplitt
m_MainSplit->show();
//show Widget if hidden
if ( mitkWidget1->isHidden() ) mitkWidget1->show();
if ( mitkWidget2->isHidden() ) mitkWidget2->show();
if ( mitkWidget3->isHidden() ) mitkWidget3->show();
if ( mitkWidget4->isHidden() ) mitkWidget4->show();
//Change Layout Name
m_Layout = LAYOUT_2D_IMAGES_UP;
//update Layout Design List
mitkWidget1->LayoutDesignListChanged( LAYOUT_2D_IMAGES_UP );
mitkWidget2->LayoutDesignListChanged( LAYOUT_2D_IMAGES_UP );
mitkWidget3->LayoutDesignListChanged( LAYOUT_2D_IMAGES_UP );
mitkWidget4->LayoutDesignListChanged( LAYOUT_2D_IMAGES_UP );
//update Alle Widgets
this->UpdateAllWidgets();
}
void QmitkStdMultiWidget::changeLayoutTo2DImagesLeft()
{
SMW_INFO << "changing layout to 2D images left... " << std::endl;
//Hide all Menu Widgets
this->HideAllWidgetToolbars();
delete QmitkStdMultiWidgetLayout ;
//create Main Layout
QmitkStdMultiWidgetLayout = new QHBoxLayout( this );
//create main splitter
m_MainSplit = new QSplitter( this );
QmitkStdMultiWidgetLayout->addWidget( m_MainSplit );
//create m_LayoutSplit and add to the mainSplit
m_LayoutSplit = new QSplitter( m_MainSplit );
m_MainSplit->addWidget( m_LayoutSplit );
//add LevelWindow Widget to mainSplitter
m_MainSplit->addWidget( levelWindowWidget );
//create m_SubSplit1 and m_SubSplit2
m_SubSplit1 = new QSplitter( Qt::Vertical, m_LayoutSplit );
m_SubSplit2 = new QSplitter( m_LayoutSplit );
//insert Widget into the splitters
m_SubSplit1->addWidget( mitkWidget1Container );
m_SubSplit1->addWidget( mitkWidget2Container );
m_SubSplit1->addWidget( mitkWidget3Container );
//set splitterSize of SubSplit1
QList<int> splitterSize;
splitterSize.push_back(1000);
splitterSize.push_back(1000);
splitterSize.push_back(1000);
m_SubSplit1->setSizes( splitterSize );
m_SubSplit2->addWidget( mitkWidget4Container );
//set splitterSize of Layout Split
splitterSize.clear();
splitterSize.push_back(400);
splitterSize.push_back(1000);
m_LayoutSplit->setSizes( splitterSize );
//show mainSplitt and add to Layout
m_MainSplit->show();
//show Widget if hidden
if ( mitkWidget1->isHidden() ) mitkWidget1->show();
if ( mitkWidget2->isHidden() ) mitkWidget2->show();
if ( mitkWidget3->isHidden() ) mitkWidget3->show();
if ( mitkWidget4->isHidden() ) mitkWidget4->show();
//update Layout Name
m_Layout = LAYOUT_2D_IMAGES_LEFT;
//update Layout Design List
mitkWidget1->LayoutDesignListChanged( LAYOUT_2D_IMAGES_LEFT );
mitkWidget2->LayoutDesignListChanged( LAYOUT_2D_IMAGES_LEFT );
mitkWidget3->LayoutDesignListChanged( LAYOUT_2D_IMAGES_LEFT );
mitkWidget4->LayoutDesignListChanged( LAYOUT_2D_IMAGES_LEFT );
//update Alle Widgets
this->UpdateAllWidgets();
}
void QmitkStdMultiWidget::changeLayoutToDefault()
{
SMW_INFO << "changing layout to default... " << std::endl;
//Hide all Menu Widgets
this->HideAllWidgetToolbars();
delete QmitkStdMultiWidgetLayout ;
//create Main Layout
QmitkStdMultiWidgetLayout = new QHBoxLayout( this );
//create main splitter
m_MainSplit = new QSplitter( this );
QmitkStdMultiWidgetLayout->addWidget( m_MainSplit );
//create m_LayoutSplit and add to the mainSplit
m_LayoutSplit = new QSplitter( Qt::Vertical, m_MainSplit );
m_MainSplit->addWidget( m_LayoutSplit );
//add LevelWindow Widget to mainSplitter
m_MainSplit->addWidget( levelWindowWidget );
//create m_SubSplit1 and m_SubSplit2
m_SubSplit1 = new QSplitter( m_LayoutSplit );
m_SubSplit2 = new QSplitter( m_LayoutSplit );
//insert Widget container into the splitters
m_SubSplit1->addWidget( mitkWidget1Container );
m_SubSplit1->addWidget( mitkWidget2Container );
m_SubSplit2->addWidget( mitkWidget3Container );
m_SubSplit2->addWidget( mitkWidget4Container );
//set splitter Size
QList<int> splitterSize;
splitterSize.push_back(1000);
splitterSize.push_back(1000);
m_SubSplit1->setSizes( splitterSize );
m_SubSplit2->setSizes( splitterSize );
m_LayoutSplit->setSizes( splitterSize );
//show mainSplitt and add to Layout
m_MainSplit->show();
//show Widget if hidden
if ( mitkWidget1->isHidden() ) mitkWidget1->show();
if ( mitkWidget2->isHidden() ) mitkWidget2->show();
if ( mitkWidget3->isHidden() ) mitkWidget3->show();
if ( mitkWidget4->isHidden() ) mitkWidget4->show();
m_Layout = LAYOUT_DEFAULT;
//update Layout Design List
mitkWidget1->LayoutDesignListChanged( LAYOUT_DEFAULT );
mitkWidget2->LayoutDesignListChanged( LAYOUT_DEFAULT );
mitkWidget3->LayoutDesignListChanged( LAYOUT_DEFAULT );
mitkWidget4->LayoutDesignListChanged( LAYOUT_DEFAULT );
//update Alle Widgets
this->UpdateAllWidgets();
}
void QmitkStdMultiWidget::changeLayoutToBig3D()
{
SMW_INFO << "changing layout to big 3D ..." << std::endl;
//Hide all Menu Widgets
this->HideAllWidgetToolbars();
delete QmitkStdMultiWidgetLayout ;
//create Main Layout
QmitkStdMultiWidgetLayout = new QHBoxLayout( this );
//create main splitter
m_MainSplit = new QSplitter( this );
QmitkStdMultiWidgetLayout->addWidget( m_MainSplit );
//add widget Splitter to main Splitter
m_MainSplit->addWidget( mitkWidget4Container );
//add LevelWindow Widget to mainSplitter
m_MainSplit->addWidget( levelWindowWidget );
//show mainSplitt and add to Layout
m_MainSplit->show();
//show/hide Widgets
mitkWidget1->hide();
mitkWidget2->hide();
mitkWidget3->hide();
if ( mitkWidget4->isHidden() ) mitkWidget4->show();
m_Layout = LAYOUT_BIG_3D;
//update Layout Design List
mitkWidget1->LayoutDesignListChanged( LAYOUT_BIG_3D );
mitkWidget2->LayoutDesignListChanged( LAYOUT_BIG_3D );
mitkWidget3->LayoutDesignListChanged( LAYOUT_BIG_3D );
mitkWidget4->LayoutDesignListChanged( LAYOUT_BIG_3D );
//update Alle Widgets
this->UpdateAllWidgets();
}
void QmitkStdMultiWidget::changeLayoutToWidget1()
{
SMW_INFO << "changing layout to big Widget1 ..." << std::endl;
//Hide all Menu Widgets
this->HideAllWidgetToolbars();
delete QmitkStdMultiWidgetLayout ;
//create Main Layout
QmitkStdMultiWidgetLayout = new QHBoxLayout( this );
//create main splitter
m_MainSplit = new QSplitter( this );
QmitkStdMultiWidgetLayout->addWidget( m_MainSplit );
//add widget Splitter to main Splitter
m_MainSplit->addWidget( mitkWidget1Container );
//add LevelWindow Widget to mainSplitter
m_MainSplit->addWidget( levelWindowWidget );
//show mainSplitt and add to Layout
m_MainSplit->show();
//show/hide Widgets
if ( mitkWidget1->isHidden() ) mitkWidget1->show();
mitkWidget2->hide();
mitkWidget3->hide();
mitkWidget4->hide();
m_Layout = LAYOUT_WIDGET1;
//update Layout Design List
mitkWidget1->LayoutDesignListChanged( LAYOUT_WIDGET1 );
mitkWidget2->LayoutDesignListChanged( LAYOUT_WIDGET1 );
mitkWidget3->LayoutDesignListChanged( LAYOUT_WIDGET1 );
mitkWidget4->LayoutDesignListChanged( LAYOUT_WIDGET1 );
//update Alle Widgets
this->UpdateAllWidgets();
}
void QmitkStdMultiWidget::changeLayoutToWidget2()
{
SMW_INFO << "changing layout to big Widget2 ..." << std::endl;
//Hide all Menu Widgets
this->HideAllWidgetToolbars();
delete QmitkStdMultiWidgetLayout ;
//create Main Layout
QmitkStdMultiWidgetLayout = new QHBoxLayout( this );
//create main splitter
m_MainSplit = new QSplitter( this );
QmitkStdMultiWidgetLayout->addWidget( m_MainSplit );
//add widget Splitter to main Splitter
m_MainSplit->addWidget( mitkWidget2Container );
//add LevelWindow Widget to mainSplitter
m_MainSplit->addWidget( levelWindowWidget );
//show mainSplitt and add to Layout
m_MainSplit->show();
//show/hide Widgets
mitkWidget1->hide();
if ( mitkWidget2->isHidden() ) mitkWidget2->show();
mitkWidget3->hide();
mitkWidget4->hide();
m_Layout = LAYOUT_WIDGET2;
//update Layout Design List
mitkWidget1->LayoutDesignListChanged( LAYOUT_WIDGET2 );
mitkWidget2->LayoutDesignListChanged( LAYOUT_WIDGET2 );
mitkWidget3->LayoutDesignListChanged( LAYOUT_WIDGET2 );
mitkWidget4->LayoutDesignListChanged( LAYOUT_WIDGET2 );
//update Alle Widgets
this->UpdateAllWidgets();
}
void QmitkStdMultiWidget::changeLayoutToWidget3()
{
SMW_INFO << "changing layout to big Widget3 ..." << std::endl;
//Hide all Menu Widgets
this->HideAllWidgetToolbars();
delete QmitkStdMultiWidgetLayout ;
//create Main Layout
QmitkStdMultiWidgetLayout = new QHBoxLayout( this );
//create main splitter
m_MainSplit = new QSplitter( this );
QmitkStdMultiWidgetLayout->addWidget( m_MainSplit );
//add widget Splitter to main Splitter
m_MainSplit->addWidget( mitkWidget3Container );
//add LevelWindow Widget to mainSplitter
m_MainSplit->addWidget( levelWindowWidget );
//show mainSplitt and add to Layout
m_MainSplit->show();
//show/hide Widgets
mitkWidget1->hide();
mitkWidget2->hide();
if ( mitkWidget3->isHidden() ) mitkWidget3->show();
mitkWidget4->hide();
m_Layout = LAYOUT_WIDGET3;
//update Layout Design List
mitkWidget1->LayoutDesignListChanged( LAYOUT_WIDGET3 );
mitkWidget2->LayoutDesignListChanged( LAYOUT_WIDGET3 );
mitkWidget3->LayoutDesignListChanged( LAYOUT_WIDGET3 );
mitkWidget4->LayoutDesignListChanged( LAYOUT_WIDGET3 );
//update Alle Widgets
this->UpdateAllWidgets();
}
void QmitkStdMultiWidget::changeLayoutToRowWidget3And4()
{
SMW_INFO << "changing layout to Widget3 and 4 in a Row..." << std::endl;
//Hide all Menu Widgets
this->HideAllWidgetToolbars();
delete QmitkStdMultiWidgetLayout ;
//create Main Layout
QmitkStdMultiWidgetLayout = new QHBoxLayout( this );
//create main splitter
m_MainSplit = new QSplitter( this );
QmitkStdMultiWidgetLayout->addWidget( m_MainSplit );
//create m_LayoutSplit and add to the mainSplit
m_LayoutSplit = new QSplitter( Qt::Vertical, m_MainSplit );
m_MainSplit->addWidget( m_LayoutSplit );
//add LevelWindow Widget to mainSplitter
m_MainSplit->addWidget( levelWindowWidget );
//add Widgets to splitter
m_LayoutSplit->addWidget( mitkWidget3Container );
m_LayoutSplit->addWidget( mitkWidget4Container );
//set Splitter Size
QList<int> splitterSize;
splitterSize.push_back(1000);
splitterSize.push_back(1000);
m_LayoutSplit->setSizes( splitterSize );
//show mainSplitt and add to Layout
m_MainSplit->show();
//show/hide Widgets
mitkWidget1->hide();
mitkWidget2->hide();
if ( mitkWidget3->isHidden() ) mitkWidget3->show();
if ( mitkWidget4->isHidden() ) mitkWidget4->show();
m_Layout = LAYOUT_ROW_WIDGET_3_AND_4;
//update Layout Design List
mitkWidget1->LayoutDesignListChanged( LAYOUT_ROW_WIDGET_3_AND_4 );
mitkWidget2->LayoutDesignListChanged( LAYOUT_ROW_WIDGET_3_AND_4 );
mitkWidget3->LayoutDesignListChanged( LAYOUT_ROW_WIDGET_3_AND_4 );
mitkWidget4->LayoutDesignListChanged( LAYOUT_ROW_WIDGET_3_AND_4 );
//update Alle Widgets
this->UpdateAllWidgets();
}
void QmitkStdMultiWidget::changeLayoutToColumnWidget3And4()
{
SMW_INFO << "changing layout to Widget3 and 4 in one Column..." << std::endl;
//Hide all Menu Widgets
this->HideAllWidgetToolbars();
delete QmitkStdMultiWidgetLayout ;
//create Main Layout
QmitkStdMultiWidgetLayout = new QHBoxLayout( this );
//create main splitter
m_MainSplit = new QSplitter( this );
QmitkStdMultiWidgetLayout->addWidget( m_MainSplit );
//create m_LayoutSplit and add to the mainSplit
m_LayoutSplit = new QSplitter( m_MainSplit );
m_MainSplit->addWidget( m_LayoutSplit );
//add LevelWindow Widget to mainSplitter
m_MainSplit->addWidget( levelWindowWidget );
//add Widgets to splitter
m_LayoutSplit->addWidget( mitkWidget3Container );
m_LayoutSplit->addWidget( mitkWidget4Container );
//set SplitterSize
QList<int> splitterSize;
splitterSize.push_back(1000);
splitterSize.push_back(1000);
m_LayoutSplit->setSizes( splitterSize );
//show mainSplitt and add to Layout
m_MainSplit->show();
//show/hide Widgets
mitkWidget1->hide();
mitkWidget2->hide();
if ( mitkWidget3->isHidden() ) mitkWidget3->show();
if ( mitkWidget4->isHidden() ) mitkWidget4->show();
m_Layout = LAYOUT_COLUMN_WIDGET_3_AND_4;
//update Layout Design List
mitkWidget1->LayoutDesignListChanged( LAYOUT_COLUMN_WIDGET_3_AND_4 );
mitkWidget2->LayoutDesignListChanged( LAYOUT_COLUMN_WIDGET_3_AND_4 );
mitkWidget3->LayoutDesignListChanged( LAYOUT_COLUMN_WIDGET_3_AND_4 );
mitkWidget4->LayoutDesignListChanged( LAYOUT_COLUMN_WIDGET_3_AND_4 );
//update Alle Widgets
this->UpdateAllWidgets();
}
void QmitkStdMultiWidget::changeLayoutToRowWidgetSmall3andBig4()
{
SMW_INFO << "changing layout to Widget3 and 4 in a Row..." << std::endl;
this->changeLayoutToRowWidget3And4();
m_Layout = LAYOUT_ROW_WIDGET_SMALL3_AND_BIG4;
}
void QmitkStdMultiWidget::changeLayoutToSmallUpperWidget2Big3and4()
{
SMW_INFO << "changing layout to Widget3 and 4 in a Row..." << std::endl;
//Hide all Menu Widgets
this->HideAllWidgetToolbars();
delete QmitkStdMultiWidgetLayout ;
//create Main Layout
QmitkStdMultiWidgetLayout = new QHBoxLayout( this );
//create main splitter
m_MainSplit = new QSplitter( this );
QmitkStdMultiWidgetLayout->addWidget( m_MainSplit );
//create m_LayoutSplit and add to the mainSplit
m_LayoutSplit = new QSplitter( Qt::Vertical, m_MainSplit );
m_MainSplit->addWidget( m_LayoutSplit );
//add LevelWindow Widget to mainSplitter
m_MainSplit->addWidget( levelWindowWidget );
//create m_SubSplit1 and m_SubSplit2
m_SubSplit1 = new QSplitter( Qt::Vertical, m_LayoutSplit );
m_SubSplit2 = new QSplitter( m_LayoutSplit );
//insert Widget into the splitters
m_SubSplit1->addWidget( mitkWidget2Container );
m_SubSplit2->addWidget( mitkWidget3Container );
m_SubSplit2->addWidget( mitkWidget4Container );
//set Splitter Size
QList<int> splitterSize;
splitterSize.push_back(1000);
splitterSize.push_back(1000);
m_SubSplit2->setSizes( splitterSize );
splitterSize.clear();
splitterSize.push_back(500);
splitterSize.push_back(1000);
m_LayoutSplit->setSizes( splitterSize );
//show mainSplitt
m_MainSplit->show();
//show Widget if hidden
mitkWidget1->hide();
if ( mitkWidget2->isHidden() ) mitkWidget2->show();
if ( mitkWidget3->isHidden() ) mitkWidget3->show();
if ( mitkWidget4->isHidden() ) mitkWidget4->show();
m_Layout = LAYOUT_SMALL_UPPER_WIDGET2_BIG3_AND4;
//update Layout Design List
mitkWidget1->LayoutDesignListChanged( LAYOUT_SMALL_UPPER_WIDGET2_BIG3_AND4 );
mitkWidget2->LayoutDesignListChanged( LAYOUT_SMALL_UPPER_WIDGET2_BIG3_AND4 );
mitkWidget3->LayoutDesignListChanged( LAYOUT_SMALL_UPPER_WIDGET2_BIG3_AND4 );
mitkWidget4->LayoutDesignListChanged( LAYOUT_SMALL_UPPER_WIDGET2_BIG3_AND4 );
//update Alle Widgets
this->UpdateAllWidgets();
}
void QmitkStdMultiWidget::changeLayoutTo2x2Dand3DWidget()
{
SMW_INFO << "changing layout to 2 x 2D and 3D Widget" << std::endl;
//Hide all Menu Widgets
this->HideAllWidgetToolbars();
delete QmitkStdMultiWidgetLayout ;
//create Main Layout
QmitkStdMultiWidgetLayout = new QHBoxLayout( this );
//create main splitter
m_MainSplit = new QSplitter( this );
QmitkStdMultiWidgetLayout->addWidget( m_MainSplit );
//create m_LayoutSplit and add to the mainSplit
m_LayoutSplit = new QSplitter( m_MainSplit );
m_MainSplit->addWidget( m_LayoutSplit );
//add LevelWindow Widget to mainSplitter
m_MainSplit->addWidget( levelWindowWidget );
//create m_SubSplit1 and m_SubSplit2
m_SubSplit1 = new QSplitter( Qt::Vertical, m_LayoutSplit );
m_SubSplit2 = new QSplitter( m_LayoutSplit );
//add Widgets to splitter
m_SubSplit1->addWidget( mitkWidget1Container );
m_SubSplit1->addWidget( mitkWidget2Container );
m_SubSplit2->addWidget( mitkWidget4Container );
//set Splitter Size
QList<int> splitterSize;
splitterSize.push_back(1000);
splitterSize.push_back(1000);
m_SubSplit1->setSizes( splitterSize );
m_LayoutSplit->setSizes( splitterSize );
//show mainSplitt and add to Layout
m_MainSplit->show();
//show/hide Widgets
if ( mitkWidget1->isHidden() ) mitkWidget1->show();
if ( mitkWidget2->isHidden() ) mitkWidget2->show();
mitkWidget3->hide();
if ( mitkWidget4->isHidden() ) mitkWidget4->show();
m_Layout = LAYOUT_2X_2D_AND_3D_WIDGET;
//update Layout Design List
mitkWidget1->LayoutDesignListChanged( LAYOUT_2X_2D_AND_3D_WIDGET );
mitkWidget2->LayoutDesignListChanged( LAYOUT_2X_2D_AND_3D_WIDGET );
mitkWidget3->LayoutDesignListChanged( LAYOUT_2X_2D_AND_3D_WIDGET );
mitkWidget4->LayoutDesignListChanged( LAYOUT_2X_2D_AND_3D_WIDGET );
//update Alle Widgets
this->UpdateAllWidgets();
}
void QmitkStdMultiWidget::changeLayoutToLeft2Dand3DRight2D()
{
SMW_INFO << "changing layout to 2D and 3D left, 2D right Widget" << std::endl;
//Hide all Menu Widgets
this->HideAllWidgetToolbars();
delete QmitkStdMultiWidgetLayout ;
//create Main Layout
QmitkStdMultiWidgetLayout = new QHBoxLayout( this );
//create main splitter
m_MainSplit = new QSplitter( this );
QmitkStdMultiWidgetLayout->addWidget( m_MainSplit );
//create m_LayoutSplit and add to the mainSplit
m_LayoutSplit = new QSplitter( m_MainSplit );
m_MainSplit->addWidget( m_LayoutSplit );
//add LevelWindow Widget to mainSplitter
m_MainSplit->addWidget( levelWindowWidget );
//create m_SubSplit1 and m_SubSplit2
m_SubSplit1 = new QSplitter( Qt::Vertical, m_LayoutSplit );
m_SubSplit2 = new QSplitter( m_LayoutSplit );
//add Widgets to splitter
m_SubSplit1->addWidget( mitkWidget1Container );
m_SubSplit1->addWidget( mitkWidget4Container );
m_SubSplit2->addWidget( mitkWidget2Container );
//set Splitter Size
QList<int> splitterSize;
splitterSize.push_back(1000);
splitterSize.push_back(1000);
m_SubSplit1->setSizes( splitterSize );
m_LayoutSplit->setSizes( splitterSize );
//show mainSplitt and add to Layout
m_MainSplit->show();
//show/hide Widgets
if ( mitkWidget1->isHidden() ) mitkWidget1->show();
if ( mitkWidget2->isHidden() ) mitkWidget2->show();
mitkWidget3->hide();
if ( mitkWidget4->isHidden() ) mitkWidget4->show();
m_Layout = LAYOUT_2D_AND_3D_LEFT_2D_RIGHT_WIDGET;
//update Layout Design List
mitkWidget1->LayoutDesignListChanged( LAYOUT_2D_AND_3D_LEFT_2D_RIGHT_WIDGET );
mitkWidget2->LayoutDesignListChanged( LAYOUT_2D_AND_3D_LEFT_2D_RIGHT_WIDGET );
mitkWidget3->LayoutDesignListChanged( LAYOUT_2D_AND_3D_LEFT_2D_RIGHT_WIDGET );
mitkWidget4->LayoutDesignListChanged( LAYOUT_2D_AND_3D_LEFT_2D_RIGHT_WIDGET );
//update Alle Widgets
this->UpdateAllWidgets();
}
void QmitkStdMultiWidget::changeLayoutTo2DUpAnd3DDown()
{
SMW_INFO << "changing layout to 2D up and 3D down" << std::endl;
//Hide all Menu Widgets
this->HideAllWidgetToolbars();
delete QmitkStdMultiWidgetLayout ;
//create Main Layout
QmitkStdMultiWidgetLayout = new QHBoxLayout( this );
//Set Layout to widget
this->setLayout(QmitkStdMultiWidgetLayout);
//create main splitter
m_MainSplit = new QSplitter( this );
QmitkStdMultiWidgetLayout->addWidget( m_MainSplit );
//create m_LayoutSplit and add to the mainSplit
m_LayoutSplit = new QSplitter( Qt::Vertical, m_MainSplit );
m_MainSplit->addWidget( m_LayoutSplit );
//add LevelWindow Widget to mainSplitter
m_MainSplit->addWidget( levelWindowWidget );
//create m_SubSplit1 and m_SubSplit2
m_SubSplit1 = new QSplitter( m_LayoutSplit );
m_SubSplit2 = new QSplitter( m_LayoutSplit );
//insert Widget Container into splitter top
m_SubSplit1->addWidget( mitkWidget1Container );
//set SplitterSize for splitter top
QList<int> splitterSize;
// splitterSize.push_back(1000);
// splitterSize.push_back(1000);
// splitterSize.push_back(1000);
// m_SubSplit1->setSizes( splitterSize );
//insert Widget Container into splitter bottom
m_SubSplit2->addWidget( mitkWidget4Container );
//set SplitterSize for splitter m_LayoutSplit
splitterSize.clear();
splitterSize.push_back(700);
splitterSize.push_back(700);
m_LayoutSplit->setSizes( splitterSize );
//show mainSplitt
m_MainSplit->show();
//show/hide Widgets
if ( mitkWidget1->isHidden() ) mitkWidget1->show();
mitkWidget2->hide();
mitkWidget3->hide();
if ( mitkWidget4->isHidden() ) mitkWidget4->show();
m_Layout = LAYOUT_2D_UP_AND_3D_DOWN;
//update Layout Design List
mitkWidget1->LayoutDesignListChanged( LAYOUT_2D_UP_AND_3D_DOWN );
mitkWidget2->LayoutDesignListChanged( LAYOUT_2D_UP_AND_3D_DOWN );
mitkWidget3->LayoutDesignListChanged( LAYOUT_2D_UP_AND_3D_DOWN );
mitkWidget4->LayoutDesignListChanged( LAYOUT_2D_UP_AND_3D_DOWN );
//update all Widgets
this->UpdateAllWidgets();
}
void QmitkStdMultiWidget::SetDataStorage( mitk::DataStorage* ds )
{
mitk::BaseRenderer::GetInstance(mitkWidget1->GetRenderWindow())->SetDataStorage(ds);
mitk::BaseRenderer::GetInstance(mitkWidget2->GetRenderWindow())->SetDataStorage(ds);
mitk::BaseRenderer::GetInstance(mitkWidget3->GetRenderWindow())->SetDataStorage(ds);
mitk::BaseRenderer::GetInstance(mitkWidget4->GetRenderWindow())->SetDataStorage(ds);
m_DataStorage = ds;
}
void QmitkStdMultiWidget::Fit()
{
vtkRenderer * vtkrenderer;
mitk::BaseRenderer::GetInstance(mitkWidget1->GetRenderWindow())->GetDisplayGeometry()->Fit();
mitk::BaseRenderer::GetInstance(mitkWidget2->GetRenderWindow())->GetDisplayGeometry()->Fit();
mitk::BaseRenderer::GetInstance(mitkWidget3->GetRenderWindow())->GetDisplayGeometry()->Fit();
mitk::BaseRenderer::GetInstance(mitkWidget4->GetRenderWindow())->GetDisplayGeometry()->Fit();
int w = vtkObject::GetGlobalWarningDisplay();
vtkObject::GlobalWarningDisplayOff();
vtkrenderer = mitk::BaseRenderer::GetInstance(mitkWidget1->GetRenderWindow())->GetVtkRenderer();
if ( vtkrenderer!= NULL )
vtkrenderer->ResetCamera();
vtkrenderer = mitk::BaseRenderer::GetInstance(mitkWidget2->GetRenderWindow())->GetVtkRenderer();
if ( vtkrenderer!= NULL )
vtkrenderer->ResetCamera();
vtkrenderer = mitk::BaseRenderer::GetInstance(mitkWidget3->GetRenderWindow())->GetVtkRenderer();
if ( vtkrenderer!= NULL )
vtkrenderer->ResetCamera();
vtkrenderer = mitk::BaseRenderer::GetInstance(mitkWidget4->GetRenderWindow())->GetVtkRenderer();
if ( vtkrenderer!= NULL )
vtkrenderer->ResetCamera();
vtkObject::SetGlobalWarningDisplay(w);
}
void QmitkStdMultiWidget::InitPositionTracking()
{
//PoinSetNode for MouseOrientation
m_PositionTrackerNode = mitk::DataNode::New();
m_PositionTrackerNode->SetProperty("name", mitk::StringProperty::New("Mouse Position"));
m_PositionTrackerNode->SetData( mitk::PointSet::New() );
m_PositionTrackerNode->SetColor(1.0,0.33,0.0);
m_PositionTrackerNode->SetProperty("layer", mitk::IntProperty::New(1001));
m_PositionTrackerNode->SetVisibility(true);
m_PositionTrackerNode->SetProperty("inputdevice", mitk::BoolProperty::New(true) );
m_PositionTrackerNode->SetProperty("BaseRendererMapperID", mitk::IntProperty::New(0) );//point position 2D mouse
m_PositionTrackerNode->SetProperty("baserenderer", mitk::StringProperty::New("N/A"));
}
void QmitkStdMultiWidget::AddDisplayPlaneSubTree()
{
// add the displayed planes of the multiwidget to a node to which the subtree
// @a planesSubTree points ...
float white[3] = {1.0f,1.0f,1.0f};
- mitk::Geometry2DDataMapper2D::Pointer mapper;
+ mitk::PlaneGeometryDataMapper2D::Pointer mapper;
// ... of widget 1
- m_PlaneNode1 = (mitk::BaseRenderer::GetInstance(mitkWidget1->GetRenderWindow()))->GetCurrentWorldGeometry2DNode();
+ m_PlaneNode1 = (mitk::BaseRenderer::GetInstance(mitkWidget1->GetRenderWindow()))->GetCurrentWorldPlaneGeometryNode();
m_PlaneNode1->SetColor(white, mitk::BaseRenderer::GetInstance(mitkWidget4->GetRenderWindow()));
m_PlaneNode1->SetProperty("visible", mitk::BoolProperty::New(true));
m_PlaneNode1->SetProperty("name", mitk::StringProperty::New("widget1Plane"));
m_PlaneNode1->SetProperty("includeInBoundingBox", mitk::BoolProperty::New(false));
m_PlaneNode1->SetProperty("helper object", mitk::BoolProperty::New(true));
- mapper = mitk::Geometry2DDataMapper2D::New();
+ mapper = mitk::PlaneGeometryDataMapper2D::New();
m_PlaneNode1->SetMapper(mitk::BaseRenderer::Standard2D, mapper);
// ... of widget 2
- m_PlaneNode2 =( mitk::BaseRenderer::GetInstance(mitkWidget2->GetRenderWindow()))->GetCurrentWorldGeometry2DNode();
+ m_PlaneNode2 =( mitk::BaseRenderer::GetInstance(mitkWidget2->GetRenderWindow()))->GetCurrentWorldPlaneGeometryNode();
m_PlaneNode2->SetColor(white, mitk::BaseRenderer::GetInstance(mitkWidget4->GetRenderWindow()));
m_PlaneNode2->SetProperty("visible", mitk::BoolProperty::New(true));
m_PlaneNode2->SetProperty("name", mitk::StringProperty::New("widget2Plane"));
m_PlaneNode2->SetProperty("includeInBoundingBox", mitk::BoolProperty::New(false));
m_PlaneNode2->SetProperty("helper object", mitk::BoolProperty::New(true));
- mapper = mitk::Geometry2DDataMapper2D::New();
+ mapper = mitk::PlaneGeometryDataMapper2D::New();
m_PlaneNode2->SetMapper(mitk::BaseRenderer::Standard2D, mapper);
// ... of widget 3
- m_PlaneNode3 = (mitk::BaseRenderer::GetInstance(mitkWidget3->GetRenderWindow()))->GetCurrentWorldGeometry2DNode();
+ m_PlaneNode3 = (mitk::BaseRenderer::GetInstance(mitkWidget3->GetRenderWindow()))->GetCurrentWorldPlaneGeometryNode();
m_PlaneNode3->SetColor(white, mitk::BaseRenderer::GetInstance(mitkWidget4->GetRenderWindow()));
m_PlaneNode3->SetProperty("visible", mitk::BoolProperty::New(true));
m_PlaneNode3->SetProperty("name", mitk::StringProperty::New("widget3Plane"));
m_PlaneNode3->SetProperty("includeInBoundingBox", mitk::BoolProperty::New(false));
m_PlaneNode3->SetProperty("helper object", mitk::BoolProperty::New(true));
- mapper = mitk::Geometry2DDataMapper2D::New();
+ mapper = mitk::PlaneGeometryDataMapper2D::New();
m_PlaneNode3->SetMapper(mitk::BaseRenderer::Standard2D, mapper);
m_Node = mitk::DataNode::New();
m_Node->SetProperty("name", mitk::StringProperty::New("Widgets"));
m_Node->SetProperty("helper object", mitk::BoolProperty::New(true));
}
mitk::SliceNavigationController* QmitkStdMultiWidget::GetTimeNavigationController()
{
return m_TimeNavigationController;
}
void QmitkStdMultiWidget::EnableStandardLevelWindow()
{
levelWindowWidget->disconnect(this);
levelWindowWidget->SetDataStorage(mitk::BaseRenderer::GetInstance(mitkWidget1->GetRenderWindow())->GetDataStorage());
levelWindowWidget->show();
}
void QmitkStdMultiWidget::DisableStandardLevelWindow()
{
levelWindowWidget->disconnect(this);
levelWindowWidget->hide();
}
// CAUTION: Legacy code for enabling Qt-signal-controlled view initialization.
// Use RenderingManager::InitializeViews() instead.
bool QmitkStdMultiWidget::InitializeStandardViews( const mitk::Geometry3D * geometry )
{
return m_RenderingManager->InitializeViews( geometry );
}
void QmitkStdMultiWidget::RequestUpdate()
{
m_RenderingManager->RequestUpdate(mitkWidget1->GetRenderWindow());
m_RenderingManager->RequestUpdate(mitkWidget2->GetRenderWindow());
m_RenderingManager->RequestUpdate(mitkWidget3->GetRenderWindow());
m_RenderingManager->RequestUpdate(mitkWidget4->GetRenderWindow());
}
void QmitkStdMultiWidget::ForceImmediateUpdate()
{
m_RenderingManager->ForceImmediateUpdate(mitkWidget1->GetRenderWindow());
m_RenderingManager->ForceImmediateUpdate(mitkWidget2->GetRenderWindow());
m_RenderingManager->ForceImmediateUpdate(mitkWidget3->GetRenderWindow());
m_RenderingManager->ForceImmediateUpdate(mitkWidget4->GetRenderWindow());
}
void QmitkStdMultiWidget::wheelEvent( QWheelEvent * e )
{
emit WheelMoved( e );
}
void QmitkStdMultiWidget::mousePressEvent(QMouseEvent * e)
{
if (e->button() == Qt::LeftButton) {
mitk::Point3D pointValue = this->GetLastLeftClickPosition();
emit LeftMouseClicked(pointValue);
}
}
void QmitkStdMultiWidget::moveEvent( QMoveEvent* e )
{
QWidget::moveEvent( e );
// it is necessary to readjust the position of the overlays as the StdMultiWidget has moved
// unfortunately it's not done by QmitkRenderWindow::moveEvent -> must be done here
emit Moved();
}
void QmitkStdMultiWidget::leaveEvent ( QEvent * /*e*/ )
{
//set cursor back to initial state
m_SlicesRotator->ResetMouseCursor();
}
QmitkRenderWindow* QmitkStdMultiWidget::GetRenderWindow1() const
{
return mitkWidget1;
}
QmitkRenderWindow* QmitkStdMultiWidget::GetRenderWindow2() const
{
return mitkWidget2;
}
QmitkRenderWindow* QmitkStdMultiWidget::GetRenderWindow3() const
{
return mitkWidget3;
}
QmitkRenderWindow* QmitkStdMultiWidget::GetRenderWindow4() const
{
return mitkWidget4;
}
const mitk::Point3D& QmitkStdMultiWidget::GetLastLeftClickPosition() const
{
return m_LastLeftClickPositionSupplier->GetCurrentPoint();
}
const mitk::Point3D QmitkStdMultiWidget::GetCrossPosition() const
{
const mitk::PlaneGeometry *plane1 =
mitkWidget1->GetSliceNavigationController()->GetCurrentPlaneGeometry();
const mitk::PlaneGeometry *plane2 =
mitkWidget2->GetSliceNavigationController()->GetCurrentPlaneGeometry();
const mitk::PlaneGeometry *plane3 =
mitkWidget3->GetSliceNavigationController()->GetCurrentPlaneGeometry();
mitk::Line3D line;
if ( (plane1 != NULL) && (plane2 != NULL)
&& (plane1->IntersectionLine( plane2, line )) )
{
mitk::Point3D point;
if ( (plane3 != NULL)
&& (plane3->IntersectionPoint( line, point )) )
{
return point;
}
}
return m_LastLeftClickPositionSupplier->GetCurrentPoint();
}
void QmitkStdMultiWidget::EnablePositionTracking()
{
if (!m_PositionTracker)
{
m_PositionTracker = mitk::PositionTracker::New("PositionTracker", NULL);
}
mitk::GlobalInteraction* globalInteraction = mitk::GlobalInteraction::GetInstance();
if (globalInteraction)
{
if(m_DataStorage.IsNotNull())
m_DataStorage->Add(m_PositionTrackerNode);
globalInteraction->AddListener(m_PositionTracker);
}
}
void QmitkStdMultiWidget::DisablePositionTracking()
{
mitk::GlobalInteraction* globalInteraction =
mitk::GlobalInteraction::GetInstance();
if(globalInteraction)
{
if (m_DataStorage.IsNotNull())
m_DataStorage->Remove(m_PositionTrackerNode);
globalInteraction->RemoveListener(m_PositionTracker);
}
}
void QmitkStdMultiWidget::EnsureDisplayContainsPoint(
mitk::DisplayGeometry* displayGeometry, const mitk::Point3D& p)
{
mitk::Point2D pointOnPlane;
displayGeometry->Map( p, pointOnPlane );
// point minus origin < width or height ==> outside ?
mitk::Vector2D pointOnRenderWindow_MM;
pointOnRenderWindow_MM = pointOnPlane.GetVectorFromOrigin()
- displayGeometry->GetOriginInMM();
mitk::Vector2D sizeOfDisplay( displayGeometry->GetSizeInMM() );
if ( sizeOfDisplay[0] < pointOnRenderWindow_MM[0]
|| 0 > pointOnRenderWindow_MM[0]
|| sizeOfDisplay[1] < pointOnRenderWindow_MM[1]
|| 0 > pointOnRenderWindow_MM[1] )
{
// point is not visible -> move geometry
mitk::Vector2D offset( (pointOnRenderWindow_MM - sizeOfDisplay / 2.0)
/ displayGeometry->GetScaleFactorMMPerDisplayUnit() );
displayGeometry->MoveBy( offset );
}
}
void QmitkStdMultiWidget::MoveCrossToPosition(const mitk::Point3D& newPosition)
{
// create a PositionEvent with the given position and
// tell the slice navigation controllers to move there
mitk::Point2D p2d;
mitk::PositionEvent event( mitk::BaseRenderer::GetInstance(mitkWidget1->GetRenderWindow()), 0, 0, 0,
mitk::Key_unknown, p2d, newPosition );
mitk::StateEvent stateEvent(mitk::EIDLEFTMOUSEBTN, &event);
mitk::StateEvent stateEvent2(mitk::EIDLEFTMOUSERELEASE, &event);
switch ( m_PlaneMode )
{
default:
case PLANE_MODE_SLICING:
mitkWidget1->GetSliceNavigationController()->HandleEvent( &stateEvent );
mitkWidget2->GetSliceNavigationController()->HandleEvent( &stateEvent );
mitkWidget3->GetSliceNavigationController()->HandleEvent( &stateEvent );
// just in case SNCs will develop something that depends on the mouse
// button being released again
mitkWidget1->GetSliceNavigationController()->HandleEvent( &stateEvent2 );
mitkWidget2->GetSliceNavigationController()->HandleEvent( &stateEvent2 );
mitkWidget3->GetSliceNavigationController()->HandleEvent( &stateEvent2 );
break;
case PLANE_MODE_ROTATION:
m_SlicesRotator->HandleEvent( &stateEvent );
// just in case SNCs will develop something that depends on the mouse
// button being released again
m_SlicesRotator->HandleEvent( &stateEvent2 );
break;
case PLANE_MODE_SWIVEL:
m_SlicesSwiveller->HandleEvent( &stateEvent );
// just in case SNCs will develop something that depends on the mouse
// button being released again
m_SlicesSwiveller->HandleEvent( &stateEvent2 );
break;
}
// determine if cross is now out of display
// if so, move the display window
EnsureDisplayContainsPoint( mitk::BaseRenderer::GetInstance(mitkWidget1->GetRenderWindow())
->GetDisplayGeometry(), newPosition );
EnsureDisplayContainsPoint( mitk::BaseRenderer::GetInstance(mitkWidget2->GetRenderWindow())
->GetDisplayGeometry(), newPosition );
EnsureDisplayContainsPoint( mitk::BaseRenderer::GetInstance(mitkWidget3->GetRenderWindow())
->GetDisplayGeometry(), newPosition );
// update displays
m_RenderingManager->RequestUpdateAll();
}
void QmitkStdMultiWidget::HandleCrosshairPositionEvent()
{
if(!m_PendingCrosshairPositionEvent)
{
m_PendingCrosshairPositionEvent=true;
QTimer::singleShot(0,this,SLOT( HandleCrosshairPositionEventDelayed() ) );
}
}
mitk::DataNode::Pointer QmitkStdMultiWidget::GetTopLayerNode(mitk::DataStorage::SetOfObjects::ConstPointer nodes)
{
mitk::Point3D crosshairPos = this->GetCrossPosition();
mitk::DataNode::Pointer node;
int maxlayer = -32768;
if(nodes.IsNotNull())
{
mitk::BaseRenderer* baseRenderer = this->mitkWidget1->GetSliceNavigationController()->GetRenderer();
// find node with largest layer, that is the node shown on top in the render window
for (unsigned int x = 0; x < nodes->size(); x++)
{
if ( (nodes->at(x)->GetData()->GetGeometry() != NULL) &&
nodes->at(x)->GetData()->GetGeometry()->IsInside(crosshairPos) )
{
int layer = 0;
if(!(nodes->at(x)->GetIntProperty("layer", layer))) continue;
if(layer > maxlayer)
{
if( static_cast<mitk::DataNode::Pointer>(nodes->at(x))->IsVisible( baseRenderer ) )
{
node = nodes->at(x);
maxlayer = layer;
}
}
}
}
}
return node;
}
void QmitkStdMultiWidget::HandleCrosshairPositionEventDelayed()
{
m_PendingCrosshairPositionEvent = false;
// find image with highest layer
mitk::TNodePredicateDataType<mitk::Image>::Pointer isImageData = mitk::TNodePredicateDataType<mitk::Image>::New();
mitk::DataStorage::SetOfObjects::ConstPointer nodes = this->m_DataStorage->GetSubset(isImageData).GetPointer();
mitk::DataNode::Pointer node;
mitk::DataNode::Pointer topSourceNode;
mitk::Image::Pointer image;
bool isBinary = false;
node = this->GetTopLayerNode(nodes);
if(node.IsNotNull())
{
node->GetBoolProperty("binary",isBinary);
if(isBinary)
{
mitk::DataStorage::SetOfObjects::ConstPointer sourcenodes = m_DataStorage->GetSources(node, NULL, true);
if(!sourcenodes->empty())
{
topSourceNode = this->GetTopLayerNode(sourcenodes);
}
if(topSourceNode.IsNotNull())
{
image = dynamic_cast<mitk::Image*>(topSourceNode->GetData());
}
else
{
image = dynamic_cast<mitk::Image*>(node->GetData());
}
}
else
{
image = dynamic_cast<mitk::Image*>(node->GetData());
}
}
mitk::Point3D crosshairPos = this->GetCrossPosition();
std::string statusText;
std::stringstream stream;
mitk::Index3D p;
mitk::BaseRenderer* baseRenderer = this->mitkWidget1->GetSliceNavigationController()->GetRenderer();
unsigned int timestep = baseRenderer->GetTimeStep();
if(image.IsNotNull() && (image->GetTimeSteps() > timestep ))
{
image->GetGeometry()->WorldToIndex(crosshairPos, p);
stream.precision(2);
stream<<"Position: <" << std::fixed <<crosshairPos[0] << ", " << std::fixed << crosshairPos[1] << ", " << std::fixed << crosshairPos[2] << "> mm";
stream<<"; Index: <"<<p[0] << ", " << p[1] << ", " << p[2] << "> ";
mitk::ScalarType pixelValue = image->GetPixelValueByIndex(p, timestep);
if (fabs(pixelValue)>1000000 || fabs(pixelValue) < 0.01)
{
stream<<"; Time: " << baseRenderer->GetTime() << " ms; Pixelvalue: "<< std::scientific<< pixelValue <<" ";
}
else
{
stream<<"; Time: " << baseRenderer->GetTime() << " ms; Pixelvalue: "<< pixelValue <<" ";
}
}
else
{
stream << "No image information at this position!";
}
statusText = stream.str();
mitk::StatusBar::GetInstance()->DisplayGreyValueText(statusText.c_str());
}
void QmitkStdMultiWidget::EnableNavigationControllerEventListening()
{
// Let NavigationControllers listen to GlobalInteraction
mitk::GlobalInteraction *gi = mitk::GlobalInteraction::GetInstance();
// Listen for SliceNavigationController
mitkWidget1->GetSliceNavigationController()->crosshairPositionEvent.AddListener( mitk::MessageDelegate<QmitkStdMultiWidget>( this, &QmitkStdMultiWidget::HandleCrosshairPositionEvent ) );
mitkWidget2->GetSliceNavigationController()->crosshairPositionEvent.AddListener( mitk::MessageDelegate<QmitkStdMultiWidget>( this, &QmitkStdMultiWidget::HandleCrosshairPositionEvent ) );
mitkWidget3->GetSliceNavigationController()->crosshairPositionEvent.AddListener( mitk::MessageDelegate<QmitkStdMultiWidget>( this, &QmitkStdMultiWidget::HandleCrosshairPositionEvent ) );
switch ( m_PlaneMode )
{
default:
case PLANE_MODE_SLICING:
gi->AddListener( mitkWidget1->GetSliceNavigationController() );
gi->AddListener( mitkWidget2->GetSliceNavigationController() );
gi->AddListener( mitkWidget3->GetSliceNavigationController() );
gi->AddListener( mitkWidget4->GetSliceNavigationController() );
break;
case PLANE_MODE_ROTATION:
gi->AddListener( m_SlicesRotator );
break;
case PLANE_MODE_SWIVEL:
gi->AddListener( m_SlicesSwiveller );
break;
}
gi->AddListener( m_TimeNavigationController );
m_CrosshairNavigationEnabled = true;
}
void QmitkStdMultiWidget::DisableNavigationControllerEventListening()
{
// Do not let NavigationControllers listen to GlobalInteraction
mitk::GlobalInteraction *gi = mitk::GlobalInteraction::GetInstance();
switch ( m_PlaneMode )
{
default:
case PLANE_MODE_SLICING:
gi->RemoveListener( mitkWidget1->GetSliceNavigationController() );
gi->RemoveListener( mitkWidget2->GetSliceNavigationController() );
gi->RemoveListener( mitkWidget3->GetSliceNavigationController() );
gi->RemoveListener( mitkWidget4->GetSliceNavigationController() );
break;
case PLANE_MODE_ROTATION:
m_SlicesRotator->ResetMouseCursor();
gi->RemoveListener( m_SlicesRotator );
break;
case PLANE_MODE_SWIVEL:
m_SlicesSwiveller->ResetMouseCursor();
gi->RemoveListener( m_SlicesSwiveller );
break;
}
gi->RemoveListener( m_TimeNavigationController );
m_CrosshairNavigationEnabled = false;
}
int QmitkStdMultiWidget::GetLayout() const
{
return m_Layout;
}
bool QmitkStdMultiWidget::GetGradientBackgroundFlag() const
{
return m_GradientBackgroundFlag;
}
void QmitkStdMultiWidget::EnableGradientBackground()
{
// gradient background is by default only in widget 4, otherwise
// interferences between 2D rendering and VTK rendering may occur.
//m_GradientBackground1->Enable();
//m_GradientBackground2->Enable();
//m_GradientBackground3->Enable();
m_GradientBackground4->Enable();
m_GradientBackgroundFlag = true;
}
void QmitkStdMultiWidget::DisableGradientBackground()
{
//m_GradientBackground1->Disable();
//m_GradientBackground2->Disable();
//m_GradientBackground3->Disable();
m_GradientBackground4->Disable();
m_GradientBackgroundFlag = false;
}
void QmitkStdMultiWidget::EnableDepartmentLogo()
{
m_LogoRendering4->Enable();
}
void QmitkStdMultiWidget::DisableDepartmentLogo()
{
m_LogoRendering4->Disable();
}
bool QmitkStdMultiWidget::IsDepartmentLogoEnabled() const
{
return m_LogoRendering4->IsEnabled();
}
bool QmitkStdMultiWidget::IsCrosshairNavigationEnabled() const
{
return m_CrosshairNavigationEnabled;
}
mitk::SlicesRotator * QmitkStdMultiWidget::GetSlicesRotator() const
{
return m_SlicesRotator;
}
mitk::SlicesSwiveller * QmitkStdMultiWidget::GetSlicesSwiveller() const
{
return m_SlicesSwiveller;
}
void QmitkStdMultiWidget::SetWidgetPlaneVisibility(const char* widgetName, bool visible, mitk::BaseRenderer *renderer)
{
if (m_DataStorage.IsNotNull())
{
mitk::DataNode* n = m_DataStorage->GetNamedNode(widgetName);
if (n != NULL)
n->SetVisibility(visible, renderer);
}
}
void QmitkStdMultiWidget::SetWidgetPlanesVisibility(bool visible, mitk::BaseRenderer *renderer)
{
SetWidgetPlaneVisibility("widget1Plane", visible, renderer);
SetWidgetPlaneVisibility("widget2Plane", visible, renderer);
SetWidgetPlaneVisibility("widget3Plane", visible, renderer);
m_RenderingManager->RequestUpdateAll();
}
void QmitkStdMultiWidget::SetWidgetPlanesLocked(bool locked)
{
//do your job and lock or unlock slices.
GetRenderWindow1()->GetSliceNavigationController()->SetSliceLocked(locked);
GetRenderWindow2()->GetSliceNavigationController()->SetSliceLocked(locked);
GetRenderWindow3()->GetSliceNavigationController()->SetSliceLocked(locked);
}
void QmitkStdMultiWidget::SetWidgetPlanesRotationLocked(bool locked)
{
//do your job and lock or unlock slices.
GetRenderWindow1()->GetSliceNavigationController()->SetSliceRotationLocked(locked);
GetRenderWindow2()->GetSliceNavigationController()->SetSliceRotationLocked(locked);
GetRenderWindow3()->GetSliceNavigationController()->SetSliceRotationLocked(locked);
}
void QmitkStdMultiWidget::SetWidgetPlanesRotationLinked( bool link )
{
m_SlicesRotator->SetLinkPlanes( link );
m_SlicesSwiveller->SetLinkPlanes( link );
emit WidgetPlanesRotationLinked( link );
}
void QmitkStdMultiWidget::SetWidgetPlaneMode( int userMode )
{
MITK_DEBUG << "Changing crosshair mode to " << userMode;
// first of all reset left mouse button interaction to default if PACS interaction style is active
m_MouseModeSwitcher->SelectMouseMode( mitk::MouseModeSwitcher::MousePointer );
emit WidgetNotifyNewCrossHairMode( userMode );
int mode = m_PlaneMode;
bool link = false;
// Convert user interface mode to actual mode
{
switch(userMode)
{
case 0:
mode = PLANE_MODE_SLICING;
link = false;
break;
case 1:
mode = PLANE_MODE_ROTATION;
link = false;
break;
case 2:
mode = PLANE_MODE_ROTATION;
link = true;
break;
case 3:
mode = PLANE_MODE_SWIVEL;
link = false;
break;
}
}
// Slice rotation linked
m_SlicesRotator->SetLinkPlanes( link );
m_SlicesSwiveller->SetLinkPlanes( link );
// Do nothing if mode didn't change
if ( m_PlaneMode == mode )
{
return;
}
mitk::GlobalInteraction *gi = mitk::GlobalInteraction::GetInstance();
// Remove listeners of previous mode
switch ( m_PlaneMode )
{
default:
case PLANE_MODE_SLICING:
// Notify MainTemplate GUI that this mode has been deselected
emit WidgetPlaneModeSlicing( false );
gi->RemoveListener( mitkWidget1->GetSliceNavigationController() );
gi->RemoveListener( mitkWidget2->GetSliceNavigationController() );
gi->RemoveListener( mitkWidget3->GetSliceNavigationController() );
gi->RemoveListener( mitkWidget4->GetSliceNavigationController() );
break;
case PLANE_MODE_ROTATION:
// Notify MainTemplate GUI that this mode has been deselected
emit WidgetPlaneModeRotation( false );
m_SlicesRotator->ResetMouseCursor();
gi->RemoveListener( m_SlicesRotator );
break;
case PLANE_MODE_SWIVEL:
// Notify MainTemplate GUI that this mode has been deselected
emit WidgetPlaneModeSwivel( false );
m_SlicesSwiveller->ResetMouseCursor();
gi->RemoveListener( m_SlicesSwiveller );
break;
}
// Set new mode and add corresponding listener to GlobalInteraction
m_PlaneMode = mode;
switch ( m_PlaneMode )
{
default:
case PLANE_MODE_SLICING:
// Notify MainTemplate GUI that this mode has been selected
emit WidgetPlaneModeSlicing( true );
// Add listeners
gi->AddListener( mitkWidget1->GetSliceNavigationController() );
gi->AddListener( mitkWidget2->GetSliceNavigationController() );
gi->AddListener( mitkWidget3->GetSliceNavigationController() );
gi->AddListener( mitkWidget4->GetSliceNavigationController() );
m_RenderingManager->InitializeViews();
break;
case PLANE_MODE_ROTATION:
// Notify MainTemplate GUI that this mode has been selected
emit WidgetPlaneModeRotation( true );
// Add listener
gi->AddListener( m_SlicesRotator );
break;
case PLANE_MODE_SWIVEL:
// Notify MainTemplate GUI that this mode has been selected
emit WidgetPlaneModeSwivel( true );
// Add listener
gi->AddListener( m_SlicesSwiveller );
break;
}
// Notify MainTemplate GUI that mode has changed
emit WidgetPlaneModeChange(m_PlaneMode);
}
void QmitkStdMultiWidget::SetGradientBackgroundColors( const mitk::Color & upper, const mitk::Color & lower )
{
m_GradientBackground1->SetGradientColors(upper[0], upper[1], upper[2], lower[0], lower[1], lower[2]);
m_GradientBackground2->SetGradientColors(upper[0], upper[1], upper[2], lower[0], lower[1], lower[2]);
m_GradientBackground3->SetGradientColors(upper[0], upper[1], upper[2], lower[0], lower[1], lower[2]);
m_GradientBackground4->SetGradientColors(upper[0], upper[1], upper[2], lower[0], lower[1], lower[2]);
m_GradientBackgroundFlag = true;
}
void QmitkStdMultiWidget::SetDepartmentLogoPath( const char * path )
{
m_LogoRendering1->SetLogoSource(path);
m_LogoRendering2->SetLogoSource(path);
m_LogoRendering3->SetLogoSource(path);
m_LogoRendering4->SetLogoSource(path);
}
void QmitkStdMultiWidget::SetWidgetPlaneModeToSlicing( bool activate )
{
if ( activate )
{
this->SetWidgetPlaneMode( PLANE_MODE_SLICING );
}
}
void QmitkStdMultiWidget::SetWidgetPlaneModeToRotation( bool activate )
{
if ( activate )
{
this->SetWidgetPlaneMode( PLANE_MODE_ROTATION );
}
}
void QmitkStdMultiWidget::SetWidgetPlaneModeToSwivel( bool activate )
{
if ( activate )
{
this->SetWidgetPlaneMode( PLANE_MODE_SWIVEL );
}
}
void QmitkStdMultiWidget::OnLayoutDesignChanged( int layoutDesignIndex )
{
switch( layoutDesignIndex )
{
case LAYOUT_DEFAULT:
{
this->changeLayoutToDefault();
break;
}
case LAYOUT_2D_IMAGES_UP:
{
this->changeLayoutTo2DImagesUp();
break;
}
case LAYOUT_2D_IMAGES_LEFT:
{
this->changeLayoutTo2DImagesLeft();
break;
}
case LAYOUT_BIG_3D:
{
this->changeLayoutToBig3D();
break;
}
case LAYOUT_WIDGET1:
{
this->changeLayoutToWidget1();
break;
}
case LAYOUT_WIDGET2:
{
this->changeLayoutToWidget2();
break;
}
case LAYOUT_WIDGET3:
{
this->changeLayoutToWidget3();
break;
}
case LAYOUT_2X_2D_AND_3D_WIDGET:
{
this->changeLayoutTo2x2Dand3DWidget();
break;
}
case LAYOUT_ROW_WIDGET_3_AND_4:
{
this->changeLayoutToRowWidget3And4();
break;
}
case LAYOUT_COLUMN_WIDGET_3_AND_4:
{
this->changeLayoutToColumnWidget3And4();
break;
}
case LAYOUT_ROW_WIDGET_SMALL3_AND_BIG4:
{
this->changeLayoutToRowWidgetSmall3andBig4();
break;
}
case LAYOUT_SMALL_UPPER_WIDGET2_BIG3_AND4:
{
this->changeLayoutToSmallUpperWidget2Big3and4();
break;
}
case LAYOUT_2D_AND_3D_LEFT_2D_RIGHT_WIDGET:
{
this->changeLayoutToLeft2Dand3DRight2D();
break;
}
};
}
void QmitkStdMultiWidget::UpdateAllWidgets()
{
mitkWidget1->resize( mitkWidget1Container->frameSize().width()-1, mitkWidget1Container->frameSize().height() );
mitkWidget1->resize( mitkWidget1Container->frameSize().width(), mitkWidget1Container->frameSize().height() );
mitkWidget2->resize( mitkWidget2Container->frameSize().width()-1, mitkWidget2Container->frameSize().height() );
mitkWidget2->resize( mitkWidget2Container->frameSize().width(), mitkWidget2Container->frameSize().height() );
mitkWidget3->resize( mitkWidget3Container->frameSize().width()-1, mitkWidget3Container->frameSize().height() );
mitkWidget3->resize( mitkWidget3Container->frameSize().width(), mitkWidget3Container->frameSize().height() );
mitkWidget4->resize( mitkWidget4Container->frameSize().width()-1, mitkWidget4Container->frameSize().height() );
mitkWidget4->resize( mitkWidget4Container->frameSize().width(), mitkWidget4Container->frameSize().height() );
}
void QmitkStdMultiWidget::HideAllWidgetToolbars()
{
mitkWidget1->HideRenderWindowMenu();
mitkWidget2->HideRenderWindowMenu();
mitkWidget3->HideRenderWindowMenu();
mitkWidget4->HideRenderWindowMenu();
}
void QmitkStdMultiWidget::ActivateMenuWidget( bool state )
{
mitkWidget1->ActivateMenuWidget( state, this );
mitkWidget2->ActivateMenuWidget( state, this );
mitkWidget3->ActivateMenuWidget( state, this );
mitkWidget4->ActivateMenuWidget( state, this );
}
bool QmitkStdMultiWidget::IsMenuWidgetEnabled() const
{
return mitkWidget1->GetActivateMenuWidgetFlag();
}
void QmitkStdMultiWidget::ResetCrosshair()
{
if (m_DataStorage.IsNotNull())
{
m_RenderingManager->InitializeViewsByBoundingObjects(m_DataStorage);
//m_RenderingManager->InitializeViews( m_DataStorage->ComputeVisibleBoundingGeometry3D() );
// reset interactor to normal slicing
this->SetWidgetPlaneMode(PLANE_MODE_SLICING);
}
}
void QmitkStdMultiWidget::EnableColoredRectangles()
{
m_RectangleRendering1->Enable(1.0, 0.0, 0.0);
m_RectangleRendering2->Enable(0.0, 1.0, 0.0);
m_RectangleRendering3->Enable(0.0, 0.0, 1.0);
m_RectangleRendering4->Enable(1.0, 1.0, 0.0);
}
void QmitkStdMultiWidget::DisableColoredRectangles()
{
m_RectangleRendering1->Disable();
m_RectangleRendering2->Disable();
m_RectangleRendering3->Disable();
m_RectangleRendering4->Disable();
}
bool QmitkStdMultiWidget::IsColoredRectanglesEnabled() const
{
return m_RectangleRendering1->IsEnabled();
}
mitk::MouseModeSwitcher* QmitkStdMultiWidget::GetMouseModeSwitcher()
{
return m_MouseModeSwitcher;
}
void QmitkStdMultiWidget::MouseModeSelected( mitk::MouseModeSwitcher::MouseMode mouseMode )
{
if ( mouseMode == 0 )
{
this->EnableNavigationControllerEventListening();
}
else
{
this->DisableNavigationControllerEventListening();
}
}
mitk::DataNode::Pointer QmitkStdMultiWidget::GetWidgetPlane1()
{
return this->m_PlaneNode1;
}
mitk::DataNode::Pointer QmitkStdMultiWidget::GetWidgetPlane2()
{
return this->m_PlaneNode2;
}
mitk::DataNode::Pointer QmitkStdMultiWidget::GetWidgetPlane3()
{
return this->m_PlaneNode3;
}
mitk::DataNode::Pointer QmitkStdMultiWidget::GetWidgetPlane(int id)
{
switch(id)
{
case 1: return this->m_PlaneNode1;
break;
case 2: return this->m_PlaneNode2;
break;
case 3: return this->m_PlaneNode3;
break;
default: return NULL;
}
}
\ No newline at end of file
diff --git a/Modules/QtWidgetsExt/QmitkSliceWidget.cpp b/Modules/QtWidgetsExt/QmitkSliceWidget.cpp
index 83b8f93df3..cdaa71d8e2 100644
--- a/Modules/QtWidgetsExt/QmitkSliceWidget.cpp
+++ b/Modules/QtWidgetsExt/QmitkSliceWidget.cpp
@@ -1,290 +1,289 @@
/*===================================================================
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 "QmitkSliceWidget.h"
#include "QmitkStepperAdapter.h"
#include "mitkNodePredicateDataType.h"
#include "mitkImage.h"
#include <mitkProportionalTimeGeometry.h>
#include <QMenu>
#include <QMouseEvent>
QmitkSliceWidget::QmitkSliceWidget(QWidget* parent, const char* name,
Qt::WindowFlags f) :
QWidget(parent, f)
{
this->setupUi(this);
if (name != 0)
this->setObjectName(name);
popUp = new QMenu(this);
popUp->addAction("Axial");
popUp->addAction("Frontal");
popUp->addAction("Sagittal");
QObject::connect(popUp, SIGNAL(triggered(QAction*)), this, SLOT(ChangeView(QAction*)) );
setPopUpEnabled(false);
m_SlicedGeometry = 0;
m_View = mitk::SliceNavigationController::Axial;
QHBoxLayout *hlayout = new QHBoxLayout(container);
hlayout->setMargin(0);
// create widget
QString composedName("QmitkSliceWidget::");
if (!this->objectName().isEmpty())
composedName += this->objectName();
else
composedName += "QmitkGLWidget";
m_RenderWindow = new QmitkRenderWindow(container, composedName);
m_Renderer = m_RenderWindow->GetRenderer();
hlayout->addWidget(m_RenderWindow);
new QmitkStepperAdapter(m_NavigatorWidget,
m_RenderWindow->GetSliceNavigationController()->GetSlice(),
"navigation");
SetLevelWindowEnabled(true);
-
}
mitk::VtkPropRenderer* QmitkSliceWidget::GetRenderer()
{
return m_Renderer;
}
QFrame* QmitkSliceWidget::GetSelectionFrame()
{
return SelectionFrame;
}
void QmitkSliceWidget::SetDataStorage(
mitk::StandaloneDataStorage::Pointer storage)
{
m_DataStorage = storage;
m_Renderer->SetDataStorage(m_DataStorage);
}
mitk::StandaloneDataStorage* QmitkSliceWidget::GetDataStorage()
{
return m_DataStorage;
}
void QmitkSliceWidget::SetData(
mitk::DataStorage::SetOfObjects::ConstIterator it)
{
SetData(it->Value(), m_View);
}
void QmitkSliceWidget::SetData(
mitk::DataStorage::SetOfObjects::ConstIterator it,
mitk::SliceNavigationController::ViewDirection view)
{
SetData(it->Value(), view);
}
void QmitkSliceWidget::SetData(mitk::DataNode::Pointer node)
{
try
{
if (m_DataStorage.IsNotNull())
{
m_DataStorage->Add(node);
}
} catch (...)
{
}
SetData(node, m_View);
}
void QmitkSliceWidget::SetData(mitk::DataNode::Pointer node,
mitk::SliceNavigationController::ViewDirection view)
{
mitk::Image::Pointer image = dynamic_cast<mitk::Image*>(node->GetData());
if (image.IsNull())
{
MITK_WARN << "QmitkSliceWidget data is not an image!";
return;
}
m_SlicedGeometry = image->GetSlicedGeometry();
this->InitWidget(view);
}
void QmitkSliceWidget::InitWidget(
mitk::SliceNavigationController::ViewDirection viewDirection)
{
m_View = viewDirection;
mitk::SliceNavigationController* controller =
m_RenderWindow->GetSliceNavigationController();
if (viewDirection == mitk::SliceNavigationController::Axial)
{
controller->SetViewDirection(
mitk::SliceNavigationController::Axial);
}
else if (viewDirection == mitk::SliceNavigationController::Frontal)
{
controller->SetViewDirection(mitk::SliceNavigationController::Frontal);
}
// init sagittal view
else
{
controller->SetViewDirection(mitk::SliceNavigationController::Sagittal);
}
if (m_SlicedGeometry.IsNull())
{
return;
}
- mitk::Geometry3D::Pointer geometry =
- static_cast<mitk::Geometry3D*> (m_SlicedGeometry->Clone().GetPointer());
+
+ mitk::BaseGeometry::Pointer geometry =
+ static_cast<mitk::BaseGeometry*> (m_SlicedGeometry->Clone().GetPointer());
const mitk::BoundingBox::Pointer boundingbox =
m_DataStorage->ComputeVisibleBoundingBox(GetRenderer(), NULL);
if (boundingbox->GetPoints()->Size() > 0)
{
//let's see if we have data with a limited live-span ...
mitk::TimeBounds timebounds = m_DataStorage->ComputeTimeBounds(
GetRenderer(), NULL);
+ mitk::ProportionalTimeGeometry::Pointer timeGeometry = mitk::ProportionalTimeGeometry::New();
+ timeGeometry->Initialize(geometry, 1);
+
if (timebounds[1] < mitk::ScalarTypeNumericTraits::max())
{
- timebounds[1] = timebounds[0] + 1.0f;
- geometry->SetTimeBounds(timebounds);
+ timeGeometry->SetFirstTimePoint(timebounds[0]);
+ timeGeometry->SetStepDuration(1.0);
}
- mitk::ProportionalTimeGeometry::Pointer timeGeometry = mitk::ProportionalTimeGeometry::New();
- timeGeometry->Initialize(geometry,1);
-
if (const_cast<mitk::BoundingBox*> (timeGeometry->GetBoundingBoxInWorld())->GetDiagonalLength2()
>= mitk::eps)
{
controller->SetInputWorldTimeGeometry(timeGeometry);
controller->Update();
}
}
GetRenderer()->GetDisplayGeometry()->Fit();
mitk::RenderingManager::GetInstance()->RequestUpdate(
GetRenderer()->GetRenderWindow());
}
void QmitkSliceWidget::UpdateGL()
{
GetRenderer()->GetDisplayGeometry()->Fit();
mitk::RenderingManager::GetInstance()->RequestUpdate(
GetRenderer()->GetRenderWindow());
}
void QmitkSliceWidget::mousePressEvent(QMouseEvent * e)
{
if (e->button() == Qt::RightButton && popUpEnabled)
{
popUp->popup(QCursor::pos());
}
}
void QmitkSliceWidget::wheelEvent(QWheelEvent * e)
{
int val = m_NavigatorWidget->GetPos();
if (e->orientation() * e->delta() > 0)
{
m_NavigatorWidget->SetPos(val + 1);
}
else
{
if (val > 0)
m_NavigatorWidget->SetPos(val - 1);
}
}
void QmitkSliceWidget::ChangeView(QAction* val)
{
if (val->text() == "Axial")
{
InitWidget(mitk::SliceNavigationController::Axial);
}
else if (val->text() == "Frontal")
{
InitWidget(mitk::SliceNavigationController::Frontal);
}
else if (val->text() == "Sagittal")
{
InitWidget(mitk::SliceNavigationController::Sagittal);
}
}
void QmitkSliceWidget::setPopUpEnabled(bool b)
{
popUpEnabled = b;
}
QmitkSliderNavigatorWidget* QmitkSliceWidget::GetNavigatorWidget()
{
return m_NavigatorWidget;
}
void QmitkSliceWidget::SetLevelWindowEnabled(bool enable)
{
levelWindow->setEnabled(enable);
if (!enable)
{
levelWindow->setMinimumWidth(0);
levelWindow->setMaximumWidth(0);
}
else
{
levelWindow->setMinimumWidth(28);
levelWindow->setMaximumWidth(28);
}
}
bool QmitkSliceWidget::IsLevelWindowEnabled()
{
return levelWindow->isEnabled();
}
QmitkRenderWindow* QmitkSliceWidget::GetRenderWindow()
{
return m_RenderWindow;
}
mitk::SliceNavigationController*
QmitkSliceWidget::GetSliceNavigationController() const
{
return m_RenderWindow->GetSliceNavigationController();
}
mitk::CameraRotationController*
QmitkSliceWidget::GetCameraRotationController() const
{
return m_RenderWindow->GetCameraRotationController();
}
mitk::BaseController*
QmitkSliceWidget::GetController() const
{
return m_RenderWindow->GetController();
}
-
diff --git a/Modules/SceneSerializationBase/Testing/mitkPropertySerializationTest.cpp b/Modules/SceneSerializationBase/Testing/mitkPropertySerializationTest.cpp
index 937b3e8e57..2c98b3808d 100644
--- a/Modules/SceneSerializationBase/Testing/mitkPropertySerializationTest.cpp
+++ b/Modules/SceneSerializationBase/Testing/mitkPropertySerializationTest.cpp
@@ -1,266 +1,266 @@
/*===================================================================
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 "mitkTestingMacros.h"
#include "mitkDataNodeFactory.h"
#include "mitkCoreObjectFactory.h"
#include "mitkBaseProperty.h"
#include "mitkProperties.h"
#include <mitkAnnotationProperty.h>
#include <mitkClippingProperty.h>
#include <mitkColorProperty.h>
#include <mitkEnumerationProperty.h>
/*
#include <mitkGridRepresentationProperty.h>
#include <mitkGridVolumeMapperProperty.h>
#include <mitkOrganTypeProperty.h>
*/
#include <mitkModalityProperty.h>
//#include <mitkOdfNormalizationMethodProperty.h>
//#include <mitkOdfScaleByProperty.h>
#include <mitkPlaneOrientationProperty.h>
#include <mitkShaderProperty.h>
#include <mitkVtkInterpolationProperty.h>
#include <mitkVtkRepresentationProperty.h>
#include <mitkVtkResliceInterpolationProperty.h>
#include <mitkVtkScalarModeProperty.h>
#include <mitkVtkVolumeRenderingProperty.h>
#include <mitkGroupTagProperty.h>
#include <mitkLevelWindowProperty.h>
#include <mitkLookupTableProperty.h>
#include <mitkStringProperty.h>
#include <mitkTransferFunctionProperty.h>
#include "mitkPropertyList.h"
#include "mitkPropertyListSerializer.h"
#include "mitkBasePropertySerializer.h"
#include <mitkPointSet.h>
#include <mitkImage.h>
#include <mitkSurface.h>
#include <mitkVtkWidgetRendering.h>
/*
#include <mitkContour.h>
#include <mitkContourSet.h>
#include <mitkMesh.h>
#include <mitkCone.h>
#include <mitkCuboid.h>
#include <mitkCylinder.h>
#include <mitkEllipsoid.h>
#include <mitkExtrudedContour.h>
#include <mitkPlane.h>
#include <mitkUnstructuredGrid.h>
*/
void TestAllProperties(const mitk::PropertyList* propList);
/**Documentation
* \brief Test for all PropertySerializer classes.
*
*/
int mitkPropertySerializationTest(int /* argc */, char* /*argv*/[])
{
MITK_TEST_BEGIN("PropertySerializationTest");
mitk::PropertyListSerializer::Pointer serializer = mitk::PropertyListSerializer::New(); // make sure something from the lib is actually used (registration of serializers)
/* build list of properties that will be serialized and deserialized */
mitk::PropertyList::Pointer propList = mitk::PropertyList::New();
propList->SetProperty("booltrue", mitk::BoolProperty::New(true));
propList->SetProperty("boolfalse", mitk::BoolProperty::New(false));
propList->SetProperty("int", mitk::IntProperty::New(-32));
propList->SetProperty("float", mitk::FloatProperty::New(-31.337));
propList->SetProperty("double", mitk::DoubleProperty::New(-31.337));
propList->SetProperty("string", mitk::StringProperty::New("Hello MITK"));
mitk::Point3D p3d;
mitk::FillVector3D(p3d, 1.0, 2.2, -3.3);
propList->SetProperty("p3d", mitk::Point3dProperty::New(p3d));
mitk::Point3I p3i;
mitk::FillVector3D(p3i, 1, 2, -3);
propList->SetProperty("p3i", mitk::Point3iProperty::New(p3i));
mitk::Point4D p4d;
mitk::FillVector4D(p4d, 1.5, 2.6, -3.7, 4.44);
propList->SetProperty("p4d", mitk::Point4dProperty::New(p4d));
mitk::Vector3D v3d;
mitk::FillVector3D(v3d, 1.0, 2.2, -3.3);
propList->SetProperty("v3d", mitk::Vector3DProperty::New(v3d));
propList->SetProperty("annotation", mitk::AnnotationProperty::New("My Annotation", p3d));
propList->SetProperty("clipping", mitk::ClippingProperty::New(p3d, v3d));
propList->SetProperty("color", mitk::ColorProperty::New(1.0, 0.2, 0.2));
//mitk::EnumerationProperty::Pointer en = mitk::EnumerationProperty::New();
//en->AddEnum("PC", 1); en->AddEnum("Playstation", 2); en->AddEnum("Wii", 111); en->AddEnum("XBox", 7);
//en->SetValue("XBox");
//propList->SetProperty("enum", en);
/*
propList->SetProperty("gridrep", mitk::GridRepresentationProperty::New(2));
propList->SetProperty("gridvol", mitk::GridVolumeMapperProperty::New(0));
propList->SetProperty("OrganTypeProperty", mitk::OrganTypeProperty::New("Larynx"));
*/
propList->SetProperty("modality", mitk::ModalityProperty::New("Color Doppler"));
//propList->SetProperty("OdfNormalizationMethodProperty", mitk::OdfNormalizationMethodProperty::New("Global Maximum"));
//propList->SetProperty("OdfScaleByProperty", mitk::OdfScaleByProperty::New("Principal Curvature"));
propList->SetProperty("PlaneOrientationProperty", mitk::PlaneOrientationProperty::New("Arrows in positive direction"));
propList->SetProperty("ShaderProperty", mitk::ShaderProperty::New("fixed"));
propList->SetProperty("VtkInterpolationProperty", mitk::VtkInterpolationProperty::New("Gouraud"));
propList->SetProperty("VtkRepresentationProperty", mitk::VtkRepresentationProperty::New("Surface"));
propList->SetProperty("VtkResliceInterpolationProperty", mitk::VtkResliceInterpolationProperty::New("Cubic"));
propList->SetProperty("VtkScalarModeProperty", mitk::VtkScalarModeProperty::New("PointFieldData"));
propList->SetProperty("VtkVolumeRenderingProperty", mitk::VtkVolumeRenderingProperty::New("COMPOSITE"));
mitk::BoolLookupTable blt;
blt.SetTableValue(0, true); blt.SetTableValue(1, false); blt.SetTableValue(2, true);
propList->SetProperty("BoolLookupTableProperty", mitk::BoolLookupTableProperty::New(blt));
mitk::FloatLookupTable flt;
flt.SetTableValue(0, 3.1); flt.SetTableValue(1, 3.3); flt.SetTableValue(2, 7.0);
propList->SetProperty("FloatLookupTableProperty", mitk::FloatLookupTableProperty::New(flt));
mitk::IntLookupTable ilt;
ilt.SetTableValue(0, 3); ilt.SetTableValue(1, 2); ilt.SetTableValue(2, 11);
propList->SetProperty("IntLookupTableProperty", mitk::IntLookupTableProperty::New(ilt));
mitk::StringLookupTable slt;
slt.SetTableValue(0, "Hello"); slt.SetTableValue(1, "MITK"); slt.SetTableValue(2, "world");
propList->SetProperty("StringLookupTableProperty", mitk::StringLookupTableProperty::New(slt));
propList->SetProperty("GroupTagProperty", mitk::GroupTagProperty::New());
propList->SetProperty("LevelWindowProperty", mitk::LevelWindowProperty::New(mitk::LevelWindow(100.0, 50.0)));
mitk::LookupTable::Pointer lt = mitk::LookupTable::New();
lt->ChangeOpacityForAll(0.25);
lt->ChangeOpacity(17, 0.88);
propList->SetProperty("LookupTableProperty", mitk::LookupTableProperty::New(lt));
propList->SetProperty("StringProperty", mitk::StringProperty::New("Oh why, gruel world"));
//mitk::TransferFunction::Pointer tf = mitk::TransferFunction::New();
//tf->SetTransferFunctionMode(1);
//propList->SetProperty("TransferFunctionProperty", mitk::TransferFunctionProperty::New(tf));
MITK_TEST_CONDITION_REQUIRED(propList->GetMap()->size() > 0, "Initialize PropertyList");
TestAllProperties(propList);
/* test default property lists of basedata objects */
// activate the following tests after MaterialProperty is deleted
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData(mitk::PointSet::New());
TestAllProperties(node->GetPropertyList());
node->SetData(mitk::Image::New());
TestAllProperties(node->GetPropertyList());
node->SetData(mitk::Surface::New());
TestAllProperties(node->GetPropertyList());
node->SetData(mitk::VtkWidgetRendering::New());
TestAllProperties(node->GetPropertyList());
/*
node->SetData(mitk::Contour::New());
TestAllProperties(node->GetPropertyList());
node->SetData(mitk::ContourSet::New());
TestAllProperties(node->GetPropertyList());
node->SetData(mitk::Mesh::New());
TestAllProperties(node->GetPropertyList());
node->SetData(mitk::Cone::New());
TestAllProperties(node->GetPropertyList());
node->SetData(mitk::Cuboid::New());
TestAllProperties(node->GetPropertyList());
node->SetData(mitk::Cylinder::New());
TestAllProperties(node->GetPropertyList());
node->SetData(mitk::Ellipsoid::New());
TestAllProperties(node->GetPropertyList());
node->SetData(mitk::ExtrudedContour::New());
TestAllProperties(node->GetPropertyList());
node->SetData(mitk::Plane::New());
TestAllProperties(node->GetPropertyList());
//node->SetData(mitk::TrackingVolume::New()); // TrackingVolume is in IGT Module, it does not have special properties, therefore we skip it here
//TestAllProperties(node->GetPropertyList());
node->SetData(mitk::UnstructuredGrid::New());
TestAllProperties(node->GetPropertyList());
*/
/* untested base data types:
BaseDataTestImplementation
RenderWindowFrame
mitk::DiffusionImage< TPixelType >
GeometryData
- mitk::Geometry2DData
+ mitk::PlaneGeometryData
GradientBackground
ItkBaseDataAdapter
ManufacturerLogo
SlicedData
QBallImage
SeedsImage
TensorImage
BoundingObject
BoundingObjectGroup
*/
MITK_TEST_END();
}
void TestAllProperties(const mitk::PropertyList* propList)
{
assert(propList);
/* try to serialize each property in the list, then deserialize again and check for equality */
for (mitk::PropertyList::PropertyMap::const_iterator it = propList->GetMap()->begin(); it != propList->GetMap()->end(); ++it)
{
const mitk::BaseProperty* prop = it->second;
// construct name of serializer class
std::string serializername = std::string(prop->GetNameOfClass()) + "Serializer";
std::list<itk::LightObject::Pointer> allSerializers = itk::ObjectFactoryBase::CreateAllInstance(serializername.c_str());
MITK_TEST_CONDITION(allSerializers.size() > 0, std::string("Creating serializers for ") + serializername);
if (allSerializers.size() == 0)
{
MITK_TEST_OUTPUT( << "serialization not possible, skipping " << prop->GetNameOfClass());
continue;
}
if (allSerializers.size() > 1)
{
MITK_TEST_OUTPUT (<< "Warning: " << allSerializers.size() << " serializers found for " << prop->GetNameOfClass() << "testing only the first one.");
}
mitk::BasePropertySerializer* serializer = dynamic_cast<mitk::BasePropertySerializer*>( allSerializers.begin()->GetPointer());
MITK_TEST_CONDITION(serializer != NULL, serializername + std::string(" is valid"));
if (serializer != NULL)
{
serializer->SetProperty(prop);
TiXmlElement* valueelement = NULL;
try
{
valueelement = serializer->Serialize();
}
catch (...)
{
}
MITK_TEST_CONDITION(valueelement != NULL, std::string("Serialize property with ") + serializername);
if (valueelement == NULL)
{
MITK_TEST_OUTPUT( << "serialization failed, skipping deserialization");
continue;
}
mitk::BaseProperty::Pointer deserializedProp = serializer->Deserialize( valueelement );
MITK_TEST_CONDITION(deserializedProp.IsNotNull(), "serializer created valid property");
if (deserializedProp.IsNotNull())
{
MITK_TEST_CONDITION(*(deserializedProp.GetPointer()) == *prop, "deserialized property equals initial property for type " << prop->GetNameOfClass());
}
}
else
{
MITK_TEST_OUTPUT( << "created serializer object is of class " << allSerializers.begin()->GetPointer()->GetNameOfClass())
}
} // for all properties
}
diff --git a/Modules/Segmentation/Algorithms/mitkContourUtils.cpp b/Modules/Segmentation/Algorithms/mitkContourUtils.cpp
index a432e0aa16..80b9831cc1 100755
--- a/Modules/Segmentation/Algorithms/mitkContourUtils.cpp
+++ b/Modules/Segmentation/Algorithms/mitkContourUtils.cpp
@@ -1,79 +1,79 @@
/*===================================================================
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 "mitkContourUtils.h"
#include "mitkContourModelUtils.h"
mitk::ContourUtils::ContourUtils()
{
}
mitk::ContourUtils::~ContourUtils()
{
}
mitk::ContourModel::Pointer mitk::ContourUtils::ProjectContourTo2DSlice(Image* slice, Contour* contourIn3D, bool itkNotUsed( correctionForIpSegmentation ), bool constrainToInside)
{
mitk::Contour::PointsContainerIterator it = contourIn3D->GetPoints()->Begin();
mitk::Contour::PointsContainerIterator end = contourIn3D->GetPoints()->End();
mitk::ContourModel::Pointer contour = mitk::ContourModel::New();
while(it!=end)
{
contour->AddVertex(it.Value());
it++;
}
return mitk::ContourModelUtils::ProjectContourTo2DSlice(slice, contour, false/*not used*/, constrainToInside );
}
-mitk::ContourModel::Pointer mitk::ContourUtils::BackProjectContourFrom2DSlice(const Geometry3D* sliceGeometry, Contour* contourIn2D, bool itkNotUsed( correctionForIpSegmentation ) )
+mitk::ContourModel::Pointer mitk::ContourUtils::BackProjectContourFrom2DSlice(const BaseGeometry* sliceGeometry, Contour* contourIn2D, bool itkNotUsed( correctionForIpSegmentation ) )
{
mitk::Contour::PointsContainerIterator it = contourIn2D->GetPoints()->Begin();
mitk::Contour::PointsContainerIterator end = contourIn2D->GetPoints()->End();
mitk::ContourModel::Pointer contour = mitk::ContourModel::New();
while(it!=end)
{
contour->AddVertex(it.Value());
it++;
}
return mitk::ContourModelUtils::BackProjectContourFrom2DSlice(sliceGeometry, contour, false/*not used*/);
}
void mitk::ContourUtils::FillContourInSlice( Contour* projectedContour, Image* sliceImage, int paintingPixelValue )
{
mitk::Contour::PointsContainerIterator it = projectedContour->GetPoints()->Begin();
mitk::Contour::PointsContainerIterator end = projectedContour->GetPoints()->End();
mitk::ContourModel::Pointer contour = mitk::ContourModel::New();
while(it!=end)
{
contour->AddVertex(it.Value());
it++;
}
mitk::ContourModelUtils::FillContourInSlice(contour, sliceImage, paintingPixelValue);
}
diff --git a/Modules/Segmentation/Algorithms/mitkContourUtils.h b/Modules/Segmentation/Algorithms/mitkContourUtils.h
index 19f468895b..ec1dcd96df 100644
--- a/Modules/Segmentation/Algorithms/mitkContourUtils.h
+++ b/Modules/Segmentation/Algorithms/mitkContourUtils.h
@@ -1,74 +1,74 @@
/*===================================================================
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 mitkContourUtilshIncludett
#define mitkContourUtilshIncludett
#include "mitkImage.h"
#include <MitkSegmentationExports.h>
#include "mitkContour.h"
#include "mitkContourModel.h"
namespace mitk
{
/**
* \brief Helpful methods for working with contours and images
*
* Legacy support for mitk::Contour
* TODO remove this class when mitk::Contour is removed
*/
class MitkSegmentation_EXPORT ContourUtils : public itk::Object
{
public:
mitkClassMacro(ContourUtils, itk::Object);
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/**
\brief Projects a contour onto an image point by point. Converts from world to index coordinates.
\param correctionForIpSegmentation adds 0.5 to x and y index coordinates (difference between ipSegmentation and MITK contours)
*/
ContourModel::Pointer ProjectContourTo2DSlice(Image* slice, Contour* contourIn3D, bool correctionForIpSegmentation, bool constrainToInside);
/**
\brief Projects a slice index coordinates of a contour back into world coordinates.
\param correctionForIpSegmentation subtracts 0.5 to x and y index coordinates (difference between ipSegmentation and MITK contours)
*/
- ContourModel::Pointer BackProjectContourFrom2DSlice(const Geometry3D* sliceGeometry, Contour* contourIn2D, bool correctionForIpSegmentation = false);
+ ContourModel::Pointer BackProjectContourFrom2DSlice(const BaseGeometry* sliceGeometry, Contour* contourIn2D, bool correctionForIpSegmentation = false);
/**
\brief Fill a contour in a 2D slice with a specified pixel value.
*/
void FillContourInSlice( Contour* projectedContour, Image* sliceImage, int paintingPixelValue = 1 );
protected:
ContourUtils();
virtual ~ContourUtils();
};
}
#endif
diff --git a/Modules/Segmentation/Algorithms/mitkDiffSliceOperation.cpp b/Modules/Segmentation/Algorithms/mitkDiffSliceOperation.cpp
index e9b634877c..a056a622fc 100644
--- a/Modules/Segmentation/Algorithms/mitkDiffSliceOperation.cpp
+++ b/Modules/Segmentation/Algorithms/mitkDiffSliceOperation.cpp
@@ -1,104 +1,105 @@
/*===================================================================
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 "mitkDiffSliceOperation.h"
#include <itkCommand.h>
mitk::DiffSliceOperation::DiffSliceOperation():Operation(1)
{
m_TimeStep = 0;
m_Slice = NULL;
m_Image = NULL;
m_WorldGeometry = NULL;
m_SliceGeometry = NULL;
m_ImageIsValid = false;
}
mitk::DiffSliceOperation::DiffSliceOperation(mitk::Image* imageVolume,
vtkImageData* slice,
- Geometry3D* sliceGeometry,
+ SlicedGeometry3D* sliceGeometry,
unsigned int timestep,
- Geometry3D* currentWorldGeometry):Operation(1)
+ BaseGeometry* currentWorldGeometry):Operation(1)
{
- m_WorldGeometry = currentWorldGeometry->Clone();
+ itk::LightObject::Pointer lopointer = currentWorldGeometry->Clone();
+ m_WorldGeometry = dynamic_cast<BaseGeometry*>(lopointer.GetPointer());
/*
Quick fix for bug 12338.
Guard object - fix this when clone method of PlaneGeometry is cloning the reference geometry (see bug 13392)*/
- m_GuardReferenceGeometry = mitk::Geometry3D::New();
- m_GuardReferenceGeometry = dynamic_cast<mitk::Geometry2D*>(m_WorldGeometry.GetPointer())->GetReferenceGeometry();
+ //xxxx m_GuardReferenceGeometry = mitk::BaseGeometry::New();
+ m_GuardReferenceGeometry = dynamic_cast<mitk::PlaneGeometry*>(m_WorldGeometry.GetPointer())->GetReferenceGeometry();
/*---------------------------------------------------------------------------------------------------*/
m_SliceGeometry = sliceGeometry->Clone();
m_TimeStep = timestep;
/*m_zlibSliceContainer = CompressedImageContainer::New();
m_zlibSliceContainer->SetImage( slice );*/
m_Slice = vtkSmartPointer<vtkImageData>::New();
m_Slice->DeepCopy(slice);
m_Image = imageVolume;
if ( m_Image) {
/*add an observer to listen to the delete event of the image, this is necessary because the operation is then invalid*/
itk::SimpleMemberCommand< DiffSliceOperation >::Pointer command = itk::SimpleMemberCommand< DiffSliceOperation >::New();
command->SetCallbackFunction( this, &DiffSliceOperation::OnImageDeleted );
//get the id of the observer, used to remove it later on
m_DeleteObserverTag = imageVolume->AddObserver( itk::DeleteEvent(), command );
m_ImageIsValid = true;
}
else
m_ImageIsValid = false;
}
mitk::DiffSliceOperation::~DiffSliceOperation()
{
m_Slice = NULL;
m_WorldGeometry = NULL;
//m_zlibSliceContainer = NULL;
if (m_ImageIsValid)
{
//if the image is still there, we have to remove the observer from it
m_Image->RemoveObserver( m_DeleteObserverTag );
}
m_Image = NULL;
}
vtkImageData* mitk::DiffSliceOperation::GetSlice()
{
//Image::ConstPointer image = m_zlibSliceContainer->GetImage().GetPointer();
return m_Slice;
}
bool mitk::DiffSliceOperation::IsValid()
{
return m_ImageIsValid && (m_Slice.GetPointer() != NULL) && (m_WorldGeometry.IsNotNull());//TODO improve
}
void mitk::DiffSliceOperation::OnImageDeleted()
{
//if our imageVolume is removed e.g. from the datastorage the operation is no lnger valid
m_ImageIsValid = false;
}
\ No newline at end of file
diff --git a/Modules/Segmentation/Algorithms/mitkDiffSliceOperation.h b/Modules/Segmentation/Algorithms/mitkDiffSliceOperation.h
index e2766af45c..f896be2165 100644
--- a/Modules/Segmentation/Algorithms/mitkDiffSliceOperation.h
+++ b/Modules/Segmentation/Algorithms/mitkDiffSliceOperation.h
@@ -1,140 +1,140 @@
/*===================================================================
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 mitkDiffSliceOperation_h_Included
#define mitkDiffSliceOperation_h_Included
#include <MitkSegmentationExports.h>
#include "mitkCommon.h"
#include <mitkOperation.h>
//#include "mitkCompressedImageContainer.h"
#include <mitkImage.h>
#include <vtkSmartPointer.h>
#include <vtkImageData.h>
//DEPRECATED
#include <mitkTimeGeometry.h>
namespace mitk
{
/** \brief An Operation for applying an edited slice to the volume.
\sa DiffSliceOperationApplier
The information for the operation is specified by properties:
imageVolume the volume where the slice was extracted from.
slice the slice to be applied.
timestep the timestep in an 4D image.
currentWorldGeometry specifies the axis where the slice has to be applied in the volume.
This Operation can be used to realize undo-redo functionality for e.g. segmentation purposes.
*/
class MitkSegmentation_EXPORT DiffSliceOperation : public Operation
{
public:
mitkClassMacro(DiffSliceOperation, OperationActor);
//itkFactorylessNewMacro(Self)
//itkCloneMacro(Self)
- //mitkNewMacro4Param(DiffSliceOperation,mitk::Image,mitk::Image,unsigned int, mitk::Geometry2D);
+ //mitkNewMacro4Param(DiffSliceOperation,mitk::Image,mitk::Image,unsigned int, mitk::PlaneGeometry);
/** \brief Creates an empty instance.
Note that it is not valid yet. The properties of the object have to be set.
*/
DiffSliceOperation();
/** \brief */
- DiffSliceOperation( mitk::Image* imageVolume, vtkImageData* slice, Geometry3D* sliceGeometry, unsigned int timestep, Geometry3D* currentWorldGeometry);
+ DiffSliceOperation( mitk::Image* imageVolume, vtkImageData* slice, SlicedGeometry3D* sliceGeometry, unsigned int timestep, BaseGeometry* currentWorldGeometry);
/** \brief
*
* \deprecatedSince{2013_09} Please use TimeGeometry instead of TimeSlicedGeometry. For more information see http://www.mitk.org/Development/Refactoring%20of%20the%20Geometry%20Classes%20-%20Part%201
*/
- DEPRECATED(DiffSliceOperation( mitk::Image* imageVolume, vtkImageData* slice, TimeSlicedGeometry* sliceGeometry, unsigned int timestep, Geometry3D* currentWorldGeometry));
+ DEPRECATED(DiffSliceOperation( mitk::Image* imageVolume, vtkImageData* slice, TimeSlicedGeometry* sliceGeometry, unsigned int timestep, BaseGeometry* currentWorldGeometry));
/** \brief Check if it is a valid operation.*/
bool IsValid();
/** \brief Set the image volume.*/
void SetImage(mitk::Image* image){ this->m_Image = image;}
/** \brief Get th image volume.*/
mitk::Image* GetImage(){return this->m_Image;}
/** \brief Set thee slice to be applied.*/
void SetImage(vtkImageData* slice){ this->m_Slice = slice;}
/** \brief Get the slice that is applied in the operation.*/
vtkImageData* GetSlice();
/** \brief Get timeStep.*/
void SetTimeStep(unsigned int timestep){this->m_TimeStep = timestep;}
/** \brief Set timeStep*/
unsigned int GetTimeStep(){return this->m_TimeStep;}
/** \brief Set the axis where the slice has to be applied in the volume.*/
- void SetSliceGeometry(Geometry3D* sliceGeometry){this->m_SliceGeometry = sliceGeometry;}
+ void SetSliceGeometry(SlicedGeometry3D* sliceGeometry){this->m_SliceGeometry = sliceGeometry;}
/** \brief Get the axis where the slice has to be applied in the volume.*/
- Geometry3D* GetSliceGeometry(){return this->m_SliceGeometry;}
+ SlicedGeometry3D* GetSliceGeometry(){return this->m_SliceGeometry;}
/** \brief Set the axis where the slice has to be applied in the volume.
* \deprecatedSince{2013_09} Please use TimeGeometry instead of TimeSlicedGeometry. For more information see http://www.mitk.org/Development/Refactoring%20of%20the%20Geometry%20Classes%20-%20Part%201
*/
void SetSliceGeometry(TimeSlicedGeometry* sliceGeometry);
/** \brief Set the axis where the slice has to be applied in the volume.*/
- void SetCurrentWorldGeometry(Geometry3D* worldGeometry){this->m_WorldGeometry = worldGeometry;}
+ void SetCurrentWorldGeometry(BaseGeometry* worldGeometry){this->m_WorldGeometry = worldGeometry;}
/** \brief Get the axis where the slice has to be applied in the volume.*/
- Geometry3D* GetWorldGeometry(){return this->m_WorldGeometry;}
+ BaseGeometry* GetWorldGeometry(){return this->m_WorldGeometry;}
/** \brief Set the axis where the slice has to be applied in the volume.
* \deprecatedSince{2013_09} Please use TimeGeometry instead of TimeSlicedGeometry. For more information see http://www.mitk.org/Development/Refactoring%20of%20the%20Geometry%20Classes%20-%20Part%201
*/
void SetCurrentWorldGeometry(TimeSlicedGeometry* worldGeometry);
protected:
virtual ~DiffSliceOperation();
/** \brief Callback for image observer.*/
void OnImageDeleted();
//CompressedImageContainer::Pointer m_zlibSliceContainer;
mitk::Image* m_Image;
vtkSmartPointer<vtkImageData> m_Slice;
- Geometry3D::Pointer m_SliceGeometry;
+ SlicedGeometry3D::Pointer m_SliceGeometry;
unsigned int m_TimeStep;
- Geometry3D::Pointer m_WorldGeometry;
+ BaseGeometry::Pointer m_WorldGeometry;
bool m_ImageIsValid;
unsigned long m_DeleteObserverTag;
- mitk::Geometry3D::Pointer m_GuardReferenceGeometry;
+ mitk::BaseGeometry::Pointer m_GuardReferenceGeometry;
};
}
#endif
diff --git a/Modules/Segmentation/Algorithms/mitkDiffSliceOperationApplier.cpp b/Modules/Segmentation/Algorithms/mitkDiffSliceOperationApplier.cpp
index 4c5610dc1f..ecc79ea58b 100644
--- a/Modules/Segmentation/Algorithms/mitkDiffSliceOperationApplier.cpp
+++ b/Modules/Segmentation/Algorithms/mitkDiffSliceOperationApplier.cpp
@@ -1,76 +1,76 @@
/*===================================================================
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 "mitkDiffSliceOperationApplier.h"
#include "mitkRenderingManager.h"
#include <vtkSmartPointer.h>
mitk::DiffSliceOperationApplier::DiffSliceOperationApplier()
{
}
mitk::DiffSliceOperationApplier::~DiffSliceOperationApplier()
{
}
void mitk::DiffSliceOperationApplier::ExecuteOperation( Operation* operation )
{
DiffSliceOperation* imageOperation = dynamic_cast<DiffSliceOperation*>( operation );
//as we only support DiffSliceOperation return if operation is not type of DiffSliceOperation
if(!imageOperation)
return;
//chak if the operation is valid
if(imageOperation->IsValid())
{
//the actual overwrite filter (vtk)
vtkSmartPointer<mitkVtkImageOverwrite> reslice = vtkSmartPointer<mitkVtkImageOverwrite>::New();
//Set the slice as 'input'
reslice->SetInputSlice(imageOperation->GetSlice());
//set overwrite mode to true to write back to the image volume
reslice->SetOverwriteMode(true);
reslice->Modified();
//a wrapper for vtkImageOverwrite
mitk::ExtractSliceFilter::Pointer extractor = mitk::ExtractSliceFilter::New(reslice);
extractor->SetInput( imageOperation->GetImage() );
extractor->SetTimeStep( imageOperation->GetTimeStep() );
- extractor->SetWorldGeometry( dynamic_cast<Geometry2D*>(imageOperation->GetWorldGeometry()) );
+ extractor->SetWorldGeometry( dynamic_cast<PlaneGeometry*>(imageOperation->GetWorldGeometry()) );
extractor->SetVtkOutputRequest(true);
extractor->SetResliceTransformByGeometry( imageOperation->GetImage()->GetGeometry( imageOperation->GetTimeStep() ) );
extractor->Modified();
extractor->Update();
//make sure the modification is rendered
RenderingManager::GetInstance()->RequestUpdateAll();
imageOperation->GetImage()->Modified();
}
}
//mitk::DiffSliceOperationApplier* mitk::DiffSliceOperationApplier::s_Instance = NULL;
mitk::DiffSliceOperationApplier* mitk::DiffSliceOperationApplier::GetInstance()
{
//if(!s_Instance)
static DiffSliceOperationApplier* s_Instance = new DiffSliceOperationApplier();
return s_Instance;
}
\ No newline at end of file
diff --git a/Modules/Segmentation/Algorithms/mitkImageToContourFilter.h b/Modules/Segmentation/Algorithms/mitkImageToContourFilter.h
index 65c50dc58a..8f9152fe00 100644
--- a/Modules/Segmentation/Algorithms/mitkImageToContourFilter.h
+++ b/Modules/Segmentation/Algorithms/mitkImageToContourFilter.h
@@ -1,95 +1,95 @@
/*===================================================================
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 mitkImageToContourFilter_h_Included
#define mitkImageToContourFilter_h_Included
//#include "MitkSBExports.h"
#include <MitkSegmentationExports.h>
#include "itkImage.h"
#include "mitkImage.h"
#include "itkContourExtractor2DImageFilter.h"
#include "mitkImageToSurfaceFilter.h"
#include "mitkSurface.h"
#include "vtkPolyData.h"
#include "vtkPolygon.h"
#include "vtkCellArray.h"
#include "mitkProgressBar.h"
namespace mitk {
/**
\brief A filter that can extract contours out of a 2D binary image
This class takes an 2D mitk::Image as input and extracts all contours which are drawn it. The contour
extraction is done by using the itk::ContourExtractor2DImageFilter.
The output is a mitk::Surface.
$Author: fetzer$
*/
class MitkSegmentation_EXPORT ImageToContourFilter : public ImageToSurfaceFilter
{
public:
mitkClassMacro(ImageToContourFilter,ImageToSurfaceFilter);
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/**
\brief Set macro for the geometry of the slice. If it is not set explicitly the geometry will be taken from the slice
\a Parameter The slice`s geometry
*/
- itkSetMacro(SliceGeometry, Geometry3D*);
+ itkSetMacro(SliceGeometry, BaseGeometry*);
//typedef unsigned int VDimension;
typedef itk::PolyLineParametricPath<2> PolyLineParametricPath2D;
typedef PolyLineParametricPath2D::VertexListType ContourPath;
/**
\brief Set whether the mitkProgressBar should be used
\a Parameter true for using the progress bar, false otherwise
*/
void SetUseProgressBar(bool);
/**
\brief Set the stepsize which the progress bar should proceed
\a Parameter The stepsize for progressing
*/
void SetProgressStepSize(unsigned int stepSize);
protected:
ImageToContourFilter();
virtual ~ImageToContourFilter();
virtual void GenerateData();
virtual void GenerateOutputInformation();
private:
- const Geometry3D* m_SliceGeometry;
+ const BaseGeometry* m_SliceGeometry;
bool m_UseProgressBar;
unsigned int m_ProgressStepSize;
template<typename TPixel, unsigned int VImageDimension>
void Itk2DContourExtraction (itk::Image<TPixel, VImageDimension>* sliceImage);
};//class
}//namespace
#endif
diff --git a/Modules/Segmentation/Algorithms/mitkOverwriteDirectedPlaneImageFilter.h b/Modules/Segmentation/Algorithms/mitkOverwriteDirectedPlaneImageFilter.h
index c5abbb562e..5cd7d3bd19 100644
--- a/Modules/Segmentation/Algorithms/mitkOverwriteDirectedPlaneImageFilter.h
+++ b/Modules/Segmentation/Algorithms/mitkOverwriteDirectedPlaneImageFilter.h
@@ -1,122 +1,122 @@
/*===================================================================
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 mitkOverwriteDirectedPlaneImageFilter_h_Included
#define mitkOverwriteDirectedPlaneImageFilter_h_Included
#include "mitkCommon.h"
#include <MitkSegmentationExports.h>
#include "mitkImageToImageFilter.h"
#include <itkImage.h>
namespace mitk
{
/**
\deprecated This class is deprecated. Use mitkVtkImageOverwrite instead.
\sa mitkVtkImageOverwrite
\brief Writes a 2D slice into a 3D image.
\sa SegTool2D
\sa ContourTool
\sa ExtractImageFilter
\ingroup Process
\ingroup Reliver
There is a separate page describing the general design of QmitkInteractiveSegmentation: \ref QmitkInteractiveSegmentationTechnicalPage
This class takes a 3D mitk::Image as input and tries to replace one slice in it with the second input image, which is specified
by calling SetSliceImage with a 2D mitk::Image.
Two parameters determine which slice is replaced: the "slice dimension" is that one, which is constant for all points in the plane, e.g. axial would mean 2.
The "slice index" is the slice index in the image direction you specified with "affected dimension". Indices count from zero.
This class works with all kind of image types, the only restrictions being that the input is 3D, and the slice image is 2D.
If requested by SetCreateUndoInformation(true), this class will create instances of ApplyDiffImageOperation for the undo stack.
These operations will (on user request) be executed by DiffImageApplier to perform undo.
Last contributor: $Author: maleike $
*/
class MitkSegmentation_EXPORT OverwriteDirectedPlaneImageFilter : public ImageToImageFilter
{
public:
mitkClassMacro(OverwriteDirectedPlaneImageFilter, ImageToImageFilter);
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/**
\brief Which plane to overwrite
*/
- const Geometry3D* GetPlaneGeometry3D() const { return m_PlaneGeometry; }
- void SetPlaneGeometry3D( const Geometry3D *geometry ) { m_PlaneGeometry = geometry; }
+ const BaseGeometry* GetPlaneGeometry3D() const { return m_PlaneGeometry; }
+ void SetPlaneGeometry3D( const BaseGeometry *geometry ) { m_PlaneGeometry = geometry; }
/**
\brief Time step of the slice to overwrite
*/
itkSetMacro(TimeStep, unsigned int);
itkGetConstMacro(TimeStep, unsigned int);
/**
\brief Whether to create undo operation in the MITK undo stack
*/
itkSetMacro(CreateUndoInformation, bool);
itkGetConstMacro(CreateUndoInformation, bool);
itkSetObjectMacro(SliceImage, Image);
const Image* GetSliceImage() { return m_SliceImage.GetPointer(); }
const Image* GetLastDifferenceImage() { return m_SliceDifferenceImage.GetPointer(); }
protected:
OverwriteDirectedPlaneImageFilter(); // purposely hidden
virtual ~OverwriteDirectedPlaneImageFilter();
virtual void GenerateData();
template<typename TPixel, unsigned int VImageDimension>
void ItkSliceOverwriting (itk::Image<TPixel, VImageDimension>* input3D);
template<typename TPixel, unsigned int VImageDimension>
void ItkImageSwitch( itk::Image<TPixel,VImageDimension>* image );
template<typename TPixel1, unsigned int VImageDimension1, typename TPixel2, unsigned int VImageDimension2>
void ItkImageProcessing( itk::Image<TPixel1,VImageDimension1>* itkImage1, itk::Image<TPixel2,VImageDimension2>* itkImage2 );
//std::string EventDescription( unsigned int sliceDimension, unsigned int sliceIndex, unsigned int timeStep );
Image::ConstPointer m_SliceImage;
Image::Pointer m_SliceDifferenceImage;
- const Geometry3D *m_PlaneGeometry;
- const Geometry3D *m_ImageGeometry3D;
+ const BaseGeometry *m_PlaneGeometry;
+ const BaseGeometry *m_ImageGeometry3D;
unsigned int m_TimeStep;
unsigned int m_Dimension0;
unsigned int m_Dimension1;
bool m_CreateUndoInformation;
};
} // namespace
#endif
diff --git a/Modules/Segmentation/Algorithms/mitkShapeBasedInterpolationAlgorithm.cpp b/Modules/Segmentation/Algorithms/mitkShapeBasedInterpolationAlgorithm.cpp
index a4c2a404aa..1c92fd30af 100644
--- a/Modules/Segmentation/Algorithms/mitkShapeBasedInterpolationAlgorithm.cpp
+++ b/Modules/Segmentation/Algorithms/mitkShapeBasedInterpolationAlgorithm.cpp
@@ -1,75 +1,75 @@
/*===================================================================
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 "mitkShapeBasedInterpolationAlgorithm.h"
#include "mitkImageCast.h"
#include "mitkImageDataItem.h"
#include "ipSegmentation.h"
mitk::Image::Pointer
mitk::ShapeBasedInterpolationAlgorithm::Interpolate(
Image::ConstPointer lowerSlice, unsigned int lowerSliceIndex,
Image::ConstPointer upperSlice, unsigned int upperSliceIndex,
unsigned int requestedIndex,
unsigned int /*sliceDimension*/, // commented variables are not used
Image::Pointer resultImage,
unsigned int /*timeStep*/,
Image::ConstPointer /*referenceImage*/)
{
// convert these slices to the ipSegmentation data type (into an ITK image)
itk::Image< ipMITKSegmentationTYPE, 2 >::Pointer correctPixelTypeLowerITKSlice;
CastToItkImage( lowerSlice, correctPixelTypeLowerITKSlice );
assert ( correctPixelTypeLowerITKSlice.IsNotNull() );
itk::Image< ipMITKSegmentationTYPE, 2 >::Pointer correctPixelTypeUpperITKSlice;
CastToItkImage( upperSlice, correctPixelTypeUpperITKSlice );
assert ( correctPixelTypeUpperITKSlice.IsNotNull() );
// correct direction info
itk::Image< ipMITKSegmentationTYPE, 2 >::DirectionType imageDirection;
imageDirection.SetIdentity();
correctPixelTypeLowerITKSlice->SetDirection(imageDirection);
correctPixelTypeUpperITKSlice->SetDirection(imageDirection);
// back-convert to MITK images to access a mitkIpPicDescriptor
Image::Pointer correctPixelTypeLowerMITKSlice = Image::New();
CastToMitkImage( correctPixelTypeLowerITKSlice, correctPixelTypeLowerMITKSlice );
mitkIpPicDescriptor* lowerPICSlice = mitkIpPicNew();
CastToIpPicDescriptor( correctPixelTypeLowerMITKSlice, lowerPICSlice);
Image::Pointer correctPixelTypeUpperMITKSlice = Image::New();
CastToMitkImage( correctPixelTypeUpperITKSlice, correctPixelTypeUpperMITKSlice );
mitkIpPicDescriptor* upperPICSlice = mitkIpPicNew();
CastToIpPicDescriptor( correctPixelTypeUpperMITKSlice, upperPICSlice);
// calculate where the current slice is in comparison to the lower and upper neighboring slices
float ratio = (float)(requestedIndex - lowerSliceIndex) / (float)(upperSliceIndex - lowerSliceIndex);
mitkIpPicDescriptor* ipPicResult = ipMITKSegmentationInterpolate( lowerPICSlice, upperPICSlice, ratio ); // magic
if (!ipPicResult) return NULL;
- Geometry3D::Pointer originalGeometry = resultImage->GetGeometry();
+ BaseGeometry::Pointer originalGeometry = resultImage->GetGeometry();
resultImage->Initialize( CastToImageDescriptor( ipPicResult ) );
// FIXME resultImage->SetPicSlice( ipPicResult );
resultImage->SetSlice( ipPicResult->data );
resultImage->SetGeometry( originalGeometry );
mitkIpPicFree( ipPicResult );
return resultImage;
}
diff --git a/Modules/Segmentation/DataManagement/mitkContour.cpp b/Modules/Segmentation/DataManagement/mitkContour.cpp
index 2359dc0e19..36a45d1b58 100644
--- a/Modules/Segmentation/DataManagement/mitkContour.cpp
+++ b/Modules/Segmentation/DataManagement/mitkContour.cpp
@@ -1,165 +1,165 @@
/*===================================================================
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 "mitkContour.h"
#include <mitkProportionalTimeGeometry.h>
mitk::Contour::Contour() :
m_ContourPath (PathType::New()),
m_CurrentWindow ( NULL ),
m_BoundingBox (BoundingBoxType::New()),
m_Vertices ( BoundingBoxType::PointsContainer::New() ),
m_Closed ( true ),
m_Selected ( false ),
m_Width (3.0)
{
Superclass::InitializeTimeGeometry();
}
mitk::Contour::Contour( const Contour & other ): BaseData(other),
m_ContourPath(other.m_ContourPath),
m_CurrentWindow(other.m_CurrentWindow),
m_BoundingBox(other.m_BoundingBox),
m_Vertices(other.m_Vertices),
m_Closed(other.m_Closed),
m_Selected(other.m_Selected),
m_Width(other.m_Width)
{
}
mitk::Contour::~Contour()
{
}
void mitk::Contour::AddVertex(mitk::Point3D newPoint)
{
BoundingBoxType::PointType p;
p.CastFrom(newPoint);
m_Vertices->InsertElement(m_Vertices->Size(), p);
ContinuousIndexType idx;
idx.CastFrom(newPoint);
m_ContourPath->AddVertex(idx);
m_BoundingBox->SetPoints(m_Vertices);
Modified();
}
void mitk::Contour::UpdateOutputInformation()
{
// \todo probably we should do this additionally for each time-step
ScalarType mitkBounds[6];
if (m_Vertices->Size() == 0) {
mitkBounds[0] = 0.0;
mitkBounds[1] = 0.0;
mitkBounds[2] = 0.0;
mitkBounds[3] = 0.0;
mitkBounds[4] = 0.0;
mitkBounds[5] = 0.0;
}
else
{
m_BoundingBox->ComputeBoundingBox();
BoundingBoxType::BoundsArrayType tmp = m_BoundingBox->GetBounds();
mitkBounds[0] = tmp[0];
mitkBounds[1] = tmp[1];
mitkBounds[2] = tmp[2];
mitkBounds[3] = tmp[3];
mitkBounds[4] = tmp[4];
mitkBounds[5] = tmp[5];
}
- Geometry3D* geometry3d = GetGeometry(0);
+ BaseGeometry* geometry3d = GetGeometry(0);
geometry3d->SetBounds(mitkBounds);
GetTimeGeometry()->Update();
}
void mitk::Contour::SetRequestedRegionToLargestPossibleRegion()
{
}
bool mitk::Contour::RequestedRegionIsOutsideOfTheBufferedRegion()
{
return false;
}
bool mitk::Contour::VerifyRequestedRegion()
{
return true;
}
void mitk::Contour::SetRequestedRegion( const itk::DataObject*)
{
}
mitk::Contour::PathType::Pointer mitk::Contour::GetContourPath() const
{
return m_ContourPath;
}
void mitk::Contour::SetCurrentWindow(vtkRenderWindow* rw)
{
m_CurrentWindow = rw;
}
vtkRenderWindow* mitk::Contour::GetCurrentWindow() const
{
return m_CurrentWindow;
}
void mitk::Contour::Initialize()
{
m_ContourPath = PathType::New();
m_ContourPath->Initialize();
m_BoundingBox = BoundingBoxType::New();
m_Vertices = BoundingBoxType::PointsContainer::New();
ProportionalTimeGeometry::Pointer timeGeometry = ProportionalTimeGeometry::New();
timeGeometry->Initialize(1);
SetTimeGeometry(timeGeometry);
}
unsigned int mitk::Contour::GetNumberOfPoints() const
{
return m_Vertices->Size();
}
mitk::Contour::PointsContainerPointer
mitk::Contour::GetPoints() const
{
return m_Vertices;
}
void mitk::Contour::SetPoints(mitk::Contour::PointsContainerPointer points)
{
m_Vertices = points;
Modified();
}
void mitk::Contour::PrintSelf( std::ostream& os, itk::Indent indent) const
{
Superclass::PrintSelf( os, indent );
os << indent << "Number of verticies: " << GetNumberOfPoints() << std::endl;
mitk::Contour::PointsContainerIterator pointsIt = m_Vertices->Begin(), end = m_Vertices->End();
os << indent << "Verticies: " << std::endl;
int i = 0;
while ( pointsIt != end )
{
os << indent << indent << i << ": " << pointsIt.Value() << std::endl;
++pointsIt; ++i;
}
}
diff --git a/Modules/Segmentation/DataManagement/mitkContourSet.cpp b/Modules/Segmentation/DataManagement/mitkContourSet.cpp
index 1004392ade..f7ace28270 100644
--- a/Modules/Segmentation/DataManagement/mitkContourSet.cpp
+++ b/Modules/Segmentation/DataManagement/mitkContourSet.cpp
@@ -1,129 +1,129 @@
/*===================================================================
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 "mitkContourSet.h"
#include <mitkProportionalTimeGeometry.h>
mitk::ContourSet::ContourSet() :
m_ContourVector( ContourVectorType() ),
m_NumberOfContours (0)
{
ProportionalTimeGeometry::Pointer timeGeometry = ProportionalTimeGeometry::New();
timeGeometry->Initialize(1);
SetTimeGeometry(timeGeometry);
}
mitk::ContourSet::~ContourSet()
{
}
void mitk::ContourSet::AddContour(unsigned int index, mitk::Contour::Pointer contour)
{
m_ContourVector.insert(std::make_pair( index , contour) );
}
void mitk::ContourSet::RemoveContour(unsigned long index)
{
m_ContourVector.erase( index );
}
void mitk::ContourSet::UpdateOutputInformation()
{
mitk::ContourSet::ContourVectorType contourVec = GetContours();
mitk::ContourSet::ContourIterator contoursIterator = contourVec.begin();
mitk::ContourSet::ContourIterator contoursIteratorEnd = contourVec.end();
// initialize container
mitk::BoundingBox::PointsContainer::Pointer pointscontainer=mitk::BoundingBox::PointsContainer::New();
mitk::BoundingBox::PointIdentifier pointid=0;
mitk::Point3D point;
mitk::AffineTransform3D* transform = GetGeometry(0)->GetIndexToWorldTransform();
mitk::AffineTransform3D::Pointer inverse = mitk::AffineTransform3D::New();
transform->GetInverse(inverse);
// calculate a bounding box that includes all contours
// \todo probably we should do this additionally for each time-step
while (contoursIterator != contoursIteratorEnd)
{
const TimeGeometry* geometry = (*contoursIterator).second->GetUpdatedTimeGeometry();
unsigned char i;
for(i=0; i<8; ++i)
{
point = inverse->TransformPoint(geometry->GetCornerPointInWorld(i));
if(point[0]*point[0]+point[1]*point[1]+point[2]*point[2] < mitk::large)
pointscontainer->InsertElement( pointid++, point);
else
{
itkGenericOutputMacro( << "Unrealistically distant corner point encountered. Ignored. BoundingObject: " << (*contoursIterator).second );
}
}
++contoursIterator;
}
mitk::BoundingBox::Pointer boundingBox = mitk::BoundingBox::New();
boundingBox->SetPoints(pointscontainer);
boundingBox->ComputeBoundingBox();
- Geometry3D* geometry3d = GetGeometry(0);
+ BaseGeometry* geometry3d = GetGeometry(0);
geometry3d->SetIndexToWorldTransform(transform);
geometry3d->SetBounds(boundingBox->GetBounds());
ProportionalTimeGeometry::Pointer timeGeometry = ProportionalTimeGeometry::New();
timeGeometry->Initialize(geometry3d,GetTimeGeometry()->CountTimeSteps());
SetTimeGeometry(timeGeometry);
}
void mitk::ContourSet::SetRequestedRegionToLargestPossibleRegion()
{
}
bool mitk::ContourSet::RequestedRegionIsOutsideOfTheBufferedRegion()
{
return true;
}
bool mitk::ContourSet::VerifyRequestedRegion()
{
return true;
}
void mitk::ContourSet::SetRequestedRegion( const itk::DataObject*)
{
}
void mitk::ContourSet::Initialize()
{
m_ContourVector = ContourVectorType();
ProportionalTimeGeometry::Pointer timeGeometry = ProportionalTimeGeometry::New();
timeGeometry->Initialize(1);
SetTimeGeometry(timeGeometry);
}
unsigned int mitk::ContourSet::GetNumberOfContours()
{
return m_ContourVector.size();
}
mitk::ContourSet::ContourVectorType mitk::ContourSet::GetContours()
{
return m_ContourVector;
}
diff --git a/Modules/Segmentation/DataManagement/mitkExtrudedContour.cpp b/Modules/Segmentation/DataManagement/mitkExtrudedContour.cpp
index 429a4bdb46..dd4ba243af 100644
--- a/Modules/Segmentation/DataManagement/mitkExtrudedContour.cpp
+++ b/Modules/Segmentation/DataManagement/mitkExtrudedContour.cpp
@@ -1,374 +1,373 @@
/*===================================================================
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 "mitkExtrudedContour.h"
#include "mitkVector.h"
#include "mitkBaseProcess.h"
#include "mitkProportionalTimeGeometry.h"
#include <vtkLinearExtrusionFilter.h>
#include <vtkPolyData.h>
#include <vtkPoints.h>
#include <vtkCellArray.h>
#include <vtkPlanes.h>
#include <vtkClipPolyData.h>
#include <vtkPolygon.h>
#include <vtkFloatArray.h>
#include <vtkDoubleArray.h>
#include <vtkPlane.h>
//vtkButterflySubdivisionFilter * subdivs;
#include <vtkSampleFunction.h>
#include <vtkTriangleFilter.h>
#include <vtkLinearSubdivisionFilter.h>
#include <vtkImageData.h>
#include <vtkCubeSource.h>
mitk::ExtrudedContour::ExtrudedContour()
: m_Contour(NULL), m_ClippingGeometry(NULL), m_AutomaticVectorGeneration(false)
{
ProportionalTimeGeometry::Pointer timeGeometry = ProportionalTimeGeometry::New();
timeGeometry->Initialize(1);
SetTimeGeometry(timeGeometry);
FillVector3D(m_Vector, 0.0, 0.0, 1.0);
m_RightVector.Fill(0.0);
m_ExtrusionFilter = vtkLinearExtrusionFilter::New();
m_ExtrusionFilter->CappingOff();
m_ExtrusionFilter->SetExtrusionTypeToVectorExtrusion();
double vtkvector[3]={0,0,1};
// set extrusion vector
m_ExtrusionFilter->SetVector(vtkvector);
m_TriangleFilter = vtkTriangleFilter::New();
m_TriangleFilter->SetInputConnection(m_ExtrusionFilter->GetOutputPort());
m_SubdivisionFilter = vtkLinearSubdivisionFilter::New();
m_SubdivisionFilter->SetInputConnection(m_TriangleFilter->GetOutputPort());
m_SubdivisionFilter->SetNumberOfSubdivisions(4);
m_ClippingBox = vtkPlanes::New();
m_ClipPolyDataFilter = vtkClipPolyData::New();
m_ClipPolyDataFilter->SetInputConnection(m_SubdivisionFilter->GetOutputPort());
m_ClipPolyDataFilter->SetClipFunction(m_ClippingBox);
m_ClipPolyDataFilter->InsideOutOn();
m_Polygon = vtkPolygon::New();
m_ProjectionPlane = mitk::PlaneGeometry::New();
}
mitk::ExtrudedContour::~ExtrudedContour()
{
m_ClipPolyDataFilter->Delete();
m_ClippingBox->Delete();
m_SubdivisionFilter->Delete();
m_TriangleFilter->Delete();
m_ExtrusionFilter->Delete();
m_Polygon->Delete();
}
bool mitk::ExtrudedContour::IsInside(const Point3D& worldPoint) const
{
static double polygonNormal[3]={0.0,0.0,1.0};
// project point onto plane
float xt[3];
itk2vtk(worldPoint, xt);
xt[0] = worldPoint[0]-m_Origin[0];
xt[1] = worldPoint[1]-m_Origin[1];
xt[2] = worldPoint[2]-m_Origin[2];
float dist=xt[0]*m_Normal[0]+xt[1]*m_Normal[1]+xt[2]*m_Normal[2];
xt[0] -= dist*m_Normal[0];
xt[1] -= dist*m_Normal[1];
xt[2] -= dist*m_Normal[2];
double x[3];
x[0] = xt[0]*m_Right[0]+xt[1]*m_Right[1]+xt[2]*m_Right[2];
x[1] = xt[0]*m_Down[0] +xt[1]*m_Down[1] +xt[2]*m_Down[2];
x[2] = 0;
// determine whether it's in the selection loop and then evaluate point
// in polygon only if absolutely necessary.
if ( x[0] >= this->m_ProjectedContourBounds[0] && x[0] <= this->m_ProjectedContourBounds[1] &&
x[1] >= this->m_ProjectedContourBounds[2] && x[1] <= this->m_ProjectedContourBounds[3] &&
this->m_Polygon->PointInPolygon(x, m_Polygon->Points->GetNumberOfPoints(),
((vtkDoubleArray *)this->m_Polygon->Points->GetData())->GetPointer(0),
(double*)const_cast<mitk::ExtrudedContour*>(this)->m_ProjectedContourBounds, polygonNormal) == 1 )
return true;
else
return false;
}
mitk::ScalarType mitk::ExtrudedContour::GetVolume()
{
return -1.0;
}
void mitk::ExtrudedContour::UpdateOutputInformation()
{
if ( this->GetSource() )
{
this->GetSource()->UpdateOutputInformation();
}
if(GetMTime() > m_LastCalculateExtrusionTime)
{
BuildGeometry();
BuildSurface();
}
//if ( ( m_CalculateBoundingBox ) && ( m_PolyDataSeries.size() > 0 ) )
// CalculateBoundingBox();
}
void mitk::ExtrudedContour::BuildSurface()
{
if(m_Contour.IsNull())
{
SetVtkPolyData(NULL);
return;
}
// set extrusion contour
vtkPolyData *polyData = vtkPolyData::New();
vtkCellArray *polys = vtkCellArray::New();
polys->InsertNextCell(m_Polygon->GetPointIds());
polyData->SetPoints(m_Polygon->GetPoints());
//float vtkpoint[3];
//unsigned int i, numPts = m_Polygon->GetNumberOfPoints();
//for(i=0; i<numPts; ++i)
//{
// float * vtkpoint = this->m_Polygon->Points->GetPoint(i);
// pointids[i]=loopPoints->InsertNextPoint(vtkpoint);
//}
//polys->InsertNextCell( i, pointids );
//delete [] pointids;
//polyData->SetPoints( loopPoints );
polyData->SetPolys( polys );
polys->Delete();
m_ExtrusionFilter->SetInputData(polyData);
polyData->Delete();
// set extrusion scale factor
m_ExtrusionFilter->SetScaleFactor(GetGeometry()->GetExtentInMM(2));
SetVtkPolyData(m_SubdivisionFilter->GetOutput());
//if(m_ClippingGeometry.IsNull())
//{
// SetVtkPolyData(m_SubdivisionFilter->GetOutput());
//}
//else
//{
// m_ClipPolyDataFilter->SetInput(m_SubdivisionFilter->GetOutput());
// mitk::BoundingBox::BoundsArrayType bounds=m_ClippingGeometry->GetBounds();
// m_ClippingBox->SetBounds(bounds[0], bounds[1], bounds[2], bounds[3], bounds[4], bounds[5]);
// m_ClippingBox->SetTransform(GetGeometry()->GetVtkTransform());
// m_ClipPolyDataFilter->SetClipFunction(m_ClippingBox);
// m_ClipPolyDataFilter->SetValue(0);
// SetVtkPolyData(m_ClipPolyDataFilter->GetOutput());
//}
m_LastCalculateExtrusionTime.Modified();
}
void mitk::ExtrudedContour::BuildGeometry()
{
if(m_Contour.IsNull())
return;
// Initialize(1);
Vector3D nullvector; nullvector.Fill(0.0);
float xProj[3];
unsigned int i;
unsigned int numPts = 20; //m_Contour->GetNumberOfPoints();
mitk::Contour::PathPointer path = m_Contour->GetContourPath();
mitk::Contour::PathType::InputType cstart = path->StartOfInput();
mitk::Contour::PathType::InputType cend = path->EndOfInput();
mitk::Contour::PathType::InputType cstep = (cend-cstart)/numPts;
mitk::Contour::PathType::InputType ccur;
// Part I: guarantee/calculate legal vectors
m_Vector.Normalize();
itk2vtk(m_Vector, m_Normal);
// check m_Vector
if(mitk::Equal(m_Vector, nullvector) || m_AutomaticVectorGeneration)
{
if ( m_AutomaticVectorGeneration == false)
itkWarningMacro("Extrusion vector is 0 ("<< m_Vector << "); trying to use normal of polygon");
vtkPoints *loopPoints = vtkPoints::New();
//mitk::Contour::PointsContainerIterator pointsIt = m_Contour->GetPoints()->Begin();
double vtkpoint[3];
unsigned int i=0;
for(i=0, ccur=cstart; i<numPts; ++i, ccur+=cstep)
{
itk2vtk(path->Evaluate(ccur), vtkpoint);
loopPoints->InsertNextPoint(vtkpoint);
}
// Make sure points define a loop with a m_Normal
vtkPolygon::ComputeNormal(loopPoints, m_Normal);
loopPoints->Delete();
vtk2itk(m_Normal, m_Vector);
if(mitk::Equal(m_Vector, nullvector))
{
itkExceptionMacro("Cannot calculate normal of polygon");
}
}
// check m_RightVector
if((mitk::Equal(m_RightVector, nullvector)) || (mitk::Equal(m_RightVector*m_Vector, 0.0)==false))
{
if(mitk::Equal(m_RightVector, nullvector))
{
itkDebugMacro("Right vector is 0. Calculating.");
}
else
{
itkWarningMacro("Right vector ("<<m_RightVector<<") not perpendicular to extrusion vector "<<m_Vector<<": "<<m_RightVector*m_Vector);
}
// calculate a legal m_RightVector
if( mitk::Equal( m_Vector[1], 0.0f ) == false )
{
FillVector3D( m_RightVector, 1.0f, -m_Vector[0]/m_Vector[1], 0.0f );
m_RightVector.Normalize();
}
else
{
FillVector3D( m_RightVector, 0.0f, 1.0f, 0.0f );
}
}
// calculate down-vector
VnlVector rightDV = m_RightVector.GetVnlVector(); rightDV.normalize(); vnl2vtk(rightDV, m_Right);
VnlVector downDV = vnl_cross_3d( m_Vector.GetVnlVector(), rightDV ); downDV.normalize(); vnl2vtk(downDV, m_Down);
// Part II: calculate plane as base for extrusion, project the contour
// on this plane and store as polygon for IsInside test and BoundingBox calculation
// initialize m_ProjectionPlane, yet with origin at 0
m_ProjectionPlane->InitializeStandardPlane(rightDV, downDV);
// create vtkPolygon from contour and simultaneously determine 2D bounds of
// contour projected on m_ProjectionPlane
//mitk::Contour::PointsContainerIterator pointsIt = m_Contour->GetPoints()->Begin();
m_Polygon->Points->Reset();
m_Polygon->Points->SetNumberOfPoints(numPts);
m_Polygon->PointIds->Reset();
m_Polygon->PointIds->SetNumberOfIds(numPts);
mitk::Point2D pt2d;
mitk::Point3D pt3d;
mitk::Point2D min, max;
min.Fill(ScalarTypeNumericTraits::max());
max.Fill(ScalarTypeNumericTraits::min());
xProj[2]=0.0;
for(i=0, ccur=cstart; i<numPts; ++i, ccur+=cstep)
{
pt3d.CastFrom(path->Evaluate(ccur));
m_ProjectionPlane->Map(pt3d, pt2d);
xProj[0]=pt2d[0];
if(pt2d[0]<min[0]) min[0]=pt2d[0];
if(pt2d[0]>max[0]) max[0]=pt2d[0];
xProj[1]=pt2d[1];
if(pt2d[1]<min[1]) min[1]=pt2d[1];
if(pt2d[1]>max[1]) max[1]=pt2d[1];
m_Polygon->Points->SetPoint(i, xProj);
m_Polygon->PointIds->SetId(i, i);
}
// shift parametric origin to (0,0)
for(i=0; i<numPts; ++i)
{
double * pt = this->m_Polygon->Points->GetPoint(i);
pt[0]-=min[0]; pt[1]-=min[1];
itkDebugMacro( << i << ": (" << pt[0] << "," << pt[1] << "," << pt[2] << ")" );
}
this->m_Polygon->GetBounds(m_ProjectedContourBounds);
//m_ProjectedContourBounds[4]=-1.0; m_ProjectedContourBounds[5]=1.0;
// calculate origin (except translation along the normal) and bounds
// of m_ProjectionPlane:
// origin is composed of the minimum x-/y-coordinates of the polygon,
// bounds from the extent of the polygon, both after projecting on the plane
mitk::Point3D origin;
m_ProjectionPlane->Map(min, origin);
ScalarType bounds[6]={0, max[0]-min[0], 0, max[1]-min[1], 0, 1};
m_ProjectionPlane->SetBounds(bounds);
m_ProjectionPlane->SetOrigin(origin);
// Part III: initialize geometry
if(m_ClippingGeometry.IsNotNull())
{
ScalarType min_dist=ScalarTypeNumericTraits::max(), max_dist=ScalarTypeNumericTraits::min(), dist;
unsigned char i;
for(i=0; i<8; ++i)
{
dist = m_ProjectionPlane->SignedDistance( m_ClippingGeometry->GetCornerPoint(i) );
if(dist<min_dist) min_dist=dist;
if(dist>max_dist) max_dist=dist;
}
//incorporate translation along the normal into origin
origin = origin+m_Vector*min_dist;
m_ProjectionPlane->SetOrigin(origin);
bounds[5]=max_dist-min_dist;
}
else
bounds[5]=20;
itk2vtk(origin, m_Origin);
- mitk::Geometry3D::Pointer g3d = GetGeometry( 0 );
+ mitk::BaseGeometry::Pointer g3d = GetGeometry( 0 );
assert( g3d.IsNotNull() );
g3d->SetBounds(bounds);
g3d->SetIndexToWorldTransform(m_ProjectionPlane->GetIndexToWorldTransform());
- g3d->TransferItkToVtkTransform();
ProportionalTimeGeometry::Pointer timeGeometry = ProportionalTimeGeometry::New();
timeGeometry->Initialize(g3d,1);
SetTimeGeometry(timeGeometry);
}
unsigned long mitk::ExtrudedContour::GetMTime() const
{
unsigned long latestTime = Superclass::GetMTime();
if(m_Contour.IsNotNull())
{
unsigned long localTime;
localTime = m_Contour->GetMTime();
if(localTime > latestTime) latestTime = localTime;
}
return latestTime;
}
diff --git a/Modules/Segmentation/DataManagement/mitkExtrudedContour.h b/Modules/Segmentation/DataManagement/mitkExtrudedContour.h
index d0ac18d482..06396245dd 100644
--- a/Modules/Segmentation/DataManagement/mitkExtrudedContour.h
+++ b/Modules/Segmentation/DataManagement/mitkExtrudedContour.h
@@ -1,128 +1,128 @@
/*===================================================================
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 MITKEXTRUDEDCONTOUR_H_HEADER_INCLUDED
#define MITKEXTRUDEDCONTOUR_H_HEADER_INCLUDED
#include "mitkBoundingObject.h"
#include <MitkSegmentationExports.h>
#include <mitkContour.h>
#include <vtkConfigure.h>
#include <mitkPlaneGeometry.h>
#include <vtkVersionMacros.h>
class vtkLinearExtrusionFilter;
class vtkPlanes;
class vtkClipPolyData;
class vtkLinearSubdivisionFilter;
class vtkTriangleFilter;
class vtkDecimatePro;
class vtkPolygon;
namespace mitk {
//##Documentation
//## @brief Data class containing a bounding-object created by
//## extruding a Contour along a vector
//##
//## The m_Contour is extruded in the direction m_Vector until
//## reaching m_ClippingGeometry.
//## @ingroup Data
class MitkSegmentation_EXPORT ExtrudedContour : public BoundingObject
{
public:
mitkClassMacro(ExtrudedContour, BoundingObject);
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
virtual mitk::ScalarType GetVolume();
virtual bool IsInside(const Point3D& p) const;
virtual void UpdateOutputInformation();
//##Documentation
//## @brief Contour to extrude
itkGetConstObjectMacro(Contour, mitk::Contour);
itkSetObjectMacro(Contour, mitk::Contour);
//##Documentation
//## @brief Vector to specify the direction of the extrusion
mitkGetVectorMacro(Vector, mitk::Vector3D);
mitkSetVectorMacro(Vector, mitk::Vector3D);
itkGetConstMacro(AutomaticVectorGeneration, bool);
itkSetMacro(AutomaticVectorGeneration, bool);
itkBooleanMacro(AutomaticVectorGeneration);
//##Documentation
//## @brief Optional vector to specify the orientation of the bounding-box
mitkGetVectorMacro(RightVector, mitk::Vector3D);
mitkSetVectorMacro(RightVector, mitk::Vector3D);
//##Documentation
//## @brief Optional geometry for clipping the extruded contour
- itkGetConstObjectMacro(ClippingGeometry, mitk::Geometry3D);
- itkSetObjectMacro(ClippingGeometry, mitk::Geometry3D);
+ itkGetConstObjectMacro(ClippingGeometry, mitk::BaseGeometry);
+ itkSetObjectMacro(ClippingGeometry, mitk::BaseGeometry);
virtual unsigned long GetMTime() const;
protected:
ExtrudedContour();
virtual ~ExtrudedContour();
void BuildSurface();
void BuildGeometry();
mitk::Contour::Pointer m_Contour;
mitk::Vector3D m_Vector;
mitk::Vector3D m_RightVector;
- mitk::Geometry3D::Pointer m_ClippingGeometry;
+ mitk::BaseGeometry::Pointer m_ClippingGeometry;
bool m_AutomaticVectorGeneration;
vtkPolygon* m_Polygon;
#if ((VTK_MAJOR_VERSION > 4) || ((VTK_MAJOR_VERSION==4) && (VTK_MINOR_VERSION>=4) ))
double m_ProjectedContourBounds[6];
#else
float m_ProjectedContourBounds[6];
#endif
mitk::PlaneGeometry::Pointer m_ProjectionPlane;
//##Documentation
//## @brief For fast projection on plane
float m_Right[3];
float m_Down[3];
#if ((VTK_MAJOR_VERSION > 4) || ((VTK_MAJOR_VERSION==4) && (VTK_MINOR_VERSION>=4) ))
double m_Normal[3];
#else
float m_Normal[3];
#endif
float m_Origin[3];
vtkLinearExtrusionFilter* m_ExtrusionFilter;
vtkTriangleFilter *m_TriangleFilter;
vtkDecimatePro* m_Decimate;
vtkLinearSubdivisionFilter* m_SubdivisionFilter;
vtkPlanes* m_ClippingBox;
vtkClipPolyData* m_ClipPolyDataFilter;
itk::TimeStamp m_LastCalculateExtrusionTime;
};
}
#endif /* MITKEXTRUDEDCONTOUR_H_HEADER_INCLUDED */
diff --git a/Modules/Segmentation/Interactions/mitkContourTool.cpp b/Modules/Segmentation/Interactions/mitkContourTool.cpp
index d50bc8e081..1346febe80 100644
--- a/Modules/Segmentation/Interactions/mitkContourTool.cpp
+++ b/Modules/Segmentation/Interactions/mitkContourTool.cpp
@@ -1,187 +1,187 @@
/*===================================================================
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 "mitkContourTool.h"
#include "mitkToolManager.h"
#include "mitkOverwriteSliceImageFilter.h"
#include "mitkOverwriteDirectedPlaneImageFilter.h"
#include "mitkBaseRenderer.h"
#include "mitkRenderingManager.h"
//#include "mitkProperties.h"
//#include "mitkPlanarCircle.h"
#include "mitkStateMachineAction.h"
#include "mitkInteractionEvent.h"
mitk::ContourTool::ContourTool(int paintingPixelValue)
:FeedbackContourTool("PressMoveReleaseWithCTRLInversion"),
m_PaintingPixelValue(paintingPixelValue)
{
}
mitk::ContourTool::~ContourTool()
{
}
void mitk::ContourTool::ConnectActionsAndFunctions()
{
CONNECT_FUNCTION( "PrimaryButtonPressed", OnMousePressed);
CONNECT_FUNCTION( "Move", OnMouseMoved);
CONNECT_FUNCTION( "Release", OnMouseReleased);
CONNECT_FUNCTION( "InvertLogic", OnInvertLogic);
}
void mitk::ContourTool::Activated()
{
Superclass::Activated();
}
void mitk::ContourTool::Deactivated()
{
Superclass::Deactivated();
}
/**
Just show the contour, insert the first point.
*/
bool mitk::ContourTool::OnMousePressed( StateMachineAction*, InteractionEvent* interactionEvent )
{
mitk::InteractionPositionEvent* positionEvent = dynamic_cast<mitk::InteractionPositionEvent*>( interactionEvent );
//const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(interactionEvent->GetEvent());
if (!positionEvent) return false;
m_LastEventSender = positionEvent->GetSender();
m_LastEventSlice = m_LastEventSender->GetSlice();
// if ( FeedbackContourTool::CanHandleEvent(stateEvent) < 1.0 ) return false;
int timestep = positionEvent->GetSender()->GetTimeStep();
ContourModel* contour = FeedbackContourTool::GetFeedbackContour();
//Clear feedback contour
contour->Initialize();
//expand time bounds because our contour was initialized
contour->Expand( timestep + 1 );
//draw as a closed contour
contour->SetClosed(true,timestep);
//add first mouse position
mitk::Point3D point = positionEvent->GetPositionInWorld();
contour->AddVertex( point, timestep );
FeedbackContourTool::SetFeedbackContourVisible(true);
assert( positionEvent->GetSender()->GetRenderWindow() );
mitk::RenderingManager::GetInstance()->RequestUpdate( positionEvent->GetSender()->GetRenderWindow() );
return true;
}
/**
Insert the point to the feedback contour.
*/
bool mitk::ContourTool::OnMouseMoved( StateMachineAction*, InteractionEvent* interactionEvent )
{
//if ( FeedbackContourTool::CanHandleEvent(stateEvent) < 1.0 ) return false;
mitk::InteractionPositionEvent* positionEvent = dynamic_cast<mitk::InteractionPositionEvent*>( interactionEvent );
//const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent());
if (!positionEvent) return false;
int timestep = positionEvent->GetSender()->GetTimeStep();
ContourModel* contour = FeedbackContourTool::GetFeedbackContour();
mitk::Point3D point = positionEvent->GetPositionInWorld();
contour->AddVertex( point, timestep );
assert( positionEvent->GetSender()->GetRenderWindow() );
mitk::RenderingManager::GetInstance()->RequestUpdate( positionEvent->GetSender()->GetRenderWindow() );
return true;
}
/**
Close the contour, project it to the image slice and fill it in 2D.
*/
bool mitk::ContourTool::OnMouseReleased( StateMachineAction*, InteractionEvent* interactionEvent )
{
// 1. Hide the feedback contour, find out which slice the user clicked, find out which slice of the toolmanager's working image corresponds to that
FeedbackContourTool::SetFeedbackContourVisible(false);
mitk::InteractionPositionEvent* positionEvent = dynamic_cast<mitk::InteractionPositionEvent*>( interactionEvent );
//const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent());
if (!positionEvent) return false;
assert( positionEvent->GetSender()->GetRenderWindow() );
mitk::RenderingManager::GetInstance()->RequestUpdate( positionEvent->GetSender()->GetRenderWindow() );
//if ( FeedbackContourTool::CanHandleEvent(stateEvent) < 1.0 ) return false;
DataNode* workingNode( m_ToolManager->GetWorkingData(0) );
if (!workingNode) return false;
Image* image = dynamic_cast<Image*>(workingNode->GetData());
- const PlaneGeometry* planeGeometry( dynamic_cast<const PlaneGeometry*> (positionEvent->GetSender()->GetCurrentWorldGeometry2D() ) );
+ const PlaneGeometry* planeGeometry( dynamic_cast<const PlaneGeometry*> (positionEvent->GetSender()->GetCurrentWorldPlaneGeometry() ) );
if ( !image || !planeGeometry ) return false;
// 2. Slice is known, now we try to get it as a 2D image and project the contour into index coordinates of this slice
Image::Pointer slice = SegTool2D::GetAffectedImageSliceAs2DImage( positionEvent, image );
if ( slice.IsNull() )
{
MITK_ERROR << "Unable to extract slice." << std::endl;
return false;
}
ContourModel* feedbackContour = FeedbackContourTool::GetFeedbackContour();
ContourModel::Pointer projectedContour = FeedbackContourTool::ProjectContourTo2DSlice( slice, feedbackContour, true, false ); // true: actually no idea why this is neccessary, but it works :-(
if (projectedContour.IsNull()) return false;
int timestep = positionEvent->GetSender()->GetTimeStep();
FeedbackContourTool::FillContourInSlice( projectedContour, timestep, slice, m_PaintingPixelValue );
this->WriteBackSegmentationResult(positionEvent, slice);
// 4. Make sure the result is drawn again --> is visible then.
assert( positionEvent->GetSender()->GetRenderWindow() );
return true;
}
/**
Called when the CTRL key is pressed. Will change the painting pixel value from 0 to 1 or from 1 to 0.
*/
bool mitk::ContourTool::OnInvertLogic( StateMachineAction*, InteractionEvent* interactionEvent )
{
// if ( FeedbackContourTool::CanHandleEvent(stateEvent) < 1.0 ) return false;
// Inversion only for 0 and 1 as painting values
if (m_PaintingPixelValue == 1)
{
m_PaintingPixelValue = 0;
FeedbackContourTool::SetFeedbackContourColor( 1.0, 0.0, 0.0 );
}
else if (m_PaintingPixelValue == 0)
{
m_PaintingPixelValue = 1;
FeedbackContourTool::SetFeedbackContourColorDefault();
}
return true;
}
diff --git a/Modules/Segmentation/Interactions/mitkCorrectorTool2D.cpp b/Modules/Segmentation/Interactions/mitkCorrectorTool2D.cpp
index c76f5951b0..265382a55d 100644
--- a/Modules/Segmentation/Interactions/mitkCorrectorTool2D.cpp
+++ b/Modules/Segmentation/Interactions/mitkCorrectorTool2D.cpp
@@ -1,195 +1,195 @@
/*===================================================================
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 "mitkCorrectorTool2D.h"
#include "mitkCorrectorAlgorithm.h"
#include "mitkToolManager.h"
#include "mitkBaseRenderer.h"
#include "mitkRenderingManager.h"
#include "mitkImageReadAccessor.h"
#include "mitkCorrectorTool2D.xpm"
// us
#include <usModule.h>
#include <usModuleResource.h>
#include <usGetModuleContext.h>
#include <usModuleContext.h>
namespace mitk {
MITK_TOOL_MACRO(MitkSegmentation_EXPORT, CorrectorTool2D, "Correction tool");
}
mitk::CorrectorTool2D::CorrectorTool2D(int paintingPixelValue)
:FeedbackContourTool("PressMoveRelease"),
m_PaintingPixelValue(paintingPixelValue)
{
GetFeedbackContour()->SetClosed( false ); // don't close the contour to a polygon
}
mitk::CorrectorTool2D::~CorrectorTool2D()
{
}
void mitk::CorrectorTool2D::ConnectActionsAndFunctions()
{
CONNECT_FUNCTION( "PrimaryButtonPressed", OnMousePressed);
CONNECT_FUNCTION( "Move", OnMouseMoved);
CONNECT_FUNCTION( "Release", OnMouseReleased);
}
const char** mitk::CorrectorTool2D::GetXPM() const
{
return mitkCorrectorTool2D_xpm;
}
us::ModuleResource mitk::CorrectorTool2D::GetIconResource() const
{
us::Module* module = us::GetModuleContext()->GetModule();
us::ModuleResource resource = module->GetResource("Correction_48x48.png");
return resource;
}
us::ModuleResource mitk::CorrectorTool2D::GetCursorIconResource() const
{
us::Module* module = us::GetModuleContext()->GetModule();
us::ModuleResource resource = module->GetResource("Correction_Cursor_32x32.png");
return resource;
}
const char* mitk::CorrectorTool2D::GetName() const
{
return "Correction";
}
void mitk::CorrectorTool2D::Activated()
{
Superclass::Activated();
}
void mitk::CorrectorTool2D::Deactivated()
{
Superclass::Deactivated();
}
bool mitk::CorrectorTool2D::OnMousePressed ( StateMachineAction*, InteractionEvent* interactionEvent )
{
mitk::InteractionPositionEvent* positionEvent = dynamic_cast<mitk::InteractionPositionEvent*>( interactionEvent );
//const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent());
if (!positionEvent) return false;
m_LastEventSender = positionEvent->GetSender();
m_LastEventSlice = m_LastEventSender->GetSlice();
//if ( FeedbackContourTool::CanHandleEvent(stateEvent) < 1.0 ) return false;
int timestep = positionEvent->GetSender()->GetTimeStep();
ContourModel* contour = FeedbackContourTool::GetFeedbackContour();
contour->Clear();
contour->Expand(timestep + 1);
contour->SetClosed(false, timestep);
mitk::Point3D point = positionEvent->GetPositionInWorld();
contour->AddVertex( point, timestep );
FeedbackContourTool::SetFeedbackContourVisible(true);
return true;
}
bool mitk::CorrectorTool2D::OnMouseMoved( StateMachineAction*, InteractionEvent* interactionEvent )
{
//if ( FeedbackContourTool::CanHandleEvent(stateEvent) < 1.0 ) return false;
mitk::InteractionPositionEvent* positionEvent = dynamic_cast<mitk::InteractionPositionEvent*>( interactionEvent );
//const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent());
if (!positionEvent) return false;
int timestep = positionEvent->GetSender()->GetTimeStep();
ContourModel* contour = FeedbackContourTool::GetFeedbackContour();
mitk::Point3D point = positionEvent->GetPositionInWorld();
contour->AddVertex( point, timestep );
assert( positionEvent->GetSender()->GetRenderWindow() );
mitk::RenderingManager::GetInstance()->RequestUpdate( positionEvent->GetSender()->GetRenderWindow() );
return true;
}
bool mitk::CorrectorTool2D::OnMouseReleased( StateMachineAction*, InteractionEvent* interactionEvent )
{
// 1. Hide the feedback contour, find out which slice the user clicked, find out which slice of the toolmanager's working image corresponds to that
FeedbackContourTool::SetFeedbackContourVisible(false);
mitk::InteractionPositionEvent* positionEvent = dynamic_cast<mitk::InteractionPositionEvent*>( interactionEvent );
//const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent());
if (!positionEvent) return false;
assert( positionEvent->GetSender()->GetRenderWindow() );
mitk::RenderingManager::GetInstance()->RequestUpdate( positionEvent->GetSender()->GetRenderWindow() );
//if ( FeedbackContourTool::CanHandleEvent(stateEvent) < 1.0 ) return false;
DataNode* workingNode( m_ToolManager->GetWorkingData(0) );
if (!workingNode) return false;
Image* image = dynamic_cast<Image*>(workingNode->GetData());
- const PlaneGeometry* planeGeometry( dynamic_cast<const PlaneGeometry*> (positionEvent->GetSender()->GetCurrentWorldGeometry2D() ) );
+ const PlaneGeometry* planeGeometry( dynamic_cast<const PlaneGeometry*> (positionEvent->GetSender()->GetCurrentWorldPlaneGeometry() ) );
if ( !image || !planeGeometry ) return false;
// 2. Slice is known, now we try to get it as a 2D image and project the contour into index coordinates of this slice
m_WorkingSlice = FeedbackContourTool::GetAffectedImageSliceAs2DImage( positionEvent, image );
if ( m_WorkingSlice.IsNull() )
{
MITK_ERROR << "Unable to extract slice." << std::endl;
return false;
}
int timestep = positionEvent->GetSender()->GetTimeStep();
mitk::ContourModel::Pointer singleTimestepContour = mitk::ContourModel::New();
mitk::ContourModel::VertexIterator it = FeedbackContourTool::GetFeedbackContour()->Begin(timestep);
mitk::ContourModel::VertexIterator end = FeedbackContourTool::GetFeedbackContour()->End(timestep);
while(it!=end)
{
singleTimestepContour->AddVertex((*it)->Coordinates);
it++;
}
CorrectorAlgorithm::Pointer algorithm = CorrectorAlgorithm::New();
algorithm->SetInput( m_WorkingSlice );
algorithm->SetContour( singleTimestepContour );
try
{
algorithm->UpdateLargestPossibleRegion();
}
catch ( std::exception& e )
{
MITK_ERROR << "Caught exception '" << e.what() << "'" << std::endl;
}
mitk::Image::Pointer resultSlice = mitk::Image::New();
resultSlice->Initialize(algorithm->GetOutput());
mitk::ImageReadAccessor imAccess(algorithm->GetOutput());
resultSlice->SetVolume(imAccess.GetData());
this->WriteBackSegmentationResult(positionEvent, resultSlice);
return true;
}
diff --git a/Modules/Segmentation/Interactions/mitkExtrudedContourInteractor.cpp b/Modules/Segmentation/Interactions/mitkExtrudedContourInteractor.cpp
index 020f50dd4c..ee7cf45a26 100644
--- a/Modules/Segmentation/Interactions/mitkExtrudedContourInteractor.cpp
+++ b/Modules/Segmentation/Interactions/mitkExtrudedContourInteractor.cpp
@@ -1,201 +1,201 @@
/*===================================================================
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 "mitkExtrudedContourInteractor.h"
#include <mitkContour.h>
#include <mitkExtrudedContour.h>
#include <mitkStateEvent.h>
#include <mitkUndoController.h>
#include <mitkProperties.h>
#include <mitkStringProperty.h>
#include <mitkPointOperation.h>
#include <mitkAction.h>
#include <mitkPositionEvent.h>
#include <mitkInteractionConst.h>
#include <mitkPositionEvent.h>
#include <mitkVtkPropRenderer.h>
#include <mitkDataNodeFactory.h>
#include <mitkVtkRepresentationProperty.h>
#include <vtkRenderer.h>
#include <vtkCamera.h>
mitk::ExtrudedContourInteractor::ExtrudedContourInteractor(const char * type, mitk::DataNode* dataNode)
: mitk::Interactor(type, dataNode), m_Started(false)
{
assert(m_DataNode != NULL);
m_DataNode->SetProperty( "material.representation", mitk::VtkRepresentationProperty::New("surface") );
m_Contour = mitk::Contour::New();
m_ContourNode = mitk::DataNode::New();
m_ContourNode->SetData(m_Contour);
m_ContourNode->SetProperty("layer", mitk::IntProperty::New(100) );
m_ContourNode->SetProperty("name", mitk::StringProperty::New("InteractiveFeedbackData") );
m_ContourNode->SetOpacity(1);
m_ContourNode->SetColor(0.4,0.9,0.0);
m_ContourNode->SetProperty( "Width", mitk::FloatProperty::New(2.0) );
m_Started = false;
}
mitk::ExtrudedContourInteractor::~ExtrudedContourInteractor()
{
}
//mitk::Contour::Pointer ExtrudedContourInteractor::ExtractContour(mitkIpPicDescriptor* pic)
//{
// int idx;
// int size = _mitkIpPicElements (pic);
// for (idx = 0; idx < size; idx++)
// if ( ((mitkIpUInt1_t*) pic->data)[idx]> 0) break;
//
// int sizePoints; // size of the _points buffer (number of coordinate pairs that fit in)
// int numPoints; // number of coordinate pairs stored in _points buffer
// float *points = 0;
//
// points = ipSegmentationGetContour8N( pic, idx, numPoints, sizePoints, points );
//
// mitk::Contour::Pointer m_Contour = mitk::Contour::New();
// m_Contour->Initialize();
// mitk::Point3D pointInMM, pointInUnits;
// mitk::Point3D itkPoint;
// for (int pointIdx = 0; pointIdx < numPoints; pointIdx++)
// {
// pointInUnits[0] = points[2*pointIdx];
// pointInUnits[1] = points[2*pointIdx+1];
// pointInUnits[2] = m_ZCoord;
// m_SelectedImageGeometry->IndexToWorld(CorrectPointCoordinates(pointInUnits),pointInMM);
// m_Contour->AddVertex(pointInMM);
// }
// return m_Contour;
//}
bool mitk::ExtrudedContourInteractor::ExecuteAction(mitk::Action* action, mitk::StateEvent const* stateEvent)
{
mitk::Point3D eventPoint;
mitk::Vector3D eventPlaneNormal;
const mitk::PositionEvent* posEvent = dynamic_cast<const mitk::PositionEvent*>(stateEvent->GetEvent());
if(posEvent==NULL)
{
const mitk::DisplayPositionEvent* displayPosEvent = dynamic_cast<const mitk::DisplayPositionEvent*>(stateEvent->GetEvent());
mitk::VtkPropRenderer* sender = (mitk::VtkPropRenderer*) stateEvent->GetEvent()->GetSender();
if((displayPosEvent == NULL) || (sender == NULL))
return false;
eventPoint[0] = displayPosEvent->GetDisplayPosition()[0];
eventPoint[1] = displayPosEvent->GetDisplayPosition()[1];
eventPoint[2] = 0;
typedef itk::Point<double,3> DoublePoint3D;
DoublePoint3D p;
p.CastFrom(eventPoint);
sender->GetVtkRenderer()->SetDisplayPoint(p.GetDataPointer());
sender->GetVtkRenderer()->DisplayToWorld();
double *vtkwp = sender->GetVtkRenderer()->GetWorldPoint();
vtk2itk(vtkwp, eventPoint);
double *vtkvpn = sender->GetVtkRenderer()->GetActiveCamera()->GetViewPlaneNormal();
vtk2itk(vtkvpn, eventPlaneNormal); eventPlaneNormal = -eventPlaneNormal;
}
else
{
eventPoint = posEvent->GetWorldPosition();
mitk::BaseRenderer* sender = (mitk::BaseRenderer*) stateEvent->GetEvent()->GetSender();
- eventPlaneNormal = sender->GetCurrentWorldGeometry2D()->GetAxisVector(2);
+ eventPlaneNormal = sender->GetCurrentWorldPlaneGeometry()->GetAxisVector(2);
}
bool ok = false;
switch (action->GetActionId())
{
case mitk::AcNEWPOINT:
{
Press(eventPoint);
ok = true;
m_Started = true;
break;
}
case mitk::AcINITMOVEMENT:
{
if (m_Started)
{
Move(eventPoint);
ok = true;
break;
}
}
case mitk::AcMOVEPOINT:
{
if (m_Started)
{
Move(eventPoint);
ok = true;
break;
}
}
case mitk::AcFINISHMOVEMENT:
{
if (m_Started)
{
mitk::ExtrudedContour* extrudedcontour = dynamic_cast<mitk::ExtrudedContour*>(m_DataNode->GetData());
extrudedcontour->SetContour(m_Contour);
extrudedcontour->SetVector(eventPlaneNormal);
Release(eventPoint);
ok = true;
m_Started = false;
InvokeEvent(itk::EndEvent());
}
break;
}
default:
ok = false;
break;
}
return ok;
}
void mitk::ExtrudedContourInteractor::Press(mitk::Point3D& point)
{
if (!m_Positive)
m_ContourNode->SetColor(1.0,0.0,0.0);
m_Contour->Initialize();
m_Contour->AddVertex( point );
}
void mitk::ExtrudedContourInteractor::Move(mitk::Point3D& point)
{
assert(m_Contour.IsNotNull());
m_Contour->AddVertex( point );
// m_Parent->UpdateWidgets();
}
void mitk::ExtrudedContourInteractor::Release(mitk::Point3D& /*point*/)
{
//vermutlich m_Parent->UpdateWidgets();
}
diff --git a/Modules/Segmentation/Interactions/mitkFeedbackContourTool.cpp b/Modules/Segmentation/Interactions/mitkFeedbackContourTool.cpp
index 5b9f6016e5..be7a8af186 100644
--- a/Modules/Segmentation/Interactions/mitkFeedbackContourTool.cpp
+++ b/Modules/Segmentation/Interactions/mitkFeedbackContourTool.cpp
@@ -1,136 +1,136 @@
/*===================================================================
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 "mitkFeedbackContourTool.h"
#include "mitkToolManager.h"
#include "mitkProperties.h"
#include "mitkStringProperty.h"
#include "mitkColorProperty.h"
#include "mitkDataStorage.h"
#include "mitkBaseRenderer.h"
#include "mitkRenderingManager.h"
mitk::FeedbackContourTool::FeedbackContourTool(const char* type)
:SegTool2D(type),
m_FeedbackContourVisible(false)
{
m_FeedbackContour = ContourModel::New();
m_FeedbackContour->SetClosed(true);
m_FeedbackContourNode = DataNode::New();
m_FeedbackContourNode->SetData( m_FeedbackContour );
m_FeedbackContourNode->SetProperty("name", StringProperty::New("One of FeedbackContourTool's feedback nodes"));
m_FeedbackContourNode->SetProperty("visible", BoolProperty::New(true));
m_FeedbackContourNode->SetProperty("helper object", BoolProperty::New(true));
m_FeedbackContourNode->SetProperty("layer", IntProperty::New(1000));
m_FeedbackContourNode->SetProperty("contour.project-onto-plane", BoolProperty::New(false));
m_FeedbackContourNode->SetProperty("contour.width", FloatProperty::New(1.0));
this->Disable3dRendering();
SetFeedbackContourColorDefault();
}
mitk::FeedbackContourTool::~FeedbackContourTool()
{
}
void mitk::FeedbackContourTool::SetFeedbackContourColor( float r, float g, float b )
{
m_FeedbackContourNode->SetProperty("contour.color", ColorProperty::New(r, g, b));
}
void mitk::FeedbackContourTool::SetFeedbackContourColorDefault()
{
m_FeedbackContourNode->SetProperty("contour.color", ColorProperty::New(0.0/255.0, 255.0/255.0, 0.0/255.0));
}
mitk::ContourModel* mitk::FeedbackContourTool::GetFeedbackContour()
{
return m_FeedbackContour;
}
void mitk::FeedbackContourTool::SetFeedbackContour(ContourModel& contour)
{
// begin of temporary fix for 3m3 release
this->Disable3dRendering();
//end of temporary fix for 3m3 release
m_FeedbackContour = &contour;
m_FeedbackContourNode->SetData( m_FeedbackContour );
}
void mitk::FeedbackContourTool::SetFeedbackContourVisible(bool visible)
{
// begin of temporary fix for 3m3 release
this->Disable3dRendering();
//end of temporary fix for 3m3 release
if ( m_FeedbackContourVisible == visible )
return; // nothing changed
if ( DataStorage* storage = m_ToolManager->GetDataStorage() )
{
if (visible)
{
storage->Add( m_FeedbackContourNode );
}
else
{
storage->Remove( m_FeedbackContourNode );
}
}
m_FeedbackContourVisible = visible;
}
mitk::ContourModel::Pointer mitk::FeedbackContourTool::ProjectContourTo2DSlice(Image* slice, ContourModel* contourIn3D, bool correctionForIpSegmentation, bool constrainToInside)
{
return mitk::ContourModelUtils::ProjectContourTo2DSlice(slice, contourIn3D, correctionForIpSegmentation, constrainToInside);
}
-mitk::ContourModel::Pointer mitk::FeedbackContourTool::BackProjectContourFrom2DSlice(const Geometry3D* sliceGeometry, ContourModel* contourIn2D, bool correctionForIpSegmentation)
+mitk::ContourModel::Pointer mitk::FeedbackContourTool::BackProjectContourFrom2DSlice(const BaseGeometry* sliceGeometry, ContourModel* contourIn2D, bool correctionForIpSegmentation)
{
return mitk::ContourModelUtils::BackProjectContourFrom2DSlice(sliceGeometry, contourIn2D, correctionForIpSegmentation);
}
void mitk::FeedbackContourTool::FillContourInSlice( ContourModel* projectedContour, Image* sliceImage, int paintingPixelValue )
{
this->FillContourInSlice(projectedContour, 0, sliceImage, paintingPixelValue);
}
void mitk::FeedbackContourTool::FillContourInSlice( ContourModel* projectedContour, unsigned int timeStep, Image* sliceImage, int paintingPixelValue )
{
mitk::ContourModelUtils::FillContourInSlice(projectedContour, timeStep, sliceImage, paintingPixelValue);
}
void mitk::FeedbackContourTool::Disable3dRendering()
{
// set explicitly visible=false for all 3D renderer (that exist already ...)
const RenderingManager::RenderWindowVector& renderWindows = RenderingManager::GetInstance()->GetAllRegisteredRenderWindows();
for (RenderingManager::RenderWindowVector::const_iterator iter = renderWindows.begin();
iter != renderWindows.end();
++iter)
{
if ( mitk::BaseRenderer::GetInstance((*iter))->GetMapperID() == BaseRenderer::Standard3D )
//if ( (*iter)->GetRenderer()->GetMapperID() == BaseRenderer::Standard3D )
{
m_FeedbackContourNode->SetProperty("visible", BoolProperty::New(false), mitk::BaseRenderer::GetInstance((*iter)));
}
}
}
diff --git a/Modules/Segmentation/Interactions/mitkFeedbackContourTool.h b/Modules/Segmentation/Interactions/mitkFeedbackContourTool.h
index 999c0488e2..b33fbe4ac6 100644
--- a/Modules/Segmentation/Interactions/mitkFeedbackContourTool.h
+++ b/Modules/Segmentation/Interactions/mitkFeedbackContourTool.h
@@ -1,110 +1,110 @@
/*===================================================================
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 mitkFeedbackContourTool_h_Included
#define mitkFeedbackContourTool_h_Included
#include "mitkCommon.h"
#include <MitkSegmentationExports.h>
#include "mitkSegTool2D.h"
#include "mitkContourModelUtils.h"
#include "mitkContourUtils.h" //TODO remove legacy support
#include "mitkImage.h"
#include "mitkDataNode.h"
#include "mitkImageCast.h"
namespace mitk
{
/**
\brief Base class for tools that use a contour for feedback
\sa Tool
\sa ContourModel
\ingroup Interaction
\ingroup ToolManagerEtAl
Implements helper methods, that might be of use to all kind of 2D segmentation tools that use a contour for user feedback.
- Providing a feedback contour that might be added or removed from the visible scene (SetFeedbackContourVisible).
- Filling of a contour into a 2D slice
These helper methods are actually implemented in ContourUtils now. FeedbackContourTool only forwards such requests.
\warning Only to be instantiated by mitk::ToolManager.
$Author: nolden $
*/
class MitkSegmentation_EXPORT FeedbackContourTool : public SegTool2D
{
public:
mitkClassMacro(FeedbackContourTool, SegTool2D);
protected:
FeedbackContourTool(); // purposely hidden
FeedbackContourTool(const char*); // purposely hidden
virtual ~FeedbackContourTool();
ContourModel* GetFeedbackContour();
void SetFeedbackContour(ContourModel&);
void Disable3dRendering();
void SetFeedbackContourVisible(bool);
/// Provide values from 0.0 (black) to 1.0 (full color)
void SetFeedbackContourColor( float r, float g, float b );
void SetFeedbackContourColorDefault();
/**
\brief Projects a contour onto an image point by point. Converts from world to index coordinates.
\param correctionForIpSegmentation adds 0.5 to x and y index coordinates (difference between ipSegmentation and MITK contours)
*/
ContourModel::Pointer ProjectContourTo2DSlice(Image* slice, ContourModel* contourIn3D, bool correctionForIpSegmentation = false, bool constrainToInside = true);
/**
\brief Projects a slice index coordinates of a contour back into world coordinates.
\param correctionForIpSegmentation subtracts 0.5 to x and y index coordinates (difference between ipSegmentation and MITK contours)
*/
- ContourModel::Pointer BackProjectContourFrom2DSlice(const Geometry3D* sliceGeometry, ContourModel* contourIn2D, bool correctionForIpSegmentation = false);
+ ContourModel::Pointer BackProjectContourFrom2DSlice(const BaseGeometry* sliceGeometry, ContourModel* contourIn2D, bool correctionForIpSegmentation = false);
/**
\brief Fill a contour in a 2D slice with a specified pixel value.
*/
void FillContourInSlice( ContourModel* projectedContour, Image* sliceImage, int paintingPixelValue = 1 );
/**
\brief Fill a contour in a 2D slice with a specified pixel value at a given time step.
*/
void FillContourInSlice( ContourModel* projectedContour, unsigned int timeStep, Image* sliceImage, int paintingPixelValue = 1 );
private:
ContourModel::Pointer m_FeedbackContour;
DataNode::Pointer m_FeedbackContourNode;
bool m_FeedbackContourVisible;
};
} // namespace
#endif
diff --git a/Modules/Segmentation/Interactions/mitkLiveWireTool2D.cpp b/Modules/Segmentation/Interactions/mitkLiveWireTool2D.cpp
index 4c72aa88dd..8fb489c2e3 100644
--- a/Modules/Segmentation/Interactions/mitkLiveWireTool2D.cpp
+++ b/Modules/Segmentation/Interactions/mitkLiveWireTool2D.cpp
@@ -1,666 +1,666 @@
/*===================================================================
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 <itkGradientMagnitudeImageFilter.h>
#include <mitkBaseRenderer.h>
#include <mitkContour.h>
#include <mitkContourModelUtils.h>
#include <mitkContourUtils.h>
#include <mitkGlobalInteraction.h>
#include <mitkInteractionConst.h>
#include <mitkRenderingManager.h>
#include <mitkToolManager.h>
#include <usGetModuleContext.h>
#include <usModule.h>
#include <usModuleContext.h>
#include <usModuleResource.h>
#include "mitkLiveWireTool2D.h"
#include "mitkLiveWireTool2D.xpm"
namespace mitk
{
MITK_TOOL_MACRO(MitkSegmentation_EXPORT, LiveWireTool2D, "LiveWire tool");
}
static void AddInteractorToGlobalInteraction(mitk::Interactor* interactor)
{
mitk::GlobalInteraction::GetInstance()->AddInteractor(interactor);
}
static void RemoveInteractorFromGlobalInteraction(mitk::Interactor* interactor)
{
mitk::GlobalInteraction::GetInstance()->RemoveInteractor(interactor);
}
class RemoveFromDataStorage
{
public:
RemoveFromDataStorage(mitk::DataStorage::Pointer dataStorage)
: m_DataStorage(dataStorage)
{
}
void operator()(mitk::DataNode* dataNode)
{
m_DataStorage->Remove(dataNode);
}
void operator()(const std::pair<mitk::DataNode::Pointer, mitk::PlaneGeometry::Pointer>& dataNode)
{
m_DataStorage->Remove(dataNode.first);
}
private:
mitk::DataStorage::Pointer m_DataStorage;
};
mitk::LiveWireTool2D::LiveWireTool2D()
: SegTool2D("LiveWireTool")
{
}
mitk::LiveWireTool2D::~LiveWireTool2D()
{
this->ClearSegmentation();
}
void mitk::LiveWireTool2D::RemoveHelperObjects()
{
DataStorage* dataStorage = m_ToolManager->GetDataStorage();
if (!m_EditingContours.empty())
std::for_each(m_EditingContours.begin(), m_EditingContours.end(), RemoveFromDataStorage(dataStorage));
if (!m_WorkingContours.empty())
std::for_each(m_WorkingContours.begin(), m_WorkingContours.end(), RemoveFromDataStorage(dataStorage));
if (m_EditingContourNode.IsNotNull())
dataStorage->Remove(m_EditingContourNode);
if (m_LiveWireContourNode.IsNotNull())
dataStorage->Remove(m_LiveWireContourNode);
if (m_ContourModelNode.IsNotNull())
dataStorage->Remove(m_ContourModelNode);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void mitk::LiveWireTool2D::ReleaseHelperObjects()
{
this->RemoveHelperObjects();
if (!m_EditingContours.empty())
m_EditingContours.clear();
if (!m_WorkingContours.empty())
m_WorkingContours.clear();
m_EditingContourNode = NULL;
m_EditingContour = NULL;
m_LiveWireContourNode = NULL;
m_LiveWireContour = NULL;
m_ContourModelNode = NULL;
m_Contour = NULL;
}
void mitk::LiveWireTool2D::ReleaseInteractors()
{
this->EnableContourLiveWireInteraction(false);
m_LiveWireInteractors.clear();
}
void mitk::LiveWireTool2D::ConnectActionsAndFunctions()
{
CONNECT_CONDITION("CheckContourClosed", OnCheckPoint);
CONNECT_FUNCTION("InitObject", OnInitLiveWire);
CONNECT_FUNCTION("AddPoint", OnAddPoint);
CONNECT_FUNCTION("CtrlAddPoint", OnAddPoint);
CONNECT_FUNCTION("MovePoint", OnMouseMoveNoDynamicCosts);
CONNECT_FUNCTION("FinishContour", OnFinish);
CONNECT_FUNCTION("DeletePoint", OnLastSegmentDelete);
CONNECT_FUNCTION("CtrlMovePoint", OnMouseMoved);
}
const char** mitk::LiveWireTool2D::GetXPM() const
{
return mitkLiveWireTool2D_xpm;
}
us::ModuleResource mitk::LiveWireTool2D::GetIconResource() const
{
return us::GetModuleContext()->GetModule()->GetResource("LiveWire_48x48.png");
}
us::ModuleResource mitk::LiveWireTool2D::GetCursorIconResource() const
{
return us::GetModuleContext()->GetModule()->GetResource("LiveWire_Cursor_32x32.png");
}
const char* mitk::LiveWireTool2D::GetName() const
{
return "Live Wire";
}
void mitk::LiveWireTool2D::Activated()
{
Superclass::Activated();
this->ResetToStartState();
this->EnableContourLiveWireInteraction(true);
}
void mitk::LiveWireTool2D::Deactivated()
{
Superclass::Deactivated();
this->ConfirmSegmentation();
}
void mitk::LiveWireTool2D::EnableContourLiveWireInteraction(bool on)
{
std::for_each(m_LiveWireInteractors.begin(), m_LiveWireInteractors.end(), on
? AddInteractorToGlobalInteraction
: RemoveInteractorFromGlobalInteraction);
}
void mitk::LiveWireTool2D::ConfirmSegmentation()
{
DataNode* workingNode( m_ToolManager->GetWorkingData(0) );
if (!workingNode)
return;
Image* workingImage = dynamic_cast<Image*>(workingNode->GetData());
if (!workingImage)
return;
// for all contours in list (currently created by tool)
std::vector< std::pair<mitk::DataNode::Pointer, mitk::PlaneGeometry::Pointer> >::iterator itWorkingContours = this->m_WorkingContours.begin();
while(itWorkingContours != this->m_WorkingContours.end() )
{
// if node contains data
if( itWorkingContours->first->GetData() )
{
// if this is a contourModel
mitk::ContourModel* contourModel = dynamic_cast<mitk::ContourModel*>(itWorkingContours->first->GetData());
if( contourModel )
{
// for each timestep of this contourModel
for( TimeStepType currentTimestep = 0; currentTimestep < contourModel->GetTimeGeometry()->CountTimeSteps(); ++currentTimestep)
{
//get the segmentation image slice at current timestep
mitk::Image::Pointer workingSlice = this->GetAffectedImageSliceAs2DImage(itWorkingContours->second, workingImage, currentTimestep);
mitk::ContourModel::Pointer projectedContour = mitk::ContourModelUtils::ProjectContourTo2DSlice(workingSlice, contourModel, true, false);
mitk::ContourModelUtils::FillContourInSlice(projectedContour, workingSlice, 1.0);
//write back to image volume
this->WriteBackSegmentationResult(itWorkingContours->second, workingSlice, currentTimestep);
}
}
}
++itWorkingContours;
}
this->ReleaseHelperObjects();
this->ReleaseInteractors();
}
void mitk::LiveWireTool2D::ClearSegmentation()
{
this->ReleaseHelperObjects();
this->ReleaseInteractors();
this->ResetToStartState();
}
bool mitk::LiveWireTool2D::OnInitLiveWire ( StateMachineAction*, InteractionEvent* interactionEvent )
{
mitk::InteractionPositionEvent* positionEvent = dynamic_cast<mitk::InteractionPositionEvent*>( interactionEvent );
if (!positionEvent) return false;
m_LastEventSender = positionEvent->GetSender();
m_LastEventSlice = m_LastEventSender->GetSlice();
int timestep = positionEvent->GetSender()->GetTimeStep();
m_Contour = mitk::ContourModel::New();
m_Contour->Expand(timestep+1);
m_ContourModelNode = mitk::DataNode::New();
m_ContourModelNode->SetData( m_Contour );
m_ContourModelNode->SetName("working contour node");
m_ContourModelNode->SetProperty( "layer", IntProperty::New(100));
m_ContourModelNode->AddProperty( "fixedLayer", BoolProperty::New(true));
m_ContourModelNode->SetProperty( "helper object", mitk::BoolProperty::New(true));
m_ContourModelNode->AddProperty( "contour.color", ColorProperty::New(1, 1, 0), NULL, true );
m_ContourModelNode->AddProperty( "contour.points.color", ColorProperty::New(1.0, 0.0, 0.1), NULL, true );
m_ContourModelNode->AddProperty( "contour.controlpoints.show", BoolProperty::New(true), NULL, true );
m_LiveWireContour = mitk::ContourModel::New();
m_LiveWireContour->Expand(timestep+1);
m_LiveWireContourNode = mitk::DataNode::New();
m_LiveWireContourNode->SetData( m_LiveWireContour );
m_LiveWireContourNode->SetName("active livewire node");
m_LiveWireContourNode->SetProperty( "layer", IntProperty::New(101));
m_LiveWireContourNode->AddProperty( "fixedLayer", BoolProperty::New(true));
m_LiveWireContourNode->SetProperty( "helper object", mitk::BoolProperty::New(true));
m_LiveWireContourNode->AddProperty( "contour.color", ColorProperty::New(0.1, 1.0, 0.1), NULL, true );
m_LiveWireContourNode->AddProperty( "contour.width", mitk::FloatProperty::New( 4.0 ), NULL, true );
m_EditingContour = mitk::ContourModel::New();
m_EditingContour->Expand(timestep+1);
m_EditingContourNode = mitk::DataNode::New();
m_EditingContourNode->SetData( m_EditingContour );
m_EditingContourNode->SetName("editing node");
m_EditingContourNode->SetProperty( "layer", IntProperty::New(102));
m_EditingContourNode->AddProperty( "fixedLayer", BoolProperty::New(true));
m_EditingContourNode->SetProperty( "helper object", mitk::BoolProperty::New(true));
m_EditingContourNode->AddProperty( "contour.color", ColorProperty::New(0.1, 1.0, 0.1), NULL, true );
m_EditingContourNode->AddProperty( "contour.points.color", ColorProperty::New(0.0, 0.0, 1.0), NULL, true );
m_EditingContourNode->AddProperty( "contour.width", mitk::FloatProperty::New( 4.0 ), NULL, true );
mitk::DataNode* workingDataNode = m_ToolManager->GetWorkingData(0);
m_ToolManager->GetDataStorage()->Add(m_ContourModelNode, workingDataNode);
m_ToolManager->GetDataStorage()->Add(m_LiveWireContourNode, workingDataNode);
m_ToolManager->GetDataStorage()->Add(m_EditingContourNode, workingDataNode);
//set current slice as input for ImageToLiveWireContourFilter
m_WorkingSlice = this->GetAffectedReferenceSlice(positionEvent);
//Transfer LiveWire's center based contour output to corner based via the adaption of the input
//slice image. Just in case someone stumbles across the 0.5 here I know what I'm doing ;-).
m_WorkingSlice->GetSlicedGeometry()->ChangeImageGeometryConsideringOriginOffset(false);
mitk::Point3D newOrigin = m_WorkingSlice->GetSlicedGeometry()->GetOrigin();
m_WorkingSlice->GetSlicedGeometry()->WorldToIndex(newOrigin, newOrigin);
newOrigin[2] += 0.5;
m_WorkingSlice->GetSlicedGeometry()->IndexToWorld(newOrigin, newOrigin);
m_WorkingSlice->GetSlicedGeometry()->SetOrigin(newOrigin);
m_LiveWireFilter = mitk::ImageLiveWireContourModelFilter::New();
m_LiveWireFilter->SetInput(m_WorkingSlice);
//map click to pixel coordinates
mitk::Point3D click = positionEvent->GetPositionInWorld();
itk::Index<3> idx;
m_WorkingSlice->GetGeometry()->WorldToIndex(click, idx);
// get the pixel the gradient in region of 5x5
itk::Index<3> indexWithHighestGradient;
AccessFixedDimensionByItk_2(m_WorkingSlice, FindHighestGradientMagnitudeByITK, 2, idx, indexWithHighestGradient);
// itk::Index to mitk::Point3D
click[0] = indexWithHighestGradient[0];
click[1] = indexWithHighestGradient[1];
click[2] = indexWithHighestGradient[2];
m_WorkingSlice->GetGeometry()->IndexToWorld(click, click);
//set initial start point
m_Contour->AddVertex( click, true, timestep );
m_LiveWireFilter->SetStartPoint(click);
m_CreateAndUseDynamicCosts = true;
//render
assert( positionEvent->GetSender()->GetRenderWindow() );
mitk::RenderingManager::GetInstance()->RequestUpdate( positionEvent->GetSender()->GetRenderWindow() );
return true;
}
bool mitk::LiveWireTool2D::OnAddPoint ( StateMachineAction*, InteractionEvent* interactionEvent )
{
//complete LiveWire interaction for last segment
//add current LiveWire contour to the finished contour and reset
//to start new segment and computation
/* check if event can be handled */
mitk::InteractionPositionEvent* positionEvent = dynamic_cast<mitk::InteractionPositionEvent*>( interactionEvent );
if (!positionEvent) return false;
int timestep = positionEvent->GetSender()->GetTimeStep();
//add repulsive points to avoid to get the same path again
typedef mitk::ImageLiveWireContourModelFilter::InternalImageType::IndexType IndexType;
mitk::ContourModel::ConstVertexIterator iter = m_LiveWireContour->IteratorBegin(timestep);
for (;iter != m_LiveWireContour->IteratorEnd(timestep); iter++)
{
IndexType idx;
this->m_WorkingSlice->GetGeometry()->WorldToIndex((*iter)->Coordinates, idx);
this->m_LiveWireFilter->AddRepulsivePoint( idx );
}
//remove duplicate first vertex, it's already contained in m_Contour
m_LiveWireContour->RemoveVertexAt(0, timestep);
// set last added point as control point
m_LiveWireContour->SetControlVertexAt(m_LiveWireContour->GetNumberOfVertices(timestep)-1, timestep);
//merge contours
m_Contour->Concatenate(m_LiveWireContour, timestep);
//clear the livewire contour and reset the corresponding datanode
m_LiveWireContour->Clear(timestep);
//set new start point
m_LiveWireFilter->SetStartPoint(positionEvent->GetPositionInWorld());
if( m_CreateAndUseDynamicCosts )
{
//use dynamic cost map for next update
m_LiveWireFilter->CreateDynamicCostMap(m_Contour);
m_LiveWireFilter->SetUseDynamicCostMap(true);
//m_CreateAndUseDynamicCosts = false;
}
//render
assert( positionEvent->GetSender()->GetRenderWindow() );
mitk::RenderingManager::GetInstance()->RequestUpdate( positionEvent->GetSender()->GetRenderWindow() );
return true;
}
bool mitk::LiveWireTool2D::OnMouseMoved( StateMachineAction*, InteractionEvent* interactionEvent )
{
//compute LiveWire segment from last control point to current mouse position
mitk::InteractionPositionEvent* positionEvent = dynamic_cast<mitk::InteractionPositionEvent*>( interactionEvent );
if (!positionEvent) return false;
// actual LiveWire computation
int timestep = positionEvent->GetSender()->GetTimeStep();
m_LiveWireFilter->SetEndPoint(positionEvent->GetPositionInWorld());
m_LiveWireFilter->SetTimeStep( timestep );
m_LiveWireFilter->Update();
m_LiveWireContour = this->m_LiveWireFilter->GetOutput();
m_LiveWireContourNode->SetData( this->m_LiveWireContour );
//render
assert( positionEvent->GetSender()->GetRenderWindow() );
positionEvent->GetSender()->GetRenderingManager()->RequestUpdate( positionEvent->GetSender()->GetRenderWindow() );
return true;
}
bool mitk::LiveWireTool2D::OnMouseMoveNoDynamicCosts( StateMachineAction*, InteractionEvent* interactionEvent )
{
//do not use dynamic cost map
m_LiveWireFilter->SetUseDynamicCostMap(false);
OnMouseMoved( NULL, interactionEvent);
m_LiveWireFilter->SetUseDynamicCostMap(true);
return true;
}
bool mitk::LiveWireTool2D::OnCheckPoint( const InteractionEvent* interactionEvent)
{
//check double click on first control point to finish the LiveWire tool
//
//Check distance to first point.
//Transition YES if click close to first control point
//
const mitk::InteractionPositionEvent* positionEvent = dynamic_cast<const mitk::InteractionPositionEvent*>( interactionEvent );
if (positionEvent)
{
int timestep = positionEvent->GetSender()->GetTimeStep();
mitk::Point3D click = positionEvent->GetPositionInWorld();
mitk::Point3D first = this->m_Contour->GetVertexAt(0, timestep)->Coordinates;
if (first.EuclideanDistanceTo(click) < 4.5)
{
// allow to finish
return true;
}
else
{
return false;
}
}
return false;
}
bool mitk::LiveWireTool2D::OnFinish( StateMachineAction*, InteractionEvent* interactionEvent )
{
// finish livewire tool interaction
mitk::InteractionPositionEvent* positionEvent = dynamic_cast<mitk::InteractionPositionEvent*>( interactionEvent );
if (!positionEvent) return false;
// actual timestep
int timestep = positionEvent->GetSender()->GetTimeStep();
// remove last control point being added by double click
m_Contour->RemoveVertexAt(m_Contour->GetNumberOfVertices(timestep) - 1, timestep);
// save contour and corresponding plane geometry to list
- std::pair<mitk::DataNode::Pointer, mitk::PlaneGeometry::Pointer> cp(m_ContourModelNode, dynamic_cast<mitk::PlaneGeometry*>(positionEvent->GetSender()->GetCurrentWorldGeometry2D()->Clone().GetPointer()) );
+ std::pair<mitk::DataNode::Pointer, mitk::PlaneGeometry::Pointer> cp(m_ContourModelNode, dynamic_cast<mitk::PlaneGeometry*>(positionEvent->GetSender()->GetCurrentWorldPlaneGeometry()->Clone().GetPointer()) );
this->m_WorkingContours.push_back(cp);
- std::pair<mitk::DataNode::Pointer, mitk::PlaneGeometry::Pointer> ecp(m_EditingContourNode, dynamic_cast<mitk::PlaneGeometry*>(positionEvent->GetSender()->GetCurrentWorldGeometry2D()->Clone().GetPointer()) );
+ std::pair<mitk::DataNode::Pointer, mitk::PlaneGeometry::Pointer> ecp(m_EditingContourNode, dynamic_cast<mitk::PlaneGeometry*>(positionEvent->GetSender()->GetCurrentWorldPlaneGeometry()->Clone().GetPointer()) );
this->m_EditingContours.push_back(ecp);
m_LiveWireFilter->SetUseDynamicCostMap(false);
this->FinishTool();
return true;
}
void mitk::LiveWireTool2D::FinishTool()
{
TimeStepType numberOfTimesteps = m_Contour->GetTimeGeometry()->CountTimeSteps();
//close contour in each timestep
for( int i = 0; i <= numberOfTimesteps; i++)
{
m_Contour->Close(i);
}
m_ToolManager->GetDataStorage()->Remove( m_LiveWireContourNode );
// clear live wire contour node
m_LiveWireContourNode = NULL;
m_LiveWireContour = NULL;
//set the livewire interactor to edit control points
m_ContourInteractor = mitk::ContourModelLiveWireInteractor::New(m_ContourModelNode);
m_ContourInteractor->SetWorkingImage(this->m_WorkingSlice);
m_ContourInteractor->SetEditingContourModelNode(this->m_EditingContourNode);
m_ContourModelNode->SetInteractor(m_ContourInteractor);
this->m_LiveWireInteractors.push_back( m_ContourInteractor );
//add interactor to globalInteraction instance
mitk::GlobalInteraction::GetInstance()->AddInteractor(m_ContourInteractor);
}
bool mitk::LiveWireTool2D::OnLastSegmentDelete( StateMachineAction*, InteractionEvent* interactionEvent )
{
int timestep = interactionEvent->GetSender()->GetTimeStep();
//if last point of current contour will be removed go to start state and remove nodes
if( m_Contour->GetNumberOfVertices(timestep) <= 1 )
{
m_ToolManager->GetDataStorage()->Remove( m_LiveWireContourNode );
m_ToolManager->GetDataStorage()->Remove( m_ContourModelNode );
m_ToolManager->GetDataStorage()->Remove( m_EditingContourNode );
m_LiveWireContour = mitk::ContourModel::New();
m_Contour = mitk::ContourModel::New();
m_ContourModelNode->SetData( m_Contour );
m_LiveWireContourNode->SetData( m_LiveWireContour );
this->ResetToStartState(); //go to start state
}
else //remove last segment from contour and reset livewire contour
{
m_LiveWireContour = mitk::ContourModel::New();
m_LiveWireContourNode->SetData(m_LiveWireContour);
mitk::ContourModel::Pointer newContour = mitk::ContourModel::New();
newContour->Expand(m_Contour->GetTimeSteps());
mitk::ContourModel::VertexIterator begin = m_Contour->IteratorBegin();
//iterate from last point to next active point
mitk::ContourModel::VertexIterator newLast = m_Contour->IteratorBegin() + (m_Contour->GetNumberOfVertices() - 1);
//go at least one down
if(newLast != begin)
{
newLast--;
}
//search next active control point
while(newLast != begin && !((*newLast)->IsControlPoint) )
{
newLast--;
}
//set position of start point for livewire filter to coordinates of the new last point
m_LiveWireFilter->SetStartPoint((*newLast)->Coordinates);
mitk::ContourModel::VertexIterator it = m_Contour->IteratorBegin();
//fill new Contour
while(it <= newLast)
{
newContour->AddVertex((*it)->Coordinates, (*it)->IsControlPoint, timestep);
it++;
}
newContour->SetClosed(m_Contour->IsClosed());
//set new contour visible
m_ContourModelNode->SetData(newContour);
m_Contour = newContour;
assert( interactionEvent->GetSender()->GetRenderWindow() );
mitk::RenderingManager::GetInstance()->RequestUpdate( interactionEvent->GetSender()->GetRenderWindow() );
}
return true;
}
template<typename TPixel, unsigned int VImageDimension>
void mitk::LiveWireTool2D::FindHighestGradientMagnitudeByITK(itk::Image<TPixel, VImageDimension>* inputImage, itk::Index<3> &index, itk::Index<3> &returnIndex)
{
typedef itk::Image<TPixel, VImageDimension> InputImageType;
typedef typename InputImageType::IndexType IndexType;
unsigned long xMAX = inputImage->GetLargestPossibleRegion().GetSize()[0];
unsigned long yMAX = inputImage->GetLargestPossibleRegion().GetSize()[1];
returnIndex[0] = index[0];
returnIndex[1] = index[1];
returnIndex[2] = 0.0;
double gradientMagnitude = 0.0;
double maxGradientMagnitude = 0.0;
/*
the size and thus the region of 7x7 is only used to calculate the gradient magnitude in that region
not for searching the maximum value
*/
//maximum value in each direction for size
typename InputImageType::SizeType size;
size[0] = 7;
size[1] = 7;
//minimum value in each direction for startRegion
IndexType startRegion;
startRegion[0] = index[0] - 3;
startRegion[1] = index[1] - 3;
if(startRegion[0] < 0) startRegion[0] = 0;
if(startRegion[1] < 0) startRegion[1] = 0;
if(xMAX - index[0] < 7) startRegion[0] = xMAX - 7;
if(yMAX - index[1] < 7) startRegion[1] = yMAX - 7;
index[0] = startRegion[0] + 3;
index[1] = startRegion[1] + 3;
typename InputImageType::RegionType region;
region.SetSize( size );
region.SetIndex( startRegion );
typedef typename itk::GradientMagnitudeImageFilter< InputImageType, InputImageType> GradientMagnitudeFilterType;
typename GradientMagnitudeFilterType::Pointer gradientFilter = GradientMagnitudeFilterType::New();
gradientFilter->SetInput(inputImage);
gradientFilter->GetOutput()->SetRequestedRegion(region);
gradientFilter->Update();
typename InputImageType::Pointer gradientMagnImage;
gradientMagnImage = gradientFilter->GetOutput();
IndexType currentIndex;
currentIndex[0] = 0;
currentIndex[1] = 0;
// search max (approximate) gradient magnitude
for( int x = -1; x <= 1; ++x)
{
currentIndex[0] = index[0] + x;
for( int y = -1; y <= 1; ++y)
{
currentIndex[1] = index[1] + y;
gradientMagnitude = gradientMagnImage->GetPixel(currentIndex);
//check for new max
if(maxGradientMagnitude < gradientMagnitude)
{
maxGradientMagnitude = gradientMagnitude;
returnIndex[0] = currentIndex[0];
returnIndex[1] = currentIndex[1];
returnIndex[2] = 0.0;
}//end if
}//end for y
currentIndex[1] = index[1];
}//end for x
}
diff --git a/Modules/Segmentation/Interactions/mitkPaintbrushTool.cpp b/Modules/Segmentation/Interactions/mitkPaintbrushTool.cpp
index 761dae953c..f7b804cdf0 100644
--- a/Modules/Segmentation/Interactions/mitkPaintbrushTool.cpp
+++ b/Modules/Segmentation/Interactions/mitkPaintbrushTool.cpp
@@ -1,517 +1,517 @@
/*===================================================================
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 "mitkPaintbrushTool.h"
#include "mitkToolManager.h"
#include "mitkOverwriteSliceImageFilter.h"
#include "mitkBaseRenderer.h"
#include "mitkImageDataItem.h"
#include "ipSegmentation.h"
#include "mitkLevelWindowProperty.h"
#define ROUND(a) ((a)>0 ? (int)((a)+0.5) : -(int)(0.5-(a)))
int mitk::PaintbrushTool::m_Size = 1;
mitk::PaintbrushTool::PaintbrushTool(int paintingPixelValue)
:FeedbackContourTool("PressMoveReleaseWithCTRLInversionAllMouseMoves"),
m_PaintingPixelValue(paintingPixelValue),
m_LastContourSize(0) // other than initial mitk::PaintbrushTool::m_Size (around l. 28)
{
m_MasterContour = ContourModel::New();
m_MasterContour->Initialize();
m_CurrentPlane = NULL;
m_WorkingNode = DataNode::New();
m_WorkingNode->SetProperty( "levelwindow", mitk::LevelWindowProperty::New( mitk::LevelWindow(0, 1) ) );
m_WorkingNode->SetProperty( "binary", mitk::BoolProperty::New(true) );
}
mitk::PaintbrushTool::~PaintbrushTool()
{
}
void mitk::PaintbrushTool::ConnectActionsAndFunctions()
{
CONNECT_FUNCTION( "PrimaryButtonPressed", OnMousePressed);
CONNECT_FUNCTION( "Move", OnPrimaryButtonPressedMoved);
CONNECT_FUNCTION( "MouseMove", OnMouseMoved);
CONNECT_FUNCTION( "Release", OnMouseReleased);
CONNECT_FUNCTION( "InvertLogic", OnInvertLogic);
}
void mitk::PaintbrushTool::Activated()
{
Superclass::Activated();
FeedbackContourTool::SetFeedbackContourVisible(true);
SizeChanged.Send(m_Size);
m_ToolManager->WorkingDataChanged += mitk::MessageDelegate<mitk::PaintbrushTool>( this, &mitk::PaintbrushTool::OnToolManagerWorkingDataModified );
}
void mitk::PaintbrushTool::Deactivated()
{
FeedbackContourTool::SetFeedbackContourVisible(false);
if (m_ToolManager->GetDataStorage()->Exists(m_WorkingNode))
m_ToolManager->GetDataStorage()->Remove(m_WorkingNode);
Superclass::Deactivated();
m_WorkingSlice = NULL;
m_CurrentPlane = NULL;
m_ToolManager->WorkingDataChanged -= mitk::MessageDelegate<mitk::PaintbrushTool>( this, &mitk::PaintbrushTool::OnToolManagerWorkingDataModified );
}
void mitk::PaintbrushTool::SetSize(int value)
{
m_Size = value;
}
mitk::Point2D mitk::PaintbrushTool::upperLeft(mitk::Point2D p)
{
p[0] -= 0.5;
p[1] += 0.5;
return p;
}
void mitk::PaintbrushTool::UpdateContour(const InteractionPositionEvent* positionEvent)
{
//MITK_INFO<<"Update...";
// examine stateEvent and create a contour that matches the pixel mask that we are going to draw
//mitk::InteractionPositionEvent* positionEvent = dynamic_cast<mitk::InteractionPositionEvent*>( interactionEvent );
//const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent());
if (!positionEvent) return;
// Get Spacing of current Slice
- //mitk::Vector3D vSpacing = m_WorkingSlice->GetSlicedGeometry()->GetGeometry2D(0)->GetSpacing();
+ //mitk::Vector3D vSpacing = m_WorkingSlice->GetSlicedGeometry()->GetPlaneGeometry(0)->GetSpacing();
//
// Draw a contour in Square according to selected brush size
//
int radius = (m_Size)/2;
float fradius = static_cast<float>(m_Size) / 2.0f;
ContourModel::Pointer contourInImageIndexCoordinates = ContourModel::New();
// estimate center point of the brush ( relative to the pixel the mouse points on )
// -- left upper corner for even sizes,
// -- midpoint for uneven sizes
mitk::Point2D centerCorrection;
centerCorrection.Fill(0);
// even --> correction of [+0.5, +0.5]
bool evenSize = ((m_Size % 2) == 0);
if( evenSize )
{
centerCorrection[0] += 0.5;
centerCorrection[1] += 0.5;
}
// we will compute the control points for the upper left quarter part of a circle contour
std::vector< mitk::Point2D > quarterCycleUpperRight;
std::vector< mitk::Point2D > quarterCycleLowerRight;
std::vector< mitk::Point2D > quarterCycleLowerLeft;
std::vector< mitk::Point2D > quarterCycleUpperLeft;
mitk::Point2D curPoint;
bool curPointIsInside = true;
curPoint[0] = 0;
curPoint[1] = radius;
quarterCycleUpperRight.push_back( upperLeft(curPoint) );
// to estimate if a pixel is inside the circle, we need to compare against the 'outer radius'
// i.e. the distance from the midpoint [0,0] to the border of the pixel [0,radius]
//const float outer_radius = static_cast<float>(radius) + 0.5;
while (curPoint[1] > 0)
{
// Move right until pixel is outside circle
float curPointX_squared = 0.0f;
float curPointY_squared = (curPoint[1] - centerCorrection[1] ) * (curPoint[1] - centerCorrection[1] );
while( curPointIsInside )
{
// increment posX and chec
curPoint[0]++;
curPointX_squared = (curPoint[0] - centerCorrection[0] ) * (curPoint[0] - centerCorrection[0] );
const float len = sqrt( curPointX_squared + curPointY_squared);
if ( len > fradius )
{
// found first Pixel in this horizontal line, that is outside the circle
curPointIsInside = false;
}
}
quarterCycleUpperRight.push_back( upperLeft(curPoint) );
// Move down until pixel is inside circle
while( !curPointIsInside )
{
// increment posX and chec
curPoint[1]--;
curPointY_squared = (curPoint[1] - centerCorrection[1] ) * (curPoint[1] - centerCorrection[1] );
const float len = sqrt( curPointX_squared + curPointY_squared);
if ( len <= fradius )
{
// found first Pixel in this horizontal line, that is outside the circle
curPointIsInside = true;
quarterCycleUpperRight.push_back( upperLeft(curPoint) );
}
// Quarter cycle is full, when curPoint y position is 0
if (curPoint[1] <= 0)
break;
}
}
// QuarterCycle is full! Now copy quarter cycle to other quarters.
if( !evenSize )
{
std::vector< mitk::Point2D >::const_iterator it = quarterCycleUpperRight.begin();
while( it != quarterCycleUpperRight.end() )
{
mitk::Point2D p;
p = *it;
// the contour points in the lower right corner have same position but with negative y values
p[1] *= -1;
quarterCycleLowerRight.push_back(p);
// the contour points in the lower left corner have same position
// but with both x,y negative
p[0] *= -1;
quarterCycleLowerLeft.push_back(p);
// the contour points in the upper left corner have same position
// but with x negative
p[1] *= -1;
quarterCycleUpperLeft.push_back(p);
it++;
}
}
else
{
std::vector< mitk::Point2D >::const_iterator it = quarterCycleUpperRight.begin();
while( it != quarterCycleUpperRight.end() )
{
mitk::Point2D p,q;
p = *it;
q = p;
// the contour points in the lower right corner have same position but with negative y values
q[1] *= -1;
// correct for moved offset if size even = the midpoint is not the midpoint of the current pixel
// but its upper rigt corner
q[1] += 1;
quarterCycleLowerRight.push_back(q);
q = p;
// the contour points in the lower left corner have same position
// but with both x,y negative
q[1] = -1.0f * q[1] + 1;
q[0] = -1.0f * q[0] + 1;
quarterCycleLowerLeft.push_back(q);
// the contour points in the upper left corner have same position
// but with x negative
q = p;
q[0] *= -1;
q[0] += 1;
quarterCycleUpperLeft.push_back(q);
it++;
}
}
// fill contour with poins in right ordering, starting with the upperRight block
mitk::Point3D tempPoint;
for (unsigned int i=0; i<quarterCycleUpperRight.size(); i++)
{
tempPoint[0] = quarterCycleUpperRight[i][0];
tempPoint[1] = quarterCycleUpperRight[i][1];
tempPoint[2] = 0;
contourInImageIndexCoordinates->AddVertex( tempPoint );
}
// the lower right has to be parsed in reverse order
for (int i=quarterCycleLowerRight.size()-1; i>=0; i--)
{
tempPoint[0] = quarterCycleLowerRight[i][0];
tempPoint[1] = quarterCycleLowerRight[i][1];
tempPoint[2] = 0;
contourInImageIndexCoordinates->AddVertex( tempPoint );
}
for (unsigned int i=0; i<quarterCycleLowerLeft.size(); i++)
{
tempPoint[0] = quarterCycleLowerLeft[i][0];
tempPoint[1] = quarterCycleLowerLeft[i][1];
tempPoint[2] = 0;
contourInImageIndexCoordinates->AddVertex( tempPoint );
}
// the upper left also has to be parsed in reverse order
for (int i=quarterCycleUpperLeft.size()-1; i>=0; i--)
{
tempPoint[0] = quarterCycleUpperLeft[i][0];
tempPoint[1] = quarterCycleUpperLeft[i][1];
tempPoint[2] = 0;
contourInImageIndexCoordinates->AddVertex( tempPoint );
}
m_MasterContour = contourInImageIndexCoordinates;
}
/**
Just show the contour, get one point as the central point and add surrounding points to the contour.
*/
bool mitk::PaintbrushTool::OnMousePressed ( StateMachineAction*, InteractionEvent* interactionEvent )
{
mitk::InteractionPositionEvent* positionEvent = dynamic_cast<mitk::InteractionPositionEvent*>( interactionEvent );
//const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent());
if (!positionEvent) return false;
m_LastEventSender = positionEvent->GetSender();
m_LastEventSlice = m_LastEventSender->GetSlice();
m_MasterContour->SetClosed(true);
return this->MouseMoved(interactionEvent, true);
}
bool mitk::PaintbrushTool::OnMouseMoved( StateMachineAction*, InteractionEvent* interactionEvent )
{
return MouseMoved(interactionEvent, false);
}
bool mitk::PaintbrushTool::OnPrimaryButtonPressedMoved( StateMachineAction*, InteractionEvent* interactionEvent )
{
return MouseMoved(interactionEvent, true);
}
/**
Insert the point to the feedback contour,finish to build the contour and at the same time the painting function
*/
bool mitk::PaintbrushTool::MouseMoved(mitk::InteractionEvent* interactionEvent, bool leftMouseButtonPressed)
{
mitk::InteractionPositionEvent* positionEvent = dynamic_cast<mitk::InteractionPositionEvent*>( interactionEvent );
//const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent());
CheckIfCurrentSliceHasChanged( positionEvent );
if ( m_LastContourSize != m_Size )
{
UpdateContour( positionEvent );
m_LastContourSize = m_Size;
}
// stateEvent->GetId() == 530
// || stateEvent->GetId() == 534
// || stateEvent->GetId() == 1
// || stateEvent->GetId() == 5
// );
Point3D worldCoordinates = positionEvent->GetPositionInWorld();
Point3D indexCoordinates;
m_WorkingSlice->GetGeometry()->WorldToIndex( worldCoordinates, indexCoordinates );
MITK_DEBUG << "Mouse at W " << worldCoordinates << std::endl;
MITK_DEBUG << "Mouse at I " << indexCoordinates << std::endl;
// round to nearest voxel center (abort if this hasn't changed)
if ( m_Size % 2 == 0 ) // even
{
indexCoordinates[0] = ROUND( indexCoordinates[0]);// /*+ 0.5*/) + 0.5;
indexCoordinates[1] = ROUND( indexCoordinates[1]);// /*+ 0.5*/ ) + 0.5;
}
else // odd
{
indexCoordinates[0] = ROUND( indexCoordinates[0] ) ;
indexCoordinates[1] = ROUND( indexCoordinates[1] ) ;
}
static Point3D lastPos; // uninitialized: if somebody finds out how this can be initialized in a one-liner, tell me
if ( fabs(indexCoordinates[0] - lastPos[0]) > mitk::eps ||
fabs(indexCoordinates[1] - lastPos[1]) > mitk::eps ||
fabs(indexCoordinates[2] - lastPos[2]) > mitk::eps ||
leftMouseButtonPressed
)
{
lastPos = indexCoordinates;
}
else
{
MITK_DEBUG << "." << std::flush;
return false;
}
MITK_DEBUG << "Mouse at C " << indexCoordinates;
int timestep = positionEvent->GetSender()->GetTimeStep();
ContourModel::Pointer contour = ContourModel::New();
contour->Expand(timestep + 1);
contour->SetClosed(true, timestep);
ContourModel::VertexIterator it = m_MasterContour->Begin();
ContourModel::VertexIterator end = m_MasterContour->End();
while(it != end)
{
Point3D point = (*it)->Coordinates;
point[0] += indexCoordinates[ 0 ];
point[1] += indexCoordinates[ 1 ];
contour->AddVertex( point, timestep );
it++;
}
if (leftMouseButtonPressed)
{
FeedbackContourTool::FillContourInSlice( contour, timestep, m_WorkingSlice, m_PaintingPixelValue );
m_WorkingNode->SetData(m_WorkingSlice);
m_WorkingNode->Modified();
}
// visualize contour
ContourModel::Pointer displayContour = ContourModel::New();
displayContour->Initialize();
//for (unsigned int index = 0; index < contour->GetNumberOfPoints(); ++index)
//{
// Point3D point = contour->GetPoints()->ElementAt(index);
// if ( m_Size % 2 == 0 ) // even
// {
// point[0] += 0.5;
// point[1] += 0.5;
// }
// displayContour->AddVertex( point );
//}
displayContour = FeedbackContourTool::BackProjectContourFrom2DSlice( m_WorkingSlice->GetGeometry(), /*displayContour*/contour );
SetFeedbackContour( *displayContour );
assert( positionEvent->GetSender()->GetRenderWindow() );
RenderingManager::GetInstance()->RequestUpdate( positionEvent->GetSender()->GetRenderWindow() );
return true;
}
bool mitk::PaintbrushTool::OnMouseReleased( StateMachineAction*, InteractionEvent* interactionEvent )
{
//When mouse is released write segmentationresult back into image
mitk::InteractionPositionEvent* positionEvent = dynamic_cast<mitk::InteractionPositionEvent*>( interactionEvent );
//const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent());
if (!positionEvent) return false;
this->WriteBackSegmentationResult(positionEvent, m_WorkingSlice->Clone());
return true;
}
/**
Called when the CTRL key is pressed. Will change the painting pixel value from 0 to 1 or from 1 to 0.
*/
bool mitk::PaintbrushTool::OnInvertLogic( StateMachineAction*, InteractionEvent* interactionEvent )
{
// Inversion only for 0 and 1 as painting values
if (m_PaintingPixelValue == 1)
{
m_PaintingPixelValue = 0;
FeedbackContourTool::SetFeedbackContourColor( 1.0, 0.0, 0.0 );
}
else if (m_PaintingPixelValue == 0)
{
m_PaintingPixelValue = 1;
FeedbackContourTool::SetFeedbackContourColorDefault();
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
return true;
}
void mitk::PaintbrushTool::CheckIfCurrentSliceHasChanged(const InteractionPositionEvent *event)
{
- const PlaneGeometry* planeGeometry( dynamic_cast<const PlaneGeometry*> (event->GetSender()->GetCurrentWorldGeometry2D() ) );
+ const PlaneGeometry* planeGeometry( dynamic_cast<const PlaneGeometry*> (event->GetSender()->GetCurrentWorldPlaneGeometry() ) );
DataNode* workingNode( m_ToolManager->GetWorkingData(0) );
if (!workingNode)
return;
Image::Pointer image = dynamic_cast<Image*>(workingNode->GetData());
if ( !image || !planeGeometry )
return;
if(m_CurrentPlane.IsNull() || m_WorkingSlice.IsNull())
{
m_CurrentPlane = const_cast<PlaneGeometry*>(planeGeometry);
m_WorkingSlice = SegTool2D::GetAffectedImageSliceAs2DImage(event, image)->Clone();
m_WorkingNode->ReplaceProperty( "color", workingNode->GetProperty("color") );
m_WorkingNode->SetData(m_WorkingSlice);
}
else
{
bool isSameSlice (false);
isSameSlice = mitk::MatrixEqualElementWise(planeGeometry->GetIndexToWorldTransform()->GetMatrix(),m_CurrentPlane->GetIndexToWorldTransform()->GetMatrix());
isSameSlice = mitk::Equal(planeGeometry->GetIndexToWorldTransform()->GetOffset(),m_CurrentPlane->GetIndexToWorldTransform()->GetOffset());
if (!isSameSlice)
{
m_ToolManager->GetDataStorage()->Remove(m_WorkingNode);
m_CurrentPlane = NULL;
m_WorkingSlice = NULL;
m_WorkingNode = NULL;
m_CurrentPlane = const_cast<PlaneGeometry*>(planeGeometry);
m_WorkingSlice = SegTool2D::GetAffectedImageSliceAs2DImage(event, image)->Clone();
m_WorkingNode = mitk::DataNode::New();
m_WorkingNode->SetProperty( "levelwindow", mitk::LevelWindowProperty::New( mitk::LevelWindow(0, 1) ) );
m_WorkingNode->SetProperty( "binary", mitk::BoolProperty::New(true) );
m_WorkingNode->SetData(m_WorkingSlice);
//So that the paintbrush contour vanished in the previous render window
RenderingManager::GetInstance()->RequestUpdateAll();
}
}
if(!m_ToolManager->GetDataStorage()->Exists(m_WorkingNode))
{
m_WorkingNode->SetProperty( "outline binary", mitk::BoolProperty::New(true) );
m_WorkingNode->SetProperty( "color", workingNode->GetProperty("color") );
m_WorkingNode->SetProperty( "name", mitk::StringProperty::New("Paintbrush_Node") );
m_WorkingNode->SetProperty( "helper object", mitk::BoolProperty::New(true) );
m_WorkingNode->SetProperty( "opacity", mitk::FloatProperty::New(0.8) );
m_WorkingNode->SetProperty( "includeInBoundingBox", mitk::BoolProperty::New(false));
m_WorkingNode->SetVisibility(false, mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4")));
m_ToolManager->GetDataStorage()->Add(m_WorkingNode);
}
}
void mitk::PaintbrushTool::OnToolManagerWorkingDataModified()
{
//Here we simply set the current working slice to null. The next time the mouse is moved
//within a renderwindow a new slice will be extracted from the new working data
m_WorkingSlice = 0;
}
diff --git a/Modules/Segmentation/Interactions/mitkPickingTool.cpp b/Modules/Segmentation/Interactions/mitkPickingTool.cpp
index 92928d6feb..e4cd87be2d 100644
--- a/Modules/Segmentation/Interactions/mitkPickingTool.cpp
+++ b/Modules/Segmentation/Interactions/mitkPickingTool.cpp
@@ -1,228 +1,228 @@
/*===================================================================
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 "mitkPickingTool.h"
#include "mitkToolManager.h"
#include "mitkProperties.h"
#include <mitkInteractionConst.h>
#include "mitkGlobalInteraction.h"
// us
#include <usModule.h>
#include <usModuleResource.h>
#include <usGetModuleContext.h>
#include <usModuleContext.h>
#include "mitkImageCast.h"
#include "mitkImageTimeSelector.h"
#include "mitkPointSetInteractor.h"
#include "mitkITKImageImport.h"
#include "mitkImageAccessByItk.h"
#include "mitkImageTimeSelector.h"
#include <itkConnectedThresholdImageFilter.h>
namespace mitk {
MITK_TOOL_MACRO(MitkSegmentation_EXPORT, PickingTool, "PickingTool");
}
mitk::PickingTool::PickingTool()
{
m_PointSetNode = mitk::DataNode::New();
m_PointSetNode->GetPropertyList()->SetProperty("name", mitk::StringProperty::New("Picking_Seedpoint"));
m_PointSetNode->GetPropertyList()->SetProperty("helper object", mitk::BoolProperty::New(true));
m_PointSet = mitk::PointSet::New();
m_PointSetNode->SetData(m_PointSet);
m_SeedPointInteractor = mitk::PointSetInteractor::New("singlepointinteractor", m_PointSetNode);
//Watch for point added or modified
itk::SimpleMemberCommand<PickingTool>::Pointer pointAddedCommand = itk::SimpleMemberCommand<PickingTool>::New();
pointAddedCommand->SetCallbackFunction(this, &mitk::PickingTool::OnPointAdded);
m_PointSetAddObserverTag = m_PointSet->AddObserver( mitk::PointSetAddEvent(), pointAddedCommand);
//create new node for picked region
m_ResultNode = mitk::DataNode::New();
// set some properties
m_ResultNode->SetProperty("name", mitk::StringProperty::New("result"));
m_ResultNode->SetProperty("helper object", mitk::BoolProperty::New(true));
m_ResultNode->SetProperty("color", mitk::ColorProperty::New(0.0,1.0,0.0));
m_ResultNode->SetProperty("layer", mitk::IntProperty::New(1));
m_ResultNode->SetProperty("opacity", mitk::FloatProperty::New(0.7));
}
mitk::PickingTool::~PickingTool()
{
m_PointSet->RemoveObserver(m_PointSetAddObserverTag);
}
const char** mitk::PickingTool::GetXPM() const
{
return NULL;
}
const char* mitk::PickingTool::GetName() const
{
return "Picking";
}
us::ModuleResource mitk::PickingTool::GetIconResource() const
{
us::Module* module = us::GetModuleContext()->GetModule();
us::ModuleResource resource = module->GetResource("Pick_48x48.png");
return resource;
}
void mitk::PickingTool::Activated()
{
//add to datastorage and enable interaction
if (!GetDataStorage()->Exists(m_PointSetNode))
GetDataStorage()->Add(m_PointSetNode, GetWorkingData());
mitk::GlobalInteraction::GetInstance()->AddInteractor(m_SeedPointInteractor);
// now add result to data tree
GetDataStorage()->Add( m_ResultNode, this->GetWorkingData() );
}
void mitk::PickingTool::Deactivated()
{
if (m_PointSet->GetPointSet()->GetNumberOfPoints() != 0)
{
mitk::Point3D point = m_PointSet->GetPoint(0);
mitk::PointOperation* doOp = new mitk::PointOperation(mitk::OpREMOVE, point, 0);
m_PointSet->ExecuteOperation(doOp);
}
//remove from data storage and disable interaction
mitk::GlobalInteraction::GetInstance()->RemoveInteractor(m_SeedPointInteractor);
GetDataStorage()->Remove(m_PointSetNode);
GetDataStorage()->Remove( m_ResultNode);
}
mitk::DataNode* mitk::PickingTool::GetReferenceData(){
return this->m_ToolManager->GetReferenceData(0);
}
mitk::DataStorage* mitk::PickingTool::GetDataStorage(){
return this->m_ToolManager->GetDataStorage();
}
mitk::DataNode* mitk::PickingTool::GetWorkingData(){
return this->m_ToolManager->GetWorkingData(0);
}
mitk::DataNode::Pointer mitk::PickingTool::GetPointSetNode()
{
return m_PointSetNode;
}
void mitk::PickingTool::OnPointAdded()
{
//Perform region growing/picking
int timeStep = mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget1") )->GetTimeStep();
mitk::PointSet::PointType seedPoint = m_PointSet->GetPointSet(timeStep)->GetPoints()->Begin().Value();
//as we want to pick a region from our segmentation image use the working data from ToolManager
mitk::Image::Pointer orgImage = dynamic_cast<mitk::Image*> (m_ToolManager->GetWorkingData(0)->GetData());
if (orgImage.IsNotNull())
{
if (orgImage->GetDimension() == 4)
{ //there may be 4D segmentation data even though we currently don't support that
mitk::ImageTimeSelector::Pointer timeSelector = mitk::ImageTimeSelector::New();
timeSelector->SetInput(orgImage);
timeSelector->SetTimeNr( timeStep );
timeSelector->UpdateLargestPossibleRegion();
mitk::Image* timedImage = timeSelector->GetOutput();
AccessByItk_2( timedImage , StartRegionGrowing, timedImage->GetGeometry(), seedPoint);
}
else if (orgImage->GetDimension() == 3)
{
AccessByItk_2(orgImage, StartRegionGrowing, orgImage->GetGeometry(), seedPoint);
}
this->m_PointSet->Clear();
}
}
template<typename TPixel, unsigned int VImageDimension>
- void mitk::PickingTool::StartRegionGrowing(itk::Image<TPixel, VImageDimension>* itkImage, mitk::Geometry3D* imageGeometry, mitk::PointSet::PointType seedPoint)
+ void mitk::PickingTool::StartRegionGrowing(itk::Image<TPixel, VImageDimension>* itkImage, mitk::BaseGeometry* imageGeometry, mitk::PointSet::PointType seedPoint)
{
typedef itk::Image<TPixel, VImageDimension> InputImageType;
typedef typename InputImageType::IndexType IndexType;
typedef itk::ConnectedThresholdImageFilter<InputImageType, InputImageType> RegionGrowingFilterType;
typename RegionGrowingFilterType::Pointer regionGrower = RegionGrowingFilterType::New();
// convert world coordinates to image indices
IndexType seedIndex;
imageGeometry->WorldToIndex( seedPoint, seedIndex);
//perform region growing in desired segmented region
regionGrower->SetInput( itkImage );
regionGrower->AddSeed( seedIndex );
regionGrower->SetLower( 1 );
regionGrower->SetUpper( 255 );
try
{
regionGrower->Update();
}
catch(itk::ExceptionObject &exc)
{
return; // can't work
}
catch( ... )
{
return;
}
//Store result and preview
mitk::Image::Pointer resultImage = mitk::ImportItkImage(regionGrower->GetOutput(),imageGeometry)->Clone();
m_ResultNode->SetData( resultImage );
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void mitk::PickingTool::ConfirmSegmentation()
{
//create a new node and store the image from the result node
mitk::DataNode::Pointer newNode = mitk::DataNode::New();
newNode->SetProperty("name", mitk::StringProperty::New("Picking_result"));
newNode->SetProperty("helper object", mitk::BoolProperty::New(false));
newNode->SetProperty("color", mitk::ColorProperty::New(1.0,0.0,0.0));
newNode->SetProperty("opacity", mitk::FloatProperty::New(1.0));
newNode->SetData(m_ResultNode->GetData());
GetDataStorage()->Add(newNode);
//reset result node
m_ResultNode->SetData(NULL);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
diff --git a/Modules/Segmentation/Interactions/mitkPickingTool.h b/Modules/Segmentation/Interactions/mitkPickingTool.h
index 7ae59389fc..8f52e4a3de 100644
--- a/Modules/Segmentation/Interactions/mitkPickingTool.h
+++ b/Modules/Segmentation/Interactions/mitkPickingTool.h
@@ -1,98 +1,98 @@
/*===================================================================
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 mitkPickingTool_h_Included
#define mitkPickingTool_h_Included
#include "mitkCommon.h"
#include <MitkSegmentationExports.h>
#include "mitkAutoSegmentationTool.h"
#include "mitkDataStorage.h"
#include "mitkPointSetInteractor.h"
#include "mitkPointSet.h"
#include "itkImage.h"
namespace us {
class ModuleResource;
}
namespace mitk
{
/**
\brief Extracts a single region from a segmentation image and creates a new image with same geometry of the input image.
The region is extracted in 3D space. This is done by performing region growing within the desired region.
Use shift click to add the seed point.
\ingroup ToolManagerEtAl
\sa mitk::Tool
\sa QmitkInteractiveSegmentation
*/
class MitkSegmentation_EXPORT PickingTool : public AutoSegmentationTool
{
public:
mitkClassMacro(PickingTool, AutoSegmentationTool);
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
virtual const char** GetXPM() const;
virtual const char* GetName() const;
us::ModuleResource GetIconResource() const;
virtual void Activated();
virtual void Deactivated();
virtual DataNode::Pointer GetPointSetNode();
mitk::DataNode* GetReferenceData();
mitk::DataNode* GetWorkingData();
mitk::DataStorage* GetDataStorage();
void ConfirmSegmentation();
protected:
PickingTool(); // purposely hidden
virtual ~PickingTool();
//Callback for point add event of PointSet
void OnPointAdded();
//Observer id
long m_PointSetAddObserverTag;
mitk::DataNode::Pointer m_ResultNode;
//itk regrowing
template < typename TPixel, unsigned int VImageDimension >
- void StartRegionGrowing( itk::Image< TPixel, VImageDimension >* itkImage, mitk::Geometry3D* imageGeometry, mitk::PointSet::PointType seedPoint );
+ void StartRegionGrowing( itk::Image< TPixel, VImageDimension >* itkImage, mitk::BaseGeometry* imageGeometry, mitk::PointSet::PointType seedPoint );
//seed point
PointSet::Pointer m_PointSet;
PointSetInteractor::Pointer m_SeedPointInteractor;
DataNode::Pointer m_PointSetNode;
};
} // namespace
#endif
diff --git a/Modules/Segmentation/Interactions/mitkRegionGrow3DTool.cpp b/Modules/Segmentation/Interactions/mitkRegionGrow3DTool.cpp
index 8ed1d441af..6ceeaacc45 100644
--- a/Modules/Segmentation/Interactions/mitkRegionGrow3DTool.cpp
+++ b/Modules/Segmentation/Interactions/mitkRegionGrow3DTool.cpp
@@ -1,439 +1,439 @@
/*===================================================================
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 "mitkRegionGrow3DTool.h"
#include "mitkToolManager.h"
#include "mitkRenderingManager.h"
#include "mitkLevelWindowProperty.h"
#include "mitkPointSetInteractor.h"
#include "mitkGlobalInteraction.h"
#include "mitkITKImageImport.h"
#include "itkImage.h"
#include "itkBinaryThresholdImageFilter.h"
#include "itkConnectedAdaptiveThresholdImageFilter.h"
#include "mitkImageCast.h"
#include "mitkImageAccessByItk.h"
#include "mitkMaskAndCutRoiImageFilter.h"
#include "mitkPadImageFilter.h"
#include "mitkRegionGrow3DTool.xpm"
namespace mitk {
MITK_TOOL_MACRO(MitkSegmentation_EXPORT, RegionGrow3DTool, "RegionGrower 3D");
}
mitk::RegionGrow3DTool::RegionGrow3DTool(): Tool("PressMoveRelease"),
m_LowerThreshold(-5000),
m_UpperThreshold(5000),
m_CurrentRGDirectionIsUpwards(false)
{
CONNECT_FUNCTION( "Release", OnMouseReleased);
m_FeedbackNode = DataNode::New();
m_FeedbackNode->SetProperty( "color", ColorProperty::New(1.0, 0.0, 0.0) );
m_FeedbackNode->SetProperty( "texture interpolation", BoolProperty::New(false) );
m_FeedbackNode->SetProperty( "layer", IntProperty::New( 100 ) );
m_FeedbackNode->SetProperty( "levelwindow", LevelWindowProperty::New( LevelWindow(100, 1) ) );
m_FeedbackNode->SetProperty( "name", StringProperty::New("failsafe region grow feedback") );
m_FeedbackNode->SetProperty( "opacity", FloatProperty::New(0.3) );
m_FeedbackNode->SetProperty( "helper object", BoolProperty::New(true) );
m_FeedbackNode->SetVisibility(false);
m_PointSetNode = mitk::DataNode::New();
m_PointSetNode->SetName("regiongrow3d pointset");
m_PointSetNode->SetProperty("helper object", mitk::BoolProperty::New(true));
m_PointSetNode->SetProperty("layer", mitk::IntProperty::New(2));
mitk::PointSet::Pointer pointSet = mitk::PointSet::New();
m_PointSetNode->SetData(pointSet);
}
mitk::RegionGrow3DTool::~RegionGrow3DTool()
{
}
bool mitk::RegionGrow3DTool::OnMouseReleased( StateMachineAction*, InteractionEvent* /*interactionEvent*/ )
{
mitk::PointSetInteractor::Pointer interactor = dynamic_cast<mitk::PointSetInteractor*> (m_PointSetNode->GetInteractor());
if (interactor.IsNotNull())
{
mitk::PointSet::Pointer pointSet = dynamic_cast<mitk::PointSet*> (m_PointSetNode->GetData());
if (pointSet.IsNotNull())
{
if (pointSet->GetSize() == 1)
{
//check if we have a valid picture
this->RunSegmentation();
SeedButtonToggled.Send(false);
}
}
}
return true;
}
void mitk::RegionGrow3DTool::Activated()
{
if (m_ToolManager)
{
m_ToolManager->RoiDataChanged += mitk::MessageDelegate<mitk::RegionGrow3DTool>(this, &mitk::RegionGrow3DTool::UpdatePreview);
m_OriginalImageNode = m_ToolManager->GetReferenceData(0);
m_NodeToProceed = m_OriginalImageNode;
if (m_NodeToProceed.IsNotNull())
{
SetupPreviewNodeFor(m_NodeToProceed);
mitk::Image::Pointer image = dynamic_cast<mitk::Image*> (m_OriginalImageNode->GetData());
if (image.IsNotNull())
{
m_RoiMin = image->GetScalarValueMin();
m_RoiMax = image->GetScalarValueMax();
}
}
else
m_ToolManager->ActivateTool(-1);
}
}
void mitk::RegionGrow3DTool::Deactivated()
{
m_ToolManager->RoiDataChanged -= mitk::MessageDelegate<mitk::RegionGrow3DTool>(this, &mitk::RegionGrow3DTool::UpdatePreview);
if (mitk::DataStorage* ds = m_ToolManager->GetDataStorage())
{
ds->Remove(m_PointSetNode);
ds->Remove(m_FeedbackNode);
}
m_FeedbackNode->SetData(NULL);
m_FeedbackNode->SetLevelWindow(NULL);
m_FeedbackNode->SetVisibility(false);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
const char* mitk::RegionGrow3DTool::GetName() const
{
return "RegionGrower 3D";
}
const char** mitk::RegionGrow3DTool::GetXPM() const
{
return mitkRegionGrow3DTool_xpm;
}
void mitk::RegionGrow3DTool::SetSeedPoint(bool toggled)
{
if (!m_ToolManager->GetDataStorage()->Exists(m_PointSetNode)) //no pointSet present
m_ToolManager->GetDataStorage()->Add(m_PointSetNode, m_OriginalImageNode);
//add Interactor if there is none and add it to GlobalInteraction
if (toggled == true) // button is down
{
mitk::PointSetInteractor::Pointer interactor = dynamic_cast<mitk::PointSetInteractor*> (m_PointSetNode->GetInteractor());
if (interactor.IsNull())
{
//create a new interactor and add it to node
interactor = mitk::PointSetInteractor::New("singlepointinteractorwithoutshiftclick", m_PointSetNode, 1);
}
mitk::GlobalInteraction::GetInstance()->AddInteractor(interactor);
}
else
{
mitk::PointSetInteractor::Pointer interactor = dynamic_cast<mitk::PointSetInteractor*> (m_PointSetNode->GetInteractor());
if (interactor.IsNotNull())
{
m_PointSetNode->SetInteractor(NULL);
mitk::GlobalInteraction::GetInstance()->RemoveInteractor(interactor);
}
}
}
void mitk::RegionGrow3DTool::RunSegmentation()
{
//safety if no pointSet or pointSet empty
mitk::PointSet::Pointer seedPointSet = dynamic_cast<mitk::PointSet*> (m_PointSetNode->GetData());
if (seedPointSet.IsNull())
{
return;
}
if (!(seedPointSet->GetSize() > 0))
{
return;
}
mitk::PointSet::PointType seedPoint = seedPointSet->GetPointSet()->GetPoints()->Begin().Value();
mitk::Image::Pointer image = dynamic_cast<mitk::Image*> (m_NodeToProceed->GetData());
if (image.IsNotNull())
{
m_LowerThreshold = static_cast<int> (m_RoiMin);
m_UpperThreshold = static_cast<int> (m_RoiMax);
AccessByItk_2(image, StartRegionGrowing, image->GetGeometry(), seedPoint);
}
}
template<typename TPixel, unsigned int VImageDimension>
-void mitk::RegionGrow3DTool::StartRegionGrowing(itk::Image<TPixel, VImageDimension>* itkImage, mitk::Geometry3D* imageGeometry, mitk::PointSet::PointType seedPoint)
+void mitk::RegionGrow3DTool::StartRegionGrowing(itk::Image<TPixel, VImageDimension>* itkImage, mitk::BaseGeometry* imageGeometry, mitk::PointSet::PointType seedPoint)
{
typedef itk::Image<TPixel, VImageDimension> InputImageType;
typedef typename InputImageType::IndexType IndexType;
typedef itk::ConnectedAdaptiveThresholdImageFilter<InputImageType, InputImageType> RegionGrowingFilterType;
typename RegionGrowingFilterType::Pointer regionGrower = RegionGrowingFilterType::New();
if ( !imageGeometry->IsInside(seedPoint) )
{
return;
}
IndexType seedIndex;
imageGeometry->WorldToIndex( seedPoint, seedIndex);// convert world coordinates to image indices
//int seedValue = itkImage->GetPixel(seedIndex);
regionGrower->SetInput( itkImage );
regionGrower->AddSeed( seedIndex );
regionGrower->SetLower( m_LowerThreshold );
regionGrower->SetUpper( m_UpperThreshold );
regionGrower->SetGrowingDirectionIsUpwards( m_CurrentRGDirectionIsUpwards );
try
{
regionGrower->Update();
}
catch( ... )
{
MITK_ERROR << "Something went wrong!" << endl;
return;
}
m_SeedpointValue = regionGrower->GetSeedpointValue();
//initialize slider
if(m_CurrentRGDirectionIsUpwards)
{
UpperThresholdValueChanged.Send(m_UpperThreshold);
LowerThresholdValueChanged.Send(m_SeedpointValue);
}
else
{
UpperThresholdValueChanged.Send(m_SeedpointValue);
LowerThresholdValueChanged.Send(m_LowerThreshold);
}
m_DetectedLeakagePoint = regionGrower->GetLeakagePoint();
mitk::Image::Pointer resultImage = mitk::ImportItkImage(regionGrower->GetOutput())->Clone();
m_FeedbackNode->SetData( resultImage );
m_FeedbackNode->SetVisibility(true);
InitializeLevelWindow();
}
void mitk::RegionGrow3DTool::InitializeLevelWindow()
{
mitk::LevelWindow tempLevelWindow;
m_FeedbackNode->GetLevelWindow(tempLevelWindow, NULL, "levelWindow");
mitk::ScalarType* level = new mitk::ScalarType(0.5);
mitk::ScalarType* window = new mitk::ScalarType(1);
int upper;
if (m_CurrentRGDirectionIsUpwards)
{
upper = m_UpperThreshold - m_SeedpointValue;
}
else
{
upper = m_SeedpointValue - m_LowerThreshold;
}
tempLevelWindow.SetRangeMinMax(mitk::ScalarType(0), mitk::ScalarType(upper));
tempLevelWindow.SetLevelWindow(*level, *window);
m_FeedbackNode->SetLevelWindow(tempLevelWindow, NULL, "levelWindow");
//get the suggested threshold from the detected leakage-point and adjust the slider
if (m_CurrentRGDirectionIsUpwards)
{
SliderValueChanged.Send(m_SeedpointValue + m_DetectedLeakagePoint -1);
}
else
{
SliderValueChanged.Send(m_SeedpointValue - m_DetectedLeakagePoint +1);
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void mitk::RegionGrow3DTool::ChangeLevelWindow(int value)
{
if (m_FeedbackNode.IsNull())
return;
mitk::LevelWindow tempLevelWindow;
m_FeedbackNode->GetLevelWindow(tempLevelWindow, NULL, "levelWindow"); //get the levelWindow associated with the preview
mitk::ScalarType level;// = this->m_UPPERTHRESHOLD - newValue + 0.5;
mitk::ScalarType* window = new mitk::ScalarType(1);
//adjust the levelwindow according to the position of the slider (newvalue)
if (m_CurrentRGDirectionIsUpwards)
{
level = m_UpperThreshold - value + 0.5;
tempLevelWindow.SetLevelWindow(level, *window);
}
else
{
level = value - m_LowerThreshold +0.5;
tempLevelWindow.SetLevelWindow(level, *window);
}
m_FeedbackNode->SetLevelWindow(tempLevelWindow, NULL, "levelWindow");
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void mitk::RegionGrow3DTool::ConfirmSegmentation( std::string name, mitk::Color color)
{
mitk::DataNode::Pointer new_node = mitk::DataNode::New();
new_node->SetColor(color);
new_node->SetName(name);
new_node->SetProperty("binary", mitk::BoolProperty::New("true"));
mitk::Image* image = dynamic_cast<mitk::Image*> (m_FeedbackNode->GetData());
mitk::LevelWindow tempLevelWindow;
m_FeedbackNode->GetLevelWindow( tempLevelWindow, NULL, "levelWindow");
int upperThresholdLabeledImage = (short int) tempLevelWindow.GetRangeMax();
int lowerThresholdLabeledImage = (short int) tempLevelWindow.GetLowerWindowBound() + 1;
typedef itk::Image<int, 3> InputImageType;
typedef itk::Image<unsigned char, 3> SegmentationType;
typedef itk::BinaryThresholdImageFilter<InputImageType, SegmentationType> ThresholdFilterType;
ThresholdFilterType::Pointer filter = ThresholdFilterType::New();
InputImageType::Pointer itkImage;
mitk::CastToItkImage(image, itkImage);
filter->SetInput(itkImage);
filter->SetInsideValue(1);
filter->SetOutsideValue(0);
filter->SetUpperThreshold(upperThresholdLabeledImage);
filter->SetLowerThreshold(lowerThresholdLabeledImage);
filter->Update();
mitk::Image::Pointer new_image = mitk::Image::New();
mitk::CastToMitkImage(filter->GetOutput(), new_image);
//pad to original size
if (m_OriginalImageNode.GetPointer() != m_NodeToProceed.GetPointer())
{
mitk::PadImageFilter::Pointer padFilter = mitk::PadImageFilter::New();
padFilter->SetInput(0, new_image);
padFilter->SetInput(1, dynamic_cast<mitk::Image*> (m_OriginalImageNode->GetData()));
padFilter->SetBinaryFilter(true);
padFilter->SetUpperThreshold(1);
padFilter->SetLowerThreshold(1);
padFilter->Update();
new_image = padFilter->GetOutput();
}
new_node->SetData(new_image);
m_ToolManager->GetDataStorage()->Add(new_node);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
m_ToolManager->ActivateTool(-1);
}
void mitk::RegionGrow3DTool::CancelSegmentation()
{
m_ToolManager->ActivateTool(-1);
}
void mitk::RegionGrow3DTool::SetupPreviewNodeFor( DataNode* nodeToProceed)
{
if (nodeToProceed)
{
Image::Pointer image = dynamic_cast<Image*>( nodeToProceed->GetData() );
if (image.IsNotNull())
{
m_FeedbackNode->SetData( image );
int layer(50);
nodeToProceed->GetIntProperty("layer", layer);
m_FeedbackNode->SetIntProperty("layer", layer+1);
m_FeedbackNode->SetLevelWindow(NULL);
if (DataStorage* storage = m_ToolManager->GetDataStorage())
{
if (storage->Exists(m_FeedbackNode))
storage->Remove(m_FeedbackNode);
storage->Add( m_FeedbackNode, nodeToProceed );
}
}
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void mitk::RegionGrow3DTool::UpdatePreview()
{
typedef itk::Image<int, 3> ItkImageType;
typedef itk::Image<unsigned char, 3> ItkMaskType;
mitk::DataNode::Pointer node = m_ToolManager->GetRoiData(0);
if (node.IsNull())
{
this->SetupPreviewNodeFor(m_OriginalImageNode);
m_NodeToProceed = m_OriginalImageNode;
mitk::Image::Pointer image = dynamic_cast<mitk::Image*> (m_OriginalImageNode->GetData());
if (image.IsNotNull())
{
m_RoiMin = image->GetScalarValueMin();
m_RoiMax = image->GetScalarValueMax();
}
return;
}
mitk::MaskAndCutRoiImageFilter::Pointer roiFilter = mitk::MaskAndCutRoiImageFilter::New();
roiFilter->SetInput(dynamic_cast<mitk::Image*> (m_NodeToProceed->GetData()));
roiFilter->SetRegionOfInterest(node->GetData());
roiFilter->Update();
mitk::DataNode::Pointer new_node = mitk::DataNode::New();
mitk::Image::Pointer tmpImage = roiFilter->GetOutput();
new_node->SetData(tmpImage);
m_RoiMax = roiFilter->GetMaxValue();
m_RoiMin = roiFilter->GetMinValue();
this->SetupPreviewNodeFor(new_node);
m_NodeToProceed = new_node;
//this->RunSegmentation();
}
void mitk::RegionGrow3DTool::SetCurrentRGDirectionIsUpwards(bool flag)
{
m_CurrentRGDirectionIsUpwards = flag;
}
diff --git a/Modules/Segmentation/Interactions/mitkRegionGrow3DTool.h b/Modules/Segmentation/Interactions/mitkRegionGrow3DTool.h
index 26d79fc4a6..190f536cef 100644
--- a/Modules/Segmentation/Interactions/mitkRegionGrow3DTool.h
+++ b/Modules/Segmentation/Interactions/mitkRegionGrow3DTool.h
@@ -1,87 +1,87 @@
/*===================================================================
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 MITKREGIONGROW3DTOOL_H
#define MITKREGIONGROW3DTOOL_H
#include "mitkTool.h"
#include "mitkPointSet.h"
#include <MitkSegmentationExports.h>
#include "mitkStateEvent.h"
#include "itkImage.h"
namespace mitk{
class StateMachineAction;
class InteractionEvent;
class MitkSegmentation_EXPORT RegionGrow3DTool : public Tool
{
public:
mitkClassMacro(RegionGrow3DTool, Tool);
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
mitk::Message1<int> UpperThresholdValueChanged;
mitk::Message1<int> LowerThresholdValueChanged;
mitk::Message1<int> SliderValueChanged;
mitk::Message1<bool> SeedButtonToggled;
virtual const char* GetName() const;
virtual const char** GetXPM() const;
virtual void Activated();
virtual void Deactivated();
void RunSegmentation();
void ConfirmSegmentation(std::string name, mitk::Color color);
void CancelSegmentation();
void InitializeLevelWindow();
void ChangeLevelWindow(int);
void SetSeedPoint(bool);
void SetCurrentRGDirectionIsUpwards(bool);
protected:
RegionGrow3DTool();
virtual ~RegionGrow3DTool();
void SetupPreviewNodeFor(mitk::DataNode* nodeToProceed);
void UpdatePreview();
template < typename TPixel, unsigned int VImageDimension >
- void StartRegionGrowing( itk::Image< TPixel, VImageDimension >* itkImage, mitk::Geometry3D* imageGeometry, mitk::PointSet::PointType seedPoint );
+ void StartRegionGrowing( itk::Image< TPixel, VImageDimension >* itkImage, mitk::BaseGeometry* imageGeometry, mitk::PointSet::PointType seedPoint );
bool OnMouseReleased( StateMachineAction*, InteractionEvent* );
int m_SeedpointValue;
mitk::ScalarType m_RoiMax;
mitk::ScalarType m_RoiMin;
int m_LowerThreshold;
int m_UpperThreshold;
int m_DetectedLeakagePoint;
bool m_CurrentRGDirectionIsUpwards;
mitk::DataNode::Pointer m_PointSetNode;
mitk::DataNode::Pointer m_FeedbackNode;
mitk::DataNode::Pointer m_NodeToProceed;
mitk::DataNode::Pointer m_OriginalImageNode;
};//class
}//namespace
#endif
diff --git a/Modules/Segmentation/Interactions/mitkRegionGrowingTool.cpp b/Modules/Segmentation/Interactions/mitkRegionGrowingTool.cpp
index 05e0dc5fa3..a6f64920ed 100644
--- a/Modules/Segmentation/Interactions/mitkRegionGrowingTool.cpp
+++ b/Modules/Segmentation/Interactions/mitkRegionGrowingTool.cpp
@@ -1,702 +1,702 @@
/*===================================================================
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 "mitkRegionGrowingTool.h"
#include "mitkToolManager.h"
#include "mitkOverwriteSliceImageFilter.h"
#include "mitkImageDataItem.h"
#include "mitkBaseRenderer.h"
#include "mitkRenderingManager.h"
#include "mitkApplicationCursor.h"
#include "ipSegmentation.h"
#include "mitkRegionGrowingTool.xpm"
#include "mitkOverwriteDirectedPlaneImageFilter.h"
#include "mitkExtractDirectedPlaneImageFilterNew.h"
// us
#include <usModule.h>
#include <usModuleResource.h>
#include <usGetModuleContext.h>
#include <usModuleContext.h>
namespace mitk {
MITK_TOOL_MACRO(MitkSegmentation_EXPORT, RegionGrowingTool, "Region growing tool");
}
#define ROUND(a) ((a)>0 ? (int)((a)+0.5) : -(int)(0.5-(a)))
mitk::RegionGrowingTool::RegionGrowingTool()
:FeedbackContourTool("PressMoveRelease"),
m_LowerThreshold(200),
m_UpperThreshold(200),
m_InitialLowerThreshold(200),
m_InitialUpperThreshold(200),
m_ScreenYDifference(0),
m_OriginalPicSlice(NULL),
m_SeedPointMemoryOffset(0),
m_VisibleWindow(0),
m_DefaultWindow(0),
m_MouseDistanceScaleFactor(0.5),
m_LastWorkingSeed(-1),
m_FillFeedbackContour(true)
{
}
mitk::RegionGrowingTool::~RegionGrowingTool()
{
}
void mitk::RegionGrowingTool::ConnectActionsAndFunctions()
{
CONNECT_FUNCTION( "PrimaryButtonPressed", OnMousePressed);
CONNECT_FUNCTION( "Move", OnMouseMoved);
CONNECT_FUNCTION( "Release", OnMouseReleased);
}
const char** mitk::RegionGrowingTool::GetXPM() const
{
return mitkRegionGrowingTool_xpm;
}
us::ModuleResource mitk::RegionGrowingTool::GetIconResource() const
{
us::Module* module = us::GetModuleContext()->GetModule();
us::ModuleResource resource = module->GetResource("RegionGrowing_48x48.png");
return resource;
}
us::ModuleResource mitk::RegionGrowingTool::GetCursorIconResource() const
{
us::Module* module = us::GetModuleContext()->GetModule();
us::ModuleResource resource = module->GetResource("RegionGrowing_Cursor_32x32.png");
return resource;
}
const char* mitk::RegionGrowingTool::GetName() const
{
return "Region Growing";
}
void mitk::RegionGrowingTool::Activated()
{
Superclass::Activated();
}
void mitk::RegionGrowingTool::Deactivated()
{
Superclass::Deactivated();
}
/**
1 Determine which slice is clicked into
2 Determine if the user clicked inside or outside of the segmentation
3 Depending on the pixel value under the mouse click position, two different things happen: (separated out into OnMousePressedInside and OnMousePressedOutside)
3.1 Create a skeletonization of the segmentation and try to find a nice cut
3.1.1 Call a ipSegmentation algorithm to create a nice cut
3.1.2 Set the result of this algorithm as the feedback contour
3.2 Initialize region growing
3.2.1 Determine memory offset inside the original image
3.2.2 Determine initial region growing parameters from the level window settings of the image
3.2.3 Perform a region growing (which generates a new feedback contour)
*/
bool mitk::RegionGrowingTool::OnMousePressed ( StateMachineAction*, InteractionEvent* interactionEvent )
{
mitk::InteractionPositionEvent* positionEvent = dynamic_cast<mitk::InteractionPositionEvent*>( interactionEvent );
//const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent());
if (!positionEvent) return false;
m_LastEventSender = positionEvent->GetSender();
m_LastEventSlice = m_LastEventSender->GetSlice();
//ToolLogger::SetVerboseness(3);
MITK_DEBUG << "OnMousePressed" << std::endl;
if ( FeedbackContourTool::CanHandleEvent(interactionEvent) > 0.0 )
{
MITK_DEBUG << "OnMousePressed: FeedbackContourTool says ok" << std::endl;
// 1. Find out which slice the user clicked, find out which slice of the toolmanager's reference and working image corresponds to that
if (positionEvent)
{
MITK_DEBUG << "OnMousePressed: got positionEvent" << std::endl;
m_ReferenceSlice = FeedbackContourTool::GetAffectedReferenceSlice( positionEvent );
m_WorkingSlice = FeedbackContourTool::GetAffectedWorkingSlice( positionEvent );
if ( m_WorkingSlice.IsNotNull() ) // can't do anything without the segmentation
{
MITK_DEBUG << "OnMousePressed: got working slice" << std::endl;
// 2. Determine if the user clicked inside or outside of the segmentation
- const Geometry3D* workingSliceGeometry = m_WorkingSlice->GetGeometry();
+ const BaseGeometry* workingSliceGeometry = m_WorkingSlice->GetGeometry();
Point3D mprojectedPointIn2D;
workingSliceGeometry->WorldToIndex( positionEvent->GetPositionInWorld(), mprojectedPointIn2D);
itk::Index<2> projectedPointInWorkingSlice2D;
projectedPointInWorkingSlice2D[0] = static_cast<int>( mprojectedPointIn2D[0] - 0.5 );
projectedPointInWorkingSlice2D[1] = static_cast<int>( mprojectedPointIn2D[1] - 0.5 );
if ( workingSliceGeometry->IsIndexInside( projectedPointInWorkingSlice2D ) )
{
MITK_DEBUG << "OnMousePressed: point " << positionEvent->GetPositionInWorld() << " (index coordinates " << projectedPointInWorkingSlice2D << ") IS in working slice" << std::endl;
// Convert to ipMITKSegmentationTYPE (because getting pixels relys on that data type)
itk::Image< ipMITKSegmentationTYPE, 2 >::Pointer correctPixelTypeImage;
CastToItkImage( m_WorkingSlice, correctPixelTypeImage );
assert (correctPixelTypeImage.IsNotNull() );
// possible bug in CastToItkImage ?
// direction maxtrix is wrong/broken/not working after CastToItkImage, leading to a failed assertion in
// mitk/Core/DataStructures/mitkSlicedGeometry3D.cpp, 479:
// virtual void mitk::SlicedGeometry3D::SetSpacing(const mitk::Vector3D&): Assertion `aSpacing[0]>0 && aSpacing[1]>0 && aSpacing[2]>0' failed
// solution here: we overwrite it with an unity matrix
itk::Image< ipMITKSegmentationTYPE, 2 >::DirectionType imageDirection;
imageDirection.SetIdentity();
correctPixelTypeImage->SetDirection(imageDirection);
Image::Pointer temporarySlice = Image::New();
// temporarySlice = ImportItkImage( correctPixelTypeImage );
CastToMitkImage( correctPixelTypeImage, temporarySlice );
mitkIpPicDescriptor* workingPicSlice = mitkIpPicNew();
CastToIpPicDescriptor(temporarySlice, workingPicSlice);
int initialWorkingOffset = projectedPointInWorkingSlice2D[1] * workingPicSlice->n[0] + projectedPointInWorkingSlice2D[0];
if ( initialWorkingOffset < static_cast<int>( workingPicSlice->n[0] * workingPicSlice->n[1] ) &&
initialWorkingOffset >= 0 )
{
// 3. determine the pixel value under the last click
bool inside = static_cast<ipMITKSegmentationTYPE*>(workingPicSlice->data)[initialWorkingOffset] != 0;
m_PaintingPixelValue = inside ? 0 : 1; // if inside, we want to remove a part, otherwise we want to add something
if ( m_LastWorkingSeed >= static_cast<int>( workingPicSlice->n[0] * workingPicSlice->n[1] ) ||
m_LastWorkingSeed < 0 )
{
inside = false;
}
if ( m_ReferenceSlice.IsNotNull() )
{
MITK_DEBUG << "OnMousePressed: got reference slice" << std::endl;
m_OriginalPicSlice = mitkIpPicNew();
CastToIpPicDescriptor(m_ReferenceSlice, m_OriginalPicSlice);
// 3.1. Switch depending on the pixel value
if (inside)
{
OnMousePressedInside( NULL, interactionEvent, workingPicSlice, initialWorkingOffset);
}
else
{
OnMousePressedOutside( NULL, interactionEvent);
}
}
}
}
}
}
}
MITK_DEBUG << "end OnMousePressed" << std::endl;
return true;
}
/**
3.1 Create a skeletonization of the segmentation and try to find a nice cut
3.1.1 Call a ipSegmentation algorithm to create a nice cut
3.1.2 Set the result of this algorithm as the feedback contour
*/
bool mitk::RegionGrowingTool::OnMousePressedInside( StateMachineAction*, InteractionEvent* interactionEvent, mitkIpPicDescriptor* workingPicSlice, int initialWorkingOffset)
{
mitk::InteractionPositionEvent* positionEvent = dynamic_cast<mitk::InteractionPositionEvent*>( interactionEvent );
//const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent()); // checked in OnMousePressed
// 3.1.1. Create a skeletonization of the segmentation and try to find a nice cut
// apply the skeletonization-and-cut algorithm
// generate contour to remove
// set m_ReferenceSlice = NULL so nothing will happen during mouse move
// remember to fill the contour with 0 in mouserelease
mitkIpPicDescriptor* segmentationHistory = ipMITKSegmentationCreateGrowerHistory( workingPicSlice, m_LastWorkingSeed, NULL ); // free again
if (segmentationHistory)
{
tCutResult cutContour = ipMITKSegmentationGetCutPoints( workingPicSlice, segmentationHistory, initialWorkingOffset ); // tCutResult is a ipSegmentation type
mitkIpPicFree( segmentationHistory );
if (cutContour.cutIt)
{
int timestep = positionEvent->GetSender()->GetTimeStep();
// 3.1.2 copy point from float* to mitk::Contour
ContourModel::Pointer contourInImageIndexCoordinates = ContourModel::New();
contourInImageIndexCoordinates->Expand(timestep + 1);
contourInImageIndexCoordinates->SetClosed(true, timestep);
Point3D newPoint;
for (int index = 0; index < cutContour.deleteSize; ++index)
{
newPoint[0] = cutContour.deleteCurve[ 2 * index + 0 ] - 0.5;//correction is needed because the output of the algorithm is center based
newPoint[1] = cutContour.deleteCurve[ 2 * index + 1 ] - 0.5;//and we want our contour displayed corner based.
newPoint[2] = 0.0;
contourInImageIndexCoordinates->AddVertex( newPoint, timestep );
}
free(cutContour.traceline);
free(cutContour.deleteCurve); // perhaps visualize this for fun?
free(cutContour.onGradient);
ContourModel::Pointer contourInWorldCoordinates = FeedbackContourTool::BackProjectContourFrom2DSlice( m_WorkingSlice->GetGeometry(), contourInImageIndexCoordinates, true ); // true: sub 0.5 for ipSegmentation correction
FeedbackContourTool::SetFeedbackContour( *contourInWorldCoordinates );
FeedbackContourTool::SetFeedbackContourVisible(true);
mitk::RenderingManager::GetInstance()->RequestUpdate( positionEvent->GetSender()->GetRenderWindow() );
m_FillFeedbackContour = true;
}
else
{
m_FillFeedbackContour = false;
}
}
else
{
m_FillFeedbackContour = false;
}
m_ReferenceSlice = NULL;
return true;
}
/**
3.2 Initialize region growing
3.2.1 Determine memory offset inside the original image
3.2.2 Determine initial region growing parameters from the level window settings of the image
3.2.3 Perform a region growing (which generates a new feedback contour)
*/
bool mitk::RegionGrowingTool::OnMousePressedOutside( StateMachineAction*, InteractionEvent* interactionEvent )
{
mitk::InteractionPositionEvent* positionEvent = dynamic_cast<mitk::InteractionPositionEvent*>( interactionEvent );
//const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent()); // checked in OnMousePressed
// 3.2 If we have a reference image, then perform an initial region growing, considering the reference image's level window
// if click was outside the image, don't continue
- const Geometry3D* sliceGeometry = m_ReferenceSlice->GetGeometry();
+ const BaseGeometry* sliceGeometry = m_ReferenceSlice->GetGeometry();
Point3D mprojectedPointIn2D;
sliceGeometry->WorldToIndex( positionEvent->GetPositionInWorld(), mprojectedPointIn2D );
itk::Index<2> projectedPointIn2D;
projectedPointIn2D[0] = static_cast<int>( mprojectedPointIn2D[0] - 0.5 );
projectedPointIn2D[1] = static_cast<int>( mprojectedPointIn2D[1] - 0.5 );
if ( sliceGeometry->IsIndexInside( mprojectedPointIn2D ) )
{
MITK_DEBUG << "OnMousePressed: point " << positionEvent->GetPositionInWorld() << " (index coordinates " << mprojectedPointIn2D << ") IS in reference slice" << std::endl;
// 3.2.1 Remember Y cursor position and initial seed point
//m_ScreenYPositionAtStart = static_cast<int>(positionEvent->GetDisplayPosition()[1]);
m_LastScreenPosition = ApplicationCursor::GetInstance()->GetCursorPosition();
m_ScreenYDifference = 0;
m_SeedPointMemoryOffset = projectedPointIn2D[1] * m_OriginalPicSlice->n[0] + projectedPointIn2D[0];
m_LastWorkingSeed = m_SeedPointMemoryOffset; // remember for skeletonization
if ( m_SeedPointMemoryOffset < static_cast<int>( m_OriginalPicSlice->n[0] * m_OriginalPicSlice->n[1] ) &&
m_SeedPointMemoryOffset >= 0 )
{
// 3.2.2 Get level window from reference DataNode
// Use some logic to determine initial gray value bounds
LevelWindow lw(0, 500);
m_ToolManager->GetReferenceData(0)->GetLevelWindow(lw); // will fill lw if levelwindow property is present, otherwise won't touch it.
ScalarType currentVisibleWindow = lw.GetWindow();
if (!mitk::Equal(currentVisibleWindow, m_VisibleWindow))
{
m_InitialLowerThreshold = currentVisibleWindow / 20.0;
m_InitialUpperThreshold = currentVisibleWindow / 20.0;
m_LowerThreshold = m_InitialLowerThreshold;
m_UpperThreshold = m_InitialUpperThreshold;
// 3.2.3. Actually perform region growing
mitkIpPicDescriptor* result = PerformRegionGrowingAndUpdateContour(positionEvent->GetSender()->GetTimeStep());
ipMITKSegmentationFree( result);
// display the contour
FeedbackContourTool::SetFeedbackContourVisible(true);
mitk::RenderingManager::GetInstance()->RequestUpdate(positionEvent->GetSender()->GetRenderWindow());
m_FillFeedbackContour = true;
}
}
return true;
}
return false;
}
/**
If in region growing mode (m_ReferenceSlice != NULL), then
1. Calculate the new thresholds from mouse position (relative to first position)
2. Perform a new region growing and update the feedback contour
*/
bool mitk::RegionGrowingTool::OnMouseMoved( StateMachineAction*, InteractionEvent* interactionEvent )
{
if ( FeedbackContourTool::CanHandleEvent(interactionEvent) > 0.0 )
{
if ( m_ReferenceSlice.IsNotNull() && m_OriginalPicSlice )
{
mitk::InteractionPositionEvent* positionEvent = dynamic_cast<mitk::InteractionPositionEvent*>( interactionEvent );
//const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent());
if (positionEvent)
{
ApplicationCursor* cursor = ApplicationCursor::GetInstance();
if (!cursor) return false;
m_ScreenYDifference += cursor->GetCursorPosition()[1] - m_LastScreenPosition[1];
cursor->SetCursorPosition( m_LastScreenPosition );
m_LowerThreshold = std::max<mitk::ScalarType>(0.0, m_InitialLowerThreshold - m_ScreenYDifference * m_MouseDistanceScaleFactor);
m_UpperThreshold = std::max<mitk::ScalarType>(0.0, m_InitialUpperThreshold - m_ScreenYDifference * m_MouseDistanceScaleFactor);
// 2. Perform region growing again and show the result
mitkIpPicDescriptor* result = PerformRegionGrowingAndUpdateContour(positionEvent->GetSender()->GetTimeStep());
ipMITKSegmentationFree( result );
// 3. Update the contour
mitk::RenderingManager::GetInstance()->ForceImmediateUpdate(positionEvent->GetSender()->GetRenderWindow());
}
}
}
return true;
}
/**
If the feedback contour should be filled, then it is done here. (Contour is NOT filled, when skeletonization is done but no nice cut was found)
*/
bool mitk::RegionGrowingTool::OnMouseReleased( StateMachineAction*, InteractionEvent* interactionEvent )
{
if ( FeedbackContourTool::CanHandleEvent(interactionEvent) > 0.0 )
{
// 1. If we have a working slice, use the contour to fill a new piece on segmentation on it (or erase a piece that was selected by ipMITKSegmentationGetCutPoints)
if ( m_WorkingSlice.IsNotNull() && m_OriginalPicSlice )
{
mitk::InteractionPositionEvent* positionEvent = dynamic_cast<mitk::InteractionPositionEvent*>( interactionEvent );
//const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent());
if (positionEvent)
{
// remember parameters for next time
m_InitialLowerThreshold = m_LowerThreshold;
m_InitialUpperThreshold = m_UpperThreshold;
int timestep = positionEvent->GetSender()->GetTimeStep();
if (m_FillFeedbackContour)
{
// 3. use contour to fill a region in our working slice
ContourModel* feedbackContour( FeedbackContourTool::GetFeedbackContour() );
if (feedbackContour)
{
ContourModel::Pointer projectedContour = FeedbackContourTool::ProjectContourTo2DSlice( m_WorkingSlice, feedbackContour, false, false ); // false: don't add any 0.5
// false: don't constrain the contour to the image's inside
if (projectedContour.IsNotNull())
{
FeedbackContourTool::FillContourInSlice( projectedContour, timestep, m_WorkingSlice, m_PaintingPixelValue );
- const PlaneGeometry* planeGeometry( dynamic_cast<const PlaneGeometry*> (positionEvent->GetSender()->GetCurrentWorldGeometry2D() ) );
+ const PlaneGeometry* planeGeometry( dynamic_cast<const PlaneGeometry*> (positionEvent->GetSender()->GetCurrentWorldPlaneGeometry() ) );
//MITK_DEBUG << "OnMouseReleased: writing back to dimension " << affectedDimension << ", slice " << affectedSlice << " in working image" << std::endl;
// 4. write working slice back into image volume
this->WriteBackSegmentationResult(positionEvent, m_WorkingSlice);
}
}
}
FeedbackContourTool::SetFeedbackContourVisible(false);
mitk::RenderingManager::GetInstance()->RequestUpdate( positionEvent->GetSender()->GetRenderWindow() );
}
}
}
m_ReferenceSlice = NULL; // don't leak
m_WorkingSlice = NULL;
m_OriginalPicSlice = NULL;
return true;
}
/**
Uses ipSegmentation algorithms to do the actual region growing. The result (binary image) is first smoothed by a 5x5 circle mask, then
its contour is extracted and converted to MITK coordinates.
*/
mitkIpPicDescriptor* mitk::RegionGrowingTool::PerformRegionGrowingAndUpdateContour(int timestep)
{
// 1. m_OriginalPicSlice and m_SeedPointMemoryOffset are set to sensitive values, as well as m_LowerThreshold and m_UpperThreshold
assert (m_OriginalPicSlice);
if (m_OriginalPicSlice->n[0] != 256 || m_OriginalPicSlice->n[1] != 256) // ???
assert( (m_SeedPointMemoryOffset < static_cast<int>( m_OriginalPicSlice->n[0] * m_OriginalPicSlice->n[1] )) && (m_SeedPointMemoryOffset >= 0) ); // inside the image
// 2. ipSegmentation is used to perform region growing
float ignored;
int oneContourOffset( 0 );
mitkIpPicDescriptor* regionGrowerResult = ipMITKSegmentationGrowRegion4N( m_OriginalPicSlice,
m_SeedPointMemoryOffset, // seed point
true, // grayvalue interval relative to seed point gray value?
m_LowerThreshold,
m_UpperThreshold,
0, // continue until done (maxIterations == 0)
NULL, // allocate new memory (only this time, on mouse move we'll reuse the old buffer)
oneContourOffset, // a pixel that is near the resulting contour
ignored // ignored by us
);
if (!regionGrowerResult || oneContourOffset == -1)
{
ContourModel::Pointer dummyContour = ContourModel::New();
dummyContour->Initialize();
FeedbackContourTool::SetFeedbackContour( *dummyContour );
if (regionGrowerResult) ipMITKSegmentationFree(regionGrowerResult);
return NULL;
}
// 3. We smooth the result a little to reduce contour complexity
bool smoothResult( true ); // currently fixed, perhaps remove else block
mitkIpPicDescriptor* smoothedRegionGrowerResult;
if (smoothResult)
{
// Smooth the result (otherwise very detailed contour)
smoothedRegionGrowerResult = SmoothIPPicBinaryImage( regionGrowerResult, oneContourOffset );
ipMITKSegmentationFree( regionGrowerResult );
}
else
{
smoothedRegionGrowerResult = regionGrowerResult;
}
// 4. convert the result of region growing into a mitk::Contour
// At this point oneContourOffset could be useless, if smoothing destroyed a thin bridge. In these
// cases, we have two or more unconnected segmentation regions, and we don't know, which one is touched by oneContourOffset.
// In the bad case, the contour is not the one around our seedpoint, so the result looks very strange to the user.
// -> we remove the point where the contour started so far. Then we look from the bottom of the image for the first segmentation pixel
// and start another contour extraction from there. This is done, until the seedpoint is inside the contour
int numberOfContourPoints( 0 );
int newBufferSize( 0 );
float* contourPoints = ipMITKSegmentationGetContour8N( smoothedRegionGrowerResult, oneContourOffset, numberOfContourPoints, newBufferSize ); // memory allocated with malloc
if (contourPoints)
{
while ( !ipMITKSegmentationIsInsideContour( contourPoints, // contour
numberOfContourPoints, // points in contour
m_SeedPointMemoryOffset % smoothedRegionGrowerResult->n[0], // test point x
m_SeedPointMemoryOffset / smoothedRegionGrowerResult->n[0] // test point y
) )
{
// we decide that this cannot be part of the segmentation because the seedpoint is not contained in the contour (fill the 4-neighborhood with 0)
ipMITKSegmentationReplaceRegion4N( smoothedRegionGrowerResult, oneContourOffset, 0 );
// move the contour offset to the last row (x position of the seed point)
int rowLength = smoothedRegionGrowerResult->n[0]; // number of pixels in a row
oneContourOffset = m_SeedPointMemoryOffset % smoothedRegionGrowerResult->n[0] // x of seed point
+ rowLength*(smoothedRegionGrowerResult->n[1]-1); // y of last row
while ( oneContourOffset >=0
&& (*(static_cast<ipMITKSegmentationTYPE*>(smoothedRegionGrowerResult->data) + oneContourOffset) == 0) )
{
oneContourOffset -= rowLength; // if pixel at data+oneContourOffset is 0, then move up one row
}
if ( oneContourOffset < 0 )
{
break; // just use the last contour we found
}
free(contourPoints); // release contour memory
contourPoints = ipMITKSegmentationGetContour8N( smoothedRegionGrowerResult, oneContourOffset, numberOfContourPoints, newBufferSize ); // memory allocated with malloc
}
// copy point from float* to mitk::Contour
ContourModel::Pointer contourInImageIndexCoordinates = ContourModel::New();
contourInImageIndexCoordinates->Expand(timestep + 1);
contourInImageIndexCoordinates->SetClosed(true, timestep);
Point3D newPoint;
for (int index = 0; index < numberOfContourPoints; ++index)
{
newPoint[0] = contourPoints[ 2 * index + 0 ] - 0.5;//correction is needed because the output of the algorithm is center based
newPoint[1] = contourPoints[ 2 * index + 1 ] - 0.5;//and we want our contour displayed corner based.
newPoint[2] = 0;
contourInImageIndexCoordinates->AddVertex( newPoint, timestep );
}
free(contourPoints);
ContourModel::Pointer contourInWorldCoordinates = FeedbackContourTool::BackProjectContourFrom2DSlice( m_ReferenceSlice->GetGeometry(), contourInImageIndexCoordinates, true ); // true: sub 0.5 for ipSegmentation correctio
FeedbackContourTool::SetFeedbackContour( *contourInWorldCoordinates );
}
// 5. Result HAS TO BE freed by caller, contains the binary region growing result
return smoothedRegionGrowerResult;
}
/**
Helper method for SmoothIPPicBinaryImage. Smoothes a given part of and image.
\param sourceImage The original binary image.
\param dest The smoothed image (will be written without bounds checking).
\param contourOfs One offset of the contour. Is updated if a pixel is changed (which might change the contour).
\param maskOffsets Memory offsets that describe the smoothing mask.
\param maskSize Entries of the mask.
\param startOffset First pixel that should be smoothed using this mask.
\param endOffset Last pixel that should be smoothed using this mask.
*/
void mitk::RegionGrowingTool::SmoothIPPicBinaryImageHelperForRows( mitkIpPicDescriptor* sourceImage, mitkIpPicDescriptor* dest, int &contourOfs, int* maskOffsets, int maskSize, int startOffset, int endOffset )
{
// work on the very first row
ipMITKSegmentationTYPE* current;
ipMITKSegmentationTYPE* source = ((ipMITKSegmentationTYPE*)sourceImage->data) + startOffset; // + 1! don't read at start-1
ipMITKSegmentationTYPE* end = ((ipMITKSegmentationTYPE*)dest->data) + endOffset;
int ofs = startOffset;
int minority = (maskSize - 1) / 2;
for (current = ((ipMITKSegmentationTYPE*)dest->data) + startOffset; current<end; current++)
{
mitkIpInt1_t sum( 0 );
for (int i = 0; i < maskSize; ++i)
{
sum += *(source+maskOffsets[i]);
}
if (sum > minority)
{
*current = 1;
contourOfs = ofs;
}
else
{
*current = 0;
}
++source;
++ofs;
}
}
/**
Smoothes a binary ipPic image with a 5x5 mask. The image borders (some first and last rows) are treated differently.
*/
mitkIpPicDescriptor* mitk::RegionGrowingTool::SmoothIPPicBinaryImage( mitkIpPicDescriptor* image, int &contourOfs, mitkIpPicDescriptor* dest )
{
if (!image) return NULL;
// Original code from /trunk/mbi-qm/Qmitk/Qmitk2DSegTools/RegionGrowerTool.cpp (first version by T. Boettger?). Reformatted and documented and restructured.
#define MSK_SIZE5x5 21
#define MSK_SIZE3x3 5
#define MSK_SIZE3x1 3
// mask is an array of coordinates that form a rastered circle like this
//
// OOO
// OOOOO
// OOOOO
// OOOOO
// OOO
//
//
int mask5x5[MSK_SIZE5x5][2]
= {
/******/ {-1,-2}, {0,-2}, {1,-2}, /*****/
{-2,-1}, {-1,-1}, {0,-1}, {1,-1}, {2,-1},
{-2, 0}, {-1, 0}, {0, 0}, {1, 0}, {2, 0},
{-2, 1}, {-1, 1}, {0, 1}, {1, 1}, {2, 1},
/******/ {-1, 2}, {0, 2}, {1, 2} /*****/
};
int mask3x3[MSK_SIZE3x3][2]
= {
/******/ {0,-1}, /*****/
{-1, 0}, {0, 0}, {1, 0},
/******/ {0, 1} /*****/
};
int mask3x1[MSK_SIZE3x1][2]
= {
{-1, 0}, {0, 0}, {1, 0}
};
// The following lines iterate over all the pixels of a (sliced) image (except the first and last three rows).
// For each pixel, all the coordinates around it (according to mask) are evaluated (this means 21 pixels).
// If more than 10 of the evaluated pixels are non-zero, then the central pixel is set to 1, else to 0.
// This is determining a majority. If there is no clear majority, then the central pixel itself "decides".
int maskOffset5x5[MSK_SIZE5x5];
int line = image->n[0];
for (int i=0; i<MSK_SIZE5x5; i++)
{
maskOffset5x5[i] = mask5x5[i][0] + line * mask5x5[i][1]; // calculate memory offsets from the x,y mask elements
}
int maskOffset3x3[MSK_SIZE3x3];
for (int i=0; i<MSK_SIZE3x3; i++)
{
maskOffset3x3[i] = mask3x3[i][0] + line * mask3x3[i][1]; // calculate memory offsets from the x,y mask elements
}
int maskOffset3x1[MSK_SIZE3x1];
for (int i=0; i<MSK_SIZE3x1; i++)
{
maskOffset3x1[i] = mask3x1[i][0] + line * mask3x1[i][1]; // calculate memory offsets from the x,y mask elements
}
if (!dest)
{
// create pic if necessary
dest = ipMITKSegmentationNew( image );
}
int spareOut3Rows = 3*image->n[0];
int spareOut1Rows = 1*image->n[0];
if ( image->n[1] > 0 ) SmoothIPPicBinaryImageHelperForRows( image, dest, contourOfs, maskOffset3x1, MSK_SIZE3x1, 1, dest->n[0] );
if ( image->n[1] > 3 ) SmoothIPPicBinaryImageHelperForRows( image, dest, contourOfs, maskOffset3x3, MSK_SIZE3x3, spareOut1Rows, dest->n[0]*3 );
if ( image->n[1] > 6 ) SmoothIPPicBinaryImageHelperForRows( image, dest, contourOfs, maskOffset5x5, MSK_SIZE5x5, spareOut3Rows, dest->n[0]*dest->n[1] - spareOut3Rows );
if ( image->n[1] > 8 ) SmoothIPPicBinaryImageHelperForRows( image, dest, contourOfs, maskOffset3x3, MSK_SIZE3x3, dest->n[0]*dest->n[1] -spareOut3Rows, dest->n[0]*dest->n[1] - spareOut1Rows );
if ( image->n[1] > 10) SmoothIPPicBinaryImageHelperForRows( image, dest, contourOfs, maskOffset3x1, MSK_SIZE3x1, dest->n[0]*dest->n[1] -spareOut1Rows, dest->n[0]*dest->n[1] - 1 );
// correction for first pixel (sorry for the ugliness)
if ( *((ipMITKSegmentationTYPE*)(dest->data)+1) == 1 )
{
*((ipMITKSegmentationTYPE*)(dest->data)+0) = 1;
}
if (dest->n[0] * dest->n[1] > 2)
{
// correction for last pixel
if ( *((ipMITKSegmentationTYPE*)(dest->data)+dest->n[0]*dest->n[1]-2) == 1 )
{
*((ipMITKSegmentationTYPE*)(dest->data)+dest->n[0]*dest->n[1]-1) = 1;
}
}
return dest;
}
diff --git a/Modules/Segmentation/Interactions/mitkSegTool2D.cpp b/Modules/Segmentation/Interactions/mitkSegTool2D.cpp
index 5ef3294046..4c3b383549 100644
--- a/Modules/Segmentation/Interactions/mitkSegTool2D.cpp
+++ b/Modules/Segmentation/Interactions/mitkSegTool2D.cpp
@@ -1,407 +1,407 @@
/*===================================================================
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 "mitkSegTool2D.h"
#include "mitkToolManager.h"
#include "mitkDataStorage.h"
#include "mitkBaseRenderer.h"
#include "mitkPlaneGeometry.h"
#include "mitkExtractImageFilter.h"
#include "mitkExtractDirectedPlaneImageFilter.h"
//Include of the new ImageExtractor
#include "mitkExtractDirectedPlaneImageFilterNew.h"
#include "mitkPlanarCircle.h"
#include "mitkOverwriteSliceImageFilter.h"
#include "mitkOverwriteDirectedPlaneImageFilter.h"
#include "usGetModuleContext.h"
//Includes for 3DSurfaceInterpolation
#include "mitkImageToContourFilter.h"
#include "mitkSurfaceInterpolationController.h"
//includes for resling and overwriting
#include <mitkExtractSliceFilter.h>
#include <mitkVtkImageOverwrite.h>
#include <vtkSmartPointer.h>
#include <vtkImageData.h>
#include <mitkDiffSliceOperationApplier.h>
#include "mitkOperationEvent.h"
#include "mitkUndoController.h"
#define ROUND(a) ((a)>0 ? (int)((a)+0.5) : -(int)(0.5-(a)))
mitk::SegTool2D::SegTool2D(const char* type)
:Tool(type),
m_LastEventSender(NULL),
m_LastEventSlice(0),
m_Contourmarkername ("Position"),
m_ShowMarkerNodes (false),
m_3DInterpolationEnabled(true)
{
}
mitk::SegTool2D::~SegTool2D()
{
}
float mitk::SegTool2D::CanHandleEvent( InteractionEvent const *stateEvent) const
{
const InteractionPositionEvent* positionEvent = dynamic_cast<const InteractionPositionEvent*>( stateEvent );
if (!positionEvent) return 0.0;
if ( positionEvent->GetSender()->GetMapperID() != BaseRenderer::Standard2D )
return 0.0; // we don't want anything but 2D
return 1.0;
// //This are the mouse event that are used by the statemachine patterns for zooming and panning. This must be possible although a tool is activ
// if (stateEvent->GetId() == EIDRIGHTMOUSEBTN || stateEvent->GetId() == EIDMIDDLEMOUSEBTN || stateEvent->GetId() == EIDRIGHTMOUSEBTNANDCTRL ||
// stateEvent->GetId() == EIDMIDDLEMOUSERELEASE || stateEvent->GetId() == EIDRIGHTMOUSERELEASE || stateEvent->GetId() == EIDRIGHTMOUSEBTNANDMOUSEMOVE ||
// stateEvent->GetId() == EIDMIDDLEMOUSEBTNANDMOUSEMOVE || stateEvent->GetId() == EIDCTRLANDRIGHTMOUSEBTNANDMOUSEMOVE || stateEvent->GetId() == EIDCTRLANDRIGHTMOUSEBTNRELEASE )
// {
// //Since the usual segmentation tools currently do not need right click interaction but the mitkDisplayVectorInteractor
// return 0.0;
// }
// else
// {
// return 1.0;
// }
}
bool mitk::SegTool2D::DetermineAffectedImageSlice( const Image* image, const PlaneGeometry* plane, int& affectedDimension, int& affectedSlice )
{
assert(image);
assert(plane);
// compare normal of plane to the three axis vectors of the image
Vector3D normal = plane->GetNormal();
Vector3D imageNormal0 = image->GetSlicedGeometry()->GetAxisVector(0);
Vector3D imageNormal1 = image->GetSlicedGeometry()->GetAxisVector(1);
Vector3D imageNormal2 = image->GetSlicedGeometry()->GetAxisVector(2);
normal.Normalize();
imageNormal0.Normalize();
imageNormal1.Normalize();
imageNormal2.Normalize();
imageNormal0.SetVnlVector( vnl_cross_3d<ScalarType>(normal.GetVnlVector(),imageNormal0.GetVnlVector()) );
imageNormal1.SetVnlVector( vnl_cross_3d<ScalarType>(normal.GetVnlVector(),imageNormal1.GetVnlVector()) );
imageNormal2.SetVnlVector( vnl_cross_3d<ScalarType>(normal.GetVnlVector(),imageNormal2.GetVnlVector()) );
double eps( 0.00001 );
// axial
if ( imageNormal2.GetNorm() <= eps )
{
affectedDimension = 2;
}
// sagittal
else if ( imageNormal1.GetNorm() <= eps )
{
affectedDimension = 1;
}
// frontal
else if ( imageNormal0.GetNorm() <= eps )
{
affectedDimension = 0;
}
else
{
affectedDimension = -1; // no idea
return false;
}
// determine slice number in image
- Geometry3D* imageGeometry = image->GetGeometry(0);
+ BaseGeometry* imageGeometry = image->GetGeometry(0);
Point3D testPoint = imageGeometry->GetCenter();
Point3D projectedPoint;
plane->Project( testPoint, projectedPoint );
Point3D indexPoint;
imageGeometry->WorldToIndex( projectedPoint, indexPoint );
affectedSlice = ROUND( indexPoint[affectedDimension] );
MITK_DEBUG << "indexPoint " << indexPoint << " affectedDimension " << affectedDimension << " affectedSlice " << affectedSlice;
// check if this index is still within the image
if ( affectedSlice < 0 || affectedSlice >= static_cast<int>(image->GetDimension(affectedDimension)) ) return false;
return true;
}
mitk::Image::Pointer mitk::SegTool2D::GetAffectedImageSliceAs2DImage(const InteractionPositionEvent* positionEvent, const Image* image)
{
if (!positionEvent) return NULL;
assert( positionEvent->GetSender() ); // sure, right?
unsigned int timeStep = positionEvent->GetSender()->GetTimeStep( image ); // get the timestep of the visible part (time-wise) of the image
// first, we determine, which slice is affected
- const PlaneGeometry* planeGeometry( dynamic_cast<const PlaneGeometry*> (positionEvent->GetSender()->GetCurrentWorldGeometry2D() ) );
+ const PlaneGeometry* planeGeometry( dynamic_cast<const PlaneGeometry*> (positionEvent->GetSender()->GetCurrentWorldPlaneGeometry() ) );
return this->GetAffectedImageSliceAs2DImage(planeGeometry, image, timeStep);
}
mitk::Image::Pointer mitk::SegTool2D::GetAffectedImageSliceAs2DImage(const PlaneGeometry* planeGeometry, const Image* image, unsigned int timeStep)
{
if ( !image || !planeGeometry ) return NULL;
//Make sure that for reslicing and overwriting the same alogrithm is used. We can specify the mode of the vtk reslicer
vtkSmartPointer<mitkVtkImageOverwrite> reslice = vtkSmartPointer<mitkVtkImageOverwrite>::New();
//set to false to extract a slice
reslice->SetOverwriteMode(false);
reslice->Modified();
//use ExtractSliceFilter with our specific vtkImageReslice for overwriting and extracting
mitk::ExtractSliceFilter::Pointer extractor = mitk::ExtractSliceFilter::New(reslice);
extractor->SetInput( image );
extractor->SetTimeStep( timeStep );
extractor->SetWorldGeometry( planeGeometry );
extractor->SetVtkOutputRequest(false);
extractor->SetResliceTransformByGeometry( image->GetTimeGeometry()->GetGeometryForTimeStep( timeStep ) );
extractor->Modified();
extractor->Update();
Image::Pointer slice = extractor->GetOutput();
/*============= BEGIN undo feature block ========================*/
//specify the undo operation with the non edited slice
- m_undoOperation = new DiffSliceOperation(const_cast<mitk::Image*>(image), extractor->GetVtkOutput(), slice->GetGeometry(), timeStep, const_cast<mitk::PlaneGeometry*>(planeGeometry));
+ m_undoOperation = new DiffSliceOperation(const_cast<mitk::Image*>(image), extractor->GetVtkOutput(), dynamic_cast<SlicedGeometry3D*>(slice->GetGeometry()), timeStep, const_cast<mitk::PlaneGeometry*>(planeGeometry));
/*============= END undo feature block ========================*/
return slice;
}
mitk::Image::Pointer mitk::SegTool2D::GetAffectedWorkingSlice(const InteractionPositionEvent* positionEvent)
{
DataNode* workingNode( m_ToolManager->GetWorkingData(0) );
if ( !workingNode ) return NULL;
Image* workingImage = dynamic_cast<Image*>(workingNode->GetData());
if ( !workingImage ) return NULL;
return GetAffectedImageSliceAs2DImage( positionEvent, workingImage );
}
mitk::Image::Pointer mitk::SegTool2D::GetAffectedReferenceSlice(const InteractionPositionEvent* positionEvent)
{
DataNode* referenceNode( m_ToolManager->GetReferenceData(0) );
if ( !referenceNode ) return NULL;
Image* referenceImage = dynamic_cast<Image*>(referenceNode->GetData());
if ( !referenceImage ) return NULL;
return GetAffectedImageSliceAs2DImage( positionEvent, referenceImage );
}
void mitk::SegTool2D::WriteBackSegmentationResult (const InteractionPositionEvent* positionEvent, Image* slice)
{
if(!positionEvent) return;
- const PlaneGeometry* planeGeometry( dynamic_cast<const PlaneGeometry*> (positionEvent->GetSender()->GetCurrentWorldGeometry2D() ) );
+ const PlaneGeometry* planeGeometry( dynamic_cast<const PlaneGeometry*> (positionEvent->GetSender()->GetCurrentWorldPlaneGeometry() ) );
if( planeGeometry && slice)
{
DataNode* workingNode( m_ToolManager->GetWorkingData(0) );
Image* image = dynamic_cast<Image*>(workingNode->GetData());
unsigned int timeStep = positionEvent->GetSender()->GetTimeStep( image );
this->WriteBackSegmentationResult(planeGeometry, slice, timeStep);
slice->DisconnectPipeline();
ImageToContourFilter::Pointer contourExtractor = ImageToContourFilter::New();
contourExtractor->SetInput(slice);
contourExtractor->Update();
mitk::Surface::Pointer contour = contourExtractor->GetOutput();
if (m_3DInterpolationEnabled && contour->GetVtkPolyData()->GetNumberOfPoints() > 0 && image->GetDimension() == 3)
{
unsigned int pos = this->AddContourmarker(positionEvent);
us::ServiceReference<PlanePositionManagerService> serviceRef =
us::GetModuleContext()->GetServiceReference<PlanePositionManagerService>();
PlanePositionManagerService* service = us::GetModuleContext()->GetService(serviceRef);
mitk::SurfaceInterpolationController::GetInstance()->AddNewContour( contour, service->GetPlanePosition(pos));
contour->DisconnectPipeline();
}
}
}
void mitk::SegTool2D::WriteBackSegmentationResult (const PlaneGeometry* planeGeometry, Image* slice, unsigned int timeStep)
{
if(!planeGeometry || !slice) return;
DataNode* workingNode( m_ToolManager->GetWorkingData(0) );
Image* image = dynamic_cast<Image*>(workingNode->GetData());
//Make sure that for reslicing and overwriting the same alogrithm is used. We can specify the mode of the vtk reslicer
vtkSmartPointer<mitkVtkImageOverwrite> reslice = vtkSmartPointer<mitkVtkImageOverwrite>::New();
//Set the slice as 'input'
reslice->SetInputSlice(slice->GetVtkImageData());
//set overwrite mode to true to write back to the image volume
reslice->SetOverwriteMode(true);
reslice->Modified();
mitk::ExtractSliceFilter::Pointer extractor = mitk::ExtractSliceFilter::New(reslice);
extractor->SetInput( image );
extractor->SetTimeStep( timeStep );
extractor->SetWorldGeometry( planeGeometry );
extractor->SetVtkOutputRequest(true);
extractor->SetResliceTransformByGeometry( image->GetGeometry( timeStep ) );
extractor->Modified();
extractor->Update();
//the image was modified within the pipeline, but not marked so
image->Modified();
image->GetVtkImageData()->Modified();
/*============= BEGIN undo feature block ========================*/
//specify the undo operation with the edited slice
- m_doOperation = new DiffSliceOperation(image, extractor->GetVtkOutput(),slice->GetGeometry(), timeStep, const_cast<mitk::PlaneGeometry*>(planeGeometry));
+ m_doOperation = new DiffSliceOperation(image, extractor->GetVtkOutput(),dynamic_cast<SlicedGeometry3D*>(slice->GetGeometry()), timeStep, const_cast<mitk::PlaneGeometry*>(planeGeometry));
//create an operation event for the undo stack
OperationEvent* undoStackItem = new OperationEvent( DiffSliceOperationApplier::GetInstance(), m_doOperation, m_undoOperation, "Segmentation" );
//add it to the undo controller
UndoController::GetCurrentUndoModel()->SetOperationEvent( undoStackItem );
//clear the pointers as the operation are stored in the undocontroller and also deleted from there
m_undoOperation = NULL;
m_doOperation = NULL;
/*============= END undo feature block ========================*/
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void mitk::SegTool2D::SetShowMarkerNodes(bool status)
{
m_ShowMarkerNodes = status;
}
void mitk::SegTool2D::SetEnable3DInterpolation(bool enabled)
{
m_3DInterpolationEnabled = enabled;
}
unsigned int mitk::SegTool2D::AddContourmarker ( const InteractionPositionEvent* positionEvent )
{
- const mitk::Geometry2D* plane = dynamic_cast<const Geometry2D*> (dynamic_cast< const mitk::SlicedGeometry3D*>(
- positionEvent->GetSender()->GetSliceNavigationController()->GetCurrentGeometry3D())->GetGeometry2D(0));
+ const mitk::PlaneGeometry* plane = dynamic_cast<const PlaneGeometry*> (dynamic_cast< const mitk::SlicedGeometry3D*>(
+ positionEvent->GetSender()->GetSliceNavigationController()->GetCurrentGeometry3D())->GetPlaneGeometry(0));
us::ServiceReference<PlanePositionManagerService> serviceRef =
us::GetModuleContext()->GetServiceReference<PlanePositionManagerService>();
PlanePositionManagerService* service = us::GetModuleContext()->GetService(serviceRef);
unsigned int size = service->GetNumberOfPlanePositions();
unsigned int id = service->AddNewPlanePosition(plane, positionEvent->GetSender()->GetSliceNavigationController()->GetSlice()->GetPos());
mitk::PlanarCircle::Pointer contourMarker = mitk::PlanarCircle::New();
mitk::Point2D p1;
plane->Map(plane->GetCenter(), p1);
mitk::Point2D p2 = p1;
p2[0] -= plane->GetSpacing()[0];
p2[1] -= plane->GetSpacing()[1];
contourMarker->PlaceFigure( p1 );
contourMarker->SetCurrentControlPoint( p1 );
- contourMarker->SetGeometry2D( const_cast<Geometry2D*>(plane));
+ contourMarker->SetPlaneGeometry( const_cast<PlaneGeometry*>(plane));
std::stringstream markerStream;
mitk::DataNode* workingNode (m_ToolManager->GetWorkingData(0));
markerStream << m_Contourmarkername ;
markerStream << " ";
markerStream << id+1;
DataNode::Pointer rotatedContourNode = DataNode::New();
rotatedContourNode->SetData(contourMarker);
rotatedContourNode->SetProperty( "name", StringProperty::New(markerStream.str()) );
rotatedContourNode->SetProperty( "isContourMarker", BoolProperty::New(true));
rotatedContourNode->SetBoolProperty( "PlanarFigureInitializedWindow", true, positionEvent->GetSender() );
rotatedContourNode->SetProperty( "includeInBoundingBox", BoolProperty::New(false));
rotatedContourNode->SetProperty( "helper object", mitk::BoolProperty::New(!m_ShowMarkerNodes));
rotatedContourNode->SetProperty( "planarfigure.drawcontrolpoints", BoolProperty::New(false));
rotatedContourNode->SetProperty( "planarfigure.drawname", BoolProperty::New(false));
rotatedContourNode->SetProperty( "planarfigure.drawoutline", BoolProperty::New(false));
rotatedContourNode->SetProperty( "planarfigure.drawshadow", BoolProperty::New(false));
if (plane)
{
if ( id == size )
{
m_ToolManager->GetDataStorage()->Add(rotatedContourNode, workingNode);
}
else
{
mitk::NodePredicateProperty::Pointer isMarker = mitk::NodePredicateProperty::New("isContourMarker", mitk::BoolProperty::New(true));
mitk::DataStorage::SetOfObjects::ConstPointer markers = m_ToolManager->GetDataStorage()->GetDerivations(workingNode,isMarker);
for ( mitk::DataStorage::SetOfObjects::const_iterator iter = markers->begin();
iter != markers->end();
++iter)
{
std::string nodeName = (*iter)->GetName();
unsigned int t = nodeName.find_last_of(" ");
unsigned int markerId = atof(nodeName.substr(t+1).c_str())-1;
if(id == markerId)
{
return id;
}
}
m_ToolManager->GetDataStorage()->Add(rotatedContourNode, workingNode);
}
}
return id;
}
void mitk::SegTool2D::InteractiveSegmentationBugMessage( const std::string& message )
{
MITK_ERROR << "********************************************************************************" << std::endl
<< " " << message << std::endl
<< "********************************************************************************" << std::endl
<< " " << std::endl
<< " If your image is rotated or the 2D views don't really contain the patient image, try to press the button next to the image selection. " << std::endl
<< " " << std::endl
<< " Please file a BUG REPORT: " << std::endl
<< " http://bugs.mitk.org" << std::endl
<< " Contain the following information:" << std::endl
<< " - What image were you working on?" << std::endl
<< " - Which region of the image?" << std::endl
<< " - Which tool did you use?" << std::endl
<< " - What did you do?" << std::endl
<< " - What happened (not)? What did you expect?" << std::endl;
}
diff --git a/Modules/Segmentation/Interactions/mitkSetRegionTool.cpp b/Modules/Segmentation/Interactions/mitkSetRegionTool.cpp
index adb20b9dba..9a83a7d1f1 100644
--- a/Modules/Segmentation/Interactions/mitkSetRegionTool.cpp
+++ b/Modules/Segmentation/Interactions/mitkSetRegionTool.cpp
@@ -1,330 +1,330 @@
/*===================================================================
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 "mitkSetRegionTool.h"
#include "mitkToolManager.h"
#include "mitkOverwriteSliceImageFilter.h"
#include "ipSegmentation.h"
#include "mitkBaseRenderer.h"
#include "mitkImageDataItem.h"
#include "mitkLegacyAdaptors.h"
#include "mitkOverwriteDirectedPlaneImageFilter.h"
mitk::SetRegionTool::SetRegionTool(int paintingPixelValue)
:FeedbackContourTool("PressMoveReleaseWithCTRLInversion"),
m_PaintingPixelValue(paintingPixelValue),
m_FillContour(false),
m_StatusFillWholeSlice(false)
{
}
mitk::SetRegionTool::~SetRegionTool()
{
}
void mitk::SetRegionTool::ConnectActionsAndFunctions()
{
CONNECT_FUNCTION( "PrimaryButtonPressed", OnMousePressed);
CONNECT_FUNCTION( "Release", OnMouseReleased);
CONNECT_FUNCTION( "InvertLogic", OnInvertLogic);
}
void mitk::SetRegionTool::Activated()
{
Superclass::Activated();
}
void mitk::SetRegionTool::Deactivated()
{
Superclass::Deactivated();
}
bool mitk::SetRegionTool::OnMousePressed ( StateMachineAction*, InteractionEvent* interactionEvent )
{
mitk::InteractionPositionEvent* positionEvent = dynamic_cast<mitk::InteractionPositionEvent*>( interactionEvent );
//const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent());
if (!positionEvent) return false;
m_LastEventSender = positionEvent->GetSender();
m_LastEventSlice = m_LastEventSender->GetSlice();
int timeStep = positionEvent->GetSender()->GetTimeStep();
if ( FeedbackContourTool::CanHandleEvent(interactionEvent) < 1.0 ) return false;
// 1. Get the working image
Image::Pointer workingSlice = FeedbackContourTool::GetAffectedWorkingSlice( positionEvent );
if ( workingSlice.IsNull() ) return false; // can't do anything without the segmentation
// if click was outside the image, don't continue
- const Geometry3D* sliceGeometry = workingSlice->GetGeometry();
+ const BaseGeometry* sliceGeometry = workingSlice->GetGeometry();
itk::Index<2> projectedPointIn2D;
sliceGeometry->WorldToIndex( positionEvent->GetPositionInWorld(), projectedPointIn2D );
if ( !sliceGeometry->IsIndexInside( projectedPointIn2D ) )
{
MITK_ERROR << "point apparently not inside segmentation slice" << std::endl;
return false; // can't use that as a seed point
}
// Convert to ipMITKSegmentationTYPE (because ipMITKSegmentationGetContour8N relys on that data type)
itk::Image< ipMITKSegmentationTYPE, 2 >::Pointer correctPixelTypeImage;
CastToItkImage( workingSlice, correctPixelTypeImage );
assert (correctPixelTypeImage.IsNotNull() );
// possible bug in CastToItkImage ?
// direction maxtrix is wrong/broken/not working after CastToItkImage, leading to a failed assertion in
// mitk/Core/DataStructures/mitkSlicedGeometry3D.cpp, 479:
// virtual void mitk::SlicedGeometry3D::SetSpacing(const mitk::Vector3D&): Assertion `aSpacing[0]>0 && aSpacing[1]>0 && aSpacing[2]>0' failed
// solution here: we overwrite it with an unity matrix
itk::Image< ipMITKSegmentationTYPE, 2 >::DirectionType imageDirection;
imageDirection.SetIdentity();
correctPixelTypeImage->SetDirection(imageDirection);
Image::Pointer temporarySlice = Image::New();
// temporarySlice = ImportItkImage( correctPixelTypeImage );
CastToMitkImage( correctPixelTypeImage, temporarySlice );
// check index positions
mitkIpPicDescriptor* originalPicSlice = mitkIpPicNew();
CastToIpPicDescriptor( temporarySlice, originalPicSlice );
int m_SeedPointMemoryOffset = projectedPointIn2D[1] * originalPicSlice->n[0] + projectedPointIn2D[0];
if ( m_SeedPointMemoryOffset >= static_cast<int>( originalPicSlice->n[0] * originalPicSlice->n[1] ) ||
m_SeedPointMemoryOffset < 0 )
{
MITK_ERROR << "Memory offset calculation if mitk::SetRegionTool has some serious flaw! Aborting.." << std::endl;
return false;
}
// 2. Determine the contour that surronds the selected "piece of the image"
// find a contour seed point
unsigned int oneContourOffset = static_cast<unsigned int>( m_SeedPointMemoryOffset ); // safe because of earlier check if m_SeedPointMemoryOffset < 0
/**
* The logic of finding a starting point for the contour is the following:
*
* - If the initial seed point is 0, we are either inside a hole or outside of every segmentation.
* We move to the right until we hit a 1, which must be part of a contour.
*
* - If the initial seed point is 1, then ...
* we now do the same (running to the right) until we hit a 1
*
* In both cases the found contour point is used to extract a contour and
* then a test is applied to find out if the initial seed point is contained
* in the contour. If this is the case, filling should be applied, otherwise
* nothing is done.
*/
unsigned int size = originalPicSlice->n[0] * originalPicSlice->n[1];
/*
unsigned int rowSize = originalPicSlice->n[0];
*/
ipMITKSegmentationTYPE* data = static_cast<ipMITKSegmentationTYPE*>(originalPicSlice->data);
if ( data[oneContourOffset] == 0 ) // initial seed 0
{
for ( ; oneContourOffset < size; ++oneContourOffset )
{
if ( data[oneContourOffset] > 0 ) break;
}
}
else if ( data[oneContourOffset] == 1 ) // initial seed 1
{
unsigned int lastValidPixel = size-1; // initialization, will be changed lateron
bool inSeg = true; // inside segmentation?
for ( ; oneContourOffset < size; ++oneContourOffset )
{
if ( ( data[oneContourOffset] == 0 ) && inSeg ) // pixel 0 and inside-flag set: this happens at the first pixel outside a filled region
{
inSeg = false;
lastValidPixel = oneContourOffset - 1; // store the last pixel position inside a filled region
break;
}
else // pixel 1, inside-flag doesn't matter: this happens while we are inside a filled region
{
inSeg = true; // first iteration lands here
}
}
oneContourOffset = lastValidPixel;
}
else
{
MITK_ERROR << "Fill/Erase was never intended to work with other than binary images." << std::endl;
m_FillContour = false;
return false;
}
if (oneContourOffset == size) // nothing found until end of slice
{
m_FillContour = false;
return false;
}
int numberOfContourPoints( 0 );
int newBufferSize( 0 );
//MITK_INFO << "getting contour from offset " << oneContourOffset << " ("<<oneContourOffset%originalPicSlice->n[0]<<","<<oneContourOffset/originalPicSlice->n[0]<<")"<<std::endl;
float* contourPoints = ipMITKSegmentationGetContour8N( originalPicSlice, oneContourOffset, numberOfContourPoints, newBufferSize ); // memory allocated with malloc
//MITK_INFO << "contourPoints " << contourPoints << " (N="<<numberOfContourPoints<<")"<<std::endl;
assert(contourPoints == NULL || numberOfContourPoints > 0);
bool cursorInsideContour = ipMITKSegmentationIsInsideContour( contourPoints, numberOfContourPoints, projectedPointIn2D[0], projectedPointIn2D[1]);
// decide if contour should be filled or not
m_FillContour = cursorInsideContour;
if (m_FillContour)
{
// copy point from float* to mitk::Contour
ContourModel::Pointer contourInImageIndexCoordinates = ContourModel::New();
contourInImageIndexCoordinates->Expand(timeStep + 1);
contourInImageIndexCoordinates->SetClosed(true, timeStep);
Point3D newPoint;
for (int index = 0; index < numberOfContourPoints; ++index)
{
newPoint[0] = contourPoints[ 2 * index + 0 ] - 0.5;
newPoint[1] = contourPoints[ 2 * index + 1] - 0.5;
newPoint[2] = 0;
contourInImageIndexCoordinates->AddVertex(newPoint, timeStep);
}
m_SegmentationContourInWorldCoordinates = FeedbackContourTool::BackProjectContourFrom2DSlice( workingSlice->GetGeometry(), contourInImageIndexCoordinates, true ); // true, correct the result from ipMITKSegmentationGetContour8N
// 3. Show the contour
FeedbackContourTool::SetFeedbackContour( *m_SegmentationContourInWorldCoordinates );
FeedbackContourTool::SetFeedbackContourVisible(true);
mitk::RenderingManager::GetInstance()->RequestUpdate(positionEvent->GetSender()->GetRenderWindow());
}
// always generate a second contour, containing the whole image (used when CTRL is pressed)
{
// copy point from float* to mitk::Contour
ContourModel::Pointer contourInImageIndexCoordinates = ContourModel::New();
contourInImageIndexCoordinates->Expand(timeStep + 1);
contourInImageIndexCoordinates->SetClosed(true, timeStep);
Point3D newPoint;
newPoint[0] = 0; newPoint[1] = 0; newPoint[2] = 0.0;
contourInImageIndexCoordinates->AddVertex( newPoint, timeStep );
newPoint[0] = originalPicSlice->n[0]; newPoint[1] = 0; newPoint[2] = 0.0;
contourInImageIndexCoordinates->AddVertex( newPoint, timeStep );
newPoint[0] = originalPicSlice->n[0]; newPoint[1] = originalPicSlice->n[1]; newPoint[2] = 0.0;
contourInImageIndexCoordinates->AddVertex( newPoint, timeStep );
newPoint[0] = 0; newPoint[1] = originalPicSlice->n[1]; newPoint[2] = 0.0;
contourInImageIndexCoordinates->AddVertex( newPoint, timeStep );
m_WholeImageContourInWorldCoordinates = FeedbackContourTool::BackProjectContourFrom2DSlice( workingSlice->GetGeometry(), contourInImageIndexCoordinates, true ); // true, correct the result from ipMITKSegmentationGetContour8N
// 3. Show the contour
FeedbackContourTool::SetFeedbackContour( *m_SegmentationContourInWorldCoordinates );
FeedbackContourTool::SetFeedbackContourVisible(true);
mitk::RenderingManager::GetInstance()->RequestUpdate(positionEvent->GetSender()->GetRenderWindow());
}
free(contourPoints);
return true;
}
bool mitk::SetRegionTool::OnMouseReleased( StateMachineAction*, InteractionEvent* interactionEvent )
{
// 1. Hide the feedback contour, find out which slice the user clicked, find out which slice of the toolmanager's working image corresponds to that
FeedbackContourTool::SetFeedbackContourVisible(false);
mitk::InteractionPositionEvent* positionEvent = dynamic_cast<mitk::InteractionPositionEvent*>( interactionEvent );
//const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent());
if (!positionEvent) return false;
assert( positionEvent->GetSender()->GetRenderWindow() );
mitk::RenderingManager::GetInstance()->RequestUpdate(positionEvent->GetSender()->GetRenderWindow());
int timeStep = positionEvent->GetSender()->GetTimeStep();
if (!m_FillContour && !m_StatusFillWholeSlice) return true;
if ( FeedbackContourTool::CanHandleEvent(interactionEvent) < 1.0 ) return false;
DataNode* workingNode( m_ToolManager->GetWorkingData(0) );
if (!workingNode) return false;
Image* image = dynamic_cast<Image*>(workingNode->GetData());
- const PlaneGeometry* planeGeometry( dynamic_cast<const PlaneGeometry*> (positionEvent->GetSender()->GetCurrentWorldGeometry2D() ) );
+ const PlaneGeometry* planeGeometry( dynamic_cast<const PlaneGeometry*> (positionEvent->GetSender()->GetCurrentWorldPlaneGeometry() ) );
if ( !image || !planeGeometry ) return false;
Image::Pointer slice = FeedbackContourTool::GetAffectedImageSliceAs2DImage( positionEvent, image );
if ( slice.IsNull() )
{
MITK_ERROR << "Unable to extract slice." << std::endl;
return false;
}
ContourModel* feedbackContour( FeedbackContourTool::GetFeedbackContour() );
ContourModel::Pointer projectedContour = FeedbackContourTool::ProjectContourTo2DSlice( slice, feedbackContour, false, false ); // false: don't add 0.5 (done by FillContourInSlice)
// false: don't constrain the contour to the image's inside
if (projectedContour.IsNull()) return false;
FeedbackContourTool::FillContourInSlice( projectedContour, timeStep, slice, m_PaintingPixelValue );
this->WriteBackSegmentationResult(positionEvent, slice);
m_WholeImageContourInWorldCoordinates = NULL;
m_SegmentationContourInWorldCoordinates = NULL;
return true;
}
/**
Called when the CTRL key is pressed. Will change the painting pixel value from 0 to 1 or from 1 to 0.
*/
bool mitk::SetRegionTool::OnInvertLogic( StateMachineAction*, InteractionEvent* interactionEvent )
{
if ( FeedbackContourTool::CanHandleEvent(interactionEvent) < 1.0 ) return false;
mitk::InteractionPositionEvent* positionEvent = dynamic_cast<mitk::InteractionPositionEvent*>( interactionEvent );
//const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent());
if (!positionEvent) return false;
if (m_StatusFillWholeSlice)
{
// use contour extracted from image data
if (m_SegmentationContourInWorldCoordinates.IsNotNull())
FeedbackContourTool::SetFeedbackContour( *m_SegmentationContourInWorldCoordinates );
mitk::RenderingManager::GetInstance()->RequestUpdate(positionEvent->GetSender()->GetRenderWindow());
}
else
{
// use some artificial contour
if (m_WholeImageContourInWorldCoordinates.IsNotNull())
FeedbackContourTool::SetFeedbackContour( *m_WholeImageContourInWorldCoordinates );
mitk::RenderingManager::GetInstance()->RequestUpdate(positionEvent->GetSender()->GetRenderWindow());
}
m_StatusFillWholeSlice = !m_StatusFillWholeSlice;
return true;
}
diff --git a/Modules/SegmentationUI/Qmitk/QmitkAdaptiveRegionGrowingToolGUI.cpp b/Modules/SegmentationUI/Qmitk/QmitkAdaptiveRegionGrowingToolGUI.cpp
index 93c4af6042..cb50c0513c 100644
--- a/Modules/SegmentationUI/Qmitk/QmitkAdaptiveRegionGrowingToolGUI.cpp
+++ b/Modules/SegmentationUI/Qmitk/QmitkAdaptiveRegionGrowingToolGUI.cpp
@@ -1,848 +1,848 @@
/*===================================================================
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 "QmitkAdaptiveRegionGrowingToolGUI.h"
#include "QmitkStdMultiWidget.h"
#include <qmessagebox.h>
#include "mitkNodePredicateDataType.h"
#include "mitkGlobalInteraction.h"
#include "mitkPointSetInteractor.h"
#include "mitkProperties.h"
#include "mitkITKImageImport.h"
#include "mitkImageAccessByItk.h"
#include "mitkTransferFunctionProperty.h"
#include "mitkImageTimeSelector.h"
#include "mitkImageStatisticsHolder.h"
#include <itkConnectedAdaptiveThresholdImageFilter.h>
#include <itkMinimumMaximumImageCalculator.h>
#include <itkBinaryThresholdImageFilter.h>
#include <itkImageIterator.h>
#include "itkOrImageFilter.h"
#include "mitkImageCast.h"
#include "QmitkConfirmSegmentationDialog.h"
#include "mitkPixelTypeMultiplex.h"
#include "mitkImagePixelReadAccessor.h"
MITK_TOOL_GUI_MACRO( , QmitkAdaptiveRegionGrowingToolGUI, "")
QmitkAdaptiveRegionGrowingToolGUI::QmitkAdaptiveRegionGrowingToolGUI(QWidget* parent) :
QmitkToolGUI(), m_MultiWidget(NULL), m_UseVolumeRendering(false), m_UpdateSuggestedThreshold(true), m_SuggestedThValue(0.0), m_DataStorage(NULL)
{
this->setParent(parent);
m_Controls.setupUi(this);
m_Controls.m_ThresholdSlider->setDecimals(1);
m_Controls.m_ThresholdSlider->setSpinBoxAlignment(Qt::AlignVCenter);
m_Controls.m_PreviewSlider->setEnabled(false);
m_Controls.m_PreviewSlider->setSingleStep(0.5);
//Not yet available
//m_Controls.m_PreviewSlider->InvertedAppearance(true);
this->CreateConnections();
this->SetDataNodeNames("labeledRGSegmentation","RGResult","RGFeedbackSurface");
connect( this, SIGNAL(NewToolAssociated(mitk::Tool*)), this, SLOT(OnNewToolAssociated(mitk::Tool*)) );
}
QmitkAdaptiveRegionGrowingToolGUI::~QmitkAdaptiveRegionGrowingToolGUI()
{
//Removing the observer of the PointSet node
if (m_RegionGrow3DTool->GetPointSetNode().IsNotNull())
{
m_RegionGrow3DTool->GetPointSetNode()->GetData()->RemoveObserver(m_PointSetAddObserverTag);
}
this->RemoveHelperNodes();
}
void QmitkAdaptiveRegionGrowingToolGUI::OnNewToolAssociated(mitk::Tool* tool)
{
m_RegionGrow3DTool = dynamic_cast<mitk::AdaptiveRegionGrowingTool*> (tool);
if(m_RegionGrow3DTool.IsNotNull())
{
SetInputImageNode( this->m_RegionGrow3DTool->GetReferenceData() );
this->m_DataStorage = this->m_RegionGrow3DTool->GetDataStorage();
this->EnableControls(true);
//Watch for point added or modified
itk::SimpleMemberCommand<QmitkAdaptiveRegionGrowingToolGUI>::Pointer pointAddedCommand = itk::SimpleMemberCommand<QmitkAdaptiveRegionGrowingToolGUI>::New();
pointAddedCommand->SetCallbackFunction(this, &QmitkAdaptiveRegionGrowingToolGUI::OnPointAdded);
m_PointSetAddObserverTag = m_RegionGrow3DTool->GetPointSetNode()->GetData()->AddObserver( mitk::PointSetAddEvent(), pointAddedCommand);
}
else
{
this->EnableControls(false);
}
}
void QmitkAdaptiveRegionGrowingToolGUI::RemoveHelperNodes()
{
mitk::DataNode::Pointer imageNode = m_DataStorage->GetNamedNode( m_NAMEFORLABLEDSEGMENTATIONIMAGE);
if( imageNode.IsNotNull() )
{
m_DataStorage->Remove(imageNode);
}
}
void QmitkAdaptiveRegionGrowingToolGUI::CreateConnections()
{
//Connecting GUI components
connect( (QObject*) (m_Controls.m_pbRunSegmentation), SIGNAL(clicked()), this, SLOT(RunSegmentation()));
connect( m_Controls.m_PreviewSlider, SIGNAL(valueChanged(double)), this, SLOT(ChangeLevelWindow(double)));
connect( (QObject*) (m_Controls.m_pbConfirmSegementation), SIGNAL(clicked()), this, SLOT(ConfirmSegmentation()));
connect( (QObject*) (m_Controls.m_cbVolumeRendering), SIGNAL(toggled(bool)), this, SLOT(UseVolumeRendering(bool) ));
connect( m_Controls.m_ThresholdSlider, SIGNAL(maximumValueChanged(double)), this, SLOT(SetUpperThresholdValue(double)));
connect( m_Controls.m_ThresholdSlider, SIGNAL(minimumValueChanged(double)), this, SLOT(SetLowerThresholdValue(double)));
}
void QmitkAdaptiveRegionGrowingToolGUI::SetDataNodeNames(std::string labledSegmentation, std::string binaryImage, std::string surface)
{
m_NAMEFORLABLEDSEGMENTATIONIMAGE = labledSegmentation;
m_NAMEFORBINARYIMAGE = binaryImage;
m_NAMEFORSURFACE = surface;
}
void QmitkAdaptiveRegionGrowingToolGUI::SetDataStorage(mitk::DataStorage* dataStorage)
{
m_DataStorage = dataStorage;
}
void QmitkAdaptiveRegionGrowingToolGUI::SetMultiWidget(QmitkStdMultiWidget* multiWidget)
{
m_MultiWidget = multiWidget;
}
void QmitkAdaptiveRegionGrowingToolGUI::SetInputImageNode(mitk::DataNode* node)
{
m_InputImageNode = node;
mitk::Image* inputImage = dynamic_cast<mitk::Image*>(m_InputImageNode->GetData());
if (inputImage)
{
mitk::ScalarType max = inputImage->GetStatistics()->GetScalarValueMax();
mitk::ScalarType min = inputImage->GetStatistics()->GetScalarValueMin();
m_Controls.m_ThresholdSlider->setMaximum(max);
m_Controls.m_ThresholdSlider->setMinimum(min);
// Just for initialization
m_Controls.m_ThresholdSlider->setMaximumValue(max);
m_Controls.m_ThresholdSlider->setMinimumValue(min);
}
}
template <typename TPixel>
static void AccessPixel(mitk::PixelType ptype, const mitk::Image::Pointer im, mitk::Point3D p, int & val)
{
mitk::ImagePixelReadAccessor<TPixel,3> access(im);
val = access.GetPixelByWorldCoordinates(p);
}
void QmitkAdaptiveRegionGrowingToolGUI::OnPointAdded()
{
if (m_RegionGrow3DTool.IsNull())
return;
mitk::DataNode* node = m_RegionGrow3DTool->GetPointSetNode();
if (node != NULL)
{
mitk::PointSet::Pointer pointSet = dynamic_cast<mitk::PointSet*>(node->GetData());
if (pointSet.IsNull())
{
QMessageBox::critical(NULL, "QmitkAdaptiveRegionGrowingToolGUI", "PointSetNode does not contain a pointset");
return;
}
m_Controls.m_lblSetSeedpoint->setText("");
mitk::Image* image = dynamic_cast<mitk::Image*>(m_InputImageNode->GetData());
mitk::Point3D seedPoint = pointSet->GetPointSet(mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget1") )->GetTimeStep())->GetPoints()->ElementAt(0);
mitkPixelTypeMultiplex3(AccessPixel,image->GetChannelDescriptor().GetPixelType(),image,seedPoint,m_SeedpointValue);
/* In this case the seedpoint is placed e.g. in the lung or bronchialtree
* The lowerFactor sets the windowsize depending on the regiongrowing direction
*/
m_CurrentRGDirectionIsUpwards = true;
if (m_SeedpointValue < -500)
{
m_CurrentRGDirectionIsUpwards = false;
}
// Initializing the region by the area around the seedpoint
m_SeedPointValueMean = 0;
mitk::Index3D currentIndex, runningIndex;
mitk::ScalarType pixelValues[125];
unsigned int pos (0);
image->GetGeometry(0)->WorldToIndex(seedPoint, currentIndex);
runningIndex = currentIndex;
for(int i = runningIndex[0]-2; i <= runningIndex[0]+2; i++)
{
for(int j = runningIndex[1]-2; j <= runningIndex[1]+2; j++)
{
for(int k = runningIndex[2]-2; k <= runningIndex[2]+2; k++)
{
currentIndex[0] = i;
currentIndex[1] = j;
currentIndex[2] = k;
if(image->GetGeometry()->IsIndexInside(currentIndex))
{
pixelValues[pos] = image->GetPixelValueByIndex(currentIndex);
pos++;
}
else
{
pixelValues[pos] = -10000000;
pos++;
}
}
}
}
//Now calculation mean of the pixelValues
unsigned int numberOfValues(0);
for (unsigned int i = 0; i < 125; i++)
{
if(pixelValues[i] > -10000000)
{
m_SeedPointValueMean += pixelValues[i];
numberOfValues++;
}
}
m_SeedPointValueMean = m_SeedPointValueMean/numberOfValues;
/*
* Here the upper- and lower threshold is calculated:
* The windowSize is 20% of the maximum range of the intensity values existing in the current image
* If the RG direction is upwards the lower TH is meanSeedValue-0.15*windowSize and upper TH is meanSeedValue+0.85*windowsSize
* if the RG direction is downwards the lower TH is meanSeedValue-0.85*windowSize and upper TH is meanSeedValue+0.15*windowsSize
*/
mitk::ScalarType min = image->GetStatistics()->GetScalarValueMin();
mitk::ScalarType max = image->GetStatistics()->GetScalarValueMax();
mitk::ScalarType windowSize = max - min;
windowSize = 0.15*windowSize;
if (m_CurrentRGDirectionIsUpwards)
{
m_LOWERTHRESHOLD = m_SeedPointValueMean;
if (m_SeedpointValue < m_SeedPointValueMean)
m_LOWERTHRESHOLD = m_SeedpointValue;
m_UPPERTHRESHOLD = m_SeedpointValue + windowSize;
if (m_UPPERTHRESHOLD > max)
m_UPPERTHRESHOLD = max;
m_Controls.m_ThresholdSlider->setMaximumValue(m_UPPERTHRESHOLD);
m_Controls.m_ThresholdSlider->setMinimumValue(m_LOWERTHRESHOLD);
}
else
{
m_UPPERTHRESHOLD = m_SeedPointValueMean;
if (m_SeedpointValue > m_SeedPointValueMean)
m_UPPERTHRESHOLD = m_SeedpointValue;
m_LOWERTHRESHOLD = m_SeedpointValue - windowSize;
if (m_LOWERTHRESHOLD < min)
m_LOWERTHRESHOLD = min;
m_Controls.m_ThresholdSlider->setMinimumValue(m_LOWERTHRESHOLD);
m_Controls.m_ThresholdSlider->setMaximumValue(m_UPPERTHRESHOLD);
}
}
}
void QmitkAdaptiveRegionGrowingToolGUI::RunSegmentation()
{
if (m_InputImageNode.IsNull())
{
QMessageBox::information( NULL, "Adaptive Region Growing functionality", "Please specify the image in Datamanager!");
return;
}
mitk::DataNode::Pointer node = m_RegionGrow3DTool->GetPointSetNode();
if (node.IsNull())
{
QMessageBox::information( NULL, "Adaptive Region Growing functionality", "Please insert a seed point inside the image.\n\nFirst press the \"Define Seed Point\" button,\nthen click left mouse button inside the image.");
return;
}
//safety if no pointSet or pointSet empty
mitk::PointSet::Pointer seedPointSet = dynamic_cast<mitk::PointSet*> (node->GetData());
if (seedPointSet.IsNull())
{
m_Controls.m_pbRunSegmentation->setEnabled(true);
QMessageBox::information( NULL, "Adaptive Region Growing functionality", "The seed point is empty! Please choose a new seed point.");
return;
}
int timeStep = mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget1") )->GetTimeStep();
if (!(seedPointSet->GetSize(timeStep)))
{
m_Controls.m_pbRunSegmentation->setEnabled(true);
QMessageBox::information( NULL, "Adaptive Region Growing functionality", "The seed point is empty! Please choose a new seed point.");
return;
}
QApplication::setOverrideCursor( QCursor(Qt::WaitCursor) );
mitk::PointSet::PointType seedPoint = seedPointSet->GetPointSet(timeStep)->GetPoints()->Begin().Value();
mitk::Image::Pointer orgImage = dynamic_cast<mitk::Image*> (m_InputImageNode->GetData());
if (orgImage.IsNotNull())
{
if (orgImage->GetDimension() == 4)
{
mitk::ImageTimeSelector::Pointer timeSelector = mitk::ImageTimeSelector::New();
timeSelector->SetInput(orgImage);
timeSelector->SetTimeNr( timeStep );
timeSelector->UpdateLargestPossibleRegion();
mitk::Image* timedImage = timeSelector->GetOutput();
AccessByItk_2( timedImage , StartRegionGrowing, timedImage->GetGeometry(), seedPoint);
}
else if (orgImage->GetDimension() == 3)
{
//QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); //set the cursor to waiting
AccessByItk_2(orgImage, StartRegionGrowing, orgImage->GetGeometry(), seedPoint);
//QApplication::restoreOverrideCursor();//reset cursor
}
else
{
QApplication::restoreOverrideCursor();//reset cursor
QMessageBox::information( NULL, "Adaptive Region Growing functionality", "Only images of dimension 3 or 4 can be processed!");
return;
}
}
EnableControls(true); // Segmentation ran successfully, so enable all controls.
node->SetVisibility(true);
QApplication::restoreOverrideCursor();//reset cursor
}
template<typename TPixel, unsigned int VImageDimension>
-void QmitkAdaptiveRegionGrowingToolGUI::StartRegionGrowing(itk::Image<TPixel, VImageDimension>* itkImage, mitk::Geometry3D* imageGeometry, mitk::PointSet::PointType seedPoint)
+void QmitkAdaptiveRegionGrowingToolGUI::StartRegionGrowing(itk::Image<TPixel, VImageDimension>* itkImage, mitk::BaseGeometry* imageGeometry, mitk::PointSet::PointType seedPoint)
{
typedef itk::Image<TPixel, VImageDimension> InputImageType;
typedef typename InputImageType::IndexType IndexType;
typedef itk::ConnectedAdaptiveThresholdImageFilter<InputImageType, InputImageType> RegionGrowingFilterType;
typename RegionGrowingFilterType::Pointer regionGrower = RegionGrowingFilterType::New();
typedef itk::MinimumMaximumImageCalculator<InputImageType> MinMaxValueFilterType;
if ( !imageGeometry->IsInside(seedPoint) )
{
QApplication::restoreOverrideCursor();//reset cursor to be able to click ok with the regular mouse cursor
QMessageBox::information( NULL, "Segmentation functionality", "The seed point is outside of the image! Please choose a position inside the image!");
return;
}
IndexType seedIndex;
imageGeometry->WorldToIndex( seedPoint, seedIndex);// convert world coordinates to image indices
if (m_SeedpointValue>m_UPPERTHRESHOLD || m_SeedpointValue<m_LOWERTHRESHOLD)
{
QApplication::restoreOverrideCursor();//reset cursor to be able to click ok with the regular mouse cursor
QMessageBox::information( NULL, "Segmentation functionality", "The seed point is outside the defined thresholds! Please set a new seed point or adjust the thresholds.");
MITK_INFO << "Mean: " <<m_SeedPointValueMean;
return;
}
//Setting the direction of the regiongrowing. For dark structures e.g. the lung the regiongrowing
//is performed starting at the upper value going to the lower one
regionGrower->SetGrowingDirectionIsUpwards( m_CurrentRGDirectionIsUpwards );
regionGrower->SetInput( itkImage );
regionGrower->AddSeed( seedIndex );
//In some cases we have to subtract 1 for the lower threshold and add 1 to the upper.
//Otherwise no region growing is done. Maybe a bug in the ConnectiveAdaptiveThresholdFilter
regionGrower->SetLower( m_LOWERTHRESHOLD-1 );
regionGrower->SetUpper( m_UPPERTHRESHOLD+1);
try
{
regionGrower->Update();
}
catch(itk::ExceptionObject &exc)
{
QMessageBox errorInfo;
errorInfo.setWindowTitle("Adaptive RG Segmentation Functionality");
errorInfo.setIcon(QMessageBox::Critical);
errorInfo.setText("An error occurred during region growing!");
errorInfo.setDetailedText(exc.what());
errorInfo.exec();
return; // can't work
}
catch( ... )
{
QMessageBox::critical( NULL, "Adaptive RG Segmentation Functionality", "An error occurred during region growing!");
return;
}
mitk::Image::Pointer resultImage = mitk::ImportItkImage(regionGrower->GetOutput())->Clone();
//initialize slider
m_Controls.m_PreviewSlider->setMinimum(m_LOWERTHRESHOLD);
mitk::ScalarType max = m_LOWERTHRESHOLD+resultImage->GetStatistics()->GetScalarValueMax();
if (max < m_UPPERTHRESHOLD)
m_Controls.m_PreviewSlider->setMaximum(max);
else
m_Controls.m_PreviewSlider->setMaximum(m_UPPERTHRESHOLD);
this->m_DetectedLeakagePoint = regionGrower->GetLeakagePoint();
if(m_CurrentRGDirectionIsUpwards)
{
m_Controls.m_PreviewSlider->setValue(m_SeedPointValueMean-1);
}
else
{
m_Controls.m_PreviewSlider->setValue(m_SeedPointValueMean+1);
}
this->m_SliderInitialized = true;
//create new node and then delete the old one if there is one
mitk::DataNode::Pointer newNode = mitk::DataNode::New();
newNode->SetData( resultImage );
// set some properties
newNode->SetProperty("name", mitk::StringProperty::New(m_NAMEFORLABLEDSEGMENTATIONIMAGE));
newNode->SetProperty("helper object", mitk::BoolProperty::New(true));
newNode->SetProperty("color", mitk::ColorProperty::New(0.0,1.0,0.0));
newNode->SetProperty("layer", mitk::IntProperty::New(1));
newNode->SetProperty("opacity", mitk::FloatProperty::New(0.7));
//delete the old image, if there was one:
mitk::DataNode::Pointer binaryNode = m_DataStorage->GetNamedNode(m_NAMEFORLABLEDSEGMENTATIONIMAGE);
m_DataStorage->Remove(binaryNode);
// now add result to data tree
m_DataStorage->Add( newNode, m_InputImageNode );
this->InitializeLevelWindow();
if(m_UseVolumeRendering)
this->EnableVolumeRendering(true);
m_UpdateSuggestedThreshold = true;// reset first stored threshold value
//Setting progress to finished
mitk::ProgressBar::GetInstance()->Progress(357);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkAdaptiveRegionGrowingToolGUI::InitializeLevelWindow()
{
//get the preview from the datatree
mitk::DataNode::Pointer newNode = m_DataStorage->GetNamedNode( m_NAMEFORLABLEDSEGMENTATIONIMAGE);
mitk::LevelWindow tempLevelWindow;
newNode->GetLevelWindow(tempLevelWindow, NULL, "levelwindow");
mitk::ScalarType* level = new mitk::ScalarType(0.0);
mitk::ScalarType* window = new mitk::ScalarType(1.0);
int upper;
if (m_CurrentRGDirectionIsUpwards)
{
upper = m_UPPERTHRESHOLD - m_SeedpointValue;
}
else
{
upper = m_SeedpointValue - m_LOWERTHRESHOLD;
}
tempLevelWindow.SetRangeMinMax(mitk::ScalarType(0), mitk::ScalarType(upper));
//get the suggested threshold from the detected leakage-point and adjust the slider
if (m_CurrentRGDirectionIsUpwards)
{
this->m_Controls.m_PreviewSlider->setValue(m_SeedpointValue);
*level = m_UPPERTHRESHOLD - (m_SeedpointValue) + 0.5;
}
else
{
this->m_Controls.m_PreviewSlider->setValue(m_SeedpointValue);
*level = (m_SeedpointValue) - m_LOWERTHRESHOLD + 0.5;
}
tempLevelWindow.SetLevelWindow(*level, *window);
newNode->SetLevelWindow(tempLevelWindow, NULL, "levelwindow");
//update the widgets
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
m_SliderInitialized = true;
//inquiry need to fix bug#1828
static int lastSliderPosition = 0;
if ((this->m_SeedpointValue + this->m_DetectedLeakagePoint - 1) == lastSliderPosition)
{
this->ChangeLevelWindow(lastSliderPosition);
}
lastSliderPosition = this->m_SeedpointValue + this->m_DetectedLeakagePoint-1;
if(m_MultiWidget)
{
this->m_MultiWidget->levelWindowWidget->GetManager()->SetAutoTopMostImage(false);
this->m_MultiWidget->levelWindowWidget->GetManager()->SetLevelWindowProperty(static_cast<mitk::LevelWindowProperty*>(newNode->GetProperty("levelwindow")));
}
if (m_UseVolumeRendering)
this->UpdateVolumeRenderingThreshold((int) (*level + 0.5));//lower threshold for labeled image
}
void QmitkAdaptiveRegionGrowingToolGUI::ChangeLevelWindow(double newValue)
{
if (m_SliderInitialized)
{
//do nothing, if no preview exists
mitk::DataNode::Pointer newNode = m_DataStorage->GetNamedNode( m_NAMEFORLABLEDSEGMENTATIONIMAGE);
if (newNode.IsNull())
return;
mitk::LevelWindow tempLevelWindow;
newNode->GetLevelWindow(tempLevelWindow, NULL, "levelwindow"); //get the levelWindow associated with the preview
mitk::ScalarType level;// = this->m_UPPERTHRESHOLD - newValue + 0.5;
mitk::ScalarType* window = new mitk::ScalarType(1);
//adjust the levelwindow according to the position of the slider (newvalue)
if (m_CurrentRGDirectionIsUpwards)
{
level = m_UPPERTHRESHOLD - newValue + 0.5;
tempLevelWindow.SetLevelWindow(level, *window);
}
else
{
level = newValue - m_LOWERTHRESHOLD +0.5;
tempLevelWindow.SetLevelWindow(level, *window);
}
newNode->SetLevelWindow(tempLevelWindow, NULL, "levelwindow");
if (m_UseVolumeRendering)
this->UpdateVolumeRenderingThreshold((int) (level - 0.5));//lower threshold for labeled image
newNode->SetVisibility(true);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
void QmitkAdaptiveRegionGrowingToolGUI::DecreaseSlider()
{
//moves the slider one step to the left, when the "-"-button is pressed
if (this->m_Controls.m_PreviewSlider->value() != this->m_Controls.m_PreviewSlider->minimum())
{
int newValue = this->m_Controls.m_PreviewSlider->value() - 1;
this->ChangeLevelWindow(newValue);
this->m_Controls.m_PreviewSlider->setValue(newValue);
}
}
void QmitkAdaptiveRegionGrowingToolGUI::IncreaseSlider()
{
//moves the slider one step to the right, when the "+"-button is pressed
if (this->m_Controls.m_PreviewSlider->value() != this->m_Controls.m_PreviewSlider->maximum())
{
int newValue = this->m_Controls.m_PreviewSlider->value() + 1;
this->ChangeLevelWindow(newValue);
this->m_Controls.m_PreviewSlider->setValue(newValue);
}
}
void QmitkAdaptiveRegionGrowingToolGUI::ConfirmSegmentation()
{
//get image node
if(m_InputImageNode.IsNull())
{
QMessageBox::critical( NULL, "Adaptive region growing functionality", "Please specify the image in Datamanager!");
return;
}
//get image data
mitk::Image::Pointer orgImage = dynamic_cast<mitk::Image*> (m_InputImageNode->GetData());
if(orgImage.IsNull())
{
QMessageBox::critical( NULL, "Adaptive region growing functionality", "No Image found!");
return;
}
//get labeled segmentation
mitk::Image::Pointer labeledSeg = (mitk::Image*)m_DataStorage->GetNamedObject<mitk::Image>(m_NAMEFORLABLEDSEGMENTATIONIMAGE);
if(labeledSeg.IsNull())
{
QMessageBox::critical( NULL, "Adaptive region growing functionality", "No Segmentation Preview found!");
return;
}
mitk::DataNode::Pointer newNode = m_DataStorage->GetNamedNode( m_NAMEFORLABLEDSEGMENTATIONIMAGE);
if (newNode.IsNull())
return;
QmitkConfirmSegmentationDialog dialog;
QString segName = QString::fromStdString(m_RegionGrow3DTool->GetCurrentSegmentationName());
dialog.SetSegmentationName(segName);
int result = dialog.exec();
switch(result)
{
case QmitkConfirmSegmentationDialog::CREATE_NEW_SEGMENTATION:
m_RegionGrow3DTool->SetOverwriteExistingSegmentation(false);
break;
case QmitkConfirmSegmentationDialog::OVERWRITE_SEGMENTATION:
m_RegionGrow3DTool->SetOverwriteExistingSegmentation(true);
break;
case QmitkConfirmSegmentationDialog::CANCEL_SEGMENTATION:
return;
}
mitk::Image* img = dynamic_cast<mitk::Image*>(newNode->GetData());
AccessByItk(img, ITKThresholding);
// disable volume rendering preview after the segmentation node was created
this->EnableVolumeRendering(false);
newNode->SetVisibility(false);
m_Controls.m_cbVolumeRendering->setChecked(false);
//TODO disable slider etc...
}
template<typename TPixel, unsigned int VImageDimension>
void QmitkAdaptiveRegionGrowingToolGUI::ITKThresholding(itk::Image<TPixel, VImageDimension>* itkImage)
{
mitk::Image::Pointer originalSegmentation = dynamic_cast<mitk::Image*>(this->m_RegionGrow3DTool->
GetTargetSegmentationNode()->GetData());
int timeStep = mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget1") )->GetTimeStep();
if (originalSegmentation)
{
typedef itk::Image<TPixel, VImageDimension> InputImageType;
typedef itk::Image<unsigned char, VImageDimension> SegmentationType;
//select single 3D volume if we have more than one time step
typename SegmentationType::Pointer originalSegmentationInITK = SegmentationType::New();
if(originalSegmentation->GetTimeGeometry()->CountTimeSteps() > 1)
{
mitk::ImageTimeSelector::Pointer timeSelector = mitk::ImageTimeSelector::New();
timeSelector->SetInput( originalSegmentation );
timeSelector->SetTimeNr( timeStep );
timeSelector->UpdateLargestPossibleRegion();
CastToItkImage( timeSelector->GetOutput(), originalSegmentationInITK );
}
else //use original
{
CastToItkImage( originalSegmentation, originalSegmentationInITK );
}
//Fill current preiview image in segmentation image
originalSegmentationInITK->FillBuffer(0);
itk::ImageRegionIterator<SegmentationType> itOutput( originalSegmentationInITK, originalSegmentationInITK->GetLargestPossibleRegion() );
itk::ImageRegionIterator<InputImageType> itInput( itkImage, itkImage->GetLargestPossibleRegion() );
itOutput.GoToBegin();
itInput.GoToBegin();
//calculate threhold from slider value
int currentTreshold = 0;
if (m_CurrentRGDirectionIsUpwards)
{
currentTreshold = m_UPPERTHRESHOLD - m_Controls.m_PreviewSlider->value() + 1;
}
else
{
currentTreshold = m_Controls.m_PreviewSlider->value() - m_LOWERTHRESHOLD;
}
//iterate over image and set pixel in segmentation according to thresholded labeled image
while( !itOutput.IsAtEnd() && !itInput.IsAtEnd() )
{
//Use threshold slider to determine if pixel is set to 1
if( itInput.Value() != 0 && itInput.Value() > currentTreshold )
{
itOutput.Set( 1 );
}
++itOutput;
++itInput;
}
//combine current working segmentation image with our region growing result
originalSegmentation->SetVolume( (void*)(originalSegmentationInITK->GetPixelContainer()->GetBufferPointer()), timeStep);
originalSegmentation->Modified();
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
void QmitkAdaptiveRegionGrowingToolGUI::EnableControls(bool enable)
{
if (m_RegionGrow3DTool.IsNull())
return;
// Check if seed point is already set, if not leave RunSegmentation disabled
//if even m_DataStorage is NULL leave node NULL
mitk::DataNode::Pointer node = m_RegionGrow3DTool->GetPointSetNode();
if (node.IsNull()) {
this->m_Controls.m_pbRunSegmentation->setEnabled(false);
}
else
{
this->m_Controls.m_pbRunSegmentation->setEnabled(enable);
}
// Check if a segmentation exists, if not leave segmentation dependent disabled.
//if even m_DataStorage is NULL leave node NULL
node = m_DataStorage?m_DataStorage->GetNamedNode(m_NAMEFORLABLEDSEGMENTATIONIMAGE):NULL;
if (node.IsNull())
{
this->m_Controls.m_PreviewSlider->setEnabled(false);
this->m_Controls.m_pbConfirmSegementation->setEnabled(false);
}
else
{
this->m_Controls.m_PreviewSlider->setEnabled(enable);
this->m_Controls.m_pbConfirmSegementation->setEnabled(enable);
}
this->m_Controls.m_cbVolumeRendering->setEnabled(enable);
}
void QmitkAdaptiveRegionGrowingToolGUI::EnableVolumeRendering(bool enable)
{
mitk::DataNode::Pointer node = m_DataStorage->GetNamedNode( m_NAMEFORLABLEDSEGMENTATIONIMAGE);
if(node.IsNull())
return;
if(m_MultiWidget)
m_MultiWidget->SetWidgetPlanesVisibility(!enable);
if (enable)
{
node->SetBoolProperty("volumerendering", enable);
node->SetBoolProperty("volumerendering.uselod", true);
}
else
{
node->SetBoolProperty("volumerendering", enable);
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkAdaptiveRegionGrowingToolGUI::UpdateVolumeRenderingThreshold(int thValue)
{
mitk::DataNode::Pointer node = m_DataStorage->GetNamedNode( m_NAMEFORLABLEDSEGMENTATIONIMAGE);
mitk::TransferFunction::Pointer tf = mitk::TransferFunction::New();
if (m_UpdateSuggestedThreshold)
{
m_SuggestedThValue = thValue;
m_UpdateSuggestedThreshold = false;
}
// grayvalue->opacity
{
vtkPiecewiseFunction *f = tf->GetScalarOpacityFunction();
f->RemoveAllPoints();
f->AddPoint(0, 0);
f->AddPoint(thValue+0.5, 0);
f->AddPoint(thValue+1.5, 1);
f->AddPoint(1000, 1);
f->ClampingOn();
f->Modified();
}
// grayvalue->color
{
float a = 255.0;
vtkColorTransferFunction *ctf = tf->GetColorTransferFunction();
ctf->RemoveAllPoints();
//ctf->AddRGBPoint(-1000, 0.0, 0.0, 0.0);
ctf->AddRGBPoint(m_SuggestedThValue+1, 203/a, 104/a, 102/a);
ctf->AddRGBPoint(m_SuggestedThValue, 255/a, 0/a, 0/a);
ctf->ClampingOn();
ctf->Modified();
}
// GradientOpacityFunction
{
vtkPiecewiseFunction *gof = tf->GetGradientOpacityFunction();
gof->RemoveAllPoints();
gof->AddPoint(-10000, 1);
gof->AddPoint(10000, 1);
gof->ClampingOn();
gof->Modified();
}
mitk::TransferFunctionProperty::Pointer tfp = mitk::TransferFunctionProperty::New();
tfp->SetValue(tf);
node->SetProperty("TransferFunction", tfp);
}
void QmitkAdaptiveRegionGrowingToolGUI::UseVolumeRendering(bool on)
{
m_UseVolumeRendering = on;
this->EnableVolumeRendering(on);
}
void QmitkAdaptiveRegionGrowingToolGUI::SetLowerThresholdValue( double lowerThreshold )
{
m_LOWERTHRESHOLD = lowerThreshold;
}
void QmitkAdaptiveRegionGrowingToolGUI::SetUpperThresholdValue( double upperThreshold)
{
m_UPPERTHRESHOLD = upperThreshold;
}
void QmitkAdaptiveRegionGrowingToolGUI::Deactivated()
{
// make the segmentation preview node invisible
mitk::DataNode::Pointer node = m_DataStorage->GetNamedNode( m_NAMEFORLABLEDSEGMENTATIONIMAGE);
if( node.IsNotNull() )
{
node->SetVisibility(false);
}
// disable volume rendering preview after the segmentation node was created
this->EnableVolumeRendering(false);
m_Controls.m_cbVolumeRendering->setChecked(false);
}
void QmitkAdaptiveRegionGrowingToolGUI::Activated()
{
}
diff --git a/Modules/SegmentationUI/Qmitk/QmitkAdaptiveRegionGrowingToolGUI.h b/Modules/SegmentationUI/Qmitk/QmitkAdaptiveRegionGrowingToolGUI.h
index f069283ebe..c5bdcd03df 100644
--- a/Modules/SegmentationUI/Qmitk/QmitkAdaptiveRegionGrowingToolGUI.h
+++ b/Modules/SegmentationUI/Qmitk/QmitkAdaptiveRegionGrowingToolGUI.h
@@ -1,162 +1,162 @@
/*===================================================================
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 QMITK_QmitkAdaptiveRegionGrowingToolGUI_H
#define QMITK_QmitkAdaptiveRegionGrowingToolGUI_H
#include "mitkDataStorage.h"
#include "itkImage.h"
#include "mitkGeometry3D.h"
#include "mitkPointSet.h"
#include "qwidget.h"
#include "ui_QmitkAdaptiveRegionGrowingToolGUIControls.h"
#include <MitkSegmentationUIExports.h>
#include "QmitkToolGUI.h"
#include "mitkAdaptiveRegionGrowingTool.h"
class QmitkStdMultiWidget;
class DataNode;
class QmitkAdaptiveRegionGrowingToolGUIControls;
/*!
*
* \brief QmitkAdaptiveRegionGrowingToolGUI
*
* Adaptive Region Growing View class of the segmentation.
*
*/
class MitkSegmentationUI_EXPORT QmitkAdaptiveRegionGrowingToolGUI : public QmitkToolGUI
{
Q_OBJECT
public:
mitkClassMacro(QmitkAdaptiveRegionGrowingToolGUI, QmitkToolGUI);
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
QmitkAdaptiveRegionGrowingToolGUI(QWidget* parent=0);
/** \brief Method to create the connections for the component. This Method is obligatory even if no connections is needed*/
virtual void CreateConnections();
///** \brief Method to set the default data storage.*/
virtual void SetDataStorage(mitk::DataStorage* dataStorage);
void SetMultiWidget(QmitkStdMultiWidget* multiWidget);
void SetDataNodeNames(std::string labledSegmentation, std::string binaryImage, /*std::string vesselTree,*/ std::string surface);
void EnableControls(bool enable);
void SetInputImageNode(mitk::DataNode* node);
void Deactivated();
void Activated();
/**
* @brief The created GUI from the .ui-File. This Attribute is obligatory
*/
Ui::QmitkAdaptiveRegionGrowingToolGUIControls m_Controls;
protected slots:
void RunSegmentation();
void ChangeLevelWindow(double newValue);//called, when the Level Window is changed via the slider in the ControlWidget
//****called, when the slider-position is modified via the +/- buttons
void IncreaseSlider();
void DecreaseSlider();
//***
void ConfirmSegmentation();
void UseVolumeRendering(bool on);
void SetLowerThresholdValue(double lowerThreshold);
void SetUpperThresholdValue(double upperThreshold);
void OnNewToolAssociated(mitk::Tool*);
protected:
mitk::AdaptiveRegionGrowingTool::Pointer m_RegionGrow3DTool;
/** \brief Destructor. */
virtual ~QmitkAdaptiveRegionGrowingToolGUI();
//Pointer to the main widget to be able to reach the renderer
QmitkStdMultiWidget* m_MultiWidget;
mitk::DataStorage* m_DataStorage;
mitk::DataNode::Pointer m_InputImageNode;
void OnPointAdded();
private:
std::string m_NAMEFORORGIMAGE;
std::string m_NAMEFORLABLEDSEGMENTATIONIMAGE;
std::string m_NAMEFORBINARYIMAGE;
std::string m_NAMEFORSURFACE;
mitk::ScalarType m_LOWERTHRESHOLD; //Hounsfield value
mitk::ScalarType m_UPPERTHRESHOLD; //Hounsfield value
mitk::ScalarType m_SeedPointValueMean;
void RemoveHelperNodes();
int m_DetectedLeakagePoint;
bool m_CurrentRGDirectionIsUpwards; // defines fixed threshold (true = LOWERTHRESHOLD fixed, false = UPPERTHRESHOLD fixed)
int m_SeedpointValue;
bool m_SliderInitialized;
bool m_UseVolumeRendering;
bool m_UpdateSuggestedThreshold;
float m_SuggestedThValue;
long m_PointSetAddObserverTag;
template < typename TPixel, unsigned int VImageDimension >
- void StartRegionGrowing( itk::Image< TPixel, VImageDimension >* itkImage, mitk::Geometry3D* imageGeometry, mitk::PointSet::PointType seedPoint );
+ void StartRegionGrowing( itk::Image< TPixel, VImageDimension >* itkImage, mitk::BaseGeometry* imageGeometry, mitk::PointSet::PointType seedPoint );
template < typename TPixel, unsigned int VImageDimension >
void ITKThresholding( itk::Image< TPixel, VImageDimension >* inputImage );
void InitializeLevelWindow();
void EnableVolumeRendering(bool enable);
void UpdateVolumeRenderingThreshold(int thValue);
};
#endif
diff --git a/Modules/SegmentationUI/Qmitk/QmitkSlicesInterpolator.cpp b/Modules/SegmentationUI/Qmitk/QmitkSlicesInterpolator.cpp
index 449d5a2e2f..b5a06fd874 100644
--- a/Modules/SegmentationUI/Qmitk/QmitkSlicesInterpolator.cpp
+++ b/Modules/SegmentationUI/Qmitk/QmitkSlicesInterpolator.cpp
@@ -1,1090 +1,1090 @@
/*===================================================================
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 "QmitkSlicesInterpolator.h"
#include "QmitkStdMultiWidget.h"
#include "QmitkSelectableGLWidget.h"
#include "mitkToolManager.h"
#include "mitkDataNodeFactory.h"
#include "mitkLevelWindowProperty.h"
#include "mitkColorProperty.h"
#include "mitkProperties.h"
#include "mitkRenderingManager.h"
#include "mitkOverwriteSliceImageFilter.h"
#include "mitkProgressBar.h"
#include "mitkGlobalInteraction.h"
#include "mitkOperationEvent.h"
#include "mitkUndoController.h"
#include "mitkInteractionConst.h"
#include "mitkApplyDiffImageOperation.h"
#include "mitkDiffImageApplier.h"
#include "mitkSegTool2D.h"
#include "mitkCoreObjectFactory.h"
#include "mitkSurfaceToImageFilter.h"
#include "mitkSliceNavigationController.h"
#include <mitkVtkImageOverwrite.h>
#include <mitkExtractSliceFilter.h>
#include <mitkImageTimeSelector.h>
#include <mitkImageWriteAccessor.h>
#include <itkCommand.h>
#include <QCheckBox>
#include <QPushButton>
#include <QMenu>
#include <QCursor>
#include <QVBoxLayout>
#include <QMessageBox>
//#define ROUND(a) ((a)>0 ? (int)((a)+0.5) : -(int)(0.5-(a)))
const std::map<QAction*, mitk::SliceNavigationController*> QmitkSlicesInterpolator::createActionToSliceDimension()
{
std::map<QAction*, mitk::SliceNavigationController*> actionToSliceDimension;
foreach(mitk::SliceNavigationController* slicer, m_ControllerToDeleteObserverTag.keys())
{
actionToSliceDimension[new QAction(QString::fromStdString(slicer->GetViewDirectionAsString()),0)] = slicer;
}
return actionToSliceDimension;
}
QmitkSlicesInterpolator::QmitkSlicesInterpolator(QWidget* parent, const char* /*name*/)
:QWidget(parent),
// ACTION_TO_SLICEDIMENSION( createActionToSliceDimension() ),
m_Interpolator( mitk::SegmentationInterpolationController::New() ),
m_SurfaceInterpolator(mitk::SurfaceInterpolationController::GetInstance()),
m_ToolManager(NULL),
m_Initialized(false),
m_LastSNC(0),
m_LastSliceIndex(0),
m_2DInterpolationEnabled(false),
m_3DInterpolationEnabled(false)
{
m_GroupBoxEnableExclusiveInterpolationMode = new QGroupBox("Interpolation", this);
QVBoxLayout* vboxLayout = new QVBoxLayout(m_GroupBoxEnableExclusiveInterpolationMode);
m_CmbInterpolation = new QComboBox(m_GroupBoxEnableExclusiveInterpolationMode);
m_CmbInterpolation->addItem("Disabled");
m_CmbInterpolation->addItem("2-Dimensional");
m_CmbInterpolation->addItem("3-Dimensional");
vboxLayout->addWidget(m_CmbInterpolation);
m_BtnApply2D = new QPushButton("Confirm for single slice", m_GroupBoxEnableExclusiveInterpolationMode);
vboxLayout->addWidget(m_BtnApply2D);
m_BtnApplyForAllSlices2D = new QPushButton("Confirm for all slices", m_GroupBoxEnableExclusiveInterpolationMode);
vboxLayout->addWidget(m_BtnApplyForAllSlices2D);
m_BtnApply3D = new QPushButton("Confirm", m_GroupBoxEnableExclusiveInterpolationMode);
vboxLayout->addWidget(m_BtnApply3D);
m_ChkShowPositionNodes = new QCheckBox("Show Position Nodes", m_GroupBoxEnableExclusiveInterpolationMode);
vboxLayout->addWidget(m_ChkShowPositionNodes);
this->HideAllInterpolationControls();
connect(m_CmbInterpolation, SIGNAL(currentIndexChanged(int)), this, SLOT(OnInterpolationMethodChanged(int)));
connect(m_BtnApply2D, SIGNAL(clicked()), this, SLOT(OnAcceptInterpolationClicked()));
connect(m_BtnApplyForAllSlices2D, SIGNAL(clicked()), this, SLOT(OnAcceptAllInterpolationsClicked()));
connect(m_BtnApply3D, SIGNAL(clicked()), this, SLOT(OnAccept3DInterpolationClicked()));
connect(m_ChkShowPositionNodes, SIGNAL(toggled(bool)), this, SLOT(OnShowMarkers(bool)));
connect(m_ChkShowPositionNodes, SIGNAL(toggled(bool)), this, SIGNAL(SignalShowMarkerNodes(bool)));
QHBoxLayout* layout = new QHBoxLayout(this);
layout->addWidget(m_GroupBoxEnableExclusiveInterpolationMode);
this->setLayout(layout);
itk::ReceptorMemberCommand<QmitkSlicesInterpolator>::Pointer command = itk::ReceptorMemberCommand<QmitkSlicesInterpolator>::New();
command->SetCallbackFunction( this, &QmitkSlicesInterpolator::OnInterpolationInfoChanged );
InterpolationInfoChangedObserverTag = m_Interpolator->AddObserver( itk::ModifiedEvent(), command );
itk::ReceptorMemberCommand<QmitkSlicesInterpolator>::Pointer command2 = itk::ReceptorMemberCommand<QmitkSlicesInterpolator>::New();
command2->SetCallbackFunction( this, &QmitkSlicesInterpolator::OnSurfaceInterpolationInfoChanged );
SurfaceInterpolationInfoChangedObserverTag = m_SurfaceInterpolator->AddObserver( itk::ModifiedEvent(), command2 );
// feedback node and its visualization properties
m_FeedbackNode = mitk::DataNode::New();
mitk::CoreObjectFactory::GetInstance()->SetDefaultProperties( m_FeedbackNode );
m_FeedbackNode->SetProperty( "binary", mitk::BoolProperty::New(true) );
m_FeedbackNode->SetProperty( "outline binary", mitk::BoolProperty::New(true) );
m_FeedbackNode->SetProperty( "color", mitk::ColorProperty::New(255.0, 255.0, 0.0) );
m_FeedbackNode->SetProperty( "texture interpolation", mitk::BoolProperty::New(false) );
m_FeedbackNode->SetProperty( "layer", mitk::IntProperty::New( 20 ) );
m_FeedbackNode->SetProperty( "levelwindow", mitk::LevelWindowProperty::New( mitk::LevelWindow(0, 1) ) );
m_FeedbackNode->SetProperty( "name", mitk::StringProperty::New("Interpolation feedback") );
m_FeedbackNode->SetProperty( "opacity", mitk::FloatProperty::New(0.8) );
m_FeedbackNode->SetProperty( "helper object", mitk::BoolProperty::New(true) );
m_InterpolatedSurfaceNode = mitk::DataNode::New();
m_InterpolatedSurfaceNode->SetProperty( "color", mitk::ColorProperty::New(255.0,255.0,0.0) );
m_InterpolatedSurfaceNode->SetProperty( "name", mitk::StringProperty::New("Surface Interpolation feedback") );
m_InterpolatedSurfaceNode->SetProperty( "opacity", mitk::FloatProperty::New(0.5) );
m_InterpolatedSurfaceNode->SetProperty( "includeInBoundingBox", mitk::BoolProperty::New(false));
m_InterpolatedSurfaceNode->SetProperty( "helper object", mitk::BoolProperty::New(true) );
m_InterpolatedSurfaceNode->SetVisibility(false);
m_3DContourNode = mitk::DataNode::New();
m_3DContourNode->SetProperty( "color", mitk::ColorProperty::New(0.0, 0.0, 0.0) );
m_3DContourNode->SetProperty("helper object", mitk::BoolProperty::New(true));
m_3DContourNode->SetProperty( "name", mitk::StringProperty::New("Drawn Contours") );
m_3DContourNode->SetProperty("material.representation", mitk::VtkRepresentationProperty::New(VTK_WIREFRAME));
m_3DContourNode->SetProperty("material.wireframeLineWidth", mitk::FloatProperty::New(2.0f));
m_3DContourNode->SetProperty("3DContourContainer", mitk::BoolProperty::New(true));
m_3DContourNode->SetProperty( "includeInBoundingBox", mitk::BoolProperty::New(false));
m_3DContourNode->SetVisibility(false, mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget1")));
m_3DContourNode->SetVisibility(false, mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget2")));
m_3DContourNode->SetVisibility(false, mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget3")));
m_3DContourNode->SetVisibility(false, mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4")));
QWidget::setContentsMargins(0, 0, 0, 0);
if ( QWidget::layout() != NULL )
{
QWidget::layout()->setContentsMargins(0, 0, 0, 0);
}
//For running 3D Interpolation in background
// create a QFuture and a QFutureWatcher
connect(&m_Watcher, SIGNAL(started()), this, SLOT(StartUpdateInterpolationTimer()));
connect(&m_Watcher, SIGNAL(finished()), this, SLOT(OnSurfaceInterpolationFinished()));
connect(&m_Watcher, SIGNAL(finished()), this, SLOT(StopUpdateInterpolationTimer()));
m_Timer = new QTimer(this);
connect(m_Timer, SIGNAL(timeout()), this, SLOT(ChangeSurfaceColor()));
}
void QmitkSlicesInterpolator::SetDataStorage( mitk::DataStorage::Pointer storage )
{
m_DataStorage = storage;
m_SurfaceInterpolator->SetDataStorage(storage);
}
mitk::DataStorage* QmitkSlicesInterpolator::GetDataStorage()
{
if ( m_DataStorage.IsNotNull() )
{
return m_DataStorage;
}
else
{
return NULL;
}
}
void QmitkSlicesInterpolator::Initialize(mitk::ToolManager* toolManager, const QList<mitk::SliceNavigationController *> &controllers)
{
Q_ASSERT(!controllers.empty());
if (m_Initialized)
{
// remove old observers
Uninitialize();
}
m_ToolManager = toolManager;
if (m_ToolManager)
{
// set enabled only if a segmentation is selected
mitk::DataNode* node = m_ToolManager->GetWorkingData(0);
QWidget::setEnabled( node != NULL );
// react whenever the set of selected segmentation changes
m_ToolManager->WorkingDataChanged += mitk::MessageDelegate<QmitkSlicesInterpolator>( this, &QmitkSlicesInterpolator::OnToolManagerWorkingDataModified );
m_ToolManager->ReferenceDataChanged += mitk::MessageDelegate<QmitkSlicesInterpolator>( this, &QmitkSlicesInterpolator::OnToolManagerReferenceDataModified );
// connect to the slice navigation controller. after each change, call the interpolator
foreach(mitk::SliceNavigationController* slicer, controllers)
{
//Has to be initialized
m_LastSNC = slicer;
m_TimeStep.insert(slicer, slicer->GetTime()->GetPos());
itk::MemberCommand<QmitkSlicesInterpolator>::Pointer deleteCommand = itk::MemberCommand<QmitkSlicesInterpolator>::New();
deleteCommand->SetCallbackFunction( this, &QmitkSlicesInterpolator::OnSliceNavigationControllerDeleted);
m_ControllerToDeleteObserverTag.insert(slicer, slicer->AddObserver(itk::DeleteEvent(), deleteCommand));
itk::MemberCommand<QmitkSlicesInterpolator>::Pointer timeChangedCommand = itk::MemberCommand<QmitkSlicesInterpolator>::New();
timeChangedCommand->SetCallbackFunction( this, &QmitkSlicesInterpolator::OnTimeChanged);
m_ControllerToTimeObserverTag.insert(slicer, slicer->AddObserver(mitk::SliceNavigationController::TimeGeometryEvent(NULL,0), timeChangedCommand));
itk::MemberCommand<QmitkSlicesInterpolator>::Pointer sliceChangedCommand = itk::MemberCommand<QmitkSlicesInterpolator>::New();
sliceChangedCommand->SetCallbackFunction( this, &QmitkSlicesInterpolator::OnSliceChanged);
m_ControllerToSliceObserverTag.insert(slicer, slicer->AddObserver(mitk::SliceNavigationController::GeometrySliceEvent(NULL,0), sliceChangedCommand));
}
ACTION_TO_SLICEDIMENSION = createActionToSliceDimension();
}
m_Initialized = true;
}
void QmitkSlicesInterpolator::Uninitialize()
{
if (m_ToolManager.IsNotNull())
{
m_ToolManager->WorkingDataChanged -= mitk::MessageDelegate<QmitkSlicesInterpolator>(this, &QmitkSlicesInterpolator::OnToolManagerWorkingDataModified);
m_ToolManager->ReferenceDataChanged -= mitk::MessageDelegate<QmitkSlicesInterpolator>(this, &QmitkSlicesInterpolator::OnToolManagerReferenceDataModified);
}
foreach(mitk::SliceNavigationController* slicer, m_ControllerToSliceObserverTag.keys())
{
slicer->RemoveObserver(m_ControllerToDeleteObserverTag.take(slicer));
slicer->RemoveObserver(m_ControllerToTimeObserverTag.take(slicer));
slicer->RemoveObserver(m_ControllerToSliceObserverTag.take(slicer));
}
ACTION_TO_SLICEDIMENSION.clear();
m_ToolManager = NULL;
m_Initialized = false;
}
QmitkSlicesInterpolator::~QmitkSlicesInterpolator()
{
if (m_Initialized)
{
// remove old observers
Uninitialize();
}
if(m_DataStorage->Exists(m_3DContourNode))
m_DataStorage->Remove(m_3DContourNode);
if(m_DataStorage->Exists(m_InterpolatedSurfaceNode))
m_DataStorage->Remove(m_InterpolatedSurfaceNode);
// remove observer
m_Interpolator->RemoveObserver( InterpolationInfoChangedObserverTag );
m_SurfaceInterpolator->RemoveObserver( SurfaceInterpolationInfoChangedObserverTag );
delete m_Timer;
}
/**
External enableization...
*/
void QmitkSlicesInterpolator::setEnabled( bool enable )
{
QWidget::setEnabled(enable);
//Set the gui elements of the different interpolation modi enabled
if (enable)
{
if (m_2DInterpolationEnabled)
{
this->Show2DInterpolationControls(true);
m_Interpolator->Activate2DInterpolation(true);
}
else if (m_3DInterpolationEnabled)
{
this->Show3DInterpolationControls(true);
this->Show3DInterpolationResult(true);
}
}
//Set all gui elements of the interpolation disabled
else
{
this->HideAllInterpolationControls();
this->Show3DInterpolationResult(false);
}
}
void QmitkSlicesInterpolator::On2DInterpolationEnabled(bool status)
{
OnInterpolationActivated(status);
m_Interpolator->Activate2DInterpolation(status);
}
void QmitkSlicesInterpolator::On3DInterpolationEnabled(bool status)
{
On3DInterpolationActivated(status);
}
void QmitkSlicesInterpolator::OnInterpolationDisabled(bool status)
{
if (status)
{
OnInterpolationActivated(!status);
On3DInterpolationActivated(!status);
this->Show3DInterpolationResult(false);
}
}
void QmitkSlicesInterpolator::HideAllInterpolationControls()
{
this->Show2DInterpolationControls(false);
this->Show3DInterpolationControls(false);
}
void QmitkSlicesInterpolator::Show2DInterpolationControls(bool show)
{
m_BtnApply2D->setVisible(show);
m_BtnApplyForAllSlices2D->setVisible(show);
}
void QmitkSlicesInterpolator::Show3DInterpolationControls(bool show)
{
m_BtnApply3D->setVisible(show);
m_ChkShowPositionNodes->setVisible(show);
}
void QmitkSlicesInterpolator::OnInterpolationMethodChanged(int index)
{
switch(index)
{
case 0: // Disabled
m_GroupBoxEnableExclusiveInterpolationMode->setTitle("Interpolation");
this->HideAllInterpolationControls();
this->OnInterpolationActivated(false);
this->On3DInterpolationActivated(false);
this->Show3DInterpolationResult(false);
m_Interpolator->Activate2DInterpolation(false);
break;
case 1: // 2D
m_GroupBoxEnableExclusiveInterpolationMode->setTitle("Interpolation (Enabled)");
this->HideAllInterpolationControls();
this->Show2DInterpolationControls(true);
this->OnInterpolationActivated(true);
this->On3DInterpolationActivated(false);
m_Interpolator->Activate2DInterpolation(true);
break;
case 2: // 3D
m_GroupBoxEnableExclusiveInterpolationMode->setTitle("Interpolation (Enabled)");
this->HideAllInterpolationControls();
this->Show3DInterpolationControls(true);
this->OnInterpolationActivated(false);
this->On3DInterpolationActivated(true);
m_Interpolator->Activate2DInterpolation(false);
break;
default:
MITK_ERROR << "Unknown interpolation method!";
m_CmbInterpolation->setCurrentIndex(0);
break;
}
}
void QmitkSlicesInterpolator::OnShowMarkers(bool state)
{
mitk::DataStorage::SetOfObjects::ConstPointer allContourMarkers = m_DataStorage->GetSubset(mitk::NodePredicateProperty::New("isContourMarker"
, mitk::BoolProperty::New(true)));
for (mitk::DataStorage::SetOfObjects::ConstIterator it = allContourMarkers->Begin(); it != allContourMarkers->End(); ++it)
{
it->Value()->SetProperty("helper object", mitk::BoolProperty::New(!state));
}
}
void QmitkSlicesInterpolator::OnToolManagerWorkingDataModified()
{
if (m_ToolManager->GetWorkingData(0) != 0)
{
m_Segmentation = dynamic_cast<mitk::Image*>(m_ToolManager->GetWorkingData(0)->GetData());
}
else
{
//If no workingdata is set, remove the interpolation feedback
this->GetDataStorage()->Remove(m_FeedbackNode);
m_FeedbackNode->SetData(NULL);
this->GetDataStorage()->Remove(m_3DContourNode);
m_3DContourNode->SetData(NULL);
this->GetDataStorage()->Remove(m_InterpolatedSurfaceNode);
m_InterpolatedSurfaceNode->SetData(NULL);
return;
}
//Updating the current selected segmentation for the 3D interpolation
SetCurrentContourListID();
if (m_2DInterpolationEnabled)
{
OnInterpolationActivated( true ); // re-initialize if needed
}
this->CheckSupportedImageDimension();
}
void QmitkSlicesInterpolator::OnToolManagerReferenceDataModified()
{
}
void QmitkSlicesInterpolator::OnTimeChanged(itk::Object* sender, const itk::EventObject& e)
{
//Check if we really have a GeometryTimeEvent
if (!dynamic_cast<const mitk::SliceNavigationController::GeometryTimeEvent*>(&e))
return;
mitk::SliceNavigationController* slicer = dynamic_cast<mitk::SliceNavigationController*>(sender);
Q_ASSERT(slicer);
m_TimeStep[slicer]/* = event.GetPos()*/;
//TODO Macht das hier wirklich Sinn????
if (m_LastSNC == slicer)
{
slicer->SendSlice();//will trigger a new interpolation
}
}
void QmitkSlicesInterpolator::OnSliceChanged(itk::Object *sender, const itk::EventObject &e)
{
//Check whether we really have a GeometrySliceEvent
if (!dynamic_cast<const mitk::SliceNavigationController::GeometrySliceEvent*>(&e))
return;
mitk::SliceNavigationController* slicer = dynamic_cast<mitk::SliceNavigationController*>(sender);
if (TranslateAndInterpolateChangedSlice(e, slicer))
{
slicer->GetRenderer()->RequestUpdate();
}
}
bool QmitkSlicesInterpolator::TranslateAndInterpolateChangedSlice(const itk::EventObject& e, mitk::SliceNavigationController* slicer)
{
if (!m_2DInterpolationEnabled) return false;
try
{
const mitk::SliceNavigationController::GeometrySliceEvent& event = dynamic_cast<const mitk::SliceNavigationController::GeometrySliceEvent&>(e);
mitk::TimeGeometry* tsg = event.GetTimeGeometry();
if (tsg && m_TimeStep.contains(slicer))
{
mitk::SlicedGeometry3D* slicedGeometry = dynamic_cast<mitk::SlicedGeometry3D*>(tsg->GetGeometryForTimeStep(m_TimeStep[slicer]).GetPointer());
if (slicedGeometry)
{
m_LastSNC = slicer;
- mitk::PlaneGeometry* plane = dynamic_cast<mitk::PlaneGeometry*>(slicedGeometry->GetGeometry2D( event.GetPos() ));
+ mitk::PlaneGeometry* plane = dynamic_cast<mitk::PlaneGeometry*>(slicedGeometry->GetPlaneGeometry( event.GetPos() ));
if (plane)
Interpolate( plane, m_TimeStep[slicer], slicer );
return true;
}
}
}
catch(std::bad_cast)
{
return false; // so what
}
return false;
}
void QmitkSlicesInterpolator::Interpolate( mitk::PlaneGeometry* plane, unsigned int timeStep, mitk::SliceNavigationController* slicer )
{
if (m_ToolManager)
{
mitk::DataNode* node = m_ToolManager->GetWorkingData(0);
if (node)
{
m_Segmentation = dynamic_cast<mitk::Image*>(node->GetData());
if (m_Segmentation)
{
int clickedSliceDimension(-1);
int clickedSliceIndex(-1);
// calculate real slice position, i.e. slice of the image and not slice of the TimeSlicedGeometry
mitk::SegTool2D::DetermineAffectedImageSlice( m_Segmentation, plane, clickedSliceDimension, clickedSliceIndex );
mitk::Image::Pointer interpolation = m_Interpolator->Interpolate( clickedSliceDimension, clickedSliceIndex, plane, timeStep );
m_FeedbackNode->SetData( interpolation );
m_LastSNC = slicer;
m_LastSliceIndex = clickedSliceIndex;
}
}
}
}
void QmitkSlicesInterpolator::OnSurfaceInterpolationFinished()
{
mitk::Surface::Pointer interpolatedSurface = m_SurfaceInterpolator->GetInterpolationResult();
mitk::DataNode* workingNode = m_ToolManager->GetWorkingData(0);
if(interpolatedSurface.IsNotNull() && workingNode &&
workingNode->IsVisible(mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget3"))))
{
m_BtnApply3D->setEnabled(true);
m_InterpolatedSurfaceNode->SetData(interpolatedSurface);
m_3DContourNode->SetData(m_SurfaceInterpolator->GetContoursAsSurface());
this->Show3DInterpolationResult(true);
if( !m_DataStorage->Exists(m_InterpolatedSurfaceNode) && !m_DataStorage->Exists(m_3DContourNode))
{
m_DataStorage->Add(m_3DContourNode);
m_DataStorage->Add(m_InterpolatedSurfaceNode);
}
}
else if (interpolatedSurface.IsNull())
{
m_BtnApply3D->setEnabled(false);
if (m_DataStorage->Exists(m_InterpolatedSurfaceNode))
{
this->Show3DInterpolationResult(false);
}
}
foreach (mitk::SliceNavigationController* slicer, m_ControllerToTimeObserverTag.keys())
{
slicer->GetRenderer()->RequestUpdate();
}
}
void QmitkSlicesInterpolator::OnAcceptInterpolationClicked()
{
if (m_Segmentation && m_FeedbackNode->GetData())
{
//making interpolation separately undoable
mitk::UndoStackItem::IncCurrObjectEventId();
mitk::UndoStackItem::IncCurrGroupEventId();
mitk::UndoStackItem::ExecuteIncrement();
//Make sure that for reslicing and overwriting the same alogrithm is used. We can specify the mode of the vtk reslicer
vtkSmartPointer<mitkVtkImageOverwrite> reslice = vtkSmartPointer<mitkVtkImageOverwrite>::New();
// Set slice as input
mitk::Image::Pointer slice = dynamic_cast<mitk::Image*>(m_FeedbackNode->GetData());
reslice->SetInputSlice(slice->GetSliceData()->GetVtkImageData(slice));
//set overwrite mode to true to write back to the image volume
reslice->SetOverwriteMode(true);
reslice->Modified();
mitk::ExtractSliceFilter::Pointer extractor = mitk::ExtractSliceFilter::New(reslice);
extractor->SetInput( m_Segmentation );
unsigned int timestep = m_LastSNC->GetTime()->GetPos();
extractor->SetTimeStep( timestep );
extractor->SetWorldGeometry( m_LastSNC->GetCurrentPlaneGeometry() );
extractor->SetVtkOutputRequest(true);
extractor->SetResliceTransformByGeometry( m_Segmentation->GetTimeGeometry()->GetGeometryForTimeStep( timestep ) );
extractor->Modified();
extractor->Update();
//the image was modified within the pipeline, but not marked so
m_Segmentation->Modified();
m_Segmentation->GetVtkImageData()->Modified();
m_FeedbackNode->SetData(NULL);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
void QmitkSlicesInterpolator::AcceptAllInterpolations(mitk::SliceNavigationController* slicer)
{
/*
* What exactly is done here:
* 1. We create an empty diff image for the current segmentation
* 2. All interpolated slices are written into the diff image
* 3. Then the diffimage is applied to the original segmentation
*/
if (m_Segmentation)
{
//making interpolation separately undoable
mitk::UndoStackItem::IncCurrObjectEventId();
mitk::UndoStackItem::IncCurrGroupEventId();
mitk::UndoStackItem::ExecuteIncrement();
mitk::Image::Pointer image3D = m_Segmentation;
unsigned int timeStep( slicer->GetTime()->GetPos() );
if (m_Segmentation->GetDimension() == 4)
{
mitk::ImageTimeSelector::Pointer timeSelector = mitk::ImageTimeSelector::New();
timeSelector->SetInput( m_Segmentation );
timeSelector->SetTimeNr( timeStep );
timeSelector->Update();
image3D = timeSelector->GetOutput();
}
// create a empty diff image for the undo operation
mitk::Image::Pointer diffImage = mitk::Image::New();
diffImage->Initialize( image3D );
// Create scope for ImageWriteAccessor so that the accessor is destroyed
// after the image is initialized. Otherwise later image access will lead to an error
{
mitk::ImageWriteAccessor imAccess(diffImage);
// Set all pixels to zero
mitk::PixelType pixelType( mitk::MakeScalarPixelType<unsigned char>() );
memset( imAccess.GetData(), 0, (pixelType.GetBpe() >> 3) * diffImage->GetDimension(0) * diffImage->GetDimension(1) * diffImage->GetDimension(2) );
}
// Since we need to shift the plane it must be clone so that the original plane isn't altered
mitk::PlaneGeometry::Pointer reslicePlane = slicer->GetCurrentPlaneGeometry()->Clone();
int sliceDimension(-1);
int sliceIndex(-1);
mitk::SegTool2D::DetermineAffectedImageSlice( m_Segmentation, reslicePlane, sliceDimension, sliceIndex );
unsigned int zslices = m_Segmentation->GetDimension( sliceDimension );
mitk::ProgressBar::GetInstance()->AddStepsToDo(zslices);
mitk::Point3D origin = reslicePlane->GetOrigin();
unsigned int totalChangedSlices(0);
for (unsigned int sliceIndex = 0; sliceIndex < zslices; ++sliceIndex)
{
// Transforming the current origin of the reslice plane
// so that it matches the one of the next slice
m_Segmentation->GetSlicedGeometry()->WorldToIndex(origin, origin);
origin[sliceDimension] = sliceIndex;
m_Segmentation->GetSlicedGeometry()->IndexToWorld(origin, origin);
reslicePlane->SetOrigin(origin);
//Set the slice as 'input'
mitk::Image::Pointer interpolation = m_Interpolator->Interpolate( sliceDimension, sliceIndex, reslicePlane, timeStep );
if (interpolation.IsNotNull()) // we don't check if interpolation is necessary/sensible - but m_Interpolator does
{
//Setting up the reslicing pipeline which allows us to write the interpolation results back into
//the image volume
vtkSmartPointer<mitkVtkImageOverwrite> reslice = vtkSmartPointer<mitkVtkImageOverwrite>::New();
//set overwrite mode to true to write back to the image volume
reslice->SetInputSlice(interpolation->GetSliceData()->GetVtkImageData(interpolation));
reslice->SetOverwriteMode(true);
reslice->Modified();
mitk::ExtractSliceFilter::Pointer diffslicewriter = mitk::ExtractSliceFilter::New(reslice);
diffslicewriter->SetInput( diffImage );
diffslicewriter->SetTimeStep( timeStep );
diffslicewriter->SetWorldGeometry(reslicePlane);
diffslicewriter->SetVtkOutputRequest(true);
diffslicewriter->SetResliceTransformByGeometry( diffImage->GetTimeGeometry()->GetGeometryForTimeStep( timeStep ) );
diffslicewriter->Modified();
diffslicewriter->Update();
++totalChangedSlices;
}
mitk::ProgressBar::GetInstance()->Progress();
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
if (totalChangedSlices > 0)
{
// store undo stack items
if ( true )
{
// create do/undo operations
mitk::ApplyDiffImageOperation* doOp = new mitk::ApplyDiffImageOperation( mitk::OpTEST, m_Segmentation, diffImage, timeStep );
mitk::ApplyDiffImageOperation* undoOp = new mitk::ApplyDiffImageOperation( mitk::OpTEST, m_Segmentation, diffImage, timeStep );
undoOp->SetFactor( -1.0 );
std::stringstream comment;
comment << "Confirm all interpolations (" << totalChangedSlices << ")";
mitk::OperationEvent* undoStackItem = new mitk::OperationEvent( mitk::DiffImageApplier::GetInstanceForUndo(), doOp, undoOp, comment.str() );
mitk::UndoController::GetCurrentUndoModel()->SetOperationEvent( undoStackItem );
// acutally apply the changes here to the original image
mitk::DiffImageApplier::GetInstanceForUndo()->ExecuteOperation( doOp );
}
}
m_FeedbackNode->SetData(NULL);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
void QmitkSlicesInterpolator::FinishInterpolation(mitk::SliceNavigationController* slicer)
{
//this redirect is for calling from outside
if (slicer == NULL)
OnAcceptAllInterpolationsClicked();
else
AcceptAllInterpolations( slicer );
}
void QmitkSlicesInterpolator::OnAcceptAllInterpolationsClicked()
{
QMenu orientationPopup(this);
std::map<QAction*, mitk::SliceNavigationController*>::const_iterator it;
for(it = ACTION_TO_SLICEDIMENSION.begin(); it != ACTION_TO_SLICEDIMENSION.end(); it++)
orientationPopup.addAction(it->first);
connect( &orientationPopup, SIGNAL(triggered(QAction*)), this, SLOT(OnAcceptAllPopupActivated(QAction*)) );
orientationPopup.exec( QCursor::pos() );
}
void QmitkSlicesInterpolator::OnAccept3DInterpolationClicked()
{
if (m_InterpolatedSurfaceNode.IsNotNull() && m_InterpolatedSurfaceNode->GetData())
{
mitk::SurfaceToImageFilter::Pointer s2iFilter = mitk::SurfaceToImageFilter::New();
s2iFilter->MakeOutputBinaryOn();
s2iFilter->SetInput(dynamic_cast<mitk::Surface*>(m_InterpolatedSurfaceNode->GetData()));
// check if ToolManager holds valid ReferenceData
if (m_ToolManager->GetReferenceData(0) == NULL || m_ToolManager->GetWorkingData(0) == NULL)
{
return;
}
s2iFilter->SetImage(dynamic_cast<mitk::Image*>(m_ToolManager->GetReferenceData(0)->GetData()));
s2iFilter->Update();
mitk::DataNode* segmentationNode = m_ToolManager->GetWorkingData(0);
segmentationNode->SetData(s2iFilter->GetOutput());
m_CmbInterpolation->setCurrentIndex(0);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
this->Show3DInterpolationResult(false);
}
}
void QmitkSlicesInterpolator::OnAcceptAllPopupActivated(QAction* action)
{
try
{
std::map<QAction*, mitk::SliceNavigationController*>::const_iterator iter = ACTION_TO_SLICEDIMENSION.find( action );
if (iter != ACTION_TO_SLICEDIMENSION.end())
{
mitk::SliceNavigationController* slicer = iter->second;
AcceptAllInterpolations( slicer );
}
}
catch(...)
{
/* Showing message box with possible memory error */
QMessageBox errorInfo;
errorInfo.setWindowTitle("Interpolation Process");
errorInfo.setIcon(QMessageBox::Critical);
errorInfo.setText("An error occurred during interpolation. Possible cause: Not enough memory!");
errorInfo.exec();
//additional error message on std::cerr
std::cerr << "Ill construction in " __FILE__ " l. " << __LINE__ << std::endl;
}
}
void QmitkSlicesInterpolator::OnInterpolationActivated(bool on)
{
m_2DInterpolationEnabled = on;
try
{
if ( m_DataStorage.IsNotNull() )
{
if (on && !m_DataStorage->Exists(m_FeedbackNode))
{
m_DataStorage->Add( m_FeedbackNode );
}
}
}
catch(...)
{
// don't care (double add/remove)
}
if (m_ToolManager)
{
mitk::DataNode* workingNode = m_ToolManager->GetWorkingData(0);
mitk::DataNode* referenceNode = m_ToolManager->GetReferenceData(0);
QWidget::setEnabled( workingNode != NULL );
m_BtnApply2D->setEnabled( on );
m_FeedbackNode->SetVisibility( on );
if (!on)
{
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
return;
}
if (workingNode)
{
mitk::Image* segmentation = dynamic_cast<mitk::Image*>(workingNode->GetData());
if (segmentation)
{
m_Interpolator->SetSegmentationVolume( segmentation );
if (referenceNode)
{
mitk::Image* referenceImage = dynamic_cast<mitk::Image*>(referenceNode->GetData());
m_Interpolator->SetReferenceVolume( referenceImage ); // may be NULL
}
}
}
}
UpdateVisibleSuggestion();
}
void QmitkSlicesInterpolator::Run3DInterpolation()
{
m_SurfaceInterpolator->Interpolate();
}
void QmitkSlicesInterpolator::StartUpdateInterpolationTimer()
{
m_Timer->start(500);
}
void QmitkSlicesInterpolator::StopUpdateInterpolationTimer()
{
m_Timer->stop();
m_InterpolatedSurfaceNode->SetProperty("color", mitk::ColorProperty::New(255.0,255.0,0.0));
mitk::RenderingManager::GetInstance()->RequestUpdate(mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))->GetRenderWindow());
}
void QmitkSlicesInterpolator::ChangeSurfaceColor()
{
float currentColor[3];
m_InterpolatedSurfaceNode->GetColor(currentColor);
float yellow[3] = {255.0,255.0,0.0};
if( currentColor[2] == yellow[2])
{
m_InterpolatedSurfaceNode->SetProperty("color", mitk::ColorProperty::New(255.0,255.0,255.0));
}
else
{
m_InterpolatedSurfaceNode->SetProperty("color", mitk::ColorProperty::New(yellow));
}
m_InterpolatedSurfaceNode->Update();
mitk::RenderingManager::GetInstance()->RequestUpdate(mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))->GetRenderWindow());
}
void QmitkSlicesInterpolator::On3DInterpolationActivated(bool on)
{
m_3DInterpolationEnabled = on;
this->CheckSupportedImageDimension();
try
{
if ( m_DataStorage.IsNotNull() && m_ToolManager && m_3DInterpolationEnabled)
{
mitk::DataNode* workingNode = m_ToolManager->GetWorkingData(0);
if (workingNode)
{
bool isInterpolationResult(false);
workingNode->GetBoolProperty("3DInterpolationResult",isInterpolationResult);
if ((workingNode->IsVisible(mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget3")))) &&
!isInterpolationResult && m_3DInterpolationEnabled)
{
int ret = QMessageBox::Yes;
if (m_SurfaceInterpolator->EstimatePortionOfNeededMemory() > 0.5)
{
QMessageBox msgBox;
msgBox.setText("Due to short handed system memory the 3D interpolation may be very slow!");
msgBox.setInformativeText("Are you sure you want to activate the 3D interpolation?");
msgBox.setStandardButtons(QMessageBox::No | QMessageBox::Yes);
ret = msgBox.exec();
}
if (m_Watcher.isRunning())
m_Watcher.waitForFinished();
if (ret == QMessageBox::Yes)
{
m_Future = QtConcurrent::run(this, &QmitkSlicesInterpolator::Run3DInterpolation);
m_Watcher.setFuture(m_Future);
}
else
{
m_CmbInterpolation->setCurrentIndex(0);
}
}
else if (!m_3DInterpolationEnabled)
{
this->Show3DInterpolationResult(false);
m_BtnApply3D->setEnabled(m_3DInterpolationEnabled);
}
}
else
{
QWidget::setEnabled( false );
m_ChkShowPositionNodes->setEnabled(m_3DInterpolationEnabled);
}
}
if (!m_3DInterpolationEnabled)
{
this->Show3DInterpolationResult(false);
m_BtnApply3D->setEnabled(m_3DInterpolationEnabled);
}
}
catch(...)
{
MITK_ERROR<<"Error with 3D surface interpolation!";
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkSlicesInterpolator::EnableInterpolation(bool on)
{
// only to be called from the outside world
// just a redirection to OnInterpolationActivated
OnInterpolationActivated(on);
}
void QmitkSlicesInterpolator::Enable3DInterpolation(bool on)
{
// only to be called from the outside world
// just a redirection to OnInterpolationActivated
On3DInterpolationActivated(on);
}
void QmitkSlicesInterpolator::UpdateVisibleSuggestion()
{
if (m_2DInterpolationEnabled && m_LastSNC)
{
// determine which one is the current view, try to do an initial interpolation
mitk::BaseRenderer* renderer = m_LastSNC->GetRenderer();
if (renderer && renderer->GetMapperID() == mitk::BaseRenderer::Standard2D)
{
const mitk::TimeGeometry* timeGeometry = dynamic_cast<const mitk::TimeGeometry*>( renderer->GetWorldGeometry() );
if (timeGeometry)
{
mitk::SliceNavigationController::GeometrySliceEvent event( const_cast<mitk::TimeGeometry*>(timeGeometry), renderer->GetSlice() );
TranslateAndInterpolateChangedSlice(event, m_LastSNC);
}
}
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkSlicesInterpolator::OnInterpolationInfoChanged(const itk::EventObject& /*e*/)
{
// something (e.g. undo) changed the interpolation info, we should refresh our display
UpdateVisibleSuggestion();
}
void QmitkSlicesInterpolator::OnSurfaceInterpolationInfoChanged(const itk::EventObject& /*e*/)
{
if(m_3DInterpolationEnabled)
{
if (m_Watcher.isRunning())
m_Watcher.waitForFinished();
m_Future = QtConcurrent::run(this, &QmitkSlicesInterpolator::Run3DInterpolation);
m_Watcher.setFuture(m_Future);
}
}
void QmitkSlicesInterpolator:: SetCurrentContourListID()
{
// New ContourList = hide current interpolation
Show3DInterpolationResult(false);
if ( m_DataStorage.IsNotNull() && m_ToolManager && m_LastSNC )
{
mitk::DataNode* workingNode = m_ToolManager->GetWorkingData(0);
if (workingNode)
{
bool isInterpolationResult(false);
workingNode->GetBoolProperty("3DInterpolationResult",isInterpolationResult);
bool isVisible (workingNode->IsVisible(m_LastSNC->GetRenderer()));
if (isVisible && !isInterpolationResult)
{
QWidget::setEnabled( true );
//TODO Aufruf hier pruefen!
mitk::Vector3D spacing = workingNode->GetData()->GetGeometry( m_LastSNC->GetTime()->GetPos() )->GetSpacing();
double minSpacing (100);
double maxSpacing (0);
for (int i =0; i < 3; i++)
{
if (spacing[i] < minSpacing)
{
minSpacing = spacing[i];
}
else if (spacing[i] > maxSpacing)
{
maxSpacing = spacing[i];
}
}
m_SurfaceInterpolator->SetSegmentationImage(dynamic_cast<mitk::Image*>(workingNode->GetData()));
m_SurfaceInterpolator->SetMaxSpacing(maxSpacing);
m_SurfaceInterpolator->SetMinSpacing(minSpacing);
m_SurfaceInterpolator->SetDistanceImageVolume(50000);
mitk::Image* segmentationImage = dynamic_cast<mitk::Image*>(workingNode->GetData());
if (segmentationImage->GetDimension() == 3)
m_SurfaceInterpolator->SetCurrentSegmentationInterpolationList(segmentationImage);
else
MITK_INFO<<"3D Interpolation is only supported for 3D images at the moment!";
if (m_3DInterpolationEnabled)
{
if (m_Watcher.isRunning())
m_Watcher.waitForFinished();
m_Future = QtConcurrent::run(this, &QmitkSlicesInterpolator::Run3DInterpolation);
m_Watcher.setFuture(m_Future);
}
}
}
else
{
QWidget::setEnabled(false);
}
}
}
void QmitkSlicesInterpolator::Show3DInterpolationResult(bool status)
{
if (m_InterpolatedSurfaceNode.IsNotNull())
m_InterpolatedSurfaceNode->SetVisibility(status);
if (m_3DContourNode.IsNotNull())
m_3DContourNode->SetVisibility(status, mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4")));
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkSlicesInterpolator::CheckSupportedImageDimension()
{
if (m_3DInterpolationEnabled && m_Segmentation->GetDimension() != 3)
{
QMessageBox info;
info.setWindowTitle("3D Interpolation Process");
info.setIcon(QMessageBox::Information);
info.setText("3D Interpolation is only supported for 3D images at the moment!");
info.exec();
m_CmbInterpolation->setCurrentIndex(0);
}
}
void QmitkSlicesInterpolator::OnSliceNavigationControllerDeleted(const itk::Object *sender, const itk::EventObject& /*e*/)
{
//Don't know how to avoid const_cast here?!
mitk::SliceNavigationController* slicer = dynamic_cast<mitk::SliceNavigationController*>(const_cast<itk::Object*>(sender));
if (slicer)
{
m_ControllerToTimeObserverTag.remove(slicer);
m_ControllerToSliceObserverTag.remove(slicer);
m_ControllerToDeleteObserverTag.remove(slicer);
}
}
diff --git a/Modules/USUI/Qmitk/QmitkUSAbstractCustomWidget.cpp b/Modules/USUI/Qmitk/QmitkUSAbstractCustomWidget.cpp
index de49a92b0f..43ad2a7c93 100644
--- a/Modules/USUI/Qmitk/QmitkUSAbstractCustomWidget.cpp
+++ b/Modules/USUI/Qmitk/QmitkUSAbstractCustomWidget.cpp
@@ -1,79 +1,79 @@
/*===================================================================
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 "QmitkUSAbstractCustomWidget.h"
#include <usPrototypeServiceFactory.h>
#include <usModuleContext.h>
std::string QmitkUSAbstractCustomWidget::US_DEVICE_PROPKEY_CLASS()
{
static std::string s = "ork.mitk.services.UltrasoundCustomWidget.deviceClass";
return s;
}
QmitkUSAbstractCustomWidget::QmitkUSAbstractCustomWidget(QWidget* parent)
: QWidget(parent), m_PrototypeServiceFactory(0), m_IsClonedForQt(false)
{
}
QmitkUSAbstractCustomWidget::~QmitkUSAbstractCustomWidget()
{
delete m_PrototypeServiceFactory;
}
void QmitkUSAbstractCustomWidget::SetDevice(mitk::USDevice::Pointer device)
{
m_Device = device;
if ( device ) { this->OnDeviceSet(); }
}
mitk::USDevice::Pointer QmitkUSAbstractCustomWidget::GetDevice() const
{
return m_Device;
}
QmitkUSAbstractCustomWidget* QmitkUSAbstractCustomWidget::CloneForQt(QWidget* parent) const
{
QmitkUSAbstractCustomWidget* clonedWidget = this->Clone(parent);
clonedWidget->Initialize(); // initialize the Qt stuff of the widget
clonedWidget->m_IsClonedForQt = true; // set flag that this object was really cloned
return clonedWidget;
}
us::ServiceProperties QmitkUSAbstractCustomWidget::GetServiceProperties() const
{
us::ServiceProperties result;
result[QmitkUSAbstractCustomWidget::US_DEVICE_PROPKEY_CLASS()] = this->GetDeviceClass();
return result;
}
void QmitkUSAbstractCustomWidget::showEvent ( QShowEvent * event )
{
// using object from micro service directly in Qt without cloning it first
// can cause problems when Qt deletes this object -> throw an exception to
// show that object should be cloned before
if ( ! m_IsClonedForQt )
{
MITK_ERROR << "Object wasn't cloned with CloneForQt() before using as QWidget.";
mitkThrow() << "Object wasn't cloned with CloneForQt() before using as QWidget.";
}
QWidget::showEvent(event);
-}
\ No newline at end of file
+}
diff --git a/Modules/USUI/Qmitk/QmitkUSControlsCustomVideoDeviceWidget.cpp b/Modules/USUI/Qmitk/QmitkUSControlsCustomVideoDeviceWidget.cpp
index 18cbbb1913..2990ec6359 100644
--- a/Modules/USUI/Qmitk/QmitkUSControlsCustomVideoDeviceWidget.cpp
+++ b/Modules/USUI/Qmitk/QmitkUSControlsCustomVideoDeviceWidget.cpp
@@ -1,123 +1,123 @@
/*===================================================================
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 "QmitkUSControlsCustomVideoDeviceWidget.h"
#include "ui_QmitkUSControlsCustomVideoDeviceWidget.h"
#include <QMessageBox>
#include <mitkException.h>
QmitkUSControlsCustomVideoDeviceWidget::QmitkUSControlsCustomVideoDeviceWidget(QWidget *parent)
: QmitkUSAbstractCustomWidget(parent), ui(new Ui::QmitkUSControlsCustomVideoDeviceWidget)
{
m_Cropping.left = 0;
m_Cropping.top = 0;
m_Cropping.right = 0;
m_Cropping.bottom = 0;
}
QmitkUSControlsCustomVideoDeviceWidget::~QmitkUSControlsCustomVideoDeviceWidget()
{
delete ui;
}
std::string QmitkUSControlsCustomVideoDeviceWidget::GetDeviceClass() const
{
return mitk::USVideoDevice::GetDeviceClassStatic();
}
QmitkUSAbstractCustomWidget* QmitkUSControlsCustomVideoDeviceWidget::Clone(QWidget* parent) const
{
QmitkUSAbstractCustomWidget* clonedWidget = new QmitkUSControlsCustomVideoDeviceWidget(parent);
clonedWidget->SetDevice(this->GetDevice());
return clonedWidget;
}
void QmitkUSControlsCustomVideoDeviceWidget::OnDeviceSet()
{
m_ControlInterface = dynamic_cast<mitk::USVideoDeviceCustomControls*>
(this->GetDevice()->GetControlInterfaceCustom().GetPointer());
if ( m_ControlInterface.IsNotNull() )
{
mitk::USImageVideoSource::USImageCropping cropping = m_ControlInterface->GetCropArea();
ui->crop_left->setValue(cropping.left);
ui->crop_right->setValue(cropping.right);
ui->crop_bot->setValue(cropping.bottom);
ui->crop_top->setValue(cropping.top);
}
else
{
MITK_WARN("QmitkUSAbstractCustomWidget")("QmitkUSControlsCustomVideoDeviceWidget")
<< "Did not get a custom video device control interface.";
}
ui->crop_left->setEnabled(m_ControlInterface.IsNotNull());
ui->crop_right->setEnabled(m_ControlInterface.IsNotNull());
ui->crop_bot->setEnabled(m_ControlInterface.IsNotNull());
ui->crop_top->setEnabled(m_ControlInterface.IsNotNull());
}
void QmitkUSControlsCustomVideoDeviceWidget::Initialize()
{
ui->setupUi(this);
connect( ui->crop_left, SIGNAL(valueChanged(int)), this, SLOT(OnCropAreaChanged()) );
connect( ui->crop_right, SIGNAL(valueChanged(int)), this, SLOT(OnCropAreaChanged()) );
connect( ui->crop_top, SIGNAL(valueChanged(int)), this, SLOT(OnCropAreaChanged()) );
connect( ui->crop_bot, SIGNAL(valueChanged(int)), this, SLOT(OnCropAreaChanged()) );
}
void QmitkUSControlsCustomVideoDeviceWidget::OnCropAreaChanged()
{
if ( m_ControlInterface.IsNull() ) { return; }
mitk::USImageVideoSource::USImageCropping cropping;
cropping.left = ui->crop_left->value();
cropping.top = ui->crop_top->value();
cropping.right = ui->crop_right->value();
cropping.bottom = ui->crop_bot->value();
try
{
m_ControlInterface->SetCropArea(cropping);
m_Cropping = cropping;
}
catch (mitk::Exception e)
{
m_ControlInterface->SetCropArea(m_Cropping); // reset to last valid crop
//reset values
BlockSignalAndSetValue(ui->crop_left, m_Cropping.left);
BlockSignalAndSetValue(ui->crop_right, m_Cropping.right);
BlockSignalAndSetValue(ui->crop_top, m_Cropping.top);
BlockSignalAndSetValue(ui->crop_bot, m_Cropping.bottom);
// inform user
QMessageBox msgBox;
msgBox.setInformativeText("The crop area you specified is invalid.\nPlease make sure that no more pixels are cropped than are available.");
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.exec();
MITK_WARN << "User tried to crop beyond limits of the image";
}
}
void QmitkUSControlsCustomVideoDeviceWidget::BlockSignalAndSetValue(QSpinBox* target, int value)
{
bool oldState = target->blockSignals(true);
target->setValue(value);
target->blockSignals(oldState);
-}
\ No newline at end of file
+}
diff --git a/Modules/USUI/mitkUSUIActivator.cpp b/Modules/USUI/mitkUSUIActivator.cpp
index b24668ccc0..ca510835fd 100644
--- a/Modules/USUI/mitkUSUIActivator.cpp
+++ b/Modules/USUI/mitkUSUIActivator.cpp
@@ -1,64 +1,64 @@
/*===================================================================
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 "mitkUSUIActivator.h"
#include "mitkUSUICustomWidgetFactory.h"
#include "QmitkUSControlsCustomVideoDeviceWidget.h"
mitk::USUIActivator::USUIActivator()
: m_CustomWidgetFactory(0), m_CustomVideoDeviceWidget(0)
{
}
mitk::USUIActivator::~USUIActivator()
{
delete m_CustomWidgetFactory;
delete m_CustomVideoDeviceWidget;
if ( m_ServiceRegistration ) { m_ServiceRegistration.Unregister(); }
}
void mitk::USUIActivator::Load(us::ModuleContext* context)
{
// create a custom video device widget, which will be used as
// a prototype for the custom widget factory
if ( ! m_CustomVideoDeviceWidget )
{
m_CustomVideoDeviceWidget = new QmitkUSControlsCustomVideoDeviceWidget();
}
// create a factory for custom widgets, using the video device
// widget as a prototype
if ( ! m_CustomWidgetFactory )
{
m_CustomWidgetFactory = new mitk::USUICustomWidgetFactory(m_CustomVideoDeviceWidget);
}
// register the custom widget factory as a microservice
m_ServiceRegistration = m_CustomWidgetFactory->RegisterService(context);
}
void mitk::USUIActivator::Unload(us::ModuleContext* /*context*/)
{
m_ServiceRegistration.Unregister();
m_ServiceRegistration = 0;
delete m_CustomWidgetFactory;
m_CustomWidgetFactory = 0;
delete m_CustomVideoDeviceWidget;
m_CustomVideoDeviceWidget = 0;
-}
\ No newline at end of file
+}
diff --git a/Modules/USUI/mitkUSUIActivator.h b/Modules/USUI/mitkUSUIActivator.h
index fdafa04987..1b21583cac 100644
--- a/Modules/USUI/mitkUSUIActivator.h
+++ b/Modules/USUI/mitkUSUIActivator.h
@@ -1,65 +1,65 @@
/*===================================================================
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 __mitkUSUIActivator_h
#define __mitkUSUIActivator_h
#include "QmitkUSAbstractCustomWidget.h"
// Microservices
#include <usModuleContext.h>
#include <usModuleActivator.h>
class QmitkUSControlsCustomVideoDeviceWidget;
namespace mitk
{
class USUICustomWidgetFactory;
/**
* \brief Module activator for the USUI module.
* Registers custom widget for mitk::USVideoDevice as microservice.
*/
class USUIActivator : public us::ModuleActivator {
public:
USUIActivator();
virtual ~USUIActivator();
/**
* Custom video device widget is registered as a micro service on module
* load. A plugin can get this widget then when using a
* mitk::USVideoDevice.
*/
void Load(us::ModuleContext* context);
/**
* Custom video device widget is deregistered from micro service on module
* unload.
*/
void Unload(us::ModuleContext* context);
protected:
us::ServiceRegistration<QmitkUSAbstractCustomWidget> m_ServiceRegistration;
USUICustomWidgetFactory* m_CustomWidgetFactory;
QmitkUSControlsCustomVideoDeviceWidget* m_CustomVideoDeviceWidget;
};
} // namespace mitk
US_EXPORT_MODULE_ACTIVATOR(MitkUSUI, mitk::USUIActivator)
-#endif // __mitkUSUIActivator_h
\ No newline at end of file
+#endif // __mitkUSUIActivator_h
diff --git a/Modules/USUI/mitkUSUICustomWidgetFactory.cpp b/Modules/USUI/mitkUSUICustomWidgetFactory.cpp
index 41435a6965..4067fac200 100644
--- a/Modules/USUI/mitkUSUICustomWidgetFactory.cpp
+++ b/Modules/USUI/mitkUSUICustomWidgetFactory.cpp
@@ -1,43 +1,43 @@
/*===================================================================
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 "mitkUSUICustomWidgetFactory.h"
#include "QmitkUSAbstractCustomWidget.h"
#include <usModuleContext.h>
mitk::USUICustomWidgetFactory::USUICustomWidgetFactory(QmitkUSAbstractCustomWidget* prototype)
: m_Prototype(prototype)
{
}
us::ServiceRegistration<QmitkUSAbstractCustomWidget> mitk::USUICustomWidgetFactory::RegisterService(us::ModuleContext* context)
{
return context->RegisterService<QmitkUSAbstractCustomWidget>(m_Prototype, m_Prototype->GetServiceProperties());
}
us::InterfaceMap mitk::USUICustomWidgetFactory::GetService(us::Module* /*module*/, const us::ServiceRegistrationBase& /*registration*/)
{
// clone the prototype for returning a uniqe instance
return us::MakeInterfaceMap<QmitkUSAbstractCustomWidget>(m_Prototype->Clone());
}
void mitk::USUICustomWidgetFactory::UngetService(us::Module*, const us::ServiceRegistrationBase&, const us::InterfaceMap& service)
{
// just delete the given service
delete us::ExtractInterface<QmitkUSAbstractCustomWidget>(service);
-}
\ No newline at end of file
+}
diff --git a/Modules/USUI/mitkUSUICustomWidgetFactory.h b/Modules/USUI/mitkUSUICustomWidgetFactory.h
index d5e743f2ec..768ba27938 100644
--- a/Modules/USUI/mitkUSUICustomWidgetFactory.h
+++ b/Modules/USUI/mitkUSUICustomWidgetFactory.h
@@ -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.
===================================================================*/
#ifndef MITKUSUICUSTOMWIDGETFACTORY_H
#define MITKUSUICUSTOMWIDGETFACTORY_H
#include <usPrototypeServiceFactory.h>
class QmitkUSAbstractCustomWidget;
namespace us {
class ModuleContext;
}
namespace mitk {
/**
* \brief Prototype service factory for creating unique instances of QmitUSAbstractCustomWidget.
*/
class USUICustomWidgetFactory : public us::PrototypeServiceFactory {
public:
USUICustomWidgetFactory(QmitkUSAbstractCustomWidget* prototype);
/**
* \brief Registers this factory in the given module context.
*/
us::ServiceRegistration<QmitkUSAbstractCustomWidget> RegisterService(us::ModuleContext* context);
us::InterfaceMap GetService(us::Module* /*module*/, const us::ServiceRegistrationBase& /*registration*/);
void UngetService(us::Module*, const us::ServiceRegistrationBase&, const us::InterfaceMap& service);
private:
QmitkUSAbstractCustomWidget* const m_Prototype;
};
} // namespace mitk
-#endif // MITKUSUICUSTOMWIDGETFACTORY_H
\ No newline at end of file
+#endif // MITKUSUICUSTOMWIDGETFACTORY_H
diff --git a/Plugins/org.mitk.gui.common/src/mitkIRenderingManager.cpp b/Plugins/org.mitk.gui.common/src/mitkIRenderingManager.cpp
index fd824d9dec..e61c6e070f 100644
--- a/Plugins/org.mitk.gui.common/src/mitkIRenderingManager.cpp
+++ b/Plugins/org.mitk.gui.common/src/mitkIRenderingManager.cpp
@@ -1,183 +1,183 @@
/*===================================================================
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 "mitkIRenderingManager.h"
namespace mitk {
struct RenderingManagerInterface : public IRenderingManager
{
RenderingManagerInterface(RenderingManager::Pointer manager)
: m_RM(manager)
{}
QList<vtkRenderWindow*> GetAllRegisteredVtkRenderWindows() const
{
RenderingManager::RenderWindowVector vec(m_RM->GetAllRegisteredRenderWindows());
QList<vtkRenderWindow*> result;
for (RenderingManager::RenderWindowVector::iterator i = vec.begin();
i != vec.end(); ++i)
{
result.append(*i);
}
return result;
}
void RequestUpdate( vtkRenderWindow *renderWindow )
{
m_RM->RequestUpdate(renderWindow);
}
void ForceImmediateUpdate( vtkRenderWindow *renderWindow )
{
m_RM->ForceImmediateUpdate(renderWindow);
}
void RequestUpdateAll( RenderingManager::RequestType type )
{
m_RM->RequestUpdateAll(type);
}
void ForceImmediateUpdateAll( RenderingManager::RequestType type )
{
m_RM->ForceImmediateUpdateAll(type);
}
- bool InitializeViews( const Geometry3D *geometry,
+ bool InitializeViews( const BaseGeometry *geometry,
RenderingManager::RequestType type = RenderingManager::REQUEST_UPDATE_ALL,
bool preserveRoughOrientationInWorldSpace = false )
{
return m_RM->InitializeViews( geometry, type, preserveRoughOrientationInWorldSpace);
}
bool InitializeViews( const TimeGeometry *geometry,
RenderingManager::RequestType type = RenderingManager::REQUEST_UPDATE_ALL,
bool preserveRoughOrientationInWorldSpace = false )
{
return m_RM->InitializeViews( geometry, type, preserveRoughOrientationInWorldSpace);
}
bool InitializeViews( RenderingManager::RequestType type )
{
return m_RM->InitializeViews(type);
}
- bool InitializeView( vtkRenderWindow *renderWindow, const Geometry3D *geometry,
+ bool InitializeView( vtkRenderWindow *renderWindow, const BaseGeometry *geometry,
bool initializeGlobalTimeSNC = false)
{
return m_RM->InitializeView(renderWindow, geometry, initializeGlobalTimeSNC);
}
bool InitializeView( vtkRenderWindow *renderWindow )
{
return m_RM->InitializeView(renderWindow);
}
const SliceNavigationController *GetTimeNavigationController() const
{
return m_RM->GetTimeNavigationController();
}
SliceNavigationController *GetTimeNavigationController()
{
return m_RM->GetTimeNavigationController();
}
bool IsRendering() const
{
return m_RM->IsRendering();
}
void AbortRendering()
{
m_RM->AbortRendering();
}
void SetLODIncreaseBlocked(bool blocked)
{
m_RM->SetLODIncreaseBlocked(blocked);
}
bool GetLODIncreaseBlocked() const
{
return m_RM->GetLODIncreaseBlocked();
}
void SetLODAbortMechanismEnabled(bool abort)
{
m_RM->SetLODAbortMechanismEnabled(abort);
}
bool GetLODAbortMechanismEnabled() const
{
return m_RM->GetLODAbortMechanismEnabled();
}
int GetNextLOD( BaseRenderer* renderer ) const
{
return m_RM->GetNextLOD(renderer);
}
void SetMaximumLOD( unsigned int max )
{
m_RM->SetMaximumLOD(max);
}
void SetShading( bool state, unsigned int lod )
{
m_RM->SetShading(state, lod);
}
bool GetShading( unsigned int lod )
{
return m_RM->GetShading(lod);
}
void SetClippingPlaneStatus( bool status )
{
m_RM->SetClippingPlaneStatus(status);
}
bool GetClippingPlaneStatus()
{
return m_RM->GetClippingPlaneStatus();
}
void SetShadingValues( float ambient, float diffuse,
float specular, float specpower )
{
m_RM->SetShadingValues(ambient, diffuse, specular, specpower);
}
QList<float> GetShadingValues() const
{
RenderingManager::FloatVector vec(m_RM->GetShadingValues());
QList<float> result;
for (RenderingManager::FloatVector::iterator i = vec.begin();
i != vec.end(); ++i)
{
result.push_back(*i);
}
return result;
}
const RenderingManager::Pointer m_RM;
};
IRenderingManager* MakeRenderingManagerInterface(RenderingManager::Pointer manager)
{
return new RenderingManagerInterface(manager);
}
}
\ No newline at end of file
diff --git a/Plugins/org.mitk.gui.common/src/mitkIRenderingManager.h b/Plugins/org.mitk.gui.common/src/mitkIRenderingManager.h
index a47e010ff3..26ab0d918b 100644
--- a/Plugins/org.mitk.gui.common/src/mitkIRenderingManager.h
+++ b/Plugins/org.mitk.gui.common/src/mitkIRenderingManager.h
@@ -1,148 +1,148 @@
/*===================================================================
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 MITKIRENDERINGMANAGER_H
#define MITKIRENDERINGMANAGER_H
#include <mitkRenderingManager.h>
#include <org_mitk_gui_common_Export.h>
#include <QList>
#include <QtPlugin>
namespace mitk {
/**
* \ingroup org_mitk_gui_common
*
* \brief An interface for accessing a mitk::RenderingManager instance.
*
* This interface acts as a wrapper to a mitk::RenderingManager instance, hiding some
* methods from the user.
*
* \see MakeRenderingManagerInterface
*/
struct IRenderingManager {
virtual ~IRenderingManager() {}
/** Get a list of all registered RenderWindows */
virtual QList<vtkRenderWindow*> GetAllRegisteredVtkRenderWindows() const = 0;
/**
* Requests an update for the specified RenderWindow, to be executed as
* soon as the main loop is ready for rendering.
*/
virtual void RequestUpdate( vtkRenderWindow *renderWindow ) = 0;
/** Immediately executes an update of the specified RenderWindow. */
virtual void ForceImmediateUpdate( vtkRenderWindow *renderWindow ) = 0;
/**
* Requests all currently registered RenderWindows to be updated.
* If only 2D or 3D windows should be updated, this can be specified
* via the parameter requestType.
*/
virtual void RequestUpdateAll( RenderingManager::RequestType type = RenderingManager::REQUEST_UPDATE_ALL ) = 0;
/**
* Immediately executes an update of all registered RenderWindows.
* If only 2D or 3D windows should be updated, this can be specified
* via the parameter requestType.
*/
virtual void ForceImmediateUpdateAll( RenderingManager::RequestType type = RenderingManager::REQUEST_UPDATE_ALL ) = 0;
/** Initializes the windows specified by requestType to the given geometry. */
- virtual bool InitializeViews( const Geometry3D *geometry,
+ virtual bool InitializeViews( const BaseGeometry *geometry,
RenderingManager::RequestType type = RenderingManager::REQUEST_UPDATE_ALL,
bool preserveRoughOrientationInWorldSpace = false ) = 0;
virtual bool InitializeViews( const TimeGeometry *geometry,
RenderingManager::RequestType type = RenderingManager::REQUEST_UPDATE_ALL,
bool preserveRoughOrientationInWorldSpace = false ) = 0;
/**
* Initializes the windows to the default viewing direction
* (geomtry information is NOT changed).
*/
virtual bool InitializeViews( RenderingManager::RequestType type = RenderingManager::REQUEST_UPDATE_ALL ) = 0;
/**
* Initializes the specified window to the given geometry. Set
* "initializeGlobalTimeSNC" to true in order to use this geometry as
* global TimeGeometry.
*/
- virtual bool InitializeView( vtkRenderWindow *renderWindow, const Geometry3D *geometry,
+ virtual bool InitializeView( vtkRenderWindow *renderWindow, const BaseGeometry *geometry,
bool initializeGlobalTimeSNC = false) = 0;
/**
* Initializes the specified window to the default viewing direction
* (geomtry information is NOT changed).
*/
virtual bool InitializeView( vtkRenderWindow *renderWindow ) = 0;
/** Gets the SliceNavigationController responsible for time-slicing. */
virtual const SliceNavigationController *GetTimeNavigationController() const = 0;
/** Gets the SliceNavigationController responsible for time-slicing. */
virtual SliceNavigationController *GetTimeNavigationController() = 0;
virtual bool IsRendering() const = 0;
virtual void AbortRendering() = 0;
/** En-/Disable LOD increase globally. */
virtual void SetLODIncreaseBlocked(bool blocked) = 0;
/** Get LOD blocked status. */
virtual bool GetLODIncreaseBlocked() const = 0;
/** En-/Disable LOD abort mechanism. */
virtual void SetLODAbortMechanismEnabled(bool abort) = 0;
/** Get LOD abort mechanism status. */
virtual bool GetLODAbortMechanismEnabled() const = 0;
virtual int GetNextLOD( BaseRenderer* renderer ) const = 0;
/** Set current LOD (NULL means all renderers)*/
virtual void SetMaximumLOD( unsigned int max ) = 0;
virtual void SetShading( bool state, unsigned int lod ) = 0;
virtual bool GetShading( unsigned int lod ) = 0;
virtual void SetClippingPlaneStatus( bool status ) = 0;
virtual bool GetClippingPlaneStatus() = 0;
virtual void SetShadingValues( float ambient, float diffuse,
float specular, float specpower ) = 0;
virtual QList<float> GetShadingValues() const = 0;
};
}
Q_DECLARE_INTERFACE(mitk::IRenderingManager, "org.mitk.ui.IRenderingManager")
namespace mitk {
/**
* Create a IRenderManager interface for a given RenderingManager. Ownership of the
* returned pointer is transferred to the caller of this function.
*
* \param manager The RenderingManager instance for which to create a interface.
* \return A pointer to the interface object. The caller is responsible for deleting the pointer.
*/
MITK_GUI_COMMON_PLUGIN IRenderingManager* MakeRenderingManagerInterface(RenderingManager::Pointer manager);
}
#endif // MITKIRENDERINGMANAGER_H
\ No newline at end of file
diff --git a/Plugins/org.mitk.gui.qt.datamanager/src/QmitkDataManagerView.cpp b/Plugins/org.mitk.gui.qt.datamanager/src/QmitkDataManagerView.cpp
index 30f41c4acd..f3f152e935 100644
--- a/Plugins/org.mitk.gui.qt.datamanager/src/QmitkDataManagerView.cpp
+++ b/Plugins/org.mitk.gui.qt.datamanager/src/QmitkDataManagerView.cpp
@@ -1,1026 +1,1026 @@
/*===================================================================
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 "QmitkDataManagerView.h"
#include <itkOtsuThresholdImageFilter.h>
//# Own Includes
//## mitk
#include "mitkDataStorageEditorInput.h"
#include "mitkIDataStorageReference.h"
#include "mitkNodePredicateDataType.h"
#include "mitkCoreObjectFactory.h"
#include "mitkDataNodeFactory.h"
#include "mitkColorProperty.h"
#include "mitkCommon.h"
#include "mitkNodePredicateData.h"
#include "mitkNodePredicateNot.h"
#include "mitkNodePredicateProperty.h"
#include "mitkEnumerationProperty.h"
#include "mitkLookupTableProperty.h"
#include "mitkProperties.h"
#include <mitkNodePredicateAnd.h>
#include <mitkITKImageImport.h>
#include <mitkIDataStorageService.h>
#include <mitkIRenderingManager.h>
#include <mitkImageCast.h>
//## Qmitk
#include <QmitkDnDFrameWidget.h>
#include <QmitkDataStorageTableModel.h>
#include <QmitkIOUtil.h>
#include <QmitkDataStorageTreeModel.h>
#include <QmitkCustomVariants.h>
#include "src/internal/QmitkNodeTableViewKeyFilter.h"
#include "src/internal/QmitkInfoDialog.h"
#include "src/internal/QmitkDataManagerItemDelegate.h"
//## Berry
#include <berryIEditorPart.h>
#include <berryIWorkbenchPage.h>
#include <berryIPreferencesService.h>
#include <berryPlatform.h>
#include <berryPlatformUI.h>
#include <berryIEditorRegistry.h>
//# Toolkit Includes
#include <QTableView>
#include <QGroupBox>
#include <QGridLayout>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QLabel>
#include <QListView>
#include <QMenu>
#include <QAction>
#include <QComboBox>
#include <QApplication>
#include <QCursor>
#include <QHeaderView>
#include <QTreeView>
#include <QWidgetAction>
#include <QSplitter>
#include <QPushButton>
#include <QMotifStyle>
#include <QFileDialog>
#include <QMessageBox>
#include <QToolBar>
#include <QKeyEvent>
#include <QColor>
#include <QColorDialog>
#include <QSizePolicy>
#include <QSignalMapper>
#include "mitkDataNodeObject.h"
#include "mitkIContextMenuAction.h"
#include "berryIExtensionPointService.h"
#include "mitkRenderingModeProperty.h"
const std::string QmitkDataManagerView::VIEW_ID = "org.mitk.views.datamanager";
QmitkDataManagerView::QmitkDataManagerView()
: m_GlobalReinitOnNodeDelete(true),
m_ItemDelegate(NULL)
{
}
QmitkDataManagerView::~QmitkDataManagerView()
{
//Remove all registered actions from each descriptor
for (std::vector< std::pair< QmitkNodeDescriptor*, QAction* > >::iterator it = m_DescriptorActionList.begin();it != m_DescriptorActionList.end(); it++)
{
// first== the NodeDescriptor; second== the registered QAction
(it->first)->RemoveAction(it->second);
}
}
void QmitkDataManagerView::CreateQtPartControl(QWidget* parent)
{
m_CurrentRowCount = 0;
m_Parent = parent;
//# Preferences
berry::IPreferencesService::Pointer prefService
= berry::Platform::GetServiceRegistry()
.GetServiceById<berry::IPreferencesService>(berry::IPreferencesService::ID);
berry::IBerryPreferences::Pointer prefs
= (prefService->GetSystemPreferences()->Node(VIEW_ID))
.Cast<berry::IBerryPreferences>();
assert( prefs );
prefs->OnChanged.AddListener( berry::MessageDelegate1<QmitkDataManagerView
, const berry::IBerryPreferences*>( this
, &QmitkDataManagerView::OnPreferencesChanged ) );
//# GUI
m_NodeTreeModel = new QmitkDataStorageTreeModel(this->GetDataStorage());
m_NodeTreeModel->setParent( parent );
m_NodeTreeModel->SetPlaceNewNodesOnTop(
prefs->GetBool("Place new nodes on top", true) );
m_NodeTreeModel->SetShowHelperObjects(
prefs->GetBool("Show helper objects", false) );
m_NodeTreeModel->SetShowNodesContainingNoData(
prefs->GetBool("Show nodes containing no data", false) );
m_SurfaceDecimation = prefs->GetBool("Use surface decimation", false);
//# Tree View (experimental)
m_NodeTreeView = new QTreeView;
m_NodeTreeView->setHeaderHidden(true);
m_NodeTreeView->setSelectionMode( QAbstractItemView::ExtendedSelection );
m_NodeTreeView->setSelectionBehavior( QAbstractItemView::SelectRows );
m_NodeTreeView->setAlternatingRowColors(true);
m_NodeTreeView->setDragEnabled(true);
m_NodeTreeView->setDropIndicatorShown(true);
m_NodeTreeView->setAcceptDrops(true);
m_NodeTreeView->setContextMenuPolicy(Qt::CustomContextMenu);
m_NodeTreeView->setModel(m_NodeTreeModel);
m_NodeTreeView->setTextElideMode(Qt::ElideMiddle);
m_NodeTreeView->installEventFilter(new QmitkNodeTableViewKeyFilter(this));
m_ItemDelegate = new QmitkDataManagerItemDelegate(m_NodeTreeView);
m_NodeTreeView->setItemDelegate(m_ItemDelegate);
QObject::connect( m_NodeTreeView, SIGNAL(customContextMenuRequested(const QPoint&))
, this, SLOT(NodeTableViewContextMenuRequested(const QPoint&)) );
QObject::connect( m_NodeTreeModel, SIGNAL(rowsInserted (const QModelIndex&, int, int))
, this, SLOT(NodeTreeViewRowsInserted ( const QModelIndex&, int, int )) );
QObject::connect( m_NodeTreeModel, SIGNAL(rowsRemoved (const QModelIndex&, int, int))
, this, SLOT(NodeTreeViewRowsRemoved( const QModelIndex&, int, int )) );
QObject::connect( m_NodeTreeView->selectionModel()
, SIGNAL( selectionChanged ( const QItemSelection &, const QItemSelection & ) )
, this
, SLOT( NodeSelectionChanged ( const QItemSelection &, const QItemSelection & ) ) );
//# m_NodeMenu
m_NodeMenu = new QMenu(m_NodeTreeView);
// # Actions
berry::IEditorRegistry* editorRegistry = berry::PlatformUI::GetWorkbench()->GetEditorRegistry();
std::list<berry::IEditorDescriptor::Pointer> editors = editorRegistry->GetEditors("*.mitk");
if (editors.size() > 1)
{
m_ShowInMapper = new QSignalMapper(this);
foreach(berry::IEditorDescriptor::Pointer descriptor, editors)
{
QAction* action = new QAction(QString::fromStdString(descriptor->GetLabel()), this);
m_ShowInActions << action;
m_ShowInMapper->connect(action, SIGNAL(triggered()), m_ShowInMapper, SLOT(map()));
m_ShowInMapper->setMapping(action, QString::fromStdString(descriptor->GetId()));
}
connect(m_ShowInMapper, SIGNAL(mapped(QString)), this, SLOT(ShowIn(QString)));
}
QmitkNodeDescriptor* unknownDataNodeDescriptor =
QmitkNodeDescriptorManager::GetInstance()->GetUnknownDataNodeDescriptor();
QmitkNodeDescriptor* imageDataNodeDescriptor =
QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("Image");
QmitkNodeDescriptor* surfaceDataNodeDescriptor =
QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("Surface");
QAction* globalReinitAction = new QAction(QIcon(":/org.mitk.gui.qt.datamanager/Refresh_48.png"), "Global Reinit", this);
QObject::connect( globalReinitAction, SIGNAL( triggered(bool) )
, this, SLOT( GlobalReinit(bool) ) );
unknownDataNodeDescriptor->AddAction(globalReinitAction);
m_DescriptorActionList.push_back(std::pair<QmitkNodeDescriptor*, QAction*>(unknownDataNodeDescriptor, globalReinitAction));
QAction* saveAction = new QAction(QIcon(":/org.mitk.gui.qt.datamanager/Save_48.png"), "Save...", this);
QObject::connect( saveAction, SIGNAL( triggered(bool) )
, this, SLOT( SaveSelectedNodes(bool) ) );
unknownDataNodeDescriptor->AddAction(saveAction);
m_DescriptorActionList.push_back(std::pair<QmitkNodeDescriptor*, QAction*>(unknownDataNodeDescriptor,saveAction));
QAction* removeAction = new QAction(QIcon(":/org.mitk.gui.qt.datamanager/Remove_48.png"), "Remove", this);
QObject::connect( removeAction, SIGNAL( triggered(bool) )
, this, SLOT( RemoveSelectedNodes(bool) ) );
unknownDataNodeDescriptor->AddAction(removeAction);
m_DescriptorActionList.push_back(std::pair<QmitkNodeDescriptor*, QAction*>(unknownDataNodeDescriptor,removeAction));
QAction* reinitAction = new QAction(QIcon(":/org.mitk.gui.qt.datamanager/Refresh_48.png"), "Reinit", this);
QObject::connect( reinitAction, SIGNAL( triggered(bool) )
, this, SLOT( ReinitSelectedNodes(bool) ) );
unknownDataNodeDescriptor->AddAction(reinitAction);
m_DescriptorActionList.push_back(std::pair<QmitkNodeDescriptor*, QAction*>(unknownDataNodeDescriptor,reinitAction));
// find contextMenuAction extension points and add them to the node descriptor
berry::IExtensionPointService::Pointer extensionPointService = berry::Platform::GetExtensionPointService();
berry::IConfigurationElement::vector cmActions(
extensionPointService->GetConfigurationElementsFor("org.mitk.gui.qt.datamanager.contextMenuActions") );
berry::IConfigurationElement::vector::iterator cmActionsIt;
std::string cmNodeDescriptorName;
std::string cmLabel;
std::string cmIcon;
std::string cmClass;
QmitkNodeDescriptor* tmpDescriptor;
QAction* contextMenuAction;
QVariant cmActionDataIt;
m_ConfElements.clear();
int i=1;
for (cmActionsIt = cmActions.begin()
; cmActionsIt != cmActions.end()
; ++cmActionsIt)
{
cmIcon.erase();
if((*cmActionsIt)->GetAttribute("nodeDescriptorName", cmNodeDescriptorName)
&& (*cmActionsIt)->GetAttribute("label", cmLabel)
&& (*cmActionsIt)->GetAttribute("class", cmClass))
{
(*cmActionsIt)->GetAttribute("icon", cmIcon);
// create context menu entry here
tmpDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor(QString::fromStdString(cmNodeDescriptorName));
if(!tmpDescriptor)
{
MITK_WARN << "cannot add action \"" << cmLabel << "\" because descriptor " << cmNodeDescriptorName << " does not exist";
continue;
}
contextMenuAction = new QAction( QString::fromStdString(cmLabel), parent);
tmpDescriptor->AddAction(contextMenuAction);
m_DescriptorActionList.push_back(std::pair<QmitkNodeDescriptor*, QAction*>(tmpDescriptor,contextMenuAction));
m_ConfElements[contextMenuAction] = *cmActionsIt;
cmActionDataIt.setValue<int>(i);
contextMenuAction->setData( cmActionDataIt );
connect( contextMenuAction, SIGNAL( triggered(bool) ) , this, SLOT( ContextMenuActionTriggered(bool) ) );
++i;
}
}
m_OpacitySlider = new QSlider;
m_OpacitySlider->setMinimum(0);
m_OpacitySlider->setMaximum(100);
m_OpacitySlider->setOrientation(Qt::Horizontal);
QObject::connect( m_OpacitySlider, SIGNAL( valueChanged(int) )
, this, SLOT( OpacityChanged(int) ) );
QLabel* _OpacityLabel = new QLabel("Opacity: ");
QHBoxLayout* _OpacityWidgetLayout = new QHBoxLayout;
_OpacityWidgetLayout->setContentsMargins(4,4,4,4);
_OpacityWidgetLayout->addWidget(_OpacityLabel);
_OpacityWidgetLayout->addWidget(m_OpacitySlider);
QWidget* _OpacityWidget = new QWidget;
_OpacityWidget->setLayout(_OpacityWidgetLayout);
QWidgetAction* opacityAction = new QWidgetAction(this);
opacityAction ->setDefaultWidget(_OpacityWidget);
QObject::connect( opacityAction , SIGNAL( changed() )
, this, SLOT( OpacityActionChanged() ) );
unknownDataNodeDescriptor->AddAction(opacityAction , false);
m_DescriptorActionList.push_back(std::pair<QmitkNodeDescriptor*, QAction*>(unknownDataNodeDescriptor,opacityAction));
m_ColorButton = new QPushButton;
m_ColorButton->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Minimum);
//m_ColorButton->setText("Change color");
QObject::connect( m_ColorButton, SIGNAL( clicked() )
, this, SLOT( ColorChanged() ) );
QLabel* _ColorLabel = new QLabel("Color: ");
_ColorLabel->setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum);
QHBoxLayout* _ColorWidgetLayout = new QHBoxLayout;
_ColorWidgetLayout->setContentsMargins(4,4,4,4);
_ColorWidgetLayout->addWidget(_ColorLabel);
_ColorWidgetLayout->addWidget(m_ColorButton);
QWidget* _ColorWidget = new QWidget;
_ColorWidget->setLayout(_ColorWidgetLayout);
QWidgetAction* colorAction = new QWidgetAction(this);
colorAction->setDefaultWidget(_ColorWidget);
QObject::connect( colorAction, SIGNAL( changed() )
, this, SLOT( ColorActionChanged() ) );
unknownDataNodeDescriptor->AddAction(colorAction, false);
m_DescriptorActionList.push_back(std::pair<QmitkNodeDescriptor*, QAction*>(unknownDataNodeDescriptor,colorAction));
m_TextureInterpolation = new QAction("Texture Interpolation", this);
m_TextureInterpolation->setCheckable ( true );
QObject::connect( m_TextureInterpolation, SIGNAL( changed() )
, this, SLOT( TextureInterpolationChanged() ) );
QObject::connect( m_TextureInterpolation, SIGNAL( toggled(bool) )
, this, SLOT( TextureInterpolationToggled(bool) ) );
imageDataNodeDescriptor->AddAction(m_TextureInterpolation, false);
m_DescriptorActionList.push_back(std::pair<QmitkNodeDescriptor*, QAction*>(imageDataNodeDescriptor,m_TextureInterpolation));
m_ColormapAction = new QAction("Colormap", this);
m_ColormapAction->setMenu(new QMenu);
QObject::connect( m_ColormapAction->menu(), SIGNAL( aboutToShow() )
, this, SLOT( ColormapMenuAboutToShow() ) );
imageDataNodeDescriptor->AddAction(m_ColormapAction, false);
m_DescriptorActionList.push_back(std::pair<QmitkNodeDescriptor*, QAction*>(imageDataNodeDescriptor, m_ColormapAction));
m_SurfaceRepresentation = new QAction("Surface Representation", this);
m_SurfaceRepresentation->setMenu(new QMenu);
QObject::connect( m_SurfaceRepresentation->menu(), SIGNAL( aboutToShow() )
, this, SLOT( SurfaceRepresentationMenuAboutToShow() ) );
surfaceDataNodeDescriptor->AddAction(m_SurfaceRepresentation, false);
m_DescriptorActionList.push_back(std::pair<QmitkNodeDescriptor*, QAction*>(surfaceDataNodeDescriptor, m_SurfaceRepresentation));
QAction* showOnlySelectedNodes
= new QAction(QIcon(":/org.mitk.gui.qt.datamanager/ShowSelectedNode_48.png")
, "Show only selected nodes", this);
QObject::connect( showOnlySelectedNodes, SIGNAL( triggered(bool) )
, this, SLOT( ShowOnlySelectedNodes(bool) ) );
unknownDataNodeDescriptor->AddAction(showOnlySelectedNodes);
m_DescriptorActionList.push_back(std::pair<QmitkNodeDescriptor*, QAction*>(unknownDataNodeDescriptor, showOnlySelectedNodes));
QAction* toggleSelectedVisibility
= new QAction(QIcon(":/org.mitk.gui.qt.datamanager/InvertShowSelectedNode_48.png")
, "Toggle visibility", this);
QObject::connect( toggleSelectedVisibility, SIGNAL( triggered(bool) )
, this, SLOT( ToggleVisibilityOfSelectedNodes(bool) ) );
unknownDataNodeDescriptor->AddAction(toggleSelectedVisibility);
m_DescriptorActionList.push_back(std::pair<QmitkNodeDescriptor*, QAction*>(unknownDataNodeDescriptor,toggleSelectedVisibility));
QAction* actionShowInfoDialog
= new QAction(QIcon(":/org.mitk.gui.qt.datamanager/ShowDataInfo_48.png")
, "Details...", this);
QObject::connect( actionShowInfoDialog, SIGNAL( triggered(bool) )
, this, SLOT( ShowInfoDialogForSelectedNodes(bool) ) );
unknownDataNodeDescriptor->AddAction(actionShowInfoDialog);
m_DescriptorActionList.push_back(std::pair<QmitkNodeDescriptor*, QAction*>(unknownDataNodeDescriptor,actionShowInfoDialog));
//obsolete...
//QAction* otsuFilterAction = new QAction("Apply Otsu Filter", this);
//QObject::connect( otsuFilterAction, SIGNAL( triggered(bool) )
// , this, SLOT( OtsuFilter(bool) ) );
// //Otsu filter does not work properly, remove it temporarily
// imageDataNodeDescriptor->AddAction(otsuFilterAction);
// m_DescriptorActionList.push_back(std::pair<QmitkNodeDescriptor*, QAction*>(imageDataNodeDescriptor,otsuFilterAction));
QGridLayout* _DndFrameWidgetLayout = new QGridLayout;
_DndFrameWidgetLayout->addWidget(m_NodeTreeView, 0, 0);
_DndFrameWidgetLayout->setContentsMargins(0,0,0,0);
m_DndFrameWidget = new QmitkDnDFrameWidget(m_Parent);
m_DndFrameWidget->setLayout(_DndFrameWidgetLayout);
QVBoxLayout* layout = new QVBoxLayout(parent);
layout->addWidget(m_DndFrameWidget);
layout->setContentsMargins(0,0,0,0);
m_Parent->setLayout(layout);
}
void QmitkDataManagerView::SetFocus()
{
}
void QmitkDataManagerView::ContextMenuActionTriggered( bool )
{
QAction* action = qobject_cast<QAction*> ( sender() );
std::map<QAction*, berry::IConfigurationElement::Pointer>::iterator it
= m_ConfElements.find( action );
if( it == m_ConfElements.end() )
{
MITK_WARN << "associated conf element for action " << action->text().toStdString() << " not found";
return;
}
berry::IConfigurationElement::Pointer confElem = it->second;
mitk::IContextMenuAction* contextMenuAction = confElem->CreateExecutableExtension<mitk::IContextMenuAction>("class");
std::string className;
std::string smoothed;
confElem->GetAttribute("class", className);
confElem->GetAttribute("smoothed", smoothed);
if(className == "QmitkCreatePolygonModelAction")
{
contextMenuAction->SetDataStorage(this->GetDataStorage());
if(smoothed == "false")
{
contextMenuAction->SetSmoothed(false);
}
else
{
contextMenuAction->SetSmoothed(true);
}
contextMenuAction->SetDecimated(m_SurfaceDecimation);
}
else if(className == "QmitkStatisticsAction")
{
contextMenuAction->SetFunctionality(this);
}
else if(className == "QmitkCreateSimulationAction")
{
contextMenuAction->SetDataStorage(this->GetDataStorage());
}
contextMenuAction->Run( this->GetCurrentSelection() ); // run the action
}
void QmitkDataManagerView::OnPreferencesChanged(const berry::IBerryPreferences* prefs)
{
if( m_NodeTreeModel->GetPlaceNewNodesOnTopFlag() != prefs->GetBool("Place new nodes on top", true) )
m_NodeTreeModel->SetPlaceNewNodesOnTop( !m_NodeTreeModel->GetPlaceNewNodesOnTopFlag() );
if( m_NodeTreeModel->GetShowHelperObjectsFlag()!= prefs->GetBool("Show helper objects", false) )
m_NodeTreeModel->SetShowHelperObjects( !m_NodeTreeModel->GetShowHelperObjectsFlag() );
if( m_NodeTreeModel->GetShowNodesContainingNoDataFlag()!= prefs->GetBool("Show nodes containing no data", false) )
m_NodeTreeModel->SetShowNodesContainingNoData( !m_NodeTreeModel->GetShowNodesContainingNoDataFlag() );
m_GlobalReinitOnNodeDelete = prefs->GetBool("Call global reinit if node is deleted", true);
m_NodeTreeView->expandAll();
m_SurfaceDecimation = prefs->GetBool("Use surface decimation", false);
this->GlobalReinit();
}
void QmitkDataManagerView::NodeTableViewContextMenuRequested( const QPoint & pos )
{
QModelIndex selected = m_NodeTreeView->indexAt ( pos );
mitk::DataNode::Pointer node = m_NodeTreeModel->GetNode(selected);
QList<mitk::DataNode::Pointer> selectedNodes = this->GetCurrentSelection();
if(!selectedNodes.isEmpty())
{
m_NodeMenu->clear();
QList<QAction*> actions;
if(selectedNodes.size() == 1 )
{
actions = QmitkNodeDescriptorManager::GetInstance()->GetActions(node);
for(QList<QAction*>::iterator it = actions.begin(); it != actions.end(); ++it)
{
(*it)->setData(QVariant::fromValue(node.GetPointer()));
}
}
else
actions = QmitkNodeDescriptorManager::GetInstance()->GetActions(selectedNodes);
if (!m_ShowInActions.isEmpty())
{
QMenu* showInMenu = m_NodeMenu->addMenu("Show In");
showInMenu->addActions(m_ShowInActions);
}
m_NodeMenu->addActions(actions);
m_NodeMenu->popup(QCursor::pos());
}
}
void QmitkDataManagerView::OpacityChanged(int value)
{
mitk::DataNode* node = m_NodeTreeModel->GetNode(m_NodeTreeView->selectionModel()->currentIndex());
if(node)
{
float opacity = static_cast<float>(value)/100.0f;
node->SetFloatProperty("opacity", opacity);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
void QmitkDataManagerView::OpacityActionChanged()
{
mitk::DataNode* node = m_NodeTreeModel->GetNode(m_NodeTreeView->selectionModel()->currentIndex());
if(node)
{
float opacity = 0.0;
if(node->GetFloatProperty("opacity", opacity))
{
m_OpacitySlider->setValue(static_cast<int>(opacity*100));
}
}
}
void QmitkDataManagerView::ColorChanged()
{
mitk::DataNode* node = m_NodeTreeModel->GetNode(m_NodeTreeView->selectionModel()->currentIndex());
if(node)
{
mitk::Color color;
mitk::ColorProperty::Pointer colorProp;
node->GetProperty(colorProp,"color");
if(colorProp.IsNull())
return;
color = colorProp->GetValue();
QColor initial(color.GetRed()*255,color.GetGreen()*255,color.GetBlue()*255);
QColor qcolor = QColorDialog::getColor(initial,0,QString("Change color"));
if (!qcolor.isValid())
return;
m_ColorButton->setAutoFillBackground(true);
node->SetProperty("color",mitk::ColorProperty::New(qcolor.red()/255.0,qcolor.green()/255.0,qcolor.blue()/255.0));
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
void QmitkDataManagerView::ColorActionChanged()
{
mitk::DataNode* node = m_NodeTreeModel->GetNode(m_NodeTreeView->selectionModel()->currentIndex());
if(node)
{
mitk::Color color;
mitk::ColorProperty::Pointer colorProp;
node->GetProperty(colorProp,"color");
if(colorProp.IsNull())
return;
color = colorProp->GetValue();
QString styleSheet = "background-color:rgb(";
styleSheet.append(QString::number(color[0]*255));
styleSheet.append(",");
styleSheet.append(QString::number(color[1]*255));
styleSheet.append(",");
styleSheet.append(QString::number(color[2]*255));
styleSheet.append(")");
m_ColorButton->setStyleSheet(styleSheet);
}
}
void QmitkDataManagerView::TextureInterpolationChanged()
{
mitk::DataNode* node = m_NodeTreeModel->GetNode(m_NodeTreeView->selectionModel()->currentIndex());
if(node)
{
bool textureInterpolation = false;
node->GetBoolProperty("texture interpolation", textureInterpolation);
m_TextureInterpolation->setChecked(textureInterpolation);
}
}
void QmitkDataManagerView::TextureInterpolationToggled( bool checked )
{
mitk::DataNode* node = m_NodeTreeModel->GetNode(m_NodeTreeView->selectionModel()->currentIndex());
if(node)
{
node->SetBoolProperty("texture interpolation", checked);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
void QmitkDataManagerView::ColormapActionToggled( bool /*checked*/ )
{
mitk::DataNode* node = m_NodeTreeModel->GetNode(m_NodeTreeView->selectionModel()->currentIndex());
if(!node)
return;
mitk::LookupTableProperty::Pointer lookupTableProperty =
dynamic_cast<mitk::LookupTableProperty*>(node->GetProperty("LookupTable"));
if (!lookupTableProperty)
return;
QAction* senderAction = qobject_cast<QAction*>(QObject::sender());
if(!senderAction)
return;
std::string activatedItem = senderAction->text().toStdString();
mitk::LookupTable::Pointer lookupTable = lookupTableProperty->GetValue();
if (!lookupTable)
return;
lookupTable->SetType(activatedItem);
lookupTableProperty->SetValue(lookupTable);
mitk::RenderingModeProperty::Pointer renderingMode =
dynamic_cast<mitk::RenderingModeProperty*>(node->GetProperty("Image Rendering.Mode"));
renderingMode->SetValue(mitk::RenderingModeProperty::LOOKUPTABLE_LEVELWINDOW_COLOR);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkDataManagerView::ColormapMenuAboutToShow()
{
mitk::DataNode* node = m_NodeTreeModel->GetNode(m_NodeTreeView->selectionModel()->currentIndex());
if(!node)
return;
mitk::LookupTableProperty::Pointer lookupTableProperty =
dynamic_cast<mitk::LookupTableProperty*>(node->GetProperty("LookupTable"));
if (!lookupTableProperty)
{
mitk::LookupTable::Pointer mitkLut = mitk::LookupTable::New();
lookupTableProperty = mitk::LookupTableProperty::New();
lookupTableProperty->SetLookupTable(mitkLut);
node->SetProperty("LookupTable", lookupTableProperty);
}
mitk::LookupTable::Pointer lookupTable = lookupTableProperty->GetValue();
if (!lookupTable)
return;
m_ColormapAction->menu()->clear();
QAction* tmp;
int i = 0;
std::string lutType = lookupTable->typenameList[i];
while (lutType != "END_OF_ARRAY")
{
tmp = m_ColormapAction->menu()->addAction(QString::fromStdString(lutType));
tmp->setCheckable(true);
if (lutType == lookupTable->GetActiveTypeAsString())
{
tmp->setChecked(true);
}
QObject::connect(tmp, SIGNAL(triggered(bool)), this, SLOT(ColormapActionToggled(bool)));
lutType = lookupTable->typenameList[++i];
}
}
void QmitkDataManagerView::SurfaceRepresentationMenuAboutToShow()
{
mitk::DataNode* node = m_NodeTreeModel->GetNode(m_NodeTreeView->selectionModel()->currentIndex());
if(!node)
return;
mitk::EnumerationProperty* representationProp =
dynamic_cast<mitk::EnumerationProperty*> (node->GetProperty("material.representation"));
if(!representationProp)
return;
// clear menu
m_SurfaceRepresentation->menu()->clear();
QAction* tmp;
// create menu entries
for(mitk::EnumerationProperty::EnumConstIterator it=representationProp->Begin(); it!=representationProp->End()
; it++)
{
tmp = m_SurfaceRepresentation->menu()->addAction(QString::fromStdString(it->second));
tmp->setCheckable(true);
if(it->second == representationProp->GetValueAsString())
{
tmp->setChecked(true);
}
QObject::connect( tmp, SIGNAL( triggered(bool) )
, this, SLOT( SurfaceRepresentationActionToggled(bool) ) );
}
}
void QmitkDataManagerView::SurfaceRepresentationActionToggled( bool /*checked*/ )
{
mitk::DataNode* node = m_NodeTreeModel->GetNode(m_NodeTreeView->selectionModel()->currentIndex());
if(!node)
return;
mitk::EnumerationProperty* representationProp =
dynamic_cast<mitk::EnumerationProperty*> (node->GetProperty("material.representation"));
if(!representationProp)
return;
QAction* senderAction = qobject_cast<QAction*> ( QObject::sender() );
if(!senderAction)
return;
std::string activatedItem = senderAction->text().toStdString();
if ( activatedItem != representationProp->GetValueAsString() )
{
if ( representationProp->IsValidEnumerationValue( activatedItem ) )
{
representationProp->SetValue( activatedItem );
representationProp->InvokeEvent( itk::ModifiedEvent() );
representationProp->Modified();
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
}
void QmitkDataManagerView::SaveSelectedNodes( bool )
{
QModelIndexList indexesOfSelectedRows = m_NodeTreeView->selectionModel()->selectedRows();
mitk::DataNode* node = 0;
unsigned int indexesOfSelectedRowsSize = indexesOfSelectedRows.size();
for (unsigned int i = 0; i<indexesOfSelectedRowsSize; ++i)
{
node = m_NodeTreeModel->GetNode(indexesOfSelectedRows.at(i));
// if node is not defined or if the node contains geometry data do not remove it
if ( node != 0 )
{
mitk::BaseData::Pointer data = node->GetData();
if (data.IsNotNull())
{
QString error;
try
{
QmitkIOUtil::SaveBaseDataWithDialog( data.GetPointer(), node->GetName().c_str(), m_Parent );
}
catch(std::exception& e)
{
error = e.what();
}
catch(...)
{
error = "Unknown error occured";
}
if( !error.isEmpty() )
QMessageBox::critical( m_Parent, "Error saving...", error );
}
}
}
}
void QmitkDataManagerView::ReinitSelectedNodes( bool )
{
mitk::IRenderWindowPart* renderWindow = this->GetRenderWindowPart();
if (renderWindow == NULL)
renderWindow = this->OpenRenderWindowPart(false);
QList<mitk::DataNode::Pointer> selectedNodes = this->GetCurrentSelection();
foreach(mitk::DataNode::Pointer node, selectedNodes)
{
mitk::BaseData::Pointer basedata = node->GetData();
if ( basedata.IsNotNull() &&
basedata->GetTimeGeometry()->IsValid() )
{
renderWindow->GetRenderingManager()->InitializeViews(
basedata->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true );
renderWindow->GetRenderingManager()->RequestUpdateAll();
}
}
}
void QmitkDataManagerView::RemoveSelectedNodes( bool )
{
QModelIndexList indexesOfSelectedRows = m_NodeTreeView->selectionModel()->selectedRows();
if(indexesOfSelectedRows.size() < 1)
{
return;
}
std::vector<mitk::DataNode*> selectedNodes;
mitk::DataNode* node = 0;
QString question = tr("Do you really want to remove ");
for (QModelIndexList::iterator it = indexesOfSelectedRows.begin()
; it != indexesOfSelectedRows.end(); it++)
{
node = m_NodeTreeModel->GetNode(*it);
// if node is not defined or if the node contains geometry data do not remove it
- if ( node != 0 /*& strcmp(node->GetData()->GetNameOfClass(), "Geometry2DData") != 0*/ )
+ if ( node != 0 /*& strcmp(node->GetData()->GetNameOfClass(), "PlaneGeometryData") != 0*/ )
{
selectedNodes.push_back(node);
question.append(QString::fromStdString(node->GetName()));
question.append(", ");
}
}
// remove the last two characters = ", "
question = question.remove(question.size()-2, 2);
question.append(" from data storage?");
QMessageBox::StandardButton answerButton = QMessageBox::question( m_Parent
, tr("DataManager")
, question
, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
if(answerButton == QMessageBox::Yes)
{
for (std::vector<mitk::DataNode*>::iterator it = selectedNodes.begin()
; it != selectedNodes.end(); it++)
{
node = *it;
this->GetDataStorage()->Remove(node);
if (m_GlobalReinitOnNodeDelete)
this->GlobalReinit(false);
}
}
}
void QmitkDataManagerView::MakeAllNodesInvisible( bool )
{
QList<mitk::DataNode::Pointer> nodes = m_NodeTreeModel->GetNodeSet();
foreach(mitk::DataNode::Pointer node, nodes)
{
node->SetVisibility(false);
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkDataManagerView::ShowOnlySelectedNodes( bool )
{
QList<mitk::DataNode::Pointer> selectedNodes = this->GetCurrentSelection();
QList<mitk::DataNode::Pointer> allNodes = m_NodeTreeModel->GetNodeSet();
foreach(mitk::DataNode::Pointer node, allNodes)
{
node->SetVisibility(selectedNodes.contains(node));
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkDataManagerView::ToggleVisibilityOfSelectedNodes( bool )
{
QList<mitk::DataNode::Pointer> selectedNodes = this->GetCurrentSelection();
bool isVisible = false;
foreach(mitk::DataNode::Pointer node, selectedNodes)
{
isVisible = false;
node->GetBoolProperty("visible", isVisible);
node->SetVisibility(!isVisible);
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkDataManagerView::ShowInfoDialogForSelectedNodes( bool )
{
QList<mitk::DataNode::Pointer> selectedNodes = this->GetCurrentSelection();
QmitkInfoDialog _QmitkInfoDialog(selectedNodes, this->m_Parent);
_QmitkInfoDialog.exec();
}
void QmitkDataManagerView::Load( bool )
{
QStringList fileNames = QFileDialog::getOpenFileNames(NULL, "Load data", "", mitk::CoreObjectFactory::GetInstance()->GetFileExtensions());
for ( QStringList::Iterator it = fileNames.begin(); it != fileNames.end(); ++it )
{
FileOpen((*it).toAscii(), 0);
}
}
void QmitkDataManagerView::FileOpen( const char * fileName, mitk::DataNode* parentNode )
{
mitk::DataNodeFactory::Pointer factory = mitk::DataNodeFactory::New();
try
{
factory->SetFileName( fileName );
QApplication::setOverrideCursor( QCursor(Qt::WaitCursor) );
factory->Update();
for ( unsigned int i = 0 ; i < factory->GetNumberOfOutputs( ); ++i )
{
mitk::DataNode::Pointer node = factory->GetOutput( i );
if ( ( node.IsNotNull() ) && ( node->GetData() != NULL ) )
{
this->GetDataStorage()->Add(node, parentNode);
mitk::BaseData::Pointer basedata = node->GetData();
mitk::RenderingManager::GetInstance()->InitializeViews(
basedata->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true );
//mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
}
catch ( itk::ExceptionObject & ex )
{
itkGenericOutputMacro( << "Exception during file open: " << ex );
}
QApplication::restoreOverrideCursor();
}
QItemSelectionModel *QmitkDataManagerView::GetDataNodeSelectionModel() const
{
return m_NodeTreeView->selectionModel();
}
void QmitkDataManagerView::GlobalReinit( bool )
{
mitk::IRenderWindowPart* renderWindow = this->GetRenderWindowPart();
if (renderWindow == NULL)
renderWindow = this->OpenRenderWindowPart(false);
// no render window available
if (renderWindow == NULL) return;
mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(this->GetDataStorage());
}
void QmitkDataManagerView::OtsuFilter( bool )
{
QList<mitk::DataNode::Pointer> selectedNodes = this->GetCurrentSelection();
mitk::Image::Pointer mitkImage = 0;
foreach(mitk::DataNode::Pointer node, selectedNodes)
{
mitkImage = dynamic_cast<mitk::Image*>( node->GetData() );
if(mitkImage.IsNull())
continue;
try
{
// get selected mitk image
const unsigned short dim = 3;
typedef short InputPixelType;
typedef unsigned char OutputPixelType;
typedef itk::Image< InputPixelType, dim > InputImageType;
typedef itk::Image< OutputPixelType, dim > OutputImageType;
typedef itk::OtsuThresholdImageFilter< InputImageType, OutputImageType > FilterType;
FilterType::Pointer filter = FilterType::New();
filter->SetOutsideValue( 1 );
filter->SetInsideValue( 0 );
InputImageType::Pointer itkImage;
mitk::CastToItkImage(mitkImage, itkImage);
filter->SetInput( itkImage );
filter->Update();
mitk::DataNode::Pointer resultNode = mitk::DataNode::New();
std::string nameOfResultImage = node->GetName();
nameOfResultImage.append("Otsu");
resultNode->SetProperty("name", mitk::StringProperty::New(nameOfResultImage) );
resultNode->SetProperty("binary", mitk::BoolProperty::New(true) );
resultNode->SetData( mitk::ImportItkImage(filter->GetOutput())->Clone());
this->GetDataStorage()->Add(resultNode, node);
}
catch( std::exception& err )
{
MITK_ERROR(this->GetClassName()) << err.what();
}
}
}
void QmitkDataManagerView::NodeTreeViewRowsRemoved (
const QModelIndex & /*parent*/, int /*start*/, int /*end*/ )
{
m_CurrentRowCount = m_NodeTreeModel->rowCount();
}
void QmitkDataManagerView::NodeTreeViewRowsInserted( const QModelIndex & parent, int, int )
{
m_NodeTreeView->setExpanded(parent, true);
// a new row was inserted
if( m_CurrentRowCount == 0 && m_NodeTreeModel->rowCount() == 1 )
{
this->OpenRenderWindowPart();
m_CurrentRowCount = m_NodeTreeModel->rowCount();
/*
std::vector<mitk::DataNode*> nodes = m_NodeTreeModel->GetNodeSet();
if(nodes.size() == 1)
{
QModelIndex treeIndex = m_NodeTreeModel->GetIndex(nodes.front());
m_NodeTreeView->selectionModel()->setCurrentIndex( treeIndex, QItemSelectionModel::ClearAndSelect );
}
*/
}
}
void QmitkDataManagerView::NodeSelectionChanged( const QItemSelection & /*selected*/, const QItemSelection & /*deselected*/ )
{
QList<mitk::DataNode::Pointer> nodes = m_NodeTreeModel->GetNodeSet();
foreach(mitk::DataNode::Pointer node, nodes)
{
if ( node.IsNotNull() )
node->SetBoolProperty("selected", false);
}
nodes.clear();
nodes = this->GetCurrentSelection();
foreach(mitk::DataNode::Pointer node, nodes)
{
if ( node.IsNotNull() )
node->SetBoolProperty("selected", true);
}
//changing the selection does NOT require any rendering processes!
//mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkDataManagerView::ShowIn(const QString &editorId)
{
berry::IWorkbenchPage::Pointer page = this->GetSite()->GetPage();
berry::IEditorInput::Pointer input(new mitk::DataStorageEditorInput(this->GetDataStorageReference()));
page->OpenEditor(input, editorId.toStdString(), false, berry::IWorkbenchPage::MATCH_ID);
}
mitk::IRenderWindowPart* QmitkDataManagerView::OpenRenderWindowPart(bool activatedEditor)
{
if (activatedEditor)
{
return this->GetRenderWindowPart(QmitkAbstractView::ACTIVATE | QmitkAbstractView::OPEN);
}
else
{
return this->GetRenderWindowPart(QmitkAbstractView::BRING_TO_FRONT | QmitkAbstractView::OPEN);
}
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkODFRenderWidget.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkODFRenderWidget.cpp
index d7594a6a69..58a3c17daa 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkODFRenderWidget.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkODFRenderWidget.cpp
@@ -1,125 +1,124 @@
/*===================================================================
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 "QmitkODFRenderWidget.h"
#include <mitkLookupTable.h>
#include <mitkLookupTableProperty.h>
#include <vtkSmartPointer.h>
#include <mitkPlaneGeometry.h>
-#include <mitkGeometry2D.h>
QmitkODFRenderWidget::QmitkODFRenderWidget(QWidget* parent, Qt::WindowFlags f): QWidget(parent, f)
{
//create Layouts
QmitkODFRenderWidgetLayout = new QHBoxLayout( this );
//Set Layout to widget
this->setLayout(QmitkODFRenderWidgetLayout);
//Create RenderWindow
m_RenderWindow = new QmitkRenderWindow(this, "odf render widget");
m_RenderWindow->setMaximumSize(300,300);
m_RenderWindow->GetRenderer()->SetMapperID( mitk::BaseRenderer::Standard3D );
//m_RenderWindow->SetLayoutIndex( 3 );
QmitkODFRenderWidgetLayout->addWidget( m_RenderWindow );
}
QmitkODFRenderWidget::~QmitkODFRenderWidget()
{
}
void QmitkODFRenderWidget::GenerateODF( itk::OrientationDistributionFunction<double, QBALL_ODFSIZE> odf )
{
try
{
m_Surface = mitk::Surface::New();
m_ds = mitk::StandaloneDataStorage::New();
m_Node = mitk::DataNode::New();
vtkPolyData* m_TemplateOdf = itk::OrientationDistributionFunction<float,QBALL_ODFSIZE>::GetBaseMesh();
vtkPolyData *polyData = vtkPolyData::New();
vtkPoints *points = vtkPoints::New();
vtkFloatArray *scalars = vtkFloatArray::New();
for (int i=0; i<QBALL_ODFSIZE; i++){
double p[3];
m_TemplateOdf->GetPoints()->GetPoint(i,p);
double val = odf[i];
p[0] *= val;
p[1] *= val;
p[2] *= val;
points->InsertPoint(i,p);
scalars->InsertTuple1(i, 1-val);
}
polyData->SetPoints(points);
vtkCellArray* polys = m_TemplateOdf->GetPolys();
polyData->SetPolys(polys);
polyData->GetPointData()->SetScalars(scalars);
polys->Delete();
scalars->Delete();
points->Delete();
m_Surface->SetVtkPolyData(polyData);
m_Node->SetData(m_Surface);
mitk::LookupTable::Pointer mitkLut = mitk::LookupTable::New();
// assign an empty vtk lookup table to the odf renderer, it is the same
// the ODF 2D Mapper has
vtkLookupTable *lut = vtkLookupTable::New();
mitkLut->SetVtkLookupTable( lut );
mitk::LookupTableProperty::Pointer mitkLutProp = mitk::LookupTableProperty::New();
mitkLutProp->SetLookupTable(mitkLut);
m_Node->SetProperty( "LookupTable", mitkLutProp );
m_Node->SetProperty("scalar visibility", mitk::BoolProperty::New(true));
m_Node->SetProperty("color mode", mitk::BoolProperty::New(true));
m_Node->SetProperty("material.specularCoefficient", mitk::FloatProperty::New(0.5));
m_ds->Add(m_Node);
m_RenderWindow->GetRenderer()->SetDataStorage( m_ds );
// adjust camera to current plane rotation
mitk::Geometry2D::ConstPointer worldGeometry = mitk::GlobalInteraction::GetInstance()->GetFocus()->GetCurrentWorldGeometry2D();
mitk::PlaneGeometry::ConstPointer worldPlaneGeometry = dynamic_cast<const mitk::PlaneGeometry*>( worldGeometry.GetPointer() );
mitk::Vector3D normal = worldPlaneGeometry->GetNormal();
mitk::Vector3D up = worldPlaneGeometry->GetAxisVector(1);
normal.Normalize();
up.Normalize();
vtkSmartPointer<vtkCamera> cam = vtkSmartPointer<vtkCamera>::New();
const double camPos[3] = {normal[0],normal[1],normal[2]};
const double camUp[3] = {up[0],up[1],up[2]};
cam->SetPosition(camPos);
cam->SetViewUp(camUp);
cam->SetParallelProjection(1);
m_RenderWindow->GetRenderer()->GetVtkRenderer()->SetActiveCamera(cam);
m_RenderWindow->update();
}
catch (...)
{
}
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkControlVisualizationPropertiesView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkControlVisualizationPropertiesView.cpp
index d376fd0fbe..c195ebae87 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkControlVisualizationPropertiesView.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkControlVisualizationPropertiesView.cpp
@@ -1,1856 +1,1856 @@
/*===================================================================
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 "QmitkControlVisualizationPropertiesView.h"
#include "mitkNodePredicateDataType.h"
#include "mitkDataNodeObject.h"
#include "mitkOdfNormalizationMethodProperty.h"
#include "mitkOdfScaleByProperty.h"
#include "mitkResliceMethodProperty.h"
#include "mitkRenderingManager.h"
#include "mitkTbssImage.h"
#include "mitkPlanarFigure.h"
#include "mitkFiberBundleX.h"
#include "QmitkDataStorageComboBox.h"
#include "QmitkStdMultiWidget.h"
#include "mitkFiberBundleInteractor.h"
#include "mitkPlanarFigureInteractor.h"
#include <mitkQBallImage.h>
#include <mitkTensorImage.h>
#include <mitkDiffusionImage.h>
#include <mitkConnectomicsNetwork.h>
#include "mitkGlobalInteraction.h"
#include "usModuleRegistry.h"
-#include "mitkGeometry2D.h"
+#include "mitkPlaneGeometry.h"
#include "berryIWorkbenchWindow.h"
#include "berryIWorkbenchPage.h"
#include "berryISelectionService.h"
#include "berryConstants.h"
#include "berryPlatformUI.h"
#include "itkRGBAPixel.h"
#include <itkTractDensityImageFilter.h>
#include "qwidgetaction.h"
#include "qcolordialog.h"
#include <itkMultiThreader.h>
#define ROUND(a) ((a)>0 ? (int)((a)+0.5) : -(int)(0.5-(a)))
static bool DetermineAffectedImageSlice( const mitk::Image* image, const mitk::PlaneGeometry* plane, int& affectedDimension, int& affectedSlice )
{
assert(image);
assert(plane);
// compare normal of plane to the three axis vectors of the image
mitk::Vector3D normal = plane->GetNormal();
mitk::Vector3D imageNormal0 = image->GetSlicedGeometry()->GetAxisVector(0);
mitk::Vector3D imageNormal1 = image->GetSlicedGeometry()->GetAxisVector(1);
mitk::Vector3D imageNormal2 = image->GetSlicedGeometry()->GetAxisVector(2);
normal.Normalize();
imageNormal0.Normalize();
imageNormal1.Normalize();
imageNormal2.Normalize();
imageNormal0.SetVnlVector( vnl_cross_3d<mitk::ScalarType>(normal.GetVnlVector(),imageNormal0.GetVnlVector()) );
imageNormal1.SetVnlVector( vnl_cross_3d<mitk::ScalarType>(normal.GetVnlVector(),imageNormal1.GetVnlVector()) );
imageNormal2.SetVnlVector( vnl_cross_3d<mitk::ScalarType>(normal.GetVnlVector(),imageNormal2.GetVnlVector()) );
double eps( 0.00001 );
// axial
if ( imageNormal2.GetNorm() <= eps )
{
affectedDimension = 2;
}
// sagittal
else if ( imageNormal1.GetNorm() <= eps )
{
affectedDimension = 1;
}
// frontal
else if ( imageNormal0.GetNorm() <= eps )
{
affectedDimension = 0;
}
else
{
affectedDimension = -1; // no idea
return false;
}
// determine slice number in image
- mitk::Geometry3D* imageGeometry = image->GetGeometry(0);
+ mitk::BaseGeometry* imageGeometry = image->GetGeometry(0);
mitk::Point3D testPoint = imageGeometry->GetCenter();
mitk::Point3D projectedPoint;
plane->Project( testPoint, projectedPoint );
mitk::Point3D indexPoint;
imageGeometry->WorldToIndex( projectedPoint, indexPoint );
affectedSlice = ROUND( indexPoint[affectedDimension] );
MITK_DEBUG << "indexPoint " << indexPoint << " affectedDimension " << affectedDimension << " affectedSlice " << affectedSlice;
// check if this index is still within the image
if ( affectedSlice < 0 || affectedSlice >= static_cast<int>(image->GetDimension(affectedDimension)) ) return false;
return true;
}
const std::string QmitkControlVisualizationPropertiesView::VIEW_ID = "org.mitk.views.controlvisualizationpropertiesview";
using namespace berry;
struct CvpSelListener : ISelectionListener
{
berryObjectMacro(CvpSelListener);
CvpSelListener(QmitkControlVisualizationPropertiesView* view)
{
m_View = view;
}
void ApplySettings(mitk::DataNode::Pointer node)
{
bool tex_int;
node->GetBoolProperty("texture interpolation", tex_int);
if(tex_int)
{
m_View->m_Controls->m_TextureIntON->setIcon(*m_View->m_IconTexON);
m_View->m_Controls->m_TextureIntON->setChecked(true);
m_View->m_TexIsOn = true;
}
else
{
m_View->m_Controls->m_TextureIntON->setIcon(*m_View->m_IconTexOFF);
m_View->m_Controls->m_TextureIntON->setChecked(false);
m_View->m_TexIsOn = false;
}
int val;
node->GetIntProperty("ShowMaxNumber", val);
m_View->m_Controls->m_ShowMaxNumber->setValue(val);
m_View->m_Controls->m_NormalizationDropdown->setCurrentIndex(dynamic_cast<mitk::EnumerationProperty*>(node->GetProperty("Normalization"))->GetValueAsId());
float fval;
node->GetFloatProperty("Scaling",fval);
m_View->m_Controls->m_ScalingFactor->setValue(fval);
m_View->m_Controls->m_AdditionalScaling->setCurrentIndex(dynamic_cast<mitk::EnumerationProperty*>(node->GetProperty("ScaleBy"))->GetValueAsId());
node->GetFloatProperty("IndexParam1",fval);
m_View->m_Controls->m_IndexParam1->setValue(fval);
node->GetFloatProperty("IndexParam2",fval);
m_View->m_Controls->m_IndexParam2->setValue(fval);
}
void DoSelectionChanged(ISelection::ConstPointer selection)
{
// save current selection in member variable
m_View->m_CurrentSelection = selection.Cast<const IStructuredSelection>();
m_View->m_Controls->m_VisibleOdfsON_T->setVisible(false);
m_View->m_Controls->m_VisibleOdfsON_S->setVisible(false);
m_View->m_Controls->m_VisibleOdfsON_C->setVisible(false);
m_View->m_Controls->m_TextureIntON->setVisible(false);
m_View->m_Controls->m_ImageControlsFrame->setVisible(false);
m_View->m_Controls->m_PlanarFigureControlsFrame->setVisible(false);
m_View->m_Controls->m_BundleControlsFrame->setVisible(false);
m_View->m_SelectedNode = 0;
if(m_View->m_CurrentSelection.IsNull())
return;
if(m_View->m_CurrentSelection->Size() == 1)
{
mitk::DataNodeObject::Pointer nodeObj = m_View->m_CurrentSelection->Begin()->Cast<mitk::DataNodeObject>();
if(nodeObj.IsNotNull())
{
mitk::DataNode::Pointer node = nodeObj->GetDataNode();
// check if node has data,
// if some helper nodes are shown in the DataManager, the GetData() returns 0x0 which would lead to SIGSEV
mitk::BaseData* nodeData = node->GetData();
if(nodeData != NULL )
{
if(dynamic_cast<mitk::PlanarFigure*>(nodeData) != 0)
{
m_View->m_Controls->m_PlanarFigureControlsFrame->setVisible(true);
m_View->m_SelectedNode = node;
float val;
node->GetFloatProperty("planarfigure.line.width", val);
m_View->m_Controls->m_PFWidth->setValue((int)(val*10.0));
QString label = "Width %1";
label = label.arg(val);
m_View->m_Controls->label_pfwidth->setText(label);
float color[3];
node->GetColor( color, NULL, "planarfigure.default.line.color");
QString styleSheet = "background-color:rgb(";
styleSheet.append(QString::number(color[0]*255.0));
styleSheet.append(",");
styleSheet.append(QString::number(color[1]*255.0));
styleSheet.append(",");
styleSheet.append(QString::number(color[2]*255.0));
styleSheet.append(")");
m_View->m_Controls->m_PFColor->setAutoFillBackground(true);
m_View->m_Controls->m_PFColor->setStyleSheet(styleSheet);
node->GetColor( color, NULL, "color");
styleSheet = "background-color:rgb(";
styleSheet.append(QString::number(color[0]*255.0));
styleSheet.append(",");
styleSheet.append(QString::number(color[1]*255.0));
styleSheet.append(",");
styleSheet.append(QString::number(color[2]*255.0));
styleSheet.append(")");
m_View->PlanarFigureFocus();
}
if(dynamic_cast<mitk::FiberBundleX*>(nodeData) != 0)
{
m_View->m_Controls->m_BundleControlsFrame->setVisible(true);
m_View->m_SelectedNode = node;
if(m_View->m_CurrentPickingNode != 0 && node.GetPointer() != m_View->m_CurrentPickingNode)
{
m_View->m_Controls->m_Crosshair->setEnabled(false);
}
else
{
m_View->m_Controls->m_Crosshair->setEnabled(true);
}
float val;
node->GetFloatProperty("TubeRadius", val);
m_View->m_Controls->m_TubeRadius->setValue((int)(val * 100.0));
QString label = "Radius %1";
label = label.arg(val);
m_View->m_Controls->label_tuberadius->setText(label);
int width;
node->GetIntProperty("LineWidth", width);
m_View->m_Controls->m_LineWidth->setValue(width);
label = "Width %1";
label = label.arg(width);
m_View->m_Controls->label_linewidth->setText(label);
float range;
node->GetFloatProperty("Fiber2DSliceThickness",range);
label = "Range %1";
label = label.arg(range*0.1);
m_View->m_Controls->label_range->setText(label);
}
} // check node data != NULL
}
}
if(m_View->m_CurrentSelection->Size() > 0 && m_View->m_SelectedNode == 0)
{
m_View->m_Controls->m_ImageControlsFrame->setVisible(true);
bool foundDiffusionImage = false;
bool foundQBIVolume = false;
bool foundTensorVolume = false;
bool foundImage = false;
bool foundMultipleOdfImages = false;
bool foundRGBAImage = false;
bool foundTbssImage = false;
// do something with the selected items
if(m_View->m_CurrentSelection)
{
// iterate selection
for (IStructuredSelection::iterator i = m_View->m_CurrentSelection->Begin();
i != m_View->m_CurrentSelection->End(); ++i)
{
// extract datatree node
if (mitk::DataNodeObject::Pointer nodeObj = i->Cast<mitk::DataNodeObject>())
{
mitk::DataNode::Pointer node = nodeObj->GetDataNode();
mitk::BaseData* nodeData = node->GetData();
if(nodeData != NULL )
{
// only look at interesting types
if(QString("DiffusionImage").compare(nodeData->GetNameOfClass())==0)
{
foundDiffusionImage = true;
bool tex_int;
node->GetBoolProperty("texture interpolation", tex_int);
if(tex_int)
{
m_View->m_Controls->m_TextureIntON->setIcon(*m_View->m_IconTexON);
m_View->m_Controls->m_TextureIntON->setChecked(true);
m_View->m_TexIsOn = true;
}
else
{
m_View->m_Controls->m_TextureIntON->setIcon(*m_View->m_IconTexOFF);
m_View->m_Controls->m_TextureIntON->setChecked(false);
m_View->m_TexIsOn = false;
}
int val;
node->GetIntProperty("DisplayChannel", val);
m_View->m_Controls->m_DisplayIndex->setValue(val);
m_View->m_Controls->m_DisplayIndexSpinBox->setValue(val);
QString label = "Channel %1";
label = label.arg(val);
m_View->m_Controls->label_channel->setText(label);
int maxVal = (dynamic_cast<mitk::DiffusionImage<short>* >(nodeData))->GetVectorImage()->GetVectorLength();
m_View->m_Controls->m_DisplayIndex->setMaximum(maxVal-1);
m_View->m_Controls->m_DisplayIndexSpinBox->setMaximum(maxVal-1);
}
if(QString("TbssImage").compare(nodeData->GetNameOfClass())==0)
{
foundTbssImage = true;
bool tex_int;
node->GetBoolProperty("texture interpolation", tex_int);
if(tex_int)
{
m_View->m_Controls->m_TextureIntON->setIcon(*m_View->m_IconTexON);
m_View->m_Controls->m_TextureIntON->setChecked(true);
m_View->m_TexIsOn = true;
}
else
{
m_View->m_Controls->m_TextureIntON->setIcon(*m_View->m_IconTexOFF);
m_View->m_Controls->m_TextureIntON->setChecked(false);
m_View->m_TexIsOn = false;
}
int val;
node->GetIntProperty("DisplayChannel", val);
m_View->m_Controls->m_DisplayIndex->setValue(val);
m_View->m_Controls->m_DisplayIndexSpinBox->setValue(val);
QString label = "Channel %1";
label = label.arg(val);
m_View->m_Controls->label_channel->setText(label);
int maxVal = (dynamic_cast<mitk::TbssImage* >(nodeData))->GetImage()->GetVectorLength();
m_View->m_Controls->m_DisplayIndex->setMaximum(maxVal-1);
m_View->m_Controls->m_DisplayIndexSpinBox->setMaximum(maxVal-1);
}
else if(QString("QBallImage").compare(nodeData->GetNameOfClass())==0)
{
foundMultipleOdfImages = foundQBIVolume || foundTensorVolume;
foundQBIVolume = true;
ApplySettings(node);
}
else if(QString("TensorImage").compare(nodeData->GetNameOfClass())==0)
{
foundMultipleOdfImages = foundQBIVolume || foundTensorVolume;
foundTensorVolume = true;
ApplySettings(node);
}
else if(QString("Image").compare(nodeData->GetNameOfClass())==0)
{
foundImage = true;
mitk::Image::Pointer img = dynamic_cast<mitk::Image*>(nodeData);
if(img.IsNotNull()
&& img->GetPixelType().GetPixelType() == itk::ImageIOBase::RGBA
&& img->GetPixelType().GetComponentType() == itk::ImageIOBase::UCHAR )
{
foundRGBAImage = true;
}
bool tex_int;
node->GetBoolProperty("texture interpolation", tex_int);
if(tex_int)
{
m_View->m_Controls->m_TextureIntON->setIcon(*m_View->m_IconTexON);
m_View->m_Controls->m_TextureIntON->setChecked(true);
m_View->m_TexIsOn = true;
}
else
{
m_View->m_Controls->m_TextureIntON->setIcon(*m_View->m_IconTexOFF);
m_View->m_Controls->m_TextureIntON->setChecked(false);
m_View->m_TexIsOn = false;
}
}
} // END CHECK node != NULL
}
}
}
m_View->m_FoundSingleOdfImage = (foundQBIVolume || foundTensorVolume)
&& !foundMultipleOdfImages;
m_View->m_Controls->m_NumberGlyphsFrame->setVisible(m_View->m_FoundSingleOdfImage);
m_View->m_Controls->m_NormalizationDropdown->setVisible(m_View->m_FoundSingleOdfImage);
m_View->m_Controls->label->setVisible(m_View->m_FoundSingleOdfImage);
m_View->m_Controls->m_ScalingFactor->setVisible(m_View->m_FoundSingleOdfImage);
m_View->m_Controls->m_AdditionalScaling->setVisible(m_View->m_FoundSingleOdfImage);
m_View->m_Controls->m_NormalizationScalingFrame->setVisible(m_View->m_FoundSingleOdfImage);
m_View->m_Controls->OpacMinFrame->setVisible(foundRGBAImage || m_View->m_FoundSingleOdfImage);
// changed for SPIE paper, Principle curvature scaling
//m_View->m_Controls->params_frame->setVisible(m_View->m_FoundSingleOdfImage);
m_View->m_Controls->params_frame->setVisible(false);
m_View->m_Controls->m_VisibleOdfsON_T->setVisible(m_View->m_FoundSingleOdfImage);
m_View->m_Controls->m_VisibleOdfsON_S->setVisible(m_View->m_FoundSingleOdfImage);
m_View->m_Controls->m_VisibleOdfsON_C->setVisible(m_View->m_FoundSingleOdfImage);
bool foundAnyImage = foundDiffusionImage ||
foundQBIVolume || foundTensorVolume || foundImage || foundTbssImage;
m_View->m_Controls->m_Reinit->setVisible(foundAnyImage);
m_View->m_Controls->m_TextureIntON->setVisible(foundAnyImage);
m_View->m_Controls->m_TSMenu->setVisible(foundAnyImage);
}
}
void SelectionChanged(IWorkbenchPart::Pointer part, ISelection::ConstPointer selection)
{
// check, if selection comes from datamanager
if (part)
{
QString partname(part->GetPartName().c_str());
if(partname.compare("Data Manager")==0)
{
// apply selection
DoSelectionChanged(selection);
}
}
}
QmitkControlVisualizationPropertiesView* m_View;
};
QmitkControlVisualizationPropertiesView::QmitkControlVisualizationPropertiesView()
: QmitkFunctionality(),
m_Controls(NULL),
m_MultiWidget(NULL),
m_NodeUsedForOdfVisualization(NULL),
m_IconTexOFF(new QIcon(":/QmitkDiffusionImaging/texIntOFFIcon.png")),
m_IconTexON(new QIcon(":/QmitkDiffusionImaging/texIntONIcon.png")),
m_IconGlyOFF_T(new QIcon(":/QmitkDiffusionImaging/glyphsoff_T.png")),
m_IconGlyON_T(new QIcon(":/QmitkDiffusionImaging/glyphson_T.png")),
m_IconGlyOFF_C(new QIcon(":/QmitkDiffusionImaging/glyphsoff_C.png")),
m_IconGlyON_C(new QIcon(":/QmitkDiffusionImaging/glyphson_C.png")),
m_IconGlyOFF_S(new QIcon(":/QmitkDiffusionImaging/glyphsoff_S.png")),
m_IconGlyON_S(new QIcon(":/QmitkDiffusionImaging/glyphson_S.png")),
m_CurrentSelection(0),
m_CurrentPickingNode(0),
m_GlyIsOn_S(false),
m_GlyIsOn_C(false),
m_GlyIsOn_T(false),
m_FiberBundleObserverTag(0),
m_Color(NULL)
{
currentThickSlicesMode = 1;
m_MyMenu = NULL;
int numThread = itk::MultiThreader::GetGlobalMaximumNumberOfThreads();
if (numThread > 12)
numThread = 12;
itk::MultiThreader::SetGlobalDefaultNumberOfThreads(numThread);
}
QmitkControlVisualizationPropertiesView::QmitkControlVisualizationPropertiesView(const QmitkControlVisualizationPropertiesView& other)
{
Q_UNUSED(other)
throw std::runtime_error("Copy constructor not implemented");
}
QmitkControlVisualizationPropertiesView::~QmitkControlVisualizationPropertiesView()
{
if(m_SlicesRotationObserverTag1 )
{
mitk::SlicesCoordinator* coordinator = m_MultiWidget->GetSlicesRotator();
if( coordinator)
coordinator->RemoveObserver(m_SlicesRotationObserverTag1);
}
if( m_SlicesRotationObserverTag2)
{
mitk::SlicesCoordinator* coordinator = m_MultiWidget->GetSlicesRotator();
if( coordinator )
coordinator->RemoveObserver(m_SlicesRotationObserverTag1);
}
this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->RemovePostSelectionListener(/*"org.mitk.views.datamanager",*/ m_SelListener);
}
void QmitkControlVisualizationPropertiesView::OnThickSlicesModeSelected( QAction* action )
{
currentThickSlicesMode = action->data().toInt();
switch(currentThickSlicesMode)
{
default:
case 1:
this->m_Controls->m_TSMenu->setText("MIP");
break;
case 2:
this->m_Controls->m_TSMenu->setText("SUM");
break;
case 3:
this->m_Controls->m_TSMenu->setText("WEIGH");
break;
}
mitk::DataNode* n;
n = this->m_MultiWidget->GetWidgetPlane1(); if(n) n->SetProperty( "reslice.thickslices", mitk::ResliceMethodProperty::New( currentThickSlicesMode ) );
n = this->m_MultiWidget->GetWidgetPlane2(); if(n) n->SetProperty( "reslice.thickslices", mitk::ResliceMethodProperty::New( currentThickSlicesMode ) );
n = this->m_MultiWidget->GetWidgetPlane3(); if(n) n->SetProperty( "reslice.thickslices", mitk::ResliceMethodProperty::New( currentThickSlicesMode ) );
mitk::BaseRenderer::Pointer renderer =
this->GetActiveStdMultiWidget()->GetRenderWindow1()->GetRenderer();
if(renderer.IsNotNull())
{
renderer->SendUpdateSlice();
}
renderer = this->GetActiveStdMultiWidget()->GetRenderWindow2()->GetRenderer();
if(renderer.IsNotNull())
{
renderer->SendUpdateSlice();
}
renderer = this->GetActiveStdMultiWidget()->GetRenderWindow3()->GetRenderer();
if(renderer.IsNotNull())
{
renderer->SendUpdateSlice();
}
renderer->GetRenderingManager()->RequestUpdateAll();
}
void QmitkControlVisualizationPropertiesView::OnTSNumChanged(int num)
{
if(num==0)
{
mitk::DataNode* n;
n = this->m_MultiWidget->GetWidgetPlane1(); if(n) n->SetProperty( "reslice.thickslices", mitk::ResliceMethodProperty::New( 0 ) );
n = this->m_MultiWidget->GetWidgetPlane2(); if(n) n->SetProperty( "reslice.thickslices", mitk::ResliceMethodProperty::New( 0 ) );
n = this->m_MultiWidget->GetWidgetPlane3(); if(n) n->SetProperty( "reslice.thickslices", mitk::ResliceMethodProperty::New( 0 ) );
}
else
{
mitk::DataNode* n;
n = this->m_MultiWidget->GetWidgetPlane1(); if(n) n->SetProperty( "reslice.thickslices", mitk::ResliceMethodProperty::New( currentThickSlicesMode ) );
n = this->m_MultiWidget->GetWidgetPlane2(); if(n) n->SetProperty( "reslice.thickslices", mitk::ResliceMethodProperty::New( currentThickSlicesMode ) );
n = this->m_MultiWidget->GetWidgetPlane3(); if(n) n->SetProperty( "reslice.thickslices", mitk::ResliceMethodProperty::New( currentThickSlicesMode ) );
n = this->m_MultiWidget->GetWidgetPlane1(); if(n) n->SetProperty( "reslice.thickslices.num", mitk::IntProperty::New( num ) );
n = this->m_MultiWidget->GetWidgetPlane2(); if(n) n->SetProperty( "reslice.thickslices.num", mitk::IntProperty::New( num ) );
n = this->m_MultiWidget->GetWidgetPlane3(); if(n) n->SetProperty( "reslice.thickslices.num", mitk::IntProperty::New( num ) );
}
m_TSLabel->setText(QString::number(num*2+1));
mitk::BaseRenderer::Pointer renderer =
this->GetActiveStdMultiWidget()->GetRenderWindow1()->GetRenderer();
if(renderer.IsNotNull())
{
renderer->SendUpdateSlice();
}
renderer = this->GetActiveStdMultiWidget()->GetRenderWindow2()->GetRenderer();
if(renderer.IsNotNull())
{
renderer->SendUpdateSlice();
}
renderer = this->GetActiveStdMultiWidget()->GetRenderWindow3()->GetRenderer();
if(renderer.IsNotNull())
{
renderer->SendUpdateSlice();
}
renderer->GetRenderingManager()->RequestUpdateAll(mitk::RenderingManager::REQUEST_UPDATE_2DWINDOWS);
}
void QmitkControlVisualizationPropertiesView::CreateQtPartControl(QWidget *parent)
{
if (!m_Controls)
{
// create GUI widgets
m_Controls = new Ui::QmitkControlVisualizationPropertiesViewControls;
m_Controls->setupUi(parent);
this->CreateConnections();
// hide warning (ODFs in rotated planes)
m_Controls->m_lblRotatedPlanesWarning->hide();
m_MyMenu = new QMenu(parent);
connect( m_MyMenu, SIGNAL( aboutToShow() ), this, SLOT(OnMenuAboutToShow()) );
// button for changing rotation mode
m_Controls->m_TSMenu->setMenu( m_MyMenu );
//m_CrosshairModeButton->setIcon( QIcon( iconCrosshairMode_xpm ) );
m_Controls->params_frame->setVisible(false);
QIcon icon5(":/QmitkDiffusionImaging/Refresh_48.png");
m_Controls->m_Reinit->setIcon(icon5);
m_Controls->m_Focus->setIcon(icon5);
QIcon iconColor(":/QmitkDiffusionImaging/color24.gif");
m_Controls->m_PFColor->setIcon(iconColor);
m_Controls->m_Color->setIcon(iconColor);
QIcon iconReset(":/QmitkDiffusionImaging/reset.png");
m_Controls->m_ResetColoring->setIcon(iconReset);
m_Controls->m_PFColor->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
QIcon iconCrosshair(":/QmitkDiffusionImaging/crosshair.png");
m_Controls->m_Crosshair->setIcon(iconCrosshair);
// was is los
QIcon iconPaint(":/QmitkDiffusionImaging/paint2.png");
m_Controls->m_TDI->setIcon(iconPaint);
QIcon iconFiberFade(":/QmitkDiffusionImaging/MapperEfx2D.png");
m_Controls->m_FiberFading2D->setIcon(iconFiberFade);
m_Controls->m_TextureIntON->setCheckable(true);
#ifndef DIFFUSION_IMAGING_EXTENDED
int size = m_Controls->m_AdditionalScaling->count();
for(int t=0; t<size; t++)
{
if(m_Controls->m_AdditionalScaling->itemText(t).toStdString() == "Scale by ASR")
{
m_Controls->m_AdditionalScaling->removeItem(t);
}
}
#endif
m_Controls->m_OpacitySlider->setRange(0.0,1.0);
m_Controls->m_OpacitySlider->setLowerValue(0.0);
m_Controls->m_OpacitySlider->setUpperValue(0.0);
m_Controls->m_ScalingFrame->setVisible(false);
m_Controls->m_NormalizationFrame->setVisible(false);
m_Controls->frame_tube->setVisible(false);
m_Controls->frame_wire->setVisible(false);
}
m_IsInitialized = false;
m_SelListener = berry::ISelectionListener::Pointer(new CvpSelListener(this));
this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->AddPostSelectionListener(/*"org.mitk.views.datamanager",*/ m_SelListener);
berry::ISelection::ConstPointer sel(
this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->GetSelection("org.mitk.views.datamanager"));
m_CurrentSelection = sel.Cast<const IStructuredSelection>();
m_SelListener.Cast<CvpSelListener>()->DoSelectionChanged(sel);
m_IsInitialized = true;
}
void QmitkControlVisualizationPropertiesView::OnMenuAboutToShow ()
{
// THICK SLICE SUPPORT
QMenu *myMenu = m_MyMenu;
myMenu->clear();
QActionGroup* thickSlicesActionGroup = new QActionGroup(myMenu);
thickSlicesActionGroup->setExclusive(true);
mitk::BaseRenderer::Pointer renderer =
this->GetActiveStdMultiWidget()->GetRenderWindow1()->GetRenderer();
int currentTSMode = 0;
{
mitk::ResliceMethodProperty::Pointer m = dynamic_cast<mitk::ResliceMethodProperty*>(renderer->GetCurrentWorldGeometry2DNode()->GetProperty( "reslice.thickslices" ));
if( m.IsNotNull() )
currentTSMode = m->GetValueAsId();
}
const int maxTS = 30;
int currentNum = 0;
{
mitk::IntProperty::Pointer m = dynamic_cast<mitk::IntProperty*>(renderer->GetCurrentWorldGeometry2DNode()->GetProperty( "reslice.thickslices.num" ));
if( m.IsNotNull() )
{
currentNum = m->GetValue();
if(currentNum < 0) currentNum = 0;
if(currentNum > maxTS) currentNum = maxTS;
}
}
if(currentTSMode==0)
currentNum=0;
QSlider *m_TSSlider = new QSlider(myMenu);
m_TSSlider->setMinimum(0);
m_TSSlider->setMaximum(maxTS-1);
m_TSSlider->setValue(currentNum);
m_TSSlider->setOrientation(Qt::Horizontal);
connect( m_TSSlider, SIGNAL( valueChanged(int) ), this, SLOT( OnTSNumChanged(int) ) );
QHBoxLayout* _TSLayout = new QHBoxLayout;
_TSLayout->setContentsMargins(4,4,4,4);
_TSLayout->addWidget(m_TSSlider);
_TSLayout->addWidget(m_TSLabel=new QLabel(QString::number(currentNum*2+1),myMenu));
QWidget* _TSWidget = new QWidget;
_TSWidget->setLayout(_TSLayout);
QActionGroup* thickSliceModeActionGroup = new QActionGroup(myMenu);
thickSliceModeActionGroup->setExclusive(true);
QWidgetAction *m_TSSliderAction = new QWidgetAction(myMenu);
m_TSSliderAction->setDefaultWidget(_TSWidget);
myMenu->addAction(m_TSSliderAction);
QAction* mipThickSlicesAction = new QAction(myMenu);
mipThickSlicesAction->setActionGroup(thickSliceModeActionGroup);
mipThickSlicesAction->setText("MIP (max. intensity proj.)");
mipThickSlicesAction->setCheckable(true);
mipThickSlicesAction->setChecked(currentThickSlicesMode==1);
mipThickSlicesAction->setData(1);
myMenu->addAction( mipThickSlicesAction );
QAction* sumThickSlicesAction = new QAction(myMenu);
sumThickSlicesAction->setActionGroup(thickSliceModeActionGroup);
sumThickSlicesAction->setText("SUM (sum intensity proj.)");
sumThickSlicesAction->setCheckable(true);
sumThickSlicesAction->setChecked(currentThickSlicesMode==2);
sumThickSlicesAction->setData(2);
myMenu->addAction( sumThickSlicesAction );
QAction* weightedThickSlicesAction = new QAction(myMenu);
weightedThickSlicesAction->setActionGroup(thickSliceModeActionGroup);
weightedThickSlicesAction->setText("WEIGHTED (gaussian proj.)");
weightedThickSlicesAction->setCheckable(true);
weightedThickSlicesAction->setChecked(currentThickSlicesMode==3);
weightedThickSlicesAction->setData(3);
myMenu->addAction( weightedThickSlicesAction );
connect( thickSliceModeActionGroup, SIGNAL(triggered(QAction*)), this, SLOT(OnThickSlicesModeSelected(QAction*)) );
}
void QmitkControlVisualizationPropertiesView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget)
{
m_MultiWidget = &stdMultiWidget;
if (m_MultiWidget)
{
mitk::SlicesCoordinator* coordinator = m_MultiWidget->GetSlicesRotator();
if (coordinator)
{
itk::ReceptorMemberCommand<QmitkControlVisualizationPropertiesView>::Pointer command2 = itk::ReceptorMemberCommand<QmitkControlVisualizationPropertiesView>::New();
command2->SetCallbackFunction( this, &QmitkControlVisualizationPropertiesView::SliceRotation );
m_SlicesRotationObserverTag1 = coordinator->AddObserver( mitk::SliceRotationEvent(), command2 );
}
coordinator = m_MultiWidget->GetSlicesSwiveller();
if (coordinator)
{
itk::ReceptorMemberCommand<QmitkControlVisualizationPropertiesView>::Pointer command2 = itk::ReceptorMemberCommand<QmitkControlVisualizationPropertiesView>::New();
command2->SetCallbackFunction( this, &QmitkControlVisualizationPropertiesView::SliceRotation );
m_SlicesRotationObserverTag2 = coordinator->AddObserver( mitk::SliceRotationEvent(), command2 );
}
}
}
void QmitkControlVisualizationPropertiesView::SliceRotation(const itk::EventObject&)
{
// test if plane rotated
if( m_GlyIsOn_T || m_GlyIsOn_C || m_GlyIsOn_S )
{
if( this->IsPlaneRotated() )
{
// show label
m_Controls->m_lblRotatedPlanesWarning->show();
}
else
{
//hide label
m_Controls->m_lblRotatedPlanesWarning->hide();
}
}
}
void QmitkControlVisualizationPropertiesView::StdMultiWidgetNotAvailable()
{
m_MultiWidget = NULL;
}
void QmitkControlVisualizationPropertiesView::CreateConnections()
{
if ( m_Controls )
{
connect( (QObject*)(m_Controls->m_DisplayIndex), SIGNAL(valueChanged(int)), this, SLOT(DisplayIndexChanged(int)) );
connect( (QObject*)(m_Controls->m_DisplayIndexSpinBox), SIGNAL(valueChanged(int)), this, SLOT(DisplayIndexChanged(int)) );
connect( (QObject*)(m_Controls->m_TextureIntON), SIGNAL(clicked()), this, SLOT(TextIntON()) );
connect( (QObject*)(m_Controls->m_Reinit), SIGNAL(clicked()), this, SLOT(Reinit()) );
connect( (QObject*)(m_Controls->m_VisibleOdfsON_T), SIGNAL(clicked()), this, SLOT(VisibleOdfsON_T()) );
connect( (QObject*)(m_Controls->m_VisibleOdfsON_S), SIGNAL(clicked()), this, SLOT(VisibleOdfsON_S()) );
connect( (QObject*)(m_Controls->m_VisibleOdfsON_C), SIGNAL(clicked()), this, SLOT(VisibleOdfsON_C()) );
connect( (QObject*)(m_Controls->m_ShowMaxNumber), SIGNAL(editingFinished()), this, SLOT(ShowMaxNumberChanged()) );
connect( (QObject*)(m_Controls->m_NormalizationDropdown), SIGNAL(currentIndexChanged(int)), this, SLOT(NormalizationDropdownChanged(int)) );
connect( (QObject*)(m_Controls->m_ScalingFactor), SIGNAL(valueChanged(double)), this, SLOT(ScalingFactorChanged(double)) );
connect( (QObject*)(m_Controls->m_AdditionalScaling), SIGNAL(currentIndexChanged(int)), this, SLOT(AdditionalScaling(int)) );
connect( (QObject*)(m_Controls->m_IndexParam1), SIGNAL(valueChanged(double)), this, SLOT(IndexParam1Changed(double)) );
connect( (QObject*)(m_Controls->m_IndexParam2), SIGNAL(valueChanged(double)), this, SLOT(IndexParam2Changed(double)) );
connect( (QObject*)(m_Controls->m_ScalingCheckbox), SIGNAL(clicked()), this, SLOT(ScalingCheckbox()) );
connect( (QObject*)(m_Controls->m_OpacitySlider), SIGNAL(spanChanged(double,double)), this, SLOT(OpacityChanged(double,double)) );
connect((QObject*) m_Controls->m_Wire, SIGNAL(clicked()), (QObject*) this, SLOT(BundleRepresentationWire()));
connect((QObject*) m_Controls->m_Tube, SIGNAL(clicked()), (QObject*) this, SLOT(BundleRepresentationTube()));
connect((QObject*) m_Controls->m_Color, SIGNAL(clicked()), (QObject*) this, SLOT(BundleRepresentationColor()));
connect((QObject*) m_Controls->m_ResetColoring, SIGNAL(clicked()), (QObject*) this, SLOT(BundleRepresentationResetColoring()));
connect((QObject*) m_Controls->m_Focus, SIGNAL(clicked()), (QObject*) this, SLOT(PlanarFigureFocus()));
connect((QObject*) m_Controls->m_FiberFading2D, SIGNAL(clicked()), (QObject*) this, SLOT( Fiber2DfadingEFX() ) );
connect((QObject*) m_Controls->m_FiberThicknessSlider, SIGNAL(sliderReleased()), (QObject*) this, SLOT( FiberSlicingThickness2D() ) );
connect((QObject*) m_Controls->m_FiberThicknessSlider, SIGNAL(valueChanged(int)), (QObject*) this, SLOT( FiberSlicingUpdateLabel(int) ));
connect((QObject*) m_Controls->m_Crosshair, SIGNAL(clicked()), (QObject*) this, SLOT(SetInteractor()));
connect((QObject*) m_Controls->m_PFWidth, SIGNAL(valueChanged(int)), (QObject*) this, SLOT(PFWidth(int)));
connect((QObject*) m_Controls->m_PFColor, SIGNAL(clicked()), (QObject*) this, SLOT(PFColor()));
connect((QObject*) m_Controls->m_TDI, SIGNAL(clicked()), (QObject*) this, SLOT(GenerateTdi()));
connect((QObject*) m_Controls->m_LineWidth, SIGNAL(valueChanged(int)), (QObject*) this, SLOT(LineWidthChanged(int)));
connect((QObject*) m_Controls->m_TubeRadius, SIGNAL(valueChanged(int)), (QObject*) this, SLOT(TubeRadiusChanged(int)));
}
}
void QmitkControlVisualizationPropertiesView::Activated()
{
berry::ISelection::ConstPointer sel(
this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->GetSelection("org.mitk.views.datamanager"));
m_CurrentSelection = sel.Cast<const IStructuredSelection>();
m_SelListener.Cast<CvpSelListener>()->DoSelectionChanged(sel);
QmitkFunctionality::Activated();
}
void QmitkControlVisualizationPropertiesView::Deactivated()
{
QmitkFunctionality::Deactivated();
}
int QmitkControlVisualizationPropertiesView::GetSizeFlags(bool width)
{
if(!width)
{
return berry::Constants::MIN | berry::Constants::MAX | berry::Constants::FILL;
}
else
{
return 0;
}
}
int QmitkControlVisualizationPropertiesView::ComputePreferredSize(bool width, int /*availableParallel*/, int /*availablePerpendicular*/, int preferredResult)
{
if(width==false)
{
return m_FoundSingleOdfImage ? 120 : 80;
}
else
{
return preferredResult;
}
}
// set diffusion image channel to b0 volume
void QmitkControlVisualizationPropertiesView::NodeAdded(const mitk::DataNode *node)
{
mitk::DataNode* notConst = const_cast<mitk::DataNode*>(node);
if (dynamic_cast<mitk::DiffusionImage<short>*>(notConst->GetData()))
{
mitk::DiffusionImage<short>::Pointer dimg = dynamic_cast<mitk::DiffusionImage<short>*>(notConst->GetData());
// if there is no b0 image in the dataset, the GetB0Indices() returns a vector of size 0
// and hence we cannot set the Property directly to .front()
int displayChannelPropertyValue = 0;
mitk::DiffusionImage<short>::BValueMap map = dimg->GetBValueMap();
if( map[0].size() > 0)
displayChannelPropertyValue = map[0].front();
notConst->SetIntProperty("DisplayChannel", displayChannelPropertyValue );
}
}
/* OnSelectionChanged is registered to SelectionService, therefore no need to
implement SelectionService Listener explicitly */
void QmitkControlVisualizationPropertiesView::OnSelectionChanged( std::vector<mitk::DataNode*> nodes )
{
// deactivate channel slider if no diffusion weighted image or tbss image is selected
m_Controls->m_DisplayIndex->setVisible(false);
m_Controls->m_DisplayIndexSpinBox->setVisible(false);
m_Controls->label_channel->setVisible(false);
for( std::vector<mitk::DataNode*>::iterator it = nodes.begin(); it != nodes.end(); ++it )
{
mitk::DataNode::Pointer node = *it;
// check if node has data,
// if some helper nodes are shown in the DataManager, the GetData() returns 0x0 which would lead to SIGSEV
mitk::BaseData* nodeData = node->GetData();
if(nodeData == NULL)
continue;
if (node.IsNotNull() && (dynamic_cast<mitk::TbssImage*>(nodeData) ||
dynamic_cast<mitk::DiffusionImage<short>*>(nodeData)))
{
m_Controls->m_DisplayIndex->setVisible(true);
m_Controls->m_DisplayIndexSpinBox->setVisible(true);
m_Controls->label_channel->setVisible(true);
}
else if (node.IsNotNull() && dynamic_cast<mitk::FiberBundleX*>(node->GetData()))
{
if (m_Color.IsNotNull())
m_Color->RemoveObserver(m_FiberBundleObserverTag);
itk::ReceptorMemberCommand<QmitkControlVisualizationPropertiesView>::Pointer command = itk::ReceptorMemberCommand<QmitkControlVisualizationPropertiesView>::New();
command->SetCallbackFunction( this, &QmitkControlVisualizationPropertiesView::SetFiberBundleCustomColor );
m_Color = dynamic_cast<mitk::ColorProperty*>(node->GetProperty("color", NULL));
if (m_Color.IsNotNull())
m_FiberBundleObserverTag = m_Color->AddObserver( itk::ModifiedEvent(), command );
}
}
for( std::vector<mitk::DataNode*>::iterator it = nodes.begin(); it != nodes.end(); ++it )
{
mitk::DataNode::Pointer node = *it;
// check if node has data,
// if some helper nodes are shown in the DataManager, the GetData() returns 0x0 which would lead to SIGSEV
mitk::BaseData* nodeData = node->GetData();
if(nodeData == NULL)
continue;
if( node.IsNotNull() && (dynamic_cast<mitk::QBallImage*>(nodeData) || dynamic_cast<mitk::TensorImage*>(nodeData)) )
{
if(m_NodeUsedForOdfVisualization.IsNotNull())
{
m_NodeUsedForOdfVisualization->SetBoolProperty("VisibleOdfs_S", false);
m_NodeUsedForOdfVisualization->SetBoolProperty("VisibleOdfs_C", false);
m_NodeUsedForOdfVisualization->SetBoolProperty("VisibleOdfs_T", false);
}
m_NodeUsedForOdfVisualization = node;
m_NodeUsedForOdfVisualization->SetBoolProperty("VisibleOdfs_S", m_GlyIsOn_S);
m_NodeUsedForOdfVisualization->SetBoolProperty("VisibleOdfs_C", m_GlyIsOn_C);
m_NodeUsedForOdfVisualization->SetBoolProperty("VisibleOdfs_T", m_GlyIsOn_T);
if(m_MultiWidget)
m_MultiWidget->RequestUpdate();
m_Controls->m_TSMenu->setVisible(false); // deactivate mip etc. for tensor and q-ball images
break;
}
else if( node.IsNotNull() && dynamic_cast<mitk::ConnectomicsNetwork*>(nodeData) )
m_Controls->m_TSMenu->setVisible(false);
else
m_Controls->m_TSMenu->setVisible(true);
}
// if selection changes, set the current selction member and call SellListener::DoSelectionChanged
berry::ISelection::ConstPointer sel(
this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->GetSelection("org.mitk.views.datamanager"));
m_CurrentSelection = sel.Cast<const IStructuredSelection>();
m_SelListener.Cast<CvpSelListener>()->DoSelectionChanged(sel);
}
mitk::DataStorage::SetOfObjects::Pointer
QmitkControlVisualizationPropertiesView::ActiveSet(std::string classname)
{
if (m_CurrentSelection)
{
mitk::DataStorage::SetOfObjects::Pointer set =
mitk::DataStorage::SetOfObjects::New();
int at = 0;
for (IStructuredSelection::iterator i = m_CurrentSelection->Begin();
i != m_CurrentSelection->End();
++i)
{
if (mitk::DataNodeObject::Pointer nodeObj = i->Cast<mitk::DataNodeObject>())
{
mitk::DataNode::Pointer node = nodeObj->GetDataNode();
// check if node has data,
// if some helper nodes are shown in the DataManager, the GetData() returns 0x0 which would lead to SIGSEV
const mitk::BaseData* nodeData = node->GetData();
if(nodeData == NULL)
continue;
if(QString(classname.c_str()).compare(nodeData->GetNameOfClass())==0)
{
set->InsertElement(at++, node);
}
}
}
return set;
}
return 0;
}
void QmitkControlVisualizationPropertiesView::SetBoolProp(
mitk::DataStorage::SetOfObjects::Pointer set,
std::string name, bool value)
{
if(set.IsNotNull())
{
mitk::DataStorage::SetOfObjects::const_iterator itemiter( set->begin() );
mitk::DataStorage::SetOfObjects::const_iterator itemiterend( set->end() );
while ( itemiter != itemiterend )
{
(*itemiter)->SetBoolProperty(name.c_str(), value);
++itemiter;
}
}
}
void QmitkControlVisualizationPropertiesView::SetIntProp(
mitk::DataStorage::SetOfObjects::Pointer set,
std::string name, int value)
{
if(set.IsNotNull())
{
mitk::DataStorage::SetOfObjects::const_iterator itemiter( set->begin() );
mitk::DataStorage::SetOfObjects::const_iterator itemiterend( set->end() );
while ( itemiter != itemiterend )
{
(*itemiter)->SetIntProperty(name.c_str(), value);
++itemiter;
}
}
}
void QmitkControlVisualizationPropertiesView::SetFloatProp(
mitk::DataStorage::SetOfObjects::Pointer set,
std::string name, float value)
{
if(set.IsNotNull())
{
mitk::DataStorage::SetOfObjects::const_iterator itemiter( set->begin() );
mitk::DataStorage::SetOfObjects::const_iterator itemiterend( set->end() );
while ( itemiter != itemiterend )
{
(*itemiter)->SetFloatProperty(name.c_str(), value);
++itemiter;
}
}
}
void QmitkControlVisualizationPropertiesView::SetLevelWindowProp(
mitk::DataStorage::SetOfObjects::Pointer set,
std::string name, mitk::LevelWindow value)
{
if(set.IsNotNull())
{
mitk::LevelWindowProperty::Pointer prop = mitk::LevelWindowProperty::New(value);
mitk::DataStorage::SetOfObjects::const_iterator itemiter( set->begin() );
mitk::DataStorage::SetOfObjects::const_iterator itemiterend( set->end() );
while ( itemiter != itemiterend )
{
(*itemiter)->SetProperty(name.c_str(), prop);
++itemiter;
}
}
}
void QmitkControlVisualizationPropertiesView::SetEnumProp(
mitk::DataStorage::SetOfObjects::Pointer set,
std::string name, mitk::EnumerationProperty::Pointer value)
{
if(set.IsNotNull())
{
mitk::DataStorage::SetOfObjects::const_iterator itemiter( set->begin() );
mitk::DataStorage::SetOfObjects::const_iterator itemiterend( set->end() );
while ( itemiter != itemiterend )
{
(*itemiter)->SetProperty(name.c_str(), value);
++itemiter;
}
}
}
void QmitkControlVisualizationPropertiesView::DisplayIndexChanged(int dispIndex)
{
m_Controls->m_DisplayIndex->setValue(dispIndex);
m_Controls->m_DisplayIndexSpinBox->setValue(dispIndex);
QString label = "Channel %1";
label = label.arg(dispIndex);
m_Controls->label_channel->setText(label);
std::vector<std::string> sets;
sets.push_back("DiffusionImage");
sets.push_back("TbssImage");
std::vector<std::string>::iterator it = sets.begin();
while(it != sets.end())
{
std::string s = *it;
mitk::DataStorage::SetOfObjects::Pointer set =
ActiveSet(s);
if(set.IsNotNull())
{
mitk::DataStorage::SetOfObjects::const_iterator itemiter( set->begin() );
mitk::DataStorage::SetOfObjects::const_iterator itemiterend( set->end() );
while ( itemiter != itemiterend )
{
(*itemiter)->SetIntProperty("DisplayChannel", dispIndex);
++itemiter;
}
//m_MultiWidget->RequestUpdate();
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
it++;
}
}
void QmitkControlVisualizationPropertiesView::Reinit()
{
if (m_CurrentSelection)
{
mitk::DataNodeObject::Pointer nodeObj =
m_CurrentSelection->Begin()->Cast<mitk::DataNodeObject>();
mitk::DataNode::Pointer node = nodeObj->GetDataNode();
mitk::BaseData::Pointer basedata = node->GetData();
if (basedata.IsNotNull())
{
mitk::RenderingManager::GetInstance()->InitializeViews(
basedata->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true );
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
}
void QmitkControlVisualizationPropertiesView::TextIntON()
{
if(m_TexIsOn)
{
m_Controls->m_TextureIntON->setIcon(*m_IconTexOFF);
}
else
{
m_Controls->m_TextureIntON->setIcon(*m_IconTexON);
}
mitk::DataStorage::SetOfObjects::Pointer set =
ActiveSet("DiffusionImage");
SetBoolProp(set,"texture interpolation", !m_TexIsOn);
set = ActiveSet("TensorImage");
SetBoolProp(set,"texture interpolation", !m_TexIsOn);
set = ActiveSet("QBallImage");
SetBoolProp(set,"texture interpolation", !m_TexIsOn);
set = ActiveSet("Image");
SetBoolProp(set,"texture interpolation", !m_TexIsOn);
m_TexIsOn = !m_TexIsOn;
if(m_MultiWidget)
m_MultiWidget->RequestUpdate();
}
void QmitkControlVisualizationPropertiesView::VisibleOdfsON_S()
{
m_GlyIsOn_S = m_Controls->m_VisibleOdfsON_S->isChecked();
if (m_NodeUsedForOdfVisualization.IsNull())
{
MITK_WARN << "ODF visualization activated but m_NodeUsedForOdfVisualization is NULL";
return;
}
m_NodeUsedForOdfVisualization->SetBoolProperty("VisibleOdfs_S", m_GlyIsOn_S);
VisibleOdfsON(0);
}
void QmitkControlVisualizationPropertiesView::VisibleOdfsON_T()
{
m_GlyIsOn_T = m_Controls->m_VisibleOdfsON_T->isChecked();
if (m_NodeUsedForOdfVisualization.IsNull())
{
MITK_WARN << "ODF visualization activated but m_NodeUsedForOdfVisualization is NULL";
return;
}
m_NodeUsedForOdfVisualization->SetBoolProperty("VisibleOdfs_T", m_GlyIsOn_T);
VisibleOdfsON(1);
}
void QmitkControlVisualizationPropertiesView::VisibleOdfsON_C()
{
m_GlyIsOn_C = m_Controls->m_VisibleOdfsON_C->isChecked();
if (m_NodeUsedForOdfVisualization.IsNull())
{
MITK_WARN << "ODF visualization activated but m_NodeUsedForOdfVisualization is NULL";
return;
}
m_NodeUsedForOdfVisualization->SetBoolProperty("VisibleOdfs_C", m_GlyIsOn_C);
VisibleOdfsON(2);
}
bool QmitkControlVisualizationPropertiesView::IsPlaneRotated()
{
// for all 2D renderwindows of m_MultiWidget check alignment
mitk::PlaneGeometry::ConstPointer displayPlane = dynamic_cast<const mitk::PlaneGeometry*>( m_MultiWidget->GetRenderWindow1()->GetRenderer()->GetCurrentWorldGeometry2D() );
if (displayPlane.IsNull()) return false;
mitk::Image* currentImage = dynamic_cast<mitk::Image* >( m_NodeUsedForOdfVisualization->GetData() );
if( currentImage == NULL )
{
MITK_ERROR << " Casting problems. Returning false";
return false;
}
int affectedDimension(-1);
int affectedSlice(-1);
return !(DetermineAffectedImageSlice( currentImage, displayPlane, affectedDimension, affectedSlice ));
}
void QmitkControlVisualizationPropertiesView::VisibleOdfsON(int view)
{
if(m_MultiWidget)
m_MultiWidget->RequestUpdate();
}
void QmitkControlVisualizationPropertiesView::ShowMaxNumberChanged()
{
int maxNr = m_Controls->m_ShowMaxNumber->value();
if ( maxNr < 1 )
{
m_Controls->m_ShowMaxNumber->setValue( 1 );
maxNr = 1;
}
mitk::DataStorage::SetOfObjects::Pointer set =
ActiveSet("QBallImage");
SetIntProp(set,"ShowMaxNumber", maxNr);
set = ActiveSet("TensorImage");
SetIntProp(set,"ShowMaxNumber", maxNr);
if(m_MultiWidget)
m_MultiWidget->RequestUpdate();
}
void QmitkControlVisualizationPropertiesView::NormalizationDropdownChanged(int normDropdown)
{
typedef mitk::OdfNormalizationMethodProperty PropType;
PropType::Pointer normMeth = PropType::New();
switch(normDropdown)
{
case 0:
normMeth->SetNormalizationToMinMax();
break;
case 1:
normMeth->SetNormalizationToMax();
break;
case 2:
normMeth->SetNormalizationToNone();
break;
case 3:
normMeth->SetNormalizationToGlobalMax();
break;
default:
normMeth->SetNormalizationToMinMax();
}
mitk::DataStorage::SetOfObjects::Pointer set =
ActiveSet("QBallImage");
SetEnumProp(set,"Normalization", normMeth.GetPointer());
set = ActiveSet("TensorImage");
SetEnumProp(set,"Normalization", normMeth.GetPointer());
// if(m_MultiWidget)
// m_MultiWidget->RequestUpdate();
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkControlVisualizationPropertiesView::ScalingFactorChanged(double scalingFactor)
{
mitk::DataStorage::SetOfObjects::Pointer set =
ActiveSet("QBallImage");
SetFloatProp(set,"Scaling", scalingFactor);
set = ActiveSet("TensorImage");
SetFloatProp(set,"Scaling", scalingFactor);
if(m_MultiWidget)
m_MultiWidget->RequestUpdate();
}
void QmitkControlVisualizationPropertiesView::AdditionalScaling(int additionalScaling)
{
typedef mitk::OdfScaleByProperty PropType;
PropType::Pointer scaleBy = PropType::New();
switch(additionalScaling)
{
case 0:
scaleBy->SetScaleByNothing();
break;
case 1:
scaleBy->SetScaleByGFA();
//m_Controls->params_frame->setVisible(true);
break;
#ifdef DIFFUSION_IMAGING_EXTENDED
case 2:
scaleBy->SetScaleByPrincipalCurvature();
// commented in for SPIE paper, Principle curvature scaling
//m_Controls->params_frame->setVisible(true);
break;
#endif
default:
scaleBy->SetScaleByNothing();
}
mitk::DataStorage::SetOfObjects::Pointer set =
ActiveSet("QBallImage");
SetEnumProp(set,"ScaleBy", scaleBy.GetPointer());
set = ActiveSet("TensorImage");
SetEnumProp(set,"ScaleBy", scaleBy.GetPointer());
if(m_MultiWidget)
m_MultiWidget->RequestUpdate();
}
void QmitkControlVisualizationPropertiesView::IndexParam1Changed(double param1)
{
mitk::DataStorage::SetOfObjects::Pointer set =
ActiveSet("QBallImage");
SetFloatProp(set,"IndexParam1", param1);
set = ActiveSet("TensorImage");
SetFloatProp(set,"IndexParam1", param1);
if(m_MultiWidget)
m_MultiWidget->RequestUpdate();
}
void QmitkControlVisualizationPropertiesView::IndexParam2Changed(double param2)
{
mitk::DataStorage::SetOfObjects::Pointer set =
ActiveSet("QBallImage");
SetFloatProp(set,"IndexParam2", param2);
set = ActiveSet("TensorImage");
SetFloatProp(set,"IndexParam2", param2);
if(m_MultiWidget)
m_MultiWidget->RequestUpdate();
}
void QmitkControlVisualizationPropertiesView::OpacityChanged(double l, double u)
{
mitk::LevelWindow olw;
olw.SetRangeMinMax(l*255, u*255);
mitk::DataStorage::SetOfObjects::Pointer set =
ActiveSet("QBallImage");
SetLevelWindowProp(set,"opaclevelwindow", olw);
set = ActiveSet("TensorImage");
SetLevelWindowProp(set,"opaclevelwindow", olw);
set = ActiveSet("Image");
SetLevelWindowProp(set,"opaclevelwindow", olw);
m_Controls->m_OpacityMinFaLabel->setText(QString::number(l,'f',2) + " : " + QString::number(u,'f',2));
if(m_MultiWidget)
m_MultiWidget->RequestUpdate();
}
void QmitkControlVisualizationPropertiesView::ScalingCheckbox()
{
m_Controls->m_ScalingFrame->setVisible(
m_Controls->m_ScalingCheckbox->isChecked());
if(!m_Controls->m_ScalingCheckbox->isChecked())
{
m_Controls->m_AdditionalScaling->setCurrentIndex(0);
m_Controls->m_ScalingFactor->setValue(1.0);
}
}
void QmitkControlVisualizationPropertiesView::Fiber2DfadingEFX()
{
if (m_SelectedNode)
{
bool currentMode;
m_SelectedNode->GetBoolProperty("Fiber2DfadeEFX", currentMode);
m_SelectedNode->SetProperty("Fiber2DfadeEFX", mitk::BoolProperty::New(!currentMode));
mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll();
}
}
void QmitkControlVisualizationPropertiesView::FiberSlicingThickness2D()
{
if (m_SelectedNode)
{
float fibThickness = m_Controls->m_FiberThicknessSlider->value() * 0.1;
m_SelectedNode->SetProperty("Fiber2DSliceThickness", mitk::FloatProperty::New(fibThickness));
mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll();
}
}
void QmitkControlVisualizationPropertiesView::FiberSlicingUpdateLabel(int value)
{
QString label = "Range %1";
label = label.arg(value * 0.1);
m_Controls->label_range->setText(label);
}
void QmitkControlVisualizationPropertiesView::BundleRepresentationWire()
{
if(m_SelectedNode)
{
int width = m_Controls->m_LineWidth->value();
m_SelectedNode->SetProperty("LineWidth",mitk::IntProperty::New(width));
m_SelectedNode->SetProperty("ColorCoding",mitk::IntProperty::New(15));
mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll();
m_SelectedNode->SetProperty("ColorCoding",mitk::IntProperty::New(18));
mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll();
m_SelectedNode->SetProperty("ColorCoding",mitk::IntProperty::New(1));
mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll();
m_SelectedNode->SetProperty("ColorCoding",mitk::IntProperty::New(2));
mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll();
m_SelectedNode->SetProperty("ColorCoding",mitk::IntProperty::New(3));
mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll();
m_SelectedNode->SetProperty("ColorCoding",mitk::IntProperty::New(4));
mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll();
m_SelectedNode->SetProperty("ColorCoding",mitk::IntProperty::New(0));
mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll();
}
}
void QmitkControlVisualizationPropertiesView::BundleRepresentationTube()
{
if(m_SelectedNode)
{
float radius = m_Controls->m_TubeRadius->value() / 100.0;
m_SelectedNode->SetProperty("TubeRadius",mitk::FloatProperty::New(radius));
m_SelectedNode->SetProperty("ColorCoding",mitk::IntProperty::New(17));
mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll();
m_SelectedNode->SetProperty("ColorCoding",mitk::IntProperty::New(13));
mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll();
m_SelectedNode->SetProperty("ColorCoding",mitk::IntProperty::New(16));
mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll();
m_SelectedNode->SetProperty("ColorCoding",mitk::IntProperty::New(0));
mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll();
}
}
void QmitkControlVisualizationPropertiesView::SetFiberBundleCustomColor(const itk::EventObject& /*e*/)
{
float color[3];
m_SelectedNode->GetColor(color);
m_Controls->m_Color->setAutoFillBackground(true);
QString styleSheet = "background-color:rgb(";
styleSheet.append(QString::number(color[0]*255.0));
styleSheet.append(",");
styleSheet.append(QString::number(color[1]*255.0));
styleSheet.append(",");
styleSheet.append(QString::number(color[2]*255.0));
styleSheet.append(")");
m_Controls->m_Color->setStyleSheet(styleSheet);
m_SelectedNode->SetProperty("color",mitk::ColorProperty::New(color[0], color[1], color[2]));
mitk::FiberBundleX::Pointer fib = dynamic_cast<mitk::FiberBundleX*>(m_SelectedNode->GetData());
fib->SetColorCoding(mitk::FiberBundleX::COLORCODING_CUSTOM);
m_SelectedNode->Modified();
mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll();
}
void QmitkControlVisualizationPropertiesView::BundleRepresentationColor()
{
if(m_SelectedNode)
{
QColor color = QColorDialog::getColor();
if (!color.isValid())
return;
m_Controls->m_Color->setAutoFillBackground(true);
QString styleSheet = "background-color:rgb(";
styleSheet.append(QString::number(color.red()));
styleSheet.append(",");
styleSheet.append(QString::number(color.green()));
styleSheet.append(",");
styleSheet.append(QString::number(color.blue()));
styleSheet.append(")");
m_Controls->m_Color->setStyleSheet(styleSheet);
m_SelectedNode->SetProperty("color",mitk::ColorProperty::New(color.red()/255.0, color.green()/255.0, color.blue()/255.0));
mitk::FiberBundleX::Pointer fib = dynamic_cast<mitk::FiberBundleX*>(m_SelectedNode->GetData());
fib->SetColorCoding(mitk::FiberBundleX::COLORCODING_CUSTOM);
m_SelectedNode->Modified();
mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll();
}
}
void QmitkControlVisualizationPropertiesView::BundleRepresentationResetColoring()
{
if(m_SelectedNode)
{
MITK_INFO << "reset colorcoding to oBased";
m_Controls->m_Color->setAutoFillBackground(true);
QString styleSheet = "background-color:rgb(255,255,255)";
m_Controls->m_Color->setStyleSheet(styleSheet);
// m_SelectedNode->SetProperty("color",NULL);
m_SelectedNode->SetProperty("color",mitk::ColorProperty::New(1.0, 1.0, 1.0));
mitk::FiberBundleX::Pointer fib = dynamic_cast<mitk::FiberBundleX*>(m_SelectedNode->GetData());
fib->SetColorCoding(mitk::FiberBundleX::COLORCODING_ORIENTATION_BASED);
fib->DoColorCodingOrientationBased();
m_SelectedNode->Modified();
mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll();
}
}
void QmitkControlVisualizationPropertiesView::PlanarFigureFocus()
{
if(m_SelectedNode)
{
mitk::PlanarFigure* _PlanarFigure = 0;
_PlanarFigure = dynamic_cast<mitk::PlanarFigure*> (m_SelectedNode->GetData());
if (_PlanarFigure && _PlanarFigure->GetGeometry2D())
{
QmitkRenderWindow* selectedRenderWindow = 0;
bool PlanarFigureInitializedWindow = false;
QmitkRenderWindow* RenderWindow1 =
this->GetActiveStdMultiWidget()->GetRenderWindow1();
if (m_SelectedNode->GetBoolProperty("PlanarFigureInitializedWindow",
PlanarFigureInitializedWindow, RenderWindow1->GetRenderer()))
{
selectedRenderWindow = RenderWindow1;
}
QmitkRenderWindow* RenderWindow2 =
this->GetActiveStdMultiWidget()->GetRenderWindow2();
if (!selectedRenderWindow && m_SelectedNode->GetBoolProperty(
"PlanarFigureInitializedWindow", PlanarFigureInitializedWindow,
RenderWindow2->GetRenderer()))
{
selectedRenderWindow = RenderWindow2;
}
QmitkRenderWindow* RenderWindow3 =
this->GetActiveStdMultiWidget()->GetRenderWindow3();
if (!selectedRenderWindow && m_SelectedNode->GetBoolProperty(
"PlanarFigureInitializedWindow", PlanarFigureInitializedWindow,
RenderWindow3->GetRenderer()))
{
selectedRenderWindow = RenderWindow3;
}
QmitkRenderWindow* RenderWindow4 =
this->GetActiveStdMultiWidget()->GetRenderWindow4();
if (!selectedRenderWindow && m_SelectedNode->GetBoolProperty(
"PlanarFigureInitializedWindow", PlanarFigureInitializedWindow,
RenderWindow4->GetRenderer()))
{
selectedRenderWindow = RenderWindow4;
}
const mitk::PlaneGeometry
* _PlaneGeometry =
dynamic_cast<const mitk::PlaneGeometry*> (_PlanarFigure->GetGeometry2D());
mitk::VnlVector normal = _PlaneGeometry->GetNormalVnl();
mitk::Geometry2D::ConstPointer worldGeometry1 =
RenderWindow1->GetRenderer()->GetCurrentWorldGeometry2D();
mitk::PlaneGeometry::ConstPointer _Plane1 =
dynamic_cast<const mitk::PlaneGeometry*>( worldGeometry1.GetPointer() );
mitk::VnlVector normal1 = _Plane1->GetNormalVnl();
mitk::Geometry2D::ConstPointer worldGeometry2 =
RenderWindow2->GetRenderer()->GetCurrentWorldGeometry2D();
mitk::PlaneGeometry::ConstPointer _Plane2 =
dynamic_cast<const mitk::PlaneGeometry*>( worldGeometry2.GetPointer() );
mitk::VnlVector normal2 = _Plane2->GetNormalVnl();
mitk::Geometry2D::ConstPointer worldGeometry3 =
RenderWindow3->GetRenderer()->GetCurrentWorldGeometry2D();
mitk::PlaneGeometry::ConstPointer _Plane3 =
dynamic_cast<const mitk::PlaneGeometry*>( worldGeometry3.GetPointer() );
mitk::VnlVector normal3 = _Plane3->GetNormalVnl();
normal[0] = fabs(normal[0]); normal[1] = fabs(normal[1]); normal[2] = fabs(normal[2]);
normal1[0] = fabs(normal1[0]); normal1[1] = fabs(normal1[1]); normal1[2] = fabs(normal1[2]);
normal2[0] = fabs(normal2[0]); normal2[1] = fabs(normal2[1]); normal2[2] = fabs(normal2[2]);
normal3[0] = fabs(normal3[0]); normal3[1] = fabs(normal3[1]); normal3[2] = fabs(normal3[2]);
double ang1 = angle(normal, normal1);
double ang2 = angle(normal, normal2);
double ang3 = angle(normal, normal3);
if(ang1 < ang2 && ang1 < ang3)
{
selectedRenderWindow = RenderWindow1;
}
else
{
if(ang2 < ang3)
{
selectedRenderWindow = RenderWindow2;
}
else
{
selectedRenderWindow = RenderWindow3;
}
}
// make node visible
if (selectedRenderWindow)
{
const mitk::Point3D& centerP = _PlaneGeometry->GetOrigin();
selectedRenderWindow->GetSliceNavigationController()->ReorientSlices(
centerP, _PlaneGeometry->GetNormal());
}
}
// set interactor for new node (if not already set)
mitk::PlanarFigureInteractor::Pointer figureInteractor
= dynamic_cast<mitk::PlanarFigureInteractor*>(m_SelectedNode->GetDataInteractor().GetPointer());
if(figureInteractor.IsNull())
{
figureInteractor = mitk::PlanarFigureInteractor::New();
us::Module* planarFigureModule = us::ModuleRegistry::GetModule( "MitkPlanarFigure" );
figureInteractor->LoadStateMachine("PlanarFigureInteraction.xml", planarFigureModule );
figureInteractor->SetEventConfig( "PlanarFigureConfig.xml", planarFigureModule );
figureInteractor->SetDataNode( m_SelectedNode );
}
m_SelectedNode->SetProperty("planarfigure.iseditable",mitk::BoolProperty::New(true));
}
}
void QmitkControlVisualizationPropertiesView::SetInteractor()
{
typedef std::vector<mitk::DataNode*> Container;
Container _NodeSet = this->GetDataManagerSelection();
mitk::DataNode* node = 0;
mitk::FiberBundleX* bundle = 0;
mitk::FiberBundleInteractor::Pointer bundleInteractor = 0;
// finally add all nodes to the model
for(Container::const_iterator it=_NodeSet.begin(); it!=_NodeSet.end()
; it++)
{
node = const_cast<mitk::DataNode*>(*it);
bundle = dynamic_cast<mitk::FiberBundleX*>(node->GetData());
if(bundle)
{
bundleInteractor = dynamic_cast<mitk::FiberBundleInteractor*>(node->GetInteractor());
if(bundleInteractor.IsNotNull())
mitk::GlobalInteraction::GetInstance()->RemoveInteractor(bundleInteractor);
if(!m_Controls->m_Crosshair->isChecked())
{
m_Controls->m_Crosshair->setChecked(false);
this->GetActiveStdMultiWidget()->GetRenderWindow4()->setCursor(Qt::ArrowCursor);
m_CurrentPickingNode = 0;
}
else
{
m_Controls->m_Crosshair->setChecked(true);
bundleInteractor = mitk::FiberBundleInteractor::New("FiberBundleInteractor", node);
mitk::GlobalInteraction::GetInstance()->AddInteractor(bundleInteractor);
this->GetActiveStdMultiWidget()->GetRenderWindow4()->setCursor(Qt::CrossCursor);
m_CurrentPickingNode = node;
}
}
}
}
void QmitkControlVisualizationPropertiesView::PFWidth(int w)
{
double width = w/10.0;
m_SelectedNode->SetProperty("planarfigure.line.width", mitk::FloatProperty::New(width) );
m_SelectedNode->SetProperty("planarfigure.shadow.widthmodifier", mitk::FloatProperty::New(width) );
m_SelectedNode->SetProperty("planarfigure.outline.width", mitk::FloatProperty::New(width) );
m_SelectedNode->SetProperty("planarfigure.helperline.width", mitk::FloatProperty::New(width) );
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
QString label = "Width %1";
label = label.arg(width);
m_Controls->label_pfwidth->setText(label);
}
void QmitkControlVisualizationPropertiesView::PFColor()
{
QColor color = QColorDialog::getColor();
if (!color.isValid())
return;
m_Controls->m_PFColor->setAutoFillBackground(true);
QString styleSheet = "background-color:rgb(";
styleSheet.append(QString::number(color.red()));
styleSheet.append(",");
styleSheet.append(QString::number(color.green()));
styleSheet.append(",");
styleSheet.append(QString::number(color.blue()));
styleSheet.append(")");
m_Controls->m_PFColor->setStyleSheet(styleSheet);
m_SelectedNode->SetProperty( "planarfigure.default.line.color", mitk::ColorProperty::New(color.red()/255.0, color.green()/255.0, color.blue()/255.0));
m_SelectedNode->SetProperty( "planarfigure.default.outline.color", mitk::ColorProperty::New(color.red()/255.0, color.green()/255.0, color.blue()/255.0));
m_SelectedNode->SetProperty( "planarfigure.default.helperline.color", mitk::ColorProperty::New(color.red()/255.0, color.green()/255.0, color.blue()/255.0));
m_SelectedNode->SetProperty( "planarfigure.default.markerline.color", mitk::ColorProperty::New(color.red()/255.0, color.green()/255.0, color.blue()/255.0));
m_SelectedNode->SetProperty( "planarfigure.default.marker.color", mitk::ColorProperty::New(color.red()/255.0, color.green()/255.0, color.blue()/255.0));
m_SelectedNode->SetProperty( "planarfigure.hover.line.color", mitk::ColorProperty::New(color.red()/255.0, color.green()/255.0, color.blue()/255.0) );
m_SelectedNode->SetProperty( "planarfigure.hover.outline.color", mitk::ColorProperty::New(color.red()/255.0, color.green()/255.0, color.blue()/255.0) );
m_SelectedNode->SetProperty( "planarfigure.hover.helperline.color", mitk::ColorProperty::New(color.red()/255.0, color.green()/255.0, color.blue()/255.0) );
m_SelectedNode->SetProperty( "color", mitk::ColorProperty::New(color.red()/255.0, color.green()/255.0, color.blue()/255.0));
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkControlVisualizationPropertiesView::GenerateTdi()
{
if(m_SelectedNode)
{
mitk::FiberBundleX* bundle = dynamic_cast<mitk::FiberBundleX*>(m_SelectedNode->GetData());
if(!bundle)
return;
typedef float OutPixType;
typedef itk::Image<OutPixType, 3> OutImageType;
// run generator
itk::TractDensityImageFilter< OutImageType >::Pointer generator = itk::TractDensityImageFilter< OutImageType >::New();
generator->SetFiberBundle(bundle);
generator->SetOutputAbsoluteValues(true);
generator->SetUpsamplingFactor(1);
generator->Update();
// get result
OutImageType::Pointer outImg = generator->GetOutput();
mitk::Image::Pointer img = mitk::Image::New();
img->InitializeByItk(outImg.GetPointer());
img->SetVolume(outImg->GetBufferPointer());
// to datastorage
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData(img);
QString name(m_SelectedNode->GetName().c_str());
name += "_TDI";
node->SetName(name.toStdString());
node->SetVisibility(true);
GetDataStorage()->Add(node);
}
}
void QmitkControlVisualizationPropertiesView::LineWidthChanged(int w)
{
QString label = "Width %1";
label = label.arg(w);
m_Controls->label_linewidth->setText(label);
BundleRepresentationWire();
}
void QmitkControlVisualizationPropertiesView::TubeRadiusChanged(int r)
{
QString label = "Radius %1";
label = label.arg(r / 100.0);
m_Controls->label_tuberadius->setText(label);
this->BundleRepresentationTube();
}
void QmitkControlVisualizationPropertiesView::Welcome()
{
berry::PlatformUI::GetWorkbench()->GetIntroManager()->ShowIntro(
GetSite()->GetWorkbenchWindow(), false);
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkDwiSoftwarePhantomView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkDwiSoftwarePhantomView.cpp
index db330266b4..3154a0d37a 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkDwiSoftwarePhantomView.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkDwiSoftwarePhantomView.cpp
@@ -1,496 +1,496 @@
/*===================================================================
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.
===================================================================*/
// Qmitk
#include "QmitkDwiSoftwarePhantomView.h"
// MITK
#include <mitkDiffusionImage.h>
#include <mitkImageToItk.h>
#include <mitkImageCast.h>
#include <itkDwiPhantomGenerationFilter.h>
#define _USE_MATH_DEFINES
#include <math.h>
const std::string QmitkDwiSoftwarePhantomView::VIEW_ID = "org.mitk.views.dwisoftwarephantomview";
QmitkDwiSoftwarePhantomView::QmitkDwiSoftwarePhantomView()
: QmitkFunctionality()
, m_Controls( 0 )
, m_MultiWidget( NULL )
{
}
// Destructor
QmitkDwiSoftwarePhantomView::~QmitkDwiSoftwarePhantomView()
{
}
void QmitkDwiSoftwarePhantomView::CreateQtPartControl( QWidget *parent )
{
// build up qt view, unless already done
if ( !m_Controls )
{
// create GUI widgets from the Qt Designer's .ui file
m_Controls = new Ui::QmitkDwiSoftwarePhantomViewControls;
m_Controls->setupUi( parent );
m_Controls->m_SignalRegionBox->setVisible(false);
connect((QObject*) m_Controls->m_GeneratePhantomButton, SIGNAL(clicked()), (QObject*) this, SLOT(GeneratePhantom()));
connect((QObject*) m_Controls->m_SimulateBaseline, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnSimulateBaselineToggle(int)));
}
}
QmitkDwiSoftwarePhantomView::GradientListType QmitkDwiSoftwarePhantomView::GenerateHalfShell(int NPoints)
{
NPoints *= 2;
vnl_vector<double> theta; theta.set_size(NPoints);
vnl_vector<double> phi; phi.set_size(NPoints);
double C = sqrt(4*M_PI);
phi(0) = 0.0;
phi(NPoints-1) = 0.0;
for(int i=0; i<NPoints; i++)
{
theta(i) = acos(-1.0+2.0*i/(NPoints-1.0)) - M_PI / 2.0;
if( i>0 && i<NPoints-1)
{
phi(i) = (phi(i-1) + C /
sqrt(NPoints*(1-(-1.0+2.0*i/(NPoints-1.0))*(-1.0+2.0*i/(NPoints-1.0)))));
// % (2*DIST_POINTSHELL_PI);
}
}
GradientListType pointshell;
int numB0 = NPoints/10;
if (numB0==0)
numB0=1;
GradientType g;
g.Fill(0.0);
for (int i=0; i<numB0; i++)
pointshell.push_back(g);
for(int i=0; i<NPoints; i++)
{
g[2] = sin(theta(i));
if (g[2]<0)
continue;
g[0] = cos(theta(i)) * cos(phi(i));
g[1] = cos(theta(i)) * sin(phi(i));
pointshell.push_back(g);
}
return pointshell;
}
template<int ndirs>
std::vector<itk::Vector<double,3> > QmitkDwiSoftwarePhantomView::MakeGradientList()
{
std::vector<itk::Vector<double,3> > retval;
vnl_matrix_fixed<double, 3, ndirs>* U =
itk::PointShell<ndirs, vnl_matrix_fixed<double, 3, ndirs> >::DistributePointShell();
// Add 0 vector for B0
int numB0 = ndirs/10;
if (numB0==0)
numB0=1;
itk::Vector<double,3> v;
v.Fill(0.0);
for (int i=0; i<numB0; i++)
{
retval.push_back(v);
}
for(int i=0; i<ndirs;i++)
{
itk::Vector<double,3> v;
v[0] = U->get(0,i); v[1] = U->get(1,i); v[2] = U->get(2,i);
retval.push_back(v);
}
return retval;
}
void QmitkDwiSoftwarePhantomView::OnSimulateBaselineToggle(int state)
{
if (state)
{
m_Controls->m_NoiseLabel->setText("Noise Variance:");
m_Controls->m_NoiseLevel->setValue(1.0/(m_Controls->m_NoiseLevel->value()*m_Controls->m_NoiseLevel->value()));
m_Controls->m_NoiseLevel->setToolTip("Variance of Rician noise.");
}
else
{
m_Controls->m_NoiseLabel->setText("SNR:");
if (m_Controls->m_NoiseLevel->value()>0)
m_Controls->m_NoiseLevel->setValue(1.0/(sqrt(m_Controls->m_NoiseLevel->value())));
else
m_Controls->m_NoiseLevel->setValue(0.0001);
m_Controls->m_NoiseLevel->setToolTip("Signal to noise ratio (for values > 99, no noise at all is added to the image).");
}
}
void QmitkDwiSoftwarePhantomView::GeneratePhantom()
{
typedef itk::DwiPhantomGenerationFilter< short > FilterType;
FilterType::GradientListType gradientList;
m_SignalRegions.clear();
for (int i=0; i<m_SignalRegionNodes.size(); i++)
{
mitk::Image::Pointer mitkBinaryImg = dynamic_cast<mitk::Image*>(m_SignalRegionNodes.at(i)->GetData());
ItkUcharImgType::Pointer signalRegion = ItkUcharImgType::New();
mitk::CastToItkImage<ItkUcharImgType>(mitkBinaryImg, signalRegion);
m_SignalRegions.push_back(signalRegion);
}
gradientList = GenerateHalfShell(m_Controls->m_NumGradientsBox->value());
// switch(m_Controls->m_NumGradientsBox->value())
// {
// case 0:
// gradientList = MakeGradientList<12>();
// break;
// case 1:
// gradientList = MakeGradientList<42>();
// break;
// case 2:
// gradientList = MakeGradientList<92>();
// break;
// case 3:
// gradientList = MakeGradientList<162>();
// break;
// case 4:
// gradientList = MakeGradientList<252>();
// break;
// case 5:
// gradientList = MakeGradientList<362>();
// break;
// case 6:
// gradientList = MakeGradientList<492>();
// break;
// case 7:
// gradientList = MakeGradientList<642>();
// break;
// case 8:
// gradientList = MakeGradientList<812>();
// break;
// case 9:
// gradientList = MakeGradientList<1002>();
// break;
// default:
// gradientList = MakeGradientList<92>();
// }
double bVal = m_Controls->m_TensorsToDWIBValueEdit->value();
itk::ImageRegion<3> imageRegion;
imageRegion.SetSize(0, m_Controls->m_SizeX->value());
imageRegion.SetSize(1, m_Controls->m_SizeY->value());
imageRegion.SetSize(2, m_Controls->m_SizeZ->value());
mitk::Vector3D spacing;
spacing[0] = m_Controls->m_SpacingX->value();
spacing[1] = m_Controls->m_SpacingY->value();
spacing[2] = m_Controls->m_SpacingZ->value();
FilterType::Pointer filter = FilterType::New();
filter->SetGradientList(gradientList);
filter->SetBValue(bVal);
filter->SetNoiseVariance(m_Controls->m_NoiseLevel->value());
filter->SetImageRegion(imageRegion);
filter->SetSpacing(spacing);
filter->SetSignalRegions(m_SignalRegions);
filter->SetGreyMatterAdc(m_Controls->m_GmAdc->value());
std::vector< float > tensorFA;
std::vector< float > tensorADC;
std::vector< float > tensorWeight;
std::vector< vnl_vector_fixed<double, 3> > tensorDirection;
for (int i=0; i<m_SpinFa.size(); i++)
{
tensorFA.push_back(m_SpinFa.at(i)->value());
tensorADC.push_back(m_SpinAdc.at(i)->value());
vnl_vector_fixed<double, 3> dir;
dir[0] = m_SpinX.at(i)->value();
dir[1] = m_SpinY.at(i)->value();
dir[2] = m_SpinZ.at(i)->value();
dir.normalize();
tensorDirection.push_back(dir);
tensorWeight.push_back(m_SpinWeight.at(i)->value());
}
filter->SetTensorFA(tensorFA);
filter->SetTensorADC(tensorADC);
filter->SetTensorWeight(tensorWeight);
filter->SetTensorDirection(tensorDirection);
if (!m_Controls->m_SimulateBaseline->isChecked())
filter->SetSimulateBaseline(false);
else
filter->SetSimulateBaseline(true);
filter->Update();
mitk::DiffusionImage<short>::Pointer image = mitk::DiffusionImage<short>::New();
image->SetVectorImage( filter->GetOutput() );
image->SetReferenceBValue(bVal);
image->SetDirections(gradientList);
image->InitializeFromVectorImage();
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData( image );
node->SetName(m_Controls->m_ImageName->text().toStdString());
GetDataStorage()->Add(node);
mitk::BaseData::Pointer basedata = node->GetData();
if (basedata.IsNotNull())
{
mitk::RenderingManager::GetInstance()->InitializeViews(
basedata->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true );
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
if (m_Controls->m_OutputNumDirectionsBox->isChecked())
{
ItkUcharImgType::Pointer numDirImage = filter->GetNumDirectionsImage();
mitk::Image::Pointer image = mitk::Image::New();
image->InitializeByItk( numDirImage.GetPointer() );
image->SetVolume( numDirImage->GetBufferPointer() );
mitk::DataNode::Pointer node2 = mitk::DataNode::New();
node2->SetData(image);
QString name(m_Controls->m_ImageName->text());
name += "_NumDirections";
node2->SetName(name.toStdString().c_str());
GetDataStorage()->Add(node2);
}
if (m_Controls->m_OutputSnrImageBox->isChecked())
{
ItkFloatImgType::Pointer snrImage = filter->GetSNRImage();
mitk::Image::Pointer image = mitk::Image::New();
image->InitializeByItk( snrImage.GetPointer() );
image->SetVolume( snrImage->GetBufferPointer() );
mitk::DataNode::Pointer node2 = mitk::DataNode::New();
node2->SetData(image);
QString name(m_Controls->m_ImageName->text());
name += "_SNR";
node2->SetName(name.toStdString().c_str());
GetDataStorage()->Add(node2);
}
if (m_SignalRegionNodes.size()==0)
return;
if (m_Controls->m_OutputDirectionImagesBox->isChecked())
{
typedef FilterType::ItkDirectionImageContainer ItkDirectionImageContainer;
ItkDirectionImageContainer::Pointer container = filter->GetDirectionImageContainer();
for (int i=0; i<container->Size(); i++)
{
FilterType::ItkDirectionImage::Pointer itkImg = container->GetElement(i);
mitk::Image::Pointer img = mitk::Image::New();
img->InitializeByItk( itkImg.GetPointer() );
img->SetVolume( itkImg->GetBufferPointer() );
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData(img);
QString name(m_Controls->m_ImageName->text());
name += "_Direction";
name += QString::number(i+1);
node->SetName(name.toStdString().c_str());
GetDataStorage()->Add(node);
}
}
if (m_Controls->m_OutputVectorFieldBox->isChecked())
{
- mitk::Geometry3D::Pointer geometry = image->GetGeometry();
+ mitk::BaseGeometry::Pointer geometry = image->GetGeometry();
mitk::Vector3D outImageSpacing = geometry->GetSpacing();
float minSpacing = 1;
if(outImageSpacing[0]<outImageSpacing[1] && outImageSpacing[0]<outImageSpacing[2])
minSpacing = outImageSpacing[0];
else if (outImageSpacing[1] < outImageSpacing[2])
minSpacing = outImageSpacing[1];
else
minSpacing = outImageSpacing[2];
mitk::FiberBundleX::Pointer directions = filter->GetOutputFiberBundle();
directions->SetGeometry(geometry);
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData(directions);
QString name(m_Controls->m_ImageName->text());
name += "_VectorField";
node->SetName(name.toStdString().c_str());
node->SetProperty("Fiber2DSliceThickness", mitk::FloatProperty::New(minSpacing));
node->SetProperty("Fiber2DfadeEFX", mitk::BoolProperty::New(false));
GetDataStorage()->Add(node);
}
}
void QmitkDwiSoftwarePhantomView::UpdateGui()
{
if (!m_SignalRegionNodes.empty())
{
m_Controls->m_SignalRegionBox->setVisible(true);
m_Controls->m_Instruction->setVisible(false);
}
else
{
m_Controls->m_SignalRegionBox->setVisible(false);
m_Controls->m_Instruction->setVisible(true);
}
QLayout* layout = m_Controls->m_SignalRegionBox->layout();
for (int i=0; i<m_Labels.size(); i++)
{
delete m_Labels.at(i);
}
for (int i=0; i<m_SpinFa.size(); i++)
{
delete m_SpinFa.at(i);
delete m_SpinAdc.at(i);
delete m_SpinX.at(i);
delete m_SpinY.at(i);
delete m_SpinZ.at(i);
delete m_SpinWeight.at(i);
}
m_Labels.clear();
m_SpinFa.clear();
m_SpinAdc.clear();
m_SpinX.clear();
m_SpinY.clear();
m_SpinZ.clear();
m_SpinWeight.clear();
if (layout)
delete layout;
QGridLayout* newlayout = new QGridLayout();
m_Controls->m_SignalRegionBox->setLayout(newlayout);
if (!m_SignalRegionNodes.empty())
{
QLabel* label1 = new QLabel("Image");
newlayout->addWidget(label1,0,0);
m_Labels.push_back(label1);
QLabel* label2 = new QLabel("FA");
newlayout->addWidget(label2,0,1);
m_Labels.push_back(label2);
QLabel* label3 = new QLabel("ADC");
newlayout->addWidget(label3,0,2);
m_Labels.push_back(label3);
QLabel* label4 = new QLabel("X");
newlayout->addWidget(label4,0,03);
m_Labels.push_back(label4);
QLabel* label5 = new QLabel("Y");
newlayout->addWidget(label5,0,4);
m_Labels.push_back(label5);
QLabel* label6 = new QLabel("Z");
newlayout->addWidget(label6,0,5);
m_Labels.push_back(label6);
QLabel* label7 = new QLabel("Weight");
newlayout->addWidget(label7,0,6);
m_Labels.push_back(label7);
}
for (int i=0; i<m_SignalRegionNodes.size(); i++)
{
QLabel* label = new QLabel(m_SignalRegionNodes.at(i)->GetName().c_str());
newlayout->addWidget(label,i+1,0);
m_Labels.push_back(label);
QDoubleSpinBox* spinFa = new QDoubleSpinBox();
spinFa->setValue(0.7);
spinFa->setMinimum(0);
spinFa->setMaximum(1);
spinFa->setSingleStep(0.1);
newlayout->addWidget(spinFa,i+1,1);
m_SpinFa.push_back(spinFa);
QDoubleSpinBox* spinAdc = new QDoubleSpinBox();
newlayout->addWidget(spinAdc,i+1,2);
spinAdc->setMinimum(0);
spinAdc->setMaximum(1);
spinAdc->setSingleStep(0.001);
spinAdc->setDecimals(3);
spinAdc->setValue(0.001); ///// ???????????????????????????
m_SpinAdc.push_back(spinAdc);
QDoubleSpinBox* spinX = new QDoubleSpinBox();
newlayout->addWidget(spinX,i+1,3);
spinX->setValue(1);
spinX->setMinimum(-1);
spinX->setMaximum(1);
spinX->setSingleStep(0.1);
m_SpinX.push_back(spinX);
QDoubleSpinBox* spinY = new QDoubleSpinBox();
newlayout->addWidget(spinY,i+1,4);
spinY->setMinimum(-1);
spinY->setMaximum(1);
spinY->setSingleStep(0.1);
m_SpinY.push_back(spinY);
QDoubleSpinBox* spinZ = new QDoubleSpinBox();
newlayout->addWidget(spinZ,i+1,5);
spinZ->setMinimum(-1);
spinZ->setMaximum(1);
spinZ->setSingleStep(0.1);
m_SpinZ.push_back(spinZ);
QDoubleSpinBox* spinWeight = new QDoubleSpinBox();
newlayout->addWidget(spinWeight,i+1,6);
spinWeight->setMinimum(0);
spinWeight->setMaximum(1);
spinWeight->setSingleStep(0.1);
spinWeight->setValue(1.0);
m_SpinWeight.push_back(spinWeight);
}
}
void QmitkDwiSoftwarePhantomView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget)
{
m_MultiWidget = &stdMultiWidget;
}
void QmitkDwiSoftwarePhantomView::StdMultiWidgetNotAvailable()
{
m_MultiWidget = NULL;
}
void QmitkDwiSoftwarePhantomView::OnSelectionChanged( std::vector<mitk::DataNode*> nodes )
{
m_SignalRegionNodes.clear();
// iterate all selected objects, adjust warning visibility
for( std::vector<mitk::DataNode*>::iterator it = nodes.begin(); it != nodes.end(); ++it )
{
mitk::DataNode::Pointer node = *it;
if( node.IsNotNull() && dynamic_cast<mitk::Image*>(node->GetData()) )
{
bool isBinary = false;
node->GetPropertyValue<bool>("binary", isBinary);
if (isBinary)
m_SignalRegionNodes.push_back(node);
}
}
UpdateGui();
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberExtractionView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberExtractionView.cpp
index 40962c1646..b008e2de6b 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberExtractionView.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberExtractionView.cpp
@@ -1,1452 +1,1452 @@
/*===================================================================
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.
===================================================================*/
// Blueberry
#include <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>
// Qmitk
#include "QmitkFiberExtractionView.h"
#include <QmitkStdMultiWidget.h>
// Qt
#include <QMessageBox>
// MITK
#include <mitkNodePredicateProperty.h>
#include <mitkImageCast.h>
#include <mitkPointSet.h>
#include <mitkPlanarCircle.h>
#include <mitkPlanarPolygon.h>
#include <mitkPlanarRectangle.h>
#include <mitkPlanarFigureInteractor.h>
#include <mitkGlobalInteraction.h>
#include <mitkImageAccessByItk.h>
#include <mitkDataNodeObject.h>
#include <mitkDiffusionImage.h>
#include <mitkTensorImage.h>
#include "usModuleRegistry.h"
// ITK
#include <itkResampleImageFilter.h>
#include <itkGaussianInterpolateImageFunction.h>
#include <itkImageRegionIteratorWithIndex.h>
#include <itkTractsToFiberEndingsImageFilter.h>
#include <itkTractDensityImageFilter.h>
#include <itkImageRegion.h>
#include <itkTractsToRgbaImageFilter.h>
#include <math.h>
const std::string QmitkFiberExtractionView::VIEW_ID = "org.mitk.views.fiberextraction";
const std::string id_DataManager = "org.mitk.views.datamanager";
using namespace mitk;
QmitkFiberExtractionView::QmitkFiberExtractionView()
: QmitkFunctionality()
, m_Controls( 0 )
, m_MultiWidget( NULL )
, m_CircleCounter(0)
, m_PolygonCounter(0)
, m_UpsamplingFactor(1)
, m_LastAddedPf(NULL)
{
}
// Destructor
QmitkFiberExtractionView::~QmitkFiberExtractionView()
{
}
void QmitkFiberExtractionView::CreateQtPartControl( QWidget *parent )
{
// build up qt view, unless already done
if ( !m_Controls )
{
// create GUI widgets from the Qt Designer's .ui file
m_Controls = new Ui::QmitkFiberExtractionViewControls;
m_Controls->setupUi( parent );
m_Controls->doExtractFibersButton->setDisabled(true);
m_Controls->PFCompoANDButton->setDisabled(true);
m_Controls->PFCompoORButton->setDisabled(true);
m_Controls->PFCompoNOTButton->setDisabled(true);
m_Controls->m_PlanarFigureButtonsFrame->setEnabled(false);
m_Controls->m_RectangleButton->setVisible(false);
connect( m_Controls->m_CircleButton, SIGNAL( clicked() ), this, SLOT( OnDrawCircle() ) );
connect( m_Controls->m_PolygonButton, SIGNAL( clicked() ), this, SLOT( OnDrawPolygon() ) );
connect(m_Controls->PFCompoANDButton, SIGNAL(clicked()), this, SLOT(GenerateAndComposite()) );
connect(m_Controls->PFCompoORButton, SIGNAL(clicked()), this, SLOT(GenerateOrComposite()) );
connect(m_Controls->PFCompoNOTButton, SIGNAL(clicked()), this, SLOT(GenerateNotComposite()) );
connect(m_Controls->m_JoinBundles, SIGNAL(clicked()), this, SLOT(JoinBundles()) );
connect(m_Controls->m_SubstractBundles, SIGNAL(clicked()), this, SLOT(SubstractBundles()) );
connect(m_Controls->m_GenerateRoiImage, SIGNAL(clicked()), this, SLOT(GenerateRoiImage()) );
connect(m_Controls->m_Extract3dButton, SIGNAL(clicked()), this, SLOT(ExtractPassingMask()));
connect( m_Controls->m_ExtractMask, SIGNAL(clicked()), this, SLOT(ExtractEndingInMask()) );
connect( m_Controls->doExtractFibersButton, SIGNAL(clicked()), this, SLOT(DoFiberExtraction()) );
connect( m_Controls->m_RemoveOutsideMaskButton, SIGNAL(clicked()), this, SLOT(DoRemoveOutsideMask()));
connect( m_Controls->m_RemoveInsideMaskButton, SIGNAL(clicked()), this, SLOT(DoRemoveInsideMask()));
}
}
void QmitkFiberExtractionView::DoRemoveInsideMask()
{
if (m_MaskImageNode.IsNull())
return;
mitk::Image::Pointer mitkMask = dynamic_cast<mitk::Image*>(m_MaskImageNode->GetData());
for (unsigned int i=0; i<m_SelectedFB.size(); i++)
{
mitk::FiberBundleX::Pointer fib = dynamic_cast<mitk::FiberBundleX*>(m_SelectedFB.at(i)->GetData());
QString name(m_SelectedFB.at(i)->GetName().c_str());
itkUCharImageType::Pointer mask = itkUCharImageType::New();
mitk::CastToItkImage<itkUCharImageType>(mitkMask, mask);
mitk::FiberBundleX::Pointer newFib = fib->RemoveFibersOutside(mask, true);
if (newFib->GetNumFibers()<=0)
{
QMessageBox::information(NULL, "No output generated:", "The resulting fiber bundle contains no fibers.");
continue;
}
DataNode::Pointer newNode = DataNode::New();
newNode->SetData(newFib);
name += "_Cut";
newNode->SetName(name.toStdString());
GetDefaultDataStorage()->Add(newNode);
m_SelectedFB.at(i)->SetVisibility(false);
}
}
void QmitkFiberExtractionView::DoRemoveOutsideMask()
{
if (m_MaskImageNode.IsNull())
return;
mitk::Image::Pointer mitkMask = dynamic_cast<mitk::Image*>(m_MaskImageNode->GetData());
for (unsigned int i=0; i<m_SelectedFB.size(); i++)
{
mitk::FiberBundleX::Pointer fib = dynamic_cast<mitk::FiberBundleX*>(m_SelectedFB.at(i)->GetData());
QString name(m_SelectedFB.at(i)->GetName().c_str());
itkUCharImageType::Pointer mask = itkUCharImageType::New();
mitk::CastToItkImage<itkUCharImageType>(mitkMask, mask);
mitk::FiberBundleX::Pointer newFib = fib->RemoveFibersOutside(mask);
if (newFib->GetNumFibers()<=0)
{
QMessageBox::information(NULL, "No output generated:", "The resulting fiber bundle contains no fibers.");
continue;
}
DataNode::Pointer newNode = DataNode::New();
newNode->SetData(newFib);
name += "_Cut";
newNode->SetName(name.toStdString());
GetDefaultDataStorage()->Add(newNode);
m_SelectedFB.at(i)->SetVisibility(false);
}
}
void QmitkFiberExtractionView::ExtractEndingInMask()
{
if (m_MaskImageNode.IsNull())
return;
mitk::Image::Pointer mitkMask = dynamic_cast<mitk::Image*>(m_MaskImageNode->GetData());
for (unsigned int i=0; i<m_SelectedFB.size(); i++)
{
mitk::FiberBundleX::Pointer fib = dynamic_cast<mitk::FiberBundleX*>(m_SelectedFB.at(i)->GetData());
QString name(m_SelectedFB.at(i)->GetName().c_str());
itkUCharImageType::Pointer mask = itkUCharImageType::New();
mitk::CastToItkImage<itkUCharImageType>(mitkMask, mask);
mitk::FiberBundleX::Pointer newFib = fib->ExtractFiberSubset(mask, false);
if (newFib->GetNumFibers()<=0)
{
QMessageBox::information(NULL, "No output generated:", "The resulting fiber bundle contains no fibers.");
continue;
}
DataNode::Pointer newNode = DataNode::New();
newNode->SetData(newFib);
name += "_ending-in-mask";
newNode->SetName(name.toStdString());
GetDefaultDataStorage()->Add(newNode);
m_SelectedFB.at(i)->SetVisibility(false);
}
}
void QmitkFiberExtractionView::ExtractPassingMask()
{
if (m_MaskImageNode.IsNull())
return;
mitk::Image::Pointer mitkMask = dynamic_cast<mitk::Image*>(m_MaskImageNode->GetData());
for (unsigned int i=0; i<m_SelectedFB.size(); i++)
{
mitk::FiberBundleX::Pointer fib = dynamic_cast<mitk::FiberBundleX*>(m_SelectedFB.at(i)->GetData());
QString name(m_SelectedFB.at(i)->GetName().c_str());
itkUCharImageType::Pointer mask = itkUCharImageType::New();
mitk::CastToItkImage<itkUCharImageType>(mitkMask, mask);
mitk::FiberBundleX::Pointer newFib = fib->ExtractFiberSubset(mask, true);
if (newFib->GetNumFibers()<=0)
{
QMessageBox::information(NULL, "No output generated:", "The resulting fiber bundle contains no fibers.");
continue;
}
DataNode::Pointer newNode = DataNode::New();
newNode->SetData(newFib);
name += "_passing-mask";
newNode->SetName(name.toStdString());
GetDefaultDataStorage()->Add(newNode);
m_SelectedFB.at(i)->SetVisibility(false);
}
}
void QmitkFiberExtractionView::GenerateRoiImage(){
if (m_SelectedPF.empty())
return;
- mitk::Geometry3D::Pointer geometry;
+ mitk::BaseGeometry::Pointer geometry;
if (!m_SelectedFB.empty())
{
mitk::FiberBundleX::Pointer fib = dynamic_cast<mitk::FiberBundleX*>(m_SelectedFB.front()->GetData());
geometry = fib->GetGeometry();
}
else if (m_SelectedImage)
geometry = m_SelectedImage->GetGeometry();
else
return;
itk::Vector<double,3> spacing = geometry->GetSpacing();
spacing /= m_UpsamplingFactor;
mitk::Point3D newOrigin = geometry->GetOrigin();
mitk::Geometry3D::BoundsArrayType bounds = geometry->GetBounds();
newOrigin[0] += bounds.GetElement(0);
newOrigin[1] += bounds.GetElement(2);
newOrigin[2] += bounds.GetElement(4);
itk::Matrix<double, 3, 3> direction;
itk::ImageRegion<3> imageRegion;
for (int i=0; i<3; i++)
for (int j=0; j<3; j++)
direction[j][i] = geometry->GetMatrixColumn(i)[j]/spacing[j];
imageRegion.SetSize(0, geometry->GetExtent(0)*m_UpsamplingFactor);
imageRegion.SetSize(1, geometry->GetExtent(1)*m_UpsamplingFactor);
imageRegion.SetSize(2, geometry->GetExtent(2)*m_UpsamplingFactor);
m_PlanarFigureImage = itkUCharImageType::New();
m_PlanarFigureImage->SetSpacing( spacing ); // Set the image spacing
m_PlanarFigureImage->SetOrigin( newOrigin ); // Set the image origin
m_PlanarFigureImage->SetDirection( direction ); // Set the image direction
m_PlanarFigureImage->SetRegions( imageRegion );
m_PlanarFigureImage->Allocate();
m_PlanarFigureImage->FillBuffer( 0 );
Image::Pointer tmpImage = Image::New();
tmpImage->InitializeByItk(m_PlanarFigureImage.GetPointer());
tmpImage->SetVolume(m_PlanarFigureImage->GetBufferPointer());
for (unsigned int i=0; i<m_SelectedPF.size(); i++)
CompositeExtraction(m_SelectedPF.at(i), tmpImage);
DataNode::Pointer node = DataNode::New();
tmpImage = Image::New();
tmpImage->InitializeByItk(m_PlanarFigureImage.GetPointer());
tmpImage->SetVolume(m_PlanarFigureImage->GetBufferPointer());
node->SetData(tmpImage);
node->SetName("ROI Image");
this->GetDefaultDataStorage()->Add(node);
}
void QmitkFiberExtractionView::CompositeExtraction(mitk::DataNode::Pointer node, mitk::Image* image)
{
if (dynamic_cast<mitk::PlanarFigure*>(node.GetPointer()->GetData()) && !dynamic_cast<mitk::PlanarFigureComposite*>(node.GetPointer()->GetData()))
{
m_PlanarFigure = dynamic_cast<mitk::PlanarFigure*>(node.GetPointer()->GetData());
AccessFixedDimensionByItk_2(
image,
InternalReorientImagePlane, 3,
m_PlanarFigure->GetGeometry(), -1);
AccessFixedDimensionByItk_2(
m_InternalImage,
InternalCalculateMaskFromPlanarFigure,
3, 2, node->GetName() );
}
}
template < typename TPixel, unsigned int VImageDimension >
-void QmitkFiberExtractionView::InternalReorientImagePlane( const itk::Image< TPixel, VImageDimension > *image, mitk::Geometry3D* planegeo3D, int additionalIndex )
+void QmitkFiberExtractionView::InternalReorientImagePlane( const itk::Image< TPixel, VImageDimension > *image, mitk::BaseGeometry* planegeo3D, int additionalIndex )
{
MITK_DEBUG << "InternalReorientImagePlane() start";
typedef itk::Image< TPixel, VImageDimension > ImageType;
typedef itk::Image< float, VImageDimension > FloatImageType;
typedef itk::ResampleImageFilter<ImageType, FloatImageType, double> ResamplerType;
typename ResamplerType::Pointer resampler = ResamplerType::New();
mitk::PlaneGeometry* planegeo = dynamic_cast<mitk::PlaneGeometry*>(planegeo3D);
float upsamp = m_UpsamplingFactor;
float gausssigma = 0.5;
// Spacing
typename ResamplerType::SpacingType spacing = planegeo->GetSpacing();
spacing[0] = image->GetSpacing()[0] / upsamp;
spacing[1] = image->GetSpacing()[1] / upsamp;
spacing[2] = image->GetSpacing()[2];
resampler->SetOutputSpacing( spacing );
// Size
typename ResamplerType::SizeType size;
- size[0] = planegeo->GetParametricExtentInMM(0) / spacing[0];
- size[1] = planegeo->GetParametricExtentInMM(1) / spacing[1];
+ size[0] = planegeo->GetExtentInMM(0) / spacing[0];
+ size[1] = planegeo->GetExtentInMM(1) / spacing[1];
size[2] = 1;
resampler->SetSize( size );
// Origin
typename mitk::Point3D orig = planegeo->GetOrigin();
typename mitk::Point3D corrorig;
planegeo3D->WorldToIndex(orig,corrorig);
corrorig[0] += 0.5/upsamp;
corrorig[1] += 0.5/upsamp;
corrorig[2] += 0;
planegeo3D->IndexToWorld(corrorig,corrorig);
resampler->SetOutputOrigin(corrorig );
// Direction
typename ResamplerType::DirectionType direction;
typename mitk::AffineTransform3D::MatrixType matrix = planegeo->GetIndexToWorldTransform()->GetMatrix();
for(int c=0; c<matrix.ColumnDimensions; c++)
{
double sum = 0;
for(int r=0; r<matrix.RowDimensions; r++)
{
sum += matrix(r,c)*matrix(r,c);
}
for(int r=0; r<matrix.RowDimensions; r++)
{
direction(r,c) = matrix(r,c)/sqrt(sum);
}
}
resampler->SetOutputDirection( direction );
// Gaussian interpolation
if(gausssigma != 0)
{
double sigma[3];
for( unsigned int d = 0; d < 3; d++ )
{
sigma[d] = gausssigma * image->GetSpacing()[d];
}
double alpha = 2.0;
typedef itk::GaussianInterpolateImageFunction<ImageType, double>
GaussianInterpolatorType;
typename GaussianInterpolatorType::Pointer interpolator
= GaussianInterpolatorType::New();
interpolator->SetInputImage( image );
interpolator->SetParameters( sigma, alpha );
resampler->SetInterpolator( interpolator );
}
else
{
// typedef typename itk::BSplineInterpolateImageFunction<ImageType, double>
// InterpolatorType;
typedef typename itk::LinearInterpolateImageFunction<ImageType, double> InterpolatorType;
typename InterpolatorType::Pointer interpolator
= InterpolatorType::New();
interpolator->SetInputImage( image );
resampler->SetInterpolator( interpolator );
}
// Other resampling options
resampler->SetInput( image );
resampler->SetDefaultPixelValue(0);
MITK_DEBUG << "Resampling requested image plane ... ";
resampler->Update();
MITK_DEBUG << " ... done";
if(additionalIndex < 0)
{
this->m_InternalImage = mitk::Image::New();
this->m_InternalImage->InitializeByItk( resampler->GetOutput() );
this->m_InternalImage->SetVolume( resampler->GetOutput()->GetBufferPointer() );
}
}
template < typename TPixel, unsigned int VImageDimension >
void QmitkFiberExtractionView::InternalCalculateMaskFromPlanarFigure( itk::Image< TPixel, VImageDimension > *image, unsigned int axis, std::string )
{
MITK_DEBUG << "InternalCalculateMaskFromPlanarFigure() start";
typedef itk::Image< TPixel, VImageDimension > ImageType;
typedef itk::CastImageFilter< ImageType, itkUCharImageType > CastFilterType;
// Generate mask image as new image with same header as input image and
// initialize with "1".
itkUCharImageType::Pointer newMaskImage = itkUCharImageType::New();
newMaskImage->SetSpacing( image->GetSpacing() ); // Set the image spacing
newMaskImage->SetOrigin( image->GetOrigin() ); // Set the image origin
newMaskImage->SetDirection( image->GetDirection() ); // Set the image direction
newMaskImage->SetRegions( image->GetLargestPossibleRegion() );
newMaskImage->Allocate();
newMaskImage->FillBuffer( 1 );
// Generate VTK polygon from (closed) PlanarFigure polyline
// (The polyline points are shifted by -0.5 in z-direction to make sure
// that the extrusion filter, which afterwards elevates all points by +0.5
// in z-direction, creates a 3D object which is cut by the the plane z=0)
const Geometry2D *planarFigureGeometry2D = m_PlanarFigure->GetGeometry2D();
const PlanarFigure::PolyLineType planarFigurePolyline = m_PlanarFigure->GetPolyLine( 0 );
- const Geometry3D *imageGeometry3D = m_InternalImage->GetGeometry( 0 );
+ const BaseGeometry *imageGeometry3D = m_InternalImage->GetGeometry( 0 );
vtkPolyData *polyline = vtkPolyData::New();
polyline->Allocate( 1, 1 );
// Determine x- and y-dimensions depending on principal axis
int i0, i1;
switch ( axis )
{
case 0:
i0 = 1;
i1 = 2;
break;
case 1:
i0 = 0;
i1 = 2;
break;
case 2:
default:
i0 = 0;
i1 = 1;
break;
}
// Create VTK polydata object of polyline contour
vtkPoints *points = vtkPoints::New();
PlanarFigure::PolyLineType::const_iterator it;
std::vector<vtkIdType> indices;
unsigned int numberOfPoints = 0;
for ( it = planarFigurePolyline.begin();
it != planarFigurePolyline.end();
++it )
{
Point3D point3D;
// Convert 2D point back to the local index coordinates of the selected
// image
Point2D point2D = it->Point;
planarFigureGeometry2D->WorldToIndex(point2D, point2D);
point2D[0] -= 0.5/m_UpsamplingFactor;
point2D[1] -= 0.5/m_UpsamplingFactor;
planarFigureGeometry2D->IndexToWorld(point2D, point2D);
planarFigureGeometry2D->Map( point2D, point3D );
// Polygons (partially) outside of the image bounds can not be processed
// further due to a bug in vtkPolyDataToImageStencil
if ( !imageGeometry3D->IsInside( point3D ) )
{
float bounds[2] = {0,0};
bounds[0] =
this->m_InternalImage->GetLargestPossibleRegion().GetSize().GetElement(i0);
bounds[1] =
this->m_InternalImage->GetLargestPossibleRegion().GetSize().GetElement(i1);
imageGeometry3D->WorldToIndex( point3D, point3D );
// if (point3D[i0]<0)
// point3D[i0] = 0.5;
// else if (point3D[i0]>bounds[0])
// point3D[i0] = bounds[0]-0.5;
// if (point3D[i1]<0)
// point3D[i1] = 0.5;
// else if (point3D[i1]>bounds[1])
// point3D[i1] = bounds[1]-0.5;
if (point3D[i0]<0)
point3D[i0] = 0.0;
else if (point3D[i0]>bounds[0])
point3D[i0] = bounds[0]-0.001;
if (point3D[i1]<0)
point3D[i1] = 0.0;
else if (point3D[i1]>bounds[1])
point3D[i1] = bounds[1]-0.001;
points->InsertNextPoint( point3D[i0], point3D[i1], -0.5 );
numberOfPoints++;
}
else
{
imageGeometry3D->WorldToIndex( point3D, point3D );
// Add point to polyline array
points->InsertNextPoint( point3D[i0], point3D[i1], -0.5 );
numberOfPoints++;
}
}
polyline->SetPoints( points );
points->Delete();
vtkIdType *ptIds = new vtkIdType[numberOfPoints];
for ( vtkIdType i = 0; i < numberOfPoints; ++i )
{
ptIds[i] = i;
}
polyline->InsertNextCell( VTK_POLY_LINE, numberOfPoints, ptIds );
// Extrude the generated contour polygon
vtkLinearExtrusionFilter *extrudeFilter = vtkLinearExtrusionFilter::New();
extrudeFilter->SetInputData( polyline );
extrudeFilter->SetScaleFactor( 1 );
extrudeFilter->SetExtrusionTypeToNormalExtrusion();
extrudeFilter->SetVector( 0.0, 0.0, 1.0 );
// Make a stencil from the extruded polygon
vtkPolyDataToImageStencil *polyDataToImageStencil = vtkPolyDataToImageStencil::New();
polyDataToImageStencil->SetInputConnection( extrudeFilter->GetOutputPort() );
// Export from ITK to VTK (to use a VTK filter)
typedef itk::VTKImageImport< itkUCharImageType > ImageImportType;
typedef itk::VTKImageExport< itkUCharImageType > ImageExportType;
typename ImageExportType::Pointer itkExporter = ImageExportType::New();
itkExporter->SetInput( newMaskImage );
vtkImageImport *vtkImporter = vtkImageImport::New();
this->ConnectPipelines( itkExporter, vtkImporter );
vtkImporter->Update();
// Apply the generated image stencil to the input image
vtkImageStencil *imageStencilFilter = vtkImageStencil::New();
imageStencilFilter->SetInputConnection( vtkImporter->GetOutputPort() );
imageStencilFilter->SetStencilConnection(polyDataToImageStencil->GetOutputPort() );
imageStencilFilter->ReverseStencilOff();
imageStencilFilter->SetBackgroundValue( 0 );
imageStencilFilter->Update();
// Export from VTK back to ITK
vtkImageExport *vtkExporter = vtkImageExport::New();
vtkExporter->SetInputConnection( imageStencilFilter->GetOutputPort() );
vtkExporter->Update();
typename ImageImportType::Pointer itkImporter = ImageImportType::New();
this->ConnectPipelines( vtkExporter, itkImporter );
itkImporter->Update();
// calculate cropping bounding box
m_InternalImageMask3D = itkImporter->GetOutput();
m_InternalImageMask3D->SetDirection(image->GetDirection());
itk::ImageRegionConstIterator<itkUCharImageType>
itmask(m_InternalImageMask3D, m_InternalImageMask3D->GetLargestPossibleRegion());
itk::ImageRegionIterator<ImageType>
itimage(image, image->GetLargestPossibleRegion());
itmask.GoToBegin();
itimage.GoToBegin();
typename ImageType::SizeType lowersize = {{9999999999,9999999999,9999999999}};
typename ImageType::SizeType uppersize = {{0,0,0}};
while( !itmask.IsAtEnd() )
{
if(itmask.Get() == 0)
{
itimage.Set(0);
}
else
{
typename ImageType::IndexType index = itimage.GetIndex();
typename ImageType::SizeType signedindex;
signedindex[0] = index[0];
signedindex[1] = index[1];
signedindex[2] = index[2];
lowersize[0] = signedindex[0] < lowersize[0] ? signedindex[0] : lowersize[0];
lowersize[1] = signedindex[1] < lowersize[1] ? signedindex[1] : lowersize[1];
lowersize[2] = signedindex[2] < lowersize[2] ? signedindex[2] : lowersize[2];
uppersize[0] = signedindex[0] > uppersize[0] ? signedindex[0] : uppersize[0];
uppersize[1] = signedindex[1] > uppersize[1] ? signedindex[1] : uppersize[1];
uppersize[2] = signedindex[2] > uppersize[2] ? signedindex[2] : uppersize[2];
}
++itmask;
++itimage;
}
typename ImageType::IndexType index;
index[0] = lowersize[0];
index[1] = lowersize[1];
index[2] = lowersize[2];
typename ImageType::SizeType size;
size[0] = uppersize[0] - lowersize[0] + 1;
size[1] = uppersize[1] - lowersize[1] + 1;
size[2] = uppersize[2] - lowersize[2] + 1;
itk::ImageRegion<3> cropRegion = itk::ImageRegion<3>(index, size);
// crop internal mask
typedef itk::RegionOfInterestImageFilter< itkUCharImageType, itkUCharImageType > ROIMaskFilterType;
typename ROIMaskFilterType::Pointer roi2 = ROIMaskFilterType::New();
roi2->SetRegionOfInterest(cropRegion);
roi2->SetInput(m_InternalImageMask3D);
roi2->Update();
m_InternalImageMask3D = roi2->GetOutput();
Image::Pointer tmpImage = Image::New();
tmpImage->InitializeByItk(m_InternalImageMask3D.GetPointer());
tmpImage->SetVolume(m_InternalImageMask3D->GetBufferPointer());
Image::Pointer tmpImage2 = Image::New();
tmpImage2->InitializeByItk(m_PlanarFigureImage.GetPointer());
- const Geometry3D *pfImageGeometry3D = tmpImage2->GetGeometry( 0 );
+ const BaseGeometry *pfImageGeometry3D = tmpImage2->GetGeometry( 0 );
- const Geometry3D *intImageGeometry3D = tmpImage->GetGeometry( 0 );
+ const BaseGeometry *intImageGeometry3D = tmpImage->GetGeometry( 0 );
typedef itk::ImageRegionIteratorWithIndex<itkUCharImageType> IteratorType;
IteratorType imageIterator (m_InternalImageMask3D, m_InternalImageMask3D->GetRequestedRegion());
imageIterator.GoToBegin();
while ( !imageIterator.IsAtEnd() )
{
unsigned char val = imageIterator.Value();
if (val>0)
{
itk::Index<3> index = imageIterator.GetIndex();
Point3D point;
point[0] = index[0];
point[1] = index[1];
point[2] = index[2];
intImageGeometry3D->IndexToWorld(point, point);
pfImageGeometry3D->WorldToIndex(point, point);
point[i0] += 0.5;
point[i1] += 0.5;
index[0] = point[0];
index[1] = point[1];
index[2] = point[2];
if (pfImageGeometry3D->IsIndexInside(index))
m_PlanarFigureImage->SetPixel(index, 1);
}
++imageIterator;
}
// Clean up VTK objects
polyline->Delete();
extrudeFilter->Delete();
polyDataToImageStencil->Delete();
vtkImporter->Delete();
imageStencilFilter->Delete();
//vtkExporter->Delete(); // TODO: crashes when outcommented; memory leak??
delete[] ptIds;
}
void QmitkFiberExtractionView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget)
{
m_MultiWidget = &stdMultiWidget;
}
void QmitkFiberExtractionView::StdMultiWidgetNotAvailable()
{
m_MultiWidget = NULL;
}
/* OnSelectionChanged is registered to SelectionService, therefore no need to
implement SelectionService Listener explicitly */
void QmitkFiberExtractionView::UpdateGui()
{
m_Controls->m_Extract3dButton->setEnabled(false);
m_Controls->m_ExtractMask->setEnabled(false);
m_Controls->m_RemoveOutsideMaskButton->setEnabled(false);
m_Controls->m_RemoveInsideMaskButton->setEnabled(false);
// are fiber bundles selected?
if ( m_SelectedFB.empty() )
{
m_Controls->m_InputData->setTitle("Please Select Input Data");
m_Controls->m_JoinBundles->setEnabled(false);
m_Controls->m_SubstractBundles->setEnabled(false);
m_Controls->doExtractFibersButton->setEnabled(false);
m_Controls->m_PlanarFigureButtonsFrame->setEnabled(false);
}
else
{
m_Controls->m_InputData->setTitle("Input Data");
m_Controls->m_PlanarFigureButtonsFrame->setEnabled(true);
// one bundle and one planar figure needed to extract fibers
if (!m_SelectedPF.empty())
m_Controls->doExtractFibersButton->setEnabled(true);
// more than two bundles needed to join/subtract
if (m_SelectedFB.size() > 1)
{
m_Controls->m_JoinBundles->setEnabled(true);
m_Controls->m_SubstractBundles->setEnabled(true);
}
else
{
m_Controls->m_JoinBundles->setEnabled(false);
m_Controls->m_SubstractBundles->setEnabled(false);
}
if (m_MaskImageNode.IsNotNull())
{
m_Controls->m_Extract3dButton->setEnabled(true);
m_Controls->m_ExtractMask->setEnabled(true);
m_Controls->m_RemoveOutsideMaskButton->setEnabled(true);
m_Controls->m_RemoveInsideMaskButton->setEnabled(true);
}
}
// are planar figures selected?
if ( m_SelectedPF.empty() )
{
m_Controls->doExtractFibersButton->setEnabled(false);
m_Controls->PFCompoANDButton->setEnabled(false);
m_Controls->PFCompoORButton->setEnabled(false);
m_Controls->PFCompoNOTButton->setEnabled(false);
m_Controls->m_GenerateRoiImage->setEnabled(false);
}
else
{
if ( !m_SelectedFB.empty() || m_SelectedImage.IsNotNull())
m_Controls->m_GenerateRoiImage->setEnabled(true);
else
m_Controls->m_GenerateRoiImage->setEnabled(false);
if (m_SelectedPF.size() > 1)
{
m_Controls->PFCompoANDButton->setEnabled(true);
m_Controls->PFCompoORButton->setEnabled(true);
m_Controls->PFCompoNOTButton->setEnabled(false);
}
else
{
m_Controls->PFCompoANDButton->setEnabled(false);
m_Controls->PFCompoORButton->setEnabled(false);
m_Controls->PFCompoNOTButton->setEnabled(true);
}
}
}
void QmitkFiberExtractionView::OnSelectionChanged( std::vector<mitk::DataNode*> nodes )
{
//reset existing Vectors containing FiberBundles and PlanarFigures from a previous selection
m_SelectedFB.clear();
m_SelectedPF.clear();
m_SelectedSurfaces.clear();
m_SelectedImage = NULL;
m_MaskImageNode = NULL;
m_Controls->m_FibLabel->setText("<font color='red'>mandatory</font>");
m_Controls->m_PfLabel->setText("<font color='grey'>needed for extraction</font>");
for( std::vector<mitk::DataNode*>::iterator it = nodes.begin(); it != nodes.end(); ++it )
{
mitk::DataNode::Pointer node = *it;
if ( dynamic_cast<mitk::FiberBundleX*>(node->GetData()) )
{
m_Controls->m_FibLabel->setText(node->GetName().c_str());
m_SelectedFB.push_back(node);
}
else if (dynamic_cast<mitk::PlanarFigure*>(node->GetData()))
{
m_Controls->m_PfLabel->setText(node->GetName().c_str());
m_SelectedPF.push_back(node);
}
else if (dynamic_cast<mitk::Image*>(node->GetData()))
{
m_SelectedImage = dynamic_cast<mitk::Image*>(node->GetData());
bool isBinary = false;
node->GetPropertyValue<bool>("binary", isBinary);
if (isBinary)
{
m_MaskImageNode = node;
m_Controls->m_PfLabel->setText(node->GetName().c_str());
}
}
else if (dynamic_cast<mitk::Surface*>(node->GetData()))
{
m_Controls->m_PfLabel->setText(node->GetName().c_str());
m_SelectedSurfaces.push_back(dynamic_cast<mitk::Surface*>(node->GetData()));
}
}
if (m_SelectedFB.empty())
{
int maxLayer = 0;
itk::VectorContainer<unsigned int, mitk::DataNode::Pointer>::ConstPointer nodes = this->GetDefaultDataStorage()->GetAll();
for (unsigned int i=0; i<nodes->Size(); i++)
if (dynamic_cast<mitk::FiberBundleX*>(nodes->at(i)->GetData()))
{
int layer = 0;
nodes->at(i)->GetPropertyValue("layer", layer);
if (layer>=maxLayer)
{
maxLayer = layer;
m_Controls->m_FibLabel->setText(nodes->at(i)->GetName().c_str());
m_SelectedFB.clear();
m_SelectedFB.push_back(nodes->at(i));
}
}
}
if (m_SelectedPF.empty() && m_LastAddedPf.IsNotNull())
{
m_Controls->m_PfLabel->setText(m_LastAddedPf->GetName().c_str());
m_SelectedPF.push_back(m_LastAddedPf);
// int maxLayer = 0;
// itk::VectorContainer<unsigned int, mitk::DataNode::Pointer>::ConstPointer nodes = this->GetDefaultDataStorage()->GetAll();
// for (unsigned int i=0; i<nodes->Size(); i++)
// if (dynamic_cast<mitk::PlanarFigure*>(nodes->at(i)->GetData()))
// {
// int layer;
// nodes->at(i)->GetPropertyValue("layer", layer);
// if (layer>=maxLayer)
// {
// maxLayer = layer;
// m_Controls->m_PfLabel->setText(nodes->at(i)->GetName().c_str());
// m_SelectedPF.clear();
// m_SelectedPF.push_back(nodes->at(i));
// }
// }
}
UpdateGui();
GenerateStats();
}
void QmitkFiberExtractionView::OnDrawPolygon()
{
// bool checked = m_Controls->m_PolygonButton->isChecked();
// if(!this->AssertDrawingIsPossible(checked))
// return;
mitk::PlanarPolygon::Pointer figure = mitk::PlanarPolygon::New();
figure->ClosedOn();
this->AddFigureToDataStorage(figure, QString("Polygon%1").arg(++m_PolygonCounter));
MITK_DEBUG << "PlanarPolygon created ...";
mitk::DataStorage::SetOfObjects::ConstPointer _NodeSet = this->GetDefaultDataStorage()->GetAll();
mitk::DataNode* node = 0;
mitk::PlanarFigureInteractor::Pointer figureInteractor = 0;
mitk::PlanarFigure* figureP = 0;
for(mitk::DataStorage::SetOfObjects::ConstIterator it=_NodeSet->Begin(); it!=_NodeSet->End()
; it++)
{
node = const_cast<mitk::DataNode*>(it->Value().GetPointer());
figureP = dynamic_cast<mitk::PlanarFigure*>(node->GetData());
if(figureP)
{
figureInteractor = dynamic_cast<mitk::PlanarFigureInteractor*>(node->GetDataInteractor().GetPointer());
if(figureInteractor.IsNull())
{
figureInteractor = mitk::PlanarFigureInteractor::New();
us::Module* planarFigureModule = us::ModuleRegistry::GetModule( "MitkPlanarFigure" );
figureInteractor->LoadStateMachine("PlanarFigureInteraction.xml", planarFigureModule );
figureInteractor->SetEventConfig( "PlanarFigureConfig.xml", planarFigureModule );
figureInteractor->SetDataNode( node );
}
}
}
}
void QmitkFiberExtractionView::OnDrawCircle()
{
mitk::PlanarCircle::Pointer figure = mitk::PlanarCircle::New();
this->AddFigureToDataStorage(figure, QString("Circle%1").arg(++m_CircleCounter));
this->GetDataStorage()->Modified();
mitk::DataStorage::SetOfObjects::ConstPointer _NodeSet = this->GetDefaultDataStorage()->GetAll();
mitk::DataNode* node = 0;
mitk::PlanarFigureInteractor::Pointer figureInteractor = 0;
mitk::PlanarFigure* figureP = 0;
for(mitk::DataStorage::SetOfObjects::ConstIterator it=_NodeSet->Begin(); it!=_NodeSet->End(); it++)
{
node = const_cast<mitk::DataNode*>(it->Value().GetPointer());
figureP = dynamic_cast<mitk::PlanarFigure*>(node->GetData());
if(figureP)
{
figureInteractor = dynamic_cast<mitk::PlanarFigureInteractor*>(node->GetDataInteractor().GetPointer());
if(figureInteractor.IsNull())
{
figureInteractor = mitk::PlanarFigureInteractor::New();
us::Module* planarFigureModule = us::ModuleRegistry::GetModule( "MitkPlanarFigure" );
figureInteractor->LoadStateMachine("PlanarFigureInteraction.xml", planarFigureModule );
figureInteractor->SetEventConfig( "PlanarFigureConfig.xml", planarFigureModule );
figureInteractor->SetDataNode( node );
}
}
}
}
void QmitkFiberExtractionView::Activated()
{
}
void QmitkFiberExtractionView::AddFigureToDataStorage(mitk::PlanarFigure* figure, const QString& name,
const char *, mitk::BaseProperty * )
{
// initialize figure's geometry with empty geometry
mitk::PlaneGeometry::Pointer emptygeometry = mitk::PlaneGeometry::New();
figure->SetGeometry2D( emptygeometry );
//set desired data to DataNode where Planarfigure is stored
mitk::DataNode::Pointer newNode = mitk::DataNode::New();
newNode->SetName(name.toStdString());
newNode->SetData(figure);
newNode->SetBoolProperty("planarfigure.3drendering", true);
// figure drawn on the topmost layer / image
newNode->SetColor(1.0,1.0,1.0);
newNode->SetOpacity(0.8);
GetDataStorage()->Add(newNode );
for(unsigned int i = 0; i < m_SelectedPF.size(); i++)
m_SelectedPF[i]->SetSelected(false);
newNode->SetSelected(true);
m_SelectedPF.clear();
m_SelectedPF.push_back(newNode);
m_LastAddedPf = newNode;
m_Controls->m_PfLabel->setText(newNode->GetName().c_str());
}
void QmitkFiberExtractionView::DoFiberExtraction()
{
if ( m_SelectedFB.empty() ){
QMessageBox::information( NULL, "Warning", "No fibe bundle selected!");
MITK_WARN("QmitkFiberExtractionView") << "no fibe bundle selected";
return;
}
for (unsigned int i=0; i<m_SelectedFB.size(); i++)
{
mitk::FiberBundleX::Pointer fib = dynamic_cast<mitk::FiberBundleX*>(m_SelectedFB.at(i)->GetData());
mitk::PlanarFigure::Pointer roi = dynamic_cast<mitk::PlanarFigure*> (m_SelectedPF.at(0)->GetData());
mitk::FiberBundleX::Pointer extFB = fib->ExtractFiberSubset(roi);
if (extFB->GetNumFibers()<=0)
{
QMessageBox::information(NULL, "No output generated:", "The resulting fiber bundle contains no fibers.");
continue;
}
mitk::DataNode::Pointer node;
node = mitk::DataNode::New();
node->SetData(extFB);
QString name(m_SelectedFB.at(i)->GetName().c_str());
name += "_";
name += m_SelectedPF.at(0)->GetName().c_str();
node->SetName(name.toStdString());
GetDataStorage()->Add(node);
m_SelectedFB.at(i)->SetVisibility(false);
}
}
void QmitkFiberExtractionView::GenerateAndComposite()
{
mitk::PlanarFigureComposite::Pointer PFCAnd = mitk::PlanarFigureComposite::New();
mitk::PlaneGeometry* currentGeometry2D = dynamic_cast<mitk::PlaneGeometry*>( const_cast<mitk::Geometry2D*>(GetActiveStdMultiWidget()->GetRenderWindow1()->GetRenderer()->GetCurrentWorldGeometry2D()));
PFCAnd->SetGeometry2D(currentGeometry2D);
PFCAnd->setOperationType(mitk::PFCOMPOSITION_AND_OPERATION);
for( std::vector<mitk::DataNode::Pointer>::iterator it = m_SelectedPF.begin();
it != m_SelectedPF.end(); ++it )
{
mitk::DataNode::Pointer nodePF = *it;
mitk::PlanarFigure::Pointer tmpPF = dynamic_cast<mitk::PlanarFigure*>( nodePF->GetData() );
PFCAnd->addPlanarFigure( tmpPF );
PFCAnd->addDataNode( nodePF );
PFCAnd->setDisplayName("AND_COMPO");
}
AddCompositeToDatastorage(PFCAnd, NULL);
}
void QmitkFiberExtractionView::GenerateOrComposite()
{
mitk::PlanarFigureComposite::Pointer PFCOr = mitk::PlanarFigureComposite::New();
mitk::PlaneGeometry* currentGeometry2D = dynamic_cast<mitk::PlaneGeometry*>( const_cast<mitk::Geometry2D*>(GetActiveStdMultiWidget()->GetRenderWindow1()->GetRenderer()->GetCurrentWorldGeometry2D()));
PFCOr->SetGeometry2D(currentGeometry2D);
PFCOr->setOperationType(mitk::PFCOMPOSITION_OR_OPERATION);
for( std::vector<mitk::DataNode::Pointer>::iterator it = m_SelectedPF.begin();
it != m_SelectedPF.end(); ++it )
{
mitk::DataNode::Pointer nodePF = *it;
mitk::PlanarFigure::Pointer tmpPF = dynamic_cast<mitk::PlanarFigure*>( nodePF->GetData() );
PFCOr->addPlanarFigure( tmpPF );
PFCOr->addDataNode( nodePF );
PFCOr->setDisplayName("OR_COMPO");
}
AddCompositeToDatastorage(PFCOr, NULL);
}
void QmitkFiberExtractionView::GenerateNotComposite()
{
mitk::PlanarFigureComposite::Pointer PFCNot = mitk::PlanarFigureComposite::New();
mitk::PlaneGeometry* currentGeometry2D = dynamic_cast<mitk::PlaneGeometry*>( const_cast<mitk::Geometry2D*>(GetActiveStdMultiWidget()->GetRenderWindow1()->GetRenderer()->GetCurrentWorldGeometry2D()));
PFCNot->SetGeometry2D(currentGeometry2D);
PFCNot->setOperationType(mitk::PFCOMPOSITION_NOT_OPERATION);
for( std::vector<mitk::DataNode::Pointer>::iterator it = m_SelectedPF.begin();
it != m_SelectedPF.end(); ++it )
{
mitk::DataNode::Pointer nodePF = *it;
mitk::PlanarFigure::Pointer tmpPF = dynamic_cast<mitk::PlanarFigure*>( nodePF->GetData() );
PFCNot->addPlanarFigure( tmpPF );
PFCNot->addDataNode( nodePF );
PFCNot->setDisplayName("NOT_COMPO");
}
AddCompositeToDatastorage(PFCNot, NULL);
}
/* CLEANUP NEEDED */
void QmitkFiberExtractionView::AddCompositeToDatastorage(mitk::PlanarFigureComposite::Pointer pfcomp, mitk::DataNode::Pointer parentDataNode )
{
mitk::DataNode::Pointer newPFCNode;
newPFCNode = mitk::DataNode::New();
newPFCNode->SetName( pfcomp->getDisplayName() );
newPFCNode->SetData(pfcomp);
newPFCNode->SetVisibility(true);
for(unsigned int i = 0; i < m_SelectedPF.size(); i++)
m_SelectedPF[i]->SetSelected(false);
newPFCNode->SetSelected(true);
m_LastAddedPf = newPFCNode;
m_SelectedPF.clear();
m_SelectedPF.push_back(newPFCNode);
m_Controls->m_PfLabel->setText(newPFCNode->GetName().c_str());
switch (pfcomp->getOperationType()) {
case 0:
{
if (!parentDataNode.IsNull()) {
GetDataStorage()->Add(newPFCNode, parentDataNode);
} else {
GetDataStorage()->Add(newPFCNode);
}
//iterate through its childs
for(int i=0; i<pfcomp->getNumberOfChildren(); ++i)
{
mitk::PlanarFigure::Pointer tmpPFchild = pfcomp->getChildAt(i);
mitk::DataNode::Pointer savedPFchildNode = pfcomp->getDataNodeAt(i);
mitk::PlanarFigureComposite::Pointer pfcompcast= dynamic_cast<mitk::PlanarFigureComposite*>(tmpPFchild.GetPointer());
if ( !pfcompcast.IsNull() )
{
// child is of type planar Figure composite
// make new node of the child, cuz later the child has to be removed of its old position in datamanager
// feed new dataNode with information of the savedDataNode, which is gonna be removed soon
mitk::DataNode::Pointer newChildPFCNode;
newChildPFCNode = mitk::DataNode::New();
newChildPFCNode->SetData(tmpPFchild);
newChildPFCNode->SetName( savedPFchildNode->GetName() );
pfcompcast->setDisplayName( savedPFchildNode->GetName() ); //name might be changed in DataManager by user
//update inside vector the dataNodePointer
pfcomp->replaceDataNodeAt(i, newChildPFCNode);
AddCompositeToDatastorage(pfcompcast, newPFCNode); //the current PFCNode becomes the childs parent
// remove savedNode here, cuz otherwise its children will change their position in the dataNodeManager
// without having its parent anymore
//GetDataStorage()->Remove(savedPFchildNode);
if ( GetDataStorage()->Exists(savedPFchildNode)) {
MITK_DEBUG << savedPFchildNode->GetName() << " exists in DS...trying to remove it";
}else{
MITK_DEBUG << "[ERROR] does NOT exist, but can I read its Name? " << savedPFchildNode->GetName();
}
// remove old child position in dataStorage
GetDataStorage()->Remove(savedPFchildNode);
if ( GetDataStorage()->Exists(savedPFchildNode)) {
MITK_DEBUG << savedPFchildNode->GetName() << " still exists";
}
}
else
{
// child is not of type PlanarFigureComposite, so its one of the planarFigures
// create new dataNode containing the data of the old dataNode, but position in dataManager will be
// modified cuz we re setting a (new) parent.
mitk::DataNode::Pointer newPFchildNode = mitk::DataNode::New();
newPFchildNode->SetName(savedPFchildNode->GetName() );
newPFchildNode->SetData(tmpPFchild);
newPFchildNode->SetVisibility(true);
// replace the dataNode in PFComp DataNodeVector
pfcomp->replaceDataNodeAt(i, newPFchildNode);
if ( GetDataStorage()->Exists(savedPFchildNode)) {
MITK_DEBUG << savedPFchildNode->GetName() << " exists in DS...trying to remove it";
}
else
{
MITK_DEBUG << "[ERROR] does NOT exist, but can I read its Name? " << savedPFchildNode->GetName();
}
// remove old child position in dataStorage
GetDataStorage()->Remove(savedPFchildNode);
if ( GetDataStorage()->Exists(savedPFchildNode))
{
MITK_DEBUG << savedPFchildNode->GetName() << " still exists";
}
MITK_DEBUG << "adding " << newPFchildNode->GetName() << " to " << newPFCNode->GetName();
//add new child to datamanager with its new position as child of newPFCNode parent
GetDataStorage()->Add(newPFchildNode, newPFCNode);
}
}
GetDataStorage()->Modified();
break;
}
case 1:
{
if (!parentDataNode.IsNull()) {
MITK_DEBUG << "adding " << newPFCNode->GetName() << " to " << parentDataNode->GetName() ;
GetDataStorage()->Add(newPFCNode, parentDataNode);
} else {
MITK_DEBUG << "adding " << newPFCNode->GetName();
GetDataStorage()->Add(newPFCNode);
}
for(int i=0; i<pfcomp->getNumberOfChildren(); ++i)
{
mitk::PlanarFigure::Pointer tmpPFchild = pfcomp->getChildAt(i);
mitk::DataNode::Pointer savedPFchildNode = pfcomp->getDataNodeAt(i);
mitk::PlanarFigureComposite::Pointer pfcompcast= dynamic_cast<mitk::PlanarFigureComposite*>(tmpPFchild.GetPointer());
if ( !pfcompcast.IsNull() )
{ // child is of type planar Figure composite
// make new node of the child, cuz later the child has to be removed of its old position in datamanager
// feed new dataNode with information of the savedDataNode, which is gonna be removed soon
mitk::DataNode::Pointer newChildPFCNode;
newChildPFCNode = mitk::DataNode::New();
newChildPFCNode->SetData(tmpPFchild);
newChildPFCNode->SetName( savedPFchildNode->GetName() );
pfcompcast->setDisplayName( savedPFchildNode->GetName() ); //name might be changed in DataManager by user
//update inside vector the dataNodePointer
pfcomp->replaceDataNodeAt(i, newChildPFCNode);
AddCompositeToDatastorage(pfcompcast, newPFCNode); //the current PFCNode becomes the childs parent
// remove savedNode here, cuz otherwise its children will change their position in the dataNodeManager
// without having its parent anymore
//GetDataStorage()->Remove(savedPFchildNode);
if ( GetDataStorage()->Exists(savedPFchildNode)) {
MITK_DEBUG << savedPFchildNode->GetName() << " exists in DS...trying to remove it";
}else{
MITK_DEBUG << "[ERROR] does NOT exist, but can I read its Name? " << savedPFchildNode->GetName();
}
// remove old child position in dataStorage
GetDataStorage()->Remove(savedPFchildNode);
if ( GetDataStorage()->Exists(savedPFchildNode)) {
MITK_DEBUG << savedPFchildNode->GetName() << " still exists";
}
} else {
// child is not of type PlanarFigureComposite, so its one of the planarFigures
// create new dataNode containing the data of the old dataNode, but position in dataManager will be
// modified cuz we re setting a (new) parent.
mitk::DataNode::Pointer newPFchildNode = mitk::DataNode::New();
newPFchildNode->SetName(savedPFchildNode->GetName() );
newPFchildNode->SetData(tmpPFchild);
newPFchildNode->SetVisibility(true);
// replace the dataNode in PFComp DataNodeVector
pfcomp->replaceDataNodeAt(i, newPFchildNode);
if ( GetDataStorage()->Exists(savedPFchildNode)) {
MITK_DEBUG << savedPFchildNode->GetName() << " exists in DS...trying to remove it";
}else{
MITK_DEBUG << "[ERROR] does NOT exist, but can I read its Name? " << savedPFchildNode->GetName();
}
// remove old child position in dataStorage
GetDataStorage()->Remove(savedPFchildNode);
if ( GetDataStorage()->Exists(savedPFchildNode)) {
MITK_DEBUG << savedPFchildNode->GetName() << " still exists";
}
MITK_DEBUG << "adding " << newPFchildNode->GetName() << " to " << newPFCNode->GetName();
//add new child to datamanager with its new position as child of newPFCNode parent
GetDataStorage()->Add(newPFchildNode, newPFCNode);
}
}
GetDataStorage()->Modified();
break;
}
case 2:
{
if (!parentDataNode.IsNull()) {
MITK_DEBUG << "adding " << newPFCNode->GetName() << " to " << parentDataNode->GetName() ;
GetDataStorage()->Add(newPFCNode, parentDataNode);
}
else
{
MITK_DEBUG << "adding " << newPFCNode->GetName();
GetDataStorage()->Add(newPFCNode);
}
//iterate through its childs
for(int i=0; i<pfcomp->getNumberOfChildren(); ++i)
{
mitk::PlanarFigure::Pointer tmpPFchild = pfcomp->getChildAt(i);
mitk::DataNode::Pointer savedPFchildNode = pfcomp->getDataNodeAt(i);
mitk::PlanarFigureComposite::Pointer pfcompcast= dynamic_cast<mitk::PlanarFigureComposite*>(tmpPFchild.GetPointer());
if ( !pfcompcast.IsNull() )
{ // child is of type planar Figure composite
// makeRemoveBundle new node of the child, cuz later the child has to be removed of its old position in datamanager
// feed new dataNode with information of the savedDataNode, which is gonna be removed soon
mitk::DataNode::Pointer newChildPFCNode;
newChildPFCNode = mitk::DataNode::New();
newChildPFCNode->SetData(tmpPFchild);
newChildPFCNode->SetName( savedPFchildNode->GetName() );
pfcompcast->setDisplayName( savedPFchildNode->GetName() ); //name might be changed in DataManager by user
//update inside vector the dataNodePointer
pfcomp->replaceDataNodeAt(i, newChildPFCNode);
AddCompositeToDatastorage(pfcompcast, newPFCNode); //the current PFCNode becomes the childs parent
// remove savedNode here, cuz otherwise its children will change their position in the dataNodeManager
// without having its parent anymore
//GetDataStorage()->Remove(savedPFchildNode);
if ( GetDataStorage()->Exists(savedPFchildNode)) {
MITK_DEBUG << savedPFchildNode->GetName() << " exists in DS...trying to remove it";
}else{
MITK_DEBUG << "[ERROR] does NOT exist, but can I read its Name? " << savedPFchildNode->GetName();
}
// remove old child position in dataStorage
GetDataStorage()->Remove(savedPFchildNode);
if ( GetDataStorage()->Exists(savedPFchildNode)) {
MITK_DEBUG << savedPFchildNode->GetName() << " still exists";
}
} else {
// child is not of type PlanarFigureComposite, so its one of the planarFigures
// create new dataNode containing the data of the old dataNode, but position in dataManager will be
// modified cuz we re setting a (new) parent.
mitk::DataNode::Pointer newPFchildNode = mitk::DataNode::New();
newPFchildNode->SetName(savedPFchildNode->GetName() );
newPFchildNode->SetData(tmpPFchild);
newPFchildNode->SetVisibility(true);
// replace the dataNode in PFComp DataNodeVector
pfcomp->replaceDataNodeAt(i, newPFchildNode);
if ( GetDataStorage()->Exists(savedPFchildNode)) {
MITK_DEBUG << savedPFchildNode->GetName() << " exists in DS...trying to remove it";
}else{
MITK_DEBUG << "[ERROR] does NOT exist, but can I read its Name? " << savedPFchildNode->GetName();
}
// remove old child position in dataStorage
GetDataStorage()->Remove(savedPFchildNode);
if ( GetDataStorage()->Exists(savedPFchildNode)) {
MITK_DEBUG << savedPFchildNode->GetName() << " still exists";
}
MITK_DEBUG << "adding " << newPFchildNode->GetName() << " to " << newPFCNode->GetName();
//add new child to datamanager with its new position as child of newPFCNode parent
GetDataStorage()->Add(newPFchildNode, newPFCNode);
}
}
GetDataStorage()->Modified();
break;
}
default:
MITK_DEBUG << "we have an UNDEFINED composition... ERROR" ;
break;
}
}
void QmitkFiberExtractionView::JoinBundles()
{
if ( m_SelectedFB.size()<2 ){
QMessageBox::information( NULL, "Warning", "Select at least two fiber bundles!");
MITK_WARN("QmitkFiberExtractionView") << "Select at least two fiber bundles!";
return;
}
mitk::FiberBundleX::Pointer newBundle = dynamic_cast<mitk::FiberBundleX*>(m_SelectedFB.at(0)->GetData());
m_SelectedFB.at(0)->SetVisibility(false);
QString name("");
name += QString(m_SelectedFB.at(0)->GetName().c_str());
for (unsigned int i=1; i<m_SelectedFB.size(); i++)
{
newBundle = newBundle->AddBundle(dynamic_cast<mitk::FiberBundleX*>(m_SelectedFB.at(i)->GetData()));
name += "+"+QString(m_SelectedFB.at(i)->GetName().c_str());
m_SelectedFB.at(i)->SetVisibility(false);
}
mitk::DataNode::Pointer fbNode = mitk::DataNode::New();
fbNode->SetData(newBundle);
fbNode->SetName(name.toStdString());
fbNode->SetVisibility(true);
GetDataStorage()->Add(fbNode);
}
void QmitkFiberExtractionView::SubstractBundles()
{
if ( m_SelectedFB.size()<2 ){
QMessageBox::information( NULL, "Warning", "Select at least two fiber bundles!");
MITK_WARN("QmitkFiberExtractionView") << "Select at least two fiber bundles!";
return;
}
mitk::FiberBundleX::Pointer newBundle = dynamic_cast<mitk::FiberBundleX*>(m_SelectedFB.at(0)->GetData());
m_SelectedFB.at(0)->SetVisibility(false);
QString name("");
name += QString(m_SelectedFB.at(0)->GetName().c_str());
for (unsigned int i=1; i<m_SelectedFB.size(); i++)
{
newBundle = newBundle->SubtractBundle(dynamic_cast<mitk::FiberBundleX*>(m_SelectedFB.at(i)->GetData()));
if (newBundle.IsNull())
break;
name += "-"+QString(m_SelectedFB.at(i)->GetName().c_str());
m_SelectedFB.at(i)->SetVisibility(false);
}
if (newBundle.IsNull())
{
QMessageBox::information(NULL, "No output generated:", "The resulting fiber bundle contains no fibers. Did you select the fiber bundles in the correct order? X-Y is not equal to Y-X!");
return;
}
mitk::DataNode::Pointer fbNode = mitk::DataNode::New();
fbNode->SetData(newBundle);
fbNode->SetName(name.toStdString());
fbNode->SetVisibility(true);
GetDataStorage()->Add(fbNode);
}
void QmitkFiberExtractionView::GenerateStats()
{
if ( m_SelectedFB.empty() )
return;
QString stats("");
for(unsigned int i=0; i<m_SelectedFB.size(); i++ )
{
mitk::DataNode::Pointer node = m_SelectedFB[i];
if (node.IsNotNull() && dynamic_cast<mitk::FiberBundleX*>(node->GetData()))
{
if (i>0)
stats += "\n-----------------------------\n";
stats += QString(node->GetName().c_str()) + "\n";
mitk::FiberBundleX::Pointer fib = dynamic_cast<mitk::FiberBundleX*>(node->GetData());
stats += "Number of fibers: "+ QString::number(fib->GetNumFibers()) + "\n";
stats += "Min. length: "+ QString::number(fib->GetMinFiberLength(),'f',1) + " mm\n";
stats += "Max. length: "+ QString::number(fib->GetMaxFiberLength(),'f',1) + " mm\n";
stats += "Mean length: "+ QString::number(fib->GetMeanFiberLength(),'f',1) + " mm\n";
stats += "Median length: "+ QString::number(fib->GetMedianFiberLength(),'f',1) + " mm\n";
stats += "Standard deviation: "+ QString::number(fib->GetLengthStDev(),'f',1) + " mm\n";
}
}
this->m_Controls->m_StatsTextEdit->setText(stats);
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberExtractionView.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberExtractionView.h
index 76c0ad0c49..f2ff67f688 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberExtractionView.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberExtractionView.h
@@ -1,175 +1,175 @@
/*===================================================================
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 QmitkFiberExtractionView_h
#define QmitkFiberExtractionView_h
#include <QmitkFunctionality.h>
#include "ui_QmitkFiberExtractionViewControls.h"
#include <mitkPlanarFigureComposite.h>
#include <mitkFiberBundleX.h>
#include <mitkSurface.h>
#include <itkCastImageFilter.h>
#include <itkVTKImageImport.h>
#include <itkVTKImageExport.h>
#include <itkRegionOfInterestImageFilter.h>
#include <vtkLinearExtrusionFilter.h>
#include <vtkPolyDataToImageStencil.h>
#include <vtkSelectEnclosedPoints.h>
#include <vtkImageImport.h>
#include <vtkImageExport.h>
#include <vtkImageStencil.h>
#include <vtkSmartPointer.h>
#include <vtkSelection.h>
#include <vtkSelectionNode.h>
#include <vtkExtractSelectedThresholds.h>
#include <vtkFloatArray.h>
/*!
\brief View to process fiber bundles. Supplies methods to extract fibers from the bundle, join and subtract bundles and much more.
\sa QmitkFunctionality
\ingroup Functionalities
*/
class QmitkFiberExtractionView : public QmitkFunctionality
{
// this is needed for all Qt objects that should have a Qt meta-object
// (everything that derives from QObject and wants to have signal/slots)
Q_OBJECT
public:
typedef itk::Image< unsigned char, 3 > itkUCharImageType;
static const std::string VIEW_ID;
QmitkFiberExtractionView();
virtual ~QmitkFiberExtractionView();
virtual void CreateQtPartControl(QWidget *parent);
virtual void StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget);
virtual void StdMultiWidgetNotAvailable();
virtual void Activated();
protected slots:
void OnDrawCircle(); ///< add circle interactors etc.
void OnDrawPolygon(); ///< add circle interactors etc.
void DoFiberExtraction(); ///< Extract fibers from selected bundle
void GenerateAndComposite();
void GenerateOrComposite();
void GenerateNotComposite();
void DoRemoveOutsideMask();
void DoRemoveInsideMask();
void JoinBundles(); ///< merge selected fiber bundles
void SubstractBundles(); ///< subtract bundle A from bundle B. Not commutative! Defined by order of selection.
void GenerateRoiImage(); ///< generate binary image of selected planar figures.
void ExtractPassingMask(); ///< extract all fibers passing the selected surface mesh
void ExtractEndingInMask(); ///< extract all fibers passing the selected surface mesh
virtual void AddFigureToDataStorage(mitk::PlanarFigure* figure, const QString& name, const char *propertyKey = NULL, mitk::BaseProperty *property = NULL );
protected:
/// \brief called by QmitkFunctionality when DataManager's selection has changed
virtual void OnSelectionChanged( std::vector<mitk::DataNode*> nodes );
Ui::QmitkFiberExtractionViewControls* m_Controls;
QmitkStdMultiWidget* m_MultiWidget;
/** Connection from VTK to ITK */
template <typename VTK_Exporter, typename ITK_Importer>
void ConnectPipelines(VTK_Exporter* exporter, ITK_Importer importer)
{
importer->SetUpdateInformationCallback(exporter->GetUpdateInformationCallback());
importer->SetPipelineModifiedCallback(exporter->GetPipelineModifiedCallback());
importer->SetWholeExtentCallback(exporter->GetWholeExtentCallback());
importer->SetSpacingCallback(exporter->GetSpacingCallback());
importer->SetOriginCallback(exporter->GetOriginCallback());
importer->SetScalarTypeCallback(exporter->GetScalarTypeCallback());
importer->SetNumberOfComponentsCallback(exporter->GetNumberOfComponentsCallback());
importer->SetPropagateUpdateExtentCallback(exporter->GetPropagateUpdateExtentCallback());
importer->SetUpdateDataCallback(exporter->GetUpdateDataCallback());
importer->SetDataExtentCallback(exporter->GetDataExtentCallback());
importer->SetBufferPointerCallback(exporter->GetBufferPointerCallback());
importer->SetCallbackUserData(exporter->GetCallbackUserData());
}
template <typename ITK_Exporter, typename VTK_Importer>
void ConnectPipelines(ITK_Exporter exporter, VTK_Importer* importer)
{
importer->SetUpdateInformationCallback(exporter->GetUpdateInformationCallback());
importer->SetPipelineModifiedCallback(exporter->GetPipelineModifiedCallback());
importer->SetWholeExtentCallback(exporter->GetWholeExtentCallback());
importer->SetSpacingCallback(exporter->GetSpacingCallback());
importer->SetOriginCallback(exporter->GetOriginCallback());
importer->SetScalarTypeCallback(exporter->GetScalarTypeCallback());
importer->SetNumberOfComponentsCallback(exporter->GetNumberOfComponentsCallback());
importer->SetPropagateUpdateExtentCallback(exporter->GetPropagateUpdateExtentCallback());
importer->SetUpdateDataCallback(exporter->GetUpdateDataCallback());
importer->SetDataExtentCallback(exporter->GetDataExtentCallback());
importer->SetBufferPointerCallback(exporter->GetBufferPointerCallback());
importer->SetCallbackUserData(exporter->GetCallbackUserData());
}
template < typename TPixel, unsigned int VImageDimension >
void InternalCalculateMaskFromPlanarFigure(
itk::Image< TPixel, VImageDimension > *image, unsigned int axis, std::string nodeName );
template < typename TPixel, unsigned int VImageDimension >
void InternalReorientImagePlane(
- const itk::Image< TPixel, VImageDimension > *image, mitk::Geometry3D* planegeo3D, int additionalIndex );
+ const itk::Image< TPixel, VImageDimension > *image, mitk::BaseGeometry* planegeo3D, int additionalIndex );
void GenerateStats(); ///< generate statistics of selected fiber bundles
void UpdateGui(); ///< update button activity etc. dpending on current datamanager selection
int m_CircleCounter; ///< used for data node naming
int m_PolygonCounter; ///< used for data node naming
std::vector<mitk::DataNode::Pointer> m_SelectedFB; ///< selected fiber bundle nodes
std::vector<mitk::DataNode::Pointer> m_SelectedPF; ///< selected planar figure nodes
std::vector<mitk::Surface::Pointer> m_SelectedSurfaces;
mitk::Image::Pointer m_SelectedImage;
mitk::Image::Pointer m_InternalImage;
mitk::PlanarFigure::Pointer m_PlanarFigure;
itkUCharImageType::Pointer m_InternalImageMask3D;
itkUCharImageType::Pointer m_PlanarFigureImage;
float m_UpsamplingFactor; ///< upsampling factor for all image generations
mitk::DataNode::Pointer m_MaskImageNode;
mitk::DataNode::Pointer m_LastAddedPf;
void AddCompositeToDatastorage(mitk::PlanarFigureComposite::Pointer, mitk::DataNode::Pointer);
void debugPFComposition(mitk::PlanarFigureComposite::Pointer , int );
void CompositeExtraction(mitk::DataNode::Pointer node, mitk::Image* image);
mitk::DataNode::Pointer GenerateTractDensityImage(mitk::FiberBundleX::Pointer fib, bool binary, bool absolute);
mitk::DataNode::Pointer GenerateColorHeatmap(mitk::FiberBundleX::Pointer fib);
mitk::DataNode::Pointer GenerateFiberEndingsImage(mitk::FiberBundleX::Pointer fib);
mitk::DataNode::Pointer GenerateFiberEndingsPointSet(mitk::FiberBundleX::Pointer fib);
};
#endif // _QMITKFIBERTRACKINGVIEW_H_INCLUDED
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.cpp
index 89389384c4..7323e6bd1f 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.cpp
@@ -1,2344 +1,2344 @@
/*===================================================================
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.
===================================================================*/
//misc
#define _USE_MATH_DEFINES
#include <math.h>
// Blueberry
#include <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>
// Qmitk
#include "QmitkFiberfoxView.h"
// MITK
#include <mitkImage.h>
#include <mitkDiffusionImage.h>
#include <mitkImageToItk.h>
#include <mitkImageCast.h>
#include <mitkProperties.h>
#include <mitkPlanarFigureInteractor.h>
#include <mitkDataStorage.h>
#include <itkFibersFromPlanarFiguresFilter.h>
#include <itkTractsToDWIImageFilter.h>
#include <mitkTensorImage.h>
#include <mitkILinkedRenderWindowPart.h>
#include <mitkGlobalInteraction.h>
#include <mitkImageToItk.h>
#include <mitkImageCast.h>
#include <mitkImageGenerator.h>
#include <mitkNodePredicateDataType.h>
#include <itkScalableAffineTransform.h>
#include <mitkLevelWindowProperty.h>
#include <mitkNodePredicateOr.h>
#include <mitkNodePredicateAnd.h>
#include <mitkNodePredicateNot.h>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <boost/foreach.hpp>
#include <QFileDialog>
#include <QMessageBox>
#include "usModuleRegistry.h"
#include <mitkChiSquareNoiseModel.h>
#include <itksys/SystemTools.hxx>
#include <mitkIOUtil.h>
#include <QScrollBar>
#include <itkInvertIntensityImageFilter.h>
#include <QDialogButtonBox>
#define _USE_MATH_DEFINES
#include <math.h>
QmitkFiberfoxWorker::QmitkFiberfoxWorker(QmitkFiberfoxView* view)
: m_View(view)
{
}
void QmitkFiberfoxWorker::run()
{
try{
switch (m_FilterType)
{
case 0:
m_View->m_TractsToDwiFilter->Update();
break;
case 1:
m_View->m_ArtifactsToDwiFilter->Update();
break;
}
}
catch( ... )
{
}
m_View->m_Thread.quit();
}
const std::string QmitkFiberfoxView::VIEW_ID = "org.mitk.views.fiberfoxview";
QmitkFiberfoxView::QmitkFiberfoxView()
: QmitkAbstractView()
, m_Controls( 0 )
, m_SelectedImage( NULL )
, m_Worker(this)
, m_ThreadIsRunning(false)
{
m_Worker.moveToThread(&m_Thread);
connect(&m_Thread, SIGNAL(started()), this, SLOT(BeforeThread()));
connect(&m_Thread, SIGNAL(started()), &m_Worker, SLOT(run()));
connect(&m_Thread, SIGNAL(finished()), this, SLOT(AfterThread()));
connect(&m_Thread, SIGNAL(terminated()), this, SLOT(AfterThread()));
m_SimulationTimer = new QTimer(this);
}
void QmitkFiberfoxView::KillThread()
{
MITK_INFO << "Aborting DWI simulation.";
switch (m_Worker.m_FilterType)
{
case 0:
m_TractsToDwiFilter->SetAbortGenerateData(true);
break;
case 1:
m_ArtifactsToDwiFilter->SetAbortGenerateData(true);
break;
}
m_Controls->m_AbortSimulationButton->setEnabled(false);
m_Controls->m_AbortSimulationButton->setText("Aborting simulation ...");
}
void QmitkFiberfoxView::BeforeThread()
{
m_SimulationTime = QTime::currentTime();
m_SimulationTimer->start(100);
m_Controls->m_AbortSimulationButton->setVisible(true);
m_Controls->m_GenerateImageButton->setVisible(false);
m_Controls->m_SimulationStatusText->setVisible(true);
m_ThreadIsRunning = true;
}
void QmitkFiberfoxView::AfterThread()
{
UpdateSimulationStatus();
m_SimulationTimer->stop();
m_Controls->m_AbortSimulationButton->setVisible(false);
m_Controls->m_AbortSimulationButton->setEnabled(true);
m_Controls->m_AbortSimulationButton->setText("Abort simulation");
m_Controls->m_GenerateImageButton->setVisible(true);
m_ThreadIsRunning = false;
QString statusText;
FiberfoxParameters<double> parameters;
mitk::DiffusionImage<short>::Pointer mitkImage = mitk::DiffusionImage<short>::New();
switch (m_Worker.m_FilterType)
{
case 0:
{
statusText = QString(m_TractsToDwiFilter->GetStatusText().c_str());
if (m_TractsToDwiFilter->GetAbortGenerateData())
{
MITK_INFO << "Simulation aborted.";
return;
}
parameters = m_TractsToDwiFilter->GetParameters();
mitkImage->SetVectorImage( m_TractsToDwiFilter->GetOutput() );
mitkImage->SetReferenceBValue(parameters.m_Bvalue);
mitkImage->SetDirections(parameters.GetGradientDirections());
mitkImage->InitializeFromVectorImage();
parameters.m_ResultNode->SetData( mitkImage );
parameters.m_ResultNode->SetName(parameters.m_ParentNode->GetName()
+"_D"+QString::number(parameters.m_ImageRegion.GetSize(0)).toStdString()
+"-"+QString::number(parameters.m_ImageRegion.GetSize(1)).toStdString()
+"-"+QString::number(parameters.m_ImageRegion.GetSize(2)).toStdString()
+"_S"+QString::number(parameters.m_ImageSpacing[0]).toStdString()
+"-"+QString::number(parameters.m_ImageSpacing[1]).toStdString()
+"-"+QString::number(parameters.m_ImageSpacing[2]).toStdString()
+"_b"+QString::number(parameters.m_Bvalue).toStdString()
+"_"+parameters.m_SignalModelString
+parameters.m_ArtifactModelString);
GetDataStorage()->Add(parameters.m_ResultNode, parameters.m_ParentNode);
parameters.m_ResultNode->SetProperty( "levelwindow", mitk::LevelWindowProperty::New(m_TractsToDwiFilter->GetLevelWindow()) );
if (m_Controls->m_VolumeFractionsBox->isChecked())
{
std::vector< itk::TractsToDWIImageFilter< short >::ItkDoubleImgType::Pointer > volumeFractions = m_TractsToDwiFilter->GetVolumeFractions();
for (unsigned int k=0; k<volumeFractions.size(); k++)
{
mitk::Image::Pointer image = mitk::Image::New();
image->InitializeByItk(volumeFractions.at(k).GetPointer());
image->SetVolume(volumeFractions.at(k)->GetBufferPointer());
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData( image );
node->SetName(parameters.m_ParentNode->GetName()+"_CompartmentVolume-"+QString::number(k).toStdString());
GetDataStorage()->Add(node, parameters.m_ParentNode);
}
}
m_TractsToDwiFilter = NULL;
break;
}
case 1:
{
statusText = QString(m_ArtifactsToDwiFilter->GetStatusText().c_str());
if (m_ArtifactsToDwiFilter->GetAbortGenerateData())
{
MITK_INFO << "Simulation aborted.";
return;
}
parameters = m_ArtifactsToDwiFilter->GetParameters().CopyParameters<double>();
mitk::DiffusionImage<short>::Pointer diffImg = dynamic_cast<mitk::DiffusionImage<short>*>(parameters.m_ParentNode->GetData());
mitkImage = mitk::DiffusionImage<short>::New();
mitkImage->SetVectorImage( m_ArtifactsToDwiFilter->GetOutput() );
mitkImage->SetReferenceBValue(diffImg->GetReferenceBValue());
mitkImage->SetDirections(diffImg->GetDirections());
mitkImage->InitializeFromVectorImage();
parameters.m_ResultNode->SetData( mitkImage );
parameters.m_ResultNode->SetName(parameters.m_ParentNode->GetName()+parameters.m_ArtifactModelString);
GetDataStorage()->Add(parameters.m_ResultNode, parameters.m_ParentNode);
m_ArtifactsToDwiFilter = NULL;
break;
}
}
mitk::BaseData::Pointer basedata = parameters.m_ResultNode->GetData();
if (basedata.IsNotNull())
{
mitk::RenderingManager::GetInstance()->InitializeViews(
basedata->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true );
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
if (!parameters.m_OutputPath.empty())
{
try{
QString outputFileName(parameters.m_OutputPath.c_str());
outputFileName += parameters.m_ResultNode->GetName().c_str();
outputFileName.replace(QString("."), QString("_"));
outputFileName += ".dwi";
QString status("Saving output image to ");
status += outputFileName;
m_Controls->m_SimulationStatusText->append(status);
mitk::IOUtil::SaveBaseData(mitkImage, outputFileName.toStdString());
m_Controls->m_SimulationStatusText->append("File saved successfully.");
}
catch (itk::ExceptionObject &e)
{
QString status("Exception during DWI writing: ");
status += e.GetDescription();
m_Controls->m_SimulationStatusText->append(status);
}
catch (...)
{
m_Controls->m_SimulationStatusText->append("Unknown exception during DWI writing!");
}
}
parameters.m_FrequencyMap = NULL;
}
void QmitkFiberfoxView::UpdateSimulationStatus()
{
QString statusText;
switch (m_Worker.m_FilterType)
{
case 0:
statusText = QString(m_TractsToDwiFilter->GetStatusText().c_str());
break;
case 1:
statusText = QString(m_ArtifactsToDwiFilter->GetStatusText().c_str());
break;
}
if (QString::compare(m_SimulationStatusText,statusText)!=0)
{
m_Controls->m_SimulationStatusText->clear();
statusText = "<pre>"+statusText+"</pre>";
m_Controls->m_SimulationStatusText->setText(statusText);
QScrollBar *vScrollBar = m_Controls->m_SimulationStatusText->verticalScrollBar();
vScrollBar->triggerAction(QScrollBar::SliderToMaximum);
}
}
// Destructor
QmitkFiberfoxView::~QmitkFiberfoxView()
{
delete m_SimulationTimer;
}
void QmitkFiberfoxView::CreateQtPartControl( QWidget *parent )
{
// build up qt view, unless already done
if ( !m_Controls )
{
// create GUI widgets from the Qt Designer's .ui file
m_Controls = new Ui::QmitkFiberfoxViewControls;
m_Controls->setupUi( parent );
m_Controls->m_StickWidget1->setVisible(true);
m_Controls->m_StickWidget2->setVisible(false);
m_Controls->m_ZeppelinWidget1->setVisible(false);
m_Controls->m_ZeppelinWidget2->setVisible(false);
m_Controls->m_TensorWidget1->setVisible(false);
m_Controls->m_TensorWidget2->setVisible(false);
m_Controls->m_BallWidget1->setVisible(true);
m_Controls->m_BallWidget2->setVisible(false);
m_Controls->m_AstrosticksWidget1->setVisible(false);
m_Controls->m_AstrosticksWidget2->setVisible(false);
m_Controls->m_DotWidget1->setVisible(false);
m_Controls->m_DotWidget2->setVisible(false);
m_Controls->m_Comp4FractionFrame->setVisible(false);
m_Controls->m_DiffusionPropsMessage->setVisible(false);
m_Controls->m_GeometryMessage->setVisible(false);
m_Controls->m_AdvancedSignalOptionsFrame->setVisible(false);
m_Controls->m_AdvancedFiberOptionsFrame->setVisible(false);
m_Controls->m_VarianceBox->setVisible(false);
m_Controls->m_NoiseFrame->setVisible(false);
m_Controls->m_GhostFrame->setVisible(false);
m_Controls->m_DistortionsFrame->setVisible(false);
m_Controls->m_EddyFrame->setVisible(false);
m_Controls->m_SpikeFrame->setVisible(false);
m_Controls->m_AliasingFrame->setVisible(false);
m_Controls->m_MotionArtifactFrame->setVisible(false);
m_ParameterFile = QDir::currentPath()+"/param.ffp";
m_Controls->m_AbortSimulationButton->setVisible(false);
m_Controls->m_SimulationStatusText->setVisible(false);
m_Controls->m_FrequencyMapBox->SetDataStorage(this->GetDataStorage());
mitk::TNodePredicateDataType<mitk::Image>::Pointer isMitkImage = mitk::TNodePredicateDataType<mitk::Image>::New();
mitk::NodePredicateDataType::Pointer isDwi = mitk::NodePredicateDataType::New("DiffusionImage");
mitk::NodePredicateDataType::Pointer isDti = mitk::NodePredicateDataType::New("TensorImage");
mitk::NodePredicateDataType::Pointer isQbi = mitk::NodePredicateDataType::New("QBallImage");
mitk::NodePredicateOr::Pointer isDiffusionImage = mitk::NodePredicateOr::New(isDwi, isDti);
isDiffusionImage = mitk::NodePredicateOr::New(isDiffusionImage, isQbi);
mitk::NodePredicateNot::Pointer noDiffusionImage = mitk::NodePredicateNot::New(isDiffusionImage);
mitk::NodePredicateAnd::Pointer finalPredicate = mitk::NodePredicateAnd::New(isMitkImage, noDiffusionImage);
m_Controls->m_FrequencyMapBox->SetPredicate(finalPredicate);
m_Controls->m_Comp4VolumeFraction->SetDataStorage(this->GetDataStorage());
m_Controls->m_Comp4VolumeFraction->SetPredicate(finalPredicate);
connect( m_SimulationTimer, SIGNAL(timeout()), this, SLOT(UpdateSimulationStatus()) );
connect((QObject*) m_Controls->m_AbortSimulationButton, SIGNAL(clicked()), (QObject*) this, SLOT(KillThread()));
connect((QObject*) m_Controls->m_GenerateImageButton, SIGNAL(clicked()), (QObject*) this, SLOT(GenerateImage()));
connect((QObject*) m_Controls->m_GenerateFibersButton, SIGNAL(clicked()), (QObject*) this, SLOT(GenerateFibers()));
connect((QObject*) m_Controls->m_CircleButton, SIGNAL(clicked()), (QObject*) this, SLOT(OnDrawROI()));
connect((QObject*) m_Controls->m_FlipButton, SIGNAL(clicked()), (QObject*) this, SLOT(OnFlipButton()));
connect((QObject*) m_Controls->m_JoinBundlesButton, SIGNAL(clicked()), (QObject*) this, SLOT(JoinBundles()));
connect((QObject*) m_Controls->m_VarianceBox, SIGNAL(valueChanged(double)), (QObject*) this, SLOT(OnVarianceChanged(double)));
connect((QObject*) m_Controls->m_DistributionBox, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(OnDistributionChanged(int)));
connect((QObject*) m_Controls->m_FiberDensityBox, SIGNAL(valueChanged(int)), (QObject*) this, SLOT(OnFiberDensityChanged(int)));
connect((QObject*) m_Controls->m_FiberSamplingBox, SIGNAL(valueChanged(double)), (QObject*) this, SLOT(OnFiberSamplingChanged(double)));
connect((QObject*) m_Controls->m_TensionBox, SIGNAL(valueChanged(double)), (QObject*) this, SLOT(OnTensionChanged(double)));
connect((QObject*) m_Controls->m_ContinuityBox, SIGNAL(valueChanged(double)), (QObject*) this, SLOT(OnContinuityChanged(double)));
connect((QObject*) m_Controls->m_BiasBox, SIGNAL(valueChanged(double)), (QObject*) this, SLOT(OnBiasChanged(double)));
connect((QObject*) m_Controls->m_AddNoise, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddNoise(int)));
connect((QObject*) m_Controls->m_AddGhosts, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddGhosts(int)));
connect((QObject*) m_Controls->m_AddDistortions, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddDistortions(int)));
connect((QObject*) m_Controls->m_AddEddy, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddEddy(int)));
connect((QObject*) m_Controls->m_AddSpikes, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddSpikes(int)));
connect((QObject*) m_Controls->m_AddAliasing, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddAliasing(int)));
connect((QObject*) m_Controls->m_AddMotion, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddMotion(int)));
connect((QObject*) m_Controls->m_ConstantRadiusBox, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnConstantRadius(int)));
connect((QObject*) m_Controls->m_CopyBundlesButton, SIGNAL(clicked()), (QObject*) this, SLOT(CopyBundles()));
connect((QObject*) m_Controls->m_TransformBundlesButton, SIGNAL(clicked()), (QObject*) this, SLOT(ApplyTransform()));
connect((QObject*) m_Controls->m_AlignOnGrid, SIGNAL(clicked()), (QObject*) this, SLOT(AlignOnGrid()));
connect((QObject*) m_Controls->m_Compartment1Box, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(Comp1ModelFrameVisibility(int)));
connect((QObject*) m_Controls->m_Compartment2Box, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(Comp2ModelFrameVisibility(int)));
connect((QObject*) m_Controls->m_Compartment3Box, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(Comp3ModelFrameVisibility(int)));
connect((QObject*) m_Controls->m_Compartment4Box, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(Comp4ModelFrameVisibility(int)));
connect((QObject*) m_Controls->m_AdvancedOptionsBox, SIGNAL( stateChanged(int)), (QObject*) this, SLOT(ShowAdvancedOptions(int)));
connect((QObject*) m_Controls->m_AdvancedOptionsBox_2, SIGNAL( stateChanged(int)), (QObject*) this, SLOT(ShowAdvancedOptions(int)));
connect((QObject*) m_Controls->m_SaveParametersButton, SIGNAL(clicked()), (QObject*) this, SLOT(SaveParameters()));
connect((QObject*) m_Controls->m_LoadParametersButton, SIGNAL(clicked()), (QObject*) this, SLOT(LoadParameters()));
connect((QObject*) m_Controls->m_OutputPathButton, SIGNAL(clicked()), (QObject*) this, SLOT(SetOutputPath()));
}
}
template< class ScalarType >
FiberfoxParameters< ScalarType > QmitkFiberfoxView::UpdateImageParameters()
{
FiberfoxParameters< ScalarType > parameters;
parameters.m_OutputPath = "";
string outputPath = m_Controls->m_SavePathEdit->text().toStdString();
if (outputPath.compare("-")!=0)
{
parameters.m_OutputPath = outputPath;
parameters.m_OutputPath += "/";
}
if (m_MaskImageNode.IsNotNull())
{
mitk::Image::Pointer mitkMaskImage = dynamic_cast<mitk::Image*>(m_MaskImageNode->GetData());
mitk::CastToItkImage<ItkUcharImgType>(mitkMaskImage, parameters.m_MaskImage);
itk::ImageDuplicator<ItkUcharImgType>::Pointer duplicator = itk::ImageDuplicator<ItkUcharImgType>::New();
duplicator->SetInputImage(parameters.m_MaskImage);
duplicator->Update();
parameters.m_MaskImage = duplicator->GetOutput();
}
if (m_SelectedDWI.IsNotNull()) // use parameters of selected DWI
{
mitk::DiffusionImage<short>::Pointer dwi = dynamic_cast<mitk::DiffusionImage<short>*>(m_SelectedDWI->GetData());
parameters.m_ImageRegion = dwi->GetVectorImage()->GetLargestPossibleRegion();
parameters.m_ImageSpacing = dwi->GetVectorImage()->GetSpacing();
parameters.m_ImageOrigin = dwi->GetVectorImage()->GetOrigin();
parameters.m_ImageDirection = dwi->GetVectorImage()->GetDirection();
parameters.m_Bvalue = dwi->GetReferenceBValue();
parameters.SetGradienDirections(dwi->GetDirections());
}
else if (m_SelectedImage.IsNotNull()) // use geometry of selected image
{
mitk::Image::Pointer img = dynamic_cast<mitk::Image*>(m_SelectedImage->GetData());
itk::Image< float, 3 >::Pointer itkImg = itk::Image< float, 3 >::New();
CastToItkImage< itk::Image< float, 3 > >(img, itkImg);
parameters.m_ImageRegion = itkImg->GetLargestPossibleRegion();
parameters.m_ImageSpacing = itkImg->GetSpacing();
parameters.m_ImageOrigin = itkImg->GetOrigin();
parameters.m_ImageDirection = itkImg->GetDirection();
parameters.SetNumWeightedGradients(m_Controls->m_NumGradientsBox->value());
parameters.m_Bvalue = m_Controls->m_BvalueBox->value();
}
else // use GUI parameters
{
parameters.m_ImageRegion.SetSize(0, m_Controls->m_SizeX->value());
parameters.m_ImageRegion.SetSize(1, m_Controls->m_SizeY->value());
parameters.m_ImageRegion.SetSize(2, m_Controls->m_SizeZ->value());
parameters.m_ImageSpacing[0] = m_Controls->m_SpacingX->value();
parameters.m_ImageSpacing[1] = m_Controls->m_SpacingY->value();
parameters.m_ImageSpacing[2] = m_Controls->m_SpacingZ->value();
parameters.m_ImageOrigin[0] = parameters.m_ImageSpacing[0]/2;
parameters.m_ImageOrigin[1] = parameters.m_ImageSpacing[1]/2;
parameters.m_ImageOrigin[2] = parameters.m_ImageSpacing[2]/2;
parameters.m_ImageDirection.SetIdentity();
parameters.SetNumWeightedGradients(m_Controls->m_NumGradientsBox->value());
parameters.m_Bvalue = m_Controls->m_BvalueBox->value();
parameters.GenerateGradientHalfShell();
}
// signal relaxation
parameters.m_DoSimulateRelaxation = m_Controls->m_RelaxationBox->isChecked();
if (parameters.m_DoSimulateRelaxation && m_SelectedBundles.size()>0 )
parameters.m_ArtifactModelString += "_RELAX";
// N/2 ghosts
if (m_Controls->m_AddGhosts->isChecked())
{
parameters.m_ArtifactModelString += "_GHOST";
parameters.m_KspaceLineOffset = m_Controls->m_kOffsetBox->value();
parameters.m_ResultNode->AddProperty("Fiberfox.Ghost", DoubleProperty::New(parameters.m_KspaceLineOffset));
}
else
parameters.m_KspaceLineOffset = 0;
// Aliasing
if (m_Controls->m_AddAliasing->isChecked())
{
parameters.m_ArtifactModelString += "_ALIASING";
parameters.m_CroppingFactor = (100-m_Controls->m_WrapBox->value())/100;
parameters.m_ResultNode->AddProperty("Fiberfox.Aliasing", DoubleProperty::New(m_Controls->m_WrapBox->value()));
}
// Motion
parameters.m_DoAddMotion = m_Controls->m_AddMotion->isChecked();
parameters.m_DoRandomizeMotion = m_Controls->m_RandomMotion->isChecked();
parameters.m_Translation[0] = m_Controls->m_MaxTranslationBoxX->value();
parameters.m_Translation[1] = m_Controls->m_MaxTranslationBoxY->value();
parameters.m_Translation[2] = m_Controls->m_MaxTranslationBoxZ->value();
parameters.m_Rotation[0] = m_Controls->m_MaxRotationBoxX->value();
parameters.m_Rotation[1] = m_Controls->m_MaxRotationBoxY->value();
parameters.m_Rotation[2] = m_Controls->m_MaxRotationBoxZ->value();
if ( m_Controls->m_AddMotion->isChecked() && m_SelectedBundles.size()>0 )
{
parameters.m_ArtifactModelString += "_MOTION";
parameters.m_ResultNode->AddProperty("Fiberfox.Motion.Random", BoolProperty::New(parameters.m_DoRandomizeMotion));
parameters.m_ResultNode->AddProperty("Fiberfox.Motion.Translation-x", DoubleProperty::New(parameters.m_Translation[0]));
parameters.m_ResultNode->AddProperty("Fiberfox.Motion.Translation-y", DoubleProperty::New(parameters.m_Translation[1]));
parameters.m_ResultNode->AddProperty("Fiberfox.Motion.Translation-z", DoubleProperty::New(parameters.m_Translation[2]));
parameters.m_ResultNode->AddProperty("Fiberfox.Motion.Rotation-x", DoubleProperty::New(parameters.m_Rotation[0]));
parameters.m_ResultNode->AddProperty("Fiberfox.Motion.Rotation-y", DoubleProperty::New(parameters.m_Rotation[1]));
parameters.m_ResultNode->AddProperty("Fiberfox.Motion.Rotation-z", DoubleProperty::New(parameters.m_Rotation[2]));
}
// other imaging parameters
parameters.m_tLine = m_Controls->m_LineReadoutTimeBox->value();
parameters.m_tInhom = m_Controls->m_T2starBox->value();
parameters.m_tEcho = m_Controls->m_TEbox->value();
parameters.m_Repetitions = m_Controls->m_RepetitionsBox->value();
parameters.m_DoDisablePartialVolume = m_Controls->m_EnforcePureFiberVoxelsBox->isChecked();
parameters.m_AxonRadius = m_Controls->m_FiberRadius->value();
parameters.m_SignalScale = m_Controls->m_SignalScaleBox->value();
if (m_Controls->m_AddSpikes->isChecked())
{
parameters.m_Spikes = m_Controls->m_SpikeNumBox->value();
parameters.m_SpikeAmplitude = m_Controls->m_SpikeScaleBox->value();
parameters.m_ArtifactModelString += "_SPIKES";
parameters.m_ResultNode->AddProperty("Fiberfox.Spikes.Number", IntProperty::New(parameters.m_Spikes));
parameters.m_ResultNode->AddProperty("Fiberfox.Spikes.Amplitude", DoubleProperty::New(parameters.m_SpikeAmplitude));
}
// adjust echo time if needed
if ( parameters.m_tEcho < parameters.m_ImageRegion.GetSize(1)*parameters.m_tLine )
{
this->m_Controls->m_TEbox->setValue( parameters.m_ImageRegion.GetSize(1)*parameters.m_tLine );
parameters.m_tEcho = m_Controls->m_TEbox->value();
QMessageBox::information( NULL, "Warning", "Echo time is too short! Time not sufficient to read slice. Automaticall adjusted to "+QString::number(parameters.m_tEcho)+" ms");
}
// rician noise
if (m_Controls->m_AddNoise->isChecked())
{
double noiseVariance = m_Controls->m_NoiseLevel->value();
{
switch (m_Controls->m_NoiseDistributionBox->currentIndex())
{
case 0:
{
parameters.m_NoiseModel = new mitk::RicianNoiseModel<ScalarType>();
parameters.m_ArtifactModelString += "_RICIAN-";
parameters.m_ResultNode->AddProperty("Fiberfox.Noise-Distribution", StringProperty::New("Rician"));
break;
}
case 1:
{
parameters.m_NoiseModel = new mitk::ChiSquareNoiseModel<ScalarType>();
parameters.m_ArtifactModelString += "_CHISQUARED-";
parameters.m_ResultNode->AddProperty("Fiberfox.Noise-Distribution", StringProperty::New("Chi-squared"));
break;
}
default:
{
parameters.m_NoiseModel = new mitk::RicianNoiseModel<ScalarType>();
parameters.m_ArtifactModelString += "_RICIAN-";
parameters.m_ResultNode->AddProperty("Fiberfox.Noise-Distribution", StringProperty::New("Rician"));
}
}
}
parameters.m_NoiseModel->SetNoiseVariance(noiseVariance);
parameters.m_ArtifactModelString += QString::number(noiseVariance).toStdString();
parameters.m_ResultNode->AddProperty("Fiberfox.Noise-Variance", DoubleProperty::New(noiseVariance));
}
// gibbs ringing
parameters.m_DoAddGibbsRinging = m_Controls->m_AddGibbsRinging->isChecked();
if (m_Controls->m_AddGibbsRinging->isChecked())
{
parameters.m_ResultNode->AddProperty("Fiberfox.Ringing", BoolProperty::New(true));
parameters.m_ArtifactModelString += "_RINGING";
}
// adjusting line readout time to the adapted image size needed for the DFT
unsigned int y = parameters.m_ImageRegion.GetSize(1);
y += y%2;
if ( y>parameters.m_ImageRegion.GetSize(1) )
parameters.m_tLine *= (double)parameters.m_ImageRegion.GetSize(1)/y;
// add distortions
if (m_Controls->m_AddDistortions->isChecked() && m_Controls->m_FrequencyMapBox->GetSelectedNode().IsNotNull())
{
mitk::DataNode::Pointer fMapNode = m_Controls->m_FrequencyMapBox->GetSelectedNode();
mitk::Image* img = dynamic_cast<mitk::Image*>(fMapNode->GetData());
ItkDoubleImgType::Pointer itkImg = ItkDoubleImgType::New();
CastToItkImage< ItkDoubleImgType >(img, itkImg);
if (parameters.m_ImageRegion.GetSize(0)==itkImg->GetLargestPossibleRegion().GetSize(0) &&
parameters.m_ImageRegion.GetSize(1)==itkImg->GetLargestPossibleRegion().GetSize(1) &&
parameters.m_ImageRegion.GetSize(2)==itkImg->GetLargestPossibleRegion().GetSize(2))
{
itk::ImageDuplicator<ItkDoubleImgType>::Pointer duplicator = itk::ImageDuplicator<ItkDoubleImgType>::New();
duplicator->SetInputImage(itkImg);
duplicator->Update();
parameters.m_FrequencyMap = duplicator->GetOutput();
parameters.m_ArtifactModelString += "_DISTORTED";
parameters.m_ResultNode->AddProperty("Fiberfox.Distortions", BoolProperty::New(true));
}
}
parameters.m_EddyStrength = 0;
if (m_Controls->m_AddEddy->isChecked())
{
parameters.m_EddyStrength = m_Controls->m_EddyGradientStrength->value();
parameters.m_ArtifactModelString += "_EDDY";
parameters.m_ResultNode->AddProperty("Fiberfox.Eddy-strength", DoubleProperty::New(parameters.m_EddyStrength));
}
// signal models
// compartment 1
switch (m_Controls->m_Compartment1Box->currentIndex())
{
case 0:
m_StickModel1.SetGradientList(parameters.GetGradientDirections());
m_StickModel1.SetBvalue(parameters.m_Bvalue);
m_StickModel1.SetDiffusivity(m_Controls->m_StickWidget1->GetD());
m_StickModel1.SetT2(m_Controls->m_StickWidget1->GetT2());
parameters.m_FiberModelList.push_back(&m_StickModel1);
parameters.m_SignalModelString += "Stick";
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment1.Description", StringProperty::New("Intra-axonal compartment") );
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment1.Model", StringProperty::New("Stick") );
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment1.D", DoubleProperty::New(m_Controls->m_StickWidget1->GetD()) );
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment1.T2", DoubleProperty::New(m_StickModel1.GetT2()) );
break;
case 1:
m_ZeppelinModel1.SetGradientList(parameters.GetGradientDirections());
m_ZeppelinModel1.SetBvalue(parameters.m_Bvalue);
m_ZeppelinModel1.SetDiffusivity1(m_Controls->m_ZeppelinWidget1->GetD1());
m_ZeppelinModel1.SetDiffusivity2(m_Controls->m_ZeppelinWidget1->GetD2());
m_ZeppelinModel1.SetDiffusivity3(m_Controls->m_ZeppelinWidget1->GetD2());
m_ZeppelinModel1.SetT2(m_Controls->m_ZeppelinWidget1->GetT2());
parameters.m_FiberModelList.push_back(&m_ZeppelinModel1);
parameters.m_SignalModelString += "Zeppelin";
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment1.Description", StringProperty::New("Intra-axonal compartment") );
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment1.Model", StringProperty::New("Zeppelin") );
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment1.D1", DoubleProperty::New(m_Controls->m_ZeppelinWidget1->GetD1()) );
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment1.D2", DoubleProperty::New(m_Controls->m_ZeppelinWidget1->GetD2()) );
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment1.T2", DoubleProperty::New(m_ZeppelinModel1.GetT2()) );
break;
case 2:
m_TensorModel1.SetGradientList(parameters.GetGradientDirections());
m_TensorModel1.SetBvalue(parameters.m_Bvalue);
m_TensorModel1.SetDiffusivity1(m_Controls->m_TensorWidget1->GetD1());
m_TensorModel1.SetDiffusivity2(m_Controls->m_TensorWidget1->GetD2());
m_TensorModel1.SetDiffusivity3(m_Controls->m_TensorWidget1->GetD3());
m_TensorModel1.SetT2(m_Controls->m_TensorWidget1->GetT2());
parameters.m_FiberModelList.push_back(&m_TensorModel1);
parameters.m_SignalModelString += "Tensor";
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment1.Description", StringProperty::New("Intra-axonal compartment") );
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment1.Model", StringProperty::New("Tensor") );
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment1.D1", DoubleProperty::New(m_Controls->m_TensorWidget1->GetD1()) );
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment1.D2", DoubleProperty::New(m_Controls->m_TensorWidget1->GetD2()) );
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment1.D3", DoubleProperty::New(m_Controls->m_TensorWidget1->GetD3()) );
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment1.T2", DoubleProperty::New(m_ZeppelinModel1.GetT2()) );
break;
}
// compartment 2
switch (m_Controls->m_Compartment2Box->currentIndex())
{
case 0:
break;
case 1:
m_StickModel2.SetGradientList(parameters.GetGradientDirections());
m_StickModel2.SetBvalue(parameters.m_Bvalue);
m_StickModel2.SetDiffusivity(m_Controls->m_StickWidget2->GetD());
m_StickModel2.SetT2(m_Controls->m_StickWidget2->GetT2());
parameters.m_FiberModelList.push_back(&m_StickModel2);
parameters.m_SignalModelString += "Stick";
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment2.Description", StringProperty::New("Inter-axonal compartment") );
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment2.Model", StringProperty::New("Stick") );
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment2.D", DoubleProperty::New(m_Controls->m_StickWidget2->GetD()) );
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment2.T2", DoubleProperty::New(m_StickModel2.GetT2()) );
break;
case 2:
m_ZeppelinModel2.SetGradientList(parameters.GetGradientDirections());
m_ZeppelinModel2.SetBvalue(parameters.m_Bvalue);
m_ZeppelinModel2.SetDiffusivity1(m_Controls->m_ZeppelinWidget2->GetD1());
m_ZeppelinModel2.SetDiffusivity2(m_Controls->m_ZeppelinWidget2->GetD2());
m_ZeppelinModel2.SetDiffusivity3(m_Controls->m_ZeppelinWidget2->GetD2());
m_ZeppelinModel2.SetT2(m_Controls->m_ZeppelinWidget2->GetT2());
parameters.m_FiberModelList.push_back(&m_ZeppelinModel2);
parameters.m_SignalModelString += "Zeppelin";
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment2.Description", StringProperty::New("Inter-axonal compartment") );
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment2.Model", StringProperty::New("Zeppelin") );
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment2.D1", DoubleProperty::New(m_Controls->m_ZeppelinWidget2->GetD1()) );
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment2.D2", DoubleProperty::New(m_Controls->m_ZeppelinWidget2->GetD2()) );
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment2.T2", DoubleProperty::New(m_ZeppelinModel2.GetT2()) );
break;
case 3:
m_TensorModel2.SetGradientList(parameters.GetGradientDirections());
m_TensorModel2.SetBvalue(parameters.m_Bvalue);
m_TensorModel2.SetDiffusivity1(m_Controls->m_TensorWidget2->GetD1());
m_TensorModel2.SetDiffusivity2(m_Controls->m_TensorWidget2->GetD2());
m_TensorModel2.SetDiffusivity3(m_Controls->m_TensorWidget2->GetD3());
m_TensorModel2.SetT2(m_Controls->m_TensorWidget2->GetT2());
parameters.m_FiberModelList.push_back(&m_TensorModel2);
parameters.m_SignalModelString += "Tensor";
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment2.Description", StringProperty::New("Inter-axonal compartment") );
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment2.Model", StringProperty::New("Tensor") );
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment2.D1", DoubleProperty::New(m_Controls->m_TensorWidget2->GetD1()) );
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment2.D2", DoubleProperty::New(m_Controls->m_TensorWidget2->GetD2()) );
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment2.D3", DoubleProperty::New(m_Controls->m_TensorWidget2->GetD3()) );
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment2.T2", DoubleProperty::New(m_ZeppelinModel2.GetT2()) );
break;
}
// compartment 3
switch (m_Controls->m_Compartment3Box->currentIndex())
{
case 0:
m_BallModel1.SetGradientList(parameters.GetGradientDirections());
m_BallModel1.SetBvalue(parameters.m_Bvalue);
m_BallModel1.SetDiffusivity(m_Controls->m_BallWidget1->GetD());
m_BallModel1.SetT2(m_Controls->m_BallWidget1->GetT2());
parameters.m_NonFiberModelList.push_back(&m_BallModel1);
parameters.m_SignalModelString += "Ball";
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment3.Description", StringProperty::New("Extra-axonal compartment 1") );
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment3.Model", StringProperty::New("Ball") );
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment3.D", DoubleProperty::New(m_Controls->m_BallWidget1->GetD()) );
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment3.T2", DoubleProperty::New(m_BallModel1.GetT2()) );
break;
case 1:
m_AstrosticksModel1.SetGradientList(parameters.GetGradientDirections());
m_AstrosticksModel1.SetBvalue(parameters.m_Bvalue);
m_AstrosticksModel1.SetDiffusivity(m_Controls->m_AstrosticksWidget1->GetD());
m_AstrosticksModel1.SetT2(m_Controls->m_AstrosticksWidget1->GetT2());
m_AstrosticksModel1.SetRandomizeSticks(m_Controls->m_AstrosticksWidget1->GetRandomizeSticks());
parameters.m_NonFiberModelList.push_back(&m_AstrosticksModel1);
parameters.m_SignalModelString += "Astrosticks";
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment3.Description", StringProperty::New("Extra-axonal compartment 1") );
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment3.Model", StringProperty::New("Astrosticks") );
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment3.D", DoubleProperty::New(m_Controls->m_AstrosticksWidget1->GetD()) );
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment3.T2", DoubleProperty::New(m_AstrosticksModel1.GetT2()) );
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment3.RandomSticks", BoolProperty::New(m_Controls->m_AstrosticksWidget1->GetRandomizeSticks()) );
break;
case 2:
m_DotModel1.SetGradientList(parameters.GetGradientDirections());
m_DotModel1.SetT2(m_Controls->m_DotWidget1->GetT2());
parameters.m_NonFiberModelList.push_back(&m_DotModel1);
parameters.m_SignalModelString += "Dot";
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment3.Description", StringProperty::New("Extra-axonal compartment 1") );
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment3.Model", StringProperty::New("Dot") );
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment3.T2", DoubleProperty::New(m_DotModel1.GetT2()) );
break;
}
// compartment 4
switch (m_Controls->m_Compartment4Box->currentIndex())
{
case 0:
break;
case 1:
{
m_BallModel2.SetGradientList(parameters.GetGradientDirections());
m_BallModel2.SetBvalue(parameters.m_Bvalue);
m_BallModel2.SetDiffusivity(m_Controls->m_BallWidget2->GetD());
m_BallModel2.SetT2(m_Controls->m_BallWidget2->GetT2());
mitk::DataNode::Pointer volumeNode = m_Controls->m_Comp4VolumeFraction->GetSelectedNode();
if (volumeNode.IsNull())
{
MITK_WARN << "No volume fraction image selected! Second extra-axonal compartment has been disabled.";
break;
}
mitk::Image* img = dynamic_cast<mitk::Image*>(volumeNode->GetData());
ItkDoubleImgType::Pointer itkImg = ItkDoubleImgType::New();
CastToItkImage< ItkDoubleImgType >(img, itkImg);
double max = img->GetScalarValueMax();
double min = img->GetScalarValueMin();
if (max>1 || min<0) // are volume fractions between 0 and 1?
{
itk::RescaleIntensityImageFilter<ItkDoubleImgType,ItkDoubleImgType>::Pointer rescaler = itk::RescaleIntensityImageFilter<ItkDoubleImgType,ItkDoubleImgType>::New();
rescaler->SetInput(0, itkImg);
rescaler->SetOutputMaximum(1);
rescaler->SetOutputMinimum(0);
rescaler->Update();
itkImg = rescaler->GetOutput();
}
m_BallModel2.SetVolumeFractionImage(itkImg);
parameters.m_NonFiberModelList.push_back(&m_BallModel2);
parameters.m_SignalModelString += "Ball";
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment4.Description", StringProperty::New("Extra-axonal compartment 2") );
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment4.Model", StringProperty::New("Ball") );
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment4.D", DoubleProperty::New(m_Controls->m_BallWidget2->GetD()) );
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment4.T2", DoubleProperty::New(m_BallModel2.GetT2()) );
itk::InvertIntensityImageFilter< ItkDoubleImgType, ItkDoubleImgType >::Pointer inverter = itk::InvertIntensityImageFilter< ItkDoubleImgType, ItkDoubleImgType >::New();
inverter->SetMaximum(1.0);
inverter->SetInput(itkImg);
inverter->Update();
parameters.m_NonFiberModelList.at(parameters.m_NonFiberModelList.size()-2)->SetVolumeFractionImage(inverter->GetOutput());
break;
}
case 2:
{
m_AstrosticksModel2.SetGradientList(parameters.GetGradientDirections());
m_AstrosticksModel2.SetBvalue(parameters.m_Bvalue);
m_AstrosticksModel2.SetDiffusivity(m_Controls->m_AstrosticksWidget2->GetD());
m_AstrosticksModel2.SetT2(m_Controls->m_AstrosticksWidget2->GetT2());
m_AstrosticksModel2.SetRandomizeSticks(m_Controls->m_AstrosticksWidget2->GetRandomizeSticks());
mitk::DataNode::Pointer volumeNode = m_Controls->m_Comp4VolumeFraction->GetSelectedNode();
if (volumeNode.IsNull())
{
MITK_WARN << "No volume fraction image selected! Second extra-axonal compartment has been disabled.";
break;
}
mitk::Image* img = dynamic_cast<mitk::Image*>(volumeNode->GetData());
ItkDoubleImgType::Pointer itkImg = ItkDoubleImgType::New();
CastToItkImage< ItkDoubleImgType >(img, itkImg);
double max = img->GetScalarValueMax();
double min = img->GetScalarValueMin();
if (max>1 || min<0) // are volume fractions between 0 and 1?
{
itk::RescaleIntensityImageFilter<ItkDoubleImgType,ItkDoubleImgType>::Pointer rescaler = itk::RescaleIntensityImageFilter<ItkDoubleImgType,ItkDoubleImgType>::New();
rescaler->SetInput(0, itkImg);
rescaler->SetOutputMaximum(1);
rescaler->SetOutputMinimum(0);
rescaler->Update();
itkImg = rescaler->GetOutput();
}
m_AstrosticksModel2.SetVolumeFractionImage(itkImg);
parameters.m_NonFiberModelList.push_back(&m_AstrosticksModel2);
parameters.m_SignalModelString += "Astrosticks";
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment4.Description", StringProperty::New("Extra-axonal compartment 2") );
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment4.Model", StringProperty::New("Astrosticks") );
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment4.D", DoubleProperty::New(m_Controls->m_AstrosticksWidget2->GetD()) );
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment4.T2", DoubleProperty::New(m_AstrosticksModel2.GetT2()) );
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment4.RandomSticks", BoolProperty::New(m_Controls->m_AstrosticksWidget2->GetRandomizeSticks()) );
itk::InvertIntensityImageFilter< ItkDoubleImgType, ItkDoubleImgType >::Pointer inverter = itk::InvertIntensityImageFilter< ItkDoubleImgType, ItkDoubleImgType >::New();
inverter->SetMaximum( 1.0 );
inverter->SetInput(itkImg);
inverter->Update();
parameters.m_NonFiberModelList.at(parameters.m_NonFiberModelList.size()-2)->SetVolumeFractionImage(inverter->GetOutput());
break;
}
case 3:
{
m_DotModel2.SetGradientList(parameters.GetGradientDirections());
m_DotModel2.SetT2(m_Controls->m_DotWidget2->GetT2());
mitk::DataNode::Pointer volumeNode = m_Controls->m_Comp4VolumeFraction->GetSelectedNode();
if (volumeNode.IsNull())
{
MITK_WARN << "No volume fraction image selected! Second extra-axonal compartment has been disabled.";
break;
}
mitk::Image* img = dynamic_cast<mitk::Image*>(volumeNode->GetData());
ItkDoubleImgType::Pointer itkImg = ItkDoubleImgType::New();
CastToItkImage< ItkDoubleImgType >(img, itkImg);
double max = img->GetScalarValueMax();
double min = img->GetScalarValueMin();
if (max>1 || min<0) // are volume fractions between 0 and 1?
{
itk::RescaleIntensityImageFilter<ItkDoubleImgType,ItkDoubleImgType>::Pointer rescaler = itk::RescaleIntensityImageFilter<ItkDoubleImgType,ItkDoubleImgType>::New();
rescaler->SetInput(0, itkImg);
rescaler->SetOutputMaximum(1);
rescaler->SetOutputMinimum(0);
rescaler->Update();
itkImg = rescaler->GetOutput();
}
m_DotModel2.SetVolumeFractionImage(itkImg);
parameters.m_NonFiberModelList.push_back(&m_DotModel2);
parameters.m_SignalModelString += "Dot";
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment4.Description", StringProperty::New("Extra-axonal compartment 2") );
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment4.Model", StringProperty::New("Dot") );
parameters.m_ResultNode->AddProperty("Fiberfox.Compartment4.T2", DoubleProperty::New(m_DotModel2.GetT2()) );
itk::InvertIntensityImageFilter< ItkDoubleImgType, ItkDoubleImgType >::Pointer inverter = itk::InvertIntensityImageFilter< ItkDoubleImgType, ItkDoubleImgType >::New();
inverter->SetMaximum( 1.0 );
inverter->SetInput(itkImg);
inverter->Update();
parameters.m_NonFiberModelList.at(parameters.m_NonFiberModelList.size()-2)->SetVolumeFractionImage(inverter->GetOutput());
break;
}
}
parameters.m_ResultNode->AddProperty("Fiberfox.SignalScale", IntProperty::New(parameters.m_SignalScale));
parameters.m_ResultNode->AddProperty("Fiberfox.FiberRadius", IntProperty::New(parameters.m_AxonRadius));
parameters.m_ResultNode->AddProperty("Fiberfox.Tinhom", DoubleProperty::New(parameters.m_tInhom));
parameters.m_ResultNode->AddProperty("Fiberfox.Tline", DoubleProperty::New(parameters.m_tLine));
parameters.m_ResultNode->AddProperty("Fiberfox.TE", DoubleProperty::New(parameters.m_tEcho));
parameters.m_ResultNode->AddProperty("Fiberfox.Repetitions", IntProperty::New(parameters.m_Repetitions));
parameters.m_ResultNode->AddProperty("Fiberfox.b-value", DoubleProperty::New(parameters.m_Bvalue));
parameters.m_ResultNode->AddProperty("Fiberfox.NoPartialVolume", BoolProperty::New(parameters.m_DoDisablePartialVolume));
parameters.m_ResultNode->AddProperty("Fiberfox.Relaxation", BoolProperty::New(parameters.m_DoSimulateRelaxation));
parameters.m_ResultNode->AddProperty("binary", BoolProperty::New(false));
return parameters;
}
void QmitkFiberfoxView::SaveParameters()
{
FiberfoxParameters<double> ffParamaters = UpdateImageParameters<double>();
QString filename = QFileDialog::getSaveFileName(
0,
tr("Save Parameters"),
m_ParameterFile,
tr("Fiberfox Parameters (*.ffp)") );
if(filename.isEmpty() || filename.isNull())
return;
if(!filename.endsWith(".ffp"))
filename += ".ffp";
m_ParameterFile = filename;
boost::property_tree::ptree parameters;
// fiber generation parameters
parameters.put("fiberfox.fibers.realtime", m_Controls->m_RealTimeFibers->isChecked());
parameters.put("fiberfox.fibers.showadvanced", m_Controls->m_AdvancedOptionsBox->isChecked());
parameters.put("fiberfox.fibers.distribution", m_Controls->m_DistributionBox->currentIndex());
parameters.put("fiberfox.fibers.variance", m_Controls->m_VarianceBox->value());
parameters.put("fiberfox.fibers.density", m_Controls->m_FiberDensityBox->value());
parameters.put("fiberfox.fibers.spline.sampling", m_Controls->m_FiberSamplingBox->value());
parameters.put("fiberfox.fibers.spline.tension", m_Controls->m_TensionBox->value());
parameters.put("fiberfox.fibers.spline.continuity", m_Controls->m_ContinuityBox->value());
parameters.put("fiberfox.fibers.spline.bias", m_Controls->m_BiasBox->value());
parameters.put("fiberfox.fibers.constantradius", m_Controls->m_ConstantRadiusBox->isChecked());
parameters.put("fiberfox.fibers.rotation.x", m_Controls->m_XrotBox->value());
parameters.put("fiberfox.fibers.rotation.y", m_Controls->m_YrotBox->value());
parameters.put("fiberfox.fibers.rotation.z", m_Controls->m_ZrotBox->value());
parameters.put("fiberfox.fibers.translation.x", m_Controls->m_XtransBox->value());
parameters.put("fiberfox.fibers.translation.y", m_Controls->m_YtransBox->value());
parameters.put("fiberfox.fibers.translation.z", m_Controls->m_ZtransBox->value());
parameters.put("fiberfox.fibers.scale.x", m_Controls->m_XscaleBox->value());
parameters.put("fiberfox.fibers.scale.y", m_Controls->m_YscaleBox->value());
parameters.put("fiberfox.fibers.scale.z", m_Controls->m_ZscaleBox->value());
parameters.put("fiberfox.fibers.includeFiducials", m_Controls->m_IncludeFiducials->isChecked());
parameters.put("fiberfox.fibers.includeFiducials", m_Controls->m_IncludeFiducials->isChecked());
// image generation parameters
parameters.put("fiberfox.image.basic.size.x", ffParamaters.m_ImageRegion.GetSize(0));
parameters.put("fiberfox.image.basic.size.y", ffParamaters.m_ImageRegion.GetSize(1));
parameters.put("fiberfox.image.basic.size.z", ffParamaters.m_ImageRegion.GetSize(2));
parameters.put("fiberfox.image.basic.spacing.x", ffParamaters.m_ImageSpacing[0]);
parameters.put("fiberfox.image.basic.spacing.y", ffParamaters.m_ImageSpacing[1]);
parameters.put("fiberfox.image.basic.spacing.z", ffParamaters.m_ImageSpacing[2]);
parameters.put("fiberfox.image.basic.numgradients", ffParamaters.GetNumWeightedVolumes());
parameters.put("fiberfox.image.basic.bvalue", ffParamaters.m_Bvalue);
parameters.put("fiberfox.image.showadvanced", m_Controls->m_AdvancedOptionsBox_2->isChecked());
parameters.put("fiberfox.image.repetitions", ffParamaters.m_Repetitions);
parameters.put("fiberfox.image.signalScale", ffParamaters.m_SignalScale);
parameters.put("fiberfox.image.tEcho", ffParamaters.m_tEcho);
parameters.put("fiberfox.image.tLine", m_Controls->m_LineReadoutTimeBox->value());
parameters.put("fiberfox.image.tInhom", ffParamaters.m_tInhom);
parameters.put("fiberfox.image.axonRadius", ffParamaters.m_AxonRadius);
parameters.put("fiberfox.image.doSimulateRelaxation", ffParamaters.m_DoSimulateRelaxation);
parameters.put("fiberfox.image.doDisablePartialVolume", ffParamaters.m_DoDisablePartialVolume);
parameters.put("fiberfox.image.outputvolumefractions", m_Controls->m_VolumeFractionsBox->isChecked());
parameters.put("fiberfox.image.artifacts.addnoise", m_Controls->m_AddNoise->isChecked());
parameters.put("fiberfox.image.artifacts.noisedistribution", m_Controls->m_NoiseDistributionBox->currentIndex());
parameters.put("fiberfox.image.artifacts.noisevariance", m_Controls->m_NoiseLevel->value());
parameters.put("fiberfox.image.artifacts.addghost", m_Controls->m_AddGhosts->isChecked());
parameters.put("fiberfox.image.artifacts.kspaceLineOffset", m_Controls->m_kOffsetBox->value());
parameters.put("fiberfox.image.artifacts.distortions", m_Controls->m_AddDistortions->isChecked());
parameters.put("fiberfox.image.artifacts.addeddy", m_Controls->m_AddEddy->isChecked());
parameters.put("fiberfox.image.artifacts.eddyStrength", m_Controls->m_EddyGradientStrength->value());
parameters.put("fiberfox.image.artifacts.addringing", m_Controls->m_AddGibbsRinging->isChecked());
parameters.put("fiberfox.image.artifacts.addspikes", m_Controls->m_AddSpikes->isChecked());
parameters.put("fiberfox.image.artifacts.spikesnum", m_Controls->m_SpikeNumBox->value());
parameters.put("fiberfox.image.artifacts.spikesscale", m_Controls->m_SpikeScaleBox->value());
parameters.put("fiberfox.image.artifacts.addaliasing", m_Controls->m_AddAliasing->isChecked());
parameters.put("fiberfox.image.artifacts.aliasingfactor", m_Controls->m_WrapBox->value());
parameters.put("fiberfox.image.artifacts.doAddMotion", m_Controls->m_AddMotion->isChecked());
parameters.put("fiberfox.image.artifacts.randomMotion", m_Controls->m_RandomMotion->isChecked());
parameters.put("fiberfox.image.artifacts.translation0", m_Controls->m_MaxTranslationBoxX->value());
parameters.put("fiberfox.image.artifacts.translation1", m_Controls->m_MaxTranslationBoxY->value());
parameters.put("fiberfox.image.artifacts.translation2", m_Controls->m_MaxTranslationBoxZ->value());
parameters.put("fiberfox.image.artifacts.rotation0", m_Controls->m_MaxRotationBoxX->value());
parameters.put("fiberfox.image.artifacts.rotation1", m_Controls->m_MaxRotationBoxY->value());
parameters.put("fiberfox.image.artifacts.rotation2", m_Controls->m_MaxRotationBoxZ->value());
parameters.put("fiberfox.image.compartment1.index", m_Controls->m_Compartment1Box->currentIndex());
parameters.put("fiberfox.image.compartment2.index", m_Controls->m_Compartment2Box->currentIndex());
parameters.put("fiberfox.image.compartment3.index", m_Controls->m_Compartment3Box->currentIndex());
parameters.put("fiberfox.image.compartment4.index", m_Controls->m_Compartment4Box->currentIndex());
parameters.put("fiberfox.image.compartment1.stick.d", m_Controls->m_StickWidget1->GetD());
parameters.put("fiberfox.image.compartment1.stick.t2", m_Controls->m_StickWidget1->GetT2());
parameters.put("fiberfox.image.compartment1.zeppelin.d1", m_Controls->m_ZeppelinWidget1->GetD1());
parameters.put("fiberfox.image.compartment1.zeppelin.d2", m_Controls->m_ZeppelinWidget1->GetD2());
parameters.put("fiberfox.image.compartment1.zeppelin.t2", m_Controls->m_ZeppelinWidget1->GetT2());
parameters.put("fiberfox.image.compartment1.tensor.d1", m_Controls->m_TensorWidget1->GetD1());
parameters.put("fiberfox.image.compartment1.tensor.d2", m_Controls->m_TensorWidget1->GetD2());
parameters.put("fiberfox.image.compartment1.tensor.d3", m_Controls->m_TensorWidget1->GetD3());
parameters.put("fiberfox.image.compartment1.tensor.t2", m_Controls->m_TensorWidget1->GetT2());
parameters.put("fiberfox.image.compartment2.stick.d", m_Controls->m_StickWidget2->GetD());
parameters.put("fiberfox.image.compartment2.stick.t2", m_Controls->m_StickWidget2->GetT2());
parameters.put("fiberfox.image.compartment2.zeppelin.d1", m_Controls->m_ZeppelinWidget2->GetD1());
parameters.put("fiberfox.image.compartment2.zeppelin.d2", m_Controls->m_ZeppelinWidget2->GetD2());
parameters.put("fiberfox.image.compartment2.zeppelin.t2", m_Controls->m_ZeppelinWidget2->GetT2());
parameters.put("fiberfox.image.compartment2.tensor.d1", m_Controls->m_TensorWidget2->GetD1());
parameters.put("fiberfox.image.compartment2.tensor.d2", m_Controls->m_TensorWidget2->GetD2());
parameters.put("fiberfox.image.compartment2.tensor.d3", m_Controls->m_TensorWidget2->GetD3());
parameters.put("fiberfox.image.compartment2.tensor.t2", m_Controls->m_TensorWidget2->GetT2());
parameters.put("fiberfox.image.compartment3.ball.d", m_Controls->m_BallWidget1->GetD());
parameters.put("fiberfox.image.compartment3.ball.t2", m_Controls->m_BallWidget1->GetT2());
parameters.put("fiberfox.image.compartment3.astrosticks.d", m_Controls->m_AstrosticksWidget1->GetD());
parameters.put("fiberfox.image.compartment3.astrosticks.t2", m_Controls->m_AstrosticksWidget1->GetT2());
parameters.put("fiberfox.image.compartment3.astrosticks.randomize", m_Controls->m_AstrosticksWidget1->GetRandomizeSticks());
parameters.put("fiberfox.image.compartment3.dot.t2", m_Controls->m_DotWidget1->GetT2());
parameters.put("fiberfox.image.compartment4.ball.d", m_Controls->m_BallWidget2->GetD());
parameters.put("fiberfox.image.compartment4.ball.t2", m_Controls->m_BallWidget2->GetT2());
parameters.put("fiberfox.image.compartment4.astrosticks.d", m_Controls->m_AstrosticksWidget2->GetD());
parameters.put("fiberfox.image.compartment4.astrosticks.t2", m_Controls->m_AstrosticksWidget2->GetT2());
parameters.put("fiberfox.image.compartment4.astrosticks.randomize", m_Controls->m_AstrosticksWidget2->GetRandomizeSticks());
parameters.put("fiberfox.image.compartment4.dot.t2", m_Controls->m_DotWidget2->GetT2());
boost::property_tree::xml_parser::write_xml(filename.toStdString(), parameters);
}
void QmitkFiberfoxView::LoadParameters()
{
QString filename = QFileDialog::getOpenFileName(0, tr("Load Parameters"), QString(itksys::SystemTools::GetFilenamePath(m_ParameterFile.toStdString()).c_str()), tr("Fiberfox Parameters (*.ffp)") );
if(filename.isEmpty() || filename.isNull())
return;
m_ParameterFile = filename;
boost::property_tree::ptree parameters;
boost::property_tree::xml_parser::read_xml(filename.toStdString(), parameters);
BOOST_FOREACH( boost::property_tree::ptree::value_type const& v1, parameters.get_child("fiberfox") )
{
if( v1.first == "fibers" )
{
m_Controls->m_RealTimeFibers->setChecked(v1.second.get<bool>("realtime"));
m_Controls->m_AdvancedOptionsBox->setChecked(v1.second.get<bool>("showadvanced"));
m_Controls->m_DistributionBox->setCurrentIndex(v1.second.get<int>("distribution"));
m_Controls->m_VarianceBox->setValue(v1.second.get<double>("variance"));
m_Controls->m_FiberDensityBox->setValue(v1.second.get<int>("density"));
m_Controls->m_IncludeFiducials->setChecked(v1.second.get<bool>("includeFiducials"));
m_Controls->m_ConstantRadiusBox->setChecked(v1.second.get<bool>("constantradius"));
BOOST_FOREACH( boost::property_tree::ptree::value_type const& v2, v1.second )
{
if( v2.first == "spline" )
{
m_Controls->m_FiberSamplingBox->setValue(v2.second.get<double>("sampling"));
m_Controls->m_TensionBox->setValue(v2.second.get<double>("tension"));
m_Controls->m_ContinuityBox->setValue(v2.second.get<double>("continuity"));
m_Controls->m_BiasBox->setValue(v2.second.get<double>("bias"));
}
if( v2.first == "rotation" )
{
m_Controls->m_XrotBox->setValue(v2.second.get<double>("x"));
m_Controls->m_YrotBox->setValue(v2.second.get<double>("y"));
m_Controls->m_ZrotBox->setValue(v2.second.get<double>("z"));
}
if( v2.first == "translation" )
{
m_Controls->m_XtransBox->setValue(v2.second.get<double>("x"));
m_Controls->m_YtransBox->setValue(v2.second.get<double>("y"));
m_Controls->m_ZtransBox->setValue(v2.second.get<double>("z"));
}
if( v2.first == "scale" )
{
m_Controls->m_XscaleBox->setValue(v2.second.get<double>("x"));
m_Controls->m_YscaleBox->setValue(v2.second.get<double>("y"));
m_Controls->m_ZscaleBox->setValue(v2.second.get<double>("z"));
}
}
}
if( v1.first == "image" )
{
m_Controls->m_SizeX->setValue(v1.second.get<int>("basic.size.x"));
m_Controls->m_SizeY->setValue(v1.second.get<int>("basic.size.y"));
m_Controls->m_SizeZ->setValue(v1.second.get<int>("basic.size.z"));
m_Controls->m_SpacingX->setValue(v1.second.get<double>("basic.spacing.x"));
m_Controls->m_SpacingY->setValue(v1.second.get<double>("basic.spacing.y"));
m_Controls->m_SpacingZ->setValue(v1.second.get<double>("basic.spacing.z"));
m_Controls->m_NumGradientsBox->setValue(v1.second.get<int>("basic.numgradients"));
m_Controls->m_BvalueBox->setValue(v1.second.get<int>("basic.bvalue"));
m_Controls->m_AdvancedOptionsBox_2->setChecked(v1.second.get<bool>("showadvanced"));
m_Controls->m_RepetitionsBox->setValue(v1.second.get<int>("repetitions"));
m_Controls->m_SignalScaleBox->setValue(v1.second.get<int>("signalScale"));
m_Controls->m_TEbox->setValue(v1.second.get<double>("tEcho"));
m_Controls->m_LineReadoutTimeBox->setValue(v1.second.get<double>("tLine"));
m_Controls->m_T2starBox->setValue(v1.second.get<double>("tInhom"));
m_Controls->m_FiberRadius->setValue(v1.second.get<double>("axonRadius"));
m_Controls->m_RelaxationBox->setChecked(v1.second.get<bool>("doSimulateRelaxation"));
m_Controls->m_EnforcePureFiberVoxelsBox->setChecked(v1.second.get<bool>("doDisablePartialVolume"));
m_Controls->m_VolumeFractionsBox->setChecked(v1.second.get<bool>("outputvolumefractions"));
m_Controls->m_AddNoise->setChecked(v1.second.get<bool>("artifacts.addnoise"));
m_Controls->m_NoiseDistributionBox->setCurrentIndex(v1.second.get<int>("artifacts.noisedistribution"));
m_Controls->m_NoiseLevel->setValue(v1.second.get<double>("artifacts.noisevariance"));
m_Controls->m_AddGhosts->setChecked(v1.second.get<bool>("artifacts.addghost"));
m_Controls->m_kOffsetBox->setValue(v1.second.get<double>("artifacts.kspaceLineOffset"));
m_Controls->m_AddAliasing->setChecked(v1.second.get<bool>("artifacts.addaliasing"));
m_Controls->m_WrapBox->setValue(v1.second.get<double>("artifacts.aliasingfactor"));
m_Controls->m_AddDistortions->setChecked(v1.second.get<bool>("artifacts.distortions"));
m_Controls->m_AddSpikes->setChecked(v1.second.get<bool>("artifacts.addspikes"));
m_Controls->m_SpikeNumBox->setValue(v1.second.get<int>("artifacts.spikesnum"));
m_Controls->m_SpikeScaleBox->setValue(v1.second.get<double>("artifacts.spikesscale"));
m_Controls->m_AddEddy->setChecked(v1.second.get<bool>("artifacts.addeddy"));
m_Controls->m_EddyGradientStrength->setValue(v1.second.get<double>("artifacts.eddyStrength"));
m_Controls->m_AddGibbsRinging->setChecked(v1.second.get<bool>("artifacts.addringing"));
m_Controls->m_AddMotion->setChecked(v1.second.get<bool>("artifacts.doAddMotion"));
m_Controls->m_RandomMotion->setChecked(v1.second.get<bool>("artifacts.randomMotion"));
m_Controls->m_MaxTranslationBoxX->setValue(v1.second.get<double>("artifacts.translation0"));
m_Controls->m_MaxTranslationBoxY->setValue(v1.second.get<double>("artifacts.translation1"));
m_Controls->m_MaxTranslationBoxZ->setValue(v1.second.get<double>("artifacts.translation2"));
m_Controls->m_MaxRotationBoxX->setValue(v1.second.get<double>("artifacts.rotation0"));
m_Controls->m_MaxRotationBoxY->setValue(v1.second.get<double>("artifacts.rotation1"));
m_Controls->m_MaxRotationBoxZ->setValue(v1.second.get<double>("artifacts.rotation2"));
m_Controls->m_Compartment1Box->setCurrentIndex(v1.second.get<int>("compartment1.index"));
m_Controls->m_Compartment2Box->setCurrentIndex(v1.second.get<int>("compartment2.index"));
m_Controls->m_Compartment3Box->setCurrentIndex(v1.second.get<int>("compartment3.index"));
m_Controls->m_Compartment4Box->setCurrentIndex(v1.second.get<int>("compartment4.index"));
m_Controls->m_StickWidget1->SetD(v1.second.get<double>("compartment1.stick.d"));
m_Controls->m_StickWidget1->SetT2(v1.second.get<double>("compartment1.stick.t2"));
m_Controls->m_ZeppelinWidget1->SetD1(v1.second.get<double>("compartment1.zeppelin.d1"));
m_Controls->m_ZeppelinWidget1->SetD2(v1.second.get<double>("compartment1.zeppelin.d2"));
m_Controls->m_ZeppelinWidget1->SetT2(v1.second.get<double>("compartment1.zeppelin.t2"));
m_Controls->m_TensorWidget1->SetD1(v1.second.get<double>("compartment1.tensor.d1"));
m_Controls->m_TensorWidget1->SetD2(v1.second.get<double>("compartment1.tensor.d2"));
m_Controls->m_TensorWidget1->SetD3(v1.second.get<double>("compartment1.tensor.d3"));
m_Controls->m_TensorWidget1->SetT2(v1.second.get<double>("compartment1.tensor.t2"));
m_Controls->m_StickWidget2->SetD(v1.second.get<double>("compartment2.stick.d"));
m_Controls->m_StickWidget2->SetT2(v1.second.get<double>("compartment2.stick.t2"));
m_Controls->m_ZeppelinWidget2->SetD1(v1.second.get<double>("compartment2.zeppelin.d1"));
m_Controls->m_ZeppelinWidget2->SetD2(v1.second.get<double>("compartment2.zeppelin.d2"));
m_Controls->m_ZeppelinWidget2->SetT2(v1.second.get<double>("compartment2.zeppelin.t2"));
m_Controls->m_TensorWidget2->SetD1(v1.second.get<double>("compartment2.tensor.d1"));
m_Controls->m_TensorWidget2->SetD2(v1.second.get<double>("compartment2.tensor.d2"));
m_Controls->m_TensorWidget2->SetD3(v1.second.get<double>("compartment2.tensor.d3"));
m_Controls->m_TensorWidget2->SetT2(v1.second.get<double>("compartment2.tensor.t2"));
m_Controls->m_BallWidget1->SetD(v1.second.get<double>("compartment3.ball.d"));
m_Controls->m_BallWidget1->SetT2(v1.second.get<double>("compartment3.ball.t2"));
m_Controls->m_AstrosticksWidget1->SetD(v1.second.get<double>("compartment3.astrosticks.d"));
m_Controls->m_AstrosticksWidget1->SetT2(v1.second.get<double>("compartment3.astrosticks.t2"));
m_Controls->m_AstrosticksWidget1->SetRandomizeSticks(v1.second.get<bool>("compartment3.astrosticks.randomize"));
m_Controls->m_DotWidget1->SetT2(v1.second.get<double>("compartment3.dot.t2"));
m_Controls->m_BallWidget2->SetD(v1.second.get<double>("compartment4.ball.d"));
m_Controls->m_BallWidget2->SetT2(v1.second.get<double>("compartment4.ball.t2"));
m_Controls->m_AstrosticksWidget2->SetD(v1.second.get<double>("compartment4.astrosticks.d"));
m_Controls->m_AstrosticksWidget2->SetT2(v1.second.get<double>("compartment4.astrosticks.t2"));
m_Controls->m_AstrosticksWidget2->SetRandomizeSticks(v1.second.get<bool>("compartment4.astrosticks.randomize"));
m_Controls->m_DotWidget2->SetT2(v1.second.get<double>("compartment4.dot.t2"));
}
}
}
void QmitkFiberfoxView::ShowAdvancedOptions(int state)
{
if (state)
{
m_Controls->m_AdvancedFiberOptionsFrame->setVisible(true);
m_Controls->m_AdvancedSignalOptionsFrame->setVisible(true);
m_Controls->m_AdvancedOptionsBox->setChecked(true);
m_Controls->m_AdvancedOptionsBox_2->setChecked(true);
}
else
{
m_Controls->m_AdvancedFiberOptionsFrame->setVisible(false);
m_Controls->m_AdvancedSignalOptionsFrame->setVisible(false);
m_Controls->m_AdvancedOptionsBox->setChecked(false);
m_Controls->m_AdvancedOptionsBox_2->setChecked(false);
}
}
void QmitkFiberfoxView::Comp1ModelFrameVisibility(int index)
{
m_Controls->m_StickWidget1->setVisible(false);
m_Controls->m_ZeppelinWidget1->setVisible(false);
m_Controls->m_TensorWidget1->setVisible(false);
switch (index)
{
case 0:
m_Controls->m_StickWidget1->setVisible(true);
break;
case 1:
m_Controls->m_ZeppelinWidget1->setVisible(true);
break;
case 2:
m_Controls->m_TensorWidget1->setVisible(true);
break;
}
}
void QmitkFiberfoxView::Comp2ModelFrameVisibility(int index)
{
m_Controls->m_StickWidget2->setVisible(false);
m_Controls->m_ZeppelinWidget2->setVisible(false);
m_Controls->m_TensorWidget2->setVisible(false);
switch (index)
{
case 0:
break;
case 1:
m_Controls->m_StickWidget2->setVisible(true);
break;
case 2:
m_Controls->m_ZeppelinWidget2->setVisible(true);
break;
case 3:
m_Controls->m_TensorWidget2->setVisible(true);
break;
}
}
void QmitkFiberfoxView::Comp3ModelFrameVisibility(int index)
{
m_Controls->m_BallWidget1->setVisible(false);
m_Controls->m_AstrosticksWidget1->setVisible(false);
m_Controls->m_DotWidget1->setVisible(false);
switch (index)
{
case 0:
m_Controls->m_BallWidget1->setVisible(true);
break;
case 1:
m_Controls->m_AstrosticksWidget1->setVisible(true);
break;
case 2:
m_Controls->m_DotWidget1->setVisible(true);
break;
}
}
void QmitkFiberfoxView::Comp4ModelFrameVisibility(int index)
{
m_Controls->m_BallWidget2->setVisible(false);
m_Controls->m_AstrosticksWidget2->setVisible(false);
m_Controls->m_DotWidget2->setVisible(false);
m_Controls->m_Comp4FractionFrame->setVisible(false);
switch (index)
{
case 0:
break;
case 1:
m_Controls->m_BallWidget2->setVisible(true);
m_Controls->m_Comp4FractionFrame->setVisible(true);
break;
case 2:
m_Controls->m_AstrosticksWidget2->setVisible(true);
m_Controls->m_Comp4FractionFrame->setVisible(true);
break;
case 3:
m_Controls->m_DotWidget2->setVisible(true);
m_Controls->m_Comp4FractionFrame->setVisible(true);
break;
}
}
void QmitkFiberfoxView::OnConstantRadius(int value)
{
if (value>0 && m_Controls->m_RealTimeFibers->isChecked())
GenerateFibers();
}
void QmitkFiberfoxView::OnAddMotion(int value)
{
if (value>0)
m_Controls->m_MotionArtifactFrame->setVisible(true);
else
m_Controls->m_MotionArtifactFrame->setVisible(false);
}
void QmitkFiberfoxView::OnAddAliasing(int value)
{
if (value>0)
m_Controls->m_AliasingFrame->setVisible(true);
else
m_Controls->m_AliasingFrame->setVisible(false);
}
void QmitkFiberfoxView::OnAddSpikes(int value)
{
if (value>0)
m_Controls->m_SpikeFrame->setVisible(true);
else
m_Controls->m_SpikeFrame->setVisible(false);
}
void QmitkFiberfoxView::OnAddEddy(int value)
{
if (value>0)
m_Controls->m_EddyFrame->setVisible(true);
else
m_Controls->m_EddyFrame->setVisible(false);
}
void QmitkFiberfoxView::OnAddDistortions(int value)
{
if (value>0)
m_Controls->m_DistortionsFrame->setVisible(true);
else
m_Controls->m_DistortionsFrame->setVisible(false);
}
void QmitkFiberfoxView::OnAddGhosts(int value)
{
if (value>0)
m_Controls->m_GhostFrame->setVisible(true);
else
m_Controls->m_GhostFrame->setVisible(false);
}
void QmitkFiberfoxView::OnAddNoise(int value)
{
if (value>0)
m_Controls->m_NoiseFrame->setVisible(true);
else
m_Controls->m_NoiseFrame->setVisible(false);
}
void QmitkFiberfoxView::OnDistributionChanged(int value)
{
if (value==1)
m_Controls->m_VarianceBox->setVisible(true);
else
m_Controls->m_VarianceBox->setVisible(false);
if (m_Controls->m_RealTimeFibers->isChecked())
GenerateFibers();
}
void QmitkFiberfoxView::OnVarianceChanged(double)
{
if (m_Controls->m_RealTimeFibers->isChecked())
GenerateFibers();
}
void QmitkFiberfoxView::OnFiberDensityChanged(int)
{
if (m_Controls->m_RealTimeFibers->isChecked())
GenerateFibers();
}
void QmitkFiberfoxView::OnFiberSamplingChanged(double)
{
if (m_Controls->m_RealTimeFibers->isChecked())
GenerateFibers();
}
void QmitkFiberfoxView::OnTensionChanged(double)
{
if (m_Controls->m_RealTimeFibers->isChecked())
GenerateFibers();
}
void QmitkFiberfoxView::OnContinuityChanged(double)
{
if (m_Controls->m_RealTimeFibers->isChecked())
GenerateFibers();
}
void QmitkFiberfoxView::OnBiasChanged(double)
{
if (m_Controls->m_RealTimeFibers->isChecked())
GenerateFibers();
}
void QmitkFiberfoxView::AlignOnGrid()
{
for (unsigned int i=0; i<m_SelectedFiducials.size(); i++)
{
mitk::PlanarEllipse::Pointer pe = dynamic_cast<mitk::PlanarEllipse*>(m_SelectedFiducials.at(i)->GetData());
mitk::Point3D wc0 = pe->GetWorldControlPoint(0);
mitk::DataStorage::SetOfObjects::ConstPointer parentFibs = GetDataStorage()->GetSources(m_SelectedFiducials.at(i));
for( mitk::DataStorage::SetOfObjects::const_iterator it = parentFibs->begin(); it != parentFibs->end(); ++it )
{
mitk::DataNode::Pointer pFibNode = *it;
if ( pFibNode.IsNotNull() && dynamic_cast<mitk::FiberBundleX*>(pFibNode->GetData()) )
{
mitk::DataStorage::SetOfObjects::ConstPointer parentImgs = GetDataStorage()->GetSources(pFibNode);
for( mitk::DataStorage::SetOfObjects::const_iterator it2 = parentImgs->begin(); it2 != parentImgs->end(); ++it2 )
{
mitk::DataNode::Pointer pImgNode = *it2;
if ( pImgNode.IsNotNull() && dynamic_cast<mitk::Image*>(pImgNode->GetData()) )
{
mitk::Image::Pointer img = dynamic_cast<mitk::Image*>(pImgNode->GetData());
- mitk::Geometry3D::Pointer geom = img->GetGeometry();
+ mitk::BaseGeometry::Pointer geom = img->GetGeometry();
itk::Index<3> idx;
geom->WorldToIndex(wc0, idx);
mitk::Point3D cIdx; cIdx[0]=idx[0]; cIdx[1]=idx[1]; cIdx[2]=idx[2];
mitk::Point3D world;
geom->IndexToWorld(cIdx,world);
mitk::Vector3D trans = world - wc0;
pe->GetGeometry()->Translate(trans);
break;
}
}
break;
}
}
}
for(unsigned int i=0; i<m_SelectedBundles2.size(); i++ )
{
mitk::DataNode::Pointer fibNode = m_SelectedBundles2.at(i);
mitk::DataStorage::SetOfObjects::ConstPointer sources = GetDataStorage()->GetSources(fibNode);
for( mitk::DataStorage::SetOfObjects::const_iterator it = sources->begin(); it != sources->end(); ++it )
{
mitk::DataNode::Pointer imgNode = *it;
if ( imgNode.IsNotNull() && dynamic_cast<mitk::Image*>(imgNode->GetData()) )
{
mitk::DataStorage::SetOfObjects::ConstPointer derivations = GetDataStorage()->GetDerivations(fibNode);
for( mitk::DataStorage::SetOfObjects::const_iterator it2 = derivations->begin(); it2 != derivations->end(); ++it2 )
{
mitk::DataNode::Pointer fiducialNode = *it2;
if ( fiducialNode.IsNotNull() && dynamic_cast<mitk::PlanarEllipse*>(fiducialNode->GetData()) )
{
mitk::PlanarEllipse::Pointer pe = dynamic_cast<mitk::PlanarEllipse*>(fiducialNode->GetData());
mitk::Point3D wc0 = pe->GetWorldControlPoint(0);
mitk::Image::Pointer img = dynamic_cast<mitk::Image*>(imgNode->GetData());
- mitk::Geometry3D::Pointer geom = img->GetGeometry();
+ mitk::BaseGeometry::Pointer geom = img->GetGeometry();
itk::Index<3> idx;
geom->WorldToIndex(wc0, idx);
mitk::Point3D cIdx; cIdx[0]=idx[0]; cIdx[1]=idx[1]; cIdx[2]=idx[2];
mitk::Point3D world;
geom->IndexToWorld(cIdx,world);
mitk::Vector3D trans = world - wc0;
pe->GetGeometry()->Translate(trans);
}
}
break;
}
}
}
for(unsigned int i=0; i<m_SelectedImages.size(); i++ )
{
mitk::Image::Pointer img = dynamic_cast<mitk::Image*>(m_SelectedImages.at(i)->GetData());
mitk::DataStorage::SetOfObjects::ConstPointer derivations = GetDataStorage()->GetDerivations(m_SelectedImages.at(i));
for( mitk::DataStorage::SetOfObjects::const_iterator it = derivations->begin(); it != derivations->end(); ++it )
{
mitk::DataNode::Pointer fibNode = *it;
if ( fibNode.IsNotNull() && dynamic_cast<mitk::FiberBundleX*>(fibNode->GetData()) )
{
mitk::DataStorage::SetOfObjects::ConstPointer derivations2 = GetDataStorage()->GetDerivations(fibNode);
for( mitk::DataStorage::SetOfObjects::const_iterator it2 = derivations2->begin(); it2 != derivations2->end(); ++it2 )
{
mitk::DataNode::Pointer fiducialNode = *it2;
if ( fiducialNode.IsNotNull() && dynamic_cast<mitk::PlanarEllipse*>(fiducialNode->GetData()) )
{
mitk::PlanarEllipse::Pointer pe = dynamic_cast<mitk::PlanarEllipse*>(fiducialNode->GetData());
mitk::Point3D wc0 = pe->GetWorldControlPoint(0);
- mitk::Geometry3D::Pointer geom = img->GetGeometry();
+ mitk::BaseGeometry::Pointer geom = img->GetGeometry();
itk::Index<3> idx;
geom->WorldToIndex(wc0, idx);
mitk::Point3D cIdx; cIdx[0]=idx[0]; cIdx[1]=idx[1]; cIdx[2]=idx[2];
mitk::Point3D world;
geom->IndexToWorld(cIdx,world);
mitk::Vector3D trans = world - wc0;
pe->GetGeometry()->Translate(trans);
}
}
}
}
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
if (m_Controls->m_RealTimeFibers->isChecked())
GenerateFibers();
}
void QmitkFiberfoxView::OnFlipButton()
{
if (m_SelectedFiducial.IsNull())
return;
std::map<mitk::DataNode*, QmitkPlanarFigureData>::iterator it = m_DataNodeToPlanarFigureData.find(m_SelectedFiducial.GetPointer());
if( it != m_DataNodeToPlanarFigureData.end() )
{
QmitkPlanarFigureData& data = it->second;
data.m_Flipped += 1;
data.m_Flipped %= 2;
}
if (m_Controls->m_RealTimeFibers->isChecked())
GenerateFibers();
}
QmitkFiberfoxView::GradientListType QmitkFiberfoxView::GenerateHalfShell(int NPoints)
{
NPoints *= 2;
GradientListType pointshell;
int numB0 = NPoints/20;
if (numB0==0)
numB0=1;
GradientType g;
g.Fill(0.0);
for (int i=0; i<numB0; i++)
pointshell.push_back(g);
if (NPoints==0)
return pointshell;
vnl_vector<double> theta; theta.set_size(NPoints);
vnl_vector<double> phi; phi.set_size(NPoints);
double C = sqrt(4*M_PI);
phi(0) = 0.0;
phi(NPoints-1) = 0.0;
for(int i=0; i<NPoints; i++)
{
theta(i) = acos(-1.0+2.0*i/(NPoints-1.0)) - M_PI / 2.0;
if( i>0 && i<NPoints-1)
{
phi(i) = (phi(i-1) + C /
sqrt(NPoints*(1-(-1.0+2.0*i/(NPoints-1.0))*(-1.0+2.0*i/(NPoints-1.0)))));
// % (2*DIST_POINTSHELL_PI);
}
}
for(int i=0; i<NPoints; i++)
{
g[2] = sin(theta(i));
if (g[2]<0)
continue;
g[0] = cos(theta(i)) * cos(phi(i));
g[1] = cos(theta(i)) * sin(phi(i));
pointshell.push_back(g);
}
return pointshell;
}
template<int ndirs>
std::vector<itk::Vector<double,3> > QmitkFiberfoxView::MakeGradientList()
{
std::vector<itk::Vector<double,3> > retval;
vnl_matrix_fixed<double, 3, ndirs>* U =
itk::PointShell<ndirs, vnl_matrix_fixed<double, 3, ndirs> >::DistributePointShell();
// Add 0 vector for B0
int numB0 = ndirs/10;
if (numB0==0)
numB0=1;
itk::Vector<double,3> v;
v.Fill(0.0);
for (int i=0; i<numB0; i++)
{
retval.push_back(v);
}
for(int i=0; i<ndirs;i++)
{
itk::Vector<double,3> v;
v[0] = U->get(0,i); v[1] = U->get(1,i); v[2] = U->get(2,i);
retval.push_back(v);
}
return retval;
}
void QmitkFiberfoxView::OnAddBundle()
{
if (m_SelectedImage.IsNull())
return;
mitk::DataStorage::SetOfObjects::ConstPointer children = GetDataStorage()->GetDerivations(m_SelectedImage);
mitk::FiberBundleX::Pointer bundle = mitk::FiberBundleX::New();
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData( bundle );
QString name = QString("Bundle_%1").arg(children->size());
node->SetName(name.toStdString());
m_SelectedBundles.push_back(node);
UpdateGui();
GetDataStorage()->Add(node, m_SelectedImage);
}
void QmitkFiberfoxView::OnDrawROI()
{
if (m_SelectedBundles.empty())
OnAddBundle();
if (m_SelectedBundles.empty())
return;
mitk::DataStorage::SetOfObjects::ConstPointer children = GetDataStorage()->GetDerivations(m_SelectedBundles.at(0));
mitk::PlanarEllipse::Pointer figure = mitk::PlanarEllipse::New();
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData( figure );
node->SetBoolProperty("planarfigure.3drendering", true);
QList<mitk::DataNode::Pointer> nodes = this->GetDataManagerSelection();
for( int i=0; i<nodes.size(); i++)
nodes.at(i)->SetSelected(false);
m_SelectedFiducial = node;
QString name = QString("Fiducial_%1").arg(children->size());
node->SetName(name.toStdString());
node->SetSelected(true);
this->DisableCrosshairNavigation();
mitk::PlanarFigureInteractor::Pointer figureInteractor = dynamic_cast<mitk::PlanarFigureInteractor*>(node->GetDataInteractor().GetPointer());
if(figureInteractor.IsNull())
{
figureInteractor = mitk::PlanarFigureInteractor::New();
us::Module* planarFigureModule = us::ModuleRegistry::GetModule( "MitkPlanarFigure" );
figureInteractor->LoadStateMachine("PlanarFigureInteraction.xml", planarFigureModule );
figureInteractor->SetEventConfig( "PlanarFigureConfig.xml", planarFigureModule );
figureInteractor->SetDataNode( node );
}
UpdateGui();
GetDataStorage()->Add(node, m_SelectedBundles.at(0));
}
bool CompareLayer(mitk::DataNode::Pointer i,mitk::DataNode::Pointer j)
{
int li = -1;
i->GetPropertyValue("layer", li);
int lj = -1;
j->GetPropertyValue("layer", lj);
return li<lj;
}
void QmitkFiberfoxView::GenerateFibers()
{
if (m_SelectedBundles.empty())
{
if (m_SelectedFiducial.IsNull())
return;
mitk::DataStorage::SetOfObjects::ConstPointer parents = GetDataStorage()->GetSources(m_SelectedFiducial);
for( mitk::DataStorage::SetOfObjects::const_iterator it = parents->begin(); it != parents->end(); ++it )
if(dynamic_cast<mitk::FiberBundleX*>((*it)->GetData()))
m_SelectedBundles.push_back(*it);
if (m_SelectedBundles.empty())
return;
}
vector< vector< mitk::PlanarEllipse::Pointer > > fiducials;
vector< vector< unsigned int > > fliplist;
for (unsigned int i=0; i<m_SelectedBundles.size(); i++)
{
mitk::DataStorage::SetOfObjects::ConstPointer children = GetDataStorage()->GetDerivations(m_SelectedBundles.at(i));
std::vector< mitk::DataNode::Pointer > childVector;
for( mitk::DataStorage::SetOfObjects::const_iterator it = children->begin(); it != children->end(); ++it )
childVector.push_back(*it);
sort(childVector.begin(), childVector.end(), CompareLayer);
vector< mitk::PlanarEllipse::Pointer > fib;
vector< unsigned int > flip;
float radius = 1;
int count = 0;
for( std::vector< mitk::DataNode::Pointer >::const_iterator it = childVector.begin(); it != childVector.end(); ++it )
{
mitk::DataNode::Pointer node = *it;
if ( node.IsNotNull() && dynamic_cast<mitk::PlanarEllipse*>(node->GetData()) )
{
mitk::PlanarEllipse* ellipse = dynamic_cast<mitk::PlanarEllipse*>(node->GetData());
if (m_Controls->m_ConstantRadiusBox->isChecked())
{
ellipse->SetTreatAsCircle(true);
mitk::Point2D c = ellipse->GetControlPoint(0);
mitk::Point2D p = ellipse->GetControlPoint(1);
mitk::Vector2D v = p-c;
if (count==0)
{
radius = v.GetVnlVector().magnitude();
ellipse->SetControlPoint(1, p);
}
else
{
v.Normalize();
v *= radius;
ellipse->SetControlPoint(1, c+v);
}
}
fib.push_back(ellipse);
std::map<mitk::DataNode*, QmitkPlanarFigureData>::iterator it = m_DataNodeToPlanarFigureData.find(node.GetPointer());
if( it != m_DataNodeToPlanarFigureData.end() )
{
QmitkPlanarFigureData& data = it->second;
flip.push_back(data.m_Flipped);
}
else
flip.push_back(0);
}
count++;
}
if (fib.size()>1)
{
fiducials.push_back(fib);
fliplist.push_back(flip);
}
else if (fib.size()>0)
m_SelectedBundles.at(i)->SetData( mitk::FiberBundleX::New() );
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
itk::FibersFromPlanarFiguresFilter::Pointer filter = itk::FibersFromPlanarFiguresFilter::New();
filter->SetFiducials(fiducials);
filter->SetFlipList(fliplist);
switch(m_Controls->m_DistributionBox->currentIndex()){
case 0:
filter->SetFiberDistribution(itk::FibersFromPlanarFiguresFilter::DISTRIBUTE_UNIFORM);
break;
case 1:
filter->SetFiberDistribution(itk::FibersFromPlanarFiguresFilter::DISTRIBUTE_GAUSSIAN);
filter->SetVariance(m_Controls->m_VarianceBox->value());
break;
}
filter->SetDensity(m_Controls->m_FiberDensityBox->value());
filter->SetTension(m_Controls->m_TensionBox->value());
filter->SetContinuity(m_Controls->m_ContinuityBox->value());
filter->SetBias(m_Controls->m_BiasBox->value());
filter->SetFiberSampling(m_Controls->m_FiberSamplingBox->value());
filter->Update();
vector< mitk::FiberBundleX::Pointer > fiberBundles = filter->GetFiberBundles();
for (unsigned int i=0; i<fiberBundles.size(); i++)
{
m_SelectedBundles.at(i)->SetData( fiberBundles.at(i) );
if (fiberBundles.at(i)->GetNumFibers()>50000)
m_SelectedBundles.at(i)->SetVisibility(false);
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkFiberfoxView::GenerateImage()
{
if (m_SelectedBundles.empty() && m_SelectedDWI.IsNull())
{
mitk::Image::Pointer image = mitk::ImageGenerator::GenerateGradientImage<unsigned int>(
m_Controls->m_SizeX->value(),
m_Controls->m_SizeY->value(),
m_Controls->m_SizeZ->value(),
m_Controls->m_SpacingX->value(),
m_Controls->m_SpacingY->value(),
m_Controls->m_SpacingZ->value());
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData( image );
node->SetName("Dummy");
unsigned int window = m_Controls->m_SizeX->value()*m_Controls->m_SizeY->value()*m_Controls->m_SizeZ->value();
unsigned int level = window/2;
mitk::LevelWindow lw; lw.SetLevelWindow(level, window);
node->SetProperty( "levelwindow", mitk::LevelWindowProperty::New( lw ) );
GetDataStorage()->Add(node);
m_SelectedImage = node;
mitk::BaseData::Pointer basedata = node->GetData();
if (basedata.IsNotNull())
{
mitk::RenderingManager::GetInstance()->InitializeViews( basedata->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true );
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
UpdateGui();
}
else if (!m_SelectedBundles.empty())
SimulateImageFromFibers(m_SelectedBundles.at(0));
else if (m_SelectedDWI.IsNotNull())
SimulateForExistingDwi(m_SelectedDWI);
}
void QmitkFiberfoxView::SimulateForExistingDwi(mitk::DataNode* imageNode)
{
if (!dynamic_cast<mitk::DiffusionImage<short>*>(imageNode->GetData()))
return;
FiberfoxParameters<short> parameters = UpdateImageParameters<short>();
if (parameters.m_NoiseModel==NULL &&
parameters.m_Spikes==0 &&
parameters.m_FrequencyMap.IsNull() &&
parameters.m_KspaceLineOffset<=0.000001 &&
!parameters.m_DoAddGibbsRinging &&
!(parameters.m_EddyStrength>0) &&
parameters.m_CroppingFactor>0.999)
{
QMessageBox::information( NULL, "Simulation cancelled", "No valid artifact enabled! Motion artifacts and relaxation effects can NOT be added to an existing diffusion weighted image.");
return;
}
mitk::DiffusionImage<short>::Pointer diffImg = dynamic_cast<mitk::DiffusionImage<short>*>(imageNode->GetData());
m_ArtifactsToDwiFilter = itk::AddArtifactsToDwiImageFilter< short >::New();
m_ArtifactsToDwiFilter->SetInput(diffImg->GetVectorImage());
parameters.m_ParentNode = imageNode;
m_ArtifactsToDwiFilter->SetParameters(parameters);
m_Worker.m_FilterType = 1;
m_Thread.start(QThread::LowestPriority);
}
void QmitkFiberfoxView::SimulateImageFromFibers(mitk::DataNode* fiberNode)
{
mitk::FiberBundleX::Pointer fiberBundle = dynamic_cast<mitk::FiberBundleX*>(fiberNode->GetData());
if (fiberBundle->GetNumFibers()<=0)
return;
FiberfoxParameters<double> parameters = UpdateImageParameters<double>();
m_TractsToDwiFilter = itk::TractsToDWIImageFilter< short >::New();
parameters.m_ParentNode = fiberNode;
m_TractsToDwiFilter->SetParameters(parameters);
m_TractsToDwiFilter->SetFiberBundle(fiberBundle);
m_Worker.m_FilterType = 0;
m_Thread.start(QThread::LowestPriority);
}
void QmitkFiberfoxView::ApplyTransform()
{
vector< mitk::DataNode::Pointer > selectedBundles;
for(unsigned int i=0; i<m_SelectedImages.size(); i++ )
{
mitk::DataStorage::SetOfObjects::ConstPointer derivations = GetDataStorage()->GetDerivations(m_SelectedImages.at(i));
for( mitk::DataStorage::SetOfObjects::const_iterator it = derivations->begin(); it != derivations->end(); ++it )
{
mitk::DataNode::Pointer fibNode = *it;
if ( fibNode.IsNotNull() && dynamic_cast<mitk::FiberBundleX*>(fibNode->GetData()) )
selectedBundles.push_back(fibNode);
}
}
if (selectedBundles.empty())
selectedBundles = m_SelectedBundles2;
if (!selectedBundles.empty())
{
for (std::vector<mitk::DataNode::Pointer>::const_iterator it = selectedBundles.begin(); it!=selectedBundles.end(); ++it)
{
mitk::FiberBundleX::Pointer fib = dynamic_cast<mitk::FiberBundleX*>((*it)->GetData());
fib->RotateAroundAxis(m_Controls->m_XrotBox->value(), m_Controls->m_YrotBox->value(), m_Controls->m_ZrotBox->value());
fib->TranslateFibers(m_Controls->m_XtransBox->value(), m_Controls->m_YtransBox->value(), m_Controls->m_ZtransBox->value());
fib->ScaleFibers(m_Controls->m_XscaleBox->value(), m_Controls->m_YscaleBox->value(), m_Controls->m_ZscaleBox->value());
// handle child fiducials
if (m_Controls->m_IncludeFiducials->isChecked())
{
mitk::DataStorage::SetOfObjects::ConstPointer derivations = GetDataStorage()->GetDerivations(*it);
for( mitk::DataStorage::SetOfObjects::const_iterator it2 = derivations->begin(); it2 != derivations->end(); ++it2 )
{
mitk::DataNode::Pointer fiducialNode = *it2;
if ( fiducialNode.IsNotNull() && dynamic_cast<mitk::PlanarEllipse*>(fiducialNode->GetData()) )
{
mitk::PlanarEllipse* pe = dynamic_cast<mitk::PlanarEllipse*>(fiducialNode->GetData());
- mitk::Geometry3D* geom = pe->GetGeometry();
+ mitk::BaseGeometry* geom = pe->GetGeometry();
// translate
mitk::Vector3D world;
world[0] = m_Controls->m_XtransBox->value();
world[1] = m_Controls->m_YtransBox->value();
world[2] = m_Controls->m_ZtransBox->value();
geom->Translate(world);
// calculate rotation matrix
double x = m_Controls->m_XrotBox->value()*M_PI/180;
double y = m_Controls->m_YrotBox->value()*M_PI/180;
double z = m_Controls->m_ZrotBox->value()*M_PI/180;
itk::Matrix< double, 3, 3 > rotX; rotX.SetIdentity();
rotX[1][1] = cos(x);
rotX[2][2] = rotX[1][1];
rotX[1][2] = -sin(x);
rotX[2][1] = -rotX[1][2];
itk::Matrix< double, 3, 3 > rotY; rotY.SetIdentity();
rotY[0][0] = cos(y);
rotY[2][2] = rotY[0][0];
rotY[0][2] = sin(y);
rotY[2][0] = -rotY[0][2];
itk::Matrix< double, 3, 3 > rotZ; rotZ.SetIdentity();
rotZ[0][0] = cos(z);
rotZ[1][1] = rotZ[0][0];
rotZ[0][1] = -sin(z);
rotZ[1][0] = -rotZ[0][1];
itk::Matrix< double, 3, 3 > rot = rotZ*rotY*rotX;
// transform control point coordinate into geometry translation
geom->SetOrigin(pe->GetWorldControlPoint(0));
mitk::Point2D cp; cp.Fill(0.0);
pe->SetControlPoint(0, cp);
// rotate fiducial
geom->GetIndexToWorldTransform()->SetMatrix(rot*geom->GetIndexToWorldTransform()->GetMatrix());
// implicit translation
mitk::Vector3D trans;
trans[0] = geom->GetOrigin()[0]-fib->GetGeometry()->GetCenter()[0];
trans[1] = geom->GetOrigin()[1]-fib->GetGeometry()->GetCenter()[1];
trans[2] = geom->GetOrigin()[2]-fib->GetGeometry()->GetCenter()[2];
mitk::Vector3D newWc = rot*trans;
newWc = newWc-trans;
geom->Translate(newWc);
pe->Modified();
}
}
}
}
}
else
{
for (unsigned int i=0; i<m_SelectedFiducials.size(); i++)
{
mitk::PlanarEllipse* pe = dynamic_cast<mitk::PlanarEllipse*>(m_SelectedFiducials.at(i)->GetData());
- mitk::Geometry3D* geom = pe->GetGeometry();
+ mitk::BaseGeometry* geom = pe->GetGeometry();
// translate
mitk::Vector3D world;
world[0] = m_Controls->m_XtransBox->value();
world[1] = m_Controls->m_YtransBox->value();
world[2] = m_Controls->m_ZtransBox->value();
geom->Translate(world);
// calculate rotation matrix
double x = m_Controls->m_XrotBox->value()*M_PI/180;
double y = m_Controls->m_YrotBox->value()*M_PI/180;
double z = m_Controls->m_ZrotBox->value()*M_PI/180;
itk::Matrix< double, 3, 3 > rotX; rotX.SetIdentity();
rotX[1][1] = cos(x);
rotX[2][2] = rotX[1][1];
rotX[1][2] = -sin(x);
rotX[2][1] = -rotX[1][2];
itk::Matrix< double, 3, 3 > rotY; rotY.SetIdentity();
rotY[0][0] = cos(y);
rotY[2][2] = rotY[0][0];
rotY[0][2] = sin(y);
rotY[2][0] = -rotY[0][2];
itk::Matrix< double, 3, 3 > rotZ; rotZ.SetIdentity();
rotZ[0][0] = cos(z);
rotZ[1][1] = rotZ[0][0];
rotZ[0][1] = -sin(z);
rotZ[1][0] = -rotZ[0][1];
itk::Matrix< double, 3, 3 > rot = rotZ*rotY*rotX;
// transform control point coordinate into geometry translation
geom->SetOrigin(pe->GetWorldControlPoint(0));
mitk::Point2D cp; cp.Fill(0.0);
pe->SetControlPoint(0, cp);
// rotate fiducial
geom->GetIndexToWorldTransform()->SetMatrix(rot*geom->GetIndexToWorldTransform()->GetMatrix());
pe->Modified();
}
if (m_Controls->m_RealTimeFibers->isChecked())
GenerateFibers();
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkFiberfoxView::CopyBundles()
{
if ( m_SelectedBundles.size()<1 ){
QMessageBox::information( NULL, "Warning", "Select at least one fiber bundle!");
MITK_WARN("QmitkFiberProcessingView") << "Select at least one fiber bundle!";
return;
}
for (std::vector<mitk::DataNode::Pointer>::const_iterator it = m_SelectedBundles.begin(); it!=m_SelectedBundles.end(); ++it)
{
// find parent image
mitk::DataNode::Pointer parentNode;
mitk::DataStorage::SetOfObjects::ConstPointer parentImgs = GetDataStorage()->GetSources(*it);
for( mitk::DataStorage::SetOfObjects::const_iterator it2 = parentImgs->begin(); it2 != parentImgs->end(); ++it2 )
{
mitk::DataNode::Pointer pImgNode = *it2;
if ( pImgNode.IsNotNull() && dynamic_cast<mitk::Image*>(pImgNode->GetData()) )
{
parentNode = pImgNode;
break;
}
}
mitk::FiberBundleX::Pointer fib = dynamic_cast<mitk::FiberBundleX*>((*it)->GetData());
mitk::FiberBundleX::Pointer newBundle = fib->GetDeepCopy();
QString name((*it)->GetName().c_str());
name += "_copy";
mitk::DataNode::Pointer fbNode = mitk::DataNode::New();
fbNode->SetData(newBundle);
fbNode->SetName(name.toStdString());
fbNode->SetVisibility(true);
if (parentNode.IsNotNull())
GetDataStorage()->Add(fbNode, parentNode);
else
GetDataStorage()->Add(fbNode);
// copy child fiducials
if (m_Controls->m_IncludeFiducials->isChecked())
{
mitk::DataStorage::SetOfObjects::ConstPointer derivations = GetDataStorage()->GetDerivations(*it);
for( mitk::DataStorage::SetOfObjects::const_iterator it2 = derivations->begin(); it2 != derivations->end(); ++it2 )
{
mitk::DataNode::Pointer fiducialNode = *it2;
if ( fiducialNode.IsNotNull() && dynamic_cast<mitk::PlanarEllipse*>(fiducialNode->GetData()) )
{
mitk::PlanarEllipse::Pointer pe = mitk::PlanarEllipse::New();
pe->DeepCopy(dynamic_cast<mitk::PlanarEllipse*>(fiducialNode->GetData()));
mitk::DataNode::Pointer newNode = mitk::DataNode::New();
newNode->SetData(pe);
newNode->SetName(fiducialNode->GetName());
newNode->SetBoolProperty("planarfigure.3drendering", true);
GetDataStorage()->Add(newNode, fbNode);
}
}
}
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkFiberfoxView::JoinBundles()
{
if ( m_SelectedBundles.size()<2 ){
QMessageBox::information( NULL, "Warning", "Select at least two fiber bundles!");
MITK_WARN("QmitkFiberProcessingView") << "Select at least two fiber bundles!";
return;
}
std::vector<mitk::DataNode::Pointer>::const_iterator it = m_SelectedBundles.begin();
mitk::FiberBundleX::Pointer newBundle = dynamic_cast<mitk::FiberBundleX*>((*it)->GetData());
QString name("");
name += QString((*it)->GetName().c_str());
++it;
for (; it!=m_SelectedBundles.end(); ++it)
{
newBundle = newBundle->AddBundle(dynamic_cast<mitk::FiberBundleX*>((*it)->GetData()));
name += "+"+QString((*it)->GetName().c_str());
}
mitk::DataNode::Pointer fbNode = mitk::DataNode::New();
fbNode->SetData(newBundle);
fbNode->SetName(name.toStdString());
fbNode->SetVisibility(true);
GetDataStorage()->Add(fbNode);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkFiberfoxView::UpdateGui()
{
m_Controls->m_FiberBundleLabel->setText("<font color='red'>mandatory</font>");
m_Controls->m_GeometryFrame->setEnabled(true);
m_Controls->m_GeometryMessage->setVisible(false);
m_Controls->m_DiffusionPropsMessage->setVisible(false);
m_Controls->m_FiberGenMessage->setVisible(true);
m_Controls->m_TransformBundlesButton->setEnabled(false);
m_Controls->m_CopyBundlesButton->setEnabled(false);
m_Controls->m_GenerateFibersButton->setEnabled(false);
m_Controls->m_FlipButton->setEnabled(false);
m_Controls->m_CircleButton->setEnabled(false);
m_Controls->m_BvalueBox->setEnabled(true);
m_Controls->m_NumGradientsBox->setEnabled(true);
m_Controls->m_JoinBundlesButton->setEnabled(false);
m_Controls->m_AlignOnGrid->setEnabled(false);
if (m_SelectedFiducial.IsNotNull())
{
m_Controls->m_TransformBundlesButton->setEnabled(true);
m_Controls->m_FlipButton->setEnabled(true);
m_Controls->m_AlignOnGrid->setEnabled(true);
}
if (m_SelectedImage.IsNotNull() || !m_SelectedBundles.empty())
{
m_Controls->m_TransformBundlesButton->setEnabled(true);
m_Controls->m_CircleButton->setEnabled(true);
m_Controls->m_FiberGenMessage->setVisible(false);
m_Controls->m_AlignOnGrid->setEnabled(true);
}
if (m_MaskImageNode.IsNotNull() || m_SelectedImage.IsNotNull())
{
m_Controls->m_GeometryMessage->setVisible(true);
m_Controls->m_GeometryFrame->setEnabled(false);
}
if (m_SelectedDWI.IsNotNull())
{
m_Controls->m_DiffusionPropsMessage->setVisible(true);
m_Controls->m_BvalueBox->setEnabled(false);
m_Controls->m_NumGradientsBox->setEnabled(false);
m_Controls->m_GeometryMessage->setVisible(true);
m_Controls->m_GeometryFrame->setEnabled(false);
}
if (!m_SelectedBundles.empty())
{
m_Controls->m_CopyBundlesButton->setEnabled(true);
m_Controls->m_GenerateFibersButton->setEnabled(true);
m_Controls->m_FiberBundleLabel->setText(m_SelectedBundles.at(0)->GetName().c_str());
if (m_SelectedBundles.size()>1)
m_Controls->m_JoinBundlesButton->setEnabled(true);
}
}
void QmitkFiberfoxView::OnSelectionChanged( berry::IWorkbenchPart::Pointer, const QList<mitk::DataNode::Pointer>& nodes )
{
m_SelectedBundles2.clear();
m_SelectedImages.clear();
m_SelectedFiducials.clear();
m_SelectedFiducial = NULL;
m_SelectedBundles.clear();
m_SelectedImage = NULL;
m_SelectedDWI = NULL;
m_MaskImageNode = NULL;
m_Controls->m_TissueMaskLabel->setText("<font color='grey'>optional</font>");
// iterate all selected objects, adjust warning visibility
for( int i=0; i<nodes.size(); i++)
{
mitk::DataNode::Pointer node = nodes.at(i);
if ( node.IsNotNull() && dynamic_cast<mitk::DiffusionImage<short>*>(node->GetData()) )
{
m_SelectedDWI = node;
m_SelectedImage = node;
m_SelectedImages.push_back(node);
}
else if( node.IsNotNull() && dynamic_cast<mitk::Image*>(node->GetData()) )
{
m_SelectedImages.push_back(node);
m_SelectedImage = node;
bool isbinary = false;
node->GetPropertyValue<bool>("binary", isbinary);
if (isbinary)
{
m_MaskImageNode = node;
m_Controls->m_TissueMaskLabel->setText(m_MaskImageNode->GetName().c_str());
}
}
else if ( node.IsNotNull() && dynamic_cast<mitk::FiberBundleX*>(node->GetData()) )
{
m_SelectedBundles2.push_back(node);
if (m_Controls->m_RealTimeFibers->isChecked())
{
m_SelectedBundles.push_back(node);
mitk::FiberBundleX::Pointer newFib = dynamic_cast<mitk::FiberBundleX*>(node->GetData());
if (newFib->GetNumFibers()!=m_Controls->m_FiberDensityBox->value())
GenerateFibers();
}
else
m_SelectedBundles.push_back(node);
}
else if ( node.IsNotNull() && dynamic_cast<mitk::PlanarEllipse*>(node->GetData()) )
{
m_SelectedFiducials.push_back(node);
m_SelectedFiducial = node;
m_SelectedBundles.clear();
mitk::DataStorage::SetOfObjects::ConstPointer parents = GetDataStorage()->GetSources(node);
for( mitk::DataStorage::SetOfObjects::const_iterator it = parents->begin(); it != parents->end(); ++it )
{
mitk::DataNode::Pointer pNode = *it;
if ( pNode.IsNotNull() && dynamic_cast<mitk::FiberBundleX*>(pNode->GetData()) )
m_SelectedBundles.push_back(pNode);
}
}
}
UpdateGui();
}
void QmitkFiberfoxView::EnableCrosshairNavigation()
{
MITK_DEBUG << "EnableCrosshairNavigation";
// enable the crosshair navigation
if (mitk::ILinkedRenderWindowPart* linkedRenderWindow =
dynamic_cast<mitk::ILinkedRenderWindowPart*>(this->GetRenderWindowPart()))
{
MITK_DEBUG << "enabling linked navigation";
linkedRenderWindow->EnableLinkedNavigation(true);
// linkedRenderWindow->EnableSlicingPlanes(true);
}
if (m_Controls->m_RealTimeFibers->isChecked())
GenerateFibers();
}
void QmitkFiberfoxView::DisableCrosshairNavigation()
{
MITK_DEBUG << "DisableCrosshairNavigation";
// disable the crosshair navigation during the drawing
if (mitk::ILinkedRenderWindowPart* linkedRenderWindow =
dynamic_cast<mitk::ILinkedRenderWindowPart*>(this->GetRenderWindowPart()))
{
MITK_DEBUG << "disabling linked navigation";
linkedRenderWindow->EnableLinkedNavigation(false);
// linkedRenderWindow->EnableSlicingPlanes(false);
}
}
void QmitkFiberfoxView::NodeRemoved(const mitk::DataNode* node)
{
mitk::DataNode* nonConstNode = const_cast<mitk::DataNode*>(node);
std::map<mitk::DataNode*, QmitkPlanarFigureData>::iterator it = m_DataNodeToPlanarFigureData.find(nonConstNode);
if (dynamic_cast<FiberBundleX*>(node->GetData()))
{
m_SelectedBundles.clear();
m_SelectedBundles2.clear();
}
else if (dynamic_cast<Image*>(node->GetData()))
m_SelectedImages.clear();
if( it != m_DataNodeToPlanarFigureData.end() )
{
QmitkPlanarFigureData& data = it->second;
// remove observers
data.m_Figure->RemoveObserver( data.m_EndPlacementObserverTag );
data.m_Figure->RemoveObserver( data.m_SelectObserverTag );
data.m_Figure->RemoveObserver( data.m_StartInteractionObserverTag );
data.m_Figure->RemoveObserver( data.m_EndInteractionObserverTag );
m_DataNodeToPlanarFigureData.erase( it );
}
}
void QmitkFiberfoxView::NodeAdded( const mitk::DataNode* node )
{
// add observer for selection in renderwindow
mitk::PlanarFigure* figure = dynamic_cast<mitk::PlanarFigure*>(node->GetData());
bool isPositionMarker (false);
node->GetBoolProperty("isContourMarker", isPositionMarker);
if( figure && !isPositionMarker )
{
MITK_DEBUG << "figure added. will add interactor if needed.";
mitk::PlanarFigureInteractor::Pointer figureInteractor
= dynamic_cast<mitk::PlanarFigureInteractor*>(node->GetDataInteractor().GetPointer());
mitk::DataNode* nonConstNode = const_cast<mitk::DataNode*>( node );
if(figureInteractor.IsNull())
{
figureInteractor = mitk::PlanarFigureInteractor::New();
us::Module* planarFigureModule = us::ModuleRegistry::GetModule( "MitkPlanarFigure" );
figureInteractor->LoadStateMachine("PlanarFigureInteraction.xml", planarFigureModule );
figureInteractor->SetEventConfig( "PlanarFigureConfig.xml", planarFigureModule );
figureInteractor->SetDataNode( nonConstNode );
}
MITK_DEBUG << "will now add observers for planarfigure";
QmitkPlanarFigureData data;
data.m_Figure = figure;
// // add observer for event when figure has been placed
typedef itk::SimpleMemberCommand< QmitkFiberfoxView > SimpleCommandType;
// SimpleCommandType::Pointer initializationCommand = SimpleCommandType::New();
// initializationCommand->SetCallbackFunction( this, &QmitkFiberfoxView::PlanarFigureInitialized );
// data.m_EndPlacementObserverTag = figure->AddObserver( mitk::EndPlacementPlanarFigureEvent(), initializationCommand );
// add observer for event when figure is picked (selected)
typedef itk::MemberCommand< QmitkFiberfoxView > MemberCommandType;
MemberCommandType::Pointer selectCommand = MemberCommandType::New();
selectCommand->SetCallbackFunction( this, &QmitkFiberfoxView::PlanarFigureSelected );
data.m_SelectObserverTag = figure->AddObserver( mitk::SelectPlanarFigureEvent(), selectCommand );
// add observer for event when interaction with figure starts
SimpleCommandType::Pointer startInteractionCommand = SimpleCommandType::New();
startInteractionCommand->SetCallbackFunction( this, &QmitkFiberfoxView::DisableCrosshairNavigation);
data.m_StartInteractionObserverTag = figure->AddObserver( mitk::StartInteractionPlanarFigureEvent(), startInteractionCommand );
// add observer for event when interaction with figure starts
SimpleCommandType::Pointer endInteractionCommand = SimpleCommandType::New();
endInteractionCommand->SetCallbackFunction( this, &QmitkFiberfoxView::EnableCrosshairNavigation);
data.m_EndInteractionObserverTag = figure->AddObserver( mitk::EndInteractionPlanarFigureEvent(), endInteractionCommand );
m_DataNodeToPlanarFigureData[nonConstNode] = data;
}
}
void QmitkFiberfoxView::PlanarFigureSelected( itk::Object* object, const itk::EventObject& )
{
mitk::TNodePredicateDataType<mitk::PlanarFigure>::Pointer isPf = mitk::TNodePredicateDataType<mitk::PlanarFigure>::New();
mitk::DataStorage::SetOfObjects::ConstPointer allPfs = this->GetDataStorage()->GetSubset( isPf );
for ( mitk::DataStorage::SetOfObjects::const_iterator it = allPfs->begin(); it!=allPfs->end(); ++it)
{
mitk::DataNode* node = *it;
if( node->GetData() == object )
{
node->SetSelected(true);
m_SelectedFiducial = node;
}
else
node->SetSelected(false);
}
UpdateGui();
this->RequestRenderWindowUpdate();
}
void QmitkFiberfoxView::SetFocus()
{
m_Controls->m_CircleButton->setFocus();
}
void QmitkFiberfoxView::SetOutputPath()
{
// SELECT FOLDER DIALOG
string outputPath = QFileDialog::getExistingDirectory(NULL, "Save images to...", QString(outputPath.c_str())).toStdString();
if (outputPath.empty())
m_Controls->m_SavePathEdit->setText("-");
else
{
outputPath += "/";
m_Controls->m_SavePathEdit->setText(QString(outputPath.c_str()));
}
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFieldmapGeneratorView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFieldmapGeneratorView.cpp
index 0632133f09..36cc39d848 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFieldmapGeneratorView.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFieldmapGeneratorView.cpp
@@ -1,299 +1,299 @@
/*===================================================================
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.
===================================================================*/
// Blueberry
#include <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>
// MITK
#include "QmitkFieldmapGeneratorView.h"
#include <QmitkStdMultiWidget.h>
#include <QmitkDataStorageComboBox.h>
#include <mitkNodePredicateDataType.h>
#include <itkFieldmapGeneratorFilter.h>
#include <mitkImage.h>
const std::string QmitkFieldmapGeneratorView::VIEW_ID = "org.mitk.views.fieldmapgenerator";
QmitkFieldmapGeneratorView::QmitkFieldmapGeneratorView()
: QmitkFunctionality()
, m_Controls( 0 )
, m_MultiWidget( NULL )
{
}
QmitkFieldmapGeneratorView::~QmitkFieldmapGeneratorView()
{
}
void QmitkFieldmapGeneratorView::CreateQtPartControl( QWidget *parent )
{
// build up qt view, unless already done
if ( !m_Controls )
{
// create GUI widgets from the Qt Designer's .ui file
m_Controls = new Ui::QmitkFieldmapGeneratorViewControls;
m_Controls->setupUi( parent );
m_Controls->m_SelectedImageBox->SetDataStorage(this->GetDataStorage());
mitk::TNodePredicateDataType<mitk::Image>::Pointer isMitkImage = mitk::TNodePredicateDataType<mitk::Image>::New();
m_Controls->m_SelectedImageBox->SetPredicate(isMitkImage);
connect((QObject*) m_Controls->m_GenerateFieldmap, SIGNAL(clicked()), (QObject*) this, SLOT(GenerateFieldmap()));
connect((QObject*) m_Controls->m_PlaceFieldSource, SIGNAL(clicked()), (QObject*) this, SLOT(PlaceFieldSource()));
connect((QObject*) m_Controls->m_SourceVarianceBox, SIGNAL(valueChanged(double)), (QObject*) this, SLOT(OnVarianceChanged(double)));
connect((QObject*) m_Controls->m_SourceHeightBox, SIGNAL(valueChanged(double)), (QObject*) this, SLOT(OnHeightChanged(double)));
}
}
void QmitkFieldmapGeneratorView::OnVarianceChanged(double value)
{
if (m_SelectedSource.IsNotNull())
{
m_SelectedSource->SetProperty("pointsize", mitk::FloatProperty::New(value));
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
void QmitkFieldmapGeneratorView::OnHeightChanged(double value)
{
if (m_SelectedSource.IsNotNull())
{
m_SelectedSource->SetProperty("color", mitk::ColorProperty::New(0, 0, value/100.0));
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
void QmitkFieldmapGeneratorView::PlaceFieldSource()
{
if (m_Controls->m_SelectedImageBox->GetSelectedNode().IsNull() || !m_MultiWidget)
{
m_Controls->m_WorldPosLabel->setText("-");
m_Controls->m_IndexLabel->setText("-");
return;
}
mitk::Point3D index;
mitk::Image::Pointer img = dynamic_cast<mitk::Image*>(m_Controls->m_SelectedImageBox->GetSelectedNode()->GetData());
- mitk::Geometry3D* geom = img->GetGeometry();
+ mitk::BaseGeometry* geom = img->GetGeometry();
if ( geom->IsInside(m_WorldPoint) )
{
img->GetGeometry()->WorldToIndex(m_WorldPoint, index);
mitk::PointSet::Pointer pointSet = mitk::PointSet::New();
pointSet->InsertPoint(0, m_WorldPoint);
mitk::DataStorage::SetOfObjects::ConstPointer children = GetDataStorage()->GetDerivations(m_Controls->m_SelectedImageBox->GetSelectedNode());
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData(pointSet);
QString name = QString("FieldSource_%1").arg(children->size());
node->SetName(name.toStdString());
node->SetVisibility(true);
float minSpacing;
if(geom->GetSpacing()[0]<geom->GetSpacing()[1] && geom->GetSpacing()[0]<geom->GetSpacing()[2])
minSpacing = geom->GetSpacing()[0];
else if (geom->GetSpacing()[1] < geom->GetSpacing()[2])
minSpacing = geom->GetSpacing()[1];
else
minSpacing = geom->GetSpacing()[2];
node->SetProperty("pointsize", mitk::FloatProperty::New(minSpacing*5));
node->SetProperty("color", mitk::ColorProperty::New(0, 0, 1));
GetDataStorage()->Add(node, m_Controls->m_SelectedImageBox->GetSelectedNode());
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
void QmitkFieldmapGeneratorView::GenerateFieldmap()
{
if (m_Controls->m_SelectedImageBox->GetSelectedNode().IsNull())
return;
mitk::Image::Pointer img = dynamic_cast<mitk::Image*>(m_Controls->m_SelectedImageBox->GetSelectedNode()->GetData());
- mitk::Geometry3D* geom = img->GetGeometry();
+ mitk::BaseGeometry* geom = img->GetGeometry();
typedef itk::Image< double, 3 > FieldMapType;
itk::Vector<double> spacing; ///< output image spacing
mitk::Point3D origin; ///< output image origin
itk::FieldmapGeneratorFilter< FieldMapType >::MatrixType directionMatrix; ///< output image rotation
itk::FieldmapGeneratorFilter< FieldMapType >::OutputImageRegionType imageRegion; ///< output image size
spacing = geom->GetSpacing();
origin = geom->GetOrigin();
imageRegion.SetSize(0, img->GetDimension(0));
imageRegion.SetSize(1, img->GetDimension(1));
imageRegion.SetSize(2, img->GetDimension(2));
for (int r=0; r<3; r++)
for (int c=0; c<3; c++)
directionMatrix[r][c]=geom->GetMatrixColumn(c)[r]/spacing[c];
std::vector< double > variances;
std::vector< double > heights;
std::vector< mitk::Point3D > worldPositions;
mitk::DataStorage::SetOfObjects::ConstPointer children = GetDataStorage()->GetDerivations(m_Controls->m_SelectedImageBox->GetSelectedNode());
for( mitk::DataStorage::SetOfObjects::const_iterator it = children->begin(); it != children->end(); ++it )
if(dynamic_cast<mitk::PointSet*>((*it)->GetData()))
{
float var = 0; (*it)->GetPropertyValue("pointsize", var); variances.push_back(var);
float color[3]; (*it)->GetColor(color); heights.push_back(color[2]*100);
mitk::PointSet* ps = dynamic_cast<mitk::PointSet*>((*it)->GetData());
mitk::Point3D point;
ps->GetPointIfExists(0, &point);
worldPositions.push_back(point);
}
vnl_vector_fixed< double, 3 > gradient, offset;
gradient[0] = m_Controls->m_xGradientBox->value();
gradient[1] = m_Controls->m_yGradientBox->value();
gradient[2] = m_Controls->m_zGradientBox->value();
offset[0] = m_Controls->m_xOffsetBox->value();
offset[1] = m_Controls->m_yOffsetBox->value();
offset[2] = m_Controls->m_zOffsetBox->value();
itk::FieldmapGeneratorFilter< FieldMapType >::Pointer filter = itk::FieldmapGeneratorFilter< FieldMapType >::New();
filter->SetHeights(heights);
filter->SetVariances(variances);
filter->SetWorldPositions(worldPositions);
filter->SetSpacing(spacing);
filter->SetOrigin(origin);
filter->SetDirectionMatrix(directionMatrix);
filter->SetImageRegion(imageRegion);
filter->SetGradient(gradient);
filter->SetOffset(offset);
filter->Update();
mitk::DataNode::Pointer resultNode = mitk::DataNode::New();
mitk::Image::Pointer image = mitk::Image::New();
image->InitializeByItk(filter->GetOutput(0));
image->SetVolume(filter->GetOutput(0)->GetBufferPointer());
resultNode->SetData( image );
resultNode->SetName(m_Controls->m_SelectedImageBox->GetSelectedNode()->GetName()+"_Fieldmap");
GetDataStorage()->Add(resultNode);
}
void QmitkFieldmapGeneratorView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget)
{
m_MultiWidget = &stdMultiWidget;
{
mitk::SliceNavigationController* slicer = m_MultiWidget->mitkWidget1->GetSliceNavigationController();
itk::ReceptorMemberCommand<QmitkFieldmapGeneratorView>::Pointer command = itk::ReceptorMemberCommand<QmitkFieldmapGeneratorView>::New();
command->SetCallbackFunction( this, &QmitkFieldmapGeneratorView::OnSliceChanged );
m_SliceObserverTag1 = slicer->AddObserver( mitk::SliceNavigationController::GeometrySliceEvent(NULL, 0), command );
}
{
mitk::SliceNavigationController* slicer = m_MultiWidget->mitkWidget2->GetSliceNavigationController();
itk::ReceptorMemberCommand<QmitkFieldmapGeneratorView>::Pointer command = itk::ReceptorMemberCommand<QmitkFieldmapGeneratorView>::New();
command->SetCallbackFunction( this, &QmitkFieldmapGeneratorView::OnSliceChanged );
m_SliceObserverTag2 = slicer->AddObserver( mitk::SliceNavigationController::GeometrySliceEvent(NULL, 0), command );
}
{
mitk::SliceNavigationController* slicer = m_MultiWidget->mitkWidget3->GetSliceNavigationController();
itk::ReceptorMemberCommand<QmitkFieldmapGeneratorView>::Pointer command = itk::ReceptorMemberCommand<QmitkFieldmapGeneratorView>::New();
command->SetCallbackFunction( this, &QmitkFieldmapGeneratorView::OnSliceChanged );
m_SliceObserverTag3 = slicer->AddObserver( mitk::SliceNavigationController::GeometrySliceEvent(NULL, 0), command );
}
}
void QmitkFieldmapGeneratorView::StdMultiWidgetNotAvailable()
{
{
mitk::SliceNavigationController* slicer = m_MultiWidget->mitkWidget1->GetSliceNavigationController();
slicer->RemoveObserver( m_SliceObserverTag1 );
}
{
mitk::SliceNavigationController* slicer = m_MultiWidget->mitkWidget2->GetSliceNavigationController();
slicer->RemoveObserver( m_SliceObserverTag2 );
}
{
mitk::SliceNavigationController* slicer = m_MultiWidget->mitkWidget3->GetSliceNavigationController();
slicer->RemoveObserver( m_SliceObserverTag3 );
}
m_MultiWidget = NULL;
}
void QmitkFieldmapGeneratorView::OnSelectionChanged( std::vector<mitk::DataNode*> nodes )
{
if (m_Controls->m_SelectedImageBox->GetSelectedNode().IsNotNull())
m_Controls->m_SelectedImageBox->GetSelectedNode()->RemoveObserver( m_PropertyObserverTag );
m_Controls->m_InputData->setTitle("Please Select Reference Image");
m_SelectedSource = NULL;
// iterate selection
for( std::vector<mitk::DataNode*>::iterator it = nodes.begin(); it != nodes.end(); ++it )
{
mitk::DataNode::Pointer node = *it;
if ( node.IsNotNull() && (dynamic_cast<mitk::PointSet*>(node->GetData())) )
{
m_Controls->m_SourceNameLabel->setText(node->GetName().c_str());
m_SelectedSource = node;
float variance = 0; node->GetPropertyValue("pointsize", variance);
m_Controls->m_SourceVarianceBox->setValue(variance);
float color[3]; node->GetColor(color);
m_Controls->m_SourceHeightBox->setValue(color[2]*100);
}
}
if (m_Controls->m_SelectedImageBox->GetSelectedNode().IsNotNull())
{
itk::ReceptorMemberCommand<QmitkFieldmapGeneratorView>::Pointer command = itk::ReceptorMemberCommand<QmitkFieldmapGeneratorView>::New();
command->SetCallbackFunction( this, &QmitkFieldmapGeneratorView::OnSliceChanged );
m_PropertyObserverTag = m_Controls->m_SelectedImageBox->GetSelectedNode()->AddObserver( itk::ModifiedEvent(), command );
m_Controls->m_InputData->setTitle("Reference Image");
}
}
void QmitkFieldmapGeneratorView::OnSliceChanged(const itk::EventObject& /*e*/)
{
if (m_Controls->m_SelectedImageBox->GetSelectedNode().IsNull() || !m_MultiWidget)
{
m_Controls->m_WorldPosLabel->setText("-");
m_Controls->m_IndexLabel->setText("-");
return;
}
m_WorldPoint = m_MultiWidget->GetCrossPosition();
QString posSting = QString::number(m_WorldPoint[0]); posSting += ", "; posSting += QString::number(m_WorldPoint[1]); posSting += ", "; posSting += QString::number(m_WorldPoint[2]);
m_Controls->m_WorldPosLabel->setText(posSting.toStdString().c_str());
mitk::Point3D index;
mitk::Image::Pointer img = dynamic_cast<mitk::Image*>(m_Controls->m_SelectedImageBox->GetSelectedNode()->GetData());
if ( m_Controls->m_SelectedImageBox->GetSelectedNode()->GetData()->GetGeometry()->IsInside(m_WorldPoint) )
{
img->GetGeometry()->WorldToIndex(m_WorldPoint, index);
posSting = QString::number(index[0]); posSting += ", "; posSting += QString::number(index[1]); posSting += ", "; posSting += QString::number(index[2]);
m_Controls->m_IndexLabel->setText(posSting.toStdString().c_str());
}
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkOdfMaximaExtractionView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkOdfMaximaExtractionView.cpp
index e1ba64bee3..e39be65d67 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkOdfMaximaExtractionView.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkOdfMaximaExtractionView.cpp
@@ -1,779 +1,779 @@
/*===================================================================
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.
===================================================================*/
//misc
#define _USE_MATH_DEFINES
#include <math.h>
#include <QFileDialog>
// Blueberry
#include <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>
// Qmitk
#include "QmitkOdfMaximaExtractionView.h"
// MITK
#include <mitkImageCast.h>
#include <mitkFiberBundleX.h>
#include <mitkImage.h>
#include <mitkDiffusionImage.h>
#include <mitkImageToItk.h>
#include <mitkTensorImage.h>
// ITK
#include <itkVectorImage.h>
#include <itkOdfMaximaExtractionFilter.h>
#include <itkFiniteDiffOdfMaximaExtractionFilter.h>
#include <itkMrtrixPeakImageConverter.h>
#include <itkFslPeakImageConverter.h>
#include <itkShCoefficientImageImporter.h>
#include <itkDiffusionTensorPrincipalDirectionImageFilter.h>
// Qt
#include <QMessageBox>
const std::string QmitkOdfMaximaExtractionView::VIEW_ID = "org.mitk.views.odfmaximaextractionview";
using namespace mitk;
QmitkOdfMaximaExtractionView::QmitkOdfMaximaExtractionView()
: QmitkFunctionality()
, m_Controls( 0 )
, m_MultiWidget( NULL )
{
}
// Destructor
QmitkOdfMaximaExtractionView::~QmitkOdfMaximaExtractionView()
{
}
void QmitkOdfMaximaExtractionView::CreateQtPartControl( QWidget *parent )
{
// build up qt view, unless already done
if ( !m_Controls )
{
// create GUI widgets from the Qt Designer's .ui file
m_Controls = new Ui::QmitkOdfMaximaExtractionViewControls;
m_Controls->setupUi( parent );
connect((QObject*) m_Controls->m_StartTensor, SIGNAL(clicked()), (QObject*) this, SLOT(StartTensor()));
connect((QObject*) m_Controls->m_StartFiniteDiff, SIGNAL(clicked()), (QObject*) this, SLOT(StartFiniteDiff()));
connect((QObject*) m_Controls->m_GenerateImageButton, SIGNAL(clicked()), (QObject*) this, SLOT(GenerateImage()));
connect((QObject*) m_Controls->m_ImportPeaks, SIGNAL(clicked()), (QObject*) this, SLOT(ConvertPeaks()));
connect((QObject*) m_Controls->m_ImportShCoeffs, SIGNAL(clicked()), (QObject*) this, SLOT(ConvertShCoeffs()));
}
}
void QmitkOdfMaximaExtractionView::UpdateGui()
{
m_Controls->m_GenerateImageButton->setEnabled(false);
m_Controls->m_StartFiniteDiff->setEnabled(false);
m_Controls->m_StartTensor->setEnabled(false);
m_Controls->m_CoeffImageFrame->setEnabled(false);
if (!m_ImageNodes.empty() || !m_TensorImageNodes.empty())
{
m_Controls->m_InputData->setTitle("Input Data");
if (!m_TensorImageNodes.empty())
{
m_Controls->m_DwiFibLabel->setText(m_TensorImageNodes.front()->GetName().c_str());
m_Controls->m_StartTensor->setEnabled(true);
}
else
{
m_Controls->m_DwiFibLabel->setText(m_ImageNodes.front()->GetName().c_str());
m_Controls->m_StartFiniteDiff->setEnabled(true);
m_Controls->m_GenerateImageButton->setEnabled(true);
m_Controls->m_CoeffImageFrame->setEnabled(true);
m_Controls->m_ShOrderBox->setEnabled(true);
m_Controls->m_MaxNumPeaksBox->setEnabled(true);
m_Controls->m_PeakThresholdBox->setEnabled(true);
m_Controls->m_AbsoluteThresholdBox->setEnabled(true);
}
}
else
m_Controls->m_DwiFibLabel->setText("<font color='red'>mandatory</font>");
if (m_ImageNodes.empty())
{
m_Controls->m_ImportPeaks->setEnabled(false);
m_Controls->m_ImportShCoeffs->setEnabled(false);
}
else
{
m_Controls->m_ImportPeaks->setEnabled(true);
m_Controls->m_ImportShCoeffs->setEnabled(true);
}
if (!m_BinaryImageNodes.empty())
{
m_Controls->m_MaskLabel->setText(m_BinaryImageNodes.front()->GetName().c_str());
}
else
{
m_Controls->m_MaskLabel->setText("<font color='grey'>optional</font>");
}
}
template<int shOrder>
void QmitkOdfMaximaExtractionView::TemplatedConvertShCoeffs(mitk::Image* mitkImg)
{
typedef itk::ShCoefficientImageImporter< float, shOrder > FilterType;
typedef mitk::ImageToItk< itk::Image< float, 4 > > CasterType;
CasterType::Pointer caster = CasterType::New();
caster->SetInput(mitkImg);
caster->Update();
typename FilterType::Pointer filter = FilterType::New();
switch (m_Controls->m_ToolkitBox->currentIndex())
{
case 0:
filter->SetToolkit(FilterType::FSL);
break;
case 1:
filter->SetToolkit(FilterType::MRTRIX);
break;
default:
filter->SetToolkit(FilterType::FSL);
}
filter->SetInputImage(caster->GetOutput());
filter->GenerateData();
typename FilterType::QballImageType::Pointer itkQbi = filter->GetQballImage();
typename FilterType::CoefficientImageType::Pointer itkCi = filter->GetCoefficientImage();
{
mitk::Image::Pointer img = mitk::Image::New();
img->InitializeByItk( itkCi.GetPointer() );
img->SetVolume( itkCi->GetBufferPointer() );
DataNode::Pointer node = DataNode::New();
node->SetData(img);
node->SetName("_ShCoefficientImage");
node->SetVisibility(false);
GetDataStorage()->Add(node);
}
{
mitk::QBallImage::Pointer img = mitk::QBallImage::New();
img->InitializeByItk( itkQbi.GetPointer() );
img->SetVolume( itkQbi->GetBufferPointer() );
DataNode::Pointer node = DataNode::New();
node->SetData(img);
node->SetName("_QballImage");
GetDataStorage()->Add(node);
}
}
void QmitkOdfMaximaExtractionView::ConvertShCoeffs()
{
if (m_ImageNodes.empty())
return;
mitk::Image::Pointer mitkImg = dynamic_cast<mitk::Image*>(m_ImageNodes.at(0)->GetData());
if (mitkImg->GetDimension()!=4)
{
MITK_INFO << "wrong image type (need 4 dimensions)";
return;
}
int nrCoeffs = mitkImg->GetLargestPossibleRegion().GetSize()[3];
// solve bx² + cx + d = 0 = shOrder² + 2*shOrder + 2-2*neededCoeffs;
int c=3, d=2-2*nrCoeffs;
double D = c*c-4*d;
int shOrder;
if (D>0)
{
shOrder = (-c+sqrt(D))/2.0;
if (shOrder<0)
shOrder = (-c-sqrt(D))/2.0;
}
else if (D==0)
shOrder = -c/2.0;
MITK_INFO << "using SH-order " << shOrder;
switch (shOrder)
{
case 2:
TemplatedConvertShCoeffs<2>(mitkImg);
break;
case 4:
TemplatedConvertShCoeffs<4>(mitkImg);
break;
case 6:
TemplatedConvertShCoeffs<6>(mitkImg);
break;
case 8:
TemplatedConvertShCoeffs<8>(mitkImg);
break;
case 10:
TemplatedConvertShCoeffs<10>(mitkImg);
break;
case 12:
TemplatedConvertShCoeffs<12>(mitkImg);
break;
default:
MITK_INFO << "SH-order " << shOrder << " not supported";
}
}
void QmitkOdfMaximaExtractionView::ConvertPeaks()
{
if (m_ImageNodes.empty())
return;
switch (m_Controls->m_ToolkitBox->currentIndex())
{
case 0:
{
typedef itk::Image< float, 4 > ItkImageType;
typedef itk::FslPeakImageConverter< float > FilterType;
FilterType::Pointer filter = FilterType::New();
FilterType::InputType::Pointer inputVec = FilterType::InputType::New();
- mitk::Geometry3D::Pointer geom;
+ mitk::BaseGeometry::Pointer geom;
for (int i=0; i<m_ImageNodes.size(); i++)
{
mitk::Image::Pointer mitkImg = dynamic_cast<mitk::Image*>(m_ImageNodes.at(i)->GetData());
geom = mitkImg->GetGeometry();
typedef mitk::ImageToItk< FilterType::InputImageType > CasterType;
CasterType::Pointer caster = CasterType::New();
caster->SetInput(mitkImg);
caster->Update();
FilterType::InputImageType::Pointer itkImg = caster->GetOutput();
inputVec->InsertElement(inputVec->Size(), itkImg);
}
filter->SetInputImages(inputVec);
filter->GenerateData();
mitk::Vector3D outImageSpacing = geom->GetSpacing();
float maxSpacing = 1;
if(outImageSpacing[0]>outImageSpacing[1] && outImageSpacing[0]>outImageSpacing[2])
maxSpacing = outImageSpacing[0];
else if (outImageSpacing[1] > outImageSpacing[2])
maxSpacing = outImageSpacing[1];
else
maxSpacing = outImageSpacing[2];
mitk::FiberBundleX::Pointer directions = filter->GetOutputFiberBundle();
// directions->SetGeometry(geom);
DataNode::Pointer node = DataNode::New();
node->SetData(directions);
node->SetName("_VectorField");
node->SetProperty("Fiber2DSliceThickness", mitk::FloatProperty::New(maxSpacing));
node->SetProperty("Fiber2DfadeEFX", mitk::BoolProperty::New(false));
GetDataStorage()->Add(node);
typedef FilterType::DirectionImageContainerType DirectionImageContainerType;
DirectionImageContainerType::Pointer container = filter->GetDirectionImageContainer();
for (int i=0; i<container->Size(); i++)
{
ItkDirectionImage3DType::Pointer itkImg = container->GetElement(i);
mitk::Image::Pointer img = mitk::Image::New();
img->InitializeByItk( itkImg.GetPointer() );
img->SetVolume( itkImg->GetBufferPointer() );
DataNode::Pointer node = DataNode::New();
node->SetData(img);
QString name(m_ImageNodes.at(i)->GetName().c_str());
name += "_Direction";
name += QString::number(i+1);
node->SetName(name.toStdString().c_str());
node->SetVisibility(false);
GetDataStorage()->Add(node);
}
break;
}
case 1:
{
typedef itk::Image< float, 4 > ItkImageType;
typedef itk::MrtrixPeakImageConverter< float > FilterType;
FilterType::Pointer filter = FilterType::New();
// cast to itk
mitk::Image::Pointer mitkImg = dynamic_cast<mitk::Image*>(m_ImageNodes.at(0)->GetData());
- mitk::Geometry3D::Pointer geom = mitkImg->GetGeometry();
+ mitk::BaseGeometry::Pointer geom = mitkImg->GetGeometry();
typedef mitk::ImageToItk< FilterType::InputImageType > CasterType;
CasterType::Pointer caster = CasterType::New();
caster->SetInput(mitkImg);
caster->Update();
FilterType::InputImageType::Pointer itkImg = caster->GetOutput();
filter->SetInputImage(itkImg);
filter->GenerateData();
mitk::Vector3D outImageSpacing = geom->GetSpacing();
float maxSpacing = 1;
if(outImageSpacing[0]>outImageSpacing[1] && outImageSpacing[0]>outImageSpacing[2])
maxSpacing = outImageSpacing[0];
else if (outImageSpacing[1] > outImageSpacing[2])
maxSpacing = outImageSpacing[1];
else
maxSpacing = outImageSpacing[2];
mitk::FiberBundleX::Pointer directions = filter->GetOutputFiberBundle();
//directions->SetGeometry(geom);
DataNode::Pointer node = DataNode::New();
node->SetData(directions);
QString name(m_ImageNodes.at(0)->GetName().c_str());
name += "_VectorField";
node->SetName(name.toStdString().c_str());
node->SetProperty("Fiber2DSliceThickness", mitk::FloatProperty::New(maxSpacing));
node->SetProperty("Fiber2DfadeEFX", mitk::BoolProperty::New(false));
GetDataStorage()->Add(node);
{
ItkUcharImgType::Pointer numDirImage = filter->GetNumDirectionsImage();
mitk::Image::Pointer image2 = mitk::Image::New();
image2->InitializeByItk( numDirImage.GetPointer() );
image2->SetVolume( numDirImage->GetBufferPointer() );
DataNode::Pointer node2 = DataNode::New();
node2->SetData(image2);
QString name(m_ImageNodes.at(0)->GetName().c_str());
name += "_NumDirections";
node2->SetName(name.toStdString().c_str());
GetDataStorage()->Add(node2);
}
typedef FilterType::DirectionImageContainerType DirectionImageContainerType;
DirectionImageContainerType::Pointer container = filter->GetDirectionImageContainer();
for (int i=0; i<container->Size(); i++)
{
ItkDirectionImage3DType::Pointer itkImg = container->GetElement(i);
mitk::Image::Pointer img = mitk::Image::New();
img->InitializeByItk( itkImg.GetPointer() );
img->SetVolume( itkImg->GetBufferPointer() );
DataNode::Pointer node = DataNode::New();
node->SetData(img);
QString name(m_ImageNodes.at(0)->GetName().c_str());
name += "_Direction";
name += QString::number(i+1);
node->SetName(name.toStdString().c_str());
node->SetVisibility(false);
GetDataStorage()->Add(node);
}
break;
}
}
}
void QmitkOdfMaximaExtractionView::GenerateImage()
{
if (!m_ImageNodes.empty())
GenerateDataFromDwi();
}
void QmitkOdfMaximaExtractionView::StartTensor()
{
if (m_TensorImageNodes.empty())
return;
typedef itk::DiffusionTensorPrincipalDirectionImageFilter< float, float > MaximaExtractionFilterType;
MaximaExtractionFilterType::Pointer filter = MaximaExtractionFilterType::New();
- mitk::Geometry3D::Pointer geometry;
+ mitk::BaseGeometry::Pointer geometry;
try{
TensorImage::Pointer img = dynamic_cast<TensorImage*>(m_TensorImageNodes.at(0)->GetData());
ItkTensorImage::Pointer itkImage = ItkTensorImage::New();
CastToItkImage<ItkTensorImage>(img, itkImage);
filter->SetInput(itkImage);
geometry = img->GetGeometry();
}
catch(itk::ExceptionObject &e)
{
MITK_INFO << "wrong image type: " << e.what();
QMessageBox::warning( NULL, "Wrong pixel type", "Could not perform Tensor Principal Direction Extraction due to Image has wrong pixel type.", QMessageBox::Ok );
return;
//throw e;
}
if (!m_BinaryImageNodes.empty())
{
ItkUcharImgType::Pointer itkMaskImage = ItkUcharImgType::New();
Image::Pointer mitkMaskImg = dynamic_cast<Image*>(m_BinaryImageNodes.at(0)->GetData());
CastToItkImage<ItkUcharImgType>(mitkMaskImg, itkMaskImage);
filter->SetMaskImage(itkMaskImage);
}
if (m_Controls->m_NormalizationBox->currentIndex()==0)
filter->SetNormalizeVectors(false);
filter->Update();
if (m_Controls->m_OutputDirectionImagesBox->isChecked())
{
MaximaExtractionFilterType::OutputImageType::Pointer itkImg = filter->GetOutput();
mitk::Image::Pointer img = mitk::Image::New();
img->InitializeByItk( itkImg.GetPointer() );
img->SetVolume( itkImg->GetBufferPointer() );
DataNode::Pointer node = DataNode::New();
node->SetData(img);
QString name(m_TensorImageNodes.at(0)->GetName().c_str());
name += "_PrincipalDirection";
node->SetName(name.toStdString().c_str());
node->SetVisibility(false);
GetDataStorage()->Add(node);
}
if (m_Controls->m_OutputNumDirectionsBox->isChecked())
{
ItkUcharImgType::Pointer numDirImage = filter->GetNumDirectionsImage();
mitk::Image::Pointer image2 = mitk::Image::New();
image2->InitializeByItk( numDirImage.GetPointer() );
image2->SetVolume( numDirImage->GetBufferPointer() );
DataNode::Pointer node2 = DataNode::New();
node2->SetData(image2);
QString name(m_TensorImageNodes.at(0)->GetName().c_str());
name += "_NumDirections";
node2->SetName(name.toStdString().c_str());
GetDataStorage()->Add(node2);
}
if (m_Controls->m_OutputVectorFieldBox->isChecked())
{
mitk::Vector3D outImageSpacing = geometry->GetSpacing();
float minSpacing = 1;
if(outImageSpacing[0]<outImageSpacing[1] && outImageSpacing[0]<outImageSpacing[2])
minSpacing = outImageSpacing[0];
else if (outImageSpacing[1] < outImageSpacing[2])
minSpacing = outImageSpacing[1];
else
minSpacing = outImageSpacing[2];
mitk::FiberBundleX::Pointer directions = filter->GetOutputFiberBundle();
// directions->SetGeometry(geometry);
DataNode::Pointer node = DataNode::New();
node->SetData(directions);
QString name(m_TensorImageNodes.at(0)->GetName().c_str());
name += "_VectorField";
node->SetName(name.toStdString().c_str());
node->SetProperty("Fiber2DSliceThickness", mitk::FloatProperty::New(minSpacing));
node->SetProperty("Fiber2DfadeEFX", mitk::BoolProperty::New(false));
GetDataStorage()->Add(node);
}
}
template<int shOrder>
void QmitkOdfMaximaExtractionView::StartMaximaExtraction()
{
typedef itk::FiniteDiffOdfMaximaExtractionFilter< float, shOrder, 20242 > MaximaExtractionFilterType;
typename MaximaExtractionFilterType::Pointer filter = MaximaExtractionFilterType::New();
switch (m_Controls->m_ToolkitBox->currentIndex())
{
case 0:
filter->SetToolkit(MaximaExtractionFilterType::FSL);
break;
case 1:
filter->SetToolkit(MaximaExtractionFilterType::MRTRIX);
break;
default:
filter->SetToolkit(MaximaExtractionFilterType::FSL);
}
- mitk::Geometry3D::Pointer geometry;
+ mitk::BaseGeometry::Pointer geometry;
try{
Image::Pointer img = dynamic_cast<Image*>(m_ImageNodes.at(0)->GetData());
typedef ImageToItk< typename MaximaExtractionFilterType::CoefficientImageType > CasterType;
typename CasterType::Pointer caster = CasterType::New();
caster->SetInput(img);
caster->Update();
filter->SetInput(caster->GetOutput());
geometry = img->GetGeometry();
}
catch(itk::ExceptionObject &e)
{
MITK_INFO << "wrong image type: " << e.what();
QMessageBox::warning( NULL, "Wrong pixel type", "Could not perform Finite Differences Extraction due to Image has wrong pixel type.", QMessageBox::Ok );
return;
//throw;
}
filter->SetAngularThreshold(cos((float)m_Controls->m_AngularThreshold->value()*M_PI/180));
filter->SetClusteringThreshold(cos((float)m_Controls->m_ClusteringAngleBox->value()*M_PI/180));
filter->SetMaxNumPeaks(m_Controls->m_MaxNumPeaksBox->value());
filter->SetPeakThreshold(m_Controls->m_PeakThresholdBox->value());
filter->SetAbsolutePeakThreshold(m_Controls->m_AbsoluteThresholdBox->value());
if (!m_BinaryImageNodes.empty())
{
ItkUcharImgType::Pointer itkMaskImage = ItkUcharImgType::New();
Image::Pointer mitkMaskImg = dynamic_cast<Image*>(m_BinaryImageNodes.at(0)->GetData());
CastToItkImage<ItkUcharImgType>(mitkMaskImg, itkMaskImage);
filter->SetMaskImage(itkMaskImage);
}
switch (m_Controls->m_NormalizationBox->currentIndex())
{
case 0:
filter->SetNormalizationMethod(MaximaExtractionFilterType::NO_NORM);
break;
case 1:
filter->SetNormalizationMethod(MaximaExtractionFilterType::MAX_VEC_NORM);
break;
case 2:
filter->SetNormalizationMethod(MaximaExtractionFilterType::SINGLE_VEC_NORM);
break;
}
filter->Update();
if (m_Controls->m_OutputDirectionImagesBox->isChecked())
{
typedef typename MaximaExtractionFilterType::ItkDirectionImageContainer ItkDirectionImageContainer;
typename ItkDirectionImageContainer::Pointer container = filter->GetDirectionImageContainer();
for (int i=0; i<container->Size(); i++)
{
typename MaximaExtractionFilterType::ItkDirectionImage::Pointer itkImg = container->GetElement(i);
mitk::Image::Pointer img = mitk::Image::New();
img->InitializeByItk( itkImg.GetPointer() );
img->SetVolume( itkImg->GetBufferPointer() );
DataNode::Pointer node = DataNode::New();
node->SetData(img);
QString name(m_ImageNodes.at(0)->GetName().c_str());
name += "_Direction";
name += QString::number(i+1);
node->SetName(name.toStdString().c_str());
node->SetVisibility(false);
GetDataStorage()->Add(node);
}
}
if (m_Controls->m_OutputNumDirectionsBox->isChecked())
{
ItkUcharImgType::Pointer numDirImage = filter->GetNumDirectionsImage();
mitk::Image::Pointer image2 = mitk::Image::New();
image2->InitializeByItk( numDirImage.GetPointer() );
image2->SetVolume( numDirImage->GetBufferPointer() );
DataNode::Pointer node2 = DataNode::New();
node2->SetData(image2);
QString name(m_ImageNodes.at(0)->GetName().c_str());
name += "_NumDirections";
node2->SetName(name.toStdString().c_str());
GetDataStorage()->Add(node2);
}
if (m_Controls->m_OutputVectorFieldBox->isChecked())
{
mitk::Vector3D outImageSpacing = geometry->GetSpacing();
float minSpacing = 1;
if(outImageSpacing[0]<outImageSpacing[1] && outImageSpacing[0]<outImageSpacing[2])
minSpacing = outImageSpacing[0];
else if (outImageSpacing[1] < outImageSpacing[2])
minSpacing = outImageSpacing[1];
else
minSpacing = outImageSpacing[2];
mitk::FiberBundleX::Pointer directions = filter->GetOutputFiberBundle();
// directions->SetGeometry(geometry);
DataNode::Pointer node = DataNode::New();
node->SetData(directions);
QString name(m_ImageNodes.at(0)->GetName().c_str());
name += "_VectorField";
node->SetName(name.toStdString().c_str());
node->SetProperty("Fiber2DSliceThickness", mitk::FloatProperty::New(minSpacing));
node->SetProperty("Fiber2DfadeEFX", mitk::BoolProperty::New(false));
GetDataStorage()->Add(node);
}
}
void QmitkOdfMaximaExtractionView::StartFiniteDiff()
{
if (m_ImageNodes.empty())
return;
switch (m_Controls->m_ShOrderBox->currentIndex())
{
case 0:
StartMaximaExtraction<2>();
break;
case 1:
StartMaximaExtraction<4>();
break;
case 2:
StartMaximaExtraction<6>();
break;
case 3:
StartMaximaExtraction<8>();
break;
case 4:
StartMaximaExtraction<10>();
break;
case 5:
StartMaximaExtraction<12>();
break;
}
}
void QmitkOdfMaximaExtractionView::GenerateDataFromDwi()
{
typedef itk::OdfMaximaExtractionFilter< float > MaximaExtractionFilterType;
MaximaExtractionFilterType::Pointer filter = MaximaExtractionFilterType::New();
- mitk::Geometry3D::Pointer geometry;
+ mitk::BaseGeometry::Pointer geometry;
if (!m_ImageNodes.empty())
{
try{
Image::Pointer img = dynamic_cast<Image*>(m_ImageNodes.at(0)->GetData());
typedef ImageToItk< MaximaExtractionFilterType::CoefficientImageType > CasterType;
CasterType::Pointer caster = CasterType::New();
caster->SetInput(img);
caster->Update();
filter->SetShCoeffImage(caster->GetOutput());
geometry = img->GetGeometry();
}
catch(itk::ExceptionObject &e)
{
MITK_INFO << "wrong image type: " << e.what();
return;
}
}
else
return;
filter->SetMaxNumPeaks(m_Controls->m_MaxNumPeaksBox->value());
filter->SetPeakThreshold(m_Controls->m_PeakThresholdBox->value());
if (!m_BinaryImageNodes.empty())
{
ItkUcharImgType::Pointer itkMaskImage = ItkUcharImgType::New();
Image::Pointer mitkMaskImg = dynamic_cast<Image*>(m_BinaryImageNodes.at(0)->GetData());
CastToItkImage<ItkUcharImgType>(mitkMaskImg, itkMaskImage);
filter->SetMaskImage(itkMaskImage);
}
switch (m_Controls->m_NormalizationBox->currentIndex())
{
case 0:
filter->SetNormalizationMethod(MaximaExtractionFilterType::NO_NORM);
break;
case 1:
filter->SetNormalizationMethod(MaximaExtractionFilterType::MAX_VEC_NORM);
break;
case 2:
filter->SetNormalizationMethod(MaximaExtractionFilterType::SINGLE_VEC_NORM);
break;
}
filter->GenerateData();
ItkUcharImgType::Pointer numDirImage = filter->GetNumDirectionsImage();
if (m_Controls->m_OutputDirectionImagesBox->isChecked())
{
typedef MaximaExtractionFilterType::ItkDirectionImageContainer ItkDirectionImageContainer;
ItkDirectionImageContainer::Pointer container = filter->GetDirectionImageContainer();
for (int i=0; i<container->Size(); i++)
{
MaximaExtractionFilterType::ItkDirectionImage::Pointer itkImg = container->GetElement(i);
mitk::Image::Pointer img = mitk::Image::New();
img->InitializeByItk( itkImg.GetPointer() );
img->SetVolume( itkImg->GetBufferPointer() );
DataNode::Pointer node = DataNode::New();
node->SetData(img);
QString name(m_ImageNodes.at(0)->GetName().c_str());
name += "_Direction";
name += QString::number(i+1);
node->SetName(name.toStdString().c_str());
GetDataStorage()->Add(node);
}
}
if (m_Controls->m_OutputNumDirectionsBox->isChecked())
{
mitk::Image::Pointer image2 = mitk::Image::New();
image2->InitializeByItk( numDirImage.GetPointer() );
image2->SetVolume( numDirImage->GetBufferPointer() );
DataNode::Pointer node = DataNode::New();
node->SetData(image2);
QString name(m_ImageNodes.at(0)->GetName().c_str());
name += "_NumDirections";
node->SetName(name.toStdString().c_str());
GetDataStorage()->Add(node);
}
if (m_Controls->m_OutputVectorFieldBox->isChecked())
{
mitk::Vector3D outImageSpacing = geometry->GetSpacing();
float minSpacing = 1;
if(outImageSpacing[0]<outImageSpacing[1] && outImageSpacing[0]<outImageSpacing[2])
minSpacing = outImageSpacing[0];
else if (outImageSpacing[1] < outImageSpacing[2])
minSpacing = outImageSpacing[1];
else
minSpacing = outImageSpacing[2];
mitk::FiberBundleX::Pointer directions = filter->GetOutputFiberBundle();
// directions->SetGeometry(geometry);
DataNode::Pointer node = DataNode::New();
node->SetData(directions);
QString name(m_ImageNodes.at(0)->GetName().c_str());
name += "_VectorField";
node->SetName(name.toStdString().c_str());
node->SetProperty("Fiber2DSliceThickness", mitk::FloatProperty::New(minSpacing));
node->SetProperty("Fiber2DfadeEFX", mitk::BoolProperty::New(false));
GetDataStorage()->Add(node);
}
}
void QmitkOdfMaximaExtractionView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget)
{
m_MultiWidget = &stdMultiWidget;
}
void QmitkOdfMaximaExtractionView::StdMultiWidgetNotAvailable()
{
m_MultiWidget = NULL;
}
void QmitkOdfMaximaExtractionView::OnSelectionChanged( std::vector<mitk::DataNode*> nodes )
{
m_Controls->m_InputData->setTitle("Please Select Input Data");
m_Controls->m_DwiFibLabel->setText("<font color='red'>mandatory</font>");
m_Controls->m_MaskLabel->setText("<font color='grey'>optional</font>");
m_BinaryImageNodes.clear();
m_ImageNodes.clear();
m_TensorImageNodes.clear();
// iterate all selected objects, adjust warning visibility
for( std::vector<mitk::DataNode*>::iterator it = nodes.begin(); it != nodes.end(); ++it )
{
mitk::DataNode::Pointer node = *it;
if ( node.IsNotNull() && dynamic_cast<mitk::TensorImage*>(node->GetData()) )
{
m_TensorImageNodes.push_back(node);
}
else if( node.IsNotNull() && dynamic_cast<mitk::Image*>(node->GetData()) )
{
bool isBinary = false;
node->GetPropertyValue<bool>("binary", isBinary);
if (isBinary)
m_BinaryImageNodes.push_back(node);
else
m_ImageNodes.push_back(node);
}
}
UpdateGui();
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPartialVolumeAnalysisView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPartialVolumeAnalysisView.cpp
index f77ba338e2..bda3c06a86 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPartialVolumeAnalysisView.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPartialVolumeAnalysisView.cpp
@@ -1,2170 +1,2170 @@
/*===================================================================
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 "QmitkPartialVolumeAnalysisView.h"
#include <limits>
#include <qlabel.h>
#include <qspinbox.h>
#include <qpushbutton.h>
#include <qcheckbox.h>
#include <qgroupbox.h>
#include <qradiobutton.h>
#include <qlineedit.h>
#include <qclipboard.h>
#include <qfiledialog.h>
#include <berryIEditorPart.h>
#include <berryIWorkbenchPage.h>
#include <berryPlatform.h>
#include "QmitkStdMultiWidget.h"
#include "QmitkStdMultiWidgetEditor.h"
#include "QmitkSliderNavigatorWidget.h"
#include <QMessageBox>
#include "mitkNodePredicateDataType.h"
#include "mitkNodePredicateOr.h"
#include "mitkImageTimeSelector.h"
#include "mitkProperties.h"
#include "mitkProgressBar.h"
#include "mitkImageCast.h"
#include "mitkImageToItk.h"
#include "mitkITKImageImport.h"
#include "mitkDataNodeObject.h"
#include "mitkNodePredicateData.h"
#include "mitkPlanarFigureInteractor.h"
#include "mitkGlobalInteraction.h"
#include "mitkTensorImage.h"
#include "mitkPlanarCircle.h"
#include "mitkPlanarRectangle.h"
#include "mitkPlanarPolygon.h"
#include "mitkPartialVolumeAnalysisClusteringCalculator.h"
#include "mitkDiffusionImage.h"
#include "usModuleRegistry.h"
#include <itkVectorImage.h>
#include "itkTensorDerivedMeasurementsFilter.h"
#include "itkDiffusionTensor3D.h"
#include "itkCartesianToPolarVectorImageFilter.h"
#include "itkPolarToCartesianVectorImageFilter.h"
#include "itkBinaryThresholdImageFilter.h"
#include "itkMaskImageFilter.h"
#include "itkCastImageFilter.h"
#include "itkImageMomentsCalculator.h"
#include <itkResampleImageFilter.h>
#include <itkGaussianInterpolateImageFunction.h>
#include <itkNearestNeighborInterpolateImageFunction.h>
#include <vnl/vnl_vector.h>
#define _USE_MATH_DEFINES
#include <math.h>
#define PVA_PI M_PI
const std::string QmitkPartialVolumeAnalysisView::VIEW_ID =
"org.mitk.views.partialvolumeanalysisview";
class QmitkRequestStatisticsUpdateEvent : public QEvent
{
public:
enum Type
{
StatisticsUpdateRequest = QEvent::MaxUser - 1025
};
QmitkRequestStatisticsUpdateEvent()
: QEvent( (QEvent::Type) StatisticsUpdateRequest ) {};
};
typedef itk::Image<short, 3> ImageType;
typedef itk::Image<float, 3> FloatImageType;
typedef itk::Image<itk::Vector<float,3>, 3> VectorImageType;
inline bool my_isnan(float x)
{
volatile float d = x;
if(d!=d)
return true;
if(d==d)
return false;
return d != d;
}
QmitkPartialVolumeAnalysisView::QmitkPartialVolumeAnalysisView(QObject * /*parent*/, const char * /*name*/)
: //QmitkFunctionality(),
m_Controls( NULL ),
m_TimeStepperAdapter( NULL ),
m_MeasurementInfoRenderer(0),
m_MeasurementInfoAnnotation(0),
m_SelectedImageNodes( ),
m_SelectedImage( NULL ),
m_SelectedMaskNode( NULL ),
m_SelectedImageMask( NULL ),
m_SelectedPlanarFigureNodes(0),
m_SelectedPlanarFigure( NULL ),
m_IsTensorImage(false),
m_FAImage(0),
m_RDImage(0),
m_ADImage(0),
m_MDImage(0),
m_CAImage(0),
// m_DirectionImage(0),
m_DirectionComp1Image(0),
m_DirectionComp2Image(0),
m_AngularErrorImage(0),
m_SelectedRenderWindow(NULL),
m_LastRenderWindow(NULL),
m_ImageObserverTag( -1 ),
m_ImageMaskObserverTag( -1 ),
m_PlanarFigureObserverTag( -1 ),
m_CurrentStatisticsValid( false ),
m_StatisticsUpdatePending( false ),
m_GaussianSigmaChangedSliding(false),
m_NumberBinsSliding(false),
m_UpsamplingChangedSliding(false),
m_ClusteringResult(NULL),
m_EllipseCounter(0),
m_RectangleCounter(0),
m_PolygonCounter(0),
m_CurrentFigureNodeInitialized(false),
m_QuantifyClass(2),
m_IconTexOFF(new QIcon(":/QmitkPartialVolumeAnalysisView/texIntOFFIcon.png")),
m_IconTexON(new QIcon(":/QmitkPartialVolumeAnalysisView/texIntONIcon.png")),
m_TexIsOn(true),
m_Visible(false)
{
}
QmitkPartialVolumeAnalysisView::~QmitkPartialVolumeAnalysisView()
{
if ( m_SelectedImage.IsNotNull() )
m_SelectedImage->RemoveObserver( m_ImageObserverTag );
if ( m_SelectedImageMask.IsNotNull() )
m_SelectedImageMask->RemoveObserver( m_ImageMaskObserverTag );
if ( m_SelectedPlanarFigure.IsNotNull() )
{
m_SelectedPlanarFigure->RemoveObserver( m_PlanarFigureObserverTag );
m_SelectedPlanarFigure->RemoveObserver( m_InitializedObserverTag );
}
this->GetDataStorage()->AddNodeEvent -= mitk::MessageDelegate1<QmitkPartialVolumeAnalysisView
, const mitk::DataNode*>( this, &QmitkPartialVolumeAnalysisView::NodeAddedInDataStorage );
m_SelectedPlanarFigureNodes->NodeChanged.RemoveListener( mitk::MessageDelegate1<QmitkPartialVolumeAnalysisView
, const mitk::DataNode*>( this, &QmitkPartialVolumeAnalysisView::NodeChanged ) );
m_SelectedPlanarFigureNodes->NodeRemoved.RemoveListener( mitk::MessageDelegate1<QmitkPartialVolumeAnalysisView
, const mitk::DataNode*>( this, &QmitkPartialVolumeAnalysisView::NodeRemoved ) );
m_SelectedPlanarFigureNodes->PropertyChanged.RemoveListener( mitk::MessageDelegate2<QmitkPartialVolumeAnalysisView
, const mitk::DataNode*, const mitk::BaseProperty*>( this, &QmitkPartialVolumeAnalysisView::PropertyChanged ) );
m_SelectedImageNodes->NodeChanged.RemoveListener( mitk::MessageDelegate1<QmitkPartialVolumeAnalysisView
, const mitk::DataNode*>( this, &QmitkPartialVolumeAnalysisView::NodeChanged ) );
m_SelectedImageNodes->NodeRemoved.RemoveListener( mitk::MessageDelegate1<QmitkPartialVolumeAnalysisView
, const mitk::DataNode*>( this, &QmitkPartialVolumeAnalysisView::NodeRemoved ) );
m_SelectedImageNodes->PropertyChanged.RemoveListener( mitk::MessageDelegate2<QmitkPartialVolumeAnalysisView
, const mitk::DataNode*, const mitk::BaseProperty*>( this, &QmitkPartialVolumeAnalysisView::PropertyChanged ) );
}
void QmitkPartialVolumeAnalysisView::CreateQtPartControl(QWidget *parent)
{
if (m_Controls == NULL)
{
m_Controls = new Ui::QmitkPartialVolumeAnalysisViewControls;
m_Controls->setupUi(parent);
this->CreateConnections();
}
SetHistogramVisibility();
m_Controls->m_TextureIntON->setIcon(*m_IconTexON);
m_Controls->m_SimilarAnglesFrame->setVisible(false);
m_Controls->m_SimilarAnglesLabel->setVisible(false);
vtkTextProperty *textProp = vtkTextProperty::New();
textProp->SetColor(1.0, 1.0, 1.0);
m_MeasurementInfoAnnotation = vtkCornerAnnotation::New();
m_MeasurementInfoAnnotation->SetMaximumFontSize(12);
m_MeasurementInfoAnnotation->SetTextProperty(textProp);
m_MeasurementInfoRenderer = vtkRenderer::New();
m_MeasurementInfoRenderer->AddActor(m_MeasurementInfoAnnotation);
m_SelectedPlanarFigureNodes = mitk::DataStorageSelection::New(this->GetDataStorage(), false);
m_SelectedPlanarFigureNodes->NodeChanged.AddListener( mitk::MessageDelegate1<QmitkPartialVolumeAnalysisView
, const mitk::DataNode*>( this, &QmitkPartialVolumeAnalysisView::NodeChanged ) );
m_SelectedPlanarFigureNodes->NodeRemoved.AddListener( mitk::MessageDelegate1<QmitkPartialVolumeAnalysisView
, const mitk::DataNode*>( this, &QmitkPartialVolumeAnalysisView::NodeRemoved ) );
m_SelectedPlanarFigureNodes->PropertyChanged.AddListener( mitk::MessageDelegate2<QmitkPartialVolumeAnalysisView
, const mitk::DataNode*, const mitk::BaseProperty*>( this, &QmitkPartialVolumeAnalysisView::PropertyChanged ) );
m_SelectedImageNodes = mitk::DataStorageSelection::New(this->GetDataStorage(), false);
m_SelectedImageNodes->PropertyChanged.AddListener( mitk::MessageDelegate2<QmitkPartialVolumeAnalysisView
, const mitk::DataNode*, const mitk::BaseProperty*>( this, &QmitkPartialVolumeAnalysisView::PropertyChanged ) );
m_SelectedImageNodes->NodeChanged.AddListener( mitk::MessageDelegate1<QmitkPartialVolumeAnalysisView
, const mitk::DataNode*>( this, &QmitkPartialVolumeAnalysisView::NodeChanged ) );
m_SelectedImageNodes->NodeRemoved.AddListener( mitk::MessageDelegate1<QmitkPartialVolumeAnalysisView
, const mitk::DataNode*>( this, &QmitkPartialVolumeAnalysisView::NodeRemoved ) );
this->GetDataStorage()->AddNodeEvent.AddListener( mitk::MessageDelegate1<QmitkPartialVolumeAnalysisView
, const mitk::DataNode*>( this, &QmitkPartialVolumeAnalysisView::NodeAddedInDataStorage ) );
Select(NULL,true,true);
SetAdvancedVisibility();
}
void QmitkPartialVolumeAnalysisView::SetHistogramVisibility()
{
m_Controls->m_HistogramWidget->setVisible(m_Controls->m_DisplayHistogramCheckbox->isChecked());
}
void QmitkPartialVolumeAnalysisView::SetAdvancedVisibility()
{
m_Controls->frame_7->setVisible(m_Controls->m_AdvancedCheckbox->isChecked());
}
void QmitkPartialVolumeAnalysisView::CreateConnections()
{
if ( m_Controls )
{
connect( m_Controls->m_DisplayHistogramCheckbox, SIGNAL( clicked() )
, this, SLOT( SetHistogramVisibility() ) );
connect( m_Controls->m_AdvancedCheckbox, SIGNAL( clicked() )
, this, SLOT( SetAdvancedVisibility() ) );
connect( m_Controls->m_NumberBinsSlider, SIGNAL( sliderReleased () ),
this, SLOT( NumberBinsReleasedSlider( ) ) );
connect( m_Controls->m_UpsamplingSlider, SIGNAL( sliderReleased( ) ),
this, SLOT( UpsamplingReleasedSlider( ) ) );
connect( m_Controls->m_GaussianSigmaSlider, SIGNAL( sliderReleased( ) ),
this, SLOT( GaussianSigmaReleasedSlider( ) ) );
connect( m_Controls->m_SimilarAnglesSlider, SIGNAL( sliderReleased( ) ),
this, SLOT( SimilarAnglesReleasedSlider( ) ) );
connect( m_Controls->m_NumberBinsSlider, SIGNAL( valueChanged (int) ),
this, SLOT( NumberBinsChangedSlider( int ) ) );
connect( m_Controls->m_UpsamplingSlider, SIGNAL( valueChanged( int ) ),
this, SLOT( UpsamplingChangedSlider( int ) ) );
connect( m_Controls->m_GaussianSigmaSlider, SIGNAL( valueChanged( int ) ),
this, SLOT( GaussianSigmaChangedSlider( int ) ) );
connect( m_Controls->m_SimilarAnglesSlider, SIGNAL( valueChanged( int ) ),
this, SLOT( SimilarAnglesChangedSlider(int) ) );
connect( m_Controls->m_OpacitySlider, SIGNAL( valueChanged( int ) ),
this, SLOT( OpacityChangedSlider(int) ) );
connect( (QObject*)(m_Controls->m_ButtonCopyHistogramToClipboard), SIGNAL(clicked()),(QObject*) this, SLOT(ToClipBoard()));
connect( m_Controls->m_CircleButton, SIGNAL( clicked() )
, this, SLOT( ActionDrawEllipseTriggered() ) );
connect( m_Controls->m_RectangleButton, SIGNAL( clicked() )
, this, SLOT( ActionDrawRectangleTriggered() ) );
connect( m_Controls->m_PolygonButton, SIGNAL( clicked() )
, this, SLOT( ActionDrawPolygonTriggered() ) );
connect( m_Controls->m_GreenRadio, SIGNAL( clicked(bool) )
, this, SLOT( GreenRadio(bool) ) );
connect( m_Controls->m_PartialVolumeRadio, SIGNAL( clicked(bool) )
, this, SLOT( PartialVolumeRadio(bool) ) );
connect( m_Controls->m_BlueRadio, SIGNAL( clicked(bool) )
, this, SLOT( BlueRadio(bool) ) );
connect( m_Controls->m_AllRadio, SIGNAL( clicked(bool) )
, this, SLOT( AllRadio(bool) ) );
connect( m_Controls->m_EstimateCircle, SIGNAL( clicked() )
, this, SLOT( EstimateCircle() ) );
connect( (QObject*)(m_Controls->m_TextureIntON), SIGNAL(clicked()), this, SLOT(TextIntON()) );
connect( m_Controls->m_ExportClusteringResultsButton, SIGNAL(clicked()), this, SLOT(ExportClusteringResults()));
}
}
void QmitkPartialVolumeAnalysisView::ExportClusteringResults()
{
if (m_ClusteringResult.IsNull() || m_SelectedImage.IsNull())
return;
- mitk::Geometry3D* geometry = m_SelectedImage->GetGeometry();
+ mitk::BaseGeometry* geometry = m_SelectedImage->GetGeometry();
itk::Image< short, 3>::Pointer referenceImage = itk::Image< short, 3>::New();
itk::Vector<double,3> newSpacing = geometry->GetSpacing();
mitk::Point3D newOrigin = geometry->GetOrigin();
mitk::Geometry3D::BoundsArrayType bounds = geometry->GetBounds();
newOrigin[0] += bounds.GetElement(0);
newOrigin[1] += bounds.GetElement(2);
newOrigin[2] += bounds.GetElement(4);
itk::Matrix<double, 3, 3> newDirection;
itk::ImageRegion<3> imageRegion;
for (int i=0; i<3; i++)
for (int j=0; j<3; j++)
newDirection[j][i] = geometry->GetMatrixColumn(i)[j]/newSpacing[j];
imageRegion.SetSize(0, geometry->GetExtent(0));
imageRegion.SetSize(1, geometry->GetExtent(1));
imageRegion.SetSize(2, geometry->GetExtent(2));
// apply new image parameters
referenceImage->SetSpacing( newSpacing );
referenceImage->SetOrigin( newOrigin );
referenceImage->SetDirection( newDirection );
referenceImage->SetRegions( imageRegion );
referenceImage->Allocate();
typedef itk::Image< float, 3 > OutType;
mitk::Image::Pointer mitkInImage = dynamic_cast<mitk::Image*>(m_ClusteringResult->GetData());
typedef itk::Image< itk::RGBAPixel<unsigned char>, 3 > ItkRgbaImageType;
typedef mitk::ImageToItk< ItkRgbaImageType > CasterType;
CasterType::Pointer caster = CasterType::New();
caster->SetInput(mitkInImage);
caster->Update();
ItkRgbaImageType::Pointer itkInImage = caster->GetOutput();
typedef itk::ExtractChannelFromRgbaImageFilter< itk::Image< short, 3>, OutType > ExtractionFilterType;
ExtractionFilterType::Pointer filter = ExtractionFilterType::New();
filter->SetInput(itkInImage);
filter->SetChannel(ExtractionFilterType::ALPHA);
filter->SetReferenceImage(referenceImage);
filter->Update();
OutType::Pointer outImg = filter->GetOutput();
mitk::Image::Pointer img = mitk::Image::New(); img->InitializeByItk(outImg.GetPointer());
img->SetVolume(outImg->GetBufferPointer());
// init data node
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData(img);
node->SetName("Clustering Result");
GetDataStorage()->Add(node);
}
void QmitkPartialVolumeAnalysisView::EstimateCircle()
{
typedef itk::Image<unsigned char, 3> SegImageType;
SegImageType::Pointer mask_itk = SegImageType::New();
typedef mitk::ImageToItk<SegImageType> CastType;
CastType::Pointer caster = CastType::New();
caster->SetInput(m_SelectedImageMask);
caster->Update();
typedef itk::ImageMomentsCalculator< SegImageType > MomentsType;
MomentsType::Pointer momentsCalc = MomentsType::New();
momentsCalc->SetImage(caster->GetOutput());
momentsCalc->Compute();
MomentsType::VectorType cog = momentsCalc->GetCenterOfGravity();
MomentsType::MatrixType axes = momentsCalc->GetPrincipalAxes();
MomentsType::VectorType moments = momentsCalc->GetPrincipalMoments();
// moments-coord conversion
// third coordinate min oder max?
// max-min = extent
MomentsType::AffineTransformPointer trafo = momentsCalc->GetPhysicalAxesToPrincipalAxesTransform();
itk::ImageRegionIterator<SegImageType>
itimage(caster->GetOutput(), caster->GetOutput()->GetLargestPossibleRegion());
itimage = itimage.Begin();
double max = -9999999999.0;
double min = 9999999999.0;
while( !itimage.IsAtEnd() )
{
if(itimage.Get())
{
ImageType::IndexType index = itimage.GetIndex();
itk::Point<float,3> point;
caster->GetOutput()->TransformIndexToPhysicalPoint(index,point);
itk::Point<float,3> newPoint;
newPoint = trafo->TransformPoint(point);
if(newPoint[2]<min)
min = newPoint[2];
if(newPoint[2]>max)
max = newPoint[2];
}
++itimage;
}
double extent = max - min;
MITK_DEBUG << "EXTENT = " << extent;
mitk::Point3D origin;
mitk::Vector3D right, bottom, normal;
double factor = 1000.0;
mitk::FillVector3D(origin, cog[0]-factor*axes[1][0]-factor*axes[2][0],
cog[1]-factor*axes[1][1]-factor*axes[2][1],
cog[2]-factor*axes[1][2]-factor*axes[2][2]);
// mitk::FillVector3D(normal, axis[0][0],axis[0][1],axis[0][2]);
mitk::FillVector3D(bottom, 2*factor*axes[1][0], 2*factor*axes[1][1], 2*factor*axes[1][2]);
mitk::FillVector3D(right, 2*factor*axes[2][0], 2*factor*axes[2][1], 2*factor*axes[2][2]);
mitk::PlaneGeometry::Pointer planegeometry = mitk::PlaneGeometry::New();
planegeometry->InitializeStandardPlane(right.Get_vnl_vector(), bottom.Get_vnl_vector());
planegeometry->SetOrigin(origin);
double len1 = sqrt(axes[1][0]*axes[1][0] + axes[1][1]*axes[1][1] + axes[1][2]*axes[1][2]);
double len2 = sqrt(axes[2][0]*axes[2][0] + axes[2][1]*axes[2][1] + axes[2][2]*axes[2][2]);
mitk::Point2D point1;
point1[0] = factor*len1;
point1[1] = factor*len2;
mitk::Point2D point2;
point2[0] = factor*len1+extent*.5;
point2[1] = factor*len2;
mitk::PlanarCircle::Pointer circle = mitk::PlanarCircle::New();
circle->SetGeometry2D(planegeometry);
circle->PlaceFigure( point1 );
circle->SetControlPoint(0,point1);
circle->SetControlPoint(1,point2);
//circle->SetCurrentControlPoint( point2 );
mitk::PlanarFigure::PolyLineType polyline = circle->GetPolyLine( 0 );
MITK_DEBUG << "SIZE of planar figure polyline: " << polyline.size();
AddFigureToDataStorage(circle, "Circle");
}
bool QmitkPartialVolumeAnalysisView::AssertDrawingIsPossible(bool checked)
{
if (m_SelectedImageNodes->GetNode().IsNull())
{
checked = false;
this->HandleException("Please select an image!", dynamic_cast<QWidget *>(this->parent()), true);
return false;
}
//this->GetActiveStdMultiWidget()->SetWidgetPlanesVisibility(false);
return checked;
}
void QmitkPartialVolumeAnalysisView::ActionDrawEllipseTriggered()
{
bool checked = m_Controls->m_CircleButton->isChecked();
if(!this->AssertDrawingIsPossible(checked))
return;
mitk::PlanarCircle::Pointer figure = mitk::PlanarCircle::New();
// using PV_ prefix for planar figures from this view
// to distinguish them from that ones created throught the measurement view
this->AddFigureToDataStorage(figure, QString("PV_Circle%1").arg(++m_EllipseCounter));
MITK_DEBUG << "PlanarCircle created ...";
}
void QmitkPartialVolumeAnalysisView::ActionDrawRectangleTriggered()
{
bool checked = m_Controls->m_RectangleButton->isChecked();
if(!this->AssertDrawingIsPossible(checked))
return;
mitk::PlanarRectangle::Pointer figure = mitk::PlanarRectangle::New();
// using PV_ prefix for planar figures from this view
// to distinguish them from that ones created throught the measurement view
this->AddFigureToDataStorage(figure, QString("PV_Rectangle%1").arg(++m_RectangleCounter));
MITK_DEBUG << "PlanarRectangle created ...";
}
void QmitkPartialVolumeAnalysisView::ActionDrawPolygonTriggered()
{
bool checked = m_Controls->m_PolygonButton->isChecked();
if(!this->AssertDrawingIsPossible(checked))
return;
mitk::PlanarPolygon::Pointer figure = mitk::PlanarPolygon::New();
figure->ClosedOn();
// using PV_ prefix for planar figures from this view
// to distinguish them from that ones created throught the measurement view
this->AddFigureToDataStorage(figure, QString("PV_Polygon%1").arg(++m_PolygonCounter));
MITK_DEBUG << "PlanarPolygon created ...";
}
void QmitkPartialVolumeAnalysisView::AddFigureToDataStorage(mitk::PlanarFigure* figure, const QString& name,
const char *propertyKey, mitk::BaseProperty *property )
{
mitk::DataNode::Pointer newNode = mitk::DataNode::New();
newNode->SetName(name.toStdString());
newNode->SetData(figure);
// Add custom property, if available
if ( (propertyKey != NULL) && (property != NULL) )
{
newNode->AddProperty( propertyKey, property );
}
// figure drawn on the topmost layer / image
this->GetDataStorage()->Add(newNode, m_SelectedImageNodes->GetNode() );
QList<mitk::DataNode::Pointer> selectedNodes = this->GetDataManagerSelection();
for(unsigned int i = 0; i < selectedNodes.size(); i++)
{
selectedNodes[i]->SetSelected(false);
}
std::vector<mitk::DataNode *> selectedPFNodes = m_SelectedPlanarFigureNodes->GetNodes();
for(unsigned int i = 0; i < selectedPFNodes.size(); i++)
{
selectedPFNodes[i]->SetSelected(false);
}
newNode->SetSelected(true);
Select(newNode);
}
void QmitkPartialVolumeAnalysisView::PlanarFigureInitialized()
{
if(m_SelectedPlanarFigureNodes->GetNode().IsNull())
return;
m_CurrentFigureNodeInitialized = true;
this->Select(m_SelectedPlanarFigureNodes->GetNode());
m_Controls->m_CircleButton->setChecked(false);
m_Controls->m_RectangleButton->setChecked(false);
m_Controls->m_PolygonButton->setChecked(false);
//this->GetActiveStdMultiWidget()->SetWidgetPlanesVisibility(true);
this->RequestStatisticsUpdate();
}
void QmitkPartialVolumeAnalysisView::PlanarFigureFocus(mitk::DataNode* node)
{
mitk::PlanarFigure* _PlanarFigure = 0;
_PlanarFigure = dynamic_cast<mitk::PlanarFigure*> (node->GetData());
if (_PlanarFigure)
{
FindRenderWindow(node);
const mitk::PlaneGeometry
* _PlaneGeometry =
dynamic_cast<const mitk::PlaneGeometry*> (_PlanarFigure->GetGeometry2D());
// make node visible
if (m_SelectedRenderWindow)
{
mitk::Point3D centerP = _PlaneGeometry->GetOrigin();
m_SelectedRenderWindow->GetSliceNavigationController()->ReorientSlices(
centerP, _PlaneGeometry->GetNormal());
m_SelectedRenderWindow->GetSliceNavigationController()->SelectSliceByPoint(
centerP);
}
}
}
void QmitkPartialVolumeAnalysisView::FindRenderWindow(mitk::DataNode* node)
{
if (node && dynamic_cast<mitk::PlanarFigure*> (node->GetData()))
{
m_SelectedRenderWindow = 0;
bool PlanarFigureInitializedWindow = false;
foreach(QmitkRenderWindow * window, this->GetRenderWindowPart()->GetQmitkRenderWindows().values())
{
if (!m_SelectedRenderWindow && node->GetBoolProperty("PlanarFigureInitializedWindow", PlanarFigureInitializedWindow, window->GetRenderer()))
{
m_SelectedRenderWindow = window;
}
}
}
}
void QmitkPartialVolumeAnalysisView::OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList<mitk::DataNode::Pointer> &nodes)
{
m_Controls->m_InputData->setTitle("Please Select Input Data");
if (!m_Visible)
return;
if ( nodes.empty() )
{
if (m_ClusteringResult.IsNotNull())
{
this->GetDataStorage()->Remove(m_ClusteringResult);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
Select(NULL, true, true);
}
for (int i=0; i<nodes.size(); i++)
Select(nodes.at(i));
}
void QmitkPartialVolumeAnalysisView::Select( mitk::DataNode::Pointer node, bool clearMaskOnFirstArgNULL, bool clearImageOnFirstArgNULL )
{
// Clear any unreferenced images
this->RemoveOrphanImages();
bool somethingChanged = false;
if(node.IsNull())
{
somethingChanged = true;
if(clearMaskOnFirstArgNULL)
{
if ( (m_SelectedImageMask.IsNotNull()) && (m_ImageMaskObserverTag >= 0) )
{
m_SelectedImageMask->RemoveObserver( m_ImageMaskObserverTag );
m_ImageMaskObserverTag = -1;
}
if ( (m_SelectedPlanarFigure.IsNotNull()) && (m_PlanarFigureObserverTag >= 0) )
{
m_SelectedPlanarFigure->RemoveObserver( m_PlanarFigureObserverTag );
m_PlanarFigureObserverTag = -1;
}
if ( (m_SelectedPlanarFigure.IsNotNull()) && (m_InitializedObserverTag >= 0) )
{
m_SelectedPlanarFigure->RemoveObserver( m_InitializedObserverTag );
m_InitializedObserverTag = -1;
}
m_SelectedPlanarFigure = NULL;
m_SelectedPlanarFigureNodes->RemoveAllNodes();
m_CurrentFigureNodeInitialized = false;
m_SelectedRenderWindow = 0;
m_SelectedMaskNode = NULL;
m_SelectedImageMask = NULL;
}
if(clearImageOnFirstArgNULL)
{
if ( (m_SelectedImage.IsNotNull()) && (m_ImageObserverTag >= 0) )
{
m_SelectedImage->RemoveObserver( m_ImageObserverTag );
m_ImageObserverTag = -1;
}
m_SelectedImageNodes->RemoveAllNodes();
m_SelectedImage = NULL;
m_IsTensorImage = false;
m_FAImage = NULL;
m_RDImage = NULL;
m_ADImage = NULL;
m_MDImage = NULL;
m_CAImage = NULL;
m_DirectionComp1Image = NULL;
m_DirectionComp2Image = NULL;
m_AngularErrorImage = NULL;
m_Controls->m_SimilarAnglesFrame->setVisible(false);
m_Controls->m_SimilarAnglesLabel->setVisible(false);
}
}
else
{
typedef itk::SimpleMemberCommand< QmitkPartialVolumeAnalysisView > ITKCommandType;
ITKCommandType::Pointer changeListener;
changeListener = ITKCommandType::New();
changeListener->SetCallbackFunction( this, &QmitkPartialVolumeAnalysisView::RequestStatisticsUpdate );
// Get selected element
mitk::TensorImage *selectedTensorImage = dynamic_cast< mitk::TensorImage * >( node->GetData() );
mitk::Image *selectedImage = dynamic_cast< mitk::Image * >( node->GetData() );
mitk::PlanarFigure *selectedPlanar = dynamic_cast< mitk::PlanarFigure * >( node->GetData() );
bool isMask = false;
bool isImage = false;
bool isPlanar = false;
bool isTensorImage = false;
if (selectedTensorImage != NULL)
{
isTensorImage = true;
}
else if(selectedImage != NULL)
{
node->GetPropertyValue("binary", isMask);
isImage = !isMask;
}
else if ( (selectedPlanar != NULL) )
{
isPlanar = true;
}
// image
if(isImage && selectedImage->GetDimension()==3)
{
if(selectedImage != m_SelectedImage.GetPointer())
{
somethingChanged = true;
if ( (m_SelectedImage.IsNotNull()) && (m_ImageObserverTag >= 0) )
{
m_SelectedImage->RemoveObserver( m_ImageObserverTag );
m_ImageObserverTag = -1;
}
*m_SelectedImageNodes = node;
m_SelectedImage = selectedImage;
m_IsTensorImage = false;
m_FAImage = NULL;
m_RDImage = NULL;
m_ADImage = NULL;
m_MDImage = NULL;
m_CAImage = NULL;
m_DirectionComp1Image = NULL;
m_DirectionComp2Image = NULL;
m_AngularErrorImage = NULL;
// Add change listeners to selected objects
m_ImageObserverTag = m_SelectedImage->AddObserver(
itk::ModifiedEvent(), changeListener );
m_Controls->m_SimilarAnglesFrame->setVisible(false);
m_Controls->m_SimilarAnglesLabel->setVisible(false);
m_Controls->m_SelectedImageLabel->setText( m_SelectedImageNodes->GetNode()->GetName().c_str() );
}
}
//planar
if(isPlanar)
{
if(selectedPlanar != m_SelectedPlanarFigure.GetPointer())
{
MITK_DEBUG << "Planar selection changed";
somethingChanged = true;
// Possibly previous change listeners
if ( (m_SelectedPlanarFigure.IsNotNull()) && (m_PlanarFigureObserverTag >= 0) )
{
m_SelectedPlanarFigure->RemoveObserver( m_PlanarFigureObserverTag );
m_PlanarFigureObserverTag = -1;
}
if ( (m_SelectedPlanarFigure.IsNotNull()) && (m_InitializedObserverTag >= 0) )
{
m_SelectedPlanarFigure->RemoveObserver( m_InitializedObserverTag );
m_InitializedObserverTag = -1;
}
m_SelectedPlanarFigure = selectedPlanar;
*m_SelectedPlanarFigureNodes = node;
m_CurrentFigureNodeInitialized = selectedPlanar->IsPlaced();
m_SelectedMaskNode = NULL;
m_SelectedImageMask = NULL;
m_PlanarFigureObserverTag = m_SelectedPlanarFigure->AddObserver(
mitk::EndInteractionPlanarFigureEvent(), changeListener );
if(!m_CurrentFigureNodeInitialized)
{
typedef itk::SimpleMemberCommand< QmitkPartialVolumeAnalysisView > ITKCommandType;
ITKCommandType::Pointer initializationCommand;
initializationCommand = ITKCommandType::New();
// set the callback function of the member command
initializationCommand->SetCallbackFunction( this, &QmitkPartialVolumeAnalysisView::PlanarFigureInitialized );
// add an observer
m_InitializedObserverTag = selectedPlanar->AddObserver( mitk::EndPlacementPlanarFigureEvent(), initializationCommand );
}
m_Controls->m_SelectedMaskLabel->setText( m_SelectedPlanarFigureNodes->GetNode()->GetName().c_str() );
PlanarFigureFocus(node);
}
}
//mask
this->m_Controls->m_EstimateCircle->setEnabled(isMask && selectedImage->GetDimension()==3);
if(isMask && selectedImage->GetDimension()==3)
{
if(selectedImage != m_SelectedImage.GetPointer())
{
somethingChanged = true;
if ( (m_SelectedImageMask.IsNotNull()) && (m_ImageMaskObserverTag >= 0) )
{
m_SelectedImageMask->RemoveObserver( m_ImageMaskObserverTag );
m_ImageMaskObserverTag = -1;
}
m_SelectedMaskNode = node;
m_SelectedImageMask = selectedImage;
m_SelectedPlanarFigure = NULL;
m_SelectedPlanarFigureNodes->RemoveAllNodes();
m_ImageMaskObserverTag = m_SelectedImageMask->AddObserver(
itk::ModifiedEvent(), changeListener );
m_Controls->m_SelectedMaskLabel->setText( m_SelectedMaskNode->GetName().c_str() );
}
}
//tensor image
if(isTensorImage && selectedTensorImage->GetDimension()==3)
{
if(selectedImage != m_SelectedImage.GetPointer())
{
somethingChanged = true;
if ( (m_SelectedImage.IsNotNull()) && (m_ImageObserverTag >= 0) )
{
m_SelectedImage->RemoveObserver( m_ImageObserverTag );
m_ImageObserverTag = -1;
}
*m_SelectedImageNodes = node;
m_SelectedImage = selectedImage;
m_IsTensorImage = true;
ExtractTensorImages(selectedImage);
// Add change listeners to selected objects
m_ImageObserverTag = m_SelectedImage->AddObserver(
itk::ModifiedEvent(), changeListener );
m_Controls->m_SimilarAnglesFrame->setVisible(true);
m_Controls->m_SimilarAnglesLabel->setVisible(true);
m_Controls->m_SelectedImageLabel->setText( m_SelectedImageNodes->GetNode()->GetName().c_str() );
}
}
}
if(somethingChanged)
{
this->SetMeasurementInfoToRenderWindow("");
if(m_SelectedPlanarFigure.IsNull() && m_SelectedImageMask.IsNull() )
{
m_Controls->m_SelectedMaskLabel->setText("<font color='red'>mandatory</font>");
m_Controls->m_ResampleOptionsFrame->setEnabled(false);
m_Controls->m_HistogramWidget->setEnabled(false);
m_Controls->m_ClassSelector->setEnabled(false);
m_Controls->m_DisplayHistogramCheckbox->setEnabled(false);
m_Controls->m_AdvancedCheckbox->setEnabled(false);
m_Controls->frame_7->setEnabled(false);
}
else
{
m_Controls->m_ResampleOptionsFrame->setEnabled(true);
m_Controls->m_HistogramWidget->setEnabled(true);
m_Controls->m_ClassSelector->setEnabled(true);
m_Controls->m_DisplayHistogramCheckbox->setEnabled(true);
m_Controls->m_AdvancedCheckbox->setEnabled(true);
m_Controls->frame_7->setEnabled(true);
}
// Clear statistics / histogram GUI if nothing is selected
if ( m_SelectedImage.IsNull() )
{
m_Controls->m_PlanarFigureButtonsFrame->setEnabled(false);
m_Controls->m_OpacityFrame->setEnabled(false);
m_Controls->m_SelectedImageLabel->setText("<font color='red'>mandatory</font>");
}
else
{
m_Controls->m_PlanarFigureButtonsFrame->setEnabled(true);
m_Controls->m_OpacityFrame->setEnabled(true);
}
if( !m_Visible || m_SelectedImage.IsNull()
|| (m_SelectedPlanarFigure.IsNull() && m_SelectedImageMask.IsNull()) )
{
m_Controls->m_InputData->setTitle("Please Select Input Data");
m_Controls->m_HistogramWidget->ClearItemModel();
m_CurrentStatisticsValid = false;
}
else
{
m_Controls->m_InputData->setTitle("Input Data");
this->RequestStatisticsUpdate();
}
}
}
void QmitkPartialVolumeAnalysisView::ShowClusteringResults()
{
typedef itk::Image<unsigned char, 3> MaskImageType;
mitk::Image::Pointer mask = 0;
MaskImageType::Pointer itkmask = 0;
if(m_IsTensorImage && m_Controls->m_SimilarAnglesSlider->value() != 0)
{
typedef itk::Image<float, 3> AngularErrorImageType;
typedef mitk::ImageToItk<AngularErrorImageType> CastType;
CastType::Pointer caster = CastType::New();
caster->SetInput(m_AngularErrorImage);
caster->Update();
typedef itk::BinaryThresholdImageFilter< AngularErrorImageType, MaskImageType > ThreshType;
ThreshType::Pointer thresh = ThreshType::New();
thresh->SetUpperThreshold((90-m_Controls->m_SimilarAnglesSlider->value())*(PVA_PI/180.0));
thresh->SetInsideValue(1.0);
thresh->SetInput(caster->GetOutput());
thresh->Update();
itkmask = thresh->GetOutput();
mask = mitk::Image::New();
mask->InitializeByItk(itkmask.GetPointer());
mask->SetVolume(itkmask->GetBufferPointer());
// GetDefaultDataStorage()->Remove(m_newnode);
// m_newnode = mitk::DataNode::New();
// m_newnode->SetData(mask);
// m_newnode->SetName("masking node");
// m_newnode->SetIntProperty( "layer", 1002 );
// GetDefaultDataStorage()->Add(m_newnode, m_SelectedImageNodes->GetNode());
}
mitk::Image::Pointer clusteredImage;
ClusteringType::Pointer clusterer = ClusteringType::New();
if(m_QuantifyClass==3)
{
if(m_IsTensorImage)
{
double *green_fa, *green_rd, *green_ad, *green_md;
//double *greengray_fa, *greengray_rd, *greengray_ad, *greengray_md;
double *gray_fa, *gray_rd, *gray_ad, *gray_md;
//double *redgray_fa, *redgray_rd, *redgray_ad, *redgray_md;
double *red_fa, *red_rd, *red_ad, *red_md;
mitk::Image* tmpImg = m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(0);
mitk::Image::ConstPointer imgToCluster = tmpImg;
red_fa = clusterer->PerformQuantification(imgToCluster, m_CurrentRGBClusteringResults->rgbChannels->r, mask);
green_fa = clusterer->PerformQuantification(imgToCluster, m_CurrentRGBClusteringResults->rgbChannels->g, mask);
gray_fa = clusterer->PerformQuantification(imgToCluster, m_CurrentRGBClusteringResults->rgbChannels->b, mask);
tmpImg = m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(3);
mitk::Image::ConstPointer imgToCluster3 = tmpImg;
red_rd = clusterer->PerformQuantification(imgToCluster3, m_CurrentRGBClusteringResults->rgbChannels->r, mask);
green_rd = clusterer->PerformQuantification(imgToCluster3, m_CurrentRGBClusteringResults->rgbChannels->g, mask);
gray_rd = clusterer->PerformQuantification(imgToCluster3, m_CurrentRGBClusteringResults->rgbChannels->b, mask);
tmpImg = m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(4);
mitk::Image::ConstPointer imgToCluster4 = tmpImg;
red_ad = clusterer->PerformQuantification(imgToCluster4, m_CurrentRGBClusteringResults->rgbChannels->r, mask);
green_ad = clusterer->PerformQuantification(imgToCluster4, m_CurrentRGBClusteringResults->rgbChannels->g, mask);
gray_ad = clusterer->PerformQuantification(imgToCluster4, m_CurrentRGBClusteringResults->rgbChannels->b, mask);
tmpImg = m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(5);
mitk::Image::ConstPointer imgToCluster5 = tmpImg;
red_md = clusterer->PerformQuantification(imgToCluster5, m_CurrentRGBClusteringResults->rgbChannels->r, mask);
green_md = clusterer->PerformQuantification(imgToCluster5, m_CurrentRGBClusteringResults->rgbChannels->g, mask);
gray_md = clusterer->PerformQuantification(imgToCluster5, m_CurrentRGBClusteringResults->rgbChannels->b, mask);
// clipboard
QString clipboardText("FA\t%1\t%2\t\t%3\t%4\t\t%5\t%6\t");
clipboardText = clipboardText
.arg(red_fa[0]).arg(red_fa[1])
.arg(gray_fa[0]).arg(gray_fa[1])
.arg(green_fa[0]).arg(green_fa[1]);
QString clipboardText3("RD\t%1\t%2\t\t%3\t%4\t\t%5\t%6\t");
clipboardText3 = clipboardText3
.arg(red_rd[0]).arg(red_rd[1])
.arg(gray_rd[0]).arg(gray_rd[1])
.arg(green_rd[0]).arg(green_rd[1]);
QString clipboardText4("AD\t%1\t%2\t\t%3\t%4\t\t%5\t%6\t");
clipboardText4 = clipboardText4
.arg(red_ad[0]).arg(red_ad[1])
.arg(gray_ad[0]).arg(gray_ad[1])
.arg(green_ad[0]).arg(green_ad[1]);
QString clipboardText5("MD\t%1\t%2\t\t%3\t%4\t\t%5\t%6");
clipboardText5 = clipboardText5
.arg(red_md[0]).arg(red_md[1])
.arg(gray_md[0]).arg(gray_md[1])
.arg(green_md[0]).arg(green_md[1]);
QApplication::clipboard()->setText(clipboardText+clipboardText3+clipboardText4+clipboardText5, QClipboard::Clipboard);
// now paint infos also on renderwindow
QString plainInfoText("%1 %2 %3 \n");
plainInfoText = plainInfoText
.arg("Red ", 20)
.arg("Gray ", 20)
.arg("Green", 20);
QString plainInfoText0("FA:%1 ± %2%3 ± %4%5 ± %6\n");
plainInfoText0 = plainInfoText0
.arg(red_fa[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(red_fa[1], -10, 'g', 2, QLatin1Char( ' ' ))
.arg(gray_fa[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(gray_fa[1], -10, 'g', 2, QLatin1Char( ' ' ))
.arg(green_fa[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(green_fa[1], -10, 'g', 2, QLatin1Char( ' ' ));
QString plainInfoText3("RDx10³:%1 ± %2%3 ± %4%5 ± %6\n");
plainInfoText3 = plainInfoText3
.arg(1000.0 * red_rd[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * red_rd[1], -10, 'g', 2, QLatin1Char( ' ' ))
.arg(1000.0 * gray_rd[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * gray_rd[1], -10, 'g', 2, QLatin1Char( ' ' ))
.arg(1000.0 * green_rd[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * green_rd[1], -10, 'g', 2, QLatin1Char( ' ' ));
QString plainInfoText4("ADx10³:%1 ± %2%3 ± %4%5 ± %6\n");
plainInfoText4 = plainInfoText4
.arg(1000.0 * red_ad[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * red_ad[1], -10, 'g', 2, QLatin1Char( ' ' ))
.arg(1000.0 * gray_ad[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * gray_ad[1], -10, 'g', 2, QLatin1Char( ' ' ))
.arg(1000.0 * green_ad[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * green_ad[1], -10, 'g', 2, QLatin1Char( ' ' ));
QString plainInfoText5("MDx10³:%1 ± %2%3 ± %4%5 ± %6");
plainInfoText5 = plainInfoText5
.arg(1000.0 * red_md[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * red_md[1], -10, 'g', 2, QLatin1Char( ' ' ))
.arg(1000.0 * gray_md[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * gray_md[1], -10, 'g', 2, QLatin1Char( ' ' ))
.arg(1000.0 * green_md[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * green_md[1], -10, 'g', 2, QLatin1Char( ' ' ));
this->SetMeasurementInfoToRenderWindow(plainInfoText+plainInfoText0+plainInfoText3+plainInfoText4+plainInfoText5);
}
else
{
double* green;
double* gray;
double* red;
mitk::Image* tmpImg = m_CurrentStatisticsCalculator->GetInternalImage();
mitk::Image::ConstPointer imgToCluster = tmpImg;
red = clusterer->PerformQuantification(imgToCluster, m_CurrentRGBClusteringResults->rgbChannels->r);
green = clusterer->PerformQuantification(imgToCluster, m_CurrentRGBClusteringResults->rgbChannels->g);
gray = clusterer->PerformQuantification(imgToCluster, m_CurrentRGBClusteringResults->rgbChannels->b);
// clipboard
QString clipboardText("%1\t%2\t\t%3\t%4\t\t%5\t%6");
clipboardText = clipboardText.arg(red[0]).arg(red[1])
.arg(gray[0]).arg(gray[1])
.arg(green[0]).arg(green[1]);
QApplication::clipboard()->setText(clipboardText, QClipboard::Clipboard);
// now paint infos also on renderwindow
QString plainInfoText("Red: %1 ± %2\nGray: %3 ± %4\nGreen: %5 ± %6");
plainInfoText = plainInfoText.arg(red[0]).arg(red[1])
.arg(gray[0]).arg(gray[1])
.arg(green[0]).arg(green[1]);
this->SetMeasurementInfoToRenderWindow(plainInfoText);
}
clusteredImage = m_CurrentRGBClusteringResults->rgb;
}
else
{
if(m_IsTensorImage)
{
double *red_fa, *red_rd, *red_ad, *red_md;
mitk::Image* tmpImg = m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(0);
mitk::Image::ConstPointer imgToCluster = tmpImg;
red_fa = clusterer->PerformQuantification(imgToCluster, m_CurrentPerformClusteringResults->clusteredImage, mask);
tmpImg = m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(3);
mitk::Image::ConstPointer imgToCluster3 = tmpImg;
red_rd = clusterer->PerformQuantification(imgToCluster3, m_CurrentPerformClusteringResults->clusteredImage, mask);
tmpImg = m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(4);
mitk::Image::ConstPointer imgToCluster4 = tmpImg;
red_ad = clusterer->PerformQuantification(imgToCluster4, m_CurrentPerformClusteringResults->clusteredImage, mask);
tmpImg = m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(5);
mitk::Image::ConstPointer imgToCluster5 = tmpImg;
red_md = clusterer->PerformQuantification(imgToCluster5, m_CurrentPerformClusteringResults->clusteredImage, mask);
// clipboard
QString clipboardText("FA\t%1\t%2\t");
clipboardText = clipboardText
.arg(red_fa[0]).arg(red_fa[1]);
QString clipboardText3("RD\t%1\t%2\t");
clipboardText3 = clipboardText3
.arg(red_rd[0]).arg(red_rd[1]);
QString clipboardText4("AD\t%1\t%2\t");
clipboardText4 = clipboardText4
.arg(red_ad[0]).arg(red_ad[1]);
QString clipboardText5("MD\t%1\t%2\t");
clipboardText5 = clipboardText5
.arg(red_md[0]).arg(red_md[1]);
QApplication::clipboard()->setText(clipboardText+clipboardText3+clipboardText4+clipboardText5, QClipboard::Clipboard);
// now paint infos also on renderwindow
QString plainInfoText("%1 \n");
plainInfoText = plainInfoText
.arg("Red ", 20);
QString plainInfoText0("FA:%1 ± %2\n");
plainInfoText0 = plainInfoText0
.arg(red_fa[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(red_fa[1], -10, 'g', 2, QLatin1Char( ' ' ));
QString plainInfoText3("RDx10³:%1 ± %2\n");
plainInfoText3 = plainInfoText3
.arg(1000.0 * red_rd[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * red_rd[1], -10, 'g', 2, QLatin1Char( ' ' ));
QString plainInfoText4("ADx10³:%1 ± %2\n");
plainInfoText4 = plainInfoText4
.arg(1000.0 * red_ad[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * red_ad[1], -10, 'g', 2, QLatin1Char( ' ' ));
QString plainInfoText5("MDx10³:%1 ± %2");
plainInfoText5 = plainInfoText5
.arg(1000.0 * red_md[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * red_md[1], -10, 'g', 2, QLatin1Char( ' ' ));
this->SetMeasurementInfoToRenderWindow(plainInfoText+plainInfoText0+plainInfoText3+plainInfoText4+plainInfoText5);
}
else
{
double* quant;
mitk::Image* tmpImg = m_CurrentStatisticsCalculator->GetInternalImage();
mitk::Image::ConstPointer imgToCluster = tmpImg;
quant = clusterer->PerformQuantification(imgToCluster, m_CurrentPerformClusteringResults->clusteredImage);
// clipboard
QString clipboardText("%1\t%2");
clipboardText = clipboardText.arg(quant[0]).arg(quant[1]);
QApplication::clipboard()->setText(clipboardText, QClipboard::Clipboard);
// now paint infos also on renderwindow
QString plainInfoText("Measurement: %1 ± %2");
plainInfoText = plainInfoText.arg(quant[0]).arg(quant[1]);
this->SetMeasurementInfoToRenderWindow(plainInfoText);
}
clusteredImage = m_CurrentPerformClusteringResults->displayImage;
}
if(mask.IsNotNull())
{
typedef itk::Image<itk::RGBAPixel<unsigned char>,3> RGBImageType;
typedef mitk::ImageToItk<RGBImageType> ClusterCasterType;
ClusterCasterType::Pointer clCaster = ClusterCasterType::New();
clCaster->SetInput(clusteredImage);
clCaster->Update();
clCaster->GetOutput();
typedef itk::MaskImageFilter< RGBImageType, MaskImageType, RGBImageType > MaskType;
MaskType::Pointer masker = MaskType::New();
masker->SetInput1(clCaster->GetOutput());
masker->SetInput2(itkmask);
masker->Update();
clusteredImage = mitk::Image::New();
clusteredImage->InitializeByItk(masker->GetOutput());
clusteredImage->SetVolume(masker->GetOutput()->GetBufferPointer());
}
if(m_ClusteringResult.IsNotNull())
{
this->GetDataStorage()->Remove(m_ClusteringResult);
}
m_ClusteringResult = mitk::DataNode::New();
m_ClusteringResult->SetBoolProperty("helper object", true);
m_ClusteringResult->SetIntProperty( "layer", 1000 );
m_ClusteringResult->SetBoolProperty("texture interpolation", m_TexIsOn);
m_ClusteringResult->SetData(clusteredImage);
m_ClusteringResult->SetName("Clusterprobs");
this->GetDataStorage()->Add(m_ClusteringResult, m_SelectedImageNodes->GetNode());
if(m_SelectedPlanarFigure.IsNotNull() && m_SelectedPlanarFigureNodes->GetNode().IsNotNull())
{
m_SelectedPlanarFigureNodes->GetNode()->SetIntProperty( "layer", 1001 );
}
this->RequestRenderWindowUpdate();
}
void QmitkPartialVolumeAnalysisView::UpdateStatistics()
{
if(!m_CurrentFigureNodeInitialized && m_SelectedPlanarFigure.IsNotNull())
{
MITK_DEBUG << "Selected planar figure not initialized. No stats calculation performed.";
return;
}
// Remove any cached images that are no longer referenced elsewhere
this->RemoveOrphanImages();
QmitkStdMultiWidget *multiWidget = 0;
QmitkStdMultiWidgetEditor * multiWidgetEdit = 0;
multiWidgetEdit = dynamic_cast<QmitkStdMultiWidgetEditor *>(this->GetRenderWindowPart());
if(multiWidgetEdit){
multiWidget = multiWidgetEdit->GetStdMultiWidget();
}
if ( multiWidget == NULL )
{
return;
}
if ( m_SelectedImage.IsNotNull() )
{
// Check if a the selected image is a multi-channel image. If yes, statistics
// cannot be calculated currently.
if ( !m_IsTensorImage && m_SelectedImage->GetPixelType().GetNumberOfComponents() > 1 )
{
QMessageBox::information( NULL, "Warning", "Non-tensor multi-component images not supported.");
m_Controls->m_HistogramWidget->ClearItemModel();
m_CurrentStatisticsValid = false;
return;
}
m_CurrentStatisticsCalculator = NULL;
if(!m_IsTensorImage)
{
// Retrieve HistogramStatisticsCalculator from has map (or create a new one
// for this image if non-existant)
PartialVolumeAnalysisMapType::iterator it =
m_PartialVolumeAnalysisMap.find( m_SelectedImage );
if ( it != m_PartialVolumeAnalysisMap.end() )
{
m_CurrentStatisticsCalculator = it->second;
}
}
if(m_CurrentStatisticsCalculator.IsNull())
{
m_CurrentStatisticsCalculator = mitk::PartialVolumeAnalysisHistogramCalculator::New();
m_CurrentStatisticsCalculator->SetPlanarFigureThickness(m_Controls->m_PlanarFiguresThickness->value());
if(m_IsTensorImage)
{
m_CurrentStatisticsCalculator->SetImage( m_CAImage );
m_CurrentStatisticsCalculator->AddAdditionalResamplingImage( m_FAImage );
m_CurrentStatisticsCalculator->AddAdditionalResamplingImage( m_DirectionComp1Image );
m_CurrentStatisticsCalculator->AddAdditionalResamplingImage( m_DirectionComp2Image );
m_CurrentStatisticsCalculator->AddAdditionalResamplingImage( m_RDImage );
m_CurrentStatisticsCalculator->AddAdditionalResamplingImage( m_ADImage );
m_CurrentStatisticsCalculator->AddAdditionalResamplingImage( m_MDImage );
}
else
{
m_CurrentStatisticsCalculator->SetImage( m_SelectedImage );
}
m_PartialVolumeAnalysisMap[m_SelectedImage] = m_CurrentStatisticsCalculator;
MITK_DEBUG << "Creating StatisticsCalculator";
}
std::string maskName;
std::string maskType;
unsigned int maskDimension;
if ( m_SelectedImageMask.IsNotNull() )
{
mitk::PixelType pixelType = m_SelectedImageMask->GetPixelType();
MITK_DEBUG << pixelType.GetPixelTypeAsString();
if(pixelType.GetComponentTypeAsString() == "char")
{
MITK_DEBUG << "Pixel type is char instead of uchar";
return;
}
if(pixelType.GetBitsPerComponent() == 16)
{
//convert from short to uchar
typedef itk::Image<short, 3> ShortImageType;
typedef itk::Image<unsigned char, 3> CharImageType;
CharImageType::Pointer charImage;
ShortImageType::Pointer shortImage;
mitk::CastToItkImage(m_SelectedImageMask, shortImage);
typedef itk::CastImageFilter<ShortImageType, CharImageType> ImageCasterType;
ImageCasterType::Pointer caster = ImageCasterType::New();
caster->SetInput( shortImage );
caster->Update();
charImage = caster->GetOutput();
mitk::CastToMitkImage(charImage, m_SelectedImageMask);
}
m_CurrentStatisticsCalculator->SetImageMask( m_SelectedImageMask );
m_CurrentStatisticsCalculator->SetMaskingModeToImage();
maskName = m_SelectedMaskNode->GetName();
maskType = m_SelectedImageMask->GetNameOfClass();
maskDimension = 3;
std::stringstream maskLabel;
maskLabel << maskName;
if ( maskDimension > 0 )
{
maskLabel << " [" << maskDimension << "D " << maskType << "]";
}
m_Controls->m_SelectedMaskLabel->setText( maskLabel.str().c_str() );
}
else if ( m_SelectedPlanarFigure.IsNotNull() && m_SelectedPlanarFigureNodes->GetNode().IsNotNull())
{
m_CurrentStatisticsCalculator->SetPlanarFigure( m_SelectedPlanarFigure );
m_CurrentStatisticsCalculator->SetMaskingModeToPlanarFigure();
maskName = m_SelectedPlanarFigureNodes->GetNode()->GetName();
maskType = m_SelectedPlanarFigure->GetNameOfClass();
maskDimension = 2;
}
else
{
m_CurrentStatisticsCalculator->SetMaskingModeToNone();
maskName = "-";
maskType = "";
maskDimension = 0;
}
bool statisticsChanged = false;
bool statisticsCalculationSuccessful = false;
// Initialize progress bar
mitk::ProgressBar::GetInstance()->AddStepsToDo( 100 );
// Install listener for progress events and initialize progress bar
typedef itk::SimpleMemberCommand< QmitkPartialVolumeAnalysisView > ITKCommandType;
ITKCommandType::Pointer progressListener;
progressListener = ITKCommandType::New();
progressListener->SetCallbackFunction( this, &QmitkPartialVolumeAnalysisView::UpdateProgressBar );
unsigned long progressObserverTag = m_CurrentStatisticsCalculator
->AddObserver( itk::ProgressEvent(), progressListener );
ClusteringType::ParamsType *cparams = 0;
ClusteringType::ClusterResultType *cresult = 0;
ClusteringType::HistType *chist = 0;
try
{
m_CurrentStatisticsCalculator->SetNumberOfBins(m_Controls->m_NumberBins->text().toInt());
m_CurrentStatisticsCalculator->SetUpsamplingFactor(m_Controls->m_Upsampling->text().toDouble());
m_CurrentStatisticsCalculator->SetGaussianSigma(m_Controls->m_GaussianSigma->text().toDouble());
// Compute statistics
statisticsChanged =
m_CurrentStatisticsCalculator->ComputeStatistics( );
mitk::Image* tmpImg = m_CurrentStatisticsCalculator->GetInternalImage();
mitk::Image::ConstPointer imgToCluster = tmpImg;
if(imgToCluster.IsNotNull())
{
// perform clustering
const HistogramType *histogram = m_CurrentStatisticsCalculator->GetHistogram( );
if(histogram != NULL)
{
ClusteringType::Pointer clusterer = ClusteringType::New();
clusterer->SetStepsNumIntegration(200);
clusterer->SetMaxIt(1000);
mitk::Image::Pointer pFiberImg;
if(m_QuantifyClass==3)
{
if(m_Controls->m_Quantiles->isChecked())
{
m_CurrentRGBClusteringResults = clusterer->PerformRGBQuantiles(imgToCluster, histogram, m_Controls->m_q1->value(),m_Controls->m_q2->value());
}
else
{
m_CurrentRGBClusteringResults = clusterer->PerformRGBClustering(imgToCluster, histogram);
}
pFiberImg = m_CurrentRGBClusteringResults->rgbChannels->r;
cparams = m_CurrentRGBClusteringResults->params;
cresult = m_CurrentRGBClusteringResults->result;
chist = m_CurrentRGBClusteringResults->hist;
}
else
{
if(m_Controls->m_Quantiles->isChecked())
{
m_CurrentPerformClusteringResults =
clusterer->PerformQuantiles(imgToCluster, histogram, m_Controls->m_q1->value(),m_Controls->m_q2->value());
}
else
{
m_CurrentPerformClusteringResults =
clusterer->PerformClustering(imgToCluster, histogram, m_QuantifyClass);
}
pFiberImg = m_CurrentPerformClusteringResults->clusteredImage;
cparams = m_CurrentPerformClusteringResults->params;
cresult = m_CurrentPerformClusteringResults->result;
chist = m_CurrentPerformClusteringResults->hist;
}
if(m_IsTensorImage)
{
m_AngularErrorImage = clusterer->CaculateAngularErrorImage(
m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(1),
m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(2),
pFiberImg);
// GetDefaultDataStorage()->Remove(m_newnode2);
// m_newnode2 = mitk::DataNode::New();
// m_newnode2->SetData(m_AngularErrorImage);
// m_newnode2->SetName(("AngularError"));
// m_newnode2->SetIntProperty( "layer", 1003 );
// GetDefaultDataStorage()->Add(m_newnode2, m_SelectedImageNodes->GetNode());
// newnode = mitk::DataNode::New();
// newnode->SetData(m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(1));
// newnode->SetName(("Comp1"));
// GetDefaultDataStorage()->Add(newnode, m_SelectedImageNodes->GetNode());
// newnode = mitk::DataNode::New();
// newnode->SetData(m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(2));
// newnode->SetName(("Comp2"));
// GetDefaultDataStorage()->Add(newnode, m_SelectedImageNodes->GetNode());
}
ShowClusteringResults();
}
}
statisticsCalculationSuccessful = true;
}
catch ( const std::runtime_error &e )
{
QMessageBox::information( NULL, "Warning", e.what());
}
catch ( const std::exception &e )
{
MITK_ERROR << "Caught exception: " << e.what();
QMessageBox::information( NULL, "Warning", e.what());
}
m_CurrentStatisticsCalculator->RemoveObserver( progressObserverTag );
// Make sure that progress bar closes
mitk::ProgressBar::GetInstance()->Progress( 100 );
if ( statisticsCalculationSuccessful )
{
if ( statisticsChanged )
{
// Do not show any error messages
m_CurrentStatisticsValid = true;
}
// m_Controls->m_HistogramWidget->SetHistogramModeToDirectHistogram();
m_Controls->m_HistogramWidget->SetParameters(
cparams, cresult, chist );
// m_Controls->m_HistogramWidget->UpdateItemModelFromHistogram();
}
else
{
m_Controls->m_SelectedMaskLabel->setText("<font color='red'>mandatory</font>");
// Clear statistics and histogram
m_Controls->m_HistogramWidget->ClearItemModel();
m_CurrentStatisticsValid = false;
// If a (non-closed) PlanarFigure is selected, display a line profile widget
if ( m_SelectedPlanarFigure.IsNotNull() )
{
// TODO: enable line profile widget
//m_Controls->m_StatisticsWidgetStack->setCurrentIndex( 1 );
//m_Controls->m_LineProfileWidget->SetImage( m_SelectedImage );
//m_Controls->m_LineProfileWidget->SetPlanarFigure( m_SelectedPlanarFigure );
//m_Controls->m_LineProfileWidget->UpdateItemModelFromPath();
}
}
}
}
void QmitkPartialVolumeAnalysisView::SetMeasurementInfoToRenderWindow(const QString& text)
{
FindRenderWindow(m_SelectedPlanarFigureNodes->GetNode());
if(m_LastRenderWindow != m_SelectedRenderWindow)
{
if(m_LastRenderWindow)
{
QObject::disconnect( m_LastRenderWindow, SIGNAL( destroyed(QObject*) )
, this, SLOT( OnRenderWindowDelete(QObject*) ) );
}
m_LastRenderWindow = m_SelectedRenderWindow;
if(m_LastRenderWindow)
{
QObject::connect( m_LastRenderWindow, SIGNAL( destroyed(QObject*) )
, this, SLOT( OnRenderWindowDelete(QObject*) ) );
}
}
if(m_LastRenderWindow && m_SelectedPlanarFigureNodes->GetNode().IsNotNull())
{
if (!text.isEmpty())
{
m_MeasurementInfoAnnotation->SetText(1, text.toLatin1().data());
mitk::VtkLayerController::GetInstance(m_LastRenderWindow->GetRenderWindow())->InsertForegroundRenderer(
m_MeasurementInfoRenderer, true);
}
else
{
if (mitk::VtkLayerController::GetInstance(
m_LastRenderWindow->GetRenderWindow()) ->IsRendererInserted(
m_MeasurementInfoRenderer))
mitk::VtkLayerController::GetInstance(m_LastRenderWindow->GetRenderWindow())->RemoveRenderer(
m_MeasurementInfoRenderer);
}
}
else
{
QmitkStdMultiWidget *multiWidget = 0;
QmitkStdMultiWidgetEditor * multiWidgetEdit = 0;
multiWidgetEdit = dynamic_cast<QmitkStdMultiWidgetEditor *>(this->GetRenderWindowPart());
if(multiWidgetEdit){
multiWidget = multiWidgetEdit->GetStdMultiWidget();
}
if ( multiWidget == NULL )
{
return;
}
if (!text.isEmpty())
{
m_MeasurementInfoAnnotation->SetText(1, text.toLatin1().data());
mitk::VtkLayerController::GetInstance(multiWidget->GetRenderWindow1()->GetRenderWindow())->InsertForegroundRenderer(
m_MeasurementInfoRenderer, true);
}
else
{
if (mitk::VtkLayerController::GetInstance(
multiWidget->GetRenderWindow1()->GetRenderWindow()) ->IsRendererInserted(
m_MeasurementInfoRenderer))
mitk::VtkLayerController::GetInstance(multiWidget->GetRenderWindow1()->GetRenderWindow())->RemoveRenderer(
m_MeasurementInfoRenderer);
}
}
}
void QmitkPartialVolumeAnalysisView::UpdateProgressBar()
{
mitk::ProgressBar::GetInstance()->Progress();
}
void QmitkPartialVolumeAnalysisView::RequestStatisticsUpdate()
{
if ( !m_StatisticsUpdatePending )
{
QApplication::postEvent( this, new QmitkRequestStatisticsUpdateEvent );
m_StatisticsUpdatePending = true;
}
}
void QmitkPartialVolumeAnalysisView::RemoveOrphanImages()
{
PartialVolumeAnalysisMapType::iterator it = m_PartialVolumeAnalysisMap.begin();
while ( it != m_PartialVolumeAnalysisMap.end() )
{
mitk::Image *image = it->first;
mitk::PartialVolumeAnalysisHistogramCalculator *calculator = it->second;
++it;
mitk::NodePredicateData::Pointer hasImage = mitk::NodePredicateData::New( image );
if ( this->GetDataStorage()->GetNode( hasImage ) == NULL )
{
if ( m_SelectedImage == image )
{
m_SelectedImage = NULL;
m_SelectedImageNodes->RemoveAllNodes();
}
if ( m_CurrentStatisticsCalculator == calculator )
{
m_CurrentStatisticsCalculator = NULL;
}
m_PartialVolumeAnalysisMap.erase( image );
it = m_PartialVolumeAnalysisMap.begin();
}
}
}
void QmitkPartialVolumeAnalysisView::ExtractTensorImages(
mitk::Image::Pointer tensorimage)
{
typedef itk::Image< itk::DiffusionTensor3D<float>, 3> TensorImageType;
typedef mitk::ImageToItk<TensorImageType> CastType;
CastType::Pointer caster = CastType::New();
caster->SetInput(tensorimage);
caster->Update();
TensorImageType::Pointer image = caster->GetOutput();
typedef itk::TensorDerivedMeasurementsFilter<float> MeasurementsType;
MeasurementsType::Pointer measurementsCalculator = MeasurementsType::New();
measurementsCalculator->SetInput(image );
measurementsCalculator->SetMeasure(MeasurementsType::FA);
measurementsCalculator->Update();
MeasurementsType::OutputImageType::Pointer fa = measurementsCalculator->GetOutput();
m_FAImage = mitk::Image::New();
m_FAImage->InitializeByItk(fa.GetPointer());
m_FAImage->SetVolume(fa->GetBufferPointer());
// mitk::DataNode::Pointer node = mitk::DataNode::New();
// node->SetData(m_FAImage);
// GetDefaultDataStorage()->Add(node);
measurementsCalculator = MeasurementsType::New();
measurementsCalculator->SetInput(image );
measurementsCalculator->SetMeasure(MeasurementsType::CA);
measurementsCalculator->Update();
MeasurementsType::OutputImageType::Pointer ca = measurementsCalculator->GetOutput();
m_CAImage = mitk::Image::New();
m_CAImage->InitializeByItk(ca.GetPointer());
m_CAImage->SetVolume(ca->GetBufferPointer());
// node = mitk::DataNode::New();
// node->SetData(m_CAImage);
// GetDefaultDataStorage()->Add(node);
measurementsCalculator = MeasurementsType::New();
measurementsCalculator->SetInput(image );
measurementsCalculator->SetMeasure(MeasurementsType::RD);
measurementsCalculator->Update();
MeasurementsType::OutputImageType::Pointer rd = measurementsCalculator->GetOutput();
m_RDImage = mitk::Image::New();
m_RDImage->InitializeByItk(rd.GetPointer());
m_RDImage->SetVolume(rd->GetBufferPointer());
// node = mitk::DataNode::New();
// node->SetData(m_CAImage);
// GetDefaultDataStorage()->Add(node);
measurementsCalculator = MeasurementsType::New();
measurementsCalculator->SetInput(image );
measurementsCalculator->SetMeasure(MeasurementsType::AD);
measurementsCalculator->Update();
MeasurementsType::OutputImageType::Pointer ad = measurementsCalculator->GetOutput();
m_ADImage = mitk::Image::New();
m_ADImage->InitializeByItk(ad.GetPointer());
m_ADImage->SetVolume(ad->GetBufferPointer());
// node = mitk::DataNode::New();
// node->SetData(m_CAImage);
// GetDefaultDataStorage()->Add(node);
measurementsCalculator = MeasurementsType::New();
measurementsCalculator->SetInput(image );
measurementsCalculator->SetMeasure(MeasurementsType::RA);
measurementsCalculator->Update();
MeasurementsType::OutputImageType::Pointer md = measurementsCalculator->GetOutput();
m_MDImage = mitk::Image::New();
m_MDImage->InitializeByItk(md.GetPointer());
m_MDImage->SetVolume(md->GetBufferPointer());
// node = mitk::DataNode::New();
// node->SetData(m_CAImage);
// GetDefaultDataStorage()->Add(node);
typedef DirectionsFilterType::OutputImageType DirImageType;
DirectionsFilterType::Pointer dirFilter = DirectionsFilterType::New();
dirFilter->SetInput(image );
dirFilter->Update();
itk::ImageRegionIterator<DirImageType>
itd(dirFilter->GetOutput(), dirFilter->GetOutput()->GetLargestPossibleRegion());
itd = itd.Begin();
while( !itd.IsAtEnd() )
{
DirImageType::PixelType direction = itd.Get();
direction[0] = fabs(direction[0]);
direction[1] = fabs(direction[1]);
direction[2] = fabs(direction[2]);
itd.Set(direction);
++itd;
}
typedef itk::CartesianToPolarVectorImageFilter<
DirImageType, DirImageType, true> C2PFilterType;
C2PFilterType::Pointer cpFilter = C2PFilterType::New();
cpFilter->SetInput(dirFilter->GetOutput());
cpFilter->Update();
DirImageType::Pointer dir = cpFilter->GetOutput();
typedef itk::Image<float, 3> CompImageType;
CompImageType::Pointer comp1 = CompImageType::New();
comp1->SetSpacing( dir->GetSpacing() ); // Set the image spacing
comp1->SetOrigin( dir->GetOrigin() ); // Set the image origin
comp1->SetDirection( dir->GetDirection() ); // Set the image direction
comp1->SetRegions( dir->GetLargestPossibleRegion() );
comp1->Allocate();
CompImageType::Pointer comp2 = CompImageType::New();
comp2->SetSpacing( dir->GetSpacing() ); // Set the image spacing
comp2->SetOrigin( dir->GetOrigin() ); // Set the image origin
comp2->SetDirection( dir->GetDirection() ); // Set the image direction
comp2->SetRegions( dir->GetLargestPossibleRegion() );
comp2->Allocate();
itk::ImageRegionConstIterator<DirImageType>
it(dir, dir->GetLargestPossibleRegion());
itk::ImageRegionIterator<CompImageType>
it1(comp1, comp1->GetLargestPossibleRegion());
itk::ImageRegionIterator<CompImageType>
it2(comp2, comp2->GetLargestPossibleRegion());
it = it.Begin();
it1 = it1.Begin();
it2 = it2.Begin();
while( !it.IsAtEnd() )
{
it1.Set(it.Get()[1]);
it2.Set(it.Get()[2]);
++it;
++it1;
++it2;
}
m_DirectionComp1Image = mitk::Image::New();
m_DirectionComp1Image->InitializeByItk(comp1.GetPointer());
m_DirectionComp1Image->SetVolume(comp1->GetBufferPointer());
m_DirectionComp2Image = mitk::Image::New();
m_DirectionComp2Image->InitializeByItk(comp2.GetPointer());
m_DirectionComp2Image->SetVolume(comp2->GetBufferPointer());
}
void QmitkPartialVolumeAnalysisView::OnRenderWindowDelete(QObject * obj)
{
if(obj == m_LastRenderWindow)
m_LastRenderWindow = 0;
if(obj == m_SelectedRenderWindow)
m_SelectedRenderWindow = 0;
}
bool QmitkPartialVolumeAnalysisView::event( QEvent *event )
{
if ( event->type() == (QEvent::Type) QmitkRequestStatisticsUpdateEvent::StatisticsUpdateRequest )
{
// Update statistics
m_StatisticsUpdatePending = false;
this->UpdateStatistics();
return true;
}
return false;
}
bool QmitkPartialVolumeAnalysisView::IsExclusiveFunctionality() const
{
return true;
}
void QmitkPartialVolumeAnalysisView::Activated()
{
mitk::DataStorage::SetOfObjects::ConstPointer _NodeSet = this->GetDataStorage()->GetAll();
mitk::DataNode* node = 0;
mitk::PlanarFigure* figure = 0;
mitk::PlanarFigureInteractor::Pointer figureInteractor = 0;
// finally add all nodes to the model
for(mitk::DataStorage::SetOfObjects::ConstIterator it=_NodeSet->Begin(); it!=_NodeSet->End()
; it++)
{
node = const_cast<mitk::DataNode*>(it->Value().GetPointer());
figure = dynamic_cast<mitk::PlanarFigure*>(node->GetData());
if(figure)
{
figureInteractor = dynamic_cast<mitk::PlanarFigureInteractor*>(node->GetDataInteractor().GetPointer());
if(figureInteractor.IsNull())
{
figureInteractor = mitk::PlanarFigureInteractor::New();
us::Module* planarFigureModule = us::ModuleRegistry::GetModule( "MitkPlanarFigure" );
figureInteractor->LoadStateMachine("PlanarFigureInteraction.xml", planarFigureModule );
figureInteractor->SetEventConfig( "PlanarFigureConfig.xml", planarFigureModule );
figureInteractor->SetDataNode( node );
}
}
}
}
void QmitkPartialVolumeAnalysisView::Deactivated()
{
}
void QmitkPartialVolumeAnalysisView::ActivatedZombieView(berry::IWorkbenchPartReference::Pointer reference)
{
this->SetMeasurementInfoToRenderWindow("");
mitk::DataStorage::SetOfObjects::ConstPointer _NodeSet = this->GetDataStorage()->GetAll();
mitk::DataNode* node = 0;
mitk::PlanarFigure* figure = 0;
mitk::PlanarFigureInteractor::Pointer figureInteractor = 0;
// finally add all nodes to the model
for(mitk::DataStorage::SetOfObjects::ConstIterator it=_NodeSet->Begin(); it!=_NodeSet->End()
; it++)
{
node = const_cast<mitk::DataNode*>(it->Value().GetPointer());
figure = dynamic_cast<mitk::PlanarFigure*>(node->GetData());
if(figure)
{
figureInteractor = dynamic_cast<mitk::PlanarFigureInteractor*>(node->GetDataInteractor().GetPointer());
if(figureInteractor)
figureInteractor->SetDataNode( NULL );
}
}
}
void QmitkPartialVolumeAnalysisView::Hidden()
{
if (m_ClusteringResult.IsNotNull())
{
this->GetDataStorage()->Remove(m_ClusteringResult);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
Select(NULL, true, true);
m_Visible = false;
}
void QmitkPartialVolumeAnalysisView::Visible()
{
m_Visible = true;
berry::IWorkbenchPart::Pointer bla;
if (!this->GetCurrentSelection().empty())
{
this->OnSelectionChanged(bla, this->GetCurrentSelection());
}
else
{
this->OnSelectionChanged(bla, this->GetDataManagerSelection());
}
}
void QmitkPartialVolumeAnalysisView::SetFocus()
{
}
void QmitkPartialVolumeAnalysisView::GreenRadio(bool checked)
{
if(checked)
{
m_Controls->m_PartialVolumeRadio->setChecked(false);
m_Controls->m_BlueRadio->setChecked(false);
m_Controls->m_AllRadio->setChecked(false);
m_Controls->m_ExportClusteringResultsButton->setEnabled(true);
}
m_QuantifyClass = 0;
RequestStatisticsUpdate();
}
void QmitkPartialVolumeAnalysisView::PartialVolumeRadio(bool checked)
{
if(checked)
{
m_Controls->m_GreenRadio->setChecked(false);
m_Controls->m_BlueRadio->setChecked(false);
m_Controls->m_AllRadio->setChecked(false);
m_Controls->m_ExportClusteringResultsButton->setEnabled(true);
}
m_QuantifyClass = 1;
RequestStatisticsUpdate();
}
void QmitkPartialVolumeAnalysisView::BlueRadio(bool checked)
{
if(checked)
{
m_Controls->m_PartialVolumeRadio->setChecked(false);
m_Controls->m_GreenRadio->setChecked(false);
m_Controls->m_AllRadio->setChecked(false);
m_Controls->m_ExportClusteringResultsButton->setEnabled(true);
}
m_QuantifyClass = 2;
RequestStatisticsUpdate();
}
void QmitkPartialVolumeAnalysisView::AllRadio(bool checked)
{
if(checked)
{
m_Controls->m_BlueRadio->setChecked(false);
m_Controls->m_PartialVolumeRadio->setChecked(false);
m_Controls->m_GreenRadio->setChecked(false);
m_Controls->m_ExportClusteringResultsButton->setEnabled(false);
}
m_QuantifyClass = 3;
RequestStatisticsUpdate();
}
void QmitkPartialVolumeAnalysisView::NumberBinsChangedSlider(int v )
{
m_Controls->m_NumberBins->setText(QString("%1").arg(m_Controls->m_NumberBinsSlider->value()*5.0));
}
void QmitkPartialVolumeAnalysisView::UpsamplingChangedSlider( int v)
{
m_Controls->m_Upsampling->setText(QString("%1").arg(m_Controls->m_UpsamplingSlider->value()/10.0));
}
void QmitkPartialVolumeAnalysisView::GaussianSigmaChangedSlider(int v )
{
m_Controls->m_GaussianSigma->setText(QString("%1").arg(m_Controls->m_GaussianSigmaSlider->value()/100.0));
}
void QmitkPartialVolumeAnalysisView::SimilarAnglesChangedSlider(int v )
{
m_Controls->m_SimilarAngles->setText(QString("%1°").arg(90-m_Controls->m_SimilarAnglesSlider->value()));
ShowClusteringResults();
}
void QmitkPartialVolumeAnalysisView::OpacityChangedSlider(int v )
{
if(m_SelectedImageNodes->GetNode().IsNotNull())
{
float opacImag = 1.0f-(v-5)/5.0f;
opacImag = opacImag < 0 ? 0 : opacImag;
m_SelectedImageNodes->GetNode()->SetFloatProperty("opacity", opacImag);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
if(m_ClusteringResult.IsNotNull())
{
float opacClust = v/5.0f;
opacClust = opacClust > 1 ? 1 : opacClust;
m_ClusteringResult->SetFloatProperty("opacity", opacClust);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
void QmitkPartialVolumeAnalysisView::NumberBinsReleasedSlider( )
{
RequestStatisticsUpdate();
}
void QmitkPartialVolumeAnalysisView::UpsamplingReleasedSlider( )
{
RequestStatisticsUpdate();
}
void QmitkPartialVolumeAnalysisView::GaussianSigmaReleasedSlider( )
{
RequestStatisticsUpdate();
}
void QmitkPartialVolumeAnalysisView::SimilarAnglesReleasedSlider( )
{
}
void QmitkPartialVolumeAnalysisView::ToClipBoard()
{
std::vector<std::vector<double>* > vals = m_Controls->m_HistogramWidget->m_Vals;
QString clipboardText;
for (std::vector<std::vector<double>* >::iterator it = vals.begin(); it
!= vals.end(); ++it)
{
for (std::vector<double>::iterator it2 = (**it).begin(); it2 != (**it).end(); ++it2)
{
clipboardText.append(QString("%1 \t").arg(*it2));
}
clipboardText.append(QString("\n"));
}
QApplication::clipboard()->setText(clipboardText, QClipboard::Clipboard);
}
void QmitkPartialVolumeAnalysisView::PropertyChanged(const mitk::DataNode* /*node*/, const mitk::BaseProperty* /*prop*/)
{
}
void QmitkPartialVolumeAnalysisView::NodeChanged(const mitk::DataNode* /*node*/)
{
}
void QmitkPartialVolumeAnalysisView::NodeRemoved(const mitk::DataNode* node)
{
if (dynamic_cast<mitk::PlanarFigure*>(node->GetData()))
this->GetDataStorage()->Remove(m_ClusteringResult);
if( node == m_SelectedPlanarFigureNodes->GetNode().GetPointer()
|| node == m_SelectedMaskNode.GetPointer() )
{
this->Select(NULL,true,false);
SetMeasurementInfoToRenderWindow("");
}
if( node == m_SelectedImageNodes->GetNode().GetPointer() )
{
this->Select(NULL,false,true);
SetMeasurementInfoToRenderWindow("");
}
}
void QmitkPartialVolumeAnalysisView::NodeAddedInDataStorage(const mitk::DataNode* node)
{
if(!m_Visible)
return;
mitk::DataNode* nonConstNode = const_cast<mitk::DataNode*>(node);
mitk::PlanarFigure* figure = dynamic_cast<mitk::PlanarFigure*>(nonConstNode->GetData());
if(figure)
{
// set interactor for new node (if not already set)
mitk::PlanarFigureInteractor::Pointer figureInteractor
= dynamic_cast<mitk::PlanarFigureInteractor*>(node->GetDataInteractor().GetPointer());
if(figureInteractor.IsNull())
{
figureInteractor = mitk::PlanarFigureInteractor::New();
us::Module* planarFigureModule = us::ModuleRegistry::GetModule( "MitkPlanarFigure" );
figureInteractor->LoadStateMachine("PlanarFigureInteraction.xml", planarFigureModule );
figureInteractor->SetEventConfig( "PlanarFigureConfig.xml", planarFigureModule );
figureInteractor->SetDataNode( nonConstNode );
}
// remove uninitialized old planars
if( m_SelectedPlanarFigureNodes->GetNode().IsNotNull() && m_CurrentFigureNodeInitialized == false )
{
mitk::Interactor::Pointer oldInteractor = m_SelectedPlanarFigureNodes->GetNode()->GetInteractor();
if(oldInteractor.IsNotNull())
mitk::GlobalInteraction::GetInstance()->RemoveInteractor(oldInteractor);
this->GetDataStorage()->Remove(m_SelectedPlanarFigureNodes->GetNode());
}
}
}
void QmitkPartialVolumeAnalysisView::TextIntON()
{
if(m_ClusteringResult.IsNotNull())
{
if(m_TexIsOn)
{
m_Controls->m_TextureIntON->setIcon(*m_IconTexOFF);
}
else
{
m_Controls->m_TextureIntON->setIcon(*m_IconTexON);
}
m_ClusteringResult->SetBoolProperty("texture interpolation", !m_TexIsOn);
m_TexIsOn = !m_TexIsOn;
this->RequestRenderWindowUpdate();
}
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingView.cpp
index 0ba1b2e187..dd47e50ae5 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingView.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingView.cpp
@@ -1,859 +1,859 @@
/*===================================================================
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.
===================================================================*/
//#define MBILOG_ENABLE_DEBUG
#include "QmitkPreprocessingView.h"
#include "mitkDiffusionImagingConfigure.h"
// qt includes
#include <QMessageBox>
// itk includes
#include "itkTimeProbe.h"
#include "itkB0ImageExtractionImageFilter.h"
#include "itkB0ImageExtractionToSeparateImageFilter.h"
#include "itkBrainMaskExtractionImageFilter.h"
#include "itkCastImageFilter.h"
#include "itkVectorContainer.h"
#include <itkElectrostaticRepulsionDiffusionGradientReductionFilter.h>
#include <itkMergeDiffusionImagesFilter.h>
#include <itkDwiGradientLengthCorrectionFilter.h>
// Multishell includes
#include <itkRadialMultishellToSingleshellImageFilter.h>
// Multishell Functors
#include <itkADCAverageFunctor.h>
#include <itkKurtosisFitFunctor.h>
#include <itkBiExpFitFunctor.h>
#include <itkADCFitFunctor.h>
// mitk includes
#include "QmitkDataStorageComboBox.h"
#include "QmitkStdMultiWidget.h"
#include "mitkProgressBar.h"
#include "mitkStatusBar.h"
#include "mitkNodePredicateDataType.h"
#include "mitkProperties.h"
#include "mitkVtkResliceInterpolationProperty.h"
#include "mitkLookupTable.h"
#include "mitkLookupTableProperty.h"
#include "mitkTransferFunction.h"
#include "mitkTransferFunctionProperty.h"
#include "mitkDataNodeObject.h"
#include "mitkOdfNormalizationMethodProperty.h"
#include "mitkOdfScaleByProperty.h"
#include <mitkPointSet.h>
#include <itkAdcImageFilter.h>
#include <QTableWidgetItem>
#include <QTableWidget>
const std::string QmitkPreprocessingView::VIEW_ID =
"org.mitk.views.preprocessing";
#define DI_INFO MITK_INFO("DiffusionImaging")
typedef float TTensorPixelType;
QmitkPreprocessingView::QmitkPreprocessingView()
: QmitkFunctionality(),
m_Controls(NULL),
m_MultiWidget(NULL),
m_DiffusionImage(NULL)
{
}
QmitkPreprocessingView::~QmitkPreprocessingView()
{
}
void QmitkPreprocessingView::CreateQtPartControl(QWidget *parent)
{
if (!m_Controls)
{
// create GUI widgets
m_Controls = new Ui::QmitkPreprocessingViewControls;
m_Controls->setupUi(parent);
this->CreateConnections();
m_Controls->m_MeasurementFrameTable->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
m_Controls->m_MeasurementFrameTable->verticalHeader()->setResizeMode(QHeaderView::Stretch);
}
}
void QmitkPreprocessingView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget)
{
m_MultiWidget = &stdMultiWidget;
}
void QmitkPreprocessingView::StdMultiWidgetNotAvailable()
{
m_MultiWidget = NULL;
}
void QmitkPreprocessingView::CreateConnections()
{
if ( m_Controls )
{
connect( (QObject*)(m_Controls->m_ButtonAverageGradients), SIGNAL(clicked()), this, SLOT(AverageGradients()) );
connect( (QObject*)(m_Controls->m_ButtonExtractB0), SIGNAL(clicked()), this, SLOT(ExtractB0()) );
connect( (QObject*)(m_Controls->m_ModifyMeasurementFrame), SIGNAL(clicked()), this, SLOT(DoApplyMesurementFrame()) );
connect( (QObject*)(m_Controls->m_ReduceGradientsButton), SIGNAL(clicked()), this, SLOT(DoReduceGradientDirections()) );
connect( (QObject*)(m_Controls->m_ShowGradientsButton), SIGNAL(clicked()), this, SLOT(DoShowGradientDirections()) );
connect( (QObject*)(m_Controls->m_MirrorGradientToHalfSphereButton), SIGNAL(clicked()), this, SLOT(DoHalfSphereGradientDirections()) );
connect( (QObject*)(m_Controls->m_MergeDwisButton), SIGNAL(clicked()), this, SLOT(MergeDwis()) );
connect( (QObject*)(m_Controls->m_AdcSignalAverage), SIGNAL(clicked()), this, SLOT(DoADCAverage()) );
//connect( (QObject*)(m_Controls->m_AdcSignalFit), SIGNAL(clicked()), this, SLOT(DoADCFit()) );
connect( (QObject*)(m_Controls->m_AkcSignalFit), SIGNAL(clicked()), this, SLOT(DoAKCFit()) );
connect( (QObject*)(m_Controls->m_BiExpSignalFit), SIGNAL(clicked()), this, SLOT(DoBiExpFit()) );
connect( (QObject*)(m_Controls->m_B_ValueMap_Rounder_SpinBox), SIGNAL(valueChanged(int)), this, SLOT(UpdateDwiBValueMapRounder(int)));
connect( (QObject*)(m_Controls->m_CreateLengthCorrectedDwi), SIGNAL(clicked()), this, SLOT(DoLengthCorrection()) );
connect( (QObject*)(m_Controls->m_CalcAdcButton), SIGNAL(clicked()), this, SLOT(DoAdcCalculation()) );
}
}
void QmitkPreprocessingView::DoLengthCorrection()
{
if (m_DiffusionImage.IsNull())
return;
typedef mitk::DiffusionImage<DiffusionPixelType> DiffusionImageType;
typedef itk::DwiGradientLengthCorrectionFilter FilterType;
FilterType::Pointer filter = FilterType::New();
filter->SetRoundingValue( m_Controls->m_B_ValueMap_Rounder_SpinBox->value());
filter->SetReferenceBValue(m_DiffusionImage->GetReferenceBValue());
filter->SetReferenceGradientDirectionContainer(m_DiffusionImage->GetDirections());
filter->Update();
DiffusionImageType::Pointer image = DiffusionImageType::New();
image->SetVectorImage( m_DiffusionImage->GetVectorImage());
image->SetReferenceBValue( filter->GetNewBValue() );
image->SetDirections( filter->GetOutputGradientDirectionContainer());
image->InitializeFromVectorImage();
mitk::DataNode::Pointer imageNode = mitk::DataNode::New();
imageNode->SetData( image );
QString name = m_SelectedDiffusionNodes.front()->GetName().c_str();
imageNode->SetName((name+"_rounded").toStdString().c_str());
GetDefaultDataStorage()->Add(imageNode);
}
void QmitkPreprocessingView::UpdateDwiBValueMapRounder(int i)
{
if (m_DiffusionImage.IsNull())
return;
//m_DiffusionImage->UpdateBValueMap();
UpdateBValueTableWidget(i);
}
void QmitkPreprocessingView::CallMultishellToSingleShellFilter(itk::DWIVoxelFunctor * functor, mitk::DiffusionImage<DiffusionPixelType>::Pointer ImPtr, QString imageName)
{
typedef itk::RadialMultishellToSingleshellImageFilter<DiffusionPixelType, DiffusionPixelType> FilterType;
// filter input parameter
const mitk::DiffusionImage<DiffusionPixelType>::BValueMap
&originalShellMap = ImPtr->GetBValueMap();
const mitk::DiffusionImage<DiffusionPixelType>::ImageType
*vectorImage = ImPtr->GetVectorImage();
const mitk::DiffusionImage<DiffusionPixelType>::GradientDirectionContainerType::Pointer
gradientContainer = ImPtr->GetDirections();
const unsigned int
&bValue = ImPtr->GetReferenceBValue();
mitk::DataNode::Pointer imageNode = 0;
// filter call
FilterType::Pointer filter = FilterType::New();
filter->SetInput(vectorImage);
filter->SetOriginalGradientDirections(gradientContainer);
filter->SetOriginalBValueMap(originalShellMap);
filter->SetOriginalBValue(bValue);
filter->SetFunctor(functor);
filter->Update();
// create new DWI image
mitk::DiffusionImage<DiffusionPixelType>::Pointer outImage = mitk::DiffusionImage<DiffusionPixelType>::New();
outImage->SetVectorImage( filter->GetOutput() );
outImage->SetReferenceBValue( m_Controls->m_targetBValueSpinBox->value() );
outImage->SetDirections( filter->GetTargetGradientDirections() );
outImage->InitializeFromVectorImage();
imageNode = mitk::DataNode::New();
imageNode->SetData( outImage );
imageNode->SetName(imageName.toStdString().c_str());
GetDefaultDataStorage()->Add(imageNode);
if(m_Controls->m_OutputRMSErrorImage->isChecked()){
// create new Error image
FilterType::ErrorImageType::Pointer errImage = filter->GetErrorImage();
mitk::Image::Pointer mitkErrImage = mitk::Image::New();
mitkErrImage->InitializeByItk<FilterType::ErrorImageType>(errImage);
mitkErrImage->SetVolume(errImage->GetBufferPointer());
imageNode = mitk::DataNode::New();
imageNode->SetData( mitkErrImage );
imageNode->SetName((imageName+"_Error").toStdString().c_str());
GetDefaultDataStorage()->Add(imageNode);
}
}
void QmitkPreprocessingView::DoBiExpFit()
{
itk::BiExpFitFunctor::Pointer functor = itk::BiExpFitFunctor::New();
for (unsigned int i=0; i<m_SelectedDiffusionNodes.size(); i++)
{
mitk::DiffusionImage<DiffusionPixelType>::Pointer inImage =
dynamic_cast< mitk::DiffusionImage<DiffusionPixelType>* >(m_SelectedDiffusionNodes.at(i)->GetData());
QString name(m_SelectedDiffusionNodes.at(i)->GetName().c_str());
const mitk::DiffusionImage<DiffusionPixelType>::BValueMap & originalShellMap = inImage->GetBValueMap();
mitk::DiffusionImage<DiffusionPixelType>::BValueMap::const_iterator it = originalShellMap.begin();
++it;/* skip b=0*/ unsigned int s = 0; /*shell index */
vnl_vector<double> bValueList(originalShellMap.size()-1);
while(it != originalShellMap.end())
bValueList.put(s++,(it++)->first);
const double targetBValue = m_Controls->m_targetBValueSpinBox->value();
functor->setListOfBValues(bValueList);
functor->setTargetBValue(targetBValue);
CallMultishellToSingleShellFilter(functor,inImage,name + "_BiExp");
}
}
void QmitkPreprocessingView::DoAKCFit()
{
itk::KurtosisFitFunctor::Pointer functor = itk::KurtosisFitFunctor::New();
for (unsigned int i=0; i<m_SelectedDiffusionNodes.size(); i++)
{
mitk::DiffusionImage<DiffusionPixelType>::Pointer inImage =
dynamic_cast< mitk::DiffusionImage<DiffusionPixelType>* >(m_SelectedDiffusionNodes.at(i)->GetData());
QString name(m_SelectedDiffusionNodes.at(i)->GetName().c_str());
const mitk::DiffusionImage<DiffusionPixelType>::BValueMap & originalShellMap = inImage->GetBValueMap();
mitk::DiffusionImage<DiffusionPixelType>::BValueMap::const_iterator it = originalShellMap.begin();
++it;/* skip b=0*/ unsigned int s = 0; /*shell index */
vnl_vector<double> bValueList(originalShellMap.size()-1);
while(it != originalShellMap.end())
bValueList.put(s++,(it++)->first);
const double targetBValue = m_Controls->m_targetBValueSpinBox->value();
functor->setListOfBValues(bValueList);
functor->setTargetBValue(targetBValue);
CallMultishellToSingleShellFilter(functor,inImage,name + "_AKC");
}
}
void QmitkPreprocessingView::DoADCFit()
{
// later
}
void QmitkPreprocessingView::DoADCAverage()
{
itk::ADCAverageFunctor::Pointer functor = itk::ADCAverageFunctor::New();
for (unsigned int i=0; i<m_SelectedDiffusionNodes.size(); i++)
{
mitk::DiffusionImage<DiffusionPixelType>::Pointer inImage =
dynamic_cast< mitk::DiffusionImage<DiffusionPixelType>* >(m_SelectedDiffusionNodes.at(i)->GetData());
QString name(m_SelectedDiffusionNodes.at(i)->GetName().c_str());
const mitk::DiffusionImage<DiffusionPixelType>::BValueMap & originalShellMap = inImage->GetBValueMap();
mitk::DiffusionImage<DiffusionPixelType>::BValueMap::const_iterator it = originalShellMap.begin();
++it;/* skip b=0*/ unsigned int s = 0; /*shell index */
vnl_vector<double> bValueList(originalShellMap.size()-1);
while(it != originalShellMap.end())
bValueList.put(s++,(it++)->first);
const double targetBValue = m_Controls->m_targetBValueSpinBox->value();
functor->setListOfBValues(bValueList);
functor->setTargetBValue(targetBValue);
CallMultishellToSingleShellFilter(functor,inImage,name + "_ADC");
}
}
void QmitkPreprocessingView::DoAdcCalculation()
{
if (m_DiffusionImage.IsNull())
return;
typedef mitk::DiffusionImage< DiffusionPixelType > DiffusionImageType;
typedef itk::AdcImageFilter< DiffusionPixelType, double > FilterType;
for (unsigned int i=0; i<m_SelectedDiffusionNodes.size(); i++)
{
DiffusionImageType::Pointer inImage = dynamic_cast< DiffusionImageType* >(m_SelectedDiffusionNodes.at(i)->GetData());
FilterType::Pointer filter = FilterType::New();
filter->SetInput(inImage->GetVectorImage());
filter->SetGradientDirections(inImage->GetDirections());
filter->SetB_value(inImage->GetReferenceBValue());
filter->Update();
mitk::Image::Pointer image = mitk::Image::New();
image->InitializeByItk( filter->GetOutput() );
image->SetVolume( filter->GetOutput()->GetBufferPointer() );
mitk::DataNode::Pointer imageNode = mitk::DataNode::New();
imageNode->SetData( image );
QString name = m_SelectedDiffusionNodes.at(i)->GetName().c_str();
imageNode->SetName((name+"_ADC").toStdString().c_str());
GetDefaultDataStorage()->Add(imageNode);
}
}
void QmitkPreprocessingView::UpdateBValueTableWidget(int i)
{
foreach(QCheckBox * box, m_ReduceGradientCheckboxes)
{
m_Controls->m_ReductionFrame->layout()->removeWidget(box);
delete box;
}
foreach(QSpinBox * box, m_ReduceGradientSpinboxes)
{
m_Controls->m_ReductionFrame->layout()->removeWidget(box);
delete box;
}
m_ReduceGradientCheckboxes.clear();
m_ReduceGradientSpinboxes.clear();
if (m_DiffusionImage.IsNull())
{
m_Controls->m_B_ValueMap_TableWidget->clear();
m_Controls->m_B_ValueMap_TableWidget->setRowCount(1);
QStringList headerList;
headerList << "b-Value" << "Number of gradients";
m_Controls->m_B_ValueMap_TableWidget->setHorizontalHeaderLabels(headerList);
m_Controls->m_B_ValueMap_TableWidget->setItem(0,0,new QTableWidgetItem("-"));
m_Controls->m_B_ValueMap_TableWidget->setItem(0,1,new QTableWidgetItem("-"));
}else{
typedef mitk::DiffusionImage<short>::BValueMap BValueMap;
typedef mitk::DiffusionImage<short>::BValueMap::iterator BValueMapIterator;
BValueMapIterator it;
BValueMap roundedBValueMap = m_DiffusionImage->GetBValueMap();
m_Controls->m_B_ValueMap_TableWidget->clear();
m_Controls->m_B_ValueMap_TableWidget->setRowCount(roundedBValueMap.size() );
QStringList headerList;
headerList << "b-Value" << "Number of gradients";
m_Controls->m_B_ValueMap_TableWidget->setHorizontalHeaderLabels(headerList);
QCheckBox* checkBox;
QSpinBox* spinBox;
int i = 0 ;
for(it = roundedBValueMap.begin() ;it != roundedBValueMap.end(); it++)
{
m_Controls->m_B_ValueMap_TableWidget->setItem(i,0,new QTableWidgetItem(QString::number(it->first)));
m_Controls->m_B_ValueMap_TableWidget->setItem(i,1,new QTableWidgetItem(QString::number(it->second.size())));
// Reduce Gradients GUI adaption
if(roundedBValueMap.size() > 1){
checkBox = new QCheckBox(QString::number(it->first) + " with " + QString::number(it->second.size()) + " directions");
checkBox->setEnabled(true);
checkBox->setChecked(true);
checkBox->setCheckable(true);
m_ReduceGradientCheckboxes.push_back(checkBox);
m_Controls->m_ReductionFrame->layout()->addWidget(checkBox);
spinBox = new QSpinBox();
spinBox->setMaximum(it->second.size());
spinBox->setValue(std::ceil((float)it->second.size()));
spinBox->setMinimum(0);
m_ReduceGradientSpinboxes.push_back(spinBox);
m_Controls->m_ReductionFrame->layout()->addWidget(spinBox);
}
i++;
}
}
}
void QmitkPreprocessingView::OnSelectionChanged( std::vector<mitk::DataNode*> nodes )
{
bool foundDwiVolume = false;
m_DiffusionImage = NULL;
m_SelectedDiffusionNodes.clear();
// iterate selection
for( std::vector<mitk::DataNode*>::iterator it = nodes.begin(); it != nodes.end(); ++it )
{
mitk::DataNode::Pointer node = *it;
if( node.IsNotNull() && dynamic_cast<mitk::DiffusionImage<short>*>(node->GetData()) )
{
foundDwiVolume = true;
m_DiffusionImage = dynamic_cast<mitk::DiffusionImage<DiffusionPixelType>*>(node->GetData());
m_Controls->m_DiffusionImageLabel->setText(node->GetName().c_str());
m_SelectedDiffusionNodes.push_back(node);
}
}
m_Controls->m_ButtonAverageGradients->setEnabled(foundDwiVolume);
m_Controls->m_ButtonExtractB0->setEnabled(foundDwiVolume);
m_Controls->m_CheckExtractAll->setEnabled(foundDwiVolume);
m_Controls->m_ModifyMeasurementFrame->setEnabled(foundDwiVolume);
m_Controls->m_MeasurementFrameTable->setEnabled(foundDwiVolume);
m_Controls->m_ReduceGradientsButton->setEnabled(foundDwiVolume);
m_Controls->m_ShowGradientsButton->setEnabled(foundDwiVolume);
m_Controls->m_MirrorGradientToHalfSphereButton->setEnabled(foundDwiVolume);
m_Controls->m_MergeDwisButton->setEnabled(foundDwiVolume);
m_Controls->m_B_ValueMap_Rounder_SpinBox->setEnabled(foundDwiVolume);
//m_Controls->m_AdcSignalFit->setEnabled(foundDwiVolume);
m_Controls->m_AdcSignalAverage->setEnabled(foundDwiVolume);
m_Controls->m_AkcSignalFit->setEnabled(foundDwiVolume);
m_Controls->m_BiExpSignalFit->setEnabled(foundDwiVolume);
m_Controls->m_CreateLengthCorrectedDwi->setEnabled(foundDwiVolume);
m_Controls->m_CalcAdcButton->setEnabled(foundDwiVolume);
m_Controls->m_targetBValueSpinBox->setEnabled(foundDwiVolume);
m_Controls->m_OutputRMSErrorImage->setEnabled(foundDwiVolume);
// reset sampling frame to 1 and update all ealted components
m_Controls->m_B_ValueMap_Rounder_SpinBox->setValue(1);
UpdateBValueTableWidget(m_Controls->m_B_ValueMap_Rounder_SpinBox->value());
if (foundDwiVolume)
{
m_Controls->m_InputData->setTitle("Input Data");
vnl_matrix_fixed< double, 3, 3 > mf = m_DiffusionImage->GetMeasurementFrame();
for (int r=0; r<3; r++)
for (int c=0; c<3; c++)
{
QTableWidgetItem* item = m_Controls->m_MeasurementFrameTable->item(r,c);
delete item;
item = new QTableWidgetItem();
item->setTextAlignment(Qt::AlignCenter | Qt::AlignVCenter);
item->setText(QString::number(mf.get(r,c)));
m_Controls->m_MeasurementFrameTable->setItem(r,c,item);
}
//calculate target bValue for MultishellToSingleShellfilter
const mitk::DiffusionImage<DiffusionPixelType>::BValueMap & bValMap = m_DiffusionImage->GetBValueMap();
mitk::DiffusionImage<DiffusionPixelType>::BValueMap::const_iterator it = bValMap.begin();
unsigned int targetBVal = 0;
while(it != bValMap.end())
targetBVal += (it++)->first;
targetBVal /= (float)bValMap.size()-1;
m_Controls->m_targetBValueSpinBox->setValue(targetBVal);
}
else
{
for (int r=0; r<3; r++)
for (int c=0; c<3; c++)
{
QTableWidgetItem* item = m_Controls->m_MeasurementFrameTable->item(r,c);
delete item;
item = new QTableWidgetItem();
m_Controls->m_MeasurementFrameTable->setItem(r,c,item);
}
m_Controls->m_DiffusionImageLabel->setText("<font color='red'>mandatory</font>");
m_Controls->m_InputData->setTitle("Please Select Input Data");
}
}
void QmitkPreprocessingView::Activated()
{
QmitkFunctionality::Activated();
}
void QmitkPreprocessingView::Deactivated()
{
QmitkFunctionality::Deactivated();
}
void QmitkPreprocessingView::DoHalfSphereGradientDirections()
{
GradientDirectionContainerType::Pointer gradientContainer = m_DiffusionImage->GetDirections();
for (unsigned int j=0; j<gradientContainer->Size(); j++)
if (gradientContainer->at(j)[0]<0)
gradientContainer->at(j) = -gradientContainer->at(j);
m_DiffusionImage->SetDirections(gradientContainer);
}
void QmitkPreprocessingView::DoApplyMesurementFrame()
{
if (m_DiffusionImage.IsNull())
return;
vnl_matrix_fixed< double, 3, 3 > mf;
for (int r=0; r<3; r++)
for (int c=0; c<3; c++)
{
QTableWidgetItem* item = m_Controls->m_MeasurementFrameTable->item(r,c);
if (!item)
return;
mf[r][c] = item->text().toDouble();
}
m_DiffusionImage->SetMeasurementFrame(mf);
}
void QmitkPreprocessingView::DoShowGradientDirections()
{
if (m_DiffusionImage.IsNull())
return;
int maxIndex = 0;
unsigned int maxSize = m_DiffusionImage->GetDimension(0);
if (maxSize<m_DiffusionImage->GetDimension(1))
{
maxSize = m_DiffusionImage->GetDimension(1);
maxIndex = 1;
}
if (maxSize<m_DiffusionImage->GetDimension(2))
{
maxSize = m_DiffusionImage->GetDimension(2);
maxIndex = 2;
}
mitk::Point3D origin = m_DiffusionImage->GetGeometry()->GetOrigin();
mitk::PointSet::Pointer originSet = mitk::PointSet::New();
typedef mitk::DiffusionImage<short>::BValueMap BValueMap;
typedef mitk::DiffusionImage<short>::BValueMap::iterator BValueMapIterator;
BValueMap bValMap = m_DiffusionImage->GetBValueMap();
GradientDirectionContainerType::Pointer gradientContainer = m_DiffusionImage->GetDirections();
- mitk::Geometry3D::Pointer geometry = m_DiffusionImage->GetGeometry();
+ mitk::BaseGeometry::Pointer geometry = m_DiffusionImage->GetGeometry();
int shellCount = 1;
for(BValueMapIterator it = bValMap.begin(); it!=bValMap.end(); ++it)
{
mitk::PointSet::Pointer pointset = mitk::PointSet::New();
for (unsigned int j=0; j<it->second.size(); j++)
{
mitk::Point3D ip;
vnl_vector_fixed< double, 3 > v = gradientContainer->at(it->second[j]);
if (v.magnitude()>mitk::eps)
{
ip[0] = v[0]*maxSize*geometry->GetSpacing()[maxIndex]/2 + origin[0]-0.5*geometry->GetSpacing()[0] + geometry->GetSpacing()[0]*m_DiffusionImage->GetDimension(0)/2;
ip[1] = v[1]*maxSize*geometry->GetSpacing()[maxIndex]/2 + origin[1]-0.5*geometry->GetSpacing()[1] + geometry->GetSpacing()[1]*m_DiffusionImage->GetDimension(1)/2;
ip[2] = v[2]*maxSize*geometry->GetSpacing()[maxIndex]/2 + origin[2]-0.5*geometry->GetSpacing()[2] + geometry->GetSpacing()[2]*m_DiffusionImage->GetDimension(2)/2;
pointset->InsertPoint(j, ip);
}
else if (originSet->IsEmpty())
{
ip[0] = v[0]*maxSize*geometry->GetSpacing()[maxIndex]/2 + origin[0]-0.5*geometry->GetSpacing()[0] + geometry->GetSpacing()[0]*m_DiffusionImage->GetDimension(0)/2;
ip[1] = v[1]*maxSize*geometry->GetSpacing()[maxIndex]/2 + origin[1]-0.5*geometry->GetSpacing()[1] + geometry->GetSpacing()[1]*m_DiffusionImage->GetDimension(1)/2;
ip[2] = v[2]*maxSize*geometry->GetSpacing()[maxIndex]/2 + origin[2]-0.5*geometry->GetSpacing()[2] + geometry->GetSpacing()[2]*m_DiffusionImage->GetDimension(2)/2;
originSet->InsertPoint(j, ip);
}
}
if (it->first<mitk::eps)
continue;
// add shell to datastorage
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData(pointset);
QString name = m_SelectedDiffusionNodes.front()->GetName().c_str();
name += "_Shell_";
name += QString::number(it->first);
node->SetName(name.toStdString().c_str());
node->SetProperty("pointsize", mitk::FloatProperty::New((float)maxSize/50));
int b0 = shellCount%2;
int b1 = 0;
int b2 = 0;
if (shellCount>4)
b2 = 1;
if (shellCount%4 >= 2)
b1 = 1;
node->SetProperty("color", mitk::ColorProperty::New(b2, b1, b0));
GetDefaultDataStorage()->Add(node, m_SelectedDiffusionNodes.front());
shellCount++;
}
// add origin to datastorage
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData(originSet);
QString name = m_SelectedDiffusionNodes.front()->GetName().c_str();
name += "_Origin";
node->SetName(name.toStdString().c_str());
node->SetProperty("pointsize", mitk::FloatProperty::New((float)maxSize/50));
node->SetProperty("color", mitk::ColorProperty::New(1,1,1));
GetDefaultDataStorage()->Add(node, m_SelectedDiffusionNodes.front());
}
void QmitkPreprocessingView::DoReduceGradientDirections()
{
if (m_DiffusionImage.IsNull())
return;
typedef mitk::DiffusionImage<DiffusionPixelType> DiffusionImageType;
typedef itk::ElectrostaticRepulsionDiffusionGradientReductionFilter<DiffusionPixelType, DiffusionPixelType> FilterType;
typedef DiffusionImageType::BValueMap BValueMap;
// GetShellSelection from GUI
BValueMap shellSlectionMap;
BValueMap originalShellMap = m_DiffusionImage->GetBValueMap();
std::vector<unsigned int> newNumGradientDirections;
int shellCounter = 0;
foreach(QCheckBox * box , m_ReduceGradientCheckboxes)
{
if(box->isChecked())
{
double BValue = (box->text().split(' ')).at(0).toDouble();
shellSlectionMap[BValue] = originalShellMap[BValue];
newNumGradientDirections.push_back(m_ReduceGradientSpinboxes.at(shellCounter)->value());
}
shellCounter++;
}
if (newNumGradientDirections.empty())
return;
GradientDirectionContainerType::Pointer gradientContainer = m_DiffusionImage->GetDirections();
FilterType::Pointer filter = FilterType::New();
filter->SetInput(m_DiffusionImage->GetVectorImage());
filter->SetOriginalGradientDirections(gradientContainer);
filter->SetNumGradientDirections(newNumGradientDirections);
filter->SetOriginalBValueMap(originalShellMap);
filter->SetShellSelectionBValueMap(shellSlectionMap);
filter->Update();
DiffusionImageType::Pointer image = DiffusionImageType::New();
image->SetVectorImage( filter->GetOutput() );
image->SetReferenceBValue(m_DiffusionImage->GetReferenceBValue());
image->SetDirections(filter->GetGradientDirections());
image->SetMeasurementFrame(m_DiffusionImage->GetMeasurementFrame());
image->InitializeFromVectorImage();
mitk::DataNode::Pointer imageNode = mitk::DataNode::New();
imageNode->SetData( image );
QString name = m_SelectedDiffusionNodes.front()->GetName().c_str();
QList<QSpinBox*>::iterator itSpinBox = m_ReduceGradientSpinboxes.begin();
QList<QCheckBox*>::iterator itCheckBox = m_ReduceGradientCheckboxes.begin();
while(itSpinBox != m_ReduceGradientSpinboxes.end() && itCheckBox != m_ReduceGradientCheckboxes.end())
{
name += "_";
if((*itCheckBox)->isChecked()){
name += QString::number((*itSpinBox)->value());
}else
{
name += QString::number(0);
}
++itSpinBox;
++itCheckBox;
}
imageNode->SetName(name.toStdString().c_str());
GetDefaultDataStorage()->Add(imageNode);
}
void QmitkPreprocessingView::MergeDwis()
{
typedef mitk::DiffusionImage<DiffusionPixelType> DiffusionImageType;
typedef DiffusionImageType::GradientDirectionContainerType GradientContainerType;
if (m_SelectedDiffusionNodes.size()<2)
return;
typedef itk::VectorImage<DiffusionPixelType,3> DwiImageType;
typedef DwiImageType::PixelType DwiPixelType;
typedef DwiImageType::RegionType DwiRegionType;
typedef std::vector< DwiImageType::Pointer > DwiImageContainerType;
typedef std::vector< GradientContainerType::Pointer > GradientListContainerType;
DwiImageContainerType imageContainer;
GradientListContainerType gradientListContainer;
std::vector< double > bValueContainer;
QString name = m_SelectedDiffusionNodes.front()->GetName().c_str();
for (unsigned int i=0; i<m_SelectedDiffusionNodes.size(); i++)
{
DiffusionImageType::Pointer dwi = dynamic_cast< mitk::DiffusionImage<DiffusionPixelType>* >( m_SelectedDiffusionNodes.at(i)->GetData() );
if ( dwi.IsNotNull() )
{
imageContainer.push_back(dwi->GetVectorImage());
gradientListContainer.push_back(dwi->GetDirections());
bValueContainer.push_back(dwi->GetReferenceBValue());
if (i>0)
{
name += "+";
name += m_SelectedDiffusionNodes.at(i)->GetName().c_str();
}
}
}
typedef itk::MergeDiffusionImagesFilter<short> FilterType;
FilterType::Pointer filter = FilterType::New();
filter->SetImageVolumes(imageContainer);
filter->SetGradientLists(gradientListContainer);
filter->SetBValues(bValueContainer);
filter->Update();
vnl_matrix_fixed< double, 3, 3 > mf; mf.set_identity();
DiffusionImageType::Pointer image = DiffusionImageType::New();
image->SetVectorImage( filter->GetOutput() );
image->SetReferenceBValue(filter->GetB_Value());
image->SetDirections(filter->GetOutputGradients());
image->SetMeasurementFrame(mf);
image->InitializeFromVectorImage();
mitk::DataNode::Pointer imageNode = mitk::DataNode::New();
imageNode->SetData( image );
imageNode->SetName(name.toStdString().c_str());
GetDefaultDataStorage()->Add(imageNode);
}
void QmitkPreprocessingView::ExtractB0()
{
typedef mitk::DiffusionImage<DiffusionPixelType> DiffusionImageType;
typedef DiffusionImageType::GradientDirectionContainerType GradientContainerType;
int nrFiles = m_SelectedDiffusionNodes.size();
if (!nrFiles) return;
// call the extraction withou averaging if the check-box is checked
if( this->m_Controls->m_CheckExtractAll->isChecked() )
{
DoExtractBOWithoutAveraging();
return;
}
mitk::DataStorage::SetOfObjects::const_iterator itemiter( m_SelectedDiffusionNodes.begin() );
mitk::DataStorage::SetOfObjects::const_iterator itemiterend( m_SelectedDiffusionNodes.end() );
std::vector<mitk::DataNode::Pointer> nodes;
while ( itemiter != itemiterend ) // for all items
{
DiffusionImageType* vols =
static_cast<DiffusionImageType*>(
(*itemiter)->GetData());
std::string nodename;
(*itemiter)->GetStringProperty("name", nodename);
// Extract image using found index
typedef itk::B0ImageExtractionImageFilter<short, short> FilterType;
FilterType::Pointer filter = FilterType::New();
filter->SetInput(vols->GetVectorImage());
filter->SetDirections(vols->GetDirections());
filter->Update();
mitk::Image::Pointer mitkImage = mitk::Image::New();
mitkImage->InitializeByItk( filter->GetOutput() );
mitkImage->SetVolume( filter->GetOutput()->GetBufferPointer() );
mitk::DataNode::Pointer node=mitk::DataNode::New();
node->SetData( mitkImage );
node->SetProperty( "name", mitk::StringProperty::New(nodename + "_B0"));
GetDefaultDataStorage()->Add(node);
++itemiter;
}
}
void QmitkPreprocessingView::DoExtractBOWithoutAveraging()
{
// typedefs
typedef mitk::DiffusionImage<DiffusionPixelType> DiffusionImageType;
typedef DiffusionImageType::GradientDirectionContainerType GradientContainerType;
typedef itk::B0ImageExtractionToSeparateImageFilter< short, short> FilterType;
// check number of selected objects, return if empty
int nrFiles = m_SelectedDiffusionNodes.size();
if (!nrFiles)
return;
mitk::DataStorage::SetOfObjects::const_iterator itemiter( m_SelectedDiffusionNodes.begin() );
mitk::DataStorage::SetOfObjects::const_iterator itemiterend( m_SelectedDiffusionNodes.end() );
while ( itemiter != itemiterend ) // for all items
{
DiffusionImageType* vols =
static_cast<DiffusionImageType*>(
(*itemiter)->GetData());
std::string nodename;
(*itemiter)->GetStringProperty("name", nodename);
// Extract image using found index
FilterType::Pointer filter = FilterType::New();
filter->SetInput(vols->GetVectorImage());
filter->SetDirections(vols->GetDirections());
filter->Update();
mitk::Image::Pointer mitkImage = mitk::Image::New();
mitkImage->InitializeByItk( filter->GetOutput() );
mitkImage->SetImportChannel( filter->GetOutput()->GetBufferPointer() );
mitk::DataNode::Pointer node=mitk::DataNode::New();
node->SetData( mitkImage );
node->SetProperty( "name", mitk::StringProperty::New(nodename + "_B0_ALL"));
GetDefaultDataStorage()->Add(node);
/*A reinitialization is needed to access the time channels via the ImageNavigationController
The Global-Geometry can not recognize the time channel without a re-init.
(for a new selection in datamanger a automatically updated of the Global-Geometry should be done - if it contains the time channel)*/
mitk::RenderingManager::GetInstance()->InitializeViews(node->GetData()->GetTimeGeometry(),mitk::RenderingManager::REQUEST_UPDATE_ALL, true);
++itemiter;
}
}
void QmitkPreprocessingView::AverageGradients()
{
int nrFiles = m_SelectedDiffusionNodes.size();
if (!nrFiles) return;
mitk::DataStorage::SetOfObjects::const_iterator itemiter( m_SelectedDiffusionNodes.begin() );
mitk::DataStorage::SetOfObjects::const_iterator itemiterend( m_SelectedDiffusionNodes.end() );
std::vector<mitk::DataNode::Pointer> nodes;
while ( itemiter != itemiterend ) // for all items
{
mitk::DiffusionImage<DiffusionPixelType>* vols =
static_cast<mitk::DiffusionImage<DiffusionPixelType>*>(
(*itemiter)->GetData());
vols->AverageRedundantGradients(m_Controls->m_Blur->value());
++itemiter;
}
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkStochasticFiberTrackingView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkStochasticFiberTrackingView.cpp
index 20a99e41ab..c50dda8e7b 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkStochasticFiberTrackingView.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkStochasticFiberTrackingView.cpp
@@ -1,290 +1,290 @@
/*===================================================================
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.
===================================================================*/
// Blueberry
#include <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>
#include <berryIStructuredSelection.h>
// Qmitk
#include "QmitkStochasticFiberTrackingView.h"
#include "QmitkStdMultiWidget.h"
// Qt
#include <QMessageBox>
// MITK
#include <mitkImageToItk.h>
#include <mitkFiberBundleX.h>
// VTK
#include <vtkPolyData.h>
#include <vtkPoints.h>
#include <vtkCellArray.h>
#include <vtkSmartPointer.h>
#include <vtkPolyLine.h>
#include <vtkCellData.h>
const std::string QmitkStochasticFiberTrackingView::VIEW_ID = "org.mitk.views.stochasticfibertracking";
const std::string id_DataManager = "org.mitk.views.datamanager";
using namespace berry;
QmitkStochasticFiberTrackingView::QmitkStochasticFiberTrackingView()
: QmitkFunctionality()
, m_Controls( 0 )
, m_MultiWidget( NULL )
, m_SeedRoi( NULL )
, m_DiffusionImage( NULL )
{
}
// Destructor
QmitkStochasticFiberTrackingView::~QmitkStochasticFiberTrackingView()
{
}
void QmitkStochasticFiberTrackingView::CreateQtPartControl( QWidget *parent )
{
if ( !m_Controls )
{
// create GUI widgets from the Qt Designer's .ui file
m_Controls = new Ui::QmitkStochasticFiberTrackingViewControls;
m_Controls->setupUi( parent );
connect( m_Controls->commandLinkButton, SIGNAL(clicked()), this, SLOT(DoFiberTracking()) );
connect( m_Controls->m_SeedsPerVoxelSlider, SIGNAL(valueChanged(int)), this, SLOT(OnSeedsPerVoxelChanged(int)) );
connect( m_Controls->m_MaxCacheSizeSlider, SIGNAL(valueChanged(int)), this, SLOT(OnMaxCacheSizeChanged(int)) );
connect( m_Controls->m_MaxTractLengthSlider, SIGNAL(valueChanged(int)), this, SLOT(OnMaxTractLengthChanged(int)) );
}
}
void QmitkStochasticFiberTrackingView::OnSeedsPerVoxelChanged(int value)
{
m_Controls->m_SeedsPerVoxelLabel->setText(QString("Seeds per Voxel: ")+QString::number(value));
}
void QmitkStochasticFiberTrackingView::OnMaxTractLengthChanged(int value)
{
m_Controls->m_MaxTractLengthLabel->setText(QString("Max. Tract Length: ")+QString::number(value));
}
void QmitkStochasticFiberTrackingView::OnMaxCacheSizeChanged(int value)
{
m_Controls->m_MaxCacheSizeLabel->setText(QString("Max. Cache Size: ")+QString::number(value)+"GB");
}
void QmitkStochasticFiberTrackingView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget)
{
m_MultiWidget = &stdMultiWidget;
}
void QmitkStochasticFiberTrackingView::StdMultiWidgetNotAvailable()
{
m_MultiWidget = NULL;
}
void QmitkStochasticFiberTrackingView::OnSelectionChanged( std::vector<mitk::DataNode*> nodes )
{
m_DiffusionImageNode = NULL;
m_DiffusionImage = NULL;
m_SeedRoi = NULL;
m_Controls->m_DiffusionImageLabel->setText("<font color='red'>mandatory</font>");
m_Controls->m_RoiImageLabel->setText("<font color='red'>mandatory</font>");
for( std::vector<mitk::DataNode*>::iterator it = nodes.begin(); it != nodes.end(); ++it )
{
mitk::DataNode::Pointer node = *it;
if( node.IsNotNull() && dynamic_cast<mitk::Image*>(node->GetData()) )
{
if( dynamic_cast<mitk::DiffusionImage<short>*>(node->GetData()) )
{
m_DiffusionImageNode = node;
m_DiffusionImage = dynamic_cast<mitk::DiffusionImage<short>*>(node->GetData());
m_Controls->m_DiffusionImageLabel->setText(node->GetName().c_str());
}
else
{
bool isBinary = false;
node->GetPropertyValue<bool>("binary", isBinary);
if (isBinary)
{
m_SeedRoi = dynamic_cast<mitk::Image*>(node->GetData());
m_Controls->m_RoiImageLabel->setText(node->GetName().c_str());
}
}
}
}
if(m_DiffusionImage.IsNotNull() && m_SeedRoi.IsNotNull())
{
m_Controls->m_InputData->setTitle("Input Data");
m_Controls->commandLinkButton->setEnabled(true);
}
else
{
m_Controls->m_InputData->setTitle("Please Select Input Data");
m_Controls->commandLinkButton->setEnabled(false);
}
}
void QmitkStochasticFiberTrackingView::DoFiberTracking()
{
typedef itk::VectorImage< short int, 3 > DWIVectorImageType;
typedef itk::Image< float, 3 > FloatImageType;
typedef itk::Image< unsigned int, 3 > CImageType;
typedef itk::StochasticTractographyFilter< DWIVectorImageType, FloatImageType, CImageType > TrackingFilterType;
typedef itk::DTITubeSpatialObject<3> DTITubeType;
typedef itk::DTITubeSpatialObjectPoint<3> DTITubePointType;
typedef itk::SceneSpatialObject<3> SceneSpatialObjectType;
/* get Gradients/Direction of dwi */
itk::VectorContainer< unsigned int, vnl_vector_fixed<double,3> >::Pointer Pdir = m_DiffusionImage->GetDirections();
/* bValueContainer, Container includes b-values according to corresponding gradient-direction*/
TrackingFilterType::bValueContainerType::Pointer vecCont = TrackingFilterType::bValueContainerType::New();
/* for each gradient set b-Value; for 0-gradient set b-value eq. 0 */
for ( int i=0; i<(int)Pdir->size(); ++i)
{
vnl_vector_fixed<double,3> valsGrad = Pdir->at(i);
if (valsGrad.get(0) == 0 && valsGrad.get(1) == 0 && valsGrad.get(2) == 0)
{ //set 0-Gradient to bValue 0
vecCont->InsertElement(i,0);
}else{
vecCont->InsertElement(i,m_DiffusionImage->GetReferenceBValue());
}
}
/* define measurement frame (identity-matrix 3x3) */
TrackingFilterType::MeasurementFrameType measurement_frame = m_DiffusionImage->GetMeasurementFrame();
/* generate white matterImage (dummy?)*/
FloatImageType::Pointer wmImage = FloatImageType::New();
wmImage->SetSpacing( m_DiffusionImage->GetVectorImage()->GetSpacing() );
wmImage->SetOrigin( m_DiffusionImage->GetVectorImage()->GetOrigin() );
wmImage->SetDirection( m_DiffusionImage->GetVectorImage()->GetDirection() );
wmImage->SetLargestPossibleRegion( m_DiffusionImage->GetVectorImage()->GetLargestPossibleRegion() );
wmImage->SetBufferedRegion( wmImage->GetLargestPossibleRegion() );
wmImage->SetRequestedRegion( wmImage->GetLargestPossibleRegion() );
wmImage->Allocate();
itk::ImageRegionIterator<FloatImageType> ot(wmImage, wmImage->GetLargestPossibleRegion() );
while (!ot.IsAtEnd())
{
ot.Set(1);
++ot;
}
/* init TractographyFilter */
TrackingFilterType::Pointer trackingFilter = TrackingFilterType::New();
trackingFilter->SetPrimaryInput(m_DiffusionImage->GetVectorImage().GetPointer());
trackingFilter->SetbValues(vecCont);
trackingFilter->SetGradients(Pdir);
trackingFilter->SetMeasurementFrame(measurement_frame);
trackingFilter->SetWhiteMatterProbabilityImage(wmImage);
trackingFilter->SetTotalTracts(m_Controls->m_SeedsPerVoxelSlider->value());
trackingFilter->SetMaxLikelihoodCacheSize(m_Controls->m_MaxCacheSizeSlider->value()*1000);
trackingFilter->SetMaxTractLength(m_Controls->m_MaxTractLengthSlider->value());
//itk::Image< char, 3 >
mitk::ImageToItk< itk::Image< unsigned char, 3 > >::Pointer binaryImageToItk1 = mitk::ImageToItk< itk::Image< unsigned char, 3 > >::New();
binaryImageToItk1->SetInput( m_SeedRoi );
binaryImageToItk1->Update();
vtkSmartPointer<vtkPoints> vPoints = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkCellArray> vCellArray = vtkSmartPointer<vtkCellArray>::New();
itk::ImageRegionConstIterator< BinaryImageType > it(binaryImageToItk1->GetOutput(), binaryImageToItk1->GetOutput()->GetRequestedRegion());
it.GoToBegin();
- mitk::Geometry3D* geom = m_DiffusionImage->GetGeometry();
+ mitk::BaseGeometry* geom = m_DiffusionImage->GetGeometry();
while(!it.IsAtEnd())
{
itk::ImageConstIterator<BinaryImageType>::PixelType tmpPxValue = it.Get();
if(tmpPxValue != 0){
mitk::Point3D point;
itk::ImageRegionConstIterator< BinaryImageType >::IndexType seedIdx = it.GetIndex();
trackingFilter->SetSeedIndex(seedIdx);
trackingFilter->Update();
/* get results from Filter */
/* write each single tract into member container */
TrackingFilterType::TractContainerType::Pointer container_tmp = trackingFilter->GetOutputTractContainer();
TrackingFilterType::TractContainerType::Iterator elIt = container_tmp->Begin();
TrackingFilterType::TractContainerType::Iterator end = container_tmp->End();
bool addTract = true;
while( elIt != end ){
TrackingFilterType::TractContainerType::Element tract = elIt.Value();
TrackingFilterType::TractContainerType::Element::ObjectType::VertexListType::ConstPointer vertexlist = tract->GetVertexList();
vtkSmartPointer<vtkPolyLine> vPolyLine = vtkSmartPointer<vtkPolyLine>::New();
for( int j=0; j<(int)vertexlist->Size(); j++)
{
TrackingFilterType::TractContainerType::Element::ObjectType::VertexListType::Element vertex = vertexlist->GetElement(j);
mitk::Point3D index;
index[0] = (float)vertex[0];
index[1] = (float)vertex[1];
index[2] = (float)vertex[2];
if (geom->IsIndexInside(index))
{
geom->IndexToWorld(index, point);
vtkIdType id = vPoints->InsertNextPoint(point.GetDataPointer());
vPolyLine->GetPointIds()->InsertNextId(id);
}
else
{
addTract = false;
break;
}
}
if (addTract)
vCellArray->InsertNextCell(vPolyLine);
++elIt;
}
}
++it;
}
vtkSmartPointer<vtkPolyData> fiberPolyData = vtkSmartPointer<vtkPolyData>::New();
fiberPolyData->SetPoints(vPoints);
fiberPolyData->SetLines(vCellArray);
mitk::FiberBundleX::Pointer fib = mitk::FiberBundleX::New(fiberPolyData);
fib->SetReferenceImage(dynamic_cast<mitk::Image*>(m_DiffusionImageNode->GetData()));
mitk::DataNode::Pointer fbNode = mitk::DataNode::New();
fbNode->SetData(fib);
QString name("FiberBundle_");
name += m_DiffusionImageNode->GetName().c_str();
name += "_Probabilistic";
fbNode->SetName(name.toStdString());
fbNode->SetVisibility(true);
GetDataStorage()->Add(fbNode, m_DiffusionImageNode);
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTbssSkeletonizationView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTbssSkeletonizationView.cpp
index 77066e4499..620ce7c77e 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTbssSkeletonizationView.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTbssSkeletonizationView.cpp
@@ -1,494 +1,494 @@
/*===================================================================
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.
===================================================================*/
// Qmitk
#include "QmitkTbssSkeletonizationView.h"
#include <itkSkeletonizationFilter.h>
#include <itkProjectionFilter.h>
#include <itkDistanceMapFilter.h>
#include <itkBinaryThresholdImageFilter.h>
#include <itkImageFileReader.h>
// mitk
#include <mitkImagePixelReadAccessor.h>
#include <mitkImage.h>
// Qt
#include <QInputDialog>
#include <QMessageBox>
//vtk
#include <vtkLinearTransform.h>
#include <vtkMatrix4x4.h>
// Boost
#include <boost/lexical_cast.hpp>
const std::string QmitkTbssSkeletonizationView::VIEW_ID = "org.mitk.views.tbssskeletonization";
using namespace berry;
QmitkTbssSkeletonizationView::QmitkTbssSkeletonizationView()
: QmitkFunctionality()
, m_Controls( 0 )
, m_MultiWidget( NULL )
{
}
QmitkTbssSkeletonizationView::~QmitkTbssSkeletonizationView()
{
}
void QmitkTbssSkeletonizationView::OnSelectionChanged(std::vector<mitk::DataNode*> nodes)
{
//datamanager selection changed
if (!this->IsActivated())
return;
bool found3dImage = false;
bool found4dImage = false;
this->m_Controls->m_TubularName->setText(QString("Tubular Structure Mask: "));
this->m_Controls->m_TubularName->setEnabled(false);
this->m_Controls->m_MeanLabel->setText(QString("Mean: "));
this->m_Controls->m_MeanLabel->setEnabled(false);
this->m_Controls->m_PatientDataLabel->setText(QString("Patient Data: "));
this->m_Controls->m_PatientDataLabel->setEnabled(false);
// iterate selection
for ( int i=0; i<nodes.size(); i++ )
{
// only look at interesting types from valid nodes
mitk::BaseData* nodeData = nodes[i]->GetData();
std::string name = "";
nodes[i]->GetStringProperty("name", name);
if(nodeData)
{
if(QString("Image").compare(nodeData->GetNameOfClass())==0)
{
mitk::Image* img = static_cast<mitk::Image*>(nodeData);
if(img->GetDimension() == 3)
{
bool isBinary(false);
nodes[i]->GetBoolProperty("binary", isBinary);
if(isBinary)
{
QString label("Tubular Structure Mask: ");
label.append(QString(name.c_str()));
this->m_Controls->m_TubularName->setText(label);
this->m_Controls->m_TubularName->setEnabled(true);
}
else
{
found3dImage = true;
QString label("Mean: ");
label.append(QString(name.c_str()));
this->m_Controls->m_MeanLabel->setText(label);
this->m_Controls->m_MeanLabel->setEnabled(true);
}
}
else if(img->GetDimension() == 4)
{
found4dImage = true;
QString label("Patient Data: ");
label.append(QString(name.c_str()));
this->m_Controls->m_PatientDataLabel->setText(label);
this->m_Controls->m_PatientDataLabel->setEnabled(true);
}
}
}
}
this->m_Controls->m_Skeletonize->setEnabled(found3dImage);
this->m_Controls->m_Project->setEnabled(found3dImage && found4dImage);
this->m_Controls->m_OutputMask->setEnabled(found3dImage && found4dImage);
this->m_Controls->m_OutputDistanceMap->setEnabled(found3dImage && found4dImage);
}
void QmitkTbssSkeletonizationView::CreateQtPartControl( QWidget *parent )
{
// build up qt view, unless already done
if ( !m_Controls )
{
// create GUI widgets from the Qt Designer's .ui file
m_Controls = new Ui::QmitkTbssSkeletonizationViewControls;
m_Controls->setupUi( parent );
this->CreateConnections();
}
}
void QmitkTbssSkeletonizationView::Activated()
{
QmitkFunctionality::Activated();
}
void QmitkTbssSkeletonizationView::Deactivated()
{
QmitkFunctionality::Deactivated();
}
void QmitkTbssSkeletonizationView::CreateConnections()
{
if ( m_Controls )
{
connect( (QObject*)(m_Controls->m_Skeletonize), SIGNAL(clicked()), this, SLOT(Skeletonize() ));
connect( (QObject*)(m_Controls->m_Project), SIGNAL(clicked()), this, SLOT(Project() ));
}
}
void QmitkTbssSkeletonizationView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget)
{
m_MultiWidget = &stdMultiWidget;
}
void QmitkTbssSkeletonizationView::StdMultiWidgetNotAvailable()
{
m_MultiWidget = NULL;
}
void QmitkTbssSkeletonizationView::Skeletonize()
{
typedef itk::SkeletonizationFilter<FloatImageType, FloatImageType> SkeletonisationFilterType;
SkeletonisationFilterType::Pointer skeletonizer = SkeletonisationFilterType::New();
std::vector<mitk::DataNode*> nodes = this->GetDataManagerSelection();
mitk::Image::Pointer meanImage = mitk::Image::New();
std::string name = "";
for ( int i=0; i<nodes.size(); i++ )
{
// process only on valid nodes
mitk::BaseData* nodeData = nodes[i]->GetData();
if(nodeData)
{
if(QString("Image").compare(nodeData->GetNameOfClass())==0)
{
bool isBinary(false);
nodes[i]->GetBoolProperty("binary", isBinary);
mitk::Image* img = static_cast<mitk::Image*>(nodeData);
if(img->GetDimension() == 3 && !isBinary)
{
meanImage = img;
name = nodes[i]->GetName();
}
}
}
}
// Calculate skeleton
FloatImageType::Pointer itkImg = FloatImageType::New();
mitk::CastToItkImage(meanImage, itkImg);
skeletonizer->SetInput(itkImg);
skeletonizer->Update();
FloatImageType::Pointer output = skeletonizer->GetOutput();
mitk::Image::Pointer mitkOutput = mitk::Image::New();
mitk::CastToMitkImage(output, mitkOutput);
name += "_skeleton";
AddToDataStorage(mitkOutput, name);
}
void QmitkTbssSkeletonizationView::Project()
{
typedef itk::SkeletonizationFilter<FloatImageType, FloatImageType> SkeletonisationFilterType;
typedef itk::ProjectionFilter ProjectionFilterType;
typedef itk::DistanceMapFilter<FloatImageType, FloatImageType> DistanceMapFilterType;
SkeletonisationFilterType::Pointer skeletonizer = SkeletonisationFilterType::New();
std::vector<mitk::DataNode*> nodes = this->GetDataManagerSelection();
mitk::Image::Pointer meanImage = mitk::Image::New();
mitk::Image::Pointer subjects = mitk::Image::New();
mitk::Image::Pointer tubular = mitk::Image::New();
for ( int i=0; i<nodes.size(); i++ )
{
// process only on valid nodes
mitk::BaseData* nodeData = nodes[i]->GetData();
if(nodeData)
{
if(QString("Image").compare(nodeData->GetNameOfClass())==0)
{
mitk::Image* img = static_cast<mitk::Image*>(nodeData);
if(img->GetDimension() == 3)
{
bool isBinary(false);
nodes[i]->GetBoolProperty("binary", isBinary);
if(isBinary)
{
tubular = img;
}
else
{
meanImage = img;
}
}
else if(img->GetDimension() == 4)
{
subjects = img;
}
}
}
}
Float4DImageType::Pointer allFA = ConvertToItk(subjects);
// Calculate skeleton
FloatImageType::Pointer itkImg = FloatImageType::New();
mitk::CastToItkImage(meanImage, itkImg);
skeletonizer->SetInput(itkImg);
skeletonizer->Update();
FloatImageType::Pointer output = skeletonizer->GetOutput();
mitk::Image::Pointer mitkOutput = mitk::Image::New();
mitk::CastToMitkImage(output, mitkOutput);
AddToDataStorage(mitkOutput, "mean_FA_skeletonised");
// Retrieve direction image needed later by the projection filter
DirectionImageType::Pointer directionImg = skeletonizer->GetVectorImage();
// Calculate distance image
DistanceMapFilterType::Pointer distanceMapFilter = DistanceMapFilterType::New();
distanceMapFilter->SetInput(output);
distanceMapFilter->Update();
FloatImageType::Pointer distanceMap = distanceMapFilter->GetOutput();
if(m_Controls->m_OutputDistanceMap->isChecked())
{
mitk::Image::Pointer mitkDistance = mitk::Image::New();
mitk::CastToMitkImage(distanceMap, mitkDistance);
AddToDataStorage(mitkDistance, "distance map");
}
// Do projection
// Ask a threshold to create a skeleton mask
double threshold = -1.0;
while(threshold == -1.0)
{
threshold = QInputDialog::getDouble(m_Controls->m_Skeletonize, tr("Specify the FA threshold"),
tr("Threshold:"), QLineEdit::Normal,
0.2);
if(threshold < 0.0 || threshold > 1.0)
{
QMessageBox msgBox;
msgBox.setText("Please choose a value between 0 and 1");
msgBox.exec();
threshold = -1.0;
}
}
typedef itk::BinaryThresholdImageFilter<FloatImageType, CharImageType> ThresholdFilterType;
ThresholdFilterType::Pointer thresholder = ThresholdFilterType::New();
thresholder->SetInput(output);
thresholder->SetLowerThreshold(threshold);
thresholder->SetUpperThreshold(std::numeric_limits<float>::max());
thresholder->SetOutsideValue(0);
thresholder->SetInsideValue(1);
thresholder->Update();
CharImageType::Pointer thresholdedImg = thresholder->GetOutput();
if(m_Controls->m_OutputMask->isChecked())
{
mitk::Image::Pointer mitkThresholded = mitk::Image::New();
mitk::CastToMitkImage(thresholdedImg, mitkThresholded);
std::string maskName = "skeleton_mask_at_" + boost::lexical_cast<std::string>(threshold);
AddToDataStorage(mitkThresholded, maskName);
}
CharImageType::Pointer itkTubular = CharImageType::New();
mitk::CastToItkImage(tubular, itkTubular);
ProjectionFilterType::Pointer projectionFilter = ProjectionFilterType::New();
projectionFilter->SetDistanceMap(distanceMap);
projectionFilter->SetDirections(directionImg);
projectionFilter->SetAllFA(allFA);
projectionFilter->SetTube(itkTubular);
projectionFilter->SetSkeleton(thresholdedImg);
projectionFilter->Project();
Float4DImageType::Pointer projected = projectionFilter->GetProjections();
mitk::Image::Pointer mitkProjections = mitk::Image::New();
mitk::CastToMitkImage(projected, mitkProjections);
AddToDataStorage(mitkProjections, "all_FA_projected");
}
void QmitkTbssSkeletonizationView::AddToDataStorage(mitk::Image* img, std::string name)
{
mitk::DataNode::Pointer result = mitk::DataNode::New();
result->SetProperty( "name", mitk::StringProperty::New(name) );
result->SetData( img );
// add new image to data storage and set as active to ease further processing
GetDefaultDataStorage()->Add( result );
}
Float4DImageType::Pointer QmitkTbssSkeletonizationView::ConvertToItk(itk::SmartPointer<mitk::Image> image)
{
Float4DImageType::Pointer output = Float4DImageType::New();
- mitk::Geometry3D* geo = image->GetGeometry();
+ mitk::BaseGeometry* geo = image->GetGeometry();
mitk::Vector3D mitkSpacing = geo->GetSpacing();
mitk::Point3D mitkOrigin = geo->GetOrigin();
Float4DImageType::SpacingType spacing;
spacing[0] = mitkSpacing[0];
spacing[1] = mitkSpacing[1];
spacing[2] = mitkSpacing[2];
spacing[3] = 1.0; // todo: check if spacing has length 4
Float4DImageType::PointType origin;
origin[0] = mitkOrigin[0];
origin[1] = mitkOrigin[1];
origin[2] = mitkOrigin[2];
origin[3] = 0;
Float4DImageType::SizeType size;
size[0] = image->GetDimension(0);
size[1] = image->GetDimension(1);
size[2] = image->GetDimension(2);
size[3] = image->GetDimension(3);
Float4DImageType::DirectionType dir;
vtkLinearTransform* lin = geo->GetVtkTransform();
vtkMatrix4x4 *m = lin->GetMatrix();
dir.Fill(0.0);
for(int x=0; x<3; x++)
{
for(int y=0; y<3; y++)
{
dir[x][y] = m->GetElement(x,y);
}
}
dir[3][3] = 1;
output->SetSpacing(spacing);
output->SetOrigin(origin);
output->SetRegions(size);
output->SetDirection(dir);
output->Allocate();
if(image->GetDimension() == 4)
{
int timesteps = image->GetDimension(3);
try{
// REPLACE THIS METHODE()ConvertToItk) WITH mitk::CastToItk
// iterate through the subjects and copy data to output
for(int t=0; t<timesteps; t++)
{
for(int x=0; x<image->GetDimension(0); x++)
{
for(int y=0; y<image->GetDimension(1); y++)
{
for(int z=0; z<image->GetDimension(2); z++)
{
itk::Index<3> ix = {x, y, z};
itk::Index<4> ix4 = {x, y, z, t};
output->SetPixel(ix4, image->GetPixelValueByIndex(ix, t));
}
}
}
}
}
catch(std::exception & e)
{
MITK_INFO << e.what();
}
}
return output;
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTensorReconstructionView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTensorReconstructionView.cpp
index db1e14a815..ba919d3c42 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTensorReconstructionView.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTensorReconstructionView.cpp
@@ -1,967 +1,967 @@
/*===================================================================
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 "QmitkTensorReconstructionView.h"
#include "mitkDiffusionImagingConfigure.h"
// qt includes
#include <QMessageBox>
#include <QImage>
#include <QGraphicsScene>
#include <QGraphicsPixmapItem>
#include <QGraphicsLinearLayout>
// itk includes
#include "itkTimeProbe.h"
//#include "itkTensor.h"
// mitk includes
#include "mitkProgressBar.h"
#include "mitkStatusBar.h"
#include "mitkNodePredicateDataType.h"
#include "QmitkDataStorageComboBox.h"
#include "QmitkStdMultiWidget.h"
#include "mitkTeemDiffusionTensor3DReconstructionImageFilter.h"
#include "itkDiffusionTensor3DReconstructionImageFilter.h"
#include "itkTensorImageToDiffusionImageFilter.h"
#include "itkPointShell.h"
#include "itkVector.h"
#include "itkB0ImageExtractionImageFilter.h"
#include "itkTensorReconstructionWithEigenvalueCorrectionFilter.h"
//#include "itkFreeWaterEliminationFilter.h"
#include "mitkProperties.h"
#include "mitkDataNodeObject.h"
#include "mitkOdfNormalizationMethodProperty.h"
#include "mitkOdfScaleByProperty.h"
#include "mitkDiffusionImageMapper.h"
#include "mitkLookupTableProperty.h"
#include "mitkLookupTable.h"
#include "mitkImageStatisticsHolder.h"
#include <itkTensorImageToQBallImageFilter.h>
#include <itkResidualImageFilter.h>
#include <berryIWorkbenchWindow.h>
#include <berryISelectionService.h>
const std::string QmitkTensorReconstructionView::VIEW_ID = "org.mitk.views.tensorreconstruction";
typedef float TTensorPixelType;
typedef itk::DiffusionTensor3D< TTensorPixelType > TensorPixelType;
typedef itk::Image< TensorPixelType, 3 > TensorImageType;
using namespace berry;
QmitkTensorReconstructionView::QmitkTensorReconstructionView()
: QmitkFunctionality(),
m_Controls(NULL),
m_MultiWidget(NULL)
{
m_DiffusionImages = mitk::DataStorage::SetOfObjects::New();
m_TensorImages = mitk::DataStorage::SetOfObjects::New();
}
QmitkTensorReconstructionView::~QmitkTensorReconstructionView()
{
}
void QmitkTensorReconstructionView::CreateQtPartControl(QWidget *parent)
{
if (!m_Controls)
{
// create GUI widgets
m_Controls = new Ui::QmitkTensorReconstructionViewControls;
m_Controls->setupUi(parent);
this->CreateConnections();
Advanced1CheckboxClicked();
}
}
void QmitkTensorReconstructionView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget)
{
m_MultiWidget = &stdMultiWidget;
}
void QmitkTensorReconstructionView::StdMultiWidgetNotAvailable()
{
m_MultiWidget = NULL;
}
void QmitkTensorReconstructionView::CreateConnections()
{
if ( m_Controls )
{
connect( (QObject*)(m_Controls->m_StartReconstruction), SIGNAL(clicked()), this, SLOT(Reconstruct()) );
connect( (QObject*)(m_Controls->m_Advanced1), SIGNAL(clicked()), this, SLOT(Advanced1CheckboxClicked()) );
connect( (QObject*)(m_Controls->m_TensorsToDWIButton), SIGNAL(clicked()), this, SLOT(TensorsToDWI()) );
connect( (QObject*)(m_Controls->m_TensorsToQbiButton), SIGNAL(clicked()), this, SLOT(TensorsToQbi()) );
connect( (QObject*)(m_Controls->m_ResidualButton), SIGNAL(clicked()), this, SLOT(ResidualCalculation()) );
connect( (QObject*)(m_Controls->m_PerSliceView), SIGNAL(pointSelected(int, int)), this, SLOT(ResidualClicked(int, int)) );
}
}
void QmitkTensorReconstructionView::ResidualClicked(int slice, int volume)
{
// Use image coord to reset crosshair
// Find currently selected diffusion image
// Update Label
// to do: This position should be modified in order to skip B0 volumes that are not taken into account
// when calculating residuals
// Find the diffusion image
mitk::DiffusionImage<DiffusionPixelType>* diffImage;
mitk::DataNode::Pointer correctNode;
- mitk::Geometry3D* geometry;
+ mitk::BaseGeometry* geometry;
if (m_DiffusionImage.IsNotNull())
{
diffImage = static_cast<mitk::DiffusionImage<DiffusionPixelType>*>(m_DiffusionImage->GetData());
geometry = diffImage->GetGeometry();
// Remember the node whose display index must be updated
correctNode = mitk::DataNode::New();
correctNode = m_DiffusionImage;
}
if(diffImage != NULL)
{
typedef vnl_vector_fixed< double, 3 > GradientDirectionType;
typedef itk::VectorContainer< unsigned int,
GradientDirectionType > GradientDirectionContainerType;
GradientDirectionContainerType::Pointer dirs = diffImage->GetDirections();
for(unsigned int i=0; i<dirs->Size() && i<=volume; i++)
{
GradientDirectionType grad = dirs->ElementAt(i);
// check if image is b0 weighted
if(fabs(grad[0]) < 0.001 && fabs(grad[1]) < 0.001 && fabs(grad[2]) < 0.001)
{
volume++;
}
}
QString pos = "Volume: ";
pos.append(QString::number(volume));
pos.append(", Slice: ");
pos.append(QString::number(slice));
m_Controls->m_PositionLabel->setText(pos);
if(correctNode)
{
int oldDisplayVal;
correctNode->GetIntProperty("DisplayChannel", oldDisplayVal);
std::string oldVal = QString::number(oldDisplayVal).toStdString();
std::string newVal = QString::number(volume).toStdString();
correctNode->SetIntProperty("DisplayChannel",volume);
correctNode->SetSelected(true);
this->FirePropertyChanged("DisplayChannel", oldVal, newVal);
correctNode->UpdateOutputInformation();
mitk::Point3D p3 = m_MultiWidget->GetCrossPosition();
itk::Index<3> ix;
geometry->WorldToIndex(p3, ix);
// ix[2] = slice;
mitk::Vector3D vec;
vec[0] = ix[0];
vec[1] = ix[1];
vec[2] = slice;
mitk::Vector3D v3New;
geometry->IndexToWorld(vec, v3New);
mitk::Point3D origin = geometry->GetOrigin();
mitk::Point3D p3New;
p3New[0] = v3New[0] + origin[0];
p3New[1] = v3New[1] + origin[1];
p3New[2] = v3New[2] + origin[2];
m_MultiWidget->MoveCrossToPosition(p3New);
m_MultiWidget->RequestUpdate();
}
}
}
void QmitkTensorReconstructionView::Advanced1CheckboxClicked()
{
bool check = m_Controls->
m_Advanced1->isChecked();
m_Controls->frame->setVisible(check);
}
void QmitkTensorReconstructionView::Activated()
{
QmitkFunctionality::Activated();
}
void QmitkTensorReconstructionView::Deactivated()
{
QmitkFunctionality::Deactivated();
}
void QmitkTensorReconstructionView::ResidualCalculation()
{
// Extract dwi and dti from current selection
// In case of multiple selections, take the first one, since taking all combinations is not meaningful
mitk::DataStorage::SetOfObjects::Pointer set =
mitk::DataStorage::SetOfObjects::New();
mitk::DiffusionImage<DiffusionPixelType>::Pointer diffImage
= mitk::DiffusionImage<DiffusionPixelType>::New();
TensorImageType::Pointer tensorImage;
std::string nodename;
if(m_DiffusionImage.IsNotNull())
{
diffImage = static_cast<mitk::DiffusionImage<DiffusionPixelType>*>(m_DiffusionImage->GetData());
}
else
return;
if(m_TensorImage.IsNotNull())
{
mitk::TensorImage* mitkVol;
mitkVol = static_cast<mitk::TensorImage*>(m_TensorImage->GetData());
mitk::CastToItkImage<TensorImageType>(mitkVol, tensorImage);
m_TensorImage->GetStringProperty("name", nodename);
}
else
return;
typedef itk::TensorImageToDiffusionImageFilter<
TTensorPixelType, DiffusionPixelType > FilterType;
mitk::DiffusionImage<DiffusionPixelType>::GradientDirectionContainerType* gradients
= diffImage->GetDirections();
// Find the min and the max values from a baseline image
mitk::ImageStatisticsHolder *stats = diffImage->GetStatistics();
//Initialize filter that calculates the modeled diffusion weighted signals
FilterType::Pointer filter = FilterType::New();
filter->SetInput( tensorImage );
filter->SetBValue(diffImage->GetReferenceBValue());
filter->SetGradientList(gradients);
filter->SetMin(stats->GetScalarValueMin());
filter->SetMax(stats->GetScalarValueMax());
filter->Update();
// TENSORS TO DATATREE
mitk::DiffusionImage<DiffusionPixelType>::Pointer image = mitk::DiffusionImage<DiffusionPixelType>::New();
image->SetVectorImage( filter->GetOutput() );
image->SetReferenceBValue(diffImage->GetReferenceBValue());
image->SetDirections(gradients);
image->InitializeFromVectorImage();
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData( image );
mitk::DiffusionImageMapper<short>::SetDefaultProperties(node);
QString newname;
newname = newname.append(nodename.c_str());
newname = newname.append("_DWI");
node->SetName(newname.toAscii());
GetDefaultDataStorage()->Add(node);
mitk::DiffusionImage<DiffusionPixelType>::BValueMap map =image->GetBValueMap();
mitk::DiffusionImage<DiffusionPixelType>::IndicesVector b0Indices = map[0];
typedef itk::ResidualImageFilter<DiffusionPixelType, float> ResidualImageFilterType;
ResidualImageFilterType::Pointer residualFilter = ResidualImageFilterType::New();
residualFilter->SetInput(diffImage->GetVectorImage());
residualFilter->SetSecondDiffusionImage(image->GetVectorImage());
residualFilter->SetGradients(gradients);
residualFilter->SetB0Index(b0Indices[0]);
residualFilter->SetB0Threshold(30);
residualFilter->Update();
itk::Image<float, 3>::Pointer residualImage = itk::Image<float, 3>::New();
residualImage = residualFilter->GetOutput();
mitk::Image::Pointer mitkResImg = mitk::Image::New();
mitk::CastToMitkImage(residualImage, mitkResImg);
stats = mitkResImg->GetStatistics();
float min = stats->GetScalarValueMin();
float max = stats->GetScalarValueMax();
mitk::LookupTableProperty::Pointer lutProp = mitk::LookupTableProperty::New();
mitk::LookupTable::Pointer lut = mitk::LookupTable::New();
vtkSmartPointer<vtkLookupTable> lookupTable =
vtkSmartPointer<vtkLookupTable>::New();
lookupTable->SetTableRange(min, max);
// If you don't want to use the whole color range, you can use
// SetValueRange, SetHueRange, and SetSaturationRange
lookupTable->Build();
vtkSmartPointer<vtkLookupTable> reversedlookupTable =
vtkSmartPointer<vtkLookupTable>::New();
reversedlookupTable->SetTableRange(min+1, max);
reversedlookupTable->Build();
for(int i=0; i<256; i++)
{
double* rgba = reversedlookupTable->GetTableValue(255-i);
lookupTable->SetTableValue(i, rgba[0], rgba[1], rgba[2], rgba[3]);
}
lut->SetVtkLookupTable(lookupTable);
lutProp->SetLookupTable(lut);
// Create lookuptable
mitk::DataNode::Pointer resNode=mitk::DataNode::New();
resNode->SetData( mitkResImg );
resNode->SetName("Residual Image");
resNode->SetProperty("LookupTable", lutProp);
bool b;
resNode->GetBoolProperty("use color", b);
resNode->SetBoolProperty("use color", false);
GetDefaultDataStorage()->Add(resNode);
m_MultiWidget->RequestUpdate();
// Draw Graph
std::vector<double> means = residualFilter->GetMeans();
std::vector<double> q1s = residualFilter->GetQ1();
std::vector<double> q3s = residualFilter->GetQ3();
std::vector<double> percentagesOfOUtliers = residualFilter->GetPercentagesOfOutliers();
m_Controls->m_ResidualAnalysis->SetMeans(means);
m_Controls->m_ResidualAnalysis->SetQ1(q1s);
m_Controls->m_ResidualAnalysis->SetQ3(q3s);
m_Controls->m_ResidualAnalysis->SetPercentagesOfOutliers(percentagesOfOUtliers);
if(m_Controls->m_PercentagesOfOutliers->isChecked())
{
m_Controls->m_ResidualAnalysis->DrawPercentagesOfOutliers();
}
else
{
m_Controls->m_ResidualAnalysis->DrawMeans();
}
// Draw Graph for volumes per slice in the QGraphicsView
std::vector< std::vector<double> > outliersPerSlice = residualFilter->GetOutliersPerSlice();
int xSize = outliersPerSlice.size();
if(xSize == 0)
{
return;
}
int ySize = outliersPerSlice[0].size();
// Find maximum in outliersPerSlice
double maxOutlier= 0.0;
for(int i=0; i<xSize; i++)
{
for(int j=0; j<ySize; j++)
{
if(outliersPerSlice[i][j]>maxOutlier)
{
maxOutlier = outliersPerSlice[i][j];
}
}
}
// Create some QImage
QImage qImage(xSize, ySize, QImage::Format_RGB32);
QImage legend(1, 256, QImage::Format_RGB32);
QRgb value;
vtkSmartPointer<vtkLookupTable> lookup =
vtkSmartPointer<vtkLookupTable>::New();
lookup->SetTableRange(0.0, maxOutlier);
lookup->Build();
reversedlookupTable->SetTableRange(0, maxOutlier);
reversedlookupTable->Build();
for(int i=0; i<256; i++)
{
double* rgba = reversedlookupTable->GetTableValue(255-i);
lookup->SetTableValue(i, rgba[0], rgba[1], rgba[2], rgba[3]);
}
// Fill qImage
for(int i=0; i<xSize; i++)
{
for(int j=0; j<ySize; j++)
{
double out = outliersPerSlice[i][j];
unsigned char *_rgba = lookup->MapValue(out);
int r, g, b;
r = _rgba[0];
g = _rgba[1];
b = _rgba[2];
value = qRgb(r, g, b);
qImage.setPixel(i,j,value);
}
}
for(int i=0; i<256; i++)
{
double* rgba = lookup->GetTableValue(i);
int r, g, b;
r = rgba[0]*255;
g = rgba[1]*255;
b = rgba[2]*255;
value = qRgb(r, g, b);
legend.setPixel(0,255-i,value);
}
QString upper = QString::number(maxOutlier, 'g', 3);
upper.append(" %");
QString lower = QString::number(0.0);
lower.append(" %");
m_Controls->m_UpperLabel->setText(upper);
m_Controls->m_LowerLabel->setText(lower);
QGraphicsScene* scene = new QGraphicsScene;
QGraphicsScene* scene2 = new QGraphicsScene;
QPixmap pixmap(QPixmap::fromImage(qImage));
QGraphicsPixmapItem *item = new QGraphicsPixmapItem( pixmap, 0, scene);
item->scale(10.0, 3.0);
QPixmap pixmap2(QPixmap::fromImage(legend));
QGraphicsPixmapItem *item2 = new QGraphicsPixmapItem( pixmap2, 0, scene2);
item2->scale(20.0, 1.0);
m_Controls->m_PerSliceView->SetResidualPixmapItem(item);
m_Controls->m_PerSliceView->setScene(scene);
m_Controls->m_LegendView->setScene(scene2);
m_Controls->m_PerSliceView->show();
m_Controls->m_PerSliceView->repaint();
m_Controls->m_LegendView->setHorizontalScrollBarPolicy ( Qt::ScrollBarAlwaysOff );
m_Controls->m_LegendView->setVerticalScrollBarPolicy ( Qt::ScrollBarAlwaysOff );
m_Controls->m_LegendView->show();
m_Controls->m_LegendView->repaint();
}
void QmitkTensorReconstructionView::Reconstruct()
{
int method = m_Controls->m_ReconctructionMethodBox->currentIndex();
switch (method)
{
case 0:
ItkTensorReconstruction(m_DiffusionImages);
break;
case 1:
TensorReconstructionWithCorr(m_DiffusionImages);
break;
default:
ItkTensorReconstruction(m_DiffusionImages);
}
}
void QmitkTensorReconstructionView::TensorReconstructionWithCorr
(mitk::DataStorage::SetOfObjects::Pointer inImages)
{
try
{
int nrFiles = inImages->size();
if (!nrFiles) return;
QString status;
mitk::ProgressBar::GetInstance()->AddStepsToDo(nrFiles);
mitk::DataStorage::SetOfObjects::const_iterator itemiter( inImages->begin() );
mitk::DataStorage::SetOfObjects::const_iterator itemiterend( inImages->end() );
while ( itemiter != itemiterend ) // for all items
{
typedef mitk::DiffusionImage<DiffusionPixelType> DiffusionImageType;
typedef DiffusionImageType::GradientDirectionContainerType GradientDirectionContainerType;
DiffusionImageType* vols = static_cast<DiffusionImageType*>((*itemiter)->GetData());
std::string nodename;
(*itemiter)->GetStringProperty("name", nodename);
// TENSOR RECONSTRUCTION
MITK_INFO << "Tensor reconstruction with correction for negative eigenvalues";
mitk::StatusBar::GetInstance()->DisplayText(status.sprintf("Tensor reconstruction for %s", nodename.c_str()).toAscii());
typedef itk::TensorReconstructionWithEigenvalueCorrectionFilter< DiffusionPixelType, TTensorPixelType > ReconstructionFilter;
float b0Threshold = m_Controls->m_TensorReconstructionThreshold->value();
GradientDirectionContainerType::Pointer gradientContainerCopy = GradientDirectionContainerType::New();
for(GradientDirectionContainerType::ConstIterator it = vols->GetDirections()->Begin();
it != vols->GetDirections()->End(); it++)
{
gradientContainerCopy->push_back(it.Value());
}
ReconstructionFilter::Pointer reconFilter = ReconstructionFilter::New();
reconFilter->SetGradientImage( gradientContainerCopy, vols->GetVectorImage() );
reconFilter->SetBValue(vols->GetReferenceBValue());
reconFilter->SetB0Threshold(b0Threshold);
reconFilter->Update();
typedef itk::Image<itk::DiffusionTensor3D<TTensorPixelType>, 3> TensorImageType;
TensorImageType::Pointer outputTensorImg = reconFilter->GetOutput();
typedef itk::ImageRegionIterator<TensorImageType> TensorImageIteratorType;
TensorImageIteratorType tensorIt(outputTensorImg, outputTensorImg->GetRequestedRegion());
tensorIt.GoToBegin();
int negatives = 0;
while(!tensorIt.IsAtEnd())
{
typedef itk::DiffusionTensor3D<TTensorPixelType> TensorType;
TensorType tensor = tensorIt.Get();
TensorType::EigenValuesArrayType ev;
tensor.ComputeEigenValues(ev);
for(unsigned int i=0; i<ev.Size(); i++)
{
if(ev[i] < 0.0)
{
tensor.Fill(0.0);
tensorIt.Set(tensor);
negatives++;
break;
}
}
++tensorIt;
}
MITK_INFO << negatives << " tensors with negative eigenvalues" << std::endl;
mitk::TensorImage::Pointer image = mitk::TensorImage::New();
image->InitializeByItk( outputTensorImg.GetPointer() );
image->SetVolume( outputTensorImg->GetBufferPointer() );
mitk::DataNode::Pointer node=mitk::DataNode::New();
node->SetData( image );
SetDefaultNodeProperties(node, nodename+"_EigenvalueCorrected_DT");
GetDefaultDataStorage()->Add(node, *itemiter);
mitk::ProgressBar::GetInstance()->Progress();
++itemiter;
}
mitk::StatusBar::GetInstance()->DisplayText(status.sprintf("Finished Processing %d Files", nrFiles).toAscii());
m_MultiWidget->RequestUpdate();
}
catch (itk::ExceptionObject &ex)
{
MITK_INFO << ex ;
QMessageBox::information(0, "Reconstruction not possible:", ex.GetDescription());
}
}
void QmitkTensorReconstructionView::ItkTensorReconstruction(mitk::DataStorage::SetOfObjects::Pointer inImages)
{
try
{
itk::TimeProbe clock;
int nrFiles = inImages->size();
if (!nrFiles) return;
QString status;
mitk::ProgressBar::GetInstance()->AddStepsToDo(nrFiles);
mitk::DataStorage::SetOfObjects::const_iterator itemiter( inImages->begin() );
mitk::DataStorage::SetOfObjects::const_iterator itemiterend( inImages->end() );
while ( itemiter != itemiterend ) // for all items
{
mitk::DiffusionImage<DiffusionPixelType>* vols =
static_cast<mitk::DiffusionImage<DiffusionPixelType>*>(
(*itemiter)->GetData());
std::string nodename;
(*itemiter)->GetStringProperty("name", nodename);
// TENSOR RECONSTRUCTION
clock.Start();
MITK_DEBUG << "Tensor reconstruction ";
mitk::StatusBar::GetInstance()->DisplayText(status.sprintf("Tensor reconstruction for %s", nodename.c_str()).toAscii());
typedef itk::DiffusionTensor3DReconstructionImageFilter<
DiffusionPixelType, DiffusionPixelType, TTensorPixelType > TensorReconstructionImageFilterType;
TensorReconstructionImageFilterType::Pointer tensorReconstructionFilter =
TensorReconstructionImageFilterType::New();
typedef mitk::DiffusionImage<DiffusionPixelType> DiffusionImageType;
typedef DiffusionImageType::GradientDirectionContainerType GradientDirectionContainerType;
GradientDirectionContainerType::Pointer gradientContainerCopy = GradientDirectionContainerType::New();
for(GradientDirectionContainerType::ConstIterator it = vols->GetDirections()->Begin();
it != vols->GetDirections()->End(); it++)
{
gradientContainerCopy->push_back(it.Value());
}
tensorReconstructionFilter->SetGradientImage( gradientContainerCopy, vols->GetVectorImage() );
tensorReconstructionFilter->SetBValue(vols->GetReferenceBValue());
tensorReconstructionFilter->SetThreshold( m_Controls->m_TensorReconstructionThreshold->value() );
tensorReconstructionFilter->Update();
clock.Stop();
MITK_DEBUG << "took " << clock.GetMean() << "s.";
// TENSORS TO DATATREE
mitk::TensorImage::Pointer image = mitk::TensorImage::New();
typedef itk::Image<itk::DiffusionTensor3D<TTensorPixelType>, 3> TensorImageType;
TensorImageType::Pointer tensorImage;
tensorImage = tensorReconstructionFilter->GetOutput();
// Check the tensor for negative eigenvalues
if(m_Controls->m_CheckNegativeEigenvalues->isChecked())
{
typedef itk::ImageRegionIterator<TensorImageType> TensorImageIteratorType;
TensorImageIteratorType tensorIt(tensorImage, tensorImage->GetRequestedRegion());
tensorIt.GoToBegin();
while(!tensorIt.IsAtEnd())
{
typedef itk::DiffusionTensor3D<TTensorPixelType> TensorType;
//typedef itk::Tensor<TTensorPixelType, 3> TensorType2;
TensorType tensor = tensorIt.Get();
TensorType::EigenValuesArrayType ev;
tensor.ComputeEigenValues(ev);
for(unsigned int i=0; i<ev.Size(); i++)
{
if(ev[i] < 0.0)
{
tensor.Fill(0.0);
tensorIt.Set(tensor);
break;
}
}
++tensorIt;
}
}
tensorImage->SetDirection( vols->GetVectorImage()->GetDirection() );
image->InitializeByItk( tensorImage.GetPointer() );
image->SetVolume( tensorReconstructionFilter->GetOutput()->GetBufferPointer() );
mitk::DataNode::Pointer node=mitk::DataNode::New();
node->SetData( image );
SetDefaultNodeProperties(node, nodename+"_WeightedLinearLeastSquares_DT");
GetDefaultDataStorage()->Add(node, *itemiter);
mitk::ProgressBar::GetInstance()->Progress();
++itemiter;
}
mitk::StatusBar::GetInstance()->DisplayText(status.sprintf("Finished Processing %d Files", nrFiles).toAscii());
m_MultiWidget->RequestUpdate();
}
catch (itk::ExceptionObject &ex)
{
MITK_INFO << ex ;
QMessageBox::information(0, "Reconstruction not possible:", ex.GetDescription());
return;
}
}
void QmitkTensorReconstructionView::SetDefaultNodeProperties(mitk::DataNode::Pointer node, std::string name)
{
node->SetProperty( "ShowMaxNumber", mitk::IntProperty::New( 500 ) );
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", mitk::BoolProperty::New( false ) );
node->SetProperty ("layer", mitk::IntProperty::New(100));
node->SetProperty( "DoRefresh", mitk::BoolProperty::New( true ) );
node->SetProperty( "name", mitk::StringProperty::New(name) );
}
void QmitkTensorReconstructionView::TensorsToDWI()
{
DoTensorsToDWI(m_TensorImages);
}
void QmitkTensorReconstructionView::TensorsToQbi()
{
for (unsigned int i=0; i<m_TensorImages->size(); i++)
{
mitk::DataNode::Pointer tensorImageNode = m_TensorImages->at(i);
MITK_INFO << "starting Q-Ball estimation";
typedef float TTensorPixelType;
typedef itk::DiffusionTensor3D< TTensorPixelType > TensorPixelType;
typedef itk::Image< TensorPixelType, 3 > TensorImageType;
TensorImageType::Pointer itkvol = TensorImageType::New();
mitk::CastToItkImage<TensorImageType>(dynamic_cast<mitk::TensorImage*>(tensorImageNode->GetData()), itkvol);
typedef itk::TensorImageToQBallImageFilter< TTensorPixelType, TTensorPixelType > FilterType;
FilterType::Pointer filter = FilterType::New();
filter->SetInput( itkvol );
filter->Update();
typedef itk::Vector<TTensorPixelType,QBALL_ODFSIZE> OutputPixelType;
typedef itk::Image<OutputPixelType,3> OutputImageType;
mitk::QBallImage::Pointer image = mitk::QBallImage::New();
OutputImageType::Pointer outimg = filter->GetOutput();
image->InitializeByItk( outimg.GetPointer() );
image->SetVolume( outimg->GetBufferPointer() );
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData( image );
node->SetName(tensorImageNode->GetName()+"_Qball");
GetDefaultDataStorage()->Add(node, tensorImageNode);
}
}
void QmitkTensorReconstructionView::OnSelectionChanged( std::vector<mitk::DataNode*> nodes )
{
m_DiffusionImages = mitk::DataStorage::SetOfObjects::New();
m_TensorImages = mitk::DataStorage::SetOfObjects::New();
bool foundDwiVolume = false;
bool foundTensorVolume = false;
m_Controls->m_DiffusionImageLabel->setText("<font color='red'>mandatory</font>");
m_DiffusionImage = NULL;
m_TensorImage = NULL;
m_Controls->m_InputData->setTitle("Please Select Input Data");
// iterate selection
for( std::vector<mitk::DataNode*>::iterator it = nodes.begin(); it != nodes.end(); ++it )
{
mitk::DataNode::Pointer node = *it;
if (node.IsNull())
continue;
// only look at interesting types
if(dynamic_cast<mitk::DiffusionImage<short>*>(node->GetData()))
{
foundDwiVolume = true;
m_Controls->m_DiffusionImageLabel->setText(node->GetName().c_str());
m_DiffusionImages->push_back(node);
m_DiffusionImage = node;
}
else if(dynamic_cast<mitk::TensorImage*>(node->GetData()))
{
foundTensorVolume = true;
m_Controls->m_DiffusionImageLabel->setText(node->GetName().c_str());
m_TensorImages->push_back(node);
m_TensorImage = node;
}
}
m_Controls->m_StartReconstruction->setEnabled(foundDwiVolume);
m_Controls->m_TensorsToDWIButton->setEnabled(foundTensorVolume);
m_Controls->m_TensorsToQbiButton->setEnabled(foundTensorVolume);
if (foundDwiVolume || foundTensorVolume)
m_Controls->m_InputData->setTitle("Input Data");
m_Controls->m_ResidualButton->setEnabled(foundDwiVolume && foundTensorVolume);
m_Controls->m_PercentagesOfOutliers->setEnabled(foundDwiVolume && foundTensorVolume);
m_Controls->m_PerSliceView->setEnabled(foundDwiVolume && foundTensorVolume);
}
template<int ndirs>
QmitkTensorReconstructionView::GradientListType::Pointer QmitkTensorReconstructionView::MakeGradientList()
{
QmitkTensorReconstructionView::GradientListType::Pointer retval = GradientListType::New();
vnl_matrix_fixed<double, 3, ndirs>* U =
itk::PointShell<ndirs, vnl_matrix_fixed<double, 3, ndirs> >::DistributePointShell();
for(int i=0; i<ndirs;i++)
{
GradientType v;
v[0] = U->get(0,i); v[1] = U->get(1,i); v[2] = U->get(2,i);
retval->push_back(v);
}
// Add 0 vector for B0
GradientType v(0.0);
retval->push_back(v);
return retval;
}
void QmitkTensorReconstructionView::DoTensorsToDWI(mitk::DataStorage::SetOfObjects::Pointer inImages)
{
try
{
itk::TimeProbe clock;
int nrFiles = inImages->size();
if (!nrFiles) return;
QString status;
mitk::ProgressBar::GetInstance()->AddStepsToDo(nrFiles);
mitk::DataStorage::SetOfObjects::const_iterator itemiter( inImages->begin() );
mitk::DataStorage::SetOfObjects::const_iterator itemiterend( inImages->end() );
while ( itemiter != itemiterend ) // for all items
{
std::string nodename;
(*itemiter)->GetStringProperty("name", nodename);
mitk::TensorImage* vol =
static_cast<mitk::TensorImage*>((*itemiter)->GetData());
typedef float TTensorPixelType;
typedef itk::DiffusionTensor3D< TTensorPixelType > TensorPixelType;
typedef itk::Image< TensorPixelType, 3 > TensorImageType;
TensorImageType::Pointer itkvol = TensorImageType::New();
mitk::CastToItkImage<TensorImageType>(vol, itkvol);
typedef itk::TensorImageToDiffusionImageFilter<
TTensorPixelType, DiffusionPixelType > FilterType;
FilterType::GradientListType::Pointer gradientList;
switch(m_Controls->m_TensorsToDWINumDirsSelect->currentIndex())
{
case 0:
gradientList = MakeGradientList<12>();
break;
case 1:
gradientList = MakeGradientList<42>();
break;
case 2:
gradientList = MakeGradientList<92>();
break;
case 3:
gradientList = MakeGradientList<162>();
break;
case 4:
gradientList = MakeGradientList<252>();
break;
case 5:
gradientList = MakeGradientList<362>();
break;
case 6:
gradientList = MakeGradientList<492>();
break;
case 7:
gradientList = MakeGradientList<642>();
break;
case 8:
gradientList = MakeGradientList<812>();
break;
case 9:
gradientList = MakeGradientList<1002>();
break;
default:
gradientList = MakeGradientList<92>();
}
double bVal = m_Controls->m_TensorsToDWIBValueEdit->text().toDouble();
// DWI ESTIMATION
clock.Start();
MBI_INFO << "DWI Estimation ";
mitk::StatusBar::GetInstance()->DisplayText(status.sprintf(
"DWI Estimation for %s", nodename.c_str()).toAscii());
FilterType::Pointer filter = FilterType::New();
filter->SetInput( itkvol );
filter->SetBValue(bVal);
filter->SetGradientList(gradientList);
//filter->SetNumberOfThreads(1);
filter->Update();
clock.Stop();
MBI_DEBUG << "took " << clock.GetMean() << "s.";
// TENSORS TO DATATREE
mitk::DiffusionImage<DiffusionPixelType>::Pointer image = mitk::DiffusionImage<DiffusionPixelType>::New();
image->SetVectorImage( filter->GetOutput() );
image->SetReferenceBValue(bVal);
image->SetDirections(gradientList);
image->InitializeFromVectorImage();
mitk::DataNode::Pointer node=mitk::DataNode::New();
node->SetData( image );
mitk::DiffusionImageMapper<short>::SetDefaultProperties(node);
node->SetName(nodename+"_DWI");
GetDefaultDataStorage()->Add(node, *itemiter);
mitk::ProgressBar::GetInstance()->Progress();
++itemiter;
}
mitk::StatusBar::GetInstance()->DisplayText(status.sprintf("Finished Processing %d Files", nrFiles).toAscii());
m_MultiWidget->RequestUpdate();
}
catch (itk::ExceptionObject &ex)
{
MITK_INFO << ex ;
QMessageBox::information(0, "DWI estimation failed:", ex.GetDescription());
return ;
}
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTractbasedSpatialStatisticsView.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTractbasedSpatialStatisticsView.h
index c6a5ce32e3..e2ff1abc48 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTractbasedSpatialStatisticsView.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTractbasedSpatialStatisticsView.h
@@ -1,178 +1,178 @@
/*===================================================================
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 QmitkTractbasedSpatialStatisticsView_h
#define QmitkTractbasedSpatialStatisticsView_h
#include <QmitkFunctionality.h>
#include "ui_QmitkTractbasedSpatialStatisticsViewControls.h"
#include <QListWidgetItem>
#include <itkImageFileReader.h>
#include <itkImageFileWriter.h>
#include <mitkDataNodeFactory.h>
#include <itkDiffusionTensor3D.h>
#include <mitkTbssImage.h>
#include <mitkTbssRoiImage.h>
#include "QmitkTbssTableModel.h"
#include "QmitkTbssMetaTableModel.h"
#include <mitkFiberBundleX.h>
// Image types
typedef short DiffusionPixelType;
typedef itk::Image<char, 3> CharImageType;
typedef itk::Image<unsigned char, 3> UCharImageType;
typedef itk::Image<float, 4> Float4DImageType;
typedef itk::Image<float, 3> FloatImageType;
typedef itk::VectorImage<float, 3> VectorImageType;
// Readers/Writers
typedef itk::ImageFileReader< CharImageType > CharReaderType;
typedef itk::ImageFileReader< UCharImageType > UCharReaderType;
typedef itk::ImageFileWriter< CharImageType > CharWriterType;
typedef itk::ImageFileReader< FloatImageType > FloatReaderType;
typedef itk::ImageFileWriter< FloatImageType > FloatWriterType;
typedef itk::ImageFileReader< Float4DImageType > Float4DReaderType;
typedef itk::ImageFileWriter< Float4DImageType > Float4DWriterType;
/*!
* \brief This plugin provides an extension for Tract-based spatial statistics (see Smith et al., 2009. http://dx.doi.org/10.1016/j.neuroimage.2006.02.024)
* TBSS enables analyzing the brain by a pipeline of registration, skeletonization, and projection that results in a white matter skeleton
* for all subjects that are analyzed statistically in a whole-brain manner.
* This plugin provides functionality to select single tracts and analyze them separately.
*
* Prerequisites: the mean_FA_skeleton and all_FA_skeletonised datasets produced by the FSL TBSS pipeline: http://fsl.fmrib.ox.ac.uk/fsl/fsl4.0/tbss/index
*/
class QmitkTractbasedSpatialStatisticsView : public QmitkFunctionality
{
Q_OBJECT
public:
static const std::string VIEW_ID;
QmitkTractbasedSpatialStatisticsView();
virtual ~QmitkTractbasedSpatialStatisticsView();
virtual void CreateQtPartControl(QWidget *parent);
/// \brief Creation of the connections of main and control widget
virtual void CreateConnections();
virtual void StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget);
virtual void StdMultiWidgetNotAvailable();
/// \brief Called when the functionality is activated
virtual void Activated();
virtual void Deactivated();
protected slots:
// Creates Roi
void CreateRoi();
void Clicked(const QPointF& pos);
// Import of FSL TBSS data
void TbssImport();
// Add a group as metadata. This metadata is required by the plotting functionality
void AddGroup();
// Remove a group
void RemoveGroup();
// Copies the values displayed in the plot widget to clipboard, i.e. exports the data
void CopyToClipboard();
// Method to cut away parts of fiber bundles that should not be plotted.
void Cut();
// Adjust plot widget
void PerformChange();
protected:
/// \brief called by QmitkFunctionality when DataManager's selection has changed
virtual void OnSelectionChanged( std::vector<mitk::DataNode*> nodes );
// Creates a plot using a 4D image containing the projections of all subjects and a region of interest
void Plot(mitk::TbssImage*, mitk::TbssRoiImage*);
void PlotFiberBundle(mitk::FiberBundleX* fib, mitk::Image* img, mitk::PlanarFigure* startRoi=NULL, mitk::PlanarFigure* endRoi=NULL);
void PlotFiber4D(mitk::TbssImage*, mitk::FiberBundleX* fib, mitk::PlanarFigure* startRoi=NULL, mitk::PlanarFigure* endRoi=NULL);
// Create a point set. This point set defines the points through which a region of interest should go
void InitPointsets();
// Pointset and DataNode to contain the PointSet used in ROI creation
mitk::PointSet::Pointer m_PointSetNode;
mitk::DataNode::Pointer m_P1;
// GUI widgets
Ui::QmitkTractbasedSpatialStatisticsViewControls* m_Controls;
/* A pointer to the QmitkStdMultiWidget. Used for interaction with the plot widget
(clicking in the plot widget makes the image cross jump to the corresponding location
on the skeleton).*/
QmitkStdMultiWidget* m_MultiWidget;
// Used to save the region of interest in a vector of itk::index.
std::vector< itk::Index<3> > m_Roi;
mitk::FiberBundleX* m_Fib;
- mitk::Geometry3D* m_CurrentGeometry;
+ mitk::BaseGeometry* m_CurrentGeometry;
// A table model for saving group information in a name,number pair.
QmitkTbssTableModel* m_GroupModel;
// Convenience function for adding a new image to the datastorage and giving it a name.
void AddTbssToDataStorage(mitk::Image* image, std::string name);
mitk::DataNode::Pointer m_CurrentFiberNode; // needed for the index property when interacting with the plot widget
// needed when a plot should only show values between a start end end roi
mitk::DataNode::Pointer m_CurrentStartRoi;
mitk::DataNode::Pointer m_CurrentEndRoi;
};
#endif // _QMITKTRACTBASEDSPATIALSTATISTICSVIEW_H_INCLUDED
diff --git a/Plugins/org.mitk.gui.qt.imagenavigator/src/internal/QmitkImageNavigatorView.cpp b/Plugins/org.mitk.gui.qt.imagenavigator/src/internal/QmitkImageNavigatorView.cpp
index 7a0ef17049..b8c7837d90 100644
--- a/Plugins/org.mitk.gui.qt.imagenavigator/src/internal/QmitkImageNavigatorView.cpp
+++ b/Plugins/org.mitk.gui.qt.imagenavigator/src/internal/QmitkImageNavigatorView.cpp
@@ -1,407 +1,407 @@
/*===================================================================
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 "QmitkImageNavigatorView.h"
#include <QmitkStepperAdapter.h>
#include <QmitkRenderWindow.h>
#include <mitkTimeGeometry.h>
#include <berryConstants.h>
#include <mitkPlaneGeometry.h>
const std::string QmitkImageNavigatorView::VIEW_ID = "org.mitk.views.imagenavigator";
QmitkImageNavigatorView::QmitkImageNavigatorView()
: m_AxialStepper(0)
, m_SagittalStepper(0)
, m_FrontalStepper(0)
, m_TimeStepper(0)
, m_Parent(0)
, m_IRenderWindowPart(0)
{
}
QmitkImageNavigatorView::~QmitkImageNavigatorView()
{
}
void QmitkImageNavigatorView::CreateQtPartControl(QWidget *parent)
{
// create GUI widgets
m_Parent = parent;
m_Controls.setupUi(parent);
m_Controls.m_SliceNavigatorAxial->SetInverseDirection(true);
connect(m_Controls.m_XWorldCoordinateSpinBox, SIGNAL(valueChanged(double)), this, SLOT(OnMillimetreCoordinateValueChanged()));
connect(m_Controls.m_YWorldCoordinateSpinBox, SIGNAL(valueChanged(double)), this, SLOT(OnMillimetreCoordinateValueChanged()));
connect(m_Controls.m_ZWorldCoordinateSpinBox, SIGNAL(valueChanged(double)), this, SLOT(OnMillimetreCoordinateValueChanged()));
m_Parent->setEnabled(false);
mitk::IRenderWindowPart* renderPart = this->GetRenderWindowPart();
this->RenderWindowPartActivated(renderPart);
}
void QmitkImageNavigatorView::SetFocus ()
{
m_Controls.m_XWorldCoordinateSpinBox->setFocus();
}
void QmitkImageNavigatorView::RenderWindowPartActivated(mitk::IRenderWindowPart* renderWindowPart)
{
if (this->m_IRenderWindowPart != renderWindowPart)
{
this->m_IRenderWindowPart = renderWindowPart;
this->m_Parent->setEnabled(true);
QmitkRenderWindow* renderWindow = renderWindowPart->GetQmitkRenderWindow("axial");
if (renderWindow)
{
if (m_AxialStepper) m_AxialStepper->deleteLater();
m_AxialStepper = new QmitkStepperAdapter(m_Controls.m_SliceNavigatorAxial,
renderWindow->GetSliceNavigationController()->GetSlice(),
"sliceNavigatorAxialFromSimpleExample");
m_Controls.m_SliceNavigatorAxial->setEnabled(true);
m_Controls.m_AxialLabel->setEnabled(true);
m_Controls.m_ZWorldCoordinateSpinBox->setEnabled(true);
connect(m_AxialStepper, SIGNAL(Refetch()), this, SLOT(OnRefetch()));
}
else
{
m_Controls.m_SliceNavigatorAxial->setEnabled(false);
m_Controls.m_AxialLabel->setEnabled(false);
m_Controls.m_ZWorldCoordinateSpinBox->setEnabled(false);
}
renderWindow = renderWindowPart->GetQmitkRenderWindow("sagittal");
if (renderWindow)
{
if (m_SagittalStepper) m_SagittalStepper->deleteLater();
m_SagittalStepper = new QmitkStepperAdapter(m_Controls.m_SliceNavigatorSagittal,
renderWindow->GetSliceNavigationController()->GetSlice(),
"sliceNavigatorSagittalFromSimpleExample");
m_Controls.m_SliceNavigatorSagittal->setEnabled(true);
m_Controls.m_SagittalLabel->setEnabled(true);
m_Controls.m_YWorldCoordinateSpinBox->setEnabled(true);
connect(m_SagittalStepper, SIGNAL(Refetch()), this, SLOT(OnRefetch()));
}
else
{
m_Controls.m_SliceNavigatorSagittal->setEnabled(false);
m_Controls.m_SagittalLabel->setEnabled(false);
m_Controls.m_YWorldCoordinateSpinBox->setEnabled(false);
}
renderWindow = renderWindowPart->GetQmitkRenderWindow("coronal");
if (renderWindow)
{
if (m_FrontalStepper) m_FrontalStepper->deleteLater();
m_FrontalStepper = new QmitkStepperAdapter(m_Controls.m_SliceNavigatorFrontal,
renderWindow->GetSliceNavigationController()->GetSlice(),
"sliceNavigatorFrontalFromSimpleExample");
m_Controls.m_SliceNavigatorFrontal->setEnabled(true);
m_Controls.m_CoronalLabel->setEnabled(true);
m_Controls.m_XWorldCoordinateSpinBox->setEnabled(true);
connect(m_FrontalStepper, SIGNAL(Refetch()), this, SLOT(OnRefetch()));
}
else
{
m_Controls.m_SliceNavigatorFrontal->setEnabled(false);
m_Controls.m_CoronalLabel->setEnabled(false);
m_Controls.m_XWorldCoordinateSpinBox->setEnabled(false);
}
mitk::SliceNavigationController* timeController = renderWindowPart->GetTimeNavigationController();
if (timeController)
{
if (m_TimeStepper) m_TimeStepper->deleteLater();
m_TimeStepper = new QmitkStepperAdapter(m_Controls.m_SliceNavigatorTime,
timeController->GetTime(),
"sliceNavigatorTimeFromSimpleExample");
m_Controls.m_SliceNavigatorTime->setEnabled(true);
m_Controls.m_TimeLabel->setEnabled(true);
}
else
{
m_Controls.m_SliceNavigatorTime->setEnabled(false);
m_Controls.m_TimeLabel->setEnabled(false);
}
}
}
void QmitkImageNavigatorView::RenderWindowPartDeactivated(mitk::IRenderWindowPart* /*renderWindowPart*/)
{
m_IRenderWindowPart = 0;
m_Parent->setEnabled(false);
}
int QmitkImageNavigatorView::GetSizeFlags(bool width)
{
if(!width)
{
return berry::Constants::MIN | berry::Constants::MAX | berry::Constants::FILL;
}
else
{
return 0;
}
}
int QmitkImageNavigatorView::ComputePreferredSize(bool width, int /*availableParallel*/, int /*availablePerpendicular*/, int preferredResult)
{
if(width==false)
{
return 200;
}
else
{
return preferredResult;
}
}
int QmitkImageNavigatorView::GetClosestAxisIndex(mitk::Vector3D normal)
{
// cos(theta) = normal . axis
// cos(theta) = (a, b, c) . (d, e, f)
// cos(theta) = (a, b, c) . (1, 0, 0) = a
// cos(theta) = (a, b, c) . (0, 1, 0) = b
// cos(theta) = (a, b, c) . (0, 0, 1) = c
double absCosThetaWithAxis[3];
for (int i = 0; i < 3; i++)
{
absCosThetaWithAxis[i] = fabs(normal[i]);
}
int largestIndex = 0;
double largestValue = absCosThetaWithAxis[0];
for (int i = 1; i < 3; i++)
{
if (absCosThetaWithAxis[i] > largestValue)
{
largestValue = absCosThetaWithAxis[i];
largestIndex = i;
}
}
return largestIndex;
}
void QmitkImageNavigatorView::SetBorderColors()
{
if (m_IRenderWindowPart)
{
QmitkRenderWindow* renderWindow = m_IRenderWindowPart->GetQmitkRenderWindow("axial");
if (renderWindow)
{
mitk::PlaneGeometry::ConstPointer geometry = renderWindow->GetSliceNavigationController()->GetCurrentPlaneGeometry();
if (geometry.IsNotNull())
{
mitk::Vector3D normal = geometry->GetNormal();
int axis = this->GetClosestAxisIndex(normal);
this->SetBorderColor(axis, QString("red"));
}
}
renderWindow = m_IRenderWindowPart->GetQmitkRenderWindow("sagittal");
if (renderWindow)
{
mitk::PlaneGeometry::ConstPointer geometry = renderWindow->GetSliceNavigationController()->GetCurrentPlaneGeometry();
if (geometry.IsNotNull())
{
mitk::Vector3D normal = geometry->GetNormal();
int axis = this->GetClosestAxisIndex(normal);
this->SetBorderColor(axis, QString("green"));
}
}
renderWindow = m_IRenderWindowPart->GetQmitkRenderWindow("coronal");
if (renderWindow)
{
mitk::PlaneGeometry::ConstPointer geometry = renderWindow->GetSliceNavigationController()->GetCurrentPlaneGeometry();
if (geometry.IsNotNull())
{
mitk::Vector3D normal = geometry->GetNormal();
int axis = this->GetClosestAxisIndex(normal);
this->SetBorderColor(axis, QString("blue"));
}
}
}
}
void QmitkImageNavigatorView::SetBorderColor(int axis, QString colorAsStyleSheetString)
{
if (axis == 0)
{
this->SetBorderColor(m_Controls.m_XWorldCoordinateSpinBox, colorAsStyleSheetString);
}
else if (axis == 1)
{
this->SetBorderColor(m_Controls.m_YWorldCoordinateSpinBox, colorAsStyleSheetString);
}
else if (axis == 2)
{
this->SetBorderColor(m_Controls.m_ZWorldCoordinateSpinBox, colorAsStyleSheetString);
}
}
void QmitkImageNavigatorView::SetBorderColor(QDoubleSpinBox *spinBox, QString colorAsStyleSheetString)
{
assert(spinBox);
spinBox->setStyleSheet(QString("border: 2px solid ") + colorAsStyleSheetString + ";");
}
void QmitkImageNavigatorView::SetStepSizes()
{
this->SetStepSize(0);
this->SetStepSize(1);
this->SetStepSize(2);
}
void QmitkImageNavigatorView::SetStepSize(int axis)
{
if (m_IRenderWindowPart)
{
- mitk::Geometry3D::ConstPointer geometry = m_IRenderWindowPart->GetActiveQmitkRenderWindow()->GetSliceNavigationController()->GetInputWorldGeometry3D();
+ mitk::BaseGeometry::ConstPointer geometry = m_IRenderWindowPart->GetActiveQmitkRenderWindow()->GetSliceNavigationController()->GetInputWorldGeometry3D();
if (geometry.IsNotNull())
{
mitk::Point3D crossPositionInIndexCoordinates;
mitk::Point3D crossPositionInIndexCoordinatesPlus1;
mitk::Point3D crossPositionInMillimetresPlus1;
mitk::Vector3D transformedAxisDirection;
mitk::Point3D crossPositionInMillimetres = m_IRenderWindowPart->GetSelectedPosition();
geometry->WorldToIndex(crossPositionInMillimetres, crossPositionInIndexCoordinates);
crossPositionInIndexCoordinatesPlus1 = crossPositionInIndexCoordinates;
crossPositionInIndexCoordinatesPlus1[axis] += 1;
geometry->IndexToWorld(crossPositionInIndexCoordinatesPlus1, crossPositionInMillimetresPlus1);
transformedAxisDirection = crossPositionInMillimetresPlus1 - crossPositionInMillimetres;
int closestAxisInMillimetreSpace = this->GetClosestAxisIndex(transformedAxisDirection);
double stepSize = transformedAxisDirection.GetNorm();
this->SetStepSize(closestAxisInMillimetreSpace, stepSize);
}
}
}
void QmitkImageNavigatorView::SetStepSize(int axis, double stepSize)
{
if (axis == 0)
{
m_Controls.m_XWorldCoordinateSpinBox->setSingleStep(stepSize);
}
else if (axis == 1)
{
m_Controls.m_YWorldCoordinateSpinBox->setSingleStep(stepSize);
}
else if (axis == 2)
{
m_Controls.m_ZWorldCoordinateSpinBox->setSingleStep(stepSize);
}
}
void QmitkImageNavigatorView::OnMillimetreCoordinateValueChanged()
{
if (m_IRenderWindowPart)
{
mitk::TimeGeometry::ConstPointer geometry = m_IRenderWindowPart->GetActiveQmitkRenderWindow()->GetSliceNavigationController()->GetInputWorldTimeGeometry();
if (geometry.IsNotNull())
{
mitk::Point3D positionInWorldCoordinates;
positionInWorldCoordinates[0] = m_Controls.m_XWorldCoordinateSpinBox->value();
positionInWorldCoordinates[1] = m_Controls.m_YWorldCoordinateSpinBox->value();
positionInWorldCoordinates[2] = m_Controls.m_ZWorldCoordinateSpinBox->value();
m_IRenderWindowPart->SetSelectedPosition(positionInWorldCoordinates);
}
}
}
void QmitkImageNavigatorView::OnRefetch()
{
if (m_IRenderWindowPart)
{
- mitk::Geometry3D::ConstPointer geometry = m_IRenderWindowPart->GetActiveQmitkRenderWindow()->GetSliceNavigationController()->GetInputWorldGeometry3D();
+ mitk::BaseGeometry::ConstPointer geometry = m_IRenderWindowPart->GetActiveQmitkRenderWindow()->GetSliceNavigationController()->GetInputWorldGeometry3D();
mitk::TimeGeometry::ConstPointer timeGeometry = m_IRenderWindowPart->GetActiveQmitkRenderWindow()->GetSliceNavigationController()->GetInputWorldTimeGeometry();
if (geometry.IsNull() && timeGeometry.IsNotNull())
{
mitk::TimeStepType timeStep = m_IRenderWindowPart->GetActiveQmitkRenderWindow()->GetSliceNavigationController()->GetTime()->GetPos();
geometry = timeGeometry->GetGeometryForTimeStep(timeStep);
}
if (geometry.IsNotNull())
{
mitk::BoundingBox::BoundsArrayType bounds = geometry->GetBounds();
mitk::Point3D cornerPoint1InIndexCoordinates;
cornerPoint1InIndexCoordinates[0] = bounds[0];
cornerPoint1InIndexCoordinates[1] = bounds[2];
cornerPoint1InIndexCoordinates[2] = bounds[4];
mitk::Point3D cornerPoint2InIndexCoordinates;
cornerPoint2InIndexCoordinates[0] = bounds[1];
cornerPoint2InIndexCoordinates[1] = bounds[3];
cornerPoint2InIndexCoordinates[2] = bounds[5];
if (!geometry->GetImageGeometry())
{
cornerPoint1InIndexCoordinates[0] += 0.5;
cornerPoint1InIndexCoordinates[1] += 0.5;
cornerPoint1InIndexCoordinates[2] += 0.5;
cornerPoint2InIndexCoordinates[0] -= 0.5;
cornerPoint2InIndexCoordinates[1] -= 0.5;
cornerPoint2InIndexCoordinates[2] -= 0.5;
}
mitk::Point3D crossPositionInWorldCoordinates = m_IRenderWindowPart->GetSelectedPosition();
mitk::Point3D cornerPoint1InWorldCoordinates;
mitk::Point3D cornerPoint2InWorldCoordinates;
geometry->IndexToWorld(cornerPoint1InIndexCoordinates, cornerPoint1InWorldCoordinates);
geometry->IndexToWorld(cornerPoint2InIndexCoordinates, cornerPoint2InWorldCoordinates);
m_Controls.m_XWorldCoordinateSpinBox->blockSignals(true);
m_Controls.m_YWorldCoordinateSpinBox->blockSignals(true);
m_Controls.m_ZWorldCoordinateSpinBox->blockSignals(true);
m_Controls.m_XWorldCoordinateSpinBox->setMinimum(std::min(cornerPoint1InWorldCoordinates[0], cornerPoint2InWorldCoordinates[0]));
m_Controls.m_YWorldCoordinateSpinBox->setMinimum(std::min(cornerPoint1InWorldCoordinates[1], cornerPoint2InWorldCoordinates[1]));
m_Controls.m_ZWorldCoordinateSpinBox->setMinimum(std::min(cornerPoint1InWorldCoordinates[2], cornerPoint2InWorldCoordinates[2]));
m_Controls.m_XWorldCoordinateSpinBox->setMaximum(std::max(cornerPoint1InWorldCoordinates[0], cornerPoint2InWorldCoordinates[0]));
m_Controls.m_YWorldCoordinateSpinBox->setMaximum(std::max(cornerPoint1InWorldCoordinates[1], cornerPoint2InWorldCoordinates[1]));
m_Controls.m_ZWorldCoordinateSpinBox->setMaximum(std::max(cornerPoint1InWorldCoordinates[2], cornerPoint2InWorldCoordinates[2]));
m_Controls.m_XWorldCoordinateSpinBox->setValue(crossPositionInWorldCoordinates[0]);
m_Controls.m_YWorldCoordinateSpinBox->setValue(crossPositionInWorldCoordinates[1]);
m_Controls.m_ZWorldCoordinateSpinBox->setValue(crossPositionInWorldCoordinates[2]);
m_Controls.m_XWorldCoordinateSpinBox->blockSignals(false);
m_Controls.m_YWorldCoordinateSpinBox->blockSignals(false);
m_Controls.m_ZWorldCoordinateSpinBox->blockSignals(false);
}
this->SetBorderColors();
}
}
diff --git a/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkImageStatisticsView.cpp b/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkImageStatisticsView.cpp
index 74d989eb8b..abe1deec32 100644
--- a/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkImageStatisticsView.cpp
+++ b/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkImageStatisticsView.cpp
@@ -1,932 +1,932 @@
/*===================================================================
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 "QmitkImageStatisticsView.h"
// Qt includes
#include <qclipboard.h>
#include <qscrollbar.h>
// berry includes
#include <berryIWorkbenchPage.h>
// mitk includes
#include "mitkNodePredicateDataType.h"
#include "mitkPlanarFigureInteractor.h"
// itk includes
#include "itksys/SystemTools.hxx"
#include <mitkILinkedRenderWindowPart.h>
#include <QmitkRenderWindow.h>
const std::string QmitkImageStatisticsView::VIEW_ID = "org.mitk.views.imagestatistics";
const int QmitkImageStatisticsView::STAT_TABLE_BASE_HEIGHT = 180;
QmitkImageStatisticsView::QmitkImageStatisticsView(QObject* /*parent*/, const char* /*name*/)
: m_Controls( NULL ),
m_TimeStepperAdapter( NULL ),
m_SelectedImage( NULL ),
m_SelectedImageMask( NULL ),
m_SelectedPlanarFigure( NULL ),
m_ImageObserverTag( -1 ),
m_ImageMaskObserverTag( -1 ),
m_PlanarFigureObserverTag( -1 ),
m_TimeObserverTag( -1 ),
m_CurrentStatisticsValid( false ),
m_StatisticsUpdatePending( false ),
m_DataNodeSelectionChanged ( false ),
m_Visible(false)
{
this->m_CalculationThread = new QmitkImageStatisticsCalculationThread;
}
QmitkImageStatisticsView::~QmitkImageStatisticsView()
{
if ( m_SelectedImage != NULL )
m_SelectedImage->RemoveObserver( m_ImageObserverTag );
if ( m_SelectedImageMask != NULL )
m_SelectedImageMask->RemoveObserver( m_ImageMaskObserverTag );
if ( m_SelectedPlanarFigure != NULL )
m_SelectedPlanarFigure->RemoveObserver( m_PlanarFigureObserverTag );
while(this->m_CalculationThread->isRunning()) // wait until thread has finished
{
itksys::SystemTools::Delay(100);
}
delete this->m_CalculationThread;
}
void QmitkImageStatisticsView::CreateQtPartControl(QWidget *parent)
{
if (m_Controls == NULL)
{
m_Controls = new Ui::QmitkImageStatisticsViewControls;
m_Controls->setupUi(parent);
this->CreateConnections();
m_Controls->m_ErrorMessageLabel->hide();
m_Controls->m_StatisticsWidgetStack->setCurrentIndex( 0 );
m_Controls->m_HistogramBinSizeSlider->setTracking(false);
}
}
void QmitkImageStatisticsView::CreateConnections()
{
if ( m_Controls )
{
connect( (QObject*)(this->m_Controls->m_ButtonCopyHistogramToClipboard), SIGNAL(clicked()),(QObject*) this, SLOT(OnClipboardHistogramButtonClicked()) );
connect( (QObject*)(this->m_Controls->m_ButtonCopyStatisticsToClipboard), SIGNAL(clicked()),(QObject*) this, SLOT(OnClipboardStatisticsButtonClicked()) );
connect( (QObject*)(this->m_Controls->m_IgnoreZerosCheckbox), SIGNAL(clicked()),(QObject*) this, SLOT(OnIgnoreZerosCheckboxClicked()) );
connect( (QObject*) this->m_CalculationThread, SIGNAL(finished()),this, SLOT( OnThreadedStatisticsCalculationEnds()),Qt::QueuedConnection);
connect( (QObject*) this, SIGNAL(StatisticsUpdate()),this, SLOT( RequestStatisticsUpdate()), Qt::QueuedConnection);
connect( (QObject*) this->m_Controls->m_StatisticsTable, SIGNAL(cellDoubleClicked(int,int)),this, SLOT( JumpToCoordinates(int,int)) );
connect( (QObject*) (this->m_Controls->m_barRadioButton), SIGNAL(clicked()), (QObject*) (this->m_Controls->m_JSHistogram), SLOT(OnBarRadioButtonSelected()));
connect( (QObject*) (this->m_Controls->m_lineRadioButton), SIGNAL(clicked()), (QObject*) (this->m_Controls->m_JSHistogram), SLOT(OnLineRadioButtonSelected()));
connect( (QObject*) (this->m_Controls->m_HistogramBinSizeSlider), SIGNAL(valueChanged(int)), this, SLOT(OnHistogramBinSizeSliderValueChanged(int)));
}
}
void QmitkImageStatisticsView::PartClosed( berry::IWorkbenchPartReference::Pointer )
{
}
void QmitkImageStatisticsView::OnTimeChanged(const itk::EventObject& e)
{
if (this->m_SelectedDataNodes.isEmpty() || this->m_SelectedImage == NULL)
return;
const mitk::SliceNavigationController::GeometryTimeEvent* timeEvent =
dynamic_cast<const mitk::SliceNavigationController::GeometryTimeEvent*>(&e);
assert(timeEvent != NULL);
unsigned int timestep = timeEvent->GetPos();
if (this->m_SelectedImage->GetTimeSteps() > 1)
{
for (unsigned int x = 0; x < this->m_Controls->m_StatisticsTable->columnCount(); x++)
{
for (unsigned int y = 0; y < this->m_Controls->m_StatisticsTable->rowCount(); y++)
{
QTableWidgetItem* item = this->m_Controls->m_StatisticsTable->item(y, x);
if (item == NULL)
break;
if (x == timestep)
{
item->setBackgroundColor(Qt::yellow);
}
else
{
if (y % 2 == 0)
item->setBackground(this->m_Controls->m_StatisticsTable->palette().base());
else
item->setBackground(this->m_Controls->m_StatisticsTable->palette().alternateBase());
}
}
}
this->m_Controls->m_StatisticsTable->viewport()->update();
}
if ((this->m_SelectedImage->GetTimeSteps() == 1 && timestep == 0) ||
this->m_SelectedImage->GetTimeSteps() > 1)
{
// display histogram for selected timestep
this->m_Controls->m_JSHistogram->ClearHistogram();
QmitkImageStatisticsCalculationThread::HistogramType::Pointer histogram =
this->m_CalculationThread->GetTimeStepHistogram(timestep);
if (histogram.IsNotNull())
{
this->m_Controls->m_JSHistogram->ComputeHistogram(histogram.GetPointer());
// this->m_Controls->m_JSHistogram->SignalGraphChanged();
// hacky way to make sure the protected SignalGraphChanged() is called
if (this->m_Controls->m_JSHistogram->GetUseLineGraph())
{
this->m_Controls->m_JSHistogram->OnBarRadioButtonSelected();
this->m_Controls->m_JSHistogram->OnLineRadioButtonSelected();
}
else
{
this->m_Controls->m_JSHistogram->OnLineRadioButtonSelected();
this->m_Controls->m_JSHistogram->OnBarRadioButtonSelected();
}
}
}
}
void QmitkImageStatisticsView::JumpToCoordinates(int row ,int col)
{
if(m_SelectedDataNodes.isEmpty())
{
MITK_WARN("QmitkImageStatisticsView") << "No data node selected for statistics calculation." ;
return;
}
mitk::Point3D world;
if (row==4)
world = m_WorldMinList[col];
else if (row==3)
world = m_WorldMaxList[col];
else
return;
mitk::IRenderWindowPart* part = this->GetRenderWindowPart();
if (part)
{
part->GetQmitkRenderWindow("axial")->GetSliceNavigationController()->SelectSliceByPoint(world);
part->GetQmitkRenderWindow("sagittal")->GetSliceNavigationController()->SelectSliceByPoint(world);
part->GetQmitkRenderWindow("coronal")->GetSliceNavigationController()->SelectSliceByPoint(world);
mitk::SliceNavigationController::GeometryTimeEvent timeEvent(this->m_SelectedImage->GetTimeGeometry(), col);
part->GetQmitkRenderWindow("axial")->GetSliceNavigationController()->SetGeometryTime(timeEvent);
}
}
void QmitkImageStatisticsView::OnIgnoreZerosCheckboxClicked()
{
emit StatisticsUpdate();
}
void QmitkImageStatisticsView::OnClipboardHistogramButtonClicked()
{
if ( m_CurrentStatisticsValid )
{
const unsigned int t = this->GetRenderWindowPart()->GetTimeNavigationController()->GetTime()->GetPos();
typedef mitk::ImageStatisticsCalculator::HistogramType HistogramType;
const HistogramType *histogram = this->m_CalculationThread->GetTimeStepHistogram(t).GetPointer();
QString clipboard( "Measurement \t Frequency\n" );
for ( HistogramType::ConstIterator it = histogram->Begin();
it != histogram->End();
++it )
{
if( m_Controls->m_HistogramBinSizeSlider->value() == 1)
{
clipboard = clipboard.append( "%L1 \t %L2\n" )
.arg( it.GetMeasurementVector()[0], 0, 'f', 0 )
.arg( it.GetFrequency() );
}
else
{
clipboard = clipboard.append( "%L1 \t %L2\n" )
.arg( it.GetMeasurementVector()[0], 0, 'f', 2 )
.arg( it.GetFrequency() );
}
}
QApplication::clipboard()->setText(
clipboard, QClipboard::Clipboard );
}
else
{
QApplication::clipboard()->clear();
}
}
void QmitkImageStatisticsView::OnClipboardStatisticsButtonClicked()
{
QLocale tempLocal;
QLocale::setDefault(QLocale(QLocale::English, QLocale::UnitedStates));
if ( this->m_CurrentStatisticsValid )
{
const std::vector<mitk::ImageStatisticsCalculator::Statistics> &statistics =
this->m_CalculationThread->GetStatisticsData();
const unsigned int t = this->GetRenderWindowPart()->GetTimeNavigationController()->GetTime()->
GetPos();
// Copy statistics to clipboard ("%Ln" will use the default locale for
// number formatting)
QString clipboard( "Mean \t StdDev \t RMS \t Max \t Min \t N \t V (mm³)\n" );
clipboard = clipboard.append( "%L1 \t %L2 \t %L3 \t %L4 \t %L5 \t %L6 \t %L7" )
.arg( statistics[t].Mean, 0, 'f', 10 )
.arg( statistics[t].Sigma, 0, 'f', 10 )
.arg( statistics[t].RMS, 0, 'f', 10 )
.arg( statistics[t].Max, 0, 'f', 10 )
.arg( statistics[t].Min, 0, 'f', 10 )
.arg( statistics[t].N )
.arg( m_Controls->m_StatisticsTable->item( 0, 6 )->text().toDouble(), 0, 'f', 10 );
QApplication::clipboard()->setText(
clipboard, QClipboard::Clipboard );
}
else
{
QApplication::clipboard()->clear();
}
QLocale::setDefault(tempLocal);
}
void QmitkImageStatisticsView::OnSelectionChanged( berry::IWorkbenchPart::Pointer /*part*/,
const QList<mitk::DataNode::Pointer> &selectedNodes )
{
if (this->m_Visible)
{
this->SelectionChanged( selectedNodes );
}
else
{
this->m_DataNodeSelectionChanged = true;
}
}
void QmitkImageStatisticsView::SelectionChanged(const QList<mitk::DataNode::Pointer> &selectedNodes)
{
if( this->m_StatisticsUpdatePending )
{
this->m_DataNodeSelectionChanged = true;
return; // not ready for new data now!
}
if (selectedNodes.size() == this->m_SelectedDataNodes.size())
{
int i = 0;
for (; i < selectedNodes.size(); ++i)
{
if (selectedNodes.at(i) != this->m_SelectedDataNodes.at(i))
{
break;
}
}
// node selection did not change
if (i == selectedNodes.size()) return;
}
this->ReinitData();
if (selectedNodes.isEmpty())
{
m_Controls->m_JSHistogram->ClearHistogram();
m_Controls->m_lineRadioButton->setEnabled(true);
m_Controls->m_barRadioButton->setEnabled(true);
m_Controls->m_HistogramBinSizeSlider->setEnabled(true);
m_Controls->m_HistogramBinSizeCaptionLabel->setEnabled(true);
m_Controls->m_HistogramBinSizeLabel->setEnabled(true);
m_Controls->m_InfoLabel->setText(QString(""));
// m_Controls->horizontalLayout_3->setEnabled(false);
m_Controls->groupBox->setEnabled(false);
m_Controls->groupBox_3->setEnabled(false);
}
else
{
// m_Controls->horizontalLayout_3->setEnabled(true);
m_Controls->groupBox->setEnabled(true);
m_Controls->groupBox_3->setEnabled(true);
}
if(selectedNodes.size() == 1 || selectedNodes.size() == 2)
{
bool isBinary = false;
selectedNodes.value(0)->GetBoolProperty("binary",isBinary);
if(isBinary)
{
m_Controls->m_JSHistogram->ClearHistogram();
m_Controls->m_lineRadioButton->setEnabled(true);
m_Controls->m_barRadioButton->setEnabled(true);
m_Controls->m_HistogramBinSizeSlider->setEnabled(true);
m_Controls->m_HistogramBinSizeCaptionLabel->setEnabled(true);
m_Controls->m_HistogramBinSizeLabel->setEnabled(true);
m_Controls->m_InfoLabel->setText(QString(""));
}
for (int i= 0; i< selectedNodes.size(); ++i)
{
this->m_SelectedDataNodes.push_back(selectedNodes.at(i));
}
this->m_DataNodeSelectionChanged = false;
this->m_Controls->m_ErrorMessageLabel->setText( "" );
this->m_Controls->m_ErrorMessageLabel->hide();
emit StatisticsUpdate();
}
else
{
this->m_DataNodeSelectionChanged = false;
}
}
void QmitkImageStatisticsView::ReinitData()
{
while( this->m_CalculationThread->isRunning()) // wait until thread has finished
{
itksys::SystemTools::Delay(100);
}
if(this->m_SelectedImage != NULL)
{
this->m_SelectedImage->RemoveObserver( this->m_ImageObserverTag);
this->m_SelectedImage = NULL;
}
if(this->m_SelectedImageMask != NULL)
{
this->m_SelectedImageMask->RemoveObserver( this->m_ImageMaskObserverTag);
this->m_SelectedImageMask = NULL;
}
if(this->m_SelectedPlanarFigure != NULL)
{
this->m_SelectedPlanarFigure->RemoveObserver( this->m_PlanarFigureObserverTag);
this->m_SelectedPlanarFigure = NULL;
}
this->m_SelectedDataNodes.clear();
this->m_StatisticsUpdatePending = false;
m_Controls->m_ErrorMessageLabel->setText( "" );
m_Controls->m_ErrorMessageLabel->hide();
this->InvalidateStatisticsTableView();
m_Controls->m_JSHistogram->ClearHistogram();
m_Controls->m_StatisticsWidgetStack->setCurrentIndex( 0 );
}
void QmitkImageStatisticsView::OnThreadedStatisticsCalculationEnds()
{
std::stringstream message;
message << "";
m_Controls->m_ErrorMessageLabel->setText( message.str().c_str() );
m_Controls->m_ErrorMessageLabel->hide();
this->WriteStatisticsToGUI();
}
void QmitkImageStatisticsView::UpdateStatistics()
{
mitk::IRenderWindowPart* renderPart = this->GetRenderWindowPart();
if ( renderPart == NULL )
{
this->m_StatisticsUpdatePending = false;
return;
}
m_WorldMinList.clear();
m_WorldMaxList.clear();
// classify selected nodes
mitk::NodePredicateDataType::Pointer imagePredicate = mitk::NodePredicateDataType::New("Image");
std::string maskName = std::string();
std::string maskType = std::string();
unsigned int maskDimension = 0;
// reset data from last run
ITKCommandType::Pointer changeListener = ITKCommandType::New();
changeListener->SetCallbackFunction( this, &QmitkImageStatisticsView::SelectedDataModified );
mitk::DataNode::Pointer planarFigureNode;
for( int i= 0 ; i < this->m_SelectedDataNodes.size(); ++i)
{
mitk::PlanarFigure::Pointer planarFig = dynamic_cast<mitk::PlanarFigure*>(this->m_SelectedDataNodes.at(i)->GetData());
if( imagePredicate->CheckNode(this->m_SelectedDataNodes.at(i)) )
{
bool isMask = false;
this->m_SelectedDataNodes.at(i)->GetPropertyValue("binary", isMask);
if( this->m_SelectedImageMask == NULL && isMask)
{
this->m_SelectedImageMask = dynamic_cast<mitk::Image*>(this->m_SelectedDataNodes.at(i)->GetData());
this->m_ImageMaskObserverTag = this->m_SelectedImageMask->AddObserver(itk::ModifiedEvent(), changeListener);
maskName = this->m_SelectedDataNodes.at(i)->GetName();
maskType = m_SelectedImageMask->GetNameOfClass();
maskDimension = 3;
}
else if( !isMask )
{
if(this->m_SelectedImage == NULL)
{
this->m_SelectedImage = static_cast<mitk::Image*>(this->m_SelectedDataNodes.at(i)->GetData());
this->m_ImageObserverTag = this->m_SelectedImage->AddObserver(itk::ModifiedEvent(), changeListener);
}
}
}
else if (planarFig.IsNotNull())
{
if(this->m_SelectedPlanarFigure == NULL)
{
this->m_SelectedPlanarFigure = planarFig;
this->m_PlanarFigureObserverTag =
this->m_SelectedPlanarFigure->AddObserver(mitk::EndInteractionPlanarFigureEvent(), changeListener);
maskName = this->m_SelectedDataNodes.at(i)->GetName();
maskType = this->m_SelectedPlanarFigure->GetNameOfClass();
maskDimension = 2;
planarFigureNode = m_SelectedDataNodes.at(i);
}
}
else
{
std::stringstream message;
message << "<font color='red'>" << "Invalid data node type!" << "</font>";
m_Controls->m_ErrorMessageLabel->setText( message.str().c_str() );
m_Controls->m_ErrorMessageLabel->show();
}
}
if(maskName == "")
{
maskName = "None";
maskType = "";
maskDimension = 0;
}
if (m_SelectedPlanarFigure != NULL && m_SelectedImage == NULL)
{
mitk::DataStorage::SetOfObjects::ConstPointer parentSet = this->GetDataStorage()->GetSources(planarFigureNode);
for (int i=0; i<parentSet->Size(); i++)
{
mitk::DataNode::Pointer node = parentSet->ElementAt(i);
if( imagePredicate->CheckNode(node) )
{
bool isMask = false;
node->GetPropertyValue("binary", isMask);
if( !isMask )
{
if(this->m_SelectedImage == NULL)
{
this->m_SelectedImage = static_cast<mitk::Image*>(node->GetData());
this->m_ImageObserverTag = this->m_SelectedImage->AddObserver(itk::ModifiedEvent(), changeListener);
}
}
}
}
}
unsigned int timeStep = renderPart->GetTimeNavigationController()->GetTime()->GetPos();
if ( m_SelectedImage != NULL && m_SelectedImage->IsInitialized())
{
// Check if a the selected image is a multi-channel image. If yes, statistics
// cannot be calculated currently.
if ( m_SelectedImage->GetPixelType().GetNumberOfComponents() > 1 )
{
std::stringstream message;
message << "<font color='red'>Multi-component images not supported.</font>";
m_Controls->m_ErrorMessageLabel->setText( message.str().c_str() );
m_Controls->m_ErrorMessageLabel->show();
this->InvalidateStatisticsTableView();
m_Controls->m_StatisticsWidgetStack->setCurrentIndex( 0 );
m_Controls->m_JSHistogram->ClearHistogram();
m_CurrentStatisticsValid = false;
this->m_StatisticsUpdatePending = false;
m_Controls->m_lineRadioButton->setEnabled(true);
m_Controls->m_barRadioButton->setEnabled(true);
m_Controls->m_HistogramBinSizeSlider->setEnabled(true);
m_Controls->m_HistogramBinSizeCaptionLabel->setEnabled(true);
m_Controls->m_HistogramBinSizeLabel->setEnabled(true);
m_Controls->m_InfoLabel->setText(QString(""));
return;
}
std::stringstream maskLabel;
maskLabel << maskName;
if ( maskDimension > 0 )
{
maskLabel << " [" << maskDimension << "D " << maskType << "]";
}
m_Controls->m_SelectedMaskLabel->setText( maskLabel.str().c_str() );
// check time step validity
if(m_SelectedImage->GetDimension() <= 3 && timeStep > m_SelectedImage->GetDimension(3)-1)
{
timeStep = m_SelectedImage->GetDimension(3)-1;
}
// Add the used mask time step to the mask label so the user knows which mask time step was used
// if the image time step is bigger than the total number of mask time steps (see
// ImageStatisticsCalculator::ExtractImageAndMask)
if (m_SelectedImageMask != NULL)
{
unsigned int maskTimeStep = timeStep;
if (maskTimeStep >= m_SelectedImageMask->GetTimeSteps())
{
maskTimeStep = m_SelectedImageMask->GetTimeSteps() - 1;
}
m_Controls->m_SelectedMaskLabel->setText(m_Controls->m_SelectedMaskLabel->text() +
QString(" (t=") +
QString::number(maskTimeStep) +
QString(")"));
}
//// initialize thread and trigger it
this->m_CalculationThread->SetIgnoreZeroValueVoxel( m_Controls->m_IgnoreZerosCheckbox->isChecked() );
this->m_CalculationThread->Initialize( m_SelectedImage, m_SelectedImageMask, m_SelectedPlanarFigure );
this->m_CalculationThread->SetTimeStep( timeStep );
this->m_CalculationThread->SetHistogramBinSize(m_Controls->m_HistogramBinSizeSlider->value());
std::stringstream message;
message << "<font color='red'>Calculating statistics...</font>";
m_Controls->m_ErrorMessageLabel->setText( message.str().c_str() );
m_Controls->m_ErrorMessageLabel->show();
try
{
// Compute statistics
this->m_CalculationThread->start();
}
catch ( const mitk::Exception& e)
{
std::stringstream message;
message << "<font color='red'>" << e.GetDescription() << "</font>";
m_Controls->m_ErrorMessageLabel->setText( message.str().c_str() );
m_Controls->m_ErrorMessageLabel->show();
this->m_StatisticsUpdatePending = false;
}
catch ( const std::runtime_error &e )
{
// In case of exception, print error message on GUI
std::stringstream message;
message << "<font color='red'>" << e.what() << "</font>";
m_Controls->m_ErrorMessageLabel->setText( message.str().c_str() );
m_Controls->m_ErrorMessageLabel->show();
this->m_StatisticsUpdatePending = false;
}
catch ( const std::exception &e )
{
MITK_ERROR << "Caught exception: " << e.what();
// In case of exception, print error message on GUI
std::stringstream message;
message << "<font color='red'>Error! Unequal Dimensions of Image and Segmentation. No recompute possible </font>";
m_Controls->m_ErrorMessageLabel->setText( message.str().c_str() );
m_Controls->m_ErrorMessageLabel->show();
this->m_StatisticsUpdatePending = false;
}
}
else
{
this->m_StatisticsUpdatePending = false;
}
}
void QmitkImageStatisticsView::SelectedDataModified()
{
if( !m_StatisticsUpdatePending )
{
emit StatisticsUpdate();
}
}
void QmitkImageStatisticsView::NodeRemoved(const mitk::DataNode *node)
{
while(this->m_CalculationThread->isRunning()) // wait until thread has finished
{
itksys::SystemTools::Delay(100);
}
if (node->GetData() == m_SelectedImage)
{
m_SelectedImage = NULL;
}
}
void QmitkImageStatisticsView::RequestStatisticsUpdate()
{
if ( !m_StatisticsUpdatePending )
{
if(this->m_DataNodeSelectionChanged)
{
this->SelectionChanged(this->GetCurrentSelection());
}
else
{
this->m_StatisticsUpdatePending = true;
this->UpdateStatistics();
}
}
if (this->GetRenderWindowPart())
this->GetRenderWindowPart()->RequestUpdate();
}
void QmitkImageStatisticsView::OnHistogramBinSizeSliderValueChanged(int)
{
m_Controls->m_HistogramBinSizeLabel->setText( QString::number( m_Controls->m_HistogramBinSizeSlider->value()) );
this->UpdateStatistics();
}
void QmitkImageStatisticsView::WriteStatisticsToGUI()
{
m_Controls->m_lineRadioButton->setEnabled(true);
m_Controls->m_barRadioButton->setEnabled(true);
m_Controls->m_HistogramBinSizeSlider->setEnabled(true);
m_Controls->m_HistogramBinSizeCaptionLabel->setEnabled(true);
m_Controls->m_HistogramBinSizeLabel->setEnabled(true);
m_Controls->m_InfoLabel->setText(QString(""));
if(m_DataNodeSelectionChanged)
{
this->m_StatisticsUpdatePending = false;
this->RequestStatisticsUpdate();
return; // stop visualization of results and calculate statistics of new selection
}
if ( this->m_CalculationThread->GetStatisticsUpdateSuccessFlag())
{
if ( this->m_CalculationThread->GetStatisticsChangedFlag() )
{
// Do not show any error messages
m_Controls->m_ErrorMessageLabel->hide();
m_CurrentStatisticsValid = true;
}
if (m_Controls->m_barRadioButton->isChecked())
{
m_Controls->m_JSHistogram->OnBarRadioButtonSelected();
}
m_Controls->m_StatisticsWidgetStack->setCurrentIndex( 0 );
//m_Controls->m_JSHistogram->ComputeHistogram( this->m_CalculationThread->GetTimeStepHistogram(this->m_CalculationThread->GetTimeStep()).GetPointer() );
this->FillStatisticsTableView( this->m_CalculationThread->GetStatisticsData(), this->m_CalculationThread->GetStatisticsImage());
}
else
{
m_Controls->m_SelectedMaskLabel->setText( "None" );
m_Controls->m_ErrorMessageLabel->setText( m_CalculationThread->GetLastErrorMessage().c_str() );
m_Controls->m_ErrorMessageLabel->show();
// Clear statistics and histogram
this->InvalidateStatisticsTableView();
m_Controls->m_StatisticsWidgetStack->setCurrentIndex( 0 );
//m_Controls->m_JSHistogram->clearHistogram();
m_CurrentStatisticsValid = false;
// If a (non-closed) PlanarFigure is selected, display a line profile widget
if ( m_SelectedPlanarFigure != NULL )
{
// Check if the (closed) planar figure is out of bounds and so no image mask could be calculated--> Intensity Profile can not be calculated
bool outOfBounds = false;
if ( m_SelectedPlanarFigure->IsClosed() && m_SelectedImageMask == NULL)
{
outOfBounds = true;
std::stringstream message;
message << "<font color='red'>Planar figure is outside the images bounds.</font>";
m_Controls->m_InfoLabel->setText(message.str().c_str());
}
// check whether PlanarFigure is initialized
- const mitk::Geometry2D *planarFigureGeometry2D = m_SelectedPlanarFigure->GetGeometry2D();
- if ( planarFigureGeometry2D == NULL || outOfBounds)
+ const mitk::PlaneGeometry *planarFigurePlaneGeometry = m_SelectedPlanarFigure->GetPlaneGeometry();
+ if ( planarFigurePlaneGeometry == NULL || outOfBounds)
{
// Clear statistics, histogram, and GUI
this->InvalidateStatisticsTableView();
m_Controls->m_StatisticsWidgetStack->setCurrentIndex( 0 );
m_Controls->m_JSHistogram->ClearHistogram();
m_CurrentStatisticsValid = false;
m_Controls->m_ErrorMessageLabel->hide();
m_Controls->m_SelectedMaskLabel->setText( "None" );
this->m_StatisticsUpdatePending = false;
m_Controls->m_lineRadioButton->setEnabled(true);
m_Controls->m_barRadioButton->setEnabled(true);
m_Controls->m_HistogramBinSizeSlider->setEnabled(true);
m_Controls->m_HistogramBinSizeCaptionLabel->setEnabled(true);
m_Controls->m_HistogramBinSizeLabel->setEnabled(true);
if (!outOfBounds)
m_Controls->m_InfoLabel->setText(QString(""));
return;
}
unsigned int timeStep = this->GetRenderWindowPart()->GetTimeNavigationController()->GetTime()->GetPos();
m_Controls->m_JSHistogram->SetImage(this->m_CalculationThread->GetStatisticsImage());
m_Controls->m_JSHistogram->SetPlanarFigure(m_SelectedPlanarFigure);
m_Controls->m_JSHistogram->ComputeIntensityProfile(timeStep);
m_Controls->m_lineRadioButton->setEnabled(false);
m_Controls->m_barRadioButton->setEnabled(false);
m_Controls->m_HistogramBinSizeSlider->setEnabled(false);
m_Controls->m_HistogramBinSizeCaptionLabel->setEnabled(false);
m_Controls->m_HistogramBinSizeLabel->setEnabled(false);
std::stringstream message;
message << "<font color='red'>Only linegraph available for an intesityprofile!</font>";
m_Controls->m_InfoLabel->setText(message.str().c_str());
}
}
this->m_StatisticsUpdatePending = false;
}
void QmitkImageStatisticsView::FillStatisticsTableView(
const std::vector<mitk::ImageStatisticsCalculator::Statistics> &s,
const mitk::Image *image )
{
this->m_Controls->m_StatisticsTable->setColumnCount(image->GetTimeSteps());
this->m_Controls->m_StatisticsTable->horizontalHeader()->setVisible(image->GetTimeSteps() > 1);
for (unsigned int t = 0; t < image->GetTimeSteps(); t++)
{
this->m_Controls->m_StatisticsTable->setHorizontalHeaderItem(t,
new QTableWidgetItem(QString::number(t)));
if (s[t].MaxIndex.size()==3)
{
mitk::Point3D index, max, min;
index[0] = s[t].MaxIndex[0];
index[1] = s[t].MaxIndex[1];
index[2] = s[t].MaxIndex[2];
m_SelectedImage->GetGeometry()->IndexToWorld(index, max);
this->m_WorldMaxList.push_back(max);
index[0] = s[t].MinIndex[0];
index[1] = s[t].MinIndex[1];
index[2] = s[t].MinIndex[2];
m_SelectedImage->GetGeometry()->IndexToWorld(index, min);
this->m_WorldMinList.push_back(min);
}
int decimals = 2;
mitk::PixelType doublePix = mitk::MakeScalarPixelType< double >();
mitk::PixelType floatPix = mitk::MakeScalarPixelType< float >();
if (image->GetPixelType()==doublePix || image->GetPixelType()==floatPix)
decimals = 5;
this->m_Controls->m_StatisticsTable->setItem( 0, t, new QTableWidgetItem(
QString("%1").arg(s[t].Mean, 0, 'f', decimals) ) );
this->m_Controls->m_StatisticsTable->setItem( 1, t, new QTableWidgetItem(
QString("%1").arg(s[t].Sigma, 0, 'f', decimals) ) );
this->m_Controls->m_StatisticsTable->setItem( 2, t, new QTableWidgetItem(
QString("%1").arg(s[t].RMS, 0, 'f', decimals) ) );
QString max; max.append(QString("%1").arg(s[t].Max, 0, 'f', decimals));
max += " (";
for (int i=0; i<s[t].MaxIndex.size(); i++)
{
max += QString::number(s[t].MaxIndex[i]);
if (i<s[t].MaxIndex.size()-1)
max += ",";
}
max += ")";
this->m_Controls->m_StatisticsTable->setItem( 3, t, new QTableWidgetItem( max ) );
QString min; min.append(QString("%1").arg(s[t].Min, 0, 'f', decimals));
min += " (";
for (int i=0; i<s[t].MinIndex.size(); i++)
{
min += QString::number(s[t].MinIndex[i]);
if (i<s[t].MinIndex.size()-1)
min += ",";
}
min += ")";
this->m_Controls->m_StatisticsTable->setItem( 4, t, new QTableWidgetItem( min ) );
this->m_Controls->m_StatisticsTable->setItem( 5, t, new QTableWidgetItem(
QString("%1").arg(s[t].N) ) );
- const mitk::Geometry3D *geometry = image->GetGeometry();
+ const mitk::BaseGeometry *geometry = image->GetGeometry();
if ( geometry != NULL )
{
const mitk::Vector3D &spacing = image->GetGeometry()->GetSpacing();
double volume = spacing[0] * spacing[1] * spacing[2] * (double) s[t].N;
this->m_Controls->m_StatisticsTable->setItem( 6, t, new QTableWidgetItem(
QString("%1").arg(volume, 0, 'f', decimals) ) );
}
else
{
this->m_Controls->m_StatisticsTable->setItem( 6, t, new QTableWidgetItem(
"NA" ) );
}
}
this->m_Controls->m_StatisticsTable->resizeColumnsToContents();
int height = STAT_TABLE_BASE_HEIGHT;
if (this->m_Controls->m_StatisticsTable->horizontalHeader()->isVisible())
height += this->m_Controls->m_StatisticsTable->horizontalHeader()->height();
if (this->m_Controls->m_StatisticsTable->horizontalScrollBar()->isVisible())
height += this->m_Controls->m_StatisticsTable->horizontalScrollBar()->height();
this->m_Controls->m_StatisticsTable->setMinimumHeight(height);
// make sure the current timestep's column is highlighted (and the correct histogram is displayed)
unsigned int timestep = this->GetRenderWindowPart()->GetTimeNavigationController()->GetTime()->
GetPos();
mitk::SliceNavigationController::GeometryTimeEvent timeEvent(this->m_SelectedImage->GetTimeGeometry(),
timestep);
this->OnTimeChanged(timeEvent);
}
void QmitkImageStatisticsView::InvalidateStatisticsTableView()
{
this->m_Controls->m_StatisticsTable->horizontalHeader()->setVisible(false);
this->m_Controls->m_StatisticsTable->setColumnCount(1);
for ( unsigned int i = 0; i < this->m_Controls->m_StatisticsTable->rowCount(); ++i )
{
{
this->m_Controls->m_StatisticsTable->setItem( i, 0, new QTableWidgetItem( "NA" ) );
}
}
this->m_Controls->m_StatisticsTable->setMinimumHeight(STAT_TABLE_BASE_HEIGHT);
}
void QmitkImageStatisticsView::Activated()
{
}
void QmitkImageStatisticsView::Deactivated()
{
}
void QmitkImageStatisticsView::Visible()
{
m_Visible = true;
mitk::IRenderWindowPart* renderWindow = GetRenderWindowPart();
if (renderWindow)
{
itk::ReceptorMemberCommand<QmitkImageStatisticsView>::Pointer cmdTimeEvent =
itk::ReceptorMemberCommand<QmitkImageStatisticsView>::New();
cmdTimeEvent->SetCallbackFunction(this, &QmitkImageStatisticsView::OnTimeChanged);
// It is sufficient to add the observer to the axial render window since the GeometryTimeEvent
// is always triggered by all views.
m_TimeObserverTag = renderWindow->GetQmitkRenderWindow("axial")->
GetSliceNavigationController()->
AddObserver(mitk::SliceNavigationController::GeometryTimeEvent(NULL, 0), cmdTimeEvent);
}
if (m_DataNodeSelectionChanged)
{
if (this->IsCurrentSelectionValid())
{
this->SelectionChanged(this->GetCurrentSelection());
}
else
{
this->SelectionChanged(this->GetDataManagerSelection());
}
m_DataNodeSelectionChanged = false;
}
}
void QmitkImageStatisticsView::Hidden()
{
m_Visible = false;
// The slice navigation controller observer is removed here instead of in the destructor.
// If it was called in the destructor, the application would freeze because the view's
// destructor gets called after the render windows have been destructed.
if ( m_TimeObserverTag != NULL )
{
mitk::IRenderWindowPart* renderWindow = GetRenderWindowPart();
if (renderWindow)
{
renderWindow->GetQmitkRenderWindow("axial")->GetSliceNavigationController()->
RemoveObserver( m_TimeObserverTag );
}
m_TimeObserverTag = NULL;
}
}
void QmitkImageStatisticsView::SetFocus()
{
}
diff --git a/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkMeasurementView.cpp b/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkMeasurementView.cpp
index c0ed888a31..060183b87f 100644
--- a/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkMeasurementView.cpp
+++ b/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkMeasurementView.cpp
@@ -1,961 +1,958 @@
/*===================================================================
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.
===================================================================*/
#define MEASUREMENT_DEBUG MITK_DEBUG("QmitkMeasurementView") << __LINE__ << ": "
#include "QmitkMeasurementView.h"
#include <QtGui>
#include <mitkIPropertyFilters.h>
#include <mitkPropertyFilter.h>
#include <mitkVtkLayerController.h>
#include <mitkWeakPointer.h>
#include <mitkPlanarCircle.h>
#include <mitkPlanarEllipse.h>
#include <mitkPlanarPolygon.h>
#include <mitkPlanarAngle.h>
#include <mitkPlanarRectangle.h>
#include <mitkPlanarLine.h>
#include <mitkPlanarCross.h>
#include <mitkPlanarFourPointAngle.h>
#include <mitkPlanarDoubleEllipse.h>
#include <mitkPlanarBezierCurve.h>
#include <mitkPlanarSubdivisionPolygon.h>
#include <mitkPlanarFigureInteractor.h>
#include <mitkPlaneGeometry.h>
#include <mitkGlobalInteraction.h>
#include <mitkILinkedRenderWindowPart.h>
#include <mitkNodePredicateDataType.h>
#include <mitkNodePredicateProperty.h>
#include <mitkNodePredicateAnd.h>
#include <mitkNodePredicateNot.h>
#include <QmitkRenderWindow.h>
#include <mitkImage.h>
#include "mitkPluginActivator.h"
#include "usModuleRegistry.h"
template <class T>
static T* GetService()
{
ctkPluginContext* context = mitk::PluginActivator::GetContext();
ctkServiceReference serviceRef = context->getServiceReference<T>();
return serviceRef
? context->getService<T>(serviceRef)
: NULL;
}
struct QmitkPlanarFigureData
{
QmitkPlanarFigureData()
: m_Figure(0), m_EndPlacementObserverTag(0), m_SelectObserverTag(0), m_StartInteractionObserverTag(0), m_EndInteractionObserverTag(0)
{
}
mitk::PlanarFigure* m_Figure;
unsigned int m_EndPlacementObserverTag;
unsigned int m_SelectObserverTag;
unsigned int m_StartInteractionObserverTag;
unsigned int m_EndInteractionObserverTag;
};
struct QmitkMeasurementViewData
{
QmitkMeasurementViewData()
: m_LineCounter(0), m_PathCounter(0), m_AngleCounter(0),
m_FourPointAngleCounter(0), m_CircleCounter(0), m_EllipseCounter(0),
m_DoubleEllipseCounter(0), m_RectangleCounter(0), m_PolygonCounter(0),
m_BezierCurveCounter(0), m_SubdivisionPolygonCounter(0), m_UnintializedPlanarFigure(false)
{
}
// internal vars
unsigned int m_LineCounter;
unsigned int m_PathCounter;
unsigned int m_AngleCounter;
unsigned int m_FourPointAngleCounter;
unsigned int m_CircleCounter;
unsigned int m_EllipseCounter;
unsigned int m_DoubleEllipseCounter;
unsigned int m_RectangleCounter;
unsigned int m_PolygonCounter;
unsigned int m_BezierCurveCounter;
unsigned int m_SubdivisionPolygonCounter;
QList<mitk::DataNode::Pointer> m_CurrentSelection;
std::map<mitk::DataNode*, QmitkPlanarFigureData> m_DataNodeToPlanarFigureData;
mitk::WeakPointer<mitk::DataNode> m_SelectedImageNode;
bool m_UnintializedPlanarFigure;
// WIDGETS
QWidget* m_Parent;
QLabel* m_SelectedImageLabel;
QAction* m_DrawLine;
QAction* m_DrawPath;
QAction* m_DrawAngle;
QAction* m_DrawFourPointAngle;
QAction* m_DrawRectangle;
QAction* m_DrawPolygon;
QAction* m_DrawCircle;
QAction* m_DrawEllipse;
QAction* m_DrawDoubleEllipse;
QAction* m_DrawBezierCurve;
QAction* m_DrawSubdivisionPolygon;
QToolBar* m_DrawActionsToolBar;
QActionGroup* m_DrawActionsGroup;
QTextBrowser* m_SelectedPlanarFiguresText;
QPushButton* m_CopyToClipboard;
QGridLayout* m_Layout;
};
const std::string QmitkMeasurementView::VIEW_ID = "org.mitk.views.measurement";
QmitkMeasurementView::QmitkMeasurementView()
: d( new QmitkMeasurementViewData )
{
}
QmitkMeasurementView::~QmitkMeasurementView()
{
this->RemoveAllInteractors();
delete d;
}
void QmitkMeasurementView::CreateQtPartControl(QWidget* parent)
{
d->m_Parent = parent;
// image label
QLabel* selectedImageLabel = new QLabel("Reference Image: ");
d->m_SelectedImageLabel = new QLabel;
d->m_SelectedImageLabel->setStyleSheet("font-weight: bold;");
d->m_DrawActionsToolBar = new QToolBar;
d->m_DrawActionsGroup = new QActionGroup(this);
d->m_DrawActionsGroup->setExclusive(true);
//# add actions
MEASUREMENT_DEBUG << "Draw Line";
QAction* currentAction = d->m_DrawActionsToolBar->addAction(QIcon(":/measurement/line.png"), "Draw Line");
currentAction->setCheckable(true);
d->m_DrawLine = currentAction;
d->m_DrawActionsToolBar->addAction(currentAction);
d->m_DrawActionsGroup->addAction(currentAction);
MEASUREMENT_DEBUG << "Draw Path";
currentAction = d->m_DrawActionsToolBar->addAction(QIcon(":/measurement/path.png"), "Draw Path");
currentAction->setCheckable(true);
d->m_DrawPath = currentAction;
d->m_DrawActionsToolBar->addAction(currentAction);
d->m_DrawActionsGroup->addAction(currentAction);
MEASUREMENT_DEBUG << "Draw Angle";
currentAction = d->m_DrawActionsToolBar->addAction(QIcon(":/measurement/angle.png"), "Draw Angle");
currentAction->setCheckable(true);
d->m_DrawAngle = currentAction;
d->m_DrawActionsToolBar->addAction(currentAction);
d->m_DrawActionsGroup->addAction(currentAction);
MEASUREMENT_DEBUG << "Draw Four Point Angle";
currentAction = d->m_DrawActionsToolBar->addAction(QIcon(":/measurement/four-point-angle.png"), "Draw Four Point Angle");
currentAction->setCheckable(true);
d->m_DrawFourPointAngle = currentAction;
d->m_DrawActionsToolBar->addAction(currentAction);
d->m_DrawActionsGroup->addAction(currentAction);
MEASUREMENT_DEBUG << "Draw Circle";
currentAction = d->m_DrawActionsToolBar->addAction(QIcon(":/measurement/circle.png"), "Draw Circle");
currentAction->setCheckable(true);
d->m_DrawCircle = currentAction;
d->m_DrawActionsToolBar->addAction(currentAction);
d->m_DrawActionsGroup->addAction(currentAction);
MEASUREMENT_DEBUG << "Draw Ellipse";
currentAction = d->m_DrawActionsToolBar->addAction(QIcon(":/measurement/ellipse.png"), "Draw Ellipse");
currentAction->setCheckable(true);
d->m_DrawEllipse = currentAction;
d->m_DrawActionsToolBar->addAction(currentAction);
d->m_DrawActionsGroup->addAction(currentAction);
MEASUREMENT_DEBUG << "Draw Double Ellipse";
currentAction = d->m_DrawActionsToolBar->addAction(QIcon(":/measurement/doubleellipse.png"), "Draw Double Ellipse");
currentAction->setCheckable(true);
d->m_DrawDoubleEllipse = currentAction;
d->m_DrawActionsToolBar->addAction(currentAction);
d->m_DrawActionsGroup->addAction(currentAction);
MEASUREMENT_DEBUG << "Draw Rectangle";
currentAction = d->m_DrawActionsToolBar->addAction(QIcon(":/measurement/rectangle.png"), "Draw Rectangle");
currentAction->setCheckable(true);
d->m_DrawRectangle = currentAction;
d->m_DrawActionsToolBar->addAction(currentAction);
d->m_DrawActionsGroup->addAction(currentAction);
MEASUREMENT_DEBUG << "Draw Polygon";
currentAction = d->m_DrawActionsToolBar->addAction(QIcon(":/measurement/polygon.png"), "Draw Polygon");
currentAction->setCheckable(true);
d->m_DrawPolygon = currentAction;
d->m_DrawActionsToolBar->addAction(currentAction);
d->m_DrawActionsGroup->addAction(currentAction);
MEASUREMENT_DEBUG << "Draw Bezier Curve";
currentAction = d->m_DrawActionsToolBar->addAction(QIcon(":/measurement/beziercurve.png"), "Draw Bezier Curve");
currentAction->setCheckable(true);
d->m_DrawBezierCurve = currentAction;
d->m_DrawActionsToolBar->addAction(currentAction);
d->m_DrawActionsGroup->addAction(currentAction);
MEASUREMENT_DEBUG << "Draw Subdivision Polygon";
currentAction = d->m_DrawActionsToolBar->addAction(QIcon(":/measurement/subdivisionpolygon.png"), "Draw Subdivision Polygon");
currentAction->setCheckable(true);
d->m_DrawSubdivisionPolygon = currentAction;
d->m_DrawActionsToolBar->addAction(currentAction);
d->m_DrawActionsGroup->addAction(currentAction);
// planar figure details text
d->m_SelectedPlanarFiguresText = new QTextBrowser;
// copy to clipboard button
d->m_CopyToClipboard = new QPushButton("Copy to Clipboard");
d->m_Layout = new QGridLayout;
d->m_Layout->addWidget(selectedImageLabel, 0, 0, 1, 1);
d->m_Layout->addWidget(d->m_SelectedImageLabel, 0, 1, 1, 1);
d->m_Layout->addWidget(d->m_DrawActionsToolBar, 1, 0, 1, 2);
d->m_Layout->addWidget(d->m_SelectedPlanarFiguresText, 2, 0, 1, 2);
d->m_Layout->addWidget(d->m_CopyToClipboard, 3, 0, 1, 2);
d->m_Parent->setLayout(d->m_Layout);
// create connections
this->CreateConnections();
// readd interactors and observers
this->AddAllInteractors();
}
void QmitkMeasurementView::CreateConnections()
{
QObject::connect( d->m_DrawLine, SIGNAL( triggered(bool) ), this, SLOT( ActionDrawLineTriggered(bool) ) );
QObject::connect( d->m_DrawPath, SIGNAL( triggered(bool) ), this, SLOT( ActionDrawPathTriggered(bool) ) );
QObject::connect( d->m_DrawAngle, SIGNAL( triggered(bool) ), this, SLOT( ActionDrawAngleTriggered(bool) ) );
QObject::connect( d->m_DrawFourPointAngle, SIGNAL( triggered(bool) ), this, SLOT( ActionDrawFourPointAngleTriggered(bool) ) );
QObject::connect( d->m_DrawCircle, SIGNAL( triggered(bool) ), this, SLOT( ActionDrawCircleTriggered(bool) ) );
QObject::connect( d->m_DrawEllipse, SIGNAL( triggered(bool) ), this, SLOT( ActionDrawEllipseTriggered(bool) ) );
QObject::connect( d->m_DrawDoubleEllipse, SIGNAL( triggered(bool) ), this, SLOT( ActionDrawDoubleEllipseTriggered(bool) ) );
QObject::connect( d->m_DrawRectangle, SIGNAL( triggered(bool) ), this, SLOT( ActionDrawRectangleTriggered(bool) ) );
QObject::connect( d->m_DrawPolygon, SIGNAL( triggered(bool) ), this, SLOT( ActionDrawPolygonTriggered(bool) ) );
QObject::connect( d->m_DrawBezierCurve, SIGNAL( triggered(bool) ), this, SLOT( ActionDrawBezierCurveTriggered(bool) ) );
QObject::connect( d->m_DrawSubdivisionPolygon, SIGNAL( triggered(bool) ), this, SLOT( ActionDrawSubdivisionPolygonTriggered(bool) ) );
QObject::connect( d->m_CopyToClipboard, SIGNAL( clicked(bool) ), this, SLOT( CopyToClipboard(bool) ) );
}
void QmitkMeasurementView::NodeAdded( const mitk::DataNode* node )
{
// add observer for selection in renderwindow
mitk::PlanarFigure* figure = dynamic_cast<mitk::PlanarFigure*>(node->GetData());
bool isPositionMarker (false);
node->GetBoolProperty("isContourMarker", isPositionMarker);
if( figure && !isPositionMarker )
{
MEASUREMENT_DEBUG << "figure added. will add interactor if needed.";
mitk::PlanarFigureInteractor::Pointer figureInteractor
= dynamic_cast<mitk::PlanarFigureInteractor*>(node->GetDataInteractor().GetPointer() );
mitk::DataNode* nonConstNode = const_cast<mitk::DataNode*>( node );
if(figureInteractor.IsNull())
{
figureInteractor = mitk::PlanarFigureInteractor::New();
us::Module* planarFigureModule = us::ModuleRegistry::GetModule( "MitkPlanarFigure" );
figureInteractor->LoadStateMachine("PlanarFigureInteraction.xml", planarFigureModule );
figureInteractor->SetEventConfig( "PlanarFigureConfig.xml", planarFigureModule );
figureInteractor->SetDataNode( nonConstNode );
// nonConstNode->SetBoolProperty( "planarfigure.isextendable", true );
}
else
{
// just to be sure that the interactor is not added twice
// mitk::GlobalInteraction::GetInstance()->RemoveInteractor(figureInteractor);
}
MEASUREMENT_DEBUG << "adding interactor to globalinteraction";
// mitk::GlobalInteraction::GetInstance()->AddInteractor(figureInteractor);
MEASUREMENT_DEBUG << "will now add observers for planarfigure";
QmitkPlanarFigureData data;
data.m_Figure = figure;
// add observer for event when figure has been placed
typedef itk::SimpleMemberCommand< QmitkMeasurementView > SimpleCommandType;
SimpleCommandType::Pointer initializationCommand = SimpleCommandType::New();
initializationCommand->SetCallbackFunction( this, &QmitkMeasurementView::PlanarFigureInitialized );
data.m_EndPlacementObserverTag = figure->AddObserver( mitk::EndPlacementPlanarFigureEvent(), initializationCommand );
// add observer for event when figure is picked (selected)
typedef itk::MemberCommand< QmitkMeasurementView > MemberCommandType;
MemberCommandType::Pointer selectCommand = MemberCommandType::New();
selectCommand->SetCallbackFunction( this, &QmitkMeasurementView::PlanarFigureSelected );
data.m_SelectObserverTag = figure->AddObserver( mitk::SelectPlanarFigureEvent(), selectCommand );
// add observer for event when interaction with figure starts
SimpleCommandType::Pointer startInteractionCommand = SimpleCommandType::New();
startInteractionCommand->SetCallbackFunction( this, &QmitkMeasurementView::DisableCrosshairNavigation);
data.m_StartInteractionObserverTag = figure->AddObserver( mitk::StartInteractionPlanarFigureEvent(), startInteractionCommand );
// add observer for event when interaction with figure starts
SimpleCommandType::Pointer endInteractionCommand = SimpleCommandType::New();
endInteractionCommand->SetCallbackFunction( this, &QmitkMeasurementView::EnableCrosshairNavigation);
data.m_EndInteractionObserverTag = figure->AddObserver( mitk::EndInteractionPlanarFigureEvent(), endInteractionCommand );
// adding to the map of tracked planarfigures
d->m_DataNodeToPlanarFigureData[nonConstNode] = data;
}
this->CheckForTopMostVisibleImage();
}
void QmitkMeasurementView::NodeChanged(const mitk::DataNode* node)
{
// DETERMINE IF WE HAVE TO RENEW OUR DETAILS TEXT (ANY NODE CHANGED IN OUR SELECTION?)
bool renewText = false;
for( int i=0; i < d->m_CurrentSelection.size(); ++i )
{
if( node == d->m_CurrentSelection.at(i) )
{
renewText = true;
break;
}
}
if(renewText)
{
MEASUREMENT_DEBUG << "Selected nodes changed. Refreshing text.";
this->UpdateMeasurementText();
}
this->CheckForTopMostVisibleImage();
}
void QmitkMeasurementView::CheckForTopMostVisibleImage(mitk::DataNode* _NodeToNeglect)
{
d->m_SelectedImageNode = this->DetectTopMostVisibleImage().GetPointer();
if( d->m_SelectedImageNode.GetPointer() == _NodeToNeglect )
d->m_SelectedImageNode = 0;
if( d->m_SelectedImageNode.IsNotNull() && d->m_UnintializedPlanarFigure == false )
{
MEASUREMENT_DEBUG << "Reference image found";
d->m_SelectedImageLabel->setText( QString::fromStdString( d->m_SelectedImageNode->GetName() ) );
d->m_DrawActionsToolBar->setEnabled(true);
MEASUREMENT_DEBUG << "Updating Measurement text";
}
else
{
MEASUREMENT_DEBUG << "No reference image available. Will disable actions for creating new planarfigures";
if( d->m_UnintializedPlanarFigure == false )
d->m_SelectedImageLabel->setText( "No visible image available." );
d->m_DrawActionsToolBar->setEnabled(false);
}
}
void QmitkMeasurementView::NodeRemoved(const mitk::DataNode* node)
{
MEASUREMENT_DEBUG << "node removed from data storage";
mitk::DataNode* nonConstNode = const_cast<mitk::DataNode*>(node);
std::map<mitk::DataNode*, QmitkPlanarFigureData>::iterator it =
d->m_DataNodeToPlanarFigureData.find(nonConstNode);
bool isFigureFinished = false;
bool isPlaced = false;
if( it != d->m_DataNodeToPlanarFigureData.end() )
{
QmitkPlanarFigureData& data = it->second;
// remove observers
data.m_Figure->RemoveObserver( data.m_EndPlacementObserverTag );
data.m_Figure->RemoveObserver( data.m_SelectObserverTag );
data.m_Figure->RemoveObserver( data.m_StartInteractionObserverTag );
data.m_Figure->RemoveObserver( data.m_EndInteractionObserverTag );
MEASUREMENT_DEBUG << "removing from the list of tracked planar figures";
isFigureFinished = data.m_Figure->GetPropertyList()->GetBoolProperty("initiallyplaced",isPlaced);
if (!isFigureFinished) { // if the property does not yet exist or is false, drop the datanode
PlanarFigureInitialized(); // normally called when a figure is finished, to reset all buttons
}
d->m_DataNodeToPlanarFigureData.erase( it );
}
mitk::TNodePredicateDataType<mitk::PlanarFigure>::Pointer isPlanarFigure = mitk::TNodePredicateDataType<mitk::PlanarFigure>::New();
mitk::DataStorage::SetOfObjects::ConstPointer nodes =
GetDataStorage()->GetDerivations(node,isPlanarFigure);
for (unsigned int x = 0; x < nodes->size(); x++)
{
mitk::PlanarFigure* planarFigure = dynamic_cast<mitk::PlanarFigure*> (nodes->at(x)->GetData());
if (planarFigure != NULL) {
isFigureFinished = planarFigure->GetPropertyList()->GetBoolProperty("initiallyplaced",isPlaced);
if (!isFigureFinished) { // if the property does not yet exist or is false, drop the datanode
GetDataStorage()->Remove(nodes->at(x));
if( !d->m_DataNodeToPlanarFigureData.empty() )
{
std::map<mitk::DataNode*, QmitkPlanarFigureData>::iterator it2 =
d->m_DataNodeToPlanarFigureData.find(nodes->at(x));
//check if returned it2 valid
if( it2 != d->m_DataNodeToPlanarFigureData.end() )
{
d->m_DataNodeToPlanarFigureData.erase( it2 );// removing planar figure from tracked figure list
PlanarFigureInitialized(); // normally called when a figure is finished, to reset all buttons
EnableCrosshairNavigation();
}
}
}
}
}
this->CheckForTopMostVisibleImage(nonConstNode);
}
void QmitkMeasurementView::PlanarFigureSelected( itk::Object* object, const itk::EventObject& )
{
MEASUREMENT_DEBUG << "planar figure " << object << " selected";
std::map<mitk::DataNode*, QmitkPlanarFigureData>::iterator it =
d->m_DataNodeToPlanarFigureData.begin();
d->m_CurrentSelection.clear();
while( it != d->m_DataNodeToPlanarFigureData.end())
{
mitk::DataNode* node = it->first;
QmitkPlanarFigureData& data = it->second;
if( data.m_Figure == object )
{
MITK_DEBUG << "selected node found. enabling selection";
node->SetSelected(true);
d->m_CurrentSelection.push_back( node );
}
else
{
node->SetSelected(false);
}
++it;
}
this->UpdateMeasurementText();
this->RequestRenderWindowUpdate();
}
void QmitkMeasurementView::PlanarFigureInitialized()
{
MEASUREMENT_DEBUG << "planar figure initialized";
d->m_UnintializedPlanarFigure = false;
d->m_DrawActionsToolBar->setEnabled(true);
d->m_DrawLine->setChecked(false);
d->m_DrawPath->setChecked(false);
d->m_DrawAngle->setChecked(false);
d->m_DrawFourPointAngle->setChecked(false);
d->m_DrawCircle->setChecked(false);
d->m_DrawEllipse->setChecked(false);
d->m_DrawDoubleEllipse->setChecked(false);
d->m_DrawRectangle->setChecked(false);
d->m_DrawPolygon->setChecked(false);
d->m_DrawBezierCurve->setChecked(false);
d->m_DrawSubdivisionPolygon->setChecked(false);
}
void QmitkMeasurementView::SetFocus()
{
d->m_SelectedImageLabel->setFocus();
}
void QmitkMeasurementView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/,
const QList<mitk::DataNode::Pointer> &nodes)
{
MEASUREMENT_DEBUG << "Determine the top most visible image";
MEASUREMENT_DEBUG << "The PlanarFigure interactor will take the currently visible PlaneGeometry from the slice navigation controller";
this->CheckForTopMostVisibleImage();
MEASUREMENT_DEBUG << "refreshing selection and detailed text";
d->m_CurrentSelection = nodes;
this->UpdateMeasurementText();
// bug 16600: deselecting all planarfigures by clicking on datamanager when no node is selected
if(d->m_CurrentSelection.size() == 0)
{
mitk::TNodePredicateDataType<mitk::PlanarFigure>::Pointer isPlanarFigure = mitk::TNodePredicateDataType<mitk::PlanarFigure>::New();
mitk::DataStorage::SetOfObjects::ConstPointer planarFigures = this->GetDataStorage()->GetSubset( isPlanarFigure );
// setting all planar figures which are not helper objects not selected
for(mitk::DataStorage::SetOfObjects::ConstIterator it=planarFigures->Begin(); it!=planarFigures->End(); it++)
{
mitk::DataNode* node = it.Value();
bool isHelperObject(false);
node->GetBoolProperty("helper object", isHelperObject);
if(!isHelperObject)
{
node->SetSelected(false);
}
}
}
for( int i=d->m_CurrentSelection.size()-1; i>= 0; --i)
{
mitk::DataNode* node = d->m_CurrentSelection.at(i);
mitk::PlanarFigure* _PlanarFigure = dynamic_cast<mitk::PlanarFigure*> (node->GetData());
// the last selected planar figure
- if (_PlanarFigure && _PlanarFigure->GetGeometry2D())
+ if (_PlanarFigure && _PlanarFigure->GetPlaneGeometry())
{
QmitkRenderWindow* selectedRenderWindow = 0;
bool PlanarFigureInitializedWindow = false;
mitk::ILinkedRenderWindowPart* linkedRenderWindow = dynamic_cast<mitk::ILinkedRenderWindowPart*>(this->GetRenderWindowPart());
if(! linkedRenderWindow )
{
return;
}
QmitkRenderWindow* RenderWindow1 = linkedRenderWindow->GetQmitkRenderWindow( "axial") ;
QmitkRenderWindow* RenderWindow2 = linkedRenderWindow->GetQmitkRenderWindow( "sagittal") ;
QmitkRenderWindow* RenderWindow3 = linkedRenderWindow->GetQmitkRenderWindow( "coronal") ;
QmitkRenderWindow* RenderWindow4 = linkedRenderWindow->GetQmitkRenderWindow( "3d") ;
if (node->GetBoolProperty("PlanarFigureInitializedWindow", PlanarFigureInitializedWindow, RenderWindow1->GetRenderer()))
{
selectedRenderWindow = RenderWindow1;
}
if (!selectedRenderWindow && node->GetBoolProperty("PlanarFigureInitializedWindow", PlanarFigureInitializedWindow, RenderWindow2->GetRenderer()))
{
selectedRenderWindow = RenderWindow2;
}
if (!selectedRenderWindow && node->GetBoolProperty("PlanarFigureInitializedWindow", PlanarFigureInitializedWindow,RenderWindow3->GetRenderer()))
{
selectedRenderWindow = RenderWindow3;
}
if (!selectedRenderWindow && node->GetBoolProperty("PlanarFigureInitializedWindow", PlanarFigureInitializedWindow, RenderWindow4->GetRenderer()))
{
selectedRenderWindow = RenderWindow4;
}
- const mitk::PlaneGeometry* _PlaneGeometry = dynamic_cast<const mitk::PlaneGeometry*> (_PlanarFigure->GetGeometry2D());
+ const mitk::PlaneGeometry* _PlaneGeometry = dynamic_cast<const mitk::PlaneGeometry*> (_PlanarFigure->GetPlaneGeometry());
mitk::VnlVector normal = _PlaneGeometry->GetNormalVnl();
- mitk::Geometry2D::ConstPointer worldGeometry1 = RenderWindow1->GetRenderer()->GetCurrentWorldGeometry2D();
- mitk::PlaneGeometry::ConstPointer _Plane1 = dynamic_cast<const mitk::PlaneGeometry*>( worldGeometry1.GetPointer() );
+ mitk::PlaneGeometry::ConstPointer _Plane1 = RenderWindow1->GetRenderer()->GetCurrentWorldPlaneGeometry();
mitk::VnlVector normal1 = _Plane1->GetNormalVnl();
- mitk::Geometry2D::ConstPointer worldGeometry2 = RenderWindow2->GetRenderer()->GetCurrentWorldGeometry2D();
- mitk::PlaneGeometry::ConstPointer _Plane2 = dynamic_cast<const mitk::PlaneGeometry*>( worldGeometry2.GetPointer() );
+ mitk::PlaneGeometry::ConstPointer _Plane2 = RenderWindow2->GetRenderer()->GetCurrentWorldPlaneGeometry();
mitk::VnlVector normal2 = _Plane2->GetNormalVnl();
- mitk::Geometry2D::ConstPointer worldGeometry3 = RenderWindow3->GetRenderer()->GetCurrentWorldGeometry2D();
- mitk::PlaneGeometry::ConstPointer _Plane3 = dynamic_cast<const mitk::PlaneGeometry*>( worldGeometry3.GetPointer() );
+ mitk::PlaneGeometry::ConstPointer _Plane3 = RenderWindow3->GetRenderer()->GetCurrentWorldPlaneGeometry();
mitk::VnlVector normal3 = _Plane3->GetNormalVnl();
normal[0] = fabs(normal[0]); normal[1] = fabs(normal[1]); normal[2] = fabs(normal[2]);
normal1[0] = fabs(normal1[0]); normal1[1] = fabs(normal1[1]); normal1[2] = fabs(normal1[2]);
normal2[0] = fabs(normal2[0]); normal2[1] = fabs(normal2[1]); normal2[2] = fabs(normal2[2]);
normal3[0] = fabs(normal3[0]); normal3[1] = fabs(normal3[1]); normal3[2] = fabs(normal3[2]);
double ang1 = angle(normal, normal1);
double ang2 = angle(normal, normal2);
double ang3 = angle(normal, normal3);
if(ang1 < ang2 && ang1 < ang3)
{
selectedRenderWindow = RenderWindow1;
}
else
{
if(ang2 < ang3)
{
selectedRenderWindow = RenderWindow2;
}
else
{
selectedRenderWindow = RenderWindow3;
}
}
// re-orient view
if (selectedRenderWindow)
{
const mitk::Point3D& centerP = _PlaneGeometry->GetOrigin();
selectedRenderWindow->GetSliceNavigationController()->ReorientSlices(centerP, _PlaneGeometry->GetNormal());
}
}
break;
}
this->RequestRenderWindowUpdate();
}
void QmitkMeasurementView::ActionDrawLineTriggered(bool checked)
{
Q_UNUSED(checked)
mitk::PlanarLine::Pointer figure = mitk::PlanarLine::New();
QString qString = QString("Line%1").arg(++d->m_LineCounter);
this->AddFigureToDataStorage(figure, qString);
MEASUREMENT_DEBUG << "PlanarLine initialized...";
}
void QmitkMeasurementView::ActionDrawPathTriggered(bool checked)
{
Q_UNUSED(checked)
mitk::IPropertyFilters* propertyFilters = GetService<mitk::IPropertyFilters>();
if (propertyFilters != NULL)
{
mitk::PropertyFilter filter;
filter.AddEntry("ClosedPlanarPolygon", mitk::PropertyFilter::Blacklist);
propertyFilters->AddFilter(filter, "PlanarPolygon");
}
mitk::PlanarPolygon::Pointer figure = mitk::PlanarPolygon::New();
figure->ClosedOff();
QString qString = QString("Path%1").arg(++d->m_PathCounter);
mitk::DataNode::Pointer node = this->AddFigureToDataStorage(figure, qString);
mitk::BoolProperty::Pointer closedProperty = mitk::BoolProperty::New( false );
node->SetProperty("ClosedPlanarPolygon", closedProperty);
node->SetProperty("planarfigure.isextendable",mitk::BoolProperty::New(true));
MEASUREMENT_DEBUG << "PlanarPath initialized...";
}
void QmitkMeasurementView::ActionDrawAngleTriggered(bool checked)
{
Q_UNUSED(checked)
mitk::PlanarAngle::Pointer figure = mitk::PlanarAngle::New();
QString qString = QString("Angle%1").arg(++d->m_AngleCounter);
this->AddFigureToDataStorage(figure, qString);
MEASUREMENT_DEBUG << "PlanarAngle initialized...";
}
void QmitkMeasurementView::ActionDrawFourPointAngleTriggered(bool checked)
{
Q_UNUSED(checked)
mitk::PlanarFourPointAngle::Pointer figure =
mitk::PlanarFourPointAngle::New();
QString qString = QString("Four Point Angle%1").arg(++d->m_FourPointAngleCounter);
this->AddFigureToDataStorage(figure, qString);
MEASUREMENT_DEBUG << "PlanarFourPointAngle initialized...";
}
void QmitkMeasurementView::ActionDrawCircleTriggered(bool checked)
{
Q_UNUSED(checked)
mitk::PlanarCircle::Pointer figure = mitk::PlanarCircle::New();
QString qString = QString("Circle%1").arg(++d->m_CircleCounter);
this->AddFigureToDataStorage(figure, qString);
MEASUREMENT_DEBUG << "PlanarCircle initialized...";
}
void QmitkMeasurementView::ActionDrawEllipseTriggered(bool checked)
{
Q_UNUSED(checked)
mitk::PlanarEllipse::Pointer figure = mitk::PlanarEllipse::New();
QString qString = QString("Ellipse%1").arg(++d->m_EllipseCounter);
this->AddFigureToDataStorage(figure, qString);
MEASUREMENT_DEBUG << "PlanarEllipse initialized...";
}
void QmitkMeasurementView::ActionDrawDoubleEllipseTriggered(bool checked)
{
Q_UNUSED(checked)
mitk::PlanarDoubleEllipse::Pointer figure = mitk::PlanarDoubleEllipse::New();
QString qString = QString("DoubleEllipse%1").arg(++d->m_DoubleEllipseCounter);
this->AddFigureToDataStorage(figure, qString);
MEASUREMENT_DEBUG << "PlanarDoubleEllipse initialized...";
}
void QmitkMeasurementView::ActionDrawBezierCurveTriggered(bool checked)
{
Q_UNUSED(checked)
mitk::PlanarBezierCurve::Pointer figure = mitk::PlanarBezierCurve::New();
QString qString = QString("BezierCurve%1").arg(++d->m_BezierCurveCounter);
this->AddFigureToDataStorage(figure, qString);
MEASUREMENT_DEBUG << "PlanarBezierCurve initialized...";
}
void QmitkMeasurementView::ActionDrawSubdivisionPolygonTriggered(bool checked)
{
Q_UNUSED(checked)
mitk::PlanarSubdivisionPolygon::Pointer figure = mitk::PlanarSubdivisionPolygon::New();
QString qString = QString("SubdivisionPolygon%1").arg(++d->m_SubdivisionPolygonCounter);
this->AddFigureToDataStorage(figure, qString);
MEASUREMENT_DEBUG << "PlanarSubdivisionPolygon initialized...";
}
void QmitkMeasurementView::ActionDrawRectangleTriggered(bool checked)
{
Q_UNUSED(checked)
mitk::PlanarRectangle::Pointer figure = mitk::PlanarRectangle::New();
QString qString = QString("Rectangle%1").arg(++d->m_RectangleCounter);
this->AddFigureToDataStorage(figure, qString);
MEASUREMENT_DEBUG << "PlanarRectangle initialized...";
}
void QmitkMeasurementView::ActionDrawPolygonTriggered(bool checked)
{
Q_UNUSED(checked)
mitk::PlanarPolygon::Pointer figure = mitk::PlanarPolygon::New();
figure->ClosedOn();
QString qString = QString("Polygon%1").arg(++d->m_PolygonCounter);
mitk::DataNode::Pointer node = this->AddFigureToDataStorage(figure, qString);
node->SetProperty("planarfigure.isextendable",mitk::BoolProperty::New(true));
MEASUREMENT_DEBUG << "PlanarPolygon initialized...";
}
void QmitkMeasurementView::CopyToClipboard( bool checked )
{
Q_UNUSED(checked)
MEASUREMENT_DEBUG << "Copying current Text to clipboard...";
QString clipboardText = d->m_SelectedPlanarFiguresText->toPlainText();
QApplication::clipboard()->setText(clipboardText, QClipboard::Clipboard);
}
mitk::DataNode::Pointer QmitkMeasurementView::AddFigureToDataStorage(
mitk::PlanarFigure* figure, const QString& name)
{
// add as
MEASUREMENT_DEBUG << "Adding new figure to datastorage...";
if( d->m_SelectedImageNode.IsNull() )
{
MITK_ERROR << "No reference image available";
return 0;
}
mitk::DataNode::Pointer newNode = mitk::DataNode::New();
newNode->SetName(name.toStdString());
newNode->SetData(figure);
// set as selected
newNode->SetSelected( true );
this->GetDataStorage()->Add(newNode, d->m_SelectedImageNode);
// set all others in selection as deselected
for( int i=0; i<d->m_CurrentSelection.size(); ++i)
d->m_CurrentSelection.at(i)->SetSelected(false);
d->m_CurrentSelection.clear();
d->m_CurrentSelection.push_back( newNode );
this->UpdateMeasurementText();
this->DisableCrosshairNavigation();
d->m_DrawActionsToolBar->setEnabled(false);
d->m_UnintializedPlanarFigure = true;
return newNode;
}
void QmitkMeasurementView::UpdateMeasurementText()
{
d->m_SelectedPlanarFiguresText->clear();
QString infoText;
QString plainInfoText;
int j = 1;
mitk::PlanarFigure* _PlanarFigure = 0;
mitk::PlanarAngle* planarAngle = 0;
mitk::PlanarFourPointAngle* planarFourPointAngle = 0;
mitk::DataNode::Pointer node = 0;
for (int i=0; i<d->m_CurrentSelection.size(); ++i, ++j)
{
plainInfoText.clear();
node = d->m_CurrentSelection.at(i);
_PlanarFigure = dynamic_cast<mitk::PlanarFigure*> (node->GetData());
if( !_PlanarFigure )
continue;
if(j>1)
infoText.append("<br />");
infoText.append(QString("<b>%1</b><hr />").arg(QString::fromStdString(
node->GetName())));
plainInfoText.append(QString("%1").arg(QString::fromStdString(
node->GetName())));
planarAngle = dynamic_cast<mitk::PlanarAngle*> (_PlanarFigure);
if(!planarAngle)
{
planarFourPointAngle = dynamic_cast<mitk::PlanarFourPointAngle*> (_PlanarFigure);
}
double featureQuantity = 0.0;
for (unsigned int k = 0; k < _PlanarFigure->GetNumberOfFeatures(); ++k)
{
if ( !_PlanarFigure->IsFeatureActive( k ) ) continue;
featureQuantity = _PlanarFigure->GetQuantity(k);
if ((planarAngle && k == planarAngle->FEATURE_ID_ANGLE)
|| (planarFourPointAngle && k == planarFourPointAngle->FEATURE_ID_ANGLE))
featureQuantity = featureQuantity * 180 / vnl_math::pi;
infoText.append(
QString("<i>%1</i>: %2 %3") .arg(QString(
_PlanarFigure->GetFeatureName(k))) .arg(featureQuantity, 0, 'f',
2) .arg(QString(_PlanarFigure->GetFeatureUnit(k))));
plainInfoText.append(
QString("\n%1: %2 %3") .arg(QString(_PlanarFigure->GetFeatureName(k))) .arg(
featureQuantity, 0, 'f', 2) .arg(QString(
_PlanarFigure->GetFeatureUnit(k))));
if(k+1 != _PlanarFigure->GetNumberOfFeatures())
infoText.append("<br />");
}
if (j != d->m_CurrentSelection.size())
infoText.append("<br />");
}
d->m_SelectedPlanarFiguresText->setHtml(infoText);
}
void QmitkMeasurementView::AddAllInteractors()
{
MEASUREMENT_DEBUG << "Adding interactors and observers to all planar figures";
mitk::DataStorage::SetOfObjects::ConstPointer planarFigures = this->GetAllPlanarFigures();
for(mitk::DataStorage::SetOfObjects::ConstIterator it=planarFigures->Begin();
it!=planarFigures->End(); it++)
{
this->NodeAdded( it.Value() );
}
}
void QmitkMeasurementView::RemoveAllInteractors()
{
MEASUREMENT_DEBUG << "Removing interactors and observers from all planar figures";
mitk::DataStorage::SetOfObjects::ConstPointer planarFigures = this->GetAllPlanarFigures();
for(mitk::DataStorage::SetOfObjects::ConstIterator it=planarFigures->Begin();
it!=planarFigures->End(); it++)
{
this->NodeRemoved( it.Value() );
}
}
mitk::DataNode::Pointer QmitkMeasurementView::DetectTopMostVisibleImage()
{
// get all images from the data storage which are not a segmentation
mitk::TNodePredicateDataType<mitk::Image>::Pointer isImage = mitk::TNodePredicateDataType<mitk::Image>::New();
mitk::NodePredicateProperty::Pointer isBinary = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true));
mitk::NodePredicateNot::Pointer isNotBinary = mitk::NodePredicateNot::New( isBinary );
mitk::NodePredicateAnd::Pointer isNormalImage = mitk::NodePredicateAnd::New( isImage, isNotBinary );
mitk::DataStorage::SetOfObjects::ConstPointer Images
= this->GetDataStorage()->GetSubset( isNormalImage );
mitk::DataNode::Pointer currentNode;
int maxLayer = itk::NumericTraits<int>::min();
// iterate over selection
for (mitk::DataStorage::SetOfObjects::ConstIterator sofIt = Images->Begin(); sofIt != Images->End(); ++sofIt)
{
mitk::DataNode::Pointer node = sofIt->Value();
if ( node.IsNull() )
continue;
if (node->IsVisible(NULL) == false)
continue;
// we also do not want to assign planar figures to helper objects ( even if they are of type image )
if (node->GetProperty("helper object"))
continue;
int layer = 0;
node->GetIntProperty("layer", layer);
if ( layer < maxLayer )
{
continue;
}
else
{
maxLayer = layer;
currentNode = node;
}
}
return currentNode;
}
void QmitkMeasurementView::EnableCrosshairNavigation()
{
MEASUREMENT_DEBUG << "EnableCrosshairNavigation";
// enable the crosshair navigation
if (mitk::ILinkedRenderWindowPart* linkedRenderWindow =
dynamic_cast<mitk::ILinkedRenderWindowPart*>(this->GetRenderWindowPart()))
{
MEASUREMENT_DEBUG << "enabling linked navigation";
linkedRenderWindow->EnableLinkedNavigation(true);
linkedRenderWindow->EnableSlicingPlanes(true);
}
}
void QmitkMeasurementView::DisableCrosshairNavigation()
{
MEASUREMENT_DEBUG << "DisableCrosshairNavigation";
// disable the crosshair navigation during the drawing
if (mitk::ILinkedRenderWindowPart* linkedRenderWindow =
dynamic_cast<mitk::ILinkedRenderWindowPart*>(this->GetRenderWindowPart()))
{
MEASUREMENT_DEBUG << "disabling linked navigation";
linkedRenderWindow->EnableLinkedNavigation(false);
linkedRenderWindow->EnableSlicingPlanes(false);
}
}
mitk::DataStorage::SetOfObjects::ConstPointer QmitkMeasurementView::GetAllPlanarFigures() const
{
mitk::TNodePredicateDataType<mitk::PlanarFigure>::Pointer isPlanarFigure = mitk::TNodePredicateDataType<mitk::PlanarFigure>::New();
mitk::NodePredicateProperty::Pointer isNotHelperObject = mitk::NodePredicateProperty::New("helper object", mitk::BoolProperty::New(false));
mitk::NodePredicateAnd::Pointer isNotHelperButPlanarFigure = mitk::NodePredicateAnd::New( isPlanarFigure, isNotHelperObject );
return this->GetDataStorage()->GetSubset( isPlanarFigure );
}
diff --git a/Plugins/org.mitk.gui.qt.registration/src/internal/QmitkDeformableRegistrationView.cpp b/Plugins/org.mitk.gui.qt.registration/src/internal/QmitkDeformableRegistrationView.cpp
index f74a4bf5d1..3fab714a72 100644
--- a/Plugins/org.mitk.gui.qt.registration/src/internal/QmitkDeformableRegistrationView.cpp
+++ b/Plugins/org.mitk.gui.qt.registration/src/internal/QmitkDeformableRegistrationView.cpp
@@ -1,644 +1,644 @@
/*===================================================================
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 "QmitkDeformableRegistrationView.h"
#include "ui_QmitkDeformableRegistrationViewControls.h"
#include "QmitkStdMultiWidget.h"
#include "qinputdialog.h"
#include "qmessagebox.h"
#include "qcursor.h"
#include "qapplication.h"
#include "qradiobutton.h"
#include "qslider.h"
#include <vtkTransform.h>
#include "mitkNodePredicateDataType.h"
#include "mitkNodePredicateProperty.h"
#include "mitkNodePredicateAnd.h"
#include "mitkNodePredicateNot.h"
#include "mitkVectorImageMapper2D.h"
#include <mitkImageCast.h>
#include "itkImageFileReader.h"
#include "itkWarpImageFilter.h"
#include "mitkDataNodeObject.h"
#include "berryIWorkbenchWindow.h"
#include "berryISelectionService.h"
typedef itk::Vector< float, 3 > VectorType;
typedef itk::Image< VectorType, 3 > DeformationFieldType;
typedef itk::ImageFileReader< DeformationFieldType > ImageReaderType;
const std::string QmitkDeformableRegistrationView::VIEW_ID = "org.mitk.views.deformableregistration";
using namespace berry;
struct SelListenerDeformableRegistration : ISelectionListener
{
berryObjectMacro(SelListenerDeformableRegistration);
SelListenerDeformableRegistration(QmitkDeformableRegistrationView* view)
{
m_View = view;
}
void DoSelectionChanged(ISelection::ConstPointer selection)
{
// if(!m_View->IsVisible())
// return;
// save current selection in member variable
m_View->m_CurrentSelection = selection.Cast<const IStructuredSelection>();
// do something with the selected items
if(m_View->m_CurrentSelection)
{
if (m_View->m_CurrentSelection->Size() != 2)
{
if (m_View->m_FixedNode.IsNull() || m_View->m_MovingNode.IsNull())
{
m_View->m_Controls.m_StatusLabel->show();
m_View->m_Controls.TextLabelFixed->hide();
m_View->m_Controls.m_SwitchImages->hide();
m_View->m_Controls.m_FixedLabel->hide();
m_View->m_Controls.TextLabelMoving->hide();
m_View->m_Controls.m_MovingLabel->hide();
m_View->m_Controls.m_OpacityLabel->setEnabled(false);
m_View->m_Controls.m_OpacitySlider->setEnabled(false);
m_View->m_Controls.label->setEnabled(false);
m_View->m_Controls.label_2->setEnabled(false);
m_View->m_Controls.m_ShowRedGreenValues->setEnabled(false);
}
}
else
{
m_View->m_Controls.m_StatusLabel->hide();
bool foundFixedImage = false;
mitk::DataNode::Pointer fixedNode;
// iterate selection
for (IStructuredSelection::iterator i = m_View->m_CurrentSelection->Begin();
i != m_View->m_CurrentSelection->End(); ++i)
{
// extract datatree node
if (mitk::DataNodeObject::Pointer nodeObj = i->Cast<mitk::DataNodeObject>())
{
mitk::DataNode::Pointer node = nodeObj->GetDataNode();
// only look at interesting types
if(QString("Image").compare(node->GetData()->GetNameOfClass())==0)
{
if (dynamic_cast<mitk::Image*>(node->GetData())->GetDimension() == 4)
{
m_View->m_Controls.m_StatusLabel->show();
QMessageBox::information( NULL, "DeformableRegistration", "Only 2D or 3D images can be processed.", QMessageBox::Ok );
return;
}
if (foundFixedImage == false)
{
fixedNode = node;
foundFixedImage = true;
}
else
{
m_View->SetImagesVisible(selection);
m_View->FixedSelected(fixedNode);
m_View->MovingSelected(node);
m_View->m_Controls.m_StatusLabel->hide();
m_View->m_Controls.TextLabelFixed->show();
m_View->m_Controls.m_SwitchImages->show();
m_View->m_Controls.m_FixedLabel->show();
m_View->m_Controls.TextLabelMoving->show();
m_View->m_Controls.m_MovingLabel->show();
m_View->m_Controls.m_OpacityLabel->setEnabled(true);
m_View->m_Controls.m_OpacitySlider->setEnabled(true);
m_View->m_Controls.label->setEnabled(true);
m_View->m_Controls.label_2->setEnabled(true);
m_View->m_Controls.m_ShowRedGreenValues->setEnabled(true);
}
}
else
{
m_View->m_Controls.m_StatusLabel->show();
return;
}
}
}
}
}
else if (m_View->m_FixedNode.IsNull() || m_View->m_MovingNode.IsNull())
{
m_View->m_Controls.m_StatusLabel->show();
}
}
void SelectionChanged(IWorkbenchPart::Pointer part, ISelection::ConstPointer selection)
{
// check, if selection comes from datamanager
if (part)
{
QString partname(part->GetPartName().c_str());
if(partname.compare("Data Manager")==0)
{
// apply selection
DoSelectionChanged(selection);
}
}
}
QmitkDeformableRegistrationView* m_View;
};
QmitkDeformableRegistrationView::QmitkDeformableRegistrationView(QObject * /*parent*/, const char * /*name*/)
: QmitkFunctionality() , m_MultiWidget(NULL), m_MovingNode(NULL), m_FixedNode(NULL), m_ShowRedGreen(false),
m_Opacity(0.5), m_OriginalOpacity(1.0), m_Deactivated(false)
{
this->GetDataStorage()->RemoveNodeEvent.AddListener(mitk::MessageDelegate1<QmitkDeformableRegistrationView,
const mitk::DataNode*> ( this, &QmitkDeformableRegistrationView::DataNodeHasBeenRemoved ));
}
QmitkDeformableRegistrationView::~QmitkDeformableRegistrationView()
{
if (m_SelListener.IsNotNull())
{
berry::ISelectionService* s = GetSite()->GetWorkbenchWindow()->GetSelectionService();
if(s)
s->RemovePostSelectionListener(m_SelListener);
m_SelListener = NULL;
}
}
void QmitkDeformableRegistrationView::CreateQtPartControl(QWidget* parent)
{
m_Controls.setupUi(parent);
m_Parent->setEnabled(false);
this->CreateConnections();
m_Controls.TextLabelFixed->hide();
m_Controls.m_SwitchImages->hide();
m_Controls.m_FixedLabel->hide();
m_Controls.TextLabelMoving->hide();
m_Controls.m_MovingLabel->hide();
m_Controls.m_OpacityLabel->setEnabled(false);
m_Controls.m_OpacitySlider->setEnabled(false);
m_Controls.label->setEnabled(false);
m_Controls.label_2->setEnabled(false);
m_Controls.m_ShowRedGreenValues->setEnabled(false);
m_Controls.m_DeformableTransform->hide();
if (m_Controls.m_DeformableTransform->currentIndex() == 0)
{
m_Controls.m_QmitkDemonsRegistrationViewControls->show();
m_Controls.m_QmitkBSplineRegistrationViewControls->hide();
}
else
{
m_Controls.m_QmitkDemonsRegistrationViewControls->hide();
m_Controls.m_QmitkBSplineRegistrationViewControls->show();
}
this->CheckCalculateEnabled();
}
void QmitkDeformableRegistrationView::DataNodeHasBeenRemoved(const mitk::DataNode* node)
{
if(node == m_FixedNode || node == m_MovingNode)
{
m_Controls.m_StatusLabel->show();
m_Controls.TextLabelFixed->hide();
m_Controls.m_SwitchImages->hide();
m_Controls.m_FixedLabel->hide();
m_Controls.TextLabelMoving->hide();
m_Controls.m_MovingLabel->hide();
m_Controls.m_OpacityLabel->setEnabled(false);
m_Controls.m_OpacitySlider->setEnabled(false);
m_Controls.label->setEnabled(false);
m_Controls.label_2->setEnabled(false);
m_Controls.m_ShowRedGreenValues->setEnabled(false);
m_Controls.m_DeformableTransform->hide();
m_Controls.m_CalculateTransformation->setEnabled(false);
}
}
void QmitkDeformableRegistrationView::ApplyDeformationField()
{
ImageReaderType::Pointer reader = ImageReaderType::New();
reader->SetFileName( m_Controls.m_QmitkBSplineRegistrationViewControls->m_Controls.m_DeformationField->text().toStdString() );
reader->Update();
DeformationFieldType::Pointer deformationField = reader->GetOutput();
mitk::Image * mimage = dynamic_cast<mitk::Image*> (m_MovingNode->GetData());
mitk::Image * fimage = dynamic_cast<mitk::Image*> (m_FixedNode->GetData());
typedef itk::Image<float, 3> FloatImageType;
FloatImageType::Pointer itkMovingImage = FloatImageType::New();
FloatImageType::Pointer itkFixedImage = FloatImageType::New();
mitk::CastToItkImage(mimage, itkMovingImage);
mitk::CastToItkImage(fimage, itkFixedImage);
typedef itk::WarpImageFilter<
FloatImageType,
FloatImageType,
DeformationFieldType > WarperType;
typedef itk::LinearInterpolateImageFunction<
FloatImageType,
double > InterpolatorType;
WarperType::Pointer warper = WarperType::New();
InterpolatorType::Pointer interpolator = InterpolatorType::New();
warper->SetInput( itkMovingImage );
warper->SetInterpolator( interpolator );
warper->SetOutputSpacing( itkFixedImage->GetSpacing() );
warper->SetOutputOrigin( itkFixedImage->GetOrigin() );
warper->SetOutputDirection (itkFixedImage->GetDirection() );
warper->SetDisplacementField( deformationField );
warper->Update();
FloatImageType::Pointer outputImage = warper->GetOutput();
mitk::Image::Pointer result = mitk::Image::New();
mitk::CastToMitkImage(outputImage, result);
// Create new DataNode
mitk::DataNode::Pointer newNode = mitk::DataNode::New();
newNode->SetData( result );
newNode->SetProperty( "name", mitk::StringProperty::New("warped image") );
// add the new datatree node to the datatree
this->GetDefaultDataStorage()->Add(newNode);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
//Image::Pointer outputImage = this->GetOutput();
//mitk::CastToMitkImage( warper->GetOutput(), outputImage );
}
void QmitkDeformableRegistrationView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget)
{
m_Parent->setEnabled(true);
m_MultiWidget = &stdMultiWidget;
m_MultiWidget->SetWidgetPlanesVisibility(true);
}
void QmitkDeformableRegistrationView::StdMultiWidgetNotAvailable()
{
m_Parent->setEnabled(false);
m_MultiWidget = NULL;
}
void QmitkDeformableRegistrationView::CreateConnections()
{
connect(m_Controls.m_ShowRedGreenValues, SIGNAL(toggled(bool)), this, SLOT(ShowRedGreen(bool)));
connect(m_Controls.m_DeformableTransform, SIGNAL(currentChanged(int)), this, SLOT(TabChanged(int)));
connect(m_Controls.m_OpacitySlider, SIGNAL(sliderMoved(int)), this, SLOT(OpacityUpdate(int)));
connect(m_Controls.m_CalculateTransformation, SIGNAL(clicked()), this, SLOT(Calculate()));
connect((QObject*)(m_Controls.m_SwitchImages),SIGNAL(clicked()),this,SLOT(SwitchImages()));
connect(this,SIGNAL(calculateBSplineRegistration()),m_Controls.m_QmitkBSplineRegistrationViewControls,SLOT(CalculateTransformation()));
connect( (QObject*)(m_Controls.m_QmitkBSplineRegistrationViewControls->m_Controls.m_ApplyDeformationField),
SIGNAL(clicked()),
(QObject*) this,
SLOT(ApplyDeformationField()) );
}
void QmitkDeformableRegistrationView::Activated()
{
m_Deactivated = false;
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
QmitkFunctionality::Activated();
if (m_SelListener.IsNull())
{
m_SelListener = berry::ISelectionListener::Pointer(new SelListenerDeformableRegistration(this));
this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->AddPostSelectionListener(/*"org.mitk.views.datamanager",*/ m_SelListener);
berry::ISelection::ConstPointer sel(
this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->GetSelection("org.mitk.views.datamanager"));
m_CurrentSelection = sel.Cast<const IStructuredSelection>();
m_SelListener.Cast<SelListenerDeformableRegistration>()->DoSelectionChanged(sel);
}
this->OpacityUpdate(m_Controls.m_OpacitySlider->value());
this->ShowRedGreen(m_Controls.m_ShowRedGreenValues->isChecked());
}
void QmitkDeformableRegistrationView::Visible()
{
/*
m_Deactivated = false;
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
QmitkFunctionality::Activated();
if (m_SelListener.IsNull())
{
m_SelListener = berry::ISelectionListener::Pointer(new SelListenerDeformableRegistration(this));
this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->AddPostSelectionListener("org.mitk.views.datamanager", m_SelListener);
berry::ISelection::ConstPointer sel(
this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->GetSelection("org.mitk.views.datamanager"));
m_CurrentSelection = sel.Cast<const IStructuredSelection>();
m_SelListener.Cast<SelListenerDeformableRegistration>()->DoSelectionChanged(sel);
}
this->OpacityUpdate(m_Controls.m_OpacitySlider->value());
this->ShowRedGreen(m_Controls.m_ShowRedGreenValues->isChecked());*/
}
void QmitkDeformableRegistrationView::Deactivated()
{
m_Deactivated = true;
this->SetImageColor(false);
if (m_FixedNode.IsNotNull())
m_FixedNode->SetOpacity(1.0);
if (m_MovingNode.IsNotNull())
{
m_MovingNode->SetOpacity(m_OriginalOpacity);
}
m_FixedNode = NULL;
m_MovingNode = NULL;
berry::ISelectionService* s = GetSite()->GetWorkbenchWindow()->GetSelectionService();
if(s)
s->RemovePostSelectionListener(m_SelListener);
m_SelListener = NULL;
}
void QmitkDeformableRegistrationView::Hidden()
{
/*
m_Deactivated = true;
this->SetImageColor(false);
if (m_MovingNode.IsNotNull())
{
m_MovingNode->SetOpacity(m_OriginalOpacity);
}
m_FixedNode = NULL;
m_MovingNode = NULL;
berry::ISelectionService* s = GetSite()->GetWorkbenchWindow()->GetSelectionService();
if(s)
s->RemovePostSelectionListener(m_SelListener);
m_SelListener = NULL;*/
//mitk::RenderingManager::GetInstance()->RequestUpdateAll();
//QmitkFunctionality::Deactivated();
}
void QmitkDeformableRegistrationView::FixedSelected(mitk::DataNode::Pointer fixedImage)
{
if (fixedImage.IsNotNull())
{
if (m_FixedNode != fixedImage)
{
// remove changes on previous selected node
if (m_FixedNode.IsNotNull())
{
this->SetImageColor(false);
m_FixedNode->SetOpacity(1.0);
m_FixedNode->SetVisibility(false);
m_FixedNode->SetProperty("selectedFixedImage", mitk::BoolProperty::New(false));
}
// get selected node
m_FixedNode = fixedImage;
m_FixedNode->SetOpacity(0.5);
m_Controls.TextLabelFixed->setText(QString::fromStdString(m_FixedNode->GetName()));
m_Controls.m_FixedLabel->show();
m_Controls.TextLabelFixed->show();
m_Controls.m_SwitchImages->show();
mitk::ColorProperty::Pointer colorProperty;
colorProperty = dynamic_cast<mitk::ColorProperty*>(m_FixedNode->GetProperty("color"));
if ( colorProperty.IsNotNull() )
{
m_FixedColor = colorProperty->GetColor();
}
this->SetImageColor(m_ShowRedGreen);
m_FixedNode->SetVisibility(true);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
else
{
m_FixedNode = fixedImage;
m_Controls.m_FixedLabel->hide();
m_Controls.TextLabelFixed->hide();
m_Controls.m_SwitchImages->hide();
}
this->CheckCalculateEnabled();
}
void QmitkDeformableRegistrationView::MovingSelected(mitk::DataNode::Pointer movingImage)
{
if (movingImage.IsNotNull())
{
if (m_MovingNode != movingImage)
{
if (m_MovingNode.IsNotNull())
{
m_MovingNode->SetOpacity(m_OriginalOpacity);
if (m_FixedNode == m_MovingNode)
m_FixedNode->SetOpacity(0.5);
this->SetImageColor(false);
}
m_MovingNode = movingImage;
m_Controls.TextLabelMoving->setText(QString::fromStdString(m_MovingNode->GetName()));
m_Controls.m_MovingLabel->show();
m_Controls.TextLabelMoving->show();
mitk::ColorProperty::Pointer colorProperty;
colorProperty = dynamic_cast<mitk::ColorProperty*>(m_MovingNode->GetProperty("color"));
if ( colorProperty.IsNotNull() )
{
m_MovingColor = colorProperty->GetColor();
}
this->SetImageColor(m_ShowRedGreen);
m_MovingNode->GetFloatProperty("opacity", m_OriginalOpacity);
this->OpacityUpdate(m_Opacity);
m_MovingNode->SetVisibility(true);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
else
{
m_MovingNode = NULL;
m_Controls.m_MovingLabel->hide();
m_Controls.TextLabelMoving->hide();
}
this->CheckCalculateEnabled();
}
bool QmitkDeformableRegistrationView::CheckCalculate()
{
if(m_MovingNode==m_FixedNode)
return false;
return true;
}
void QmitkDeformableRegistrationView::ShowRedGreen(bool redGreen)
{
m_ShowRedGreen = redGreen;
this->SetImageColor(m_ShowRedGreen);
}
void QmitkDeformableRegistrationView::SetImageColor(bool redGreen)
{
if (!redGreen && m_FixedNode.IsNotNull())
{
m_FixedNode->SetColor(m_FixedColor);
}
if (!redGreen && m_MovingNode.IsNotNull())
{
m_MovingNode->SetColor(m_MovingColor);
}
if (redGreen && m_FixedNode.IsNotNull())
{
m_FixedNode->SetColor(1.0f, 0.0f, 0.0f);
}
if (redGreen && m_MovingNode.IsNotNull())
{
m_MovingNode->SetColor(0.0f, 1.0f, 0.0f);
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkDeformableRegistrationView::OpacityUpdate(float opacity)
{
m_Opacity = opacity;
if (m_MovingNode.IsNotNull())
{
m_MovingNode->SetOpacity(m_Opacity);
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkDeformableRegistrationView::OpacityUpdate(int opacity)
{
float fValue = ((float)opacity)/100.0f;
this->OpacityUpdate(fValue);
}
void QmitkDeformableRegistrationView::CheckCalculateEnabled()
{
if (m_FixedNode.IsNotNull() && m_MovingNode.IsNotNull())
{
m_Controls.m_CalculateTransformation->setEnabled(true);
}
else
{
m_Controls.m_CalculateTransformation->setEnabled(false);
}
}
void QmitkDeformableRegistrationView::Calculate()
{
if (m_Controls.m_DeformableTransform->tabText(m_Controls.m_DeformableTransform->currentIndex()) == "Demons")
{
m_Controls.m_QmitkDemonsRegistrationViewControls->SetFixedNode(m_FixedNode);
m_Controls.m_QmitkDemonsRegistrationViewControls->SetMovingNode(m_MovingNode);
try
{
m_Controls.m_QmitkDemonsRegistrationViewControls->CalculateTransformation();
}
catch (itk::ExceptionObject& excpt)
{
QMessageBox::information( NULL, "Registration exception", excpt.GetDescription(), QMessageBox::Ok );
return;
}
mitk::Image::Pointer resultImage = m_Controls.m_QmitkDemonsRegistrationViewControls->GetResultImage();
mitk::Image::Pointer resultDeformationField = m_Controls.m_QmitkDemonsRegistrationViewControls->GetResultDeformationfield();
if (resultImage.IsNotNull())
{
mitk::DataNode::Pointer resultImageNode = mitk::DataNode::New();
resultImageNode->SetData(resultImage);
mitk::LevelWindowProperty::Pointer levWinProp = mitk::LevelWindowProperty::New();
mitk::LevelWindow levelWindow;
levelWindow.SetAuto( resultImage );
levWinProp->SetLevelWindow(levelWindow);
resultImageNode->GetPropertyList()->SetProperty("levelwindow",levWinProp);
resultImageNode->SetStringProperty("name", "DeformableRegistrationResultImage");
this->GetDataStorage()->Add(resultImageNode, m_MovingNode);
}
if (resultDeformationField.IsNotNull())
{
mitk::DataNode::Pointer resultDeformationFieldNode = mitk::DataNode::New();
resultDeformationFieldNode->SetData(resultDeformationField);
mitk::LevelWindowProperty::Pointer levWinProp = mitk::LevelWindowProperty::New();
mitk::LevelWindow levelWindow;
levelWindow.SetAuto( resultDeformationField );
levWinProp->SetLevelWindow(levelWindow);
resultDeformationFieldNode->GetPropertyList()->SetProperty("levelwindow",levWinProp);
resultDeformationFieldNode->SetStringProperty("name", "DeformableRegistrationResultDeformationField");
mitk::VectorImageMapper2D::Pointer mapper = mitk::VectorImageMapper2D::New();
resultDeformationFieldNode->SetMapper(1, mapper);
resultDeformationFieldNode->SetVisibility(false);
this->GetDataStorage()->Add(resultDeformationFieldNode, m_MovingNode);
}
}
else if (m_Controls.m_DeformableTransform->tabText(m_Controls.m_DeformableTransform->currentIndex()) == "B-Spline")
{
m_Controls.m_QmitkBSplineRegistrationViewControls->SetFixedNode(m_FixedNode);
m_Controls.m_QmitkBSplineRegistrationViewControls->SetMovingNode(m_MovingNode);
emit calculateBSplineRegistration();
}
}
void QmitkDeformableRegistrationView::SetImagesVisible(berry::ISelection::ConstPointer /*selection*/)
{
if (this->m_CurrentSelection->Size() == 0)
{
// show all images
mitk::DataStorage::SetOfObjects::ConstPointer setOfObjects = this->GetDataStorage()->GetAll();
for (mitk::DataStorage::SetOfObjects::ConstIterator nodeIt = setOfObjects->Begin()
; nodeIt != setOfObjects->End(); ++nodeIt) // for each node
{
- if ( (nodeIt->Value().IsNotNull()) && (nodeIt->Value()->GetProperty("visible")) && dynamic_cast<mitk::Geometry2DData*>(nodeIt->Value()->GetData())==NULL)
+ if ( (nodeIt->Value().IsNotNull()) && (nodeIt->Value()->GetProperty("visible")) && dynamic_cast<mitk::PlaneGeometryData*>(nodeIt->Value()->GetData())==NULL)
{
nodeIt->Value()->SetVisibility(true);
}
}
}
else
{
// hide all images
mitk::DataStorage::SetOfObjects::ConstPointer setOfObjects = this->GetDataStorage()->GetAll();
for (mitk::DataStorage::SetOfObjects::ConstIterator nodeIt = setOfObjects->Begin()
; nodeIt != setOfObjects->End(); ++nodeIt) // for each node
{
- if ( (nodeIt->Value().IsNotNull()) && (nodeIt->Value()->GetProperty("visible")) && dynamic_cast<mitk::Geometry2DData*>(nodeIt->Value()->GetData())==NULL)
+ if ( (nodeIt->Value().IsNotNull()) && (nodeIt->Value()->GetProperty("visible")) && dynamic_cast<mitk::PlaneGeometryData*>(nodeIt->Value()->GetData())==NULL)
{
nodeIt->Value()->SetVisibility(false);
}
}
}
}
void QmitkDeformableRegistrationView::TabChanged(int index)
{
if (index == 0)
{
m_Controls.m_QmitkDemonsRegistrationViewControls->show();
m_Controls.m_QmitkBSplineRegistrationViewControls->hide();
}
else
{
m_Controls.m_QmitkDemonsRegistrationViewControls->hide();
m_Controls.m_QmitkBSplineRegistrationViewControls->show();
}
}
void QmitkDeformableRegistrationView::SwitchImages()
{
mitk::DataNode::Pointer newMoving = m_FixedNode;
mitk::DataNode::Pointer newFixed = m_MovingNode;
this->FixedSelected(newFixed);
this->MovingSelected(newMoving);
}
diff --git a/Plugins/org.mitk.gui.qt.registration/src/internal/QmitkPointBasedRegistrationView.cpp b/Plugins/org.mitk.gui.qt.registration/src/internal/QmitkPointBasedRegistrationView.cpp
index 35a2b9f717..7ccd197187 100644
--- a/Plugins/org.mitk.gui.qt.registration/src/internal/QmitkPointBasedRegistrationView.cpp
+++ b/Plugins/org.mitk.gui.qt.registration/src/internal/QmitkPointBasedRegistrationView.cpp
@@ -1,1360 +1,1368 @@
/*===================================================================
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 "QmitkPointBasedRegistrationView.h"
#include "ui_QmitkPointBasedRegistrationViewControls.h"
#include "QmitkPointListWidget.h"
#include <vtkIterativeClosestPointTransform.h>
#include <vtkMatrix4x4.h>
#include <vtkMath.h>
#include "vtkPolyData.h"
#include <vtkLandmarkTransform.h>
#include <QmitkStdMultiWidget.h>
#include "qradiobutton.h"
#include "qapplication.h"
#include <qcursor.h>
#include <qinputdialog.h>
#include <qlcdnumber.h>
#include <qlabel.h>
#include "qmessagebox.h"
#include "mitkLandmarkWarping.h"
#include <mitkPointOperation.h>
#include <mitkPositionEvent.h>
#include "mitkOperationEvent.h"
#include "mitkUndoController.h"
#include <mitkPointSetWriter.h>
#include <mitkPointSetReader.h>
#include "mitkNodePredicateDataType.h"
#include "mitkNodePredicateProperty.h"
#include "mitkNodePredicateAnd.h"
#include "mitkNodePredicateNot.h"
#include <mitkMessage.h>
#include <mitkImageCast.h>
#include <itkCommand.h>
#include "mitkDataNodeObject.h"
#include "berryIWorkbenchWindow.h"
#include "berryISelectionService.h"
const std::string QmitkPointBasedRegistrationView::VIEW_ID = "org.mitk.views.pointbasedregistration";
using namespace berry;
struct SelListenerPointBasedRegistration : ISelectionListener
{
berryObjectMacro(SelListenerPointBasedRegistration);
SelListenerPointBasedRegistration(QmitkPointBasedRegistrationView* view)
{
m_View = view;
}
void DoSelectionChanged(ISelection::ConstPointer selection)
{
// if(!m_View->IsVisible())
// return;
// save current selection in member variable
m_View->m_CurrentSelection = selection.Cast<const IStructuredSelection>();
// do something with the selected items
if(m_View->m_CurrentSelection)
{
if (m_View->m_CurrentSelection->Size() != 2)
{
if (m_View->m_FixedNode.IsNull() || m_View->m_MovingNode.IsNull())
{
m_View->m_Controls.m_StatusLabel->show();
m_View->m_Controls.TextLabelFixed->hide();
m_View->m_Controls.m_FixedLabel->hide();
m_View->m_Controls.line2->hide();
m_View->m_Controls.m_FixedPointListWidget->hide();
m_View->m_Controls.TextLabelMoving->hide();
m_View->m_Controls.m_MovingLabel->hide();
m_View->m_Controls.line1->hide();
m_View->m_Controls.m_MovingPointListWidget->hide();
m_View->m_Controls.m_OpacityLabel->hide();
m_View->m_Controls.m_OpacitySlider->hide();
m_View->m_Controls.label->hide();
m_View->m_Controls.label_2->hide();
m_View->m_Controls.m_SwitchImages->hide();
m_View->m_Controls.m_ShowRedGreenValues->setEnabled(false);
}
}
else
{
m_View->m_Controls.m_StatusLabel->hide();
bool foundFixedImage = false;
mitk::DataNode::Pointer fixedNode;
// iterate selection
for (IStructuredSelection::iterator i = m_View->m_CurrentSelection->Begin();
i != m_View->m_CurrentSelection->End(); ++i)
{
// extract datatree node
if (mitk::DataNodeObject::Pointer nodeObj = i->Cast<mitk::DataNodeObject>())
{
mitk::TNodePredicateDataType<mitk::BaseData>::Pointer isBaseData(mitk::TNodePredicateDataType<mitk::BaseData>::New());
mitk::TNodePredicateDataType<mitk::PointSet>::Pointer isPointSet(mitk::TNodePredicateDataType<mitk::PointSet>::New());
mitk::NodePredicateNot::Pointer notPointSet = mitk::NodePredicateNot::New(isPointSet);
- mitk::TNodePredicateDataType<mitk::Geometry2DData>::Pointer isGeometry2DData(mitk::TNodePredicateDataType<mitk::Geometry2DData>::New());
- mitk::NodePredicateNot::Pointer notGeometry2DData = mitk::NodePredicateNot::New(isGeometry2DData);
- mitk::NodePredicateAnd::Pointer notPointSetAndNotGeometry2DData = mitk::NodePredicateAnd::New( notPointSet, notGeometry2DData );
- mitk::NodePredicateAnd::Pointer predicate = mitk::NodePredicateAnd::New( isBaseData, notPointSetAndNotGeometry2DData );
+ mitk::TNodePredicateDataType<mitk::PlaneGeometryData>::Pointer isPlaneGeometryData(mitk::TNodePredicateDataType<mitk::PlaneGeometryData>::New());
+ mitk::NodePredicateNot::Pointer notPlaneGeometryData = mitk::NodePredicateNot::New(isPlaneGeometryData);
+ mitk::NodePredicateAnd::Pointer notPointSetAndNotPlaneGeometryData = mitk::NodePredicateAnd::New( notPointSet, notPlaneGeometryData );
+ mitk::NodePredicateAnd::Pointer predicate = mitk::NodePredicateAnd::New( isBaseData, notPointSetAndNotPlaneGeometryData );
mitk::DataStorage::SetOfObjects::ConstPointer setOfObjects = m_View->GetDataStorage()->GetSubset(predicate);
mitk::DataNode::Pointer node = nodeObj->GetDataNode();
// only look at interesting types
for (mitk::DataStorage::SetOfObjects::ConstIterator nodeIt = setOfObjects->Begin()
; nodeIt != setOfObjects->End(); ++nodeIt) // for each node
{
if(nodeIt->Value().GetPointer() == node.GetPointer())
{
// was - compare()
// use contain to allow other Image types to be selected, i.e. a diffusion image
if (QString( node->GetData()->GetNameOfClass() ).contains("Image") )
{
// verify that the node selected by name is really an image or derived class
mitk::Image* _image = dynamic_cast<mitk::Image*>(node->GetData());
if (_image != NULL)
{
if( _image->GetDimension() == 4)
{
m_View->m_Controls.m_StatusLabel->show();
QMessageBox::information( NULL, "PointBasedRegistration", "Only 2D or 3D images can be processed.", QMessageBox::Ok );
return;
}
if (foundFixedImage == false)
{
fixedNode = node;
foundFixedImage = true;
}
else
{
m_View->SetImagesVisible(selection);
m_View->FixedSelected(fixedNode);
m_View->MovingSelected(node);
m_View->m_Controls.m_StatusLabel->hide();
m_View->m_Controls.TextLabelFixed->show();
m_View->m_Controls.m_FixedLabel->show();
m_View->m_Controls.line2->show();
m_View->m_Controls.m_FixedPointListWidget->show();
m_View->m_Controls.TextLabelMoving->show();
m_View->m_Controls.m_MovingLabel->show();
m_View->m_Controls.line1->show();
m_View->m_Controls.m_MovingPointListWidget->show();
m_View->m_Controls.m_OpacityLabel->show();
m_View->m_Controls.m_OpacitySlider->show();
m_View->m_Controls.label->show();
m_View->m_Controls.label_2->show();
m_View->m_Controls.m_SwitchImages->show();
m_View->m_Controls.m_ShowRedGreenValues->setEnabled(true);
}
}
}
else
{
m_View->m_Controls.m_StatusLabel->show();
return;
}
}
}
}
}
if (m_View->m_FixedNode.IsNull() || m_View->m_MovingNode.IsNull())
{
m_View->m_Controls.m_StatusLabel->show();
}
}
}
else if (m_View->m_FixedNode.IsNull() || m_View->m_MovingNode.IsNull())
{
m_View->m_Controls.m_StatusLabel->show();
}
}
void SelectionChanged(IWorkbenchPart::Pointer part, ISelection::ConstPointer selection)
{
// check, if selection comes from datamanager
if (part)
{
QString partname(part->GetPartName().c_str());
if(partname.compare("Data Manager")==0)
{
// apply selection
DoSelectionChanged(selection);
}
}
}
QmitkPointBasedRegistrationView* m_View;
};
QmitkPointBasedRegistrationView::QmitkPointBasedRegistrationView(QObject * /*parent*/, const char * /*name*/)
: QmitkFunctionality(), m_SelListener(0), m_MultiWidget(NULL), m_FixedLandmarks(NULL), m_MovingLandmarks(NULL), m_MovingNode(NULL),
m_FixedNode(NULL), m_ShowRedGreen(false), m_Opacity(0.5), m_OriginalOpacity(1.0), m_Transformation(0), m_HideFixedImage(false), m_HideMovingImage(false),
m_OldFixedLabel(""), m_OldMovingLabel(""), m_Deactivated (false), m_CurrentFixedLandmarksObserverID(0), m_CurrentMovingLandmarksObserverID(0)
{
m_FixedLandmarksChangedCommand = itk::SimpleMemberCommand<QmitkPointBasedRegistrationView>::New();
m_FixedLandmarksChangedCommand->SetCallbackFunction(this, &QmitkPointBasedRegistrationView::updateFixedLandmarksList);
m_MovingLandmarksChangedCommand = itk::SimpleMemberCommand<QmitkPointBasedRegistrationView>::New();
m_MovingLandmarksChangedCommand->SetCallbackFunction(this, &QmitkPointBasedRegistrationView::updateMovingLandmarksList);
this->GetDataStorage()->RemoveNodeEvent.AddListener(mitk::MessageDelegate1<QmitkPointBasedRegistrationView,
const mitk::DataNode*> ( this, &QmitkPointBasedRegistrationView::DataNodeHasBeenRemoved ));
}
QmitkPointBasedRegistrationView::~QmitkPointBasedRegistrationView()
{
if(m_SelListener.IsNotNull())
{
berry::ISelectionService* s = GetSite()->GetWorkbenchWindow()->GetSelectionService();
if(s)
s->RemovePostSelectionListener(m_SelListener);
m_SelListener = NULL;
}
if (m_FixedPointSetNode.IsNotNull())
{
m_Controls.m_FixedPointListWidget->DeactivateInteractor(true);
m_FixedPointSetNode->SetProperty("label", mitk::StringProperty::New(m_OldFixedLabel));
}
if (m_MovingPointSetNode.IsNotNull())
{
m_Controls.m_MovingPointListWidget->DeactivateInteractor(true);
m_MovingPointSetNode->SetProperty("label", mitk::StringProperty::New(m_OldMovingLabel));
}
m_Controls.m_FixedPointListWidget->SetPointSetNode(NULL);
m_Controls.m_MovingPointListWidget->SetPointSetNode(NULL);
}
void QmitkPointBasedRegistrationView::CreateQtPartControl(QWidget* parent)
{
m_Controls.setupUi(parent);
m_Parent->setEnabled(false);
m_Controls.m_MeanErrorLCD->hide();
m_Controls.m_MeanError->hide();
m_Controls.TextLabelFixed->hide();
m_Controls.line2->hide();
m_Controls.m_FixedPointListWidget->hide();
m_Controls.m_FixedLabel->hide();
m_Controls.TextLabelMoving->hide();
m_Controls.m_MovingLabel->hide();
m_Controls.line1->hide();
m_Controls.m_MovingPointListWidget->hide();
m_Controls.m_OpacityLabel->hide();
m_Controls.m_OpacitySlider->hide();
m_Controls.label->hide();
m_Controls.label_2->hide();
m_Controls.m_SwitchImages->hide();
m_Controls.m_ShowRedGreenValues->setEnabled(false);
this->CreateConnections();
// let the point set widget know about the multi widget (cross hair updates)
m_Controls.m_FixedPointListWidget->SetMultiWidget( m_MultiWidget );
m_Controls.m_MovingPointListWidget->SetMultiWidget( m_MultiWidget );
}
void QmitkPointBasedRegistrationView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget)
{
m_Parent->setEnabled(true);
m_MultiWidget = &stdMultiWidget;
m_MultiWidget->SetWidgetPlanesVisibility(true);
m_Controls.m_FixedPointListWidget->SetMultiWidget( m_MultiWidget );
m_Controls.m_MovingPointListWidget->SetMultiWidget( m_MultiWidget );
}
void QmitkPointBasedRegistrationView::StdMultiWidgetNotAvailable()
{
m_Parent->setEnabled(false);
m_MultiWidget = NULL;
m_Controls.m_FixedPointListWidget->SetMultiWidget( NULL );
m_Controls.m_MovingPointListWidget->SetMultiWidget( NULL );
}
void QmitkPointBasedRegistrationView::CreateConnections()
{
connect( (QObject*)(m_Controls.m_FixedPointListWidget), SIGNAL(EditPointSets(bool)), (QObject*)(m_Controls.m_MovingPointListWidget), SLOT(DeactivateInteractor(bool)));
connect( (QObject*)(m_Controls.m_MovingPointListWidget), SIGNAL(EditPointSets(bool)), (QObject*)(m_Controls.m_FixedPointListWidget), SLOT(DeactivateInteractor(bool)));
connect( (QObject*)(m_Controls.m_FixedPointListWidget), SIGNAL(EditPointSets(bool)), this, SLOT(HideMovingImage(bool)));
connect( (QObject*)(m_Controls.m_MovingPointListWidget), SIGNAL(EditPointSets(bool)), this, SLOT(HideFixedImage(bool)));
connect( (QObject*)(m_Controls.m_FixedPointListWidget), SIGNAL(PointListChanged()), this, SLOT(updateFixedLandmarksList()));
connect( (QObject*)(m_Controls.m_MovingPointListWidget), SIGNAL(PointListChanged()), this, SLOT(updateMovingLandmarksList()));
connect((QObject*)(m_Controls.m_Calculate),SIGNAL(clicked()),this,SLOT(calculate()));
connect((QObject*)(m_Controls.m_SwitchImages),SIGNAL(clicked()),this,SLOT(SwitchImages()));
connect((QObject*)(m_Controls.m_UndoTransformation),SIGNAL(clicked()),this,SLOT(UndoTransformation()));
connect((QObject*)(m_Controls.m_RedoTransformation),SIGNAL(clicked()),this,SLOT(RedoTransformation()));
connect((QObject*)(m_Controls.m_ShowRedGreenValues),SIGNAL(toggled(bool)),this,SLOT(showRedGreen(bool)));
connect((QObject*)(m_Controls.m_OpacitySlider),SIGNAL(valueChanged(int)),this,SLOT(OpacityUpdate(int)));
connect((QObject*)(m_Controls.m_SelectedTransformationClass),SIGNAL(activated(int)), this,SLOT(transformationChanged(int)));
connect((QObject*)(m_Controls.m_UseICP),SIGNAL(toggled(bool)), this,SLOT(checkCalculateEnabled()));
connect((QObject*)(m_Controls.m_UseICP),SIGNAL(toggled(bool)), this,SLOT(checkLandmarkError()));
}
void QmitkPointBasedRegistrationView::Activated()
{
m_Deactivated = false;
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
QmitkFunctionality::Activated();
this->clearTransformationLists();
if (m_SelListener.IsNull())
{
m_SelListener = berry::ISelectionListener::Pointer(new SelListenerPointBasedRegistration(this));
this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->AddPostSelectionListener(/*"org.mitk.views.datamanager",*/ m_SelListener);
berry::ISelection::ConstPointer sel(
this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->GetSelection("org.mitk.views.datamanager"));
m_CurrentSelection = sel.Cast<const IStructuredSelection>();
m_SelListener.Cast<SelListenerPointBasedRegistration>()->DoSelectionChanged(sel);
}
this->OpacityUpdate(m_Controls.m_OpacitySlider->value());
this->showRedGreen(m_Controls.m_ShowRedGreenValues->isChecked());
}
void QmitkPointBasedRegistrationView::Visible()
{
}
void QmitkPointBasedRegistrationView::Deactivated()
{
m_Deactivated = true;
if (m_FixedPointSetNode.IsNotNull())
m_FixedPointSetNode->SetProperty("label", mitk::StringProperty::New(m_OldFixedLabel));
m_Controls.m_FixedPointListWidget->SetPointSetNode(NULL);
m_Controls.m_FixedPointListWidget->DeactivateInteractor(true);
if (m_MovingPointSetNode.IsNotNull())
m_MovingPointSetNode->SetProperty("label", mitk::StringProperty::New(m_OldMovingLabel));
m_Controls.m_MovingPointListWidget->SetPointSetNode(NULL);
m_Controls.m_MovingPointListWidget->DeactivateInteractor(true);
this->setImageColor(false);
if (m_FixedNode.IsNotNull())
m_FixedNode->SetOpacity(1.0);
if (m_MovingNode.IsNotNull())
{
m_MovingNode->SetOpacity(m_OriginalOpacity);
}
this->clearTransformationLists();
if (m_FixedPointSetNode.IsNotNull() && m_FixedLandmarks.IsNotNull() && m_FixedLandmarks->GetSize() == 0)
{
this->GetDataStorage()->Remove(m_FixedPointSetNode);
}
if (m_MovingPointSetNode.IsNotNull() && m_MovingLandmarks.IsNotNull() && m_MovingLandmarks->GetSize() == 0)
{
this->GetDataStorage()->Remove(m_MovingPointSetNode);
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
m_FixedNode = NULL;
m_MovingNode = NULL;
if(m_FixedLandmarks.IsNotNull())
m_FixedLandmarks->RemoveObserver(m_CurrentFixedLandmarksObserverID);
m_FixedLandmarks = NULL;
if(m_MovingLandmarks.IsNotNull())
m_MovingLandmarks->RemoveObserver(m_CurrentMovingLandmarksObserverID);
m_MovingLandmarks = NULL;
m_FixedPointSetNode = NULL;
m_MovingPointSetNode = NULL;
m_Controls.m_FixedLabel->hide();
m_Controls.TextLabelFixed->hide();
m_Controls.line2->hide();
m_Controls.m_FixedPointListWidget->hide();
m_Controls.m_MovingLabel->hide();
m_Controls.TextLabelMoving->hide();
m_Controls.line1->hide();
m_Controls.m_MovingPointListWidget->hide();
m_Controls.m_OpacityLabel->hide();
m_Controls.m_OpacitySlider->hide();
m_Controls.label->hide();
m_Controls.label_2->hide();
m_Controls.m_SwitchImages->hide();
berry::ISelectionService* s = GetSite()->GetWorkbenchWindow()->GetSelectionService();
if(s)
s->RemovePostSelectionListener(m_SelListener);
m_SelListener = NULL;
}
void QmitkPointBasedRegistrationView::Hidden()
{
/*
m_Deactivated = true;
if (m_FixedPointSetNode.IsNotNull())
m_FixedPointSetNode->SetProperty("label", mitk::StringProperty::New(m_OldFixedLabel));
m_Controls.m_FixedPointListWidget->SetPointSetNode(NULL);
m_Controls.m_FixedPointListWidget->DeactivateInteractor(true);
if (m_MovingPointSetNode.IsNotNull())
m_MovingPointSetNode->SetProperty("label", mitk::StringProperty::New(m_OldMovingLabel));
m_Controls.m_MovingPointListWidget->SetPointSetNode(NULL);
m_Controls.m_MovingPointListWidget->DeactivateInteractor(true);
this->setImageColor(false);
if (m_MovingNode.IsNotNull())
{
m_MovingNode->SetOpacity(m_OriginalOpacity);
}
this->clearTransformationLists();
if (m_FixedPointSetNode.IsNotNull() && m_FixedLandmarks.IsNotNull() && m_FixedLandmarks->GetSize() == 0)
{
this->GetDataStorage()->Remove(m_FixedPointSetNode);
}
if (m_MovingPointSetNode.IsNotNull() && m_MovingLandmarks.IsNotNull() && m_MovingLandmarks->GetSize() == 0)
{
this->GetDataStorage()->Remove(m_MovingPointSetNode);
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
m_FixedNode = NULL;
m_MovingNode = NULL;
if(m_FixedLandmarks.IsNotNull())
m_FixedLandmarks->RemoveObserver(m_CurrentFixedLandmarksObserverID);
m_FixedLandmarks = NULL;
if(m_MovingLandmarks.IsNotNull())
m_MovingLandmarks->RemoveObserver(m_CurrentMovingLandmarksObserverID);
m_MovingLandmarks = NULL;
m_FixedPointSetNode = NULL;
m_MovingPointSetNode = NULL;
m_Controls.m_FixedLabel->hide();
m_Controls.TextLabelFixed->hide();
m_Controls.line2->hide();
m_Controls.m_FixedPointListWidget->hide();
m_Controls.m_MovingLabel->hide();
m_Controls.TextLabelMoving->hide();
m_Controls.line1->hide();
m_Controls.m_MovingPointListWidget->hide();
m_Controls.m_OpacityLabel->hide();
m_Controls.m_OpacitySlider->hide();
m_Controls.label->hide();
m_Controls.label_2->hide();
m_Controls.m_SwitchImages->hide();
berry::ISelectionService* s = GetSite()->GetWorkbenchWindow()->GetSelectionService();
if(s)
s->RemovePostSelectionListener(m_SelListener);
m_SelListener = NULL;
//mitk::RenderingManager::GetInstance()->RequestUpdateAll();
//QmitkFunctionality::Deactivated();*/
}
void QmitkPointBasedRegistrationView::DataNodeHasBeenRemoved(const mitk::DataNode* node)
{
if(node == m_FixedNode || node == m_MovingNode)
{
m_Controls.m_StatusLabel->show();
m_Controls.TextLabelFixed->hide();
m_Controls.m_FixedLabel->hide();
m_Controls.line2->hide();
m_Controls.m_FixedPointListWidget->hide();
m_Controls.TextLabelMoving->hide();
m_Controls.m_MovingLabel->hide();
m_Controls.line1->hide();
m_Controls.m_MovingPointListWidget->hide();
m_Controls.m_OpacityLabel->hide();
m_Controls.m_OpacitySlider->hide();
m_Controls.label->hide();
m_Controls.label_2->hide();
m_Controls.m_SwitchImages->hide();
m_Controls.m_ShowRedGreenValues->setEnabled(false);
}
}
void QmitkPointBasedRegistrationView::FixedSelected(mitk::DataNode::Pointer fixedImage)
{
if(m_FixedLandmarks.IsNotNull())
m_FixedLandmarks->RemoveObserver(m_CurrentFixedLandmarksObserverID);
if (fixedImage.IsNotNull())
{
if (m_FixedNode != fixedImage)
{
// remove changes on previous selected node
if (m_FixedNode.IsNotNull())
{
this->setImageColor(false);
m_FixedNode->SetOpacity(1.0);
if (m_FixedPointSetNode.IsNotNull())
{
m_FixedPointSetNode->SetProperty("label", mitk::StringProperty::New(m_OldFixedLabel));
}
}
// get selected node
m_FixedNode = fixedImage;
m_FixedNode->SetOpacity(0.5);
m_FixedNode->SetVisibility(true);
m_Controls.m_FixedLabel->setText(QString::fromStdString(m_FixedNode->GetName()));
m_Controls.m_FixedLabel->show();
m_Controls.m_SwitchImages->show();
m_Controls.TextLabelFixed->show();
m_Controls.line2->show();
m_Controls.m_FixedPointListWidget->show();
mitk::ColorProperty::Pointer colorProperty;
colorProperty = dynamic_cast<mitk::ColorProperty*>(m_FixedNode->GetProperty("color"));
if ( colorProperty.IsNotNull() )
{
m_FixedColor = colorProperty->GetColor();
}
this->setImageColor(m_ShowRedGreen);
bool hasPointSetNode = false;
mitk::DataStorage::SetOfObjects::ConstPointer children = this->GetDataStorage()->GetDerivations(m_FixedNode);
unsigned long size;
size = children->Size();
for (unsigned long i = 0; i < size; ++i)
{
mitk::StringProperty::Pointer nameProp = dynamic_cast<mitk::StringProperty*>(children->GetElement(i)->GetProperty("name"));
if(nameProp.IsNotNull() && nameProp->GetValueAsString()=="PointBasedRegistrationNode")
{
m_FixedPointSetNode=children->GetElement(i);
m_FixedLandmarks = dynamic_cast<mitk::PointSet*> (m_FixedPointSetNode->GetData());
this->GetDataStorage()->Remove(m_FixedPointSetNode);
hasPointSetNode = true;
break;
}
}
if (!hasPointSetNode)
{
m_FixedLandmarks = mitk::PointSet::New();
m_FixedPointSetNode = mitk::DataNode::New();
m_FixedPointSetNode->SetData(m_FixedLandmarks);
m_FixedPointSetNode->SetProperty("name", mitk::StringProperty::New("PointBasedRegistrationNode"));
}
m_FixedPointSetNode->GetStringProperty("label", m_OldFixedLabel);
m_FixedPointSetNode->SetProperty("label", mitk::StringProperty::New("F "));
m_FixedPointSetNode->SetProperty("color", mitk::ColorProperty::New(0.0f, 1.0f, 1.0f));
m_FixedPointSetNode->SetVisibility(true);
m_Controls.m_FixedPointListWidget->SetPointSetNode(m_FixedPointSetNode);
this->GetDataStorage()->Add(m_FixedPointSetNode, m_FixedNode);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
if (m_FixedPointSetNode.IsNull())
{
m_FixedLandmarks = mitk::PointSet::New();
m_FixedPointSetNode = mitk::DataNode::New();
m_FixedPointSetNode->SetData(m_FixedLandmarks);
m_FixedPointSetNode->SetProperty("name", mitk::StringProperty::New("PointBasedRegistrationNode"));
m_FixedPointSetNode->GetStringProperty("label", m_OldFixedLabel);
m_FixedPointSetNode->SetProperty("label", mitk::StringProperty::New("F "));
m_FixedPointSetNode->SetProperty("color", mitk::ColorProperty::New(0.0f, 1.0f, 1.0f));
m_FixedPointSetNode->SetVisibility(true);
m_Controls.m_FixedPointListWidget->SetPointSetNode(m_FixedPointSetNode);
this->GetDataStorage()->Add(m_FixedPointSetNode, m_FixedNode);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
else
{
m_FixedNode = NULL;
if (m_FixedPointSetNode.IsNotNull())
m_FixedPointSetNode->SetProperty("label", mitk::StringProperty::New(m_OldFixedLabel));
m_FixedPointSetNode = NULL;
m_FixedLandmarks = NULL;
m_Controls.m_FixedPointListWidget->SetPointSetNode(m_FixedPointSetNode);
m_Controls.m_FixedLabel->hide();
m_Controls.TextLabelFixed->hide();
m_Controls.line2->hide();
m_Controls.m_FixedPointListWidget->hide();
m_Controls.m_SwitchImages->hide();
}
if(m_FixedLandmarks.IsNotNull())
m_CurrentFixedLandmarksObserverID = m_FixedLandmarks->AddObserver(itk::ModifiedEvent(), m_FixedLandmarksChangedCommand);
}
void QmitkPointBasedRegistrationView::MovingSelected(mitk::DataNode::Pointer movingImage)
{
if(m_MovingLandmarks.IsNotNull())
m_MovingLandmarks->RemoveObserver(m_CurrentMovingLandmarksObserverID);
if (movingImage.IsNotNull())
{
if (m_MovingNode != movingImage)
{
if (m_MovingNode.IsNotNull())
{
m_MovingNode->SetOpacity(m_OriginalOpacity);
if (m_FixedNode == m_MovingNode)
m_FixedNode->SetOpacity(0.5);
this->setImageColor(false);
if (m_MovingNode != m_FixedNode)
{
m_MovingPointSetNode->SetProperty("label", mitk::StringProperty::New(m_OldMovingLabel));
}
else
{
m_OldFixedLabel = m_OldMovingLabel;
}
}
if (m_MovingPointSetNode.IsNotNull())
m_MovingPointSetNode->SetProperty("label", mitk::StringProperty::New(m_OldMovingLabel));
m_MovingNode = movingImage;
m_MovingNode->SetVisibility(true);
m_Controls.m_MovingLabel->setText(QString::fromStdString(m_MovingNode->GetName()));
m_Controls.m_MovingLabel->show();
m_Controls.TextLabelMoving->show();
m_Controls.line1->show();
m_Controls.m_MovingPointListWidget->show();
m_Controls.m_OpacityLabel->show();
m_Controls.m_OpacitySlider->show();
m_Controls.label->show();
m_Controls.label_2->show();
mitk::ColorProperty::Pointer colorProperty;
colorProperty = dynamic_cast<mitk::ColorProperty*>(m_MovingNode->GetProperty("color"));
if ( colorProperty.IsNotNull() )
{
m_MovingColor = colorProperty->GetColor();
}
this->setImageColor(m_ShowRedGreen);
m_MovingNode->GetFloatProperty("opacity", m_OriginalOpacity);
this->OpacityUpdate(m_Opacity);
bool hasPointSetNode = false;
mitk::DataStorage::SetOfObjects::ConstPointer children = this->GetDataStorage()->GetDerivations(m_MovingNode);
unsigned long size;
size = children->Size();
for (unsigned long i = 0; i < size; ++i)
{
mitk::StringProperty::Pointer nameProp = dynamic_cast<mitk::StringProperty*>(children->GetElement(i)->GetProperty("name"));
if(nameProp.IsNotNull() && nameProp->GetValueAsString()=="PointBasedRegistrationNode")
{
m_MovingPointSetNode=children->GetElement(i);
m_MovingLandmarks = dynamic_cast<mitk::PointSet*> (m_MovingPointSetNode->GetData());
this->GetDataStorage()->Remove(m_MovingPointSetNode);
hasPointSetNode = true;
break;
}
}
if (!hasPointSetNode)
{
m_MovingLandmarks = mitk::PointSet::New();
m_MovingPointSetNode = mitk::DataNode::New();
m_MovingPointSetNode->SetData(m_MovingLandmarks);
m_MovingPointSetNode->SetProperty("name", mitk::StringProperty::New("PointBasedRegistrationNode"));
}
this->GetDataStorage()->Add(m_MovingPointSetNode, m_MovingNode);
m_MovingPointSetNode->GetStringProperty("label", m_OldMovingLabel);
m_MovingPointSetNode->SetProperty("label", mitk::StringProperty::New("M "));
m_MovingPointSetNode->SetProperty("color", mitk::ColorProperty::New(1.0f, 1.0f, 0.0f));
m_MovingPointSetNode->SetVisibility(true);
m_Controls.m_MovingPointListWidget->SetPointSetNode(m_MovingPointSetNode);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
this->clearTransformationLists();
this->OpacityUpdate(m_Opacity);
}
if (m_MovingPointSetNode.IsNull())
{
m_MovingLandmarks = mitk::PointSet::New();
m_MovingPointSetNode = mitk::DataNode::New();
m_MovingPointSetNode->SetData(m_MovingLandmarks);
m_MovingPointSetNode->SetProperty("name", mitk::StringProperty::New("PointBasedRegistrationNode"));
m_MovingPointSetNode->GetStringProperty("label", m_OldMovingLabel);
m_MovingPointSetNode->SetProperty("label", mitk::StringProperty::New("M "));
m_MovingPointSetNode->SetProperty("color", mitk::ColorProperty::New(1.0f, 1.0f, 0.0f));
m_MovingPointSetNode->SetVisibility(true);
m_Controls.m_MovingPointListWidget->SetPointSetNode(m_MovingPointSetNode);
this->GetDataStorage()->Add(m_MovingPointSetNode, m_MovingNode);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
else
{
m_MovingNode = NULL;
if (m_MovingPointSetNode.IsNotNull())
m_MovingPointSetNode->SetProperty("label", mitk::StringProperty::New(m_OldMovingLabel));
m_MovingPointSetNode = NULL;
m_MovingLandmarks = NULL;
m_Controls.m_MovingPointListWidget->SetPointSetNode(m_MovingPointSetNode);
m_Controls.m_MovingLabel->hide();
m_Controls.TextLabelMoving->hide();
m_Controls.line1->hide();
m_Controls.m_MovingPointListWidget->hide();
m_Controls.m_OpacityLabel->hide();
m_Controls.m_OpacitySlider->hide();
m_Controls.label->hide();
m_Controls.label_2->hide();
}
if(m_MovingLandmarks.IsNotNull())
m_CurrentMovingLandmarksObserverID = m_MovingLandmarks->AddObserver(itk::ModifiedEvent(), m_MovingLandmarksChangedCommand);
}
void QmitkPointBasedRegistrationView::updateMovingLandmarksList()
{
// mitk::PointSet* ps = mitk::PointSet::New();
// ps = dynamic_cast<mitk::PointSet*>(m_MovingPointSetNode->GetData());
// mitk::DataNode::Pointer tmpPtr = m_MovingPointSetNode;
// m_MovingLandmarks = 0;
// m_MovingLandmarks = (ps);
m_MovingLandmarks = dynamic_cast<mitk::PointSet*>(m_MovingPointSetNode->GetData());
// m_Controls.m_MovingPointListWidget->SetPointSetNode(m_MovingPointSetNode); //Workaround: m_MovingPointListWidget->m_PointListView->m_PointListModel loses the pointer on the pointsetnode
this->checkLandmarkError();
this->CheckCalculate();
}
void QmitkPointBasedRegistrationView::updateFixedLandmarksList()
{
m_FixedLandmarks = dynamic_cast<mitk::PointSet*>(m_FixedPointSetNode->GetData());
this->checkLandmarkError();
this->CheckCalculate();
}
void QmitkPointBasedRegistrationView::HideFixedImage(bool hide)
{
m_HideFixedImage = hide;
if(m_FixedNode.IsNotNull())
{
m_FixedNode->SetVisibility(!hide);
}
if (hide)
{
//this->reinitMovingClicked();
}
if (!m_HideMovingImage && !m_HideFixedImage)
{
//this->globalReinitClicked();
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkPointBasedRegistrationView::HideMovingImage(bool hide)
{
m_HideMovingImage = hide;
if(m_MovingNode.IsNotNull())
{
m_MovingNode->SetVisibility(!hide);
}
if (hide)
{
//this->reinitFixedClicked();
}
if (!m_HideMovingImage && !m_HideFixedImage)
{
//this->globalReinitClicked();
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
bool QmitkPointBasedRegistrationView::CheckCalculate()
{
if((m_MovingPointSetNode.IsNull())||(m_FixedPointSetNode.IsNull()||m_FixedLandmarks.IsNull()||m_MovingLandmarks.IsNull()))
return false;
if(m_MovingNode==m_FixedNode)
return false;
return this->checkCalculateEnabled();
}
void QmitkPointBasedRegistrationView::UndoTransformation()
{
if(!m_UndoPointsGeometryList.empty())
{
- mitk::Geometry3D::Pointer movingLandmarksGeometry = m_MovingLandmarks->GetGeometry(0)->Clone();
+ itk::LightObject::Pointer lopointer = m_MovingLandmarks->GetGeometry(0)->Clone();
+ mitk::BaseGeometry::Pointer movingLandmarksGeometry = dynamic_cast<mitk::BaseGeometry*>(lopointer.GetPointer());
m_RedoPointsGeometryList.push_back(movingLandmarksGeometry.GetPointer());
m_MovingLandmarks->SetGeometry(m_UndoPointsGeometryList.back());
m_UndoPointsGeometryList.pop_back();
//\FIXME when geometry is substituted the matrix referenced by the actor created by the mapper
//is still pointing to the old one. Workaround: delete mapper
m_MovingPointSetNode->SetMapper(1, NULL);
mitk::BaseData::Pointer movingData = m_MovingNode->GetData();
- mitk::Geometry3D::Pointer movingGeometry = movingData->GetGeometry(0)->Clone();
+ itk::LightObject::Pointer lopointer2 = movingData->GetGeometry(0)->Clone();
+ mitk::BaseGeometry::Pointer movingGeometry = dynamic_cast<mitk::BaseGeometry*>(lopointer2.GetPointer());
m_RedoGeometryList.push_back(movingGeometry.GetPointer());
movingData->SetGeometry(m_UndoGeometryList.back());
m_UndoGeometryList.pop_back();
//\FIXME when geometry is substituted the matrix referenced by the actor created by the mapper
//is still pointing to the old one. Workaround: delete mapper
m_MovingNode->SetMapper(1, NULL);
mitk::RenderingManager::GetInstance()->RequestUpdate(m_MultiWidget->mitkWidget4->GetRenderWindow());
movingData->GetTimeGeometry()->Update();
m_MovingLandmarks->GetTimeGeometry()->Update();
m_Controls.m_RedoTransformation->setEnabled(true);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
this->checkLandmarkError();
}
if(!m_UndoPointsGeometryList.empty())
{
m_Controls.m_UndoTransformation->setEnabled(true);
}
else
{
m_Controls.m_UndoTransformation->setEnabled(false);
}
}
void QmitkPointBasedRegistrationView::RedoTransformation()
{
if(!m_RedoPointsGeometryList.empty())
{
- mitk::Geometry3D::Pointer movingLandmarksGeometry = m_MovingLandmarks->GetGeometry(0)->Clone();
+ itk::LightObject::Pointer lopointer = m_MovingLandmarks->GetGeometry(0)->Clone();
+ mitk::BaseGeometry::Pointer movingLandmarksGeometry = dynamic_cast<mitk::BaseGeometry*>(lopointer.GetPointer());
m_UndoPointsGeometryList.push_back(movingLandmarksGeometry.GetPointer());
m_MovingLandmarks->SetGeometry(m_RedoPointsGeometryList.back());
m_RedoPointsGeometryList.pop_back();
//\FIXME when geometry is substituted the matrix referenced by the actor created by the mapper
//is still pointing to the old one. Workaround: delete mapper
m_MovingPointSetNode->SetMapper(1, NULL);
mitk::BaseData::Pointer movingData = m_MovingNode->GetData();
- mitk::Geometry3D::Pointer movingGeometry = movingData->GetGeometry(0)->Clone();
+ itk::LightObject::Pointer lopointer2 = movingData->GetGeometry(0)->Clone();
+ mitk::BaseGeometry::Pointer movingGeometry = dynamic_cast<mitk::BaseGeometry*>(lopointer2.GetPointer());
m_UndoGeometryList.push_back(movingGeometry.GetPointer());
movingData->SetGeometry(m_RedoGeometryList.back());
m_RedoGeometryList.pop_back();
//\FIXME when geometry is substituted the matrix referenced by the actor created by the mapper
//is still pointing to the old one. Workaround: delete mapper
m_MovingNode->SetMapper(1, NULL);
mitk::RenderingManager::GetInstance()->RequestUpdate(m_MultiWidget->mitkWidget4->GetRenderWindow());
movingData->GetTimeGeometry()->Update();
m_MovingLandmarks->GetTimeGeometry()->Update();
m_Controls.m_UndoTransformation->setEnabled(true);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
this->checkLandmarkError();
}
if(!m_RedoPointsGeometryList.empty())
{
m_Controls.m_RedoTransformation->setEnabled(true);
}
else
{
m_Controls.m_RedoTransformation->setEnabled(false);
}
}
void QmitkPointBasedRegistrationView::showRedGreen(bool redGreen)
{
m_ShowRedGreen = redGreen;
this->setImageColor(m_ShowRedGreen);
}
void QmitkPointBasedRegistrationView::setImageColor(bool redGreen)
{
if (!redGreen && m_FixedNode.IsNotNull())
{
m_FixedNode->SetColor(m_FixedColor);
}
if (!redGreen && m_MovingNode.IsNotNull())
{
m_MovingNode->SetColor(m_MovingColor);
}
if (redGreen && m_FixedNode.IsNotNull())
{
m_FixedNode->SetColor(1.0f, 0.0f, 0.0f);
}
if (redGreen && m_MovingNode.IsNotNull())
{
m_MovingNode->SetColor(0.0f, 1.0f, 0.0f);
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkPointBasedRegistrationView::OpacityUpdate(float opacity)
{
if (opacity > 1)
{
opacity = opacity/100.0f;
}
m_Opacity = opacity;
if (m_MovingNode.IsNotNull())
{
m_MovingNode->SetOpacity(m_Opacity);
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkPointBasedRegistrationView::OpacityUpdate(int opacity)
{
float fValue = ((float)opacity)/100.0f;
this->OpacityUpdate(fValue);
}
void QmitkPointBasedRegistrationView::clearTransformationLists()
{
m_Controls.m_UndoTransformation->setEnabled(false);
m_Controls.m_RedoTransformation->setEnabled(false);
m_Controls.m_MeanErrorLCD->hide();
m_Controls.m_MeanError->hide();
m_UndoGeometryList.clear();
m_UndoPointsGeometryList.clear();
m_RedoGeometryList.clear();
m_RedoPointsGeometryList.clear();
}
void QmitkPointBasedRegistrationView::checkLandmarkError()
{
double totalDist = 0, dist = 0, dist2 = 0;
mitk::Point3D point1, point2, point3;
double p1[3], p2[3];
if(m_Transformation < 3)
{
if (m_Controls.m_UseICP->isChecked())
{
if (m_MovingLandmarks.IsNotNull() && m_FixedLandmarks.IsNotNull()&& m_MovingLandmarks->GetSize() != 0 && m_FixedLandmarks->GetSize() != 0)
{
for(int pointId = 0; pointId < m_MovingLandmarks->GetSize(); ++pointId)
{
point1 = m_MovingLandmarks->GetPoint(pointId);
point2 = m_FixedLandmarks->GetPoint(0);
p1[0] = point1[0]; p1[1] = point1[1]; p1[2] = point1[2];
p2[0] = point2[0]; p2[1] = point2[1]; p2[2] = point2[2];
dist = vtkMath::Distance2BetweenPoints(p1, p2);
for(int pointId2 = 1; pointId2 < m_FixedLandmarks->GetSize(); ++pointId2)
{
point2 = m_FixedLandmarks->GetPoint(pointId2);
p1[0] = point1[0]; p1[1] = point1[1]; p1[2] = p1[2];
p2[0] = point2[0]; p2[1] = point2[1]; p2[2] = p2[2];
dist2 = vtkMath::Distance2BetweenPoints(p1, p2);
if (dist2 < dist)
{
dist = dist2;
}
}
totalDist += dist;
}
m_Controls.m_MeanErrorLCD->display(sqrt(totalDist/m_FixedLandmarks->GetSize()));
m_Controls.m_MeanErrorLCD->show();
m_Controls.m_MeanError->show();
}
else
{
m_Controls.m_MeanErrorLCD->hide();
m_Controls.m_MeanError->hide();
}
}
else
{
if (m_MovingLandmarks.IsNotNull() && m_FixedLandmarks.IsNotNull() && m_MovingLandmarks->GetSize() != 0 && m_FixedLandmarks->GetSize() != 0 && m_MovingLandmarks->GetSize() == m_FixedLandmarks->GetSize())
{
for(int pointId = 0; pointId < m_MovingLandmarks->GetSize(); ++pointId)
{
point1 = m_MovingLandmarks->GetPoint(pointId);
point2 = m_FixedLandmarks->GetPoint(pointId);
p1[0] = point1[0]; p1[1] = point1[1]; p1[2] = point1[2];
p2[0] = point2[0]; p2[1] = point2[1]; p2[2] = point2[2];
totalDist += vtkMath::Distance2BetweenPoints(p1, p2);
}
m_Controls.m_MeanErrorLCD->display(sqrt(totalDist/m_FixedLandmarks->GetSize()));
m_Controls.m_MeanErrorLCD->show();
m_Controls.m_MeanError->show();
}
else
{
m_Controls.m_MeanErrorLCD->hide();
m_Controls.m_MeanError->hide();
}
}
}
else
{
if (m_MovingLandmarks.IsNotNull() && m_FixedLandmarks.IsNotNull() && m_MovingLandmarks->GetSize() != 0 && m_FixedLandmarks->GetSize() != 0 && m_MovingLandmarks->GetSize() == m_FixedLandmarks->GetSize())
{
for(int pointId = 0; pointId < m_MovingLandmarks->GetSize(); ++pointId)
{
point1 = m_MovingLandmarks->GetPoint(pointId);
point2 = m_FixedLandmarks->GetPoint(pointId);
p1[0] = point1[0]; p1[1] = point1[1]; p1[2] = point1[2];
p2[0] = point2[0]; p2[1] = point2[1]; p2[2] = point2[2];
totalDist += vtkMath::Distance2BetweenPoints(p1, p2);
}
m_Controls.m_MeanErrorLCD->display(sqrt(totalDist/m_FixedLandmarks->GetSize()));
m_Controls.m_MeanErrorLCD->show();
m_Controls.m_MeanError->show();
}
else
{
m_Controls.m_MeanErrorLCD->hide();
m_Controls.m_MeanError->hide();
}
}
}
void QmitkPointBasedRegistrationView::transformationChanged(int transform)
{
m_Transformation = transform;
this->checkCalculateEnabled();
this->checkLandmarkError();
}
// ICP with vtkLandmarkTransformation
void QmitkPointBasedRegistrationView::calculateLandmarkbasedWithICP()
{
if(CheckCalculate())
{
- mitk::Geometry3D::Pointer pointsGeometry = m_MovingLandmarks->GetGeometry(0);
- mitk::Geometry3D::Pointer movingLandmarksGeometry = m_MovingLandmarks->GetGeometry(0)->Clone();
+ mitk::BaseGeometry::Pointer pointsGeometry = m_MovingLandmarks->GetGeometry(0);
+ itk::LightObject::Pointer lopointer = m_MovingLandmarks->GetGeometry(0)->Clone();
+ mitk::BaseGeometry::Pointer movingLandmarksGeometry = dynamic_cast<mitk::BaseGeometry*>(lopointer.GetPointer());
m_UndoPointsGeometryList.push_back(movingLandmarksGeometry.GetPointer());
mitk::BaseData::Pointer originalData = m_MovingNode->GetData();
- mitk::Geometry3D::Pointer originalDataGeometry = originalData->GetGeometry(0)->Clone();
+ itk::LightObject::Pointer lopointer2 = originalData->GetGeometry(0)->Clone();
+ mitk::BaseGeometry::Pointer originalDataGeometry = dynamic_cast<mitk::BaseGeometry*>(lopointer2.GetPointer());
m_UndoGeometryList.push_back(originalDataGeometry.GetPointer());
vtkIdType pointId;
vtkPoints* vPointsSource=vtkPoints::New();
vtkCellArray* vCellsSource=vtkCellArray::New();
for(pointId=0; pointId<m_MovingLandmarks->GetSize();++pointId)
{
mitk::Point3D pointSource=m_MovingLandmarks->GetPoint(pointId);
vPointsSource->InsertNextPoint(pointSource[0],pointSource[1],pointSource[2]);
vCellsSource->InsertNextCell(1, &pointId);
}
vtkPoints* vPointsTarget=vtkPoints::New();
vtkCellArray* vCellsTarget = vtkCellArray::New();
for(pointId=0; pointId<m_FixedLandmarks->GetSize();++pointId)
{
mitk::Point3D pointTarget=m_FixedLandmarks->GetPoint(pointId);
vPointsTarget->InsertNextPoint(pointTarget[0],pointTarget[1],pointTarget[2]);
vCellsTarget->InsertNextCell(1, &pointId);
}
vtkPolyData* vPointSetSource=vtkPolyData::New();
vtkPolyData* vPointSetTarget=vtkPolyData::New();
vPointSetTarget->SetPoints(vPointsTarget);
vPointSetTarget->SetVerts(vCellsTarget);
vPointSetSource->SetPoints(vPointsSource);
vPointSetSource->SetVerts(vCellsSource);
vtkIterativeClosestPointTransform * icp=vtkIterativeClosestPointTransform::New();
icp->SetCheckMeanDistance(1);
icp->SetSource(vPointSetSource);
icp->SetTarget(vPointSetTarget);
icp->SetMaximumNumberOfIterations(50);
icp->StartByMatchingCentroidsOn();
vtkLandmarkTransform * transform=icp->GetLandmarkTransform();
if(m_Transformation==0)
{
transform->SetModeToRigidBody();
}
if(m_Transformation==1)
{
transform->SetModeToSimilarity();
}
if(m_Transformation==2)
{
transform->SetModeToAffine();
}
vtkMatrix4x4 * matrix=icp->GetMatrix();
double determinant = fabs(matrix->Determinant());
if((determinant < mitk::eps) || (determinant > 100) || (determinant < 0.01)
|| (determinant==itk::NumericTraits<double>::infinity())
|| (determinant==itk::NumericTraits<double>::quiet_NaN())
|| (determinant==itk::NumericTraits<double>::signaling_NaN())
|| (determinant==-itk::NumericTraits<double>::infinity())
|| (determinant==-itk::NumericTraits<double>::quiet_NaN())
|| (determinant==-itk::NumericTraits<double>::signaling_NaN())
|| (!(determinant <= 0) && !(determinant > 0)))
{
QMessageBox msgBox;
msgBox.setText("Suspicious determinant of matrix calculated by ICP.\n"
"Please select more points or other points!" );
msgBox.exec();
return;
}
pointsGeometry->Compose(matrix);
m_MovingLandmarks->GetTimeGeometry()->Update();
mitk::BaseData::Pointer movingData = m_MovingNode->GetData();
- mitk::Geometry3D::Pointer movingGeometry = movingData->GetGeometry(0);
+ mitk::BaseGeometry::Pointer movingGeometry = movingData->GetGeometry(0);
movingGeometry->Compose(matrix);
movingData->GetTimeGeometry()->Update();
m_Controls.m_UndoTransformation->setEnabled(true);
m_Controls.m_RedoTransformation->setEnabled(false);
m_RedoGeometryList.clear();
m_RedoPointsGeometryList.clear();
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
this->checkLandmarkError();
}
}
// only vtkLandmarkTransformation
void QmitkPointBasedRegistrationView::calculateLandmarkbased()
{
if(CheckCalculate())
{
- mitk::Geometry3D::Pointer pointsGeometry = m_MovingLandmarks->GetGeometry(0);
- mitk::Geometry3D::Pointer movingLandmarksGeometry = m_MovingLandmarks->GetGeometry(0)->Clone();
+ mitk::BaseGeometry::Pointer pointsGeometry = m_MovingLandmarks->GetGeometry(0);
+ itk::LightObject::Pointer lopointer = m_MovingLandmarks->GetGeometry(0)->Clone();
+ mitk::BaseGeometry::Pointer movingLandmarksGeometry = dynamic_cast<mitk::BaseGeometry*>(lopointer.GetPointer());
m_UndoPointsGeometryList.push_back(movingLandmarksGeometry.GetPointer());
mitk::BaseData::Pointer originalData = m_MovingNode->GetData();
- mitk::Geometry3D::Pointer originalDataGeometry = originalData->GetGeometry(0)->Clone();
+ itk::LightObject::Pointer lopointer2 = originalData->GetGeometry(0)->Clone();
+ mitk::BaseGeometry::Pointer originalDataGeometry = dynamic_cast<mitk::BaseGeometry*>(lopointer2.GetPointer());
m_UndoGeometryList.push_back(originalDataGeometry.GetPointer());
vtkIdType pointId;
vtkPoints* vPointsSource=vtkPoints::New();
for(pointId = 0; pointId < m_MovingLandmarks->GetSize(); ++pointId)
{
mitk::Point3D sourcePoint = m_MovingLandmarks->GetPoint(pointId);
vPointsSource->InsertNextPoint(sourcePoint[0],sourcePoint[1],sourcePoint[2]);
}
vtkPoints* vPointsTarget=vtkPoints::New();
for(pointId=0; pointId<m_FixedLandmarks->GetSize();++pointId)
{
mitk::Point3D targetPoint=m_FixedLandmarks->GetPoint(pointId);
vPointsTarget->InsertNextPoint(targetPoint[0],targetPoint[1],targetPoint[2]);
}
vtkLandmarkTransform * transform= vtkLandmarkTransform::New();
transform->SetSourceLandmarks(vPointsSource);
transform->SetTargetLandmarks(vPointsTarget);
if(m_Transformation==0)
{
transform->SetModeToRigidBody();
}
if(m_Transformation==1)
{
transform->SetModeToSimilarity();
}
if(m_Transformation==2)
{
transform->SetModeToAffine();
}
vtkMatrix4x4 * matrix=transform->GetMatrix();
double determinant = fabs(matrix->Determinant());
if((determinant < mitk::eps) || (determinant > 100) || (determinant < 0.01)
|| (determinant==itk::NumericTraits<double>::infinity())
|| (determinant==itk::NumericTraits<double>::quiet_NaN())
|| (determinant==itk::NumericTraits<double>::signaling_NaN())
|| (determinant==-itk::NumericTraits<double>::infinity())
|| (determinant==-itk::NumericTraits<double>::quiet_NaN())
|| (determinant==-itk::NumericTraits<double>::signaling_NaN())
|| (!(determinant <= 0) && !(determinant > 0)))
{
QMessageBox msgBox;
msgBox.setText("Suspicious determinant of matrix calculated.\n"
"Please select more points or other points!" );
msgBox.exec();
return;
}
pointsGeometry->Compose(matrix);
m_MovingLandmarks->GetTimeGeometry()->Update();
mitk::BaseData::Pointer movingData = m_MovingNode->GetData();
- mitk::Geometry3D::Pointer movingGeometry = movingData->GetGeometry(0);
+ mitk::BaseGeometry::Pointer movingGeometry = movingData->GetGeometry(0);
movingGeometry->Compose(matrix);
movingData->GetTimeGeometry()->Update();
m_Controls.m_UndoTransformation->setEnabled(true);
m_Controls.m_RedoTransformation->setEnabled(false);
m_RedoGeometryList.clear();
m_RedoPointsGeometryList.clear();
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
this->checkLandmarkError();
}
}
void QmitkPointBasedRegistrationView::calculateLandmarkWarping()
{
mitk::LandmarkWarping* registration = new mitk::LandmarkWarping();
mitk::LandmarkWarping::FixedImageType::Pointer fixedImage = mitk::LandmarkWarping::FixedImageType::New();
mitk::Image::Pointer fimage = dynamic_cast<mitk::Image*>(m_FixedNode->GetData());
mitk::LandmarkWarping::MovingImageType::Pointer movingImage = mitk::LandmarkWarping::MovingImageType::New();
mitk::Image::Pointer mimage = dynamic_cast<mitk::Image*>(m_MovingNode->GetData());
if (fimage.IsNotNull() && /*fimage->GetDimension() == 2 || */ fimage->GetDimension() == 3 && mimage.IsNotNull() && mimage->GetDimension() == 3)
{
mitk::CastToItkImage(fimage, fixedImage);
mitk::CastToItkImage(mimage, movingImage);
registration->SetFixedImage(fixedImage);
registration->SetMovingImage(movingImage);
unsigned int pointId;
mitk::Point3D sourcePoint, targetPoint;
mitk::LandmarkWarping::LandmarkContainerType::Pointer fixedLandmarks = mitk::LandmarkWarping::LandmarkContainerType::New();
mitk::LandmarkWarping::LandmarkPointType point;
for(pointId = 0; pointId < (unsigned int)m_FixedLandmarks->GetSize(); ++pointId)
{
fimage->GetGeometry(0)->WorldToItkPhysicalPoint(m_FixedLandmarks->GetPoint(pointId), point);
fixedLandmarks->InsertElement( pointId, point);
}
mitk::LandmarkWarping::LandmarkContainerType::Pointer movingLandmarks = mitk::LandmarkWarping::LandmarkContainerType::New();
for(pointId = 0; pointId < (unsigned int)m_MovingLandmarks->GetSize(); ++pointId)
{
mitk::BaseData::Pointer fixedData = m_FixedNode->GetData();
- mitk::Geometry3D::Pointer fixedGeometry = fixedData->GetGeometry(0);
+ mitk::BaseGeometry::Pointer fixedGeometry = fixedData->GetGeometry(0);
fixedGeometry->WorldToItkPhysicalPoint(m_MovingLandmarks->GetPoint(pointId), point);
movingLandmarks->InsertElement( pointId, point);
}
registration->SetLandmarks(fixedLandmarks.GetPointer(), movingLandmarks.GetPointer());
mitk::LandmarkWarping::MovingImageType::Pointer output = registration->Register();
if (output.IsNotNull())
{
mitk::Image::Pointer image = mitk::Image::New();
mitk::CastToMitkImage(output, image);
m_MovingNode->SetData(image);
mitk::LevelWindowProperty::Pointer levWinProp = mitk::LevelWindowProperty::New();
mitk::LevelWindow levelWindow;
levelWindow.SetAuto( image );
levWinProp->SetLevelWindow(levelWindow);
m_MovingNode->GetPropertyList()->SetProperty("levelwindow",levWinProp);
movingLandmarks = registration->GetTransformedTargetLandmarks();
mitk::PointSet::PointDataIterator it;
it = m_MovingLandmarks->GetPointSet()->GetPointData()->Begin();
//increase the eventId to encapsulate the coming operations
mitk::OperationEvent::IncCurrObjectEventId();
mitk::OperationEvent::ExecuteIncrement();
for(pointId=0; pointId<movingLandmarks->Size();++pointId, ++it)
{
int position = it->Index();
mitk::PointSet::PointType pt = m_MovingLandmarks->GetPoint(position);
mitk::Point3D undoPoint = ( pt );
point = movingLandmarks->GetElement(pointId);
fimage->GetGeometry(0)->ItkPhysicalPointToWorld(point, pt);
mitk::PointOperation* doOp = new mitk::PointOperation(mitk::OpMOVE, pt, position);
//undo operation
mitk::PointOperation* undoOp = new mitk::PointOperation(mitk::OpMOVE, undoPoint, position);
mitk::OperationEvent* operationEvent = new mitk::OperationEvent(m_MovingLandmarks, doOp, undoOp, "Move point");
mitk::UndoController::GetCurrentUndoModel()->SetOperationEvent(operationEvent);
//execute the Operation
m_MovingLandmarks->ExecuteOperation(doOp);
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
this->clearTransformationLists();
this->checkLandmarkError();
}
}
}
bool QmitkPointBasedRegistrationView::checkCalculateEnabled()
{
if (m_FixedLandmarks.IsNotNull() && m_MovingLandmarks.IsNotNull())
{
int fixedPoints = m_FixedLandmarks->GetSize();
int movingPoints = m_MovingLandmarks->GetSize();
if (m_Transformation == 0 || m_Transformation == 1 || m_Transformation == 2)
{
if (m_Controls.m_UseICP->isChecked())
{
if((movingPoints > 0 && fixedPoints > 0))
{
m_Controls.m_Calculate->setEnabled(true);
return true;
}
else
{
m_Controls.m_Calculate->setEnabled(false);
return false;
}
}
else
{
if ((movingPoints == fixedPoints) && movingPoints > 0)
{
m_Controls.m_Calculate->setEnabled(true);
return true;
}
else
{
m_Controls.m_Calculate->setEnabled(false);
return false;
}
}
}
else
{
m_Controls.m_Calculate->setEnabled(true);
return true;
}
}
else
{
return false;
}
}
void QmitkPointBasedRegistrationView::calculate()
{
if (m_Transformation == 0 || m_Transformation == 1 || m_Transformation == 2)
{
if (m_Controls.m_UseICP->isChecked())
{
if (m_MovingLandmarks->GetSize() == 1 && m_FixedLandmarks->GetSize() == 1)
{
this->calculateLandmarkbased();
}
else
{
this->calculateLandmarkbasedWithICP();
}
}
else
{
this->calculateLandmarkbased();
}
}
else
{
this->calculateLandmarkWarping();
}
}
void QmitkPointBasedRegistrationView::SetImagesVisible(berry::ISelection::ConstPointer /*selection*/)
{
if (this->m_CurrentSelection->Size() == 0)
{
// show all images
mitk::DataStorage::SetOfObjects::ConstPointer setOfObjects = this->GetDataStorage()->GetAll();
for (mitk::DataStorage::SetOfObjects::ConstIterator nodeIt = setOfObjects->Begin()
; nodeIt != setOfObjects->End(); ++nodeIt) // for each node
{
- if ( (nodeIt->Value().IsNotNull()) && (nodeIt->Value()->GetProperty("visible")) && dynamic_cast<mitk::Geometry2DData*>(nodeIt->Value()->GetData())==NULL)
+ if ( (nodeIt->Value().IsNotNull()) && (nodeIt->Value()->GetProperty("visible")) && dynamic_cast<mitk::PlaneGeometryData*>(nodeIt->Value()->GetData())==NULL)
{
nodeIt->Value()->SetVisibility(true);
}
}
}
else
{
// hide all images
mitk::DataStorage::SetOfObjects::ConstPointer setOfObjects = this->GetDataStorage()->GetAll();
for (mitk::DataStorage::SetOfObjects::ConstIterator nodeIt = setOfObjects->Begin()
; nodeIt != setOfObjects->End(); ++nodeIt) // for each node
{
- if ( (nodeIt->Value().IsNotNull()) && (nodeIt->Value()->GetProperty("visible")) && dynamic_cast<mitk::Geometry2DData*>(nodeIt->Value()->GetData())==NULL)
+ if ( (nodeIt->Value().IsNotNull()) && (nodeIt->Value()->GetProperty("visible")) && dynamic_cast<mitk::PlaneGeometryData*>(nodeIt->Value()->GetData())==NULL)
{
nodeIt->Value()->SetVisibility(false);
}
}
}
}
void QmitkPointBasedRegistrationView::SwitchImages()
{
mitk::DataNode::Pointer newMoving = m_FixedNode;
mitk::DataNode::Pointer newFixed = m_MovingNode;
this->FixedSelected(newFixed);
this->MovingSelected(newMoving);
}
diff --git a/Plugins/org.mitk.gui.qt.registration/src/internal/QmitkPointBasedRegistrationView.h b/Plugins/org.mitk.gui.qt.registration/src/internal/QmitkPointBasedRegistrationView.h
index eb166f9efd..cf6161ee2c 100644
--- a/Plugins/org.mitk.gui.qt.registration/src/internal/QmitkPointBasedRegistrationView.h
+++ b/Plugins/org.mitk.gui.qt.registration/src/internal/QmitkPointBasedRegistrationView.h
@@ -1,297 +1,297 @@
/*===================================================================
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.
===================================================================*/
#if !defined(QMITK_POINTBASEDREGISTRATION_H__INCLUDED)
#define QMITK_POINTBASEDREGISTRATION_H__INCLUDED
#include "QmitkFunctionality.h"
#include "berryISelectionListener.h"
#include "berryIStructuredSelection.h"
//#include "mitkTestingConfig.h" // IMPORTANT: this defines or undefines BUILD_TESTING !
#include <mitkPointSetInteractor.h>
#include <mitkGlobalInteraction.h>
#include <mitkAffineInteractor.h>
#include <mitkPointSet.h>
#include <vtkCellArray.h>
#include <vtkLandmarkTransform.h>
//#include "QmitkMessageBoxHelper.h"
#include "ui_QmitkPointBasedRegistrationViewControls.h"
#include <org_mitk_gui_qt_registration_Export.h>
/*!
\brief The PointBasedRegistration functionality is used to perform point based registration.
This functionality allows you to register 2D as well as 3D images in a rigid and deformable manner via corresponding
PointSets. Register means to align two images, so that they become as similar as possible.
Therefore you have to set corresponding points in both images, which will be matched. The movement, which has to be
performed on the points to align them will be performed on the moving image as well. The result is shown in the multi-widget.
For more informations see: \ref QmitkPointBasedRegistrationUserManual
\sa QmitkFunctionality
\ingroup Functionalities
\ingroup PointBasedRegistration
*/
class REGISTRATION_EXPORT QmitkPointBasedRegistrationView : public QmitkFunctionality
{
friend struct SelListenerPointBasedRegistration;
Q_OBJECT
public:
static const std::string VIEW_ID;
/*!
\brief Default constructor
*/
QmitkPointBasedRegistrationView(QObject *parent=0, const char *name=0);
/*!
\brief Default destructor
*/
virtual ~QmitkPointBasedRegistrationView();
/*!
\brief method for creating the applications main widget
*/
virtual void CreateQtPartControl(QWidget *parent);
/*!
\brief Sets the StdMultiWidget and connects it to the functionality.
*/
virtual void StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget);
/*!
\brief Removes the StdMultiWidget and disconnects it from the functionality.
*/
virtual void StdMultiWidgetNotAvailable();
/*!
\brief Method for creating the connections of main and control widget
*/
virtual void CreateConnections();
virtual void Activated();
virtual void Deactivated();
virtual void Visible();
virtual void Hidden();
//
// #ifdef BUILD_TESTING
// / **
// \brief Testing entry point
// * /
// virtual int TestYourself();
//
// / **
// \brief Helper method for testing
// * /
// bool TestAllTools();
//
//
// protected slots:
// /**
// \brief Helper method for testing
// */
// void RegistrationErrorDialogFound( QWidget* widget );
//
// /**
// \brief Helper method for testing
// */
// void ClearPointSetDialogFound( QWidget* widget );
//
// private:
// bool m_MessageBox;
//
//
// public:
// #else
// // slot function is needed, because moc ignores our #ifdefs
// void RegistrationErrorDialogFound( QWidget* widget ) {}
// // slot function is needed, because moc ignores our #ifdefs
// void ClearPointSetDialogFound(QWidget* widget){}
// #endif
void DataNodeHasBeenRemoved(const mitk::DataNode* node);
protected slots:
/*!
\brief Sets the fixed Image according to TreeNodeSelector widget
*/
void FixedSelected(mitk::DataNode::Pointer fixedImage);
/*!
\brief Sets the moving Image according to TreeNodeSelector widget
*/
void MovingSelected(mitk::DataNode::Pointer movingImage);
/*!
\brief Calculates registration with vtkLandmarkTransform
*/
void calculateLandmarkbased();
/*!
\brief Calculates registration with itkLandmarkWarping
*/
void calculateLandmarkWarping();
/*!
\brief Calculates registration with ICP and vtkLandmarkTransform
*/
void calculateLandmarkbasedWithICP();
/*!
\brief lets the fixed image become invisible and the moving image visible
*/
void HideMovingImage(bool hide);
/*!
\brief lets the moving image become invisible and the fixed image visible
*/
void HideFixedImage(bool hide);
/*!
\brief Checks if registration is possible
*/
bool CheckCalculate();
/*!
\brief Performs an undo for the last transform.
*/
void UndoTransformation();
/*!
\brief Performs a redo for the last undo transform.
*/
void RedoTransformation();
/*!
\brief Stores whether the image will be shown in grayvalues or in red for fixed image and green for moving image
@param show if true, then images will be shown in red and green
*/
void showRedGreen(bool show);
/*!
\brief Sets the selected opacity for moving image
@param opacity the selected opacity
*/
void OpacityUpdate(float opacity);
/*!
\brief Sets the selected opacity for moving image
@param opacity the selected opacity
*/
void OpacityUpdate(int opacity);
/*!
\brief Updates the moving landmarks
*/
void updateMovingLandmarksList();
/*!
\brief Updates the fixed landmarks
*/
void updateFixedLandmarksList();
/*!
\brief Sets the images to gray values or fixed image to red and moving image to green
@param redGreen if true, then images will be shown in red and green
*/
void setImageColor(bool redGreen);
/*!
\brief Clears the undo and redo transformation lists.
*/
void clearTransformationLists();
/*!
\brief Calculates the landmark error for the selected transformation.
*/
void checkLandmarkError();
/*!
\brief Changes the transformation type and calls checkLandmarkError().
*/
void transformationChanged(int transform);
/*!
\brief Checks whether the registration can be performed.
*/
bool checkCalculateEnabled();
/*!
\brief Performs the registration.
*/
void calculate();
void SetImagesVisible(berry::ISelection::ConstPointer /*selection*/);
void SwitchImages();
protected:
berry::ISelectionListener::Pointer m_SelListener;
berry::IStructuredSelection::ConstPointer m_CurrentSelection;
/*!
* default main widget containing 4 windows showing 3
* orthogonal slices of the volume and a 3d render window
*/
QmitkStdMultiWidget * m_MultiWidget;
/*!
* control widget to make all changes for point based registration
*/
Ui::QmitkPointBasedRegistrationControls m_Controls;
mitk::PointSet::Pointer m_FixedLandmarks;
mitk::PointSet::Pointer m_MovingLandmarks;
mitk::DataNode::Pointer m_MovingPointSetNode;
mitk::DataNode::Pointer m_FixedPointSetNode;
mitk::DataNode::Pointer m_MovingNode;
mitk::DataNode::Pointer m_FixedNode;
- std::list<mitk::Geometry3D::Pointer> m_UndoGeometryList;
- std::list<mitk::Geometry3D::Pointer> m_UndoPointsGeometryList;
- std::list<mitk::Geometry3D::Pointer> m_RedoGeometryList;
- std::list<mitk::Geometry3D::Pointer> m_RedoPointsGeometryList;
+ std::list<mitk::BaseGeometry::Pointer> m_UndoGeometryList;
+ std::list<mitk::BaseGeometry::Pointer> m_UndoPointsGeometryList;
+ std::list<mitk::BaseGeometry::Pointer> m_RedoGeometryList;
+ std::list<mitk::BaseGeometry::Pointer> m_RedoPointsGeometryList;
bool m_ShowRedGreen;
float m_Opacity;
float m_OriginalOpacity;
mitk::Color m_FixedColor;
mitk::Color m_MovingColor;
int m_Transformation;
bool m_HideFixedImage;
bool m_HideMovingImage;
std::string m_OldFixedLabel;
std::string m_OldMovingLabel;
bool m_Deactivated;
int m_CurrentFixedLandmarksObserverID;
int m_CurrentMovingLandmarksObserverID;
itk::SimpleMemberCommand<QmitkPointBasedRegistrationView>::Pointer m_FixedLandmarksChangedCommand;
itk::SimpleMemberCommand<QmitkPointBasedRegistrationView>::Pointer m_MovingLandmarksChangedCommand;
};
#endif // !defined(QMITK_POINTBASEDREGISTRATION_H__INCLUDED)
diff --git a/Plugins/org.mitk.gui.qt.registration/src/internal/QmitkRigidRegistrationSelectorView.cpp b/Plugins/org.mitk.gui.qt.registration/src/internal/QmitkRigidRegistrationSelectorView.cpp
index e1f4827627..ecb1ff7d00 100644
--- a/Plugins/org.mitk.gui.qt.registration/src/internal/QmitkRigidRegistrationSelectorView.cpp
+++ b/Plugins/org.mitk.gui.qt.registration/src/internal/QmitkRigidRegistrationSelectorView.cpp
@@ -1,783 +1,786 @@
/*===================================================================
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 "mitkImageTimeSelector.h"
#include <QValidator>
#include <vtkTransform.h>
#include <vtkMatrix4x4.h>
#include "mitkMatrixConvert.h"
#include <qinputdialog.h>
#include <qmessagebox.h>
#include "QmitkLoadPresetDialog.h"
#include <itkArray.h>
#include "mitkRigidRegistrationPreset.h"
#include "mitkProgressBar.h"
#include "QmitkRigidRegistrationSelectorView.h"
#include "QmitkTranslationTransformView.h"
#include "QmitkScaleTransformView.h"
#include "QmitkScaleLogarithmicTransformView.h"
#include "QmitkAffineTransformView.h"
#include "QmitkFixedCenterOfRotationAffineTransformView.h"
#include "QmitkEuler3DTransformView.h"
#include "QmitkCenteredEuler3DTransformView.h"
#include "QmitkQuaternionRigidTransformView.h"
#include "QmitkVersorTransformView.h"
#include "QmitkVersorRigid3DTransformView.h"
#include "QmitkScaleSkewVersor3DTransformView.h"
#include "QmitkSimilarity3DTransformView.h"
#include "QmitkRigid2DTransformView.h"
#include "QmitkCenteredRigid2DTransformView.h"
#include "QmitkEuler2DTransformView.h"
#include "QmitkSimilarity2DTransformView.h"
#include "QmitkCenteredSimilarity2DTransformView.h"
#include "QmitkMeanSquaresMetricView.h"
#include "QmitkNormalizedCorrelationMetricView.h"
#include "QmitkGradientDifferenceMetricView.h"
#include "QmitkKullbackLeiblerCompareHistogramMetricView.h"
#include "QmitkCorrelationCoefficientHistogramMetricView.h"
#include "QmitkMeanSquaresHistogramMetricView.h"
#include "QmitkMutualInformationHistogramMetricView.h"
#include "QmitkNormalizedMutualInformationHistogramMetricView.h"
#include "QmitkMattesMutualInformationMetricView.h"
#include "QmitkMeanReciprocalSquareDifferenceMetricView.h"
#include "QmitkMutualInformationMetricView.h"
#include "QmitkMatchCardinalityMetricView.h"
#include "QmitkKappaStatisticMetricView.h"
#include "QmitkExhaustiveOptimizerView.h"
#include "QmitkGradientDescentOptimizerView.h"
#include "QmitkQuaternionRigidTransformGradientDescentOptimizerView.h"
#include "QmitkLBFGSBOptimizerView.h"
#include "QmitkOnePlusOneEvolutionaryOptimizerView.h"
#include "QmitkPowellOptimizerView.h"
#include "QmitkFRPROptimizerView.h"
#include "QmitkRegularStepGradientDescentOptimizerView.h"
#include "QmitkVersorTransformOptimizerView.h"
#include "QmitkAmoebaOptimizerView.h"
#include "QmitkConjugateGradientOptimizerView.h"
#include "QmitkLBFGSOptimizerView.h"
#include "QmitkSPSAOptimizerView.h"
#include "QmitkVersorRigid3DTransformOptimizerView.h"
QmitkRigidRegistrationSelectorView::QmitkRigidRegistrationSelectorView(QWidget* parent, Qt::WindowFlags f ) : QWidget( parent, f ),
m_FixedNode(NULL), m_FixedMaskNode(NULL), m_MovingNode(NULL), m_MovingMaskNode(NULL), m_FixedDimension(0), m_MovingDimension(0),
m_StopOptimization(false), m_GeometryItkPhysicalToWorldTransform(NULL), m_GeometryWorldToItkPhysicalTransform(NULL),
m_MovingGeometry(NULL), m_ImageGeometry(NULL)
{
m_Controls.setupUi(parent);
this->AddTransform(new QmitkTranslationTransformView(this, f));
this->AddTransform(new QmitkScaleTransformView(this, f));
this->AddTransform(new QmitkScaleLogarithmicTransformView(this, f));
this->AddTransform(new QmitkAffineTransformView(this, f));
this->AddTransform(new QmitkFixedCenterOfRotationAffineTransformView(this, f));
this->AddTransform(new QmitkEuler3DTransformView(this, f));
this->AddTransform(new QmitkCenteredEuler3DTransformView(this, f));
this->AddTransform(new QmitkQuaternionRigidTransformView(this, f));
this->AddTransform(new QmitkVersorTransformView(this, f));
this->AddTransform(new QmitkVersorRigid3DTransformView(this, f));
this->AddTransform(new QmitkScaleSkewVersor3DTransformView(this, f));
this->AddTransform(new QmitkSimilarity3DTransformView(this, f));
this->AddTransform(new QmitkRigid2DTransformView(this, f));
this->AddTransform(new QmitkCenteredRigid2DTransformView(this, f));
this->AddTransform(new QmitkEuler2DTransformView(this, f));
this->AddTransform(new QmitkSimilarity2DTransformView(this, f));
this->AddTransform(new QmitkCenteredSimilarity2DTransformView(this, f));
this->AddMetric(new QmitkMeanSquaresMetricView(this, f));
this->AddMetric(new QmitkNormalizedCorrelationMetricView(this, f));
this->AddMetric(new QmitkGradientDifferenceMetricView(this, f));
this->AddMetric(new QmitkKullbackLeiblerCompareHistogramMetricView(this, f));
this->AddMetric(new QmitkCorrelationCoefficientHistogramMetricView(this, f));
this->AddMetric(new QmitkMeanSquaresHistogramMetricView(this, f));
this->AddMetric(new QmitkMutualInformationHistogramMetricView(this, f));
this->AddMetric(new QmitkNormalizedMutualInformationHistogramMetricView(this, f));
this->AddMetric(new QmitkMattesMutualInformationMetricView(this, f));
this->AddMetric(new QmitkMeanReciprocalSquareDifferenceMetricView(this, f));
this->AddMetric(new QmitkMutualInformationMetricView(this, f));
this->AddMetric(new QmitkMatchCardinalityMetricView(this, f));
this->AddMetric(new QmitkKappaStatisticMetricView(this, f));
this->AddOptimizer(new QmitkExhaustiveOptimizerView(this, f));
this->AddOptimizer(new QmitkGradientDescentOptimizerView(this, f));
this->AddOptimizer(new QmitkQuaternionRigidTransformGradientDescentOptimizerView(this, f));
this->AddOptimizer(new QmitkLBFGSBOptimizerView(this, f));
this->AddOptimizer(new QmitkOnePlusOneEvolutionaryOptimizerView(this, f));
this->AddOptimizer(new QmitkPowellOptimizerView(this, f));
this->AddOptimizer(new QmitkFRPROptimizerView(this, f));
this->AddOptimizer(new QmitkRegularStepGradientDescentOptimizerView(this, f));
this->AddOptimizer(new QmitkVersorTransformOptimizerView(this, f));
this->AddOptimizer(new QmitkAmoebaOptimizerView(this, f));
this->AddOptimizer(new QmitkConjugateGradientOptimizerView(this, f));
this->AddOptimizer(new QmitkLBFGSOptimizerView(this, f));
this->AddOptimizer(new QmitkSPSAOptimizerView(this, f));
this->AddOptimizer(new QmitkVersorRigid3DTransformOptimizerView(this, f));
m_Observer = mitk::RigidRegistrationObserver::New();
m_Controls.m_TransformFrame->setEnabled(true);
m_Controls.m_MetricFrame->setEnabled(true);
m_Controls.m_OptimizerFrame->setEnabled(true);
m_Controls.m_InterpolatorFrame->setEnabled(true);
m_Controls.m_TransformFrame->hide();
m_Controls.m_MetricFrame->hide();
m_Controls.m_OptimizerFrame->hide();
m_Controls.m_InterpolatorFrame->hide();
m_Controls.m_TransformBox->setCurrentIndex(0);
m_Controls.m_MetricBox->setCurrentIndex(0);
m_Controls.m_OptimizerBox->setCurrentIndex(0);
m_Controls.m_TransformWidgetStack->setCurrentIndex(0);
m_Controls.m_MetricWidgetStack->setCurrentIndex(0);
m_Controls.m_OptimizerWidgetStack->setCurrentIndex(0);
/// and show the selected views
this->TransformSelected(m_Controls.m_TransformBox->currentIndex());
this->MetricSelected(m_Controls.m_MetricBox->currentIndex());
this->OptimizerSelected(m_Controls.m_OptimizerBox->currentIndex());
//// create connections
connect( m_Controls.m_TransformGroup, SIGNAL(clicked(bool)), m_Controls.m_TransformFrame, SLOT(setVisible(bool)));
connect( m_Controls.m_TransformBox, SIGNAL(activated(int)), m_Controls.m_TransformWidgetStack, SLOT(setCurrentIndex(int)));
connect( m_Controls.m_TransformBox, SIGNAL(activated(int)), this, SLOT(TransformSelected(int)));
connect( m_Controls.m_MetricBox, SIGNAL(activated(int)), this, SLOT(MetricSelected(int)));
connect( m_Controls.m_OptimizerBox, SIGNAL(activated(int)), this, SLOT(OptimizerSelected(int)));
connect( m_Controls.m_MetricGroup, SIGNAL(clicked(bool)), m_Controls.m_MetricFrame, SLOT(setVisible(bool)));
connect( m_Controls.m_MetricBox, SIGNAL(activated(int)), m_Controls.m_MetricWidgetStack, SLOT(setCurrentIndex(int)));
connect( m_Controls.m_OptimizerGroup, SIGNAL(clicked(bool)), m_Controls.m_OptimizerFrame, SLOT(setVisible(bool)));
connect( m_Controls.m_OptimizerBox, SIGNAL(activated(int)), m_Controls.m_OptimizerWidgetStack, SLOT(setCurrentIndex(int)));
connect( m_Controls.m_InterpolatorGroup, SIGNAL(toggled(bool)), m_Controls.m_InterpolatorFrame, SLOT(setVisible(bool)));
m_Preset = new mitk::RigidRegistrationPreset();
m_Preset->LoadPreset();
this->DoLoadRigidRegistrationPreset("AffineMutualInformationGradientDescent");
}
QmitkRigidRegistrationSelectorView::~QmitkRigidRegistrationSelectorView()
{
}
/// this method starts the registration process
void QmitkRigidRegistrationSelectorView::CalculateTransformation(unsigned int timestep)
{
if (m_FixedNode.IsNotNull() && m_MovingNode.IsNotNull())
{
emit AddNewTransformationToUndoList();
mitk::Image::Pointer fimage = dynamic_cast<mitk::Image*>(m_FixedNode->GetData())->Clone();
mitk::Image::Pointer mimage = dynamic_cast<mitk::Image*>(m_MovingNode->GetData())->Clone();
mitk::Image::Pointer mmimage = NULL;
mitk::Image::Pointer fmimage = NULL;
if (m_MovingMaskNode.IsNotNull())
{
mmimage = dynamic_cast<mitk::Image*>(m_MovingMaskNode->GetData());
}
if (m_FixedMaskNode.IsNotNull())
{
fmimage = dynamic_cast<mitk::Image*>(m_FixedMaskNode->GetData());
}
mitk::ImageTimeSelector::Pointer its = mitk::ImageTimeSelector::New();
if(fimage->GetDimension()>3)
{
its->SetInput(fimage);
its->SetTimeNr(timestep);
its->Update();
fimage = its->GetOutput();
}
if(mimage->GetDimension()>3)
{
its->SetInput(mimage);
its->SetTimeNr(timestep);
its->Update();
mimage = its->GetOutput();
}
// Initial moving image geometry
- m_ImageGeometry = m_MovingNode->GetData()->GetGeometry()->Clone();
+ itk::LightObject::Pointer lopointer = m_MovingNode->GetData()->GetGeometry()->Clone();
+ m_ImageGeometry = dynamic_cast<mitk::BaseGeometry*>(lopointer.GetPointer());
std::cout << "Moving Image Geometry (IndexToWorldTransform)" << std::endl;
std::cout << m_ImageGeometry->GetIndexToWorldTransform()->GetMatrix();
- mitk::Geometry3D::TransformType::InputPointType center = m_ImageGeometry->GetIndexToWorldTransform()->GetCenter();
+ mitk::BaseGeometry::TransformType::InputPointType center = m_ImageGeometry->GetIndexToWorldTransform()->GetCenter();
std::cout << "center " << center[0] << " " << center[1] << " " << center[2] << std::endl;
- mitk::Geometry3D::TransformType::OutputVectorType offset = m_ImageGeometry->GetIndexToWorldTransform()->GetOffset();
+ mitk::BaseGeometry::TransformType::OutputVectorType offset = m_ImageGeometry->GetIndexToWorldTransform()->GetOffset();
std::cout << "offset " << offset[0] << " " << offset[1] << " " << offset[2] << std::endl;
std::cout << std::endl;
// Fixed image geometry
// mitk::Geometry3D::Pointer m_FixedGeometryCopy = m_FixedNode->GetData()->GetGeometry()->Clone();
// std::cout << "Fixed Image Geometry (IndexToWorldTransform)" << std::endl;
// std::cout << m_FixedGeometryCopy->GetIndexToWorldTransform()->GetMatrix();
// center = m_FixedGeometryCopy->GetIndexToWorldTransform()->GetCenter();
// std::cout << "center " << center[0] << " " << center[1] << " " << center[2] << std::endl;
// offset = m_FixedGeometryCopy->GetIndexToWorldTransform()->GetOffset();
// std::cout << "offset " << offset[0] << " " << offset[1] << " " << offset[2] << std::endl;
// std::cout << std::endl;
// Calculate the World to ITK-Physical transform for the moving image
m_MovingGeometry = m_MovingNode->GetData()->GetGeometry();
// container that holds all derived moving data, that needs to be transformed with the transformation found by registration
if(m_MovingMaskNode.IsNotNull())
{
- m_ChildNodes.insert(std::pair<mitk::DataNode::Pointer, mitk::Geometry3D*>(m_MovingMaskNode, m_MovingMaskNode->GetData()->GetGeometry()));
- m_ChildNodes2.insert(std::pair<mitk::DataNode::Pointer, mitk::Geometry3D::Pointer>(m_MovingMaskNode, m_MovingMaskNode->GetData()->GetGeometry()->Clone()));
+ m_ChildNodes.insert(std::pair<mitk::DataNode::Pointer, mitk::BaseGeometry*>(m_MovingMaskNode, m_MovingMaskNode->GetData()->GetGeometry()));
+ itk::LightObject::Pointer lopointer = m_MovingMaskNode->GetData()->GetGeometry()->Clone();
+ m_ChildNodes2.insert(std::pair<mitk::DataNode::Pointer, mitk::BaseGeometry::Pointer>(m_MovingMaskNode, dynamic_cast<mitk::BaseGeometry*>(lopointer.GetPointer())));
}
if(m_MovingNodeChildren.IsNotNull())
{
unsigned long size = 0;
size = m_MovingNodeChildren->Size();
mitk::DataNode::Pointer childNode;
for (unsigned long i = 0; i < size; ++i)
{
- m_ChildNodes.insert(std::pair<mitk::DataNode::Pointer, mitk::Geometry3D*>(m_MovingNodeChildren->GetElement(i), m_MovingNodeChildren->GetElement(i)->GetData()->GetGeometry()));
- m_ChildNodes2.insert(std::pair<mitk::DataNode::Pointer, mitk::Geometry3D::Pointer>(m_MovingNodeChildren->GetElement(i), m_MovingNodeChildren->GetElement(i)->GetData()->GetGeometry()->Clone()));
+ m_ChildNodes.insert(std::pair<mitk::DataNode::Pointer, mitk::BaseGeometry*>(m_MovingNodeChildren->GetElement(i), m_MovingNodeChildren->GetElement(i)->GetData()->GetGeometry()));
+ itk::LightObject::Pointer lopointer = m_MovingNodeChildren->GetElement(i)->GetData()->GetGeometry()->Clone();
+ m_ChildNodes2.insert(std::pair<mitk::DataNode::Pointer, mitk::BaseGeometry::Pointer>(m_MovingNodeChildren->GetElement(i), dynamic_cast<mitk::BaseGeometry*>(lopointer.GetPointer())));
}
}
- m_GeometryWorldToItkPhysicalTransform = mitk::Geometry3D::TransformType::New();
+ m_GeometryWorldToItkPhysicalTransform = mitk::BaseGeometry::TransformType::New();
GetWorldToItkPhysicalTransform(m_MovingGeometry, m_GeometryWorldToItkPhysicalTransform.GetPointer());
// std::cout << "Moving Image: World to ITK-physical transform" << std::endl;
// std::cout << m_GeometryWorldToItkPhysicalTransform->GetMatrix();
// center = m_GeometryWorldToItkPhysicalTransform->GetCenter();
// std::cout << "center " << center[0] << " " << center[1] << " " << center[2] << std::endl;
// offset = m_GeometryWorldToItkPhysicalTransform->GetOffset();
// std::cout << "offset " << offset[0] << " " << offset[1] << " " << offset[2] << std::endl;
// std::cout << std::endl;
// Calculate the ITK-Physical to World transform for the fixed image
- m_GeometryItkPhysicalToWorldTransform = mitk::Geometry3D::TransformType::New();
- mitk::Geometry3D::TransformType::Pointer fixedWorld2Phys = mitk::Geometry3D::TransformType::New();
+ m_GeometryItkPhysicalToWorldTransform = mitk::BaseGeometry::TransformType::New();
+ mitk::BaseGeometry::TransformType::Pointer fixedWorld2Phys = mitk::BaseGeometry::TransformType::New();
GetWorldToItkPhysicalTransform(m_FixedNode->GetData()->GetGeometry(), fixedWorld2Phys.GetPointer());
fixedWorld2Phys->GetInverse(m_GeometryItkPhysicalToWorldTransform);
// std::cout << "Fixed Image: ITK-physical to World transform" << std::endl;
// std::cout << m_GeometryItkPhysicalToWorldTransform->GetMatrix();
// center = m_GeometryItkPhysicalToWorldTransform->GetCenter();
// std::cout << "center " << center[0] << " " << center[1] << " " << center[2] << std::endl;
// offset = m_GeometryItkPhysicalToWorldTransform->GetOffset();
// std::cout << "offset " << offset[0] << " " << offset[1] << " " << offset[2] << std::endl;
// std::cout << std::endl;
// init callback
itk::ReceptorMemberCommand<QmitkRigidRegistrationSelectorView>::Pointer command = itk::ReceptorMemberCommand<QmitkRigidRegistrationSelectorView>::New();
command->SetCallbackFunction(this, &QmitkRigidRegistrationSelectorView::SetOptimizerValue);
int observer = m_Observer->AddObserver( itk::AnyEvent(), command );
std::vector<std::string> presets;
// init registration method
mitk::ImageRegistrationMethod::Pointer registration = mitk::ImageRegistrationMethod::New();
registration->SetObserver(m_Observer);
registration->SetInterpolator(m_Controls.m_InterpolatorBox->currentIndex());
registration->SetReferenceImage(fimage);
registration->SetInput(mimage);
if (mmimage.IsNotNull())
{
registration->SetMovingMask(mmimage);
}
if (fmimage.IsNotNull())
{
registration->SetFixedMask(fmimage);
}
dynamic_cast<QmitkRigidRegistrationTransformsGUIBase*>(m_Controls.m_TransformWidgetStack->currentWidget())->SetFixedImage(dynamic_cast<mitk::Image*>(m_FixedNode->GetData()));
dynamic_cast<QmitkRigidRegistrationTransformsGUIBase*>(m_Controls.m_TransformWidgetStack->currentWidget())->SetMovingImage(dynamic_cast<mitk::Image*>(m_MovingNode->GetData()));
registration->SetOptimizerScales(dynamic_cast<QmitkRigidRegistrationTransformsGUIBase*>(m_Controls.m_TransformWidgetStack->currentWidget())->GetScales());
registration->SetTransform(dynamic_cast<QmitkRigidRegistrationTransformsGUIBase*>(m_Controls.m_TransformWidgetStack->currentWidget())->GetTransform());
dynamic_cast<QmitkRigidRegistrationMetricsGUIBase*>(m_Controls.m_MetricWidgetStack->currentWidget())->SetMovingImage(dynamic_cast<mitk::Image*>(m_MovingNode->GetData()));
registration->SetMetric(dynamic_cast<QmitkRigidRegistrationMetricsGUIBase*>(m_Controls.m_MetricWidgetStack->currentWidget())->GetMetric());
registration->SetOptimizer(dynamic_cast<QmitkRigidRegistrationOptimizerGUIBase*>(m_Controls.m_OptimizerWidgetStack->currentWidget())->GetOptimizer());
double time(0.0);
double tstart(0.0);
tstart = clock();
try
{
registration->Update();
}
catch (itk::ExceptionObject e)
{
MITK_INFO << "Caught exception: "<<e.GetDescription();
QMessageBox::information( this, "Registration exception", e.GetDescription());
mitk::ProgressBar::GetInstance()->Progress(20);
}
time += clock() - tstart;
time = time / CLOCKS_PER_SEC;
//printOut of the Time
MITK_INFO << "Registration Time: " << time;
m_Observer->RemoveObserver(observer);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
void QmitkRigidRegistrationSelectorView::SetFixedNode( mitk::DataNode * fixedNode )
{
m_FixedNode = fixedNode;
m_Controls.m_TransformBox->setCurrentIndex(m_Controls.m_TransformBox->currentIndex());
}
void QmitkRigidRegistrationSelectorView::SetFixedDimension( int dimension )
{
m_FixedDimension = dimension;
}
void QmitkRigidRegistrationSelectorView::SetMovingNode( mitk::DataNode * movingNode )
{
m_MovingNode = movingNode;
this->TransformSelected(m_Controls.m_TransformBox->currentIndex());
}
void QmitkRigidRegistrationSelectorView::SetMovingDimension(int dimension )
{
m_MovingDimension = dimension;
}
// this is a callback function that retrieves the current transformation
// parameters after every step of progress in the optimizer.
// depending on the choosen transformation, we construct a vtktransform
// that will be applied to the geometry of the moving image.
// the values are delivered by mitkRigidRgistrationObserver.cpp
void QmitkRigidRegistrationSelectorView::SetOptimizerValue( const itk::EventObject & )
{
if (m_StopOptimization)
{
m_Observer->SetStopOptimization(true);
m_StopOptimization = false;
}
// retreive optimizer value for the current transformation
double value = m_Observer->GetCurrentOptimizerValue();
// retreive current parameterset of the transformation
itk::Array<double> transformParams = m_Observer->GetCurrentTranslation();
// init an empty affine transformation that will be filled with
// the corresponding transformation parameters in the following
vtkMatrix4x4* vtkmatrix = vtkMatrix4x4::New();
vtkmatrix->Identity();
// init a transform that will be initialized with the vtkmatrix later
vtkTransform* vtktransform = vtkTransform::New();
if (m_MovingNode.IsNotNull())
{
vtktransform = dynamic_cast<QmitkRigidRegistrationTransformsGUIBase*>(m_Controls.m_TransformWidgetStack->currentWidget())->Transform(vtkmatrix, vtktransform, transformParams);
// the retrieved transform goes from fixed to moving space.
// invert the transform in order to go from moving to fixed space.
vtkMatrix4x4* vtkmatrix_inv = vtkMatrix4x4::New();
vtktransform->GetInverse(vtkmatrix_inv);
// now adapt the moving geometry accordingly
m_MovingGeometry->GetIndexToWorldTransform()->SetIdentity();
// the next view lines: Phi(Phys2World)*Phi(Result)*Phi(World2Phy)*Phi(Initial)
// set moving image geometry to registration result
m_MovingGeometry->SetIndexToWorldTransformByVtkMatrix(vtkmatrix_inv);
/*std::cout << std::endl;
std::cout << m_MovingGeometry->GetIndexToWorldTransform()->GetMatrix();
mitk::Geometry3D::TransformType::OutputVectorType offset = m_MovingGeometry->GetIndexToWorldTransform()->GetOffset();
std::cout << "offset " << offset[0] << " " << offset[1] << " " << offset[2] << std::endl;*/
#if !defined(ITK_IMAGE_BEHAVES_AS_ORIENTED_IMAGE)
// the next few lines: Phi(Phys2World)*Phi(Result)*Phi(World2Phy)*Phi(Initial)
// go to itk physical space before applying the registration result
m_MovingGeometry->Compose(m_GeometryWorldToItkPhysicalTransform, 1);
// right in the beginning, transform by initial moving image geometry
m_MovingGeometry->Compose(m_ImageGeometry->GetIndexToWorldTransform(), 1);
// in the end, go back to world space
m_MovingGeometry->Compose(m_GeometryItkPhysicalToWorldTransform, 0);
#else
m_MovingGeometry->Compose(m_ImageGeometry->GetIndexToWorldTransform(), 1);
#endif
/*std::cout << std::endl << m_MovingGeometry->GetIndexToWorldTransform()->GetMatrix();
offset = m_MovingGeometry->GetIndexToWorldTransform()->GetOffset();
std::cout << "offset " << offset[0] << " " << offset[1] << " " << offset[2] << std::endl << std::endl;*/
// now adapt all children geometries accordingly if children exist
- std::map<mitk::DataNode::Pointer, mitk::Geometry3D*>::iterator iter;
- std::map<mitk::DataNode::Pointer, mitk::Geometry3D::Pointer>::iterator iter2;
+ std::map<mitk::DataNode::Pointer, mitk::BaseGeometry*>::iterator iter;
+ std::map<mitk::DataNode::Pointer, mitk::BaseGeometry::Pointer>::iterator iter2;
mitk::DataNode::Pointer childNode;
for( iter = m_ChildNodes.begin(); iter != m_ChildNodes.end(); iter++ )
{
childNode = (*iter).first;
if (childNode.IsNotNull())
{
- mitk::Geometry3D* childGeometry;
- mitk::Geometry3D::Pointer childImageGeometry;
+ mitk::BaseGeometry* childGeometry;
+ mitk::BaseGeometry::Pointer childImageGeometry;
// Calculate the World to ITK-Physical transform for the moving mask
childGeometry = (*iter).second;
iter2 = m_ChildNodes2.find(childNode);
childImageGeometry = (*iter2).second;
childGeometry->GetIndexToWorldTransform()->SetIdentity();
// the next view lines: Phi(Phys2World)*Phi(Result)*Phi(World2Phy)*Phi(Initial)
// set moving mask geometry to registration result
childGeometry->SetIndexToWorldTransformByVtkMatrix(vtkmatrix_inv);
#if !defined(ITK_IMAGE_BEHAVES_AS_ORIENTED_IMAGE)
// the next few lines: Phi(Phys2World)*Phi(Result)*Phi(World2Phy)*Phi(Initial)
// go to itk physical space before applying the registration result
childGeometry->Compose(m_GeometryWorldToItkPhysicalTransform, 1);
// right in the beginning, transform by initial moving image geometry
childGeometry->Compose(childImageGeometry->GetIndexToWorldTransform(), 1);
// in the end, go back to world space
childGeometry->Compose(m_GeometryItkPhysicalToWorldTransform, 0);
#else
childGeometry->Compose(childImageGeometry->GetIndexToWorldTransform(), 1);
#endif
}
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
emit OptimizerChanged(value);
}
/// this method is called whenever the combobox with the selectable transforms changes
/// responsible for showing the selected transform parameters
void QmitkRigidRegistrationSelectorView::TransformSelected( int transform )
{
if (m_FixedNode.IsNotNull())
{
dynamic_cast<QmitkRigidRegistrationTransformsGUIBase*>(m_Controls.m_TransformWidgetStack->widget(transform))->SetFixedImage(dynamic_cast<mitk::Image*>(m_FixedNode->GetData()));
}
if (m_MovingNode.IsNotNull())
{
dynamic_cast<QmitkRigidRegistrationTransformsGUIBase*>(m_Controls.m_TransformWidgetStack->widget(transform))->SetMovingImage(dynamic_cast<mitk::Image*>(m_MovingNode->GetData()));
}
int numberOfTransformParameters = dynamic_cast<QmitkRigidRegistrationTransformsGUIBase*>(m_Controls.m_TransformWidgetStack->widget(transform))->GetNumberOfTransformParameters();
dynamic_cast<QmitkRigidRegistrationOptimizerGUIBase*>(m_Controls.m_OptimizerWidgetStack->currentWidget())->SetNumberOfTransformParameters(numberOfTransformParameters);
//set fixed height
m_Controls.m_TransformWidgetStack->setFixedHeight( dynamic_cast<QmitkRigidRegistrationTransformsGUIBase*>(m_Controls.m_TransformWidgetStack->widget(transform))->minimumSizeHint().height() );
this->OptimizerSelected(m_Controls.m_OptimizerWidgetStack->currentIndex());
}
/// this method is called whenever the combobox with the selectable metrics changes
/// responsible for showing the selected metric parameters
void QmitkRigidRegistrationSelectorView::MetricSelected( int metric )
{
if (m_FixedNode.IsNotNull())
{
dynamic_cast<QmitkRigidRegistrationMetricsGUIBase*>(m_Controls.m_MetricWidgetStack->widget(metric))->SetMovingImage(dynamic_cast<mitk::Image*>(m_MovingNode->GetData()));
}
//set fixed height
m_Controls.m_MetricWidgetStack->setFixedHeight( dynamic_cast<QmitkRigidRegistrationMetricsGUIBase*>(m_Controls.m_MetricWidgetStack->widget(metric))->minimumSizeHint().height() );
}
/// this method is called whenever the combobox with the selectable optimizers changes
/// responsible for showing the selected optimizer parameters
void QmitkRigidRegistrationSelectorView::OptimizerSelected( int optimizer )
{
int numberOfTransformParameters = dynamic_cast<QmitkRigidRegistrationTransformsGUIBase*>(m_Controls.m_TransformWidgetStack->currentWidget())->GetNumberOfTransformParameters();
dynamic_cast<QmitkRigidRegistrationOptimizerGUIBase*>(m_Controls.m_OptimizerWidgetStack->widget(optimizer))->SetNumberOfTransformParameters(numberOfTransformParameters);
//set fixed height
m_Controls.m_OptimizerWidgetStack->setFixedHeight( dynamic_cast<QmitkRigidRegistrationOptimizerGUIBase*>(m_Controls.m_OptimizerWidgetStack->widget(optimizer))->minimumSizeHint().height() );
}
void QmitkRigidRegistrationSelectorView::LoadRigidRegistrationParameter()
{
this->DoLoadRigidRegistrationParameter();
}
void QmitkRigidRegistrationSelectorView::DoLoadRigidRegistrationParameter()
{
std::map<std::string, itk::Array<double> > existingPresets;
existingPresets = m_Preset->getTransformValuesPresets();
std::map<std::string, itk::Array<double> >::iterator iter;
std::list<std::string> presets;
for( iter = existingPresets.begin(); iter != existingPresets.end(); iter++ )
{
presets.push_back( (*iter).first );
}
if (presets.empty())
{
QMessageBox::warning( NULL, "RigidRegistrationParameters.xml", "RigidRegistrationParameters.xml is empty/does not exist. There are no presets to select.");
return;
}
presets.sort();
// ask about the name to load a preset
QmitkLoadPresetDialog dialog( this, 0, "Load Preset", presets ); // needs a QWidget as parent
int dialogReturnValue = dialog.exec();
if ( dialogReturnValue == QDialog::Rejected ) return; // user clicked cancel or pressed Esc or something similar
this->DoLoadRigidRegistrationPreset(dialog.GetPresetName());
}
void QmitkRigidRegistrationSelectorView::DoLoadRigidRegistrationPreset(std::string presetName)
{
itk::Array<double> transformValues;
transformValues = m_Preset->getTransformValues(presetName);
m_Controls.m_TransformGroup->setChecked(true);
m_Controls.m_TransformFrame->setVisible(true);
m_Controls.m_TransformBox->setCurrentIndex((int)transformValues[0]);
m_Controls.m_TransformWidgetStack->setCurrentIndex((int)transformValues[0]);
this->TransformSelected((int)transformValues[0]);
itk::Array<double> transformValuesForGUI;
transformValuesForGUI.SetSize(transformValues.Size());
transformValuesForGUI.fill(0);
for (unsigned int i = 1; i < transformValues.Size(); i++)
{
transformValuesForGUI[i-1] = transformValues[i];
}
dynamic_cast<QmitkRigidRegistrationTransformsGUIBase*>(m_Controls.m_TransformWidgetStack->currentWidget())->SetTransformParameters(transformValuesForGUI);
itk::Array<double> metricValues;
metricValues = m_Preset->getMetricValues(presetName);
m_Controls.m_MetricGroup->setChecked(true);
m_Controls.m_MetricFrame->setVisible(true);
m_Controls.m_MetricBox->setCurrentIndex((int)metricValues[0]);
m_Controls.m_MetricWidgetStack->setCurrentIndex((int)metricValues[0]);
this->MetricSelected((int)metricValues[0]);
itk::Array<double> metricValuesForGUI;
metricValuesForGUI.SetSize(metricValues.Size());
metricValuesForGUI.fill(0);
for (unsigned int i = 1; i < metricValues.Size(); i++)
{
metricValuesForGUI[i-1] = metricValues[i];
}
dynamic_cast<QmitkRigidRegistrationMetricsGUIBase*>(m_Controls.m_MetricWidgetStack->currentWidget())->SetMetricParameters(metricValuesForGUI);
itk::Array<double> optimizerValues;
optimizerValues = m_Preset->getOptimizerValues(presetName);
m_Controls.m_OptimizerGroup->setChecked(true);
m_Controls.m_OptimizerFrame->setVisible(true);
m_Controls.m_OptimizerBox->setCurrentIndex((int)optimizerValues[0]);
m_Controls.m_OptimizerWidgetStack->setCurrentIndex((int)optimizerValues[0]);
this->OptimizerSelected((int)optimizerValues[0]);
itk::Array<double> optimizerValuesForGUI;
optimizerValuesForGUI.SetSize(optimizerValues.Size());
optimizerValuesForGUI.fill(0);
for (unsigned int i = 1; i < optimizerValues.Size(); i++)
{
optimizerValuesForGUI[i-1] = optimizerValues[i];
}
dynamic_cast<QmitkRigidRegistrationOptimizerGUIBase*>(m_Controls.m_OptimizerWidgetStack->currentWidget())->SetOptimizerParameters(optimizerValuesForGUI);
itk::Array<double> interpolatorValues;
interpolatorValues = m_Preset->getInterpolatorValues(presetName);
m_Controls.m_InterpolatorGroup->setChecked(true);
m_Controls.m_InterpolatorFrame->setVisible(true);
m_Controls.m_InterpolatorBox->setCurrentIndex((int)interpolatorValues[0]);
}
void QmitkRigidRegistrationSelectorView::SaveRigidRegistrationParameter()
{
this->DoSaveRigidRegistrationParameter();
}
void QmitkRigidRegistrationSelectorView::DoSaveRigidRegistrationParameter()
{
bool ok;
QString text = QInputDialog::getText(this,
"Save Parameter Preset", "Enter name for preset:", QLineEdit::Normal,
QString::null, &ok );
if ( ok )
{
std::map<std::string, itk::Array<double> > existingPresets;
existingPresets = m_Preset->getTransformValuesPresets();
std::map<std::string, itk::Array<double> >::iterator iter = existingPresets.find(std::string((const char*)text.toLatin1()));
if (iter != existingPresets.end())
{
QMessageBox::critical( this, "Preset definition",
"Presetname already exists.");
return;
}
if (text.isEmpty())
{
QMessageBox::critical( this, "Preset definition",
"Presetname has to be set.\n"
"You have to enter a Presetname." );
return;
}
itk::Array<double> transformValues;
transformValues.SetSize(25);
transformValues.fill(0);
transformValues[0] = m_Controls.m_TransformBox->currentIndex();
itk::Array<double> transformValuesFromGUI = dynamic_cast<QmitkRigidRegistrationTransformsGUIBase*>(m_Controls.m_TransformWidgetStack->currentWidget())->GetTransformParameters();
for (unsigned int i = 0; i < transformValuesFromGUI.Size(); i++)
{
transformValues[i+1] = transformValuesFromGUI[i];
}
std::map<std::string, itk::Array<double> > transformMap;
transformMap = m_Preset->getTransformValuesPresets();
transformMap[std::string((const char*)text.toLatin1())] = transformValues;
itk::Array<double> metricValues;
metricValues.SetSize(25);
metricValues.fill(0);
metricValues[0] = m_Controls.m_MetricBox->currentIndex();
itk::Array<double> metricValuesFromGUI = dynamic_cast<QmitkRigidRegistrationMetricsGUIBase*>(m_Controls.m_MetricWidgetStack->currentWidget())->GetMetricParameters();
for (unsigned int i = 0; i < metricValuesFromGUI.Size(); i++)
{
metricValues[i+1] = metricValuesFromGUI[i];
}
std::map<std::string, itk::Array<double> > metricMap;
metricMap = m_Preset->getMetricValuesPresets();
metricMap[std::string((const char*)text.toLatin1())] = metricValues;
itk::Array<double> optimizerValues;
optimizerValues.SetSize(25);
optimizerValues.fill(0);
optimizerValues[0] = m_Controls.m_OptimizerBox->currentIndex();
itk::Array<double> optimizerValuesFromGUI = dynamic_cast<QmitkRigidRegistrationOptimizerGUIBase*>(m_Controls.m_OptimizerWidgetStack->currentWidget())->GetOptimizerParameters();
for (unsigned int i = 0; i < optimizerValuesFromGUI.Size(); i++)
{
optimizerValues[i+1] = optimizerValuesFromGUI[i];
}
std::map<std::string, itk::Array<double> > optimizerMap;
optimizerMap = m_Preset->getOptimizerValuesPresets();
optimizerMap[std::string((const char*)text.toLatin1())] = optimizerValues;
itk::Array<double> interpolatorValues;
interpolatorValues.SetSize(25);
interpolatorValues.fill(0);
interpolatorValues[0] = m_Controls.m_InterpolatorBox->currentIndex();
std::map<std::string, itk::Array<double> > interpolatorMap;
interpolatorMap = m_Preset->getInterpolatorValuesPresets();
interpolatorMap[std::string((const char*)text.toLatin1())] = interpolatorValues;
m_Preset->newPresets(transformMap, metricMap, optimizerMap, interpolatorMap);
}
else
{
// user pressed Cancel
}
}
void QmitkRigidRegistrationSelectorView::StopOptimization(bool stopOptimization)
{
m_StopOptimization = stopOptimization;
}
int QmitkRigidRegistrationSelectorView::GetSelectedTransform()
{
return m_Controls.m_TransformBox->currentIndex();
}
void QmitkRigidRegistrationSelectorView::SetFixedMaskNode( mitk::DataNode * fixedMaskNode )
{
m_FixedMaskNode = fixedMaskNode;
this->TransformSelected(m_Controls.m_TransformBox->currentIndex());
}
void QmitkRigidRegistrationSelectorView::SetMovingMaskNode( mitk::DataNode * movingMaskNode )
{
m_MovingMaskNode = movingMaskNode;
this->TransformSelected(m_Controls.m_TransformBox->currentIndex());
}
void QmitkRigidRegistrationSelectorView::SetMovingNodeChildren(mitk::DataStorage::SetOfObjects::ConstPointer children)
{
m_MovingNodeChildren = children;
}
void QmitkRigidRegistrationSelectorView::AddTransform(QmitkRigidRegistrationTransformsGUIBase* transform)
{
m_Controls.m_TransformBox->addItem(transform->GetName());
int i = 0;
if (!dynamic_cast<QmitkRigidRegistrationTransformsGUIBase*>(m_Controls.m_TransformWidgetStack->widget(i)))
{
m_Controls.m_TransformWidgetStack->addWidget(transform);
m_Controls.m_TransformWidgetStack->removeWidget(m_Controls.m_TransformWidgetStack->widget(i));
transform->SetupUI(m_Controls.m_TransformWidgetStack->widget(i));
}
else
{
i = m_Controls.m_TransformWidgetStack->addWidget(transform);
transform->SetupUI(m_Controls.m_TransformWidgetStack->widget(i));
}
}
void QmitkRigidRegistrationSelectorView::AddMetric(QmitkRigidRegistrationMetricsGUIBase* metric)
{
m_Controls.m_MetricBox->addItem(metric->GetName());
int i = 0;
if (!dynamic_cast<QmitkRigidRegistrationMetricsGUIBase*>(m_Controls.m_MetricWidgetStack->widget(i)))
{
m_Controls.m_MetricWidgetStack->addWidget(metric);
m_Controls.m_MetricWidgetStack->removeWidget(m_Controls.m_MetricWidgetStack->widget(i));
metric->SetupUI(m_Controls.m_MetricWidgetStack->widget(i));
}
else
{
i = m_Controls.m_MetricWidgetStack->addWidget(metric);
metric->SetupUI(m_Controls.m_MetricWidgetStack->widget(i));
}
}
void QmitkRigidRegistrationSelectorView::AddOptimizer(QmitkRigidRegistrationOptimizerGUIBase* optimizer)
{
m_Controls.m_OptimizerBox->addItem(optimizer->GetName());
int i = 0;
if (!dynamic_cast<QmitkRigidRegistrationOptimizerGUIBase*>(m_Controls.m_OptimizerWidgetStack->widget(i)))
{
m_Controls.m_OptimizerWidgetStack->addWidget(optimizer);
m_Controls.m_OptimizerWidgetStack->removeWidget(m_Controls.m_OptimizerWidgetStack->widget(i));
optimizer->SetupUI(m_Controls.m_OptimizerWidgetStack->widget(i));
}
else
{
i = m_Controls.m_OptimizerWidgetStack->addWidget(optimizer);
optimizer->SetupUI(m_Controls.m_OptimizerWidgetStack->widget(i));
}
}
diff --git a/Plugins/org.mitk.gui.qt.registration/src/internal/QmitkRigidRegistrationSelectorView.h b/Plugins/org.mitk.gui.qt.registration/src/internal/QmitkRigidRegistrationSelectorView.h
index 955fc12807..66fd552fc6 100644
--- a/Plugins/org.mitk.gui.qt.registration/src/internal/QmitkRigidRegistrationSelectorView.h
+++ b/Plugins/org.mitk.gui.qt.registration/src/internal/QmitkRigidRegistrationSelectorView.h
@@ -1,110 +1,110 @@
/*===================================================================
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 QmitkRigidRegistrationSelectorViewWidgetHIncluded
#define QmitkRigidRegistrationSelectorViewWidgetHIncluded
#include "mitkDataNode.h"
#include "mitkDataStorage.h"
#include "ui_QmitkRigidRegistrationSelector.h"
#include "qobject.h"
#include <org_mitk_gui_qt_registration_Export.h>
#include "QmitkRigidRegistrationTransformsGUIBase.h"
#include "QmitkRigidRegistrationMetricsGUIBase.h"
#include "QmitkRigidRegistrationOptimizerGUIBase.h"
/*!
* \brief Widget for rigid registration
*
* Displays options for rigid registration.
*/
class REGISTRATION_EXPORT QmitkRigidRegistrationSelectorView : public QWidget
{
Q_OBJECT
public:
QmitkRigidRegistrationSelectorView( QWidget* parent = 0, Qt::WindowFlags f = 0 );
~QmitkRigidRegistrationSelectorView();
signals:
void TransformChanged();
void OptimizerChanged(double value);
void AddNewTransformationToUndoList();
public slots:
void SetFixedNode( mitk::DataNode * fixedNode );
void SetFixedMaskNode(mitk::DataNode * fixedMaskNode );
void SetFixedDimension( int dimension );
void SetMovingNode( mitk::DataNode * movingNode );
void SetMovingNodeChildren(mitk::DataStorage::SetOfObjects::ConstPointer children);
void SetMovingMaskNode(mitk::DataNode * movingMaskNode );
void SetMovingDimension(int dimension );
int GetSelectedTransform();
void CalculateTransformation(unsigned int timestep = 0);
void StopOptimization(bool stopOptimization);
protected slots:
// this is a callback function that retrieves the current transformation
// parameters after every step of progress in the optimizer.
// depending on the choosen transformation, we construct a vtktransform
// that will be applied to the geometry of the moving image.
// the values are delivered by mitkRigidRgistrationObserver.cpp
void SetOptimizerValue( const itk::EventObject & );
/// this method is called whenever the combobox with the selectable transforms changes
/// responsible for showing the selected transformparameters
void TransformSelected( int transform );
/// this method is called whenever the combobox with the selectable metrics changes
/// responsible for showing the selected metricparameters
void MetricSelected( int metric );
/// this method is called whenever the combobox with the selectable optimizer changes
/// responsible for showing the selected optimizerparameters
void OptimizerSelected( int optimizer );
void LoadRigidRegistrationParameter();
void SaveRigidRegistrationParameter();
//void LoadRigidRegistrationTestParameter();
//void SaveRigidRegistrationTestParameter();
void DoLoadRigidRegistrationParameter();
void DoLoadRigidRegistrationPreset(std::string presetName);
void DoSaveRigidRegistrationParameter();
void AddTransform(QmitkRigidRegistrationTransformsGUIBase* transform);
void AddMetric(QmitkRigidRegistrationMetricsGUIBase* metric);
void AddOptimizer(QmitkRigidRegistrationOptimizerGUIBase* optimizer);
protected:
Ui::QmitkRigidRegistrationSelector m_Controls;
mitk::DataNode::Pointer m_FixedNode;
mitk::DataNode::Pointer m_FixedMaskNode;
mitk::DataNode::Pointer m_MovingNode;
mitk::DataNode::Pointer m_MovingMaskNode;
int m_FixedDimension;
int m_MovingDimension;
bool m_StopOptimization;
mitk::RigidRegistrationPreset* m_Preset;
- mitk::Geometry3D::TransformType::Pointer m_GeometryItkPhysicalToWorldTransform;
- mitk::Geometry3D::TransformType::Pointer m_GeometryWorldToItkPhysicalTransform;
- mitk::Geometry3D* m_MovingGeometry;
- mitk::Geometry3D::Pointer m_ImageGeometry;
+ mitk::BaseGeometry::TransformType::Pointer m_GeometryItkPhysicalToWorldTransform;
+ mitk::BaseGeometry::TransformType::Pointer m_GeometryWorldToItkPhysicalTransform;
+ mitk::BaseGeometry* m_MovingGeometry;
+ mitk::BaseGeometry::Pointer m_ImageGeometry;
mitk::RigidRegistrationObserver::Pointer m_Observer;
mitk::DataStorage::SetOfObjects::ConstPointer m_MovingNodeChildren;
- std::map<mitk::DataNode::Pointer, mitk::Geometry3D*> m_ChildNodes;
- std::map<mitk::DataNode::Pointer, mitk::Geometry3D::Pointer> m_ChildNodes2;
+ std::map<mitk::DataNode::Pointer, mitk::BaseGeometry*> m_ChildNodes;
+ std::map<mitk::DataNode::Pointer, mitk::BaseGeometry::Pointer> m_ChildNodes2;
};
#endif
diff --git a/Plugins/org.mitk.gui.qt.registration/src/internal/QmitkRigidRegistrationView.cpp b/Plugins/org.mitk.gui.qt.registration/src/internal/QmitkRigidRegistrationView.cpp
index eedf572147..a09be60d72 100644
--- a/Plugins/org.mitk.gui.qt.registration/src/internal/QmitkRigidRegistrationView.cpp
+++ b/Plugins/org.mitk.gui.qt.registration/src/internal/QmitkRigidRegistrationView.cpp
@@ -1,1456 +1,1456 @@
/*===================================================================
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.
===================================================================*/
// Qmitk includes
#include "QmitkRigidRegistrationView.h"
#include "QmitkStdMultiWidget.h"
// MITK includes
#include "mitkDataNodeObject.h"
#include <mitkImageCast.h>
#include "mitkManualSegmentationToSurfaceFilter.h"
#include <mitkSegmentationSink.h>
#include <mitkImageStatisticsHolder.h>
#include "mitkNodePredicateDataType.h"
#include "mitkNodePredicateAnd.h"
#include "mitkNodePredicateProperty.h"
// QT includes
#include "qinputdialog.h"
#include "qmessagebox.h"
#include "qcursor.h"
#include "qapplication.h"
#include "qradiobutton.h"
#include "qslider.h"
#include "qtooltip.h"
// VTK includes
#include <vtkTransform.h>
// ITK includes
#include <itkBinaryThresholdImageFilter.h>
// BlueBerry includes
#include "berryIWorkbenchWindow.h"
#include "berryISelectionService.h"
const std::string QmitkRigidRegistrationView::VIEW_ID = "org.mitk.views.rigidregistration";
using namespace berry;
struct SelListenerRigidRegistration : ISelectionListener
{
berryObjectMacro(SelListenerRigidRegistration);
SelListenerRigidRegistration(QmitkRigidRegistrationView* view)
{
m_View = view;
}
void DoSelectionChanged(ISelection::ConstPointer selection)
{
// save current selection in member variable
m_View->m_CurrentSelection = selection.Cast<const IStructuredSelection>();
// do something with the selected items
if(m_View->m_CurrentSelection)
{
if (m_View->m_CurrentSelection->Size() != 2)
{
if (m_View->m_FixedNode.IsNull() || m_View->m_MovingNode.IsNull())
{
m_View->m_Controls.m_StatusLabel->show();
m_View->m_Controls.TextLabelFixed->hide();
m_View->m_Controls.m_FixedLabel->hide();
m_View->m_Controls.TextLabelMoving->hide();
m_View->m_Controls.m_MovingLabel->hide();
m_View->m_Controls.m_UseMaskingCB->hide();
m_View->m_Controls.m_OpacityLabel->setEnabled(false);
m_View->m_Controls.m_OpacitySlider->setEnabled(false);
m_View->m_Controls.label->setEnabled(false);
m_View->m_Controls.label_2->setEnabled(false);
m_View->m_Controls.m_ShowRedGreenValues->setEnabled(false);
m_View->m_Controls.m_SwitchImages->hide();
}
}
else
{
m_View->m_Controls.m_StatusLabel->hide();
bool foundFixedImage = false;
mitk::DataNode::Pointer fixedNode;
// iterate selection
for (IStructuredSelection::iterator i = m_View->m_CurrentSelection->Begin();
i != m_View->m_CurrentSelection->End(); ++i)
{
// extract datatree node
if (mitk::DataNodeObject::Pointer nodeObj = i->Cast<mitk::DataNodeObject>())
{
mitk::DataNode::Pointer node = nodeObj->GetDataNode();
// only look at interesting types
if(QString("Image").compare(node->GetData()->GetNameOfClass())==0)
{
if (dynamic_cast<mitk::Image*>(node->GetData())->GetDimension() == 4)
{
m_View->m_Controls.m_StatusLabel->show();
QMessageBox::information( NULL, "RigidRegistration", "Only 2D or 3D images can be processed.", QMessageBox::Ok );
return;
}
if (foundFixedImage == false)
{
fixedNode = node;
foundFixedImage = true;
}
else
{
// m_View->SetImagesVisible(selection);
m_View->FixedSelected(fixedNode);
m_View->MovingSelected(node);
m_View->m_Controls.m_StatusLabel->hide();
m_View->m_Controls.TextLabelFixed->show();
m_View->m_Controls.m_FixedLabel->show();
m_View->m_Controls.TextLabelMoving->show();
m_View->m_Controls.m_MovingLabel->show();
m_View->m_Controls.m_UseMaskingCB->show();
m_View->m_Controls.m_OpacityLabel->setEnabled(true);
m_View->m_Controls.m_OpacitySlider->setEnabled(true);
m_View->m_Controls.label->setEnabled(true);
m_View->m_Controls.label_2->setEnabled(true);
m_View->m_Controls.m_ShowRedGreenValues->setEnabled(true);
}
}
else
{
m_View->m_Controls.m_StatusLabel->show();
return;
}
}
}
}
}
else if (m_View->m_FixedNode.IsNull() || m_View->m_MovingNode.IsNull())
{
m_View->m_Controls.m_StatusLabel->show();
}
}
void SelectionChanged(IWorkbenchPart::Pointer part, ISelection::ConstPointer selection)
{
// check, if selection comes from datamanager
if (part)
{
QString partname(part->GetPartName().c_str());
if(partname.compare("Data Manager")==0)
{
// apply selection
DoSelectionChanged(selection);
}
}
}
QmitkRigidRegistrationView* m_View;
};
QmitkRigidRegistrationView::QmitkRigidRegistrationView(QObject * /*parent*/, const char * /*name*/)
: QmitkFunctionality(), m_MultiWidget(NULL), m_MovingNode(NULL), m_MovingMaskNode(NULL), m_FixedNode(NULL), m_FixedMaskNode(NULL),
m_ShowRedGreen(false), m_Opacity(0.5), m_OriginalOpacity(1.0), m_Deactivated(false),m_FixedDimension(0), m_MovingDimension(0)
{
m_TranslateSliderPos[0] = 0;
m_TranslateSliderPos[1] = 0;
m_TranslateSliderPos[2] = 0;
m_RotateSliderPos[0] = 0;
m_RotateSliderPos[1] = 0;
m_RotateSliderPos[2] = 0;
m_ScaleSliderPos[0] = 0;
m_ScaleSliderPos[1] = 0;
m_ScaleSliderPos[2] = 0;
translationParams = new int[3];
rotationParams = new int[3];
scalingParams = new int[3];
m_TimeStepperAdapter = NULL;
this->GetDataStorage()->RemoveNodeEvent.AddListener(mitk::MessageDelegate1<QmitkRigidRegistrationView,
const mitk::DataNode*> ( this, &QmitkRigidRegistrationView::DataNodeHasBeenRemoved ));
}
QmitkRigidRegistrationView::~QmitkRigidRegistrationView()
{
if(m_SelListener.IsNotNull())
{
berry::ISelectionService* s = GetSite()->GetWorkbenchWindow()->GetSelectionService();
if(s)
s->RemovePostSelectionListener(m_SelListener);
m_SelListener = NULL;
}
this->GetDataStorage()->RemoveNodeEvent.RemoveListener(mitk::MessageDelegate1<QmitkRigidRegistrationView,
const mitk::DataNode*> ( this, &QmitkRigidRegistrationView::DataNodeHasBeenRemoved ));
}
void QmitkRigidRegistrationView::CreateQtPartControl(QWidget* parent)
{
m_Controls.setupUi(parent);
m_Controls.m_ManualFrame->hide();
m_Controls.timeSlider->hide();
m_Controls.TextLabelFixed->hide();
m_Controls.m_FixedLabel->hide();
m_Controls.TextLabelMoving->hide();
m_Controls.m_MovingLabel->hide();
//m_Controls.m_UseFixedImageMask->hide();
//m_Controls.m_UseMovingImageMask->hide();
m_Controls.m_UseMaskingCB->hide();
m_Controls.m_OpacityLabel->setEnabled(false);
m_Controls.m_OpacitySlider->setEnabled(false);
m_Controls.label->setEnabled(false);
m_Controls.label_2->setEnabled(false);
m_Controls.m_ShowRedGreenValues->setEnabled(false);
m_Controls.m_SwitchImages->hide();
if (m_Controls.m_RigidTransform->currentIndex() == 1)
{
m_Controls.frame->show();
}
else
{
m_Controls.frame->hide();
}
m_Controls.m_ManualFrame->setEnabled(false);
m_Parent->setEnabled(false);
mitk::NodePredicateAnd::Pointer andPred = // we want binary images in the selectors
mitk::NodePredicateAnd::New(mitk::NodePredicateDataType::New("Image"),
mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true)));
m_Controls.m_FixedImageCB->SetPredicate(andPred);
m_Controls.m_FixedImageCB->SetDataStorage(this->GetDataStorage());
m_Controls.m_FixedImageCB->hide();
m_Controls.m_FixedMaskLB->hide();
m_Controls.m_MovingImageCB->SetPredicate(andPred);
m_Controls.m_MovingImageCB->SetDataStorage(this->GetDataStorage());
m_Controls.m_MovingImageCB->hide();
m_Controls.m_MovingMaskLB->hide();
this->CreateConnections();
this->CheckCalculateEnabled();
}
void QmitkRigidRegistrationView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget)
{
m_Parent->setEnabled(true);
m_MultiWidget = &stdMultiWidget;
m_MultiWidget->SetWidgetPlanesVisibility(true);
}
void QmitkRigidRegistrationView::StdMultiWidgetNotAvailable()
{
m_Parent->setEnabled(false);
m_MultiWidget = NULL;
}
void QmitkRigidRegistrationView::CreateConnections()
{
connect( m_Controls.m_ManualRegistrationCheckbox, SIGNAL(toggled(bool)), this, SLOT(ShowManualRegistrationFrame(bool)));
connect((QObject*)(m_Controls.m_SwitchImages),SIGNAL(clicked()),this,SLOT(SwitchImages()));
connect(m_Controls.m_ShowRedGreenValues, SIGNAL(toggled(bool)), this, SLOT(ShowRedGreen(bool)));
connect(m_Controls.m_ShowContour, SIGNAL(toggled(bool)), this, SLOT(EnableContour(bool)));
//connect(m_Controls.m_UseFixedImageMask, SIGNAL(toggled(bool)), this, SLOT(UseFixedMaskImageChecked(bool)));
//connect(m_Controls.m_UseMovingImageMask, SIGNAL(toggled(bool)), this, SLOT(UseMovingMaskImageChecked(bool)));
connect(m_Controls.m_RigidTransform, SIGNAL(currentChanged(int)), this, SLOT(TabChanged(int)));
connect(m_Controls.m_OpacitySlider, SIGNAL(valueChanged(int)), this, SLOT(OpacityUpdate(int)));
connect(m_Controls.m_ContourSlider, SIGNAL(sliderReleased()), this, SLOT(ShowContour()));
connect(m_Controls.m_CalculateTransformation, SIGNAL(clicked()), this, SLOT(Calculate()));
connect(m_Controls.m_UndoTransformation,SIGNAL(clicked()),this,SLOT(UndoTransformation()));
connect(m_Controls.m_RedoTransformation,SIGNAL(clicked()),this,SLOT(RedoTransformation()));
connect(m_Controls.m_AutomaticTranslation,SIGNAL(clicked()),this,SLOT(AlignCenters()));
connect(m_Controls.m_StopOptimization,SIGNAL(clicked()), this , SLOT(StopOptimizationClicked()));
connect(m_Controls.m_XTransSlider, SIGNAL(valueChanged(int)), this, SLOT(xTrans_valueChanged(int)));
connect(m_Controls.m_YTransSlider, SIGNAL(valueChanged(int)), this, SLOT(yTrans_valueChanged(int)));
connect(m_Controls.m_ZTransSlider, SIGNAL(valueChanged(int)), this, SLOT(zTrans_valueChanged(int)));
connect(m_Controls.m_XRotSlider, SIGNAL(valueChanged(int)), this, SLOT(xRot_valueChanged(int)));
connect(m_Controls.m_YRotSlider, SIGNAL(valueChanged(int)), this, SLOT(yRot_valueChanged(int)));
connect(m_Controls.m_ZRotSlider, SIGNAL(valueChanged(int)), this, SLOT(zRot_valueChanged(int)));
connect(m_Controls.m_XScaleSlider, SIGNAL(valueChanged(int)), this, SLOT(xScale_valueChanged(int)));
connect(m_Controls.m_YScaleSlider, SIGNAL(valueChanged(int)), this, SLOT(yScale_valueChanged(int)));
connect(m_Controls.m_ZScaleSlider, SIGNAL(valueChanged(int)), this, SLOT(zScale_valueChanged(int)));
connect(m_Controls.m_LoadRigidRegistrationParameter, SIGNAL(clicked()), m_Controls.qmitkRigidRegistrationSelector1, SLOT(LoadRigidRegistrationParameter()));
connect(m_Controls.m_SaveRigidRegistrationParameter, SIGNAL(clicked()), m_Controls.qmitkRigidRegistrationSelector1, SLOT(SaveRigidRegistrationParameter()));
connect(m_Controls.m_LoadRigidRegistrationTestParameter, SIGNAL(clicked()), m_Controls.qmitkRigidRegistrationSelector1, SLOT(LoadRigidRegistrationTestParameter()));
connect(m_Controls.m_SaveRigidRegistrationTestParameter, SIGNAL(clicked()), m_Controls.qmitkRigidRegistrationSelector1, SLOT(SaveRigidRegistrationTestParameter()));
connect(m_Controls.qmitkRigidRegistrationSelector1,SIGNAL(OptimizerChanged(double)),this,SLOT(SetOptimizerValue( double )));
connect(m_Controls.qmitkRigidRegistrationSelector1,SIGNAL(TransformChanged()),this,SLOT(CheckCalculateEnabled()));
connect(m_Controls.qmitkRigidRegistrationSelector1,SIGNAL(AddNewTransformationToUndoList()),this,SLOT(AddNewTransformationToUndoList()));
connect(m_Controls.m_UseMaskingCB, SIGNAL(stateChanged(int)),this,SLOT(OnUseMaskingChanged(int)));
connect(m_Controls.m_FixedImageCB, SIGNAL(OnSelectionChanged(const mitk::DataNode*)),this,SLOT(OnFixedMaskImageChanged(const mitk::DataNode*)));
connect(m_Controls.m_MovingImageCB, SIGNAL(OnSelectionChanged(const mitk::DataNode*)),this,SLOT(OnMovingMaskImageChanged(const mitk::DataNode*)));
}
void QmitkRigidRegistrationView::Activated()
{
m_Deactivated = false;
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
QmitkFunctionality::Activated();
if (m_SelListener.IsNull())
{
m_SelListener = berry::ISelectionListener::Pointer(new SelListenerRigidRegistration(this));
this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->AddPostSelectionListener(/*"org.mitk.views.datamanager",*/ m_SelListener);
berry::ISelection::ConstPointer sel(
this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->GetSelection("org.mitk.views.datamanager"));
m_CurrentSelection = sel.Cast<const IStructuredSelection>();
m_SelListener.Cast<SelListenerRigidRegistration>()->DoSelectionChanged(sel);
}
this->OpacityUpdate(m_Controls.m_OpacitySlider->value());
this->ShowRedGreen(m_Controls.m_ShowRedGreenValues->isChecked());
this->ClearTransformationLists();
this->CheckCalculateEnabled();
/*
m_Deactivated = false;
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
QmitkFunctionality::Activated();
if (m_SelListener.IsNull())
{
m_SelListener = berry::ISelectionListener::Pointer(new SelListenerRigidRegistration(this));
this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->AddPostSelectionListener(/ *"org.mitk.views.datamanager",* / m_SelListener);
berry::ISelection::ConstPointer sel(
this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->GetSelection("org.mitk.views.datamanager"));
m_CurrentSelection = sel.Cast<const IStructuredSelection>();
m_SelListener.Cast<SelListenerRigidRegistration>()->DoSelectionChanged(sel);
}
this->OpacityUpdate(m_Controls.m_OpacitySlider->value());
this->ShowRedGreen(m_Controls.m_ShowRedGreenValues->isChecked());
this->ClearTransformationLists();
this->CheckCalculateEnabled();*/
}
void QmitkRigidRegistrationView::Visible()
{
/*
m_Deactivated = false;
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
QmitkFunctionality::Activated();
if (m_SelListener.IsNull())
{
m_SelListener = berry::ISelectionListener::Pointer(new SelListenerRigidRegistration(this));
this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->AddPostSelectionListener("org.mitk.views.datamanager", m_SelListener);
berry::ISelection::ConstPointer sel(
this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->GetSelection("org.mitk.views.datamanager"));
m_CurrentSelection = sel.Cast<const IStructuredSelection>();
m_SelListener.Cast<SelListenerRigidRegistration>()->DoSelectionChanged(sel);
}
this->OpacityUpdate(m_Controls.m_OpacitySlider->value());
this->ShowRedGreen(m_Controls.m_ShowRedGreenValues->isChecked());
this->ClearTransformationLists();
this->CheckCalculateEnabled();*/
}
void QmitkRigidRegistrationView::Deactivated()
{
m_Deactivated = true;
this->SetImageColor(false);
if (m_FixedNode.IsNotNull())
m_FixedNode->SetOpacity(1.0);
m_FixedNode = NULL;
m_MovingNode = NULL;
this->ClearTransformationLists();
berry::ISelectionService* s = GetSite()->GetWorkbenchWindow()->GetSelectionService();
if(s)
s->RemovePostSelectionListener(m_SelListener);
m_SelListener = NULL;
/*
m_Deactivated = true;
this->SetImageColor(false);
m_FixedNode = NULL;
m_MovingNode = NULL;
this->ClearTransformationLists();
berry::ISelectionService* s = GetSite()->GetWorkbenchWindow()->GetSelectionService();
if(s)
s->RemovePostSelectionListener(m_SelListener);
m_SelListener = NULL;
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
QmitkFunctionality::Deactivated();*/
}
void QmitkRigidRegistrationView::Hidden()
{
/*m_Deactivated = true;
this->SetImageColor(false);
m_FixedNode = NULL;
m_MovingNode = NULL;
this->ClearTransformationLists();
berry::ISelectionService* s = GetSite()->GetWorkbenchWindow()->GetSelectionService();
if(s)
s->RemovePostSelectionListener(m_SelListener);
m_SelListener = NULL;
//mitk::RenderingManager::GetInstance()->RequestUpdateAll();
//QmitkFunctionality::Deactivated();*/
}
void QmitkRigidRegistrationView::DataNodeHasBeenRemoved(const mitk::DataNode* node)
{
if(node == m_FixedNode || node == m_MovingNode)
{
m_Controls.m_StatusLabel->show();
m_Controls.TextLabelFixed->hide();
m_Controls.m_FixedLabel->hide();
m_Controls.TextLabelMoving->hide();
m_Controls.m_MovingLabel->hide();
m_Controls.m_OpacityLabel->setEnabled(false);
m_Controls.m_OpacitySlider->setEnabled(false);
m_Controls.label->setEnabled(false);
m_Controls.label_2->setEnabled(false);
m_Controls.m_ShowRedGreenValues->setEnabled(false);
m_Controls.m_SwitchImages->hide();
}
else if(node == m_ContourHelperNode)
{
// can this cause a memory leak?
m_ContourHelperNode = NULL;
}
}
void QmitkRigidRegistrationView::FixedSelected(mitk::DataNode::Pointer fixedImage)
{
if (m_FixedNode.IsNotNull())
{
this->SetImageColor(false);
m_FixedNode->SetOpacity(1.0);
}
m_FixedNode = fixedImage;
if (m_FixedNode.IsNotNull())
{
m_FixedNode->SetOpacity(0.5);
m_FixedNode->SetVisibility(true);
m_Controls.TextLabelFixed->setText(QString::fromStdString(m_FixedNode->GetName()));
m_Controls.m_FixedLabel->show();
m_Controls.TextLabelFixed->show();
m_Controls.m_SwitchImages->show();
mitk::ColorProperty::Pointer colorProperty;
colorProperty = dynamic_cast<mitk::ColorProperty*>(m_FixedNode->GetProperty("color"));
if ( colorProperty.IsNotNull() )
{
m_FixedColor = colorProperty->GetColor();
}
this->SetImageColor(m_ShowRedGreen);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
if (dynamic_cast<mitk::Image*>(m_FixedNode->GetData()))
{
m_FixedDimension = dynamic_cast<mitk::Image*>(m_FixedNode->GetData())->GetDimension();
m_Controls.qmitkRigidRegistrationSelector1->SetFixedDimension(m_FixedDimension);
m_Controls.qmitkRigidRegistrationSelector1->SetFixedNode(m_FixedNode);
}
// what's about masking?
m_Controls.m_UseMaskingCB->show();
// Modify slider range
mitk::Image::Pointer image = dynamic_cast<mitk::Image*>(m_FixedNode->GetData());
int min = (int)image->GetStatistics()->GetScalarValueMin();
int max = (int)image->GetStatistics()->GetScalarValueMax();
m_Controls.m_ContourSlider->setRange(min, max);
// Set slider to a default value
int avg = (min+max) / 2;
m_Controls.m_ContourSlider->setSliderPosition(avg);
m_Controls.m_ThresholdLabel->setText(QString::number(avg));
}
else
{
m_Controls.m_FixedLabel->hide();
m_Controls.TextLabelFixed->hide();
m_Controls.m_SwitchImages->hide();
}
this->CheckCalculateEnabled();
if(this->GetActiveStdMultiWidget())
{
m_TimeStepperAdapter = new QmitkStepperAdapter((QObject*) m_Controls.timeSlider, m_MultiWidget->GetTimeNavigationController()->GetTime(), "sliceNavigatorTimeFromRigidRegistration");
connect( m_TimeStepperAdapter, SIGNAL( Refetch() ), this, SLOT( UpdateTimestep() ) );
}
}
void QmitkRigidRegistrationView::MovingSelected(mitk::DataNode::Pointer movingImage)
{
if (m_MovingNode.IsNotNull())
{
m_MovingNode->SetOpacity(m_OriginalOpacity);
if (m_FixedNode == m_MovingNode)
m_FixedNode->SetOpacity(0.5);
this->SetImageColor(false);
}
m_MovingNode = movingImage;
if (m_MovingNode.IsNotNull())
{
m_MovingNode->SetVisibility(true);
m_Controls.TextLabelMoving->setText(QString::fromStdString(m_MovingNode->GetName()));
m_Controls.m_MovingLabel->show();
m_Controls.TextLabelMoving->show();
mitk::ColorProperty::Pointer colorProperty;
colorProperty = dynamic_cast<mitk::ColorProperty*>(m_MovingNode->GetProperty("color"));
if ( colorProperty.IsNotNull() )
{
m_MovingColor = colorProperty->GetColor();
}
this->SetImageColor(m_ShowRedGreen);
m_MovingNode->GetFloatProperty("opacity", m_OriginalOpacity);
this->OpacityUpdate(m_Opacity);
// what's about masking?
m_Controls.m_UseMaskingCB->show();
}
else
{
m_Controls.m_MovingLabel->hide();
m_Controls.TextLabelMoving->hide();
m_Controls.m_UseMaskingCB->hide();
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
this->MovingImageChanged();
this->CheckCalculateEnabled();
}
bool QmitkRigidRegistrationView::CheckCalculate()
{
if(m_MovingNode==m_FixedNode)
return false;
return true;
}
void QmitkRigidRegistrationView::AddNewTransformationToUndoList()
{
mitk::BaseData::Pointer movingData = m_MovingNode->GetData();
m_UndoGeometryList.push_back(static_cast<mitk::Geometry3D *>(movingData->GetGeometry()->Clone().GetPointer()));
GeometryMapType childGeometries = GeometryMapType();
if(m_MovingMaskNode.IsNotNull())
{
childGeometries.insert(std::pair<mitk::DataNode::Pointer, mitk::Geometry3D::Pointer>(m_MovingMaskNode,
static_cast<mitk::Geometry3D *>(m_MovingMaskNode->GetData()->GetGeometry()->Clone().GetPointer())));
}
mitk::DataStorage::SetOfObjects::ConstPointer children = this->GetDataStorage()->GetDerivations(m_MovingNode);
if(children.IsNotNull() && children->Size() != 0)
{
unsigned long size;
size = children->Size();
for (unsigned long i = 0; i < size; ++i)
{
childGeometries.insert(std::pair<mitk::DataNode::Pointer, mitk::Geometry3D::Pointer>(children->GetElement(i),
static_cast<mitk::Geometry3D *>(children->GetElement(i)->GetData()->GetGeometry()->Clone().GetPointer())));
}
}
m_UndoChildGeometryList.push_back(childGeometries);
m_RedoGeometryList.clear();
m_RedoChildGeometryList.clear();
this->SetUndoEnabled(true);
this->SetRedoEnabled(false);
}
void QmitkRigidRegistrationView::UndoTransformation()
{
if(!m_UndoGeometryList.empty())
{
mitk::BaseData::Pointer movingData = m_MovingNode->GetData();
m_RedoGeometryList.push_back(static_cast<mitk::Geometry3D *>(movingData->GetGeometry(0)->Clone().GetPointer()));
unsigned long size = 0;
GeometryMapType childGeometries = GeometryMapType();
if(m_MovingMaskNode.IsNotNull())
{
++size;
}
mitk::DataStorage::SetOfObjects::ConstPointer children = this->GetDataStorage()->GetDerivations(m_MovingNode);
size += children->Size();
for (unsigned long i = 0; i < size; ++i)
{
if(i==0)
{
childGeometries.insert(std::pair<mitk::DataNode::Pointer, mitk::Geometry3D::Pointer>(m_MovingMaskNode,
static_cast<mitk::Geometry3D *>(m_MovingMaskNode->GetData()->GetGeometry()->Clone().GetPointer())));
}
else
{
childGeometries.insert(std::pair<mitk::DataNode::Pointer, mitk::Geometry3D::Pointer>(children->GetElement(i),
static_cast<mitk::Geometry3D *>(children->GetElement(i)->GetData()->GetGeometry()->Clone().GetPointer())));
}
}
m_RedoChildGeometryList.push_back(childGeometries);
movingData->SetGeometry(m_UndoGeometryList.back());
m_UndoGeometryList.pop_back();
GeometryMapType oldChildGeometries;
oldChildGeometries = m_UndoChildGeometryList.back();
m_UndoChildGeometryList.pop_back();
GeometryMapType::iterator iter;
for (unsigned long j = 0; j < size; ++j)
{
if(j == 0) // we have put the geometry for the moving mask at position one
{
iter = oldChildGeometries.find(m_MovingMaskNode);
mitk::Geometry3D* geo = static_cast<mitk::Geometry3D*>((*iter).second);
m_MovingMaskNode->GetData()->SetGeometry(geo);
m_MovingMaskNode->GetData()->GetTimeGeometry()->Update();
}
else
{
iter = oldChildGeometries.find(children->GetElement(j));
children->GetElement(j)->GetData()->SetGeometry((*iter).second);
}
}
//\FIXME when geometry is substituted the matrix referenced by the actor created by the mapper
//is still pointing to the old one. Workaround: delete mapper
//m_MovingNode->SetMapper(1, NULL);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
this->SetRedoEnabled(true);
}
if(!m_UndoGeometryList.empty())
{
this->SetUndoEnabled(true);
}
else
{
this->SetUndoEnabled(false);
}
this->CheckCalculateEnabled();
}
void QmitkRigidRegistrationView::RedoTransformation()
{
if(!m_RedoGeometryList.empty())
{
mitk::BaseData::Pointer movingData = m_MovingNode->GetData();
m_UndoGeometryList.push_back(static_cast<mitk::Geometry3D *>(movingData->GetGeometry(0)->Clone().GetPointer()));
unsigned long size = 0;
GeometryMapType childGeometries = GeometryMapType();
if(m_MovingMaskNode.IsNotNull())
{
++size;
}
mitk::DataStorage::SetOfObjects::ConstPointer children = this->GetDataStorage()->GetDerivations(m_MovingNode);
size += children->Size();
for (unsigned long i = 0; i < size; ++i)
{
if(i == 0)
{
childGeometries.insert(std::pair<mitk::DataNode::Pointer, mitk::Geometry3D::Pointer>(m_MovingMaskNode,
static_cast<mitk::Geometry3D *>(m_MovingMaskNode->GetData()->GetGeometry()->Clone().GetPointer())));
}
else
{
childGeometries.insert(std::pair<mitk::DataNode::Pointer, mitk::Geometry3D::Pointer>(children->GetElement(i),
static_cast<mitk::Geometry3D *>(children->GetElement(i)->GetData()->GetGeometry()->Clone().GetPointer())));
}
}
m_UndoChildGeometryList.push_back(childGeometries);
movingData->SetGeometry(m_RedoGeometryList.back());
m_RedoGeometryList.pop_back();
GeometryMapType oldChildGeometries;
oldChildGeometries = m_RedoChildGeometryList.back();
m_RedoChildGeometryList.pop_back();
GeometryMapType::iterator iter;
for (unsigned long j = 0; j < size; ++j)
{
if(j == 0)
{
iter = oldChildGeometries.find(m_MovingMaskNode);
m_MovingMaskNode->GetData()->SetGeometry((*iter).second);
}
else
{
iter = oldChildGeometries.find(children->GetElement(j));
children->GetElement(j)->GetData()->SetGeometry((*iter).second);
}
}
movingData->GetTimeGeometry()->Update();
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
this->SetUndoEnabled(true);
}
if(!m_RedoGeometryList.empty())
{
this->SetRedoEnabled(true);
}
else
{
this->SetRedoEnabled(false);
}
}
void QmitkRigidRegistrationView::ShowRedGreen(bool redGreen)
{
m_ShowRedGreen = redGreen;
this->SetImageColor(m_ShowRedGreen);
}
void QmitkRigidRegistrationView::EnableContour(bool show)
{
if(show)
ShowContour();
// Can happen when the m_ContourHelperNode was deleted before and now the show contour checkbox is turned off
if(m_ContourHelperNode.IsNull())
return;
m_Controls.m_ContourSlider->setEnabled(show);
m_ContourHelperNode->SetProperty("visible", mitk::BoolProperty::New(show));
mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll();
}
void QmitkRigidRegistrationView::ShowContour()
{
int threshold = m_Controls.m_ContourSlider->value();
bool show = m_Controls.m_ShowContour->isChecked();
if(m_FixedNode.IsNull() || !show)
return;
// Update the label next to the slider
m_Controls.m_ThresholdLabel->setText(QString::number(threshold));
mitk::Image::Pointer image = dynamic_cast<mitk::Image *>(m_FixedNode->GetData());
typedef itk::Image<float,3> FloatImageType;
typedef itk::Image<short,3> ShortImageType;
// Create a binary image using the given treshold
typedef itk::BinaryThresholdImageFilter<FloatImageType, ShortImageType> ThresholdFilterType;
FloatImageType::Pointer floatImage = FloatImageType::New();
mitk::CastToItkImage(image, floatImage);
ThresholdFilterType::Pointer thresholdFilter = ThresholdFilterType::New();
thresholdFilter->SetInput(floatImage);
thresholdFilter->SetLowerThreshold(threshold);
thresholdFilter->SetUpperThreshold((int)image->GetStatistics()->GetScalarValueMax());
thresholdFilter->SetInsideValue(1);
thresholdFilter->SetOutsideValue(0);
thresholdFilter->Update();
ShortImageType::Pointer binaryImage = thresholdFilter->GetOutput();
mitk::Image::Pointer mitkBinaryImage = mitk::Image::New();
mitk::CastToMitkImage(binaryImage, mitkBinaryImage);
// Create a contour from the binary image
mitk::ManualSegmentationToSurfaceFilter::Pointer surfaceFilter = mitk::ManualSegmentationToSurfaceFilter::New();
surfaceFilter->SetInput( mitkBinaryImage );
surfaceFilter->SetThreshold( 1 ); //expects binary image with zeros and ones
surfaceFilter->SetUseGaussianImageSmooth(false); // apply gaussian to thresholded image ?
surfaceFilter->SetMedianFilter3D(false); // apply median to segmentation before marching cubes ?
surfaceFilter->SetDecimate( mitk::ImageToSurfaceFilter::NoDecimation );
surfaceFilter->UpdateLargestPossibleRegion();
// calculate normals for nicer display
mitk::Surface::Pointer surface = surfaceFilter->GetOutput();
if(m_ContourHelperNode.IsNull())
{
m_ContourHelperNode = mitk::DataNode::New();
m_ContourHelperNode->SetData(surface);
m_ContourHelperNode->SetProperty("opacity", mitk::FloatProperty::New(1.0) );
m_ContourHelperNode->SetProperty("line width", mitk::IntProperty::New(2) );
m_ContourHelperNode->SetProperty("scalar visibility", mitk::BoolProperty::New(false) );
m_ContourHelperNode->SetProperty( "name", mitk::StringProperty::New("surface") );
m_ContourHelperNode->SetProperty("color", mitk::ColorProperty::New(1.0, 0.0, 0.0));
m_ContourHelperNode->SetBoolProperty("helper object", true);
this->GetDataStorage()->Add(m_ContourHelperNode);
}
else
{
m_ContourHelperNode->SetData(surface);
}
mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll();
}
void QmitkRigidRegistrationView::SetImageColor(bool redGreen)
{
if (!redGreen && m_FixedNode.IsNotNull())
{
m_FixedNode->SetColor(m_FixedColor);
}
if (!redGreen && m_MovingNode.IsNotNull())
{
m_MovingNode->SetColor(m_MovingColor);
}
if (redGreen && m_FixedNode.IsNotNull())
{
m_FixedNode->SetColor(1.0f, 0.0f, 0.0f);
}
if (redGreen && m_MovingNode.IsNotNull())
{
m_MovingNode->SetColor(0.0f, 1.0f, 0.0f);
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkRigidRegistrationView::OpacityUpdate(float opacity)
{
m_Opacity = opacity;
if (m_MovingNode.IsNotNull())
{
m_MovingNode->SetOpacity(m_Opacity);
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkRigidRegistrationView::OpacityUpdate(int opacity)
{
float fValue = ((float)opacity)/100.0f;
this->OpacityUpdate(fValue);
}
void QmitkRigidRegistrationView::ClearTransformationLists()
{
this->SetUndoEnabled(false);
this->SetRedoEnabled(false);
m_UndoGeometryList.clear();
m_UndoChildGeometryList.clear();
m_RedoGeometryList.clear();
m_RedoChildGeometryList.clear();
}
void QmitkRigidRegistrationView::Translate(int* translateVector)
{
if (m_MovingNode.IsNotNull())
{
mitk::Vector3D translateVec;
translateVec[0] = translateVector[0] - m_TranslateSliderPos[0];
translateVec[1] = translateVector[1] - m_TranslateSliderPos[1];
translateVec[2] = translateVector[2] - m_TranslateSliderPos[2];
m_TranslateSliderPos[0] = translateVector[0];
m_TranslateSliderPos[1] = translateVector[1];
m_TranslateSliderPos[2] = translateVector[2];
vtkMatrix4x4* translationMatrix = vtkMatrix4x4::New();
translationMatrix->Identity();
double (*transMatrix)[4] = translationMatrix->Element;
transMatrix[0][3] = -translateVec[0];
transMatrix[1][3] = -translateVec[1];
transMatrix[2][3] = -translateVec[2];
translationMatrix->Invert();
m_MovingNode->GetData()->GetGeometry()->Compose( translationMatrix );
m_MovingNode->GetData()->Modified();
mitk::DataStorage::SetOfObjects::ConstPointer children = this->GetDataStorage()->GetDerivations(m_MovingNode);
unsigned long size;
size = children->Size();
mitk::DataNode::Pointer childNode;
for (unsigned long i = 0; i < size; ++i)
{
childNode = children->GetElement(i);
childNode->GetData()->GetGeometry()->Compose( translationMatrix );
childNode->GetData()->Modified();
}
m_RedoGeometryList.clear();
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
void QmitkRigidRegistrationView::Rotate(int* rotateVector)
{
if (m_MovingNode.IsNotNull())
{
mitk::Vector3D rotateVec;
rotateVec[0] = rotateVector[0] - m_RotateSliderPos[0];
rotateVec[1] = rotateVector[1] - m_RotateSliderPos[1];
rotateVec[2] = rotateVector[2] - m_RotateSliderPos[2];
m_RotateSliderPos[0] = rotateVector[0];
m_RotateSliderPos[1] = rotateVector[1];
m_RotateSliderPos[2] = rotateVector[2];
vtkMatrix4x4* rotationMatrix = vtkMatrix4x4::New();
vtkMatrix4x4* translationMatrix = vtkMatrix4x4::New();
rotationMatrix->Identity();
translationMatrix->Identity();
double (*rotMatrix)[4] = rotationMatrix->Element;
double (*transMatrix)[4] = translationMatrix->Element;
mitk::Point3D centerBB = m_MovingNode->GetData()->GetGeometry()->GetCenter();
transMatrix[0][3] = centerBB[0];
transMatrix[1][3] = centerBB[1];
transMatrix[2][3] = centerBB[2];
translationMatrix->Invert();
m_MovingNode->GetData()->GetGeometry()->Compose( translationMatrix );
mitk::DataStorage::SetOfObjects::ConstPointer children = this->GetDataStorage()->GetDerivations(m_MovingNode);
unsigned long size;
size = children->Size();
mitk::DataNode::Pointer childNode;
for (unsigned long i = 0; i < size; ++i)
{
childNode = children->GetElement(i);
childNode->GetData()->GetGeometry()->Compose( translationMatrix );
childNode->GetData()->Modified();
}
double radianX = rotateVec[0] * vnl_math::pi / 180;
double radianY = rotateVec[1] * vnl_math::pi / 180;
double radianZ = rotateVec[2] * vnl_math::pi / 180;
if ( rotateVec[0] != 0 )
{
rotMatrix[1][1] = cos( radianX );
rotMatrix[1][2] = -sin( radianX );
rotMatrix[2][1] = sin( radianX );
rotMatrix[2][2] = cos( radianX );
}
else if ( rotateVec[1] != 0 )
{
rotMatrix[0][0] = cos( radianY );
rotMatrix[0][2] = sin( radianY );
rotMatrix[2][0] = -sin( radianY );
rotMatrix[2][2] = cos( radianY );
}
else if ( rotateVec[2] != 0 )
{
rotMatrix[0][0] = cos( radianZ );
rotMatrix[0][1] = -sin( radianZ );
rotMatrix[1][0] = sin( radianZ );
rotMatrix[1][1] = cos( radianZ );
}
m_MovingNode->GetData()->GetGeometry()->Compose( rotationMatrix );
for (unsigned long i = 0; i < size; ++i)
{
childNode = children->GetElement(i);
childNode->GetData()->GetGeometry()->Compose( rotationMatrix );
childNode->GetData()->Modified();
}
translationMatrix->Invert();
m_MovingNode->GetData()->GetGeometry()->Compose( translationMatrix );
for (unsigned long i = 0; i < size; ++i)
{
childNode = children->GetElement(i);
childNode->GetData()->GetGeometry()->Compose( rotationMatrix );
childNode->GetData()->Modified();
}
m_MovingNode->GetData()->Modified();
m_RedoGeometryList.clear();
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
void QmitkRigidRegistrationView::Scale(int* scaleVector)
{
if (m_MovingNode.IsNotNull())
{
mitk::Vector3D scaleVec;
scaleVec[0] = scaleVector[0] - m_ScaleSliderPos[0];
scaleVec[1] = scaleVector[1] - m_ScaleSliderPos[1];
scaleVec[2] = scaleVector[2] - m_ScaleSliderPos[2];
m_ScaleSliderPos[0] = scaleVector[0];
m_ScaleSliderPos[1] = scaleVector[1];
m_ScaleSliderPos[2] = scaleVector[2];
vtkMatrix4x4* scalingMatrix = vtkMatrix4x4::New();
scalingMatrix->Identity();
double (*scaleMatrix)[4] = scalingMatrix->Element;
if (scaleVec[0] >= 0)
{
for(int i = 0; i<scaleVec[0]; i++)
{
scaleMatrix[0][0] *= 0.95;
}
}
else
{
for(int i = 0; i<-scaleVec[0]; i++)
{
scaleMatrix[0][0] *= 1/0.95;
}
}
if (scaleVec[1] >= 0)
{
for(int i = 0; i<scaleVec[1]; i++)
{
scaleMatrix[1][1] *= 0.95;
}
}
else
{
for(int i = 0; i<-scaleVec[1]; i++)
{
scaleMatrix[1][1] *= 1/0.95;
}
}
if (scaleVec[2] >= 0)
{
for(int i = 0; i<scaleVec[2]; i++)
{
scaleMatrix[2][2] *= 0.95;
}
}
else
{
for(int i = 0; i<-scaleVec[2]; i++)
{
scaleMatrix[2][2] *= 1/0.95;
}
}
scalingMatrix->Invert();
m_MovingNode->GetData()->GetGeometry()->Compose( scalingMatrix );
m_MovingNode->GetData()->Modified();
mitk::DataStorage::SetOfObjects::ConstPointer children = this->GetDataStorage()->GetDerivations(m_MovingNode);
unsigned long size;
size = children->Size();
mitk::DataNode::Pointer childNode;
for (unsigned long i = 0; i < size; ++i)
{
childNode = children->GetElement(i);
childNode->GetData()->GetGeometry()->Compose( scalingMatrix );
childNode->GetData()->Modified();
}
m_RedoGeometryList.clear();
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
void QmitkRigidRegistrationView::AlignCenters()
{
if (m_FixedNode.IsNotNull() && m_MovingNode.IsNotNull())
{
mitk::Point3D fixedPoint = m_FixedNode->GetData()->GetGeometry()->GetCenter();
mitk::Point3D movingPoint = m_MovingNode->GetData()->GetGeometry()->GetCenter();
mitk::Vector3D translateVec;
translateVec = fixedPoint - movingPoint;
m_Controls.m_XTransSlider->setValue((int)m_Controls.m_XTransSlider->value() + (int)translateVec[0]);
m_Controls.m_YTransSlider->setValue((int)m_Controls.m_YTransSlider->value() + (int)translateVec[1]);
m_Controls.m_ZTransSlider->setValue((int)m_Controls.m_ZTransSlider->value() + (int)translateVec[2]);
}
}
void QmitkRigidRegistrationView::SetUndoEnabled( bool enable )
{
m_Controls.m_UndoTransformation->setEnabled(enable);
}
void QmitkRigidRegistrationView::SetRedoEnabled( bool enable )
{
m_Controls.m_RedoTransformation->setEnabled(enable);
}
void QmitkRigidRegistrationView::CheckCalculateEnabled()
{
if (m_FixedNode.IsNotNull() && m_MovingNode.IsNotNull())
{
m_Controls.m_ManualFrame->setEnabled(true);
m_Controls.m_CalculateTransformation->setEnabled(true);
if ( (m_FixedDimension != m_MovingDimension && std::max<int>(m_FixedDimension, m_MovingDimension) != 4) || m_FixedDimension < 2 /*|| m_FixedDimension > 3*/)
{
m_Controls.m_CalculateTransformation->setEnabled(false);
}
else if (m_Controls.qmitkRigidRegistrationSelector1->GetSelectedTransform() < 5 && (m_FixedDimension < 2) /*|| m_FixedDimension > 3)*/)
{
m_Controls.m_CalculateTransformation->setEnabled(false);
}
else if ((m_Controls.qmitkRigidRegistrationSelector1->GetSelectedTransform() > 4 && m_Controls.qmitkRigidRegistrationSelector1->GetSelectedTransform() < 13) && !(m_FixedDimension > 2))
{
m_Controls.m_CalculateTransformation->setEnabled(false);
}
else if (m_Controls.qmitkRigidRegistrationSelector1->GetSelectedTransform() > 12 && m_FixedDimension != 2)
{
m_Controls.m_CalculateTransformation->setEnabled(false);
}
}
else
{
m_Controls.m_CalculateTransformation->setEnabled(false);
m_Controls.m_ManualFrame->setEnabled(false);
}
}
void QmitkRigidRegistrationView::xTrans_valueChanged( int v )
{
if (m_MovingNode.IsNotNull())
{
translationParams[0]=v;
translationParams[1]=m_Controls.m_YTransSlider->value();
translationParams[2]=m_Controls.m_ZTransSlider->value();
Translate(translationParams);
}
else
{
MovingImageChanged();
}
}
void QmitkRigidRegistrationView::yTrans_valueChanged( int v )
{
if (m_MovingNode.IsNotNull())
{
translationParams[0]=m_Controls.m_XTransSlider->value();
translationParams[1]=v;
translationParams[2]=m_Controls.m_ZTransSlider->value();
Translate(translationParams);
}
else
{
MovingImageChanged();
}
}
void QmitkRigidRegistrationView::zTrans_valueChanged( int v )
{
if (m_MovingNode.IsNotNull())
{
translationParams[0]=m_Controls.m_XTransSlider->value();
translationParams[1]=m_Controls.m_YTransSlider->value();
translationParams[2]=v;
Translate(translationParams);
}
else
{
MovingImageChanged();
}
}
void QmitkRigidRegistrationView::xRot_valueChanged( int v )
{
if (m_MovingNode.IsNotNull())
{
rotationParams[0]=v;
rotationParams[1]=m_Controls.m_YRotSlider->value();
rotationParams[2]=m_Controls.m_ZRotSlider->value();
Rotate(rotationParams);
}
else
{
MovingImageChanged();
}
}
void QmitkRigidRegistrationView::yRot_valueChanged( int v )
{
if (m_MovingNode.IsNotNull())
{
rotationParams[0]=m_Controls.m_XRotSlider->value();
rotationParams[1]=v;
rotationParams[2]=m_Controls.m_ZRotSlider->value();
Rotate(rotationParams);
}
else
{
MovingImageChanged();
}
}
void QmitkRigidRegistrationView::zRot_valueChanged( int v )
{
if (m_MovingNode.IsNotNull())
{
rotationParams[0]=m_Controls.m_XRotSlider->value();
rotationParams[1]=m_Controls.m_YRotSlider->value();
rotationParams[2]=v;
Rotate(rotationParams);
}
else
{
MovingImageChanged();
}
}
void QmitkRigidRegistrationView::xScale_valueChanged( int v )
{
if (m_MovingNode.IsNotNull())
{
scalingParams[0]=v;
scalingParams[1]=m_Controls.m_YScaleSlider->value();
scalingParams[2]=m_Controls.m_ZScaleSlider->value();
Scale(scalingParams);
}
else
{
MovingImageChanged();
}
}
void QmitkRigidRegistrationView::yScale_valueChanged( int v )
{
if (m_MovingNode.IsNotNull())
{
scalingParams[0]=m_Controls.m_XScaleSlider->value();
scalingParams[1]=v;
scalingParams[2]=m_Controls.m_ZScaleSlider->value();
Scale(scalingParams);
}
else
{
MovingImageChanged();
}
}
void QmitkRigidRegistrationView::zScale_valueChanged( int v )
{
if (m_MovingNode.IsNotNull())
{
scalingParams[0]=m_Controls.m_XScaleSlider->value();
scalingParams[1]=m_Controls.m_YScaleSlider->value();
scalingParams[2]=v;
Scale(scalingParams);
}
else
{
MovingImageChanged();
}
}
void QmitkRigidRegistrationView::MovingImageChanged()
{
if (dynamic_cast<mitk::Image*>(m_MovingNode->GetData()))
{
m_Controls.m_XTransSlider->setValue(0);
m_Controls.m_YTransSlider->setValue(0);
m_Controls.m_ZTransSlider->setValue(0);
translationParams[0]=0;
translationParams[1]=0;
translationParams[2]=0;
m_Controls.m_XRotSlider->setValue(0);
m_Controls.m_YRotSlider->setValue(0);
m_Controls.m_ZRotSlider->setValue(0);
rotationParams[0]=0;
rotationParams[1]=0;
rotationParams[2]=0;
m_Controls.m_XScaleSlider->setValue(0);
m_Controls.m_YScaleSlider->setValue(0);
m_Controls.m_ZScaleSlider->setValue(0);
scalingParams[0]=0;
scalingParams[1]=0;
scalingParams[2]=0;
m_MovingDimension = dynamic_cast<mitk::Image*>(m_MovingNode->GetData())->GetDimension();
m_Controls.qmitkRigidRegistrationSelector1->SetMovingDimension(m_MovingDimension);
m_Controls.qmitkRigidRegistrationSelector1->SetMovingNode(m_MovingNode);
this->CheckCalculateEnabled();
}
}
void QmitkRigidRegistrationView::Calculate()
{
m_Controls.qmitkRigidRegistrationSelector1->SetFixedNode(m_FixedNode);
m_Controls.qmitkRigidRegistrationSelector1->SetMovingNode(m_MovingNode);
if (m_FixedMaskNode.IsNotNull() && m_Controls.m_UseMaskingCB->isChecked())
{
m_Controls.qmitkRigidRegistrationSelector1->SetFixedMaskNode(m_FixedMaskNode);
}
else
{
m_Controls.qmitkRigidRegistrationSelector1->SetFixedMaskNode(NULL);
}
if (m_MovingMaskNode.IsNotNull() && m_Controls.m_UseMaskingCB->isChecked())
{
m_Controls.qmitkRigidRegistrationSelector1->SetMovingMaskNode(m_MovingMaskNode);
}
else
{
m_Controls.qmitkRigidRegistrationSelector1->SetMovingMaskNode(NULL);
}
m_Controls.frame_2->setEnabled(false);
m_Controls.frame_3->setEnabled(false);
m_Controls.m_CalculateTransformation->setEnabled(false);
m_Controls.m_StopOptimization->setEnabled(true);
m_Controls.qmitkRigidRegistrationSelector1->CalculateTransformation(((QmitkSliderNavigatorWidget*)m_Controls.timeSlider)->GetPos());
m_Controls.m_StopOptimization->setEnabled(false);
m_Controls.frame_2->setEnabled(true);
m_Controls.frame_3->setEnabled(true);
m_Controls.m_CalculateTransformation->setEnabled(true);
m_Controls.qmitkRigidRegistrationSelector1->StopOptimization(false);
}
void QmitkRigidRegistrationView::SetOptimizerValue( double value )
{
m_Controls.m_OptimizerValueLCD->display(value);
}
void QmitkRigidRegistrationView::StopOptimizationClicked()
{
m_Controls.qmitkRigidRegistrationSelector1->StopOptimization(true);
}
void QmitkRigidRegistrationView::UpdateTimestep()
{
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkRigidRegistrationView::ShowManualRegistrationFrame(bool show)
{
if (show)
{
m_Controls.m_ManualFrame->show();
}
else
{
m_Controls.m_ManualFrame->hide();
}
}
void QmitkRigidRegistrationView::SetImagesVisible(berry::ISelection::ConstPointer /*selection*/)
{
if (this->m_CurrentSelection->Size() == 0)
{
// show all images
mitk::DataStorage::SetOfObjects::ConstPointer setOfObjects = this->GetDataStorage()->GetAll();
for (mitk::DataStorage::SetOfObjects::ConstIterator nodeIt = setOfObjects->Begin()
; nodeIt != setOfObjects->End(); ++nodeIt) // for each node
{
- if ( (nodeIt->Value().IsNotNull()) && (nodeIt->Value()->GetProperty("visible")) && dynamic_cast<mitk::Geometry2DData*>(nodeIt->Value()->GetData())==NULL)
+ if ( (nodeIt->Value().IsNotNull()) && (nodeIt->Value()->GetProperty("visible")) && dynamic_cast<mitk::PlaneGeometryData*>(nodeIt->Value()->GetData())==NULL)
{
nodeIt->Value()->SetVisibility(true);
}
}
}
else
{
// hide all images
mitk::DataStorage::SetOfObjects::ConstPointer setOfObjects = this->GetDataStorage()->GetAll();
for (mitk::DataStorage::SetOfObjects::ConstIterator nodeIt = setOfObjects->Begin()
; nodeIt != setOfObjects->End(); ++nodeIt) // for each node
{
- if ( (nodeIt->Value().IsNotNull()) && (nodeIt->Value()->GetProperty("visible")) && dynamic_cast<mitk::Geometry2DData*>(nodeIt->Value()->GetData())==NULL)
+ if ( (nodeIt->Value().IsNotNull()) && (nodeIt->Value()->GetProperty("visible")) && dynamic_cast<mitk::PlaneGeometryData*>(nodeIt->Value()->GetData())==NULL)
{
nodeIt->Value()->SetVisibility(false);
}
}
}
}
void QmitkRigidRegistrationView::TabChanged(int index)
{
if (index == 0)
{
m_Controls.frame->hide();
}
else
{
m_Controls.frame->show();
}
}
void QmitkRigidRegistrationView::SwitchImages()
{
mitk::DataNode::Pointer newMoving = m_FixedNode;
mitk::DataNode::Pointer newFixed = m_MovingNode;
this->FixedSelected(newFixed);
this->MovingSelected(newMoving);
if(m_ContourHelperNode.IsNotNull())
{
// Update the contour
ShowContour();
}
if(m_Controls.m_UseMaskingCB->isChecked())
{
mitk::DataNode::Pointer tempMovingMask = NULL;
mitk::DataNode::Pointer tempFixedMask = NULL;
if(m_FixedMaskNode.IsNotNull()) // it is initialized
{
tempFixedMask = m_Controls.m_FixedImageCB->GetSelectedNode();
}
if(m_MovingMaskNode.IsNotNull()) // it is initialized
{
tempMovingMask = m_Controls.m_MovingImageCB->GetSelectedNode();
}
m_Controls.m_FixedImageCB->SetSelectedNode(tempMovingMask);
m_Controls.m_MovingImageCB->SetSelectedNode(tempFixedMask);
}
}
void QmitkRigidRegistrationView::OnUseMaskingChanged( int state )
{
if(state == Qt::Checked)
{
m_Controls.m_FixedImageCB->show();
m_Controls.m_MovingImageCB->show();
m_Controls.m_MovingMaskLB->show();
m_Controls.m_FixedMaskLB->show();
}
else
{
m_Controls.m_FixedImageCB->hide();
m_Controls.m_MovingImageCB->hide();
m_Controls.m_MovingMaskLB->hide();
m_Controls.m_FixedMaskLB->hide();
m_FixedMaskNode = NULL;
m_MovingMaskNode = NULL;
}
}
void QmitkRigidRegistrationView::OnFixedMaskImageChanged( const mitk::DataNode* node )
{
if(m_Controls.m_UseMaskingCB->isChecked())
m_FixedMaskNode = const_cast<mitk::DataNode*>(node);
else
m_FixedMaskNode = NULL;
}
void QmitkRigidRegistrationView::OnMovingMaskImageChanged( const mitk::DataNode* node )
{
if(m_Controls.m_UseMaskingCB->isChecked())
m_MovingMaskNode = const_cast<mitk::DataNode*>(node);
else
m_MovingMaskNode = NULL;
}
\ No newline at end of file
diff --git a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.cpp b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.cpp
index ce7494dd13..5dcdc18953 100644
--- a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.cpp
+++ b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.cpp
@@ -1,1226 +1,1226 @@
/*===================================================================
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 "mitkProperties.h"
#include "mitkSegTool2D.h"
#include "mitkStatusBar.h"
#include "QmitkStdMultiWidget.h"
#include "QmitkNewSegmentationDialog.h"
#include <QMessageBox>
#include <berryIWorkbenchPage.h>
#include "QmitkSegmentationView.h"
#include "QmitkSegmentationOrganNamesHandling.cpp"
#include <mitkSurfaceToImageFilter.h>
#include "mitkVtkResliceInterpolationProperty.h"
#include "mitkApplicationCursor.h"
#include "mitkSegmentationObjectFactory.h"
#include "mitkPluginActivator.h"
#include "usModuleResource.h"
#include "usModuleResourceStream.h"
//micro service to get the ToolManager instance
#include "mitkToolManagerProvider.h"
const std::string QmitkSegmentationView::VIEW_ID =
"org.mitk.views.segmentation";
// public methods
QmitkSegmentationView::QmitkSegmentationView()
:m_Parent(NULL)
,m_Controls(NULL)
,m_MultiWidget(NULL)
,m_DataSelectionChanged(false)
,m_MouseCursorSet(false)
{
mitk::NodePredicateDataType::Pointer isDwi = mitk::NodePredicateDataType::New("DiffusionImage");
mitk::NodePredicateDataType::Pointer isDti = mitk::NodePredicateDataType::New("TensorImage");
mitk::NodePredicateDataType::Pointer isQbi = mitk::NodePredicateDataType::New("QBallImage");
mitk::NodePredicateOr::Pointer isDiffusionImage = mitk::NodePredicateOr::New(isDwi, isDti);
isDiffusionImage = mitk::NodePredicateOr::New(isDiffusionImage, isQbi);
m_IsOfTypeImagePredicate = mitk::NodePredicateOr::New(isDiffusionImage, mitk::TNodePredicateDataType<mitk::Image>::New());
m_IsBinaryPredicate = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true));
m_IsNotBinaryPredicate = mitk::NodePredicateNot::New( m_IsBinaryPredicate );
m_IsNotABinaryImagePredicate = mitk::NodePredicateAnd::New( m_IsOfTypeImagePredicate, m_IsNotBinaryPredicate );
m_IsABinaryImagePredicate = mitk::NodePredicateAnd::New( m_IsOfTypeImagePredicate, m_IsBinaryPredicate);
}
QmitkSegmentationView::~QmitkSegmentationView()
{
delete m_Controls;
}
void QmitkSegmentationView::NewNodesGenerated()
{
MITK_WARN<<"Use of deprecated function: NewNodesGenerated!! This function is empty and will be removed in the next time!";
}
void QmitkSegmentationView::NewNodeObjectsGenerated(mitk::ToolManager::DataVectorType* nodes)
{
if (!nodes) return;
mitk::ToolManager* toolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager();
if (!toolManager) return;
for (mitk::ToolManager::DataVectorType::iterator iter = nodes->begin(); iter != nodes->end(); ++iter)
{
this->FireNodeSelected( *iter );
// only last iteration meaningful, multiple generated objects are not taken into account here
}
}
void QmitkSegmentationView::Visible()
{
if (m_DataSelectionChanged)
{
this->OnSelectionChanged(this->GetDataManagerSelection());
}
}
void QmitkSegmentationView::Activated()
{
// should be moved to ::BecomesVisible() or similar
if( m_Controls )
{
m_Controls->m_ManualToolSelectionBox2D->setEnabled( true );
m_Controls->m_ManualToolSelectionBox3D->setEnabled( true );
// m_Controls->m_OrganToolSelectionBox->setEnabled( true );
// m_Controls->m_LesionToolSelectionBox->setEnabled( true );
// m_Controls->m_SlicesInterpolator->Enable3DInterpolation( m_Controls->widgetStack->currentWidget() == m_Controls->pageManual );
mitk::DataStorage::SetOfObjects::ConstPointer segmentations = this->GetDefaultDataStorage()->GetSubset( m_IsABinaryImagePredicate );
mitk::DataStorage::SetOfObjects::ConstPointer image = this->GetDefaultDataStorage()->GetSubset( m_IsNotABinaryImagePredicate );
if (!image->empty()) {
OnSelectionChanged(*image->begin());
}
for ( mitk::DataStorage::SetOfObjects::const_iterator iter = segmentations->begin();
iter != segmentations->end();
++iter)
{
mitk::DataNode* node = *iter;
itk::SimpleMemberCommand<QmitkSegmentationView>::Pointer command = itk::SimpleMemberCommand<QmitkSegmentationView>::New();
command->SetCallbackFunction(this, &QmitkSegmentationView::OnWorkingNodeVisibilityChanged);
m_WorkingDataObserverTags.insert( std::pair<mitk::DataNode*, unsigned long>( node, node->GetProperty("visible")->AddObserver( itk::ModifiedEvent(), command ) ) );
itk::SimpleMemberCommand<QmitkSegmentationView>::Pointer command2 = itk::SimpleMemberCommand<QmitkSegmentationView>::New();
command2->SetCallbackFunction(this, &QmitkSegmentationView::OnBinaryPropertyChanged);
m_BinaryPropertyObserverTags.insert( std::pair<mitk::DataNode*, unsigned long>( node, node->GetProperty("binary")->AddObserver( itk::ModifiedEvent(), command2 ) ) );
}
}
itk::SimpleMemberCommand<QmitkSegmentationView>::Pointer command3 = itk::SimpleMemberCommand<QmitkSegmentationView>::New();
command3->SetCallbackFunction( this, &QmitkSegmentationView::RenderingManagerReinitialized );
m_RenderingManagerObserverTag = mitk::RenderingManager::GetInstance()->AddObserver( mitk::RenderingManagerViewsInitializedEvent(), command3 );
this->SetToolManagerSelection(m_Controls->patImageSelector->GetSelectedNode(), m_Controls->segImageSelector->GetSelectedNode());
}
void QmitkSegmentationView::Deactivated()
{
if( m_Controls )
{
this->SetToolSelectionBoxesEnabled( false );
//deactivate all tools
mitk::ToolManagerProvider::GetInstance()->GetToolManager()->ActivateTool(-1);
//Removing all observers
for ( NodeTagMapType::iterator dataIter = m_WorkingDataObserverTags.begin(); dataIter != m_WorkingDataObserverTags.end(); ++dataIter )
{
(*dataIter).first->GetProperty("visible")->RemoveObserver( (*dataIter).second );
}
m_WorkingDataObserverTags.clear();
for ( NodeTagMapType::iterator dataIter = m_BinaryPropertyObserverTags.begin(); dataIter != m_BinaryPropertyObserverTags.end(); ++dataIter )
{
(*dataIter).first->GetProperty("binary")->RemoveObserver( (*dataIter).second );
}
m_BinaryPropertyObserverTags.clear();
mitk::RenderingManager::GetInstance()->RemoveObserver(m_RenderingManagerObserverTag);
ctkPluginContext* context = mitk::PluginActivator::getContext();
ctkServiceReference ppmRef = context->getServiceReference<mitk::PlanePositionManagerService>();
mitk::PlanePositionManagerService* service = context->getService<mitk::PlanePositionManagerService>(ppmRef);
service->RemoveAllPlanePositions();
context->ungetService(ppmRef);
this->SetToolManagerSelection(0,0);
}
}
void QmitkSegmentationView::StdMultiWidgetAvailable( QmitkStdMultiWidget& stdMultiWidget )
{
SetMultiWidget(&stdMultiWidget);
}
void QmitkSegmentationView::StdMultiWidgetNotAvailable()
{
SetMultiWidget(NULL);
}
void QmitkSegmentationView::StdMultiWidgetClosed( QmitkStdMultiWidget& /*stdMultiWidget*/ )
{
SetMultiWidget(NULL);
}
void QmitkSegmentationView::SetMultiWidget(QmitkStdMultiWidget* multiWidget)
{
// save the current multiwidget as the working widget
m_MultiWidget = multiWidget;
if (m_Parent)
{
m_Parent->setEnabled(m_MultiWidget);
}
// tell the interpolation about toolmanager and multiwidget (and data storage)
if (m_Controls && m_MultiWidget)
{
mitk::ToolManager* toolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager();
m_Controls->m_SlicesInterpolator->SetDataStorage( this->GetDefaultDataStorage());
QList<mitk::SliceNavigationController*> controllers;
controllers.push_back(m_MultiWidget->GetRenderWindow1()->GetSliceNavigationController());
controllers.push_back(m_MultiWidget->GetRenderWindow2()->GetSliceNavigationController());
controllers.push_back(m_MultiWidget->GetRenderWindow3()->GetSliceNavigationController());
m_Controls->m_SlicesInterpolator->Initialize( toolManager, controllers );
}
}
void QmitkSegmentationView::OnPreferencesChanged(const berry::IBerryPreferences* prefs)
{
if (m_Controls != NULL)
{
bool slimView = prefs->GetBool("slim view", false);
m_Controls->m_ManualToolSelectionBox2D->SetShowNames(!slimView);
m_Controls->m_ManualToolSelectionBox3D->SetShowNames(!slimView);
}
m_AutoSelectionEnabled = prefs->GetBool("auto selection", false);
this->ForceDisplayPreferencesUponAllImages();
}
void QmitkSegmentationView::CreateNewSegmentation()
{
mitk::DataNode::Pointer node = mitk::ToolManagerProvider::GetInstance()->GetToolManager()->GetReferenceData(0);
if (node.IsNotNull())
{
mitk::Image::Pointer image = dynamic_cast<mitk::Image*>( node->GetData() );
if (image.IsNotNull())
{
if (image->GetDimension()>1)
{
// ask about the name and organ type of the new segmentation
QmitkNewSegmentationDialog* dialog = new QmitkNewSegmentationDialog( m_Parent ); // needs a QWidget as parent, "this" is not QWidget
QString storedList = QString::fromStdString( this->GetPreferences()->GetByteArray("Organ-Color-List","") );
QStringList organColors;
if (storedList.isEmpty())
{
organColors = GetDefaultOrganColorString();
}
else
{
/*
a couple of examples of how organ names are stored:
a simple item is built up like 'name#AABBCC' where #AABBCC is the hexadecimal notation of a color as known from HTML
items are stored separated by ';'
this makes it necessary to escape occurrences of ';' in name.
otherwise the string "hugo;ypsilon#AABBCC;eugen#AABBCC" could not be parsed as two organs
but we would get "hugo" and "ypsilon#AABBCC" and "eugen#AABBCC"
so the organ name "hugo;ypsilon" is stored as "hugo\;ypsilon"
and must be unescaped after loading
the following lines could be one split with Perl's negative lookbehind
*/
// recover string list from BlueBerry view's preferences
QString storedString = QString::fromStdString( this->GetPreferences()->GetByteArray("Organ-Color-List","") );
MITK_DEBUG << "storedString: " << storedString.toStdString();
// match a string consisting of any number of repetitions of either "anything but ;" or "\;". This matches everything until the next unescaped ';'
QRegExp onePart("(?:[^;]|\\\\;)*");
MITK_DEBUG << "matching " << onePart.pattern().toStdString();
int count = 0;
int pos = 0;
while( (pos = onePart.indexIn( storedString, pos )) != -1 )
{
++count;
int length = onePart.matchedLength();
if (length == 0) break;
QString matchedString = storedString.mid(pos, length);
MITK_DEBUG << " Captured length " << length << ": " << matchedString.toStdString();
pos += length + 1; // skip separating ';'
// unescape possible occurrences of '\;' in the string
matchedString.replace("\\;", ";");
// add matched string part to output list
organColors << matchedString;
}
MITK_DEBUG << "Captured " << count << " organ name/colors";
}
dialog->SetSuggestionList( organColors );
int dialogReturnValue = dialog->exec();
if ( dialogReturnValue == QDialog::Rejected ) return; // user clicked cancel or pressed Esc or something similar
// ask the user about an organ type and name, add this information to the image's (!) propertylist
// create a new image of the same dimensions and smallest possible pixel type
mitk::ToolManager* toolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager();
mitk::Tool* firstTool = toolManager->GetToolById(0);
if (firstTool)
{
try
{
std::string newNodeName = dialog->GetSegmentationName().toStdString();
if(newNodeName.empty())
newNodeName = "no_name";
mitk::DataNode::Pointer emptySegmentation =
firstTool->CreateEmptySegmentationNode( image, newNodeName, dialog->GetColor() );
// initialize showVolume to false to prevent recalculating the volume while working on the segmentation
emptySegmentation->SetProperty( "showVolume", mitk::BoolProperty::New( false ) );
if (!emptySegmentation) return; // could be aborted by user
UpdateOrganList( organColors, dialog->GetSegmentationName(), dialog->GetColor() );
/*
escape ';' here (replace by '\;'), see longer comment above
*/
std::string stringForStorage = organColors.replaceInStrings(";","\\;").join(";").toStdString();
MITK_DEBUG << "Will store: " << stringForStorage;
this->GetPreferences()->PutByteArray("Organ-Color-List", stringForStorage );
this->GetPreferences()->Flush();
if(mitk::ToolManagerProvider::GetInstance()->GetToolManager()->GetWorkingData(0))
{
mitk::ToolManagerProvider::GetInstance()->GetToolManager()->GetWorkingData(0)->SetSelected(false);
}
emptySegmentation->SetSelected(true);
this->GetDefaultDataStorage()->Add( emptySegmentation, node ); // add as a child, because the segmentation "derives" from the original
this->ApplyDisplayOptions( emptySegmentation );
this->FireNodeSelected( emptySegmentation );
this->OnSelectionChanged( emptySegmentation );
m_Controls->segImageSelector->SetSelectedNode(emptySegmentation);
}
catch (std::bad_alloc)
{
QMessageBox::warning(NULL,"Create new segmentation","Could not allocate memory for new segmentation");
}
}
}
else
{
QMessageBox::information(NULL,"Segmentation","Segmentation is currently not supported for 2D images");
}
}
}
else
{
MITK_ERROR << "'Create new segmentation' button should never be clickable unless a patient image is selected...";
}
}
void QmitkSegmentationView::OnWorkingNodeVisibilityChanged()
{
mitk::DataNode* selectedNode = m_Controls->segImageSelector->GetSelectedNode();
bool selectedNodeIsVisible = selectedNode->IsVisible(mitk::BaseRenderer::GetInstance(
mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget1")));
if (!selectedNodeIsVisible)
{
this->SetToolSelectionBoxesEnabled(false);
this->UpdateWarningLabel("The selected segmentation is currently not visible!");
}
else
{
this->SetToolSelectionBoxesEnabled(true);
this->UpdateWarningLabel("");
}
}
void QmitkSegmentationView::OnBinaryPropertyChanged()
{
mitk::DataStorage::SetOfObjects::ConstPointer patImages = m_Controls->patImageSelector->GetNodes();
bool isBinary(false);
for (mitk::DataStorage::SetOfObjects::ConstIterator it = patImages->Begin(); it != patImages->End(); ++it)
{
const mitk::DataNode* node = it->Value();
node->GetBoolProperty("binary", isBinary);
if(isBinary)
{
m_Controls->patImageSelector->RemoveNode(node);
m_Controls->segImageSelector->AddNode(node);
this->SetToolManagerSelection(NULL,NULL);
return;
}
}
mitk::DataStorage::SetOfObjects::ConstPointer segImages = m_Controls->segImageSelector->GetNodes();
isBinary = true;
for (mitk::DataStorage::SetOfObjects::ConstIterator it = segImages->Begin(); it != segImages->End(); ++it)
{
const mitk::DataNode* node = it->Value();
node->GetBoolProperty("binary", isBinary);
if(!isBinary)
{
m_Controls->segImageSelector->RemoveNode(node);
m_Controls->patImageSelector->AddNode(node);
if (mitk::ToolManagerProvider::GetInstance()->GetToolManager()->GetWorkingData(0) == node)
mitk::ToolManagerProvider::GetInstance()->GetToolManager()->SetWorkingData(NULL);
return;
}
}
}
void QmitkSegmentationView::NodeAdded(const mitk::DataNode *node)
{
bool isBinary (false);
bool isHelperObject (false);
node->GetBoolProperty("binary", isBinary);
node->GetBoolProperty("helper object", isHelperObject);
if (m_AutoSelectionEnabled)
{
if (!isBinary && dynamic_cast<mitk::Image*>(node->GetData()))
{
FireNodeSelected(const_cast<mitk::DataNode*>(node));
}
}
if (isBinary && !isHelperObject)
{
itk::SimpleMemberCommand<QmitkSegmentationView>::Pointer command = itk::SimpleMemberCommand<QmitkSegmentationView>::New();
command->SetCallbackFunction(this, &QmitkSegmentationView::OnWorkingNodeVisibilityChanged);
m_WorkingDataObserverTags.insert( std::pair<mitk::DataNode*, unsigned long>( const_cast<mitk::DataNode*>(node), node->GetProperty("visible")->AddObserver( itk::ModifiedEvent(), command ) ) );
itk::SimpleMemberCommand<QmitkSegmentationView>::Pointer command2 = itk::SimpleMemberCommand<QmitkSegmentationView>::New();
command2->SetCallbackFunction(this, &QmitkSegmentationView::OnBinaryPropertyChanged);
m_BinaryPropertyObserverTags.insert( std::pair<mitk::DataNode*, unsigned long>( const_cast<mitk::DataNode*>(node), node->GetProperty("binary")->AddObserver( itk::ModifiedEvent(), command2 ) ) );
this->ApplyDisplayOptions( const_cast<mitk::DataNode*>(node) );
m_Controls->segImageSelector->setCurrentIndex( m_Controls->segImageSelector->Find(node) );
}
}
void QmitkSegmentationView::NodeRemoved(const mitk::DataNode* node)
{
bool isSeg(false);
bool isHelperObject(false);
node->GetBoolProperty("helper object", isHelperObject);
node->GetBoolProperty("binary", isSeg);
mitk::Image* image = dynamic_cast<mitk::Image*>(node->GetData());
if(isSeg && !isHelperObject && image)
{
//First of all remove all possible contour markers of the segmentation
mitk::DataStorage::SetOfObjects::ConstPointer allContourMarkers = this->GetDataStorage()->GetDerivations(node, mitk::NodePredicateProperty::New("isContourMarker"
, mitk::BoolProperty::New(true)));
ctkPluginContext* context = mitk::PluginActivator::getContext();
ctkServiceReference ppmRef = context->getServiceReference<mitk::PlanePositionManagerService>();
mitk::PlanePositionManagerService* service = context->getService<mitk::PlanePositionManagerService>(ppmRef);
for (mitk::DataStorage::SetOfObjects::ConstIterator it = allContourMarkers->Begin(); it != allContourMarkers->End(); ++it)
{
std::string nodeName = node->GetName();
unsigned int t = nodeName.find_last_of(" ");
unsigned int id = atof(nodeName.substr(t+1).c_str())-1;
service->RemovePlanePosition(id);
this->GetDataStorage()->Remove(it->Value());
}
context->ungetService(ppmRef);
service = NULL;
if ((mitk::ToolManagerProvider::GetInstance()->GetToolManager()->GetWorkingData(0) == node) && m_Controls->patImageSelector->GetSelectedNode().IsNotNull())
{
this->SetToolManagerSelection(mitk::ToolManagerProvider::GetInstance()->GetToolManager()->GetReferenceData(0), NULL);
this->UpdateWarningLabel("Select or create a segmentation");
}
mitk::SurfaceInterpolationController::GetInstance()->RemoveSegmentationFromContourList(image);
}
mitk::DataNode* tempNode = const_cast<mitk::DataNode*>(node);
//Since the binary property could be changed during runtime by the user
if (image && !isHelperObject)
{
node->GetProperty("visible")->RemoveObserver( m_WorkingDataObserverTags[tempNode] );
m_WorkingDataObserverTags.erase(tempNode);
node->GetProperty("binary")->RemoveObserver( m_BinaryPropertyObserverTags[tempNode] );
m_BinaryPropertyObserverTags.erase(tempNode);
}
if((mitk::ToolManagerProvider::GetInstance()->GetToolManager()->GetReferenceData(0) == node))
{
//as we don't know which node was actually removed e.g. our reference node, disable 'New Segmentation' button.
//consider the case that there is no more image in the datastorage
this->SetToolManagerSelection(NULL, NULL);
this->SetToolSelectionBoxesEnabled( false );
}
}
//void QmitkSegmentationView::CreateSegmentationFromSurface()
//{
// mitk::DataNode::Pointer surfaceNode =
// m_Controls->MaskSurfaces->GetSelectedNode();
// mitk::Surface::Pointer surface(0);
// if(surfaceNode.IsNotNull())
// surface = dynamic_cast<mitk::Surface*> ( surfaceNode->GetData() );
// if(surface.IsNull())
// {
// this->HandleException( "No surface selected.", m_Parent, true);
// return;
// }
// mitk::DataNode::Pointer imageNode
// = mitk::ToolManagerProvider::GetInstance()->GetToolManager()->GetReferenceData(0);
// mitk::Image::Pointer image(0);
// if (imageNode.IsNotNull())
// image = dynamic_cast<mitk::Image*>( imageNode->GetData() );
// if(image.IsNull())
// {
// this->HandleException( "No image selected.", m_Parent, true);
// return;
// }
// mitk::SurfaceToImageFilter::Pointer s2iFilter
// = mitk::SurfaceToImageFilter::New();
// s2iFilter->MakeOutputBinaryOn();
// s2iFilter->SetInput(surface);
// s2iFilter->SetImage(image);
// s2iFilter->Update();
// mitk::DataNode::Pointer resultNode = mitk::DataNode::New();
// std::string nameOfResultImage = imageNode->GetName();
// nameOfResultImage.append(surfaceNode->GetName());
// resultNode->SetProperty("name", mitk::StringProperty::New(nameOfResultImage) );
// resultNode->SetProperty("binary", mitk::BoolProperty::New(true) );
// resultNode->SetData( s2iFilter->GetOutput() );
// this->GetDataStorage()->Add(resultNode, imageNode);
//}
//void QmitkSegmentationView::ToolboxStackPageChanged(int id)
//{
// // interpolation only with manual tools visible
// m_Controls->m_SlicesInterpolator->EnableInterpolation( id == 0 );
// if( id == 0 )
// {
// mitk::DataNode::Pointer workingData = mitk::ToolManagerProvider::GetInstance()->GetToolManager()->GetWorkingData(0);
// if( workingData.IsNotNull() )
// {
// m_Controls->segImageSelector->setCurrentIndex( m_Controls->segImageSelector->Find(workingData) );
// }
// }
// // this is just a workaround, should be removed when all tools support 3D+t
// if (id==2) // lesions
// {
// mitk::DataNode::Pointer node = mitk::ToolManagerProvider::GetInstance()->GetToolManager()->GetReferenceData(0);
// if (node.IsNotNull())
// {
// mitk::Image::Pointer image = dynamic_cast<mitk::Image*>( node->GetData() );
// if (image.IsNotNull())
// {
// if (image->GetDimension()>3)
// {
// m_Controls->widgetStack->setCurrentIndex(0);
// QMessageBox::information(NULL,"Segmentation","Lesion segmentation is currently not supported for 4D images");
// }
// }
// }
// }
//}
// protected
void QmitkSegmentationView::OnPatientComboBoxSelectionChanged( const mitk::DataNode* node )
{
//mitk::DataNode* selectedNode = const_cast<mitk::DataNode*>(node);
if( node != NULL )
{
this->UpdateWarningLabel("");
mitk::DataNode* segNode = m_Controls->segImageSelector->GetSelectedNode();
if (segNode)
{
mitk::DataStorage::SetOfObjects::ConstPointer possibleParents = this->GetDefaultDataStorage()->GetSources( segNode, m_IsNotABinaryImagePredicate );
bool isSourceNode(false);
for (mitk::DataStorage::SetOfObjects::ConstIterator it = possibleParents->Begin(); it != possibleParents->End(); it++)
{
if (it.Value() == node)
isSourceNode = true;
}
if ( !isSourceNode && (!this->CheckForSameGeometry(segNode, node) || possibleParents->Size() > 0 ))
{
this->SetToolManagerSelection(node, NULL);
this->SetToolSelectionBoxesEnabled( false );
this->UpdateWarningLabel("The selected patient image does not match with the selected segmentation!");
}
else if ((!isSourceNode && this->CheckForSameGeometry(segNode, node)) || isSourceNode )
{
this->SetToolManagerSelection(node, segNode);
//Doing this we can assure that the segmenation is always visible if the segmentation and the patient image are
//loaded separately
int layer(10);
node->GetIntProperty("layer", layer);
layer++;
segNode->SetProperty("layer", mitk::IntProperty::New(layer));
//this->UpdateWarningLabel("");
RenderingManagerReinitialized();
}
}
else
{
this->SetToolManagerSelection(node, NULL);
this->SetToolSelectionBoxesEnabled( false );
this->UpdateWarningLabel("Select or create a segmentation");
}
}
else
{
this->UpdateWarningLabel("Please load an image!");
this->SetToolSelectionBoxesEnabled( false );
}
}
void QmitkSegmentationView::OnSegmentationComboBoxSelectionChanged(const mitk::DataNode *node)
{
if (node == NULL)
{
this->UpdateWarningLabel("Select or create a segmentation");
this->SetToolSelectionBoxesEnabled( false );
return;
}
mitk::DataNode* refNode = m_Controls->patImageSelector->GetSelectedNode();
RenderingManagerReinitialized();
if ( m_Controls->lblSegmentationWarnings->isVisible()) // "RenderingManagerReinitialized()" caused a warning. we do not nede to go any further
return;
if (m_AutoSelectionEnabled)
{
this->OnSelectionChanged(const_cast<mitk::DataNode*>(node));
}
else
{
mitk::DataStorage::SetOfObjects::ConstPointer possibleParents = this->GetDefaultDataStorage()->GetSources( node, m_IsNotABinaryImagePredicate );
if ( possibleParents->Size() == 1 )
{
mitk::DataNode* parentNode = possibleParents->ElementAt(0);
if (parentNode != refNode)
{
this->UpdateWarningLabel("The selected segmentation does not match with the selected patient image!");
this->SetToolSelectionBoxesEnabled( false );
this->SetToolManagerSelection(NULL, node);
}
else
{
this->UpdateWarningLabel("");
this->SetToolManagerSelection(refNode, node);
}
}
else if (refNode && this->CheckForSameGeometry(node, refNode))
{
this->UpdateWarningLabel("");
this->SetToolManagerSelection(refNode, node);
}
else if (!refNode || !this->CheckForSameGeometry(node, refNode))
{
this->UpdateWarningLabel("Please select or load the according patient image!");
}
}
if (!node->IsVisible(mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget1"))))
{
this->UpdateWarningLabel("The selected segmentation is currently not visible!");
this->SetToolSelectionBoxesEnabled( false );
}
}
void QmitkSegmentationView::OnShowMarkerNodes (bool state)
{
mitk::SegTool2D::Pointer manualSegmentationTool;
unsigned int numberOfExistingTools = mitk::ToolManagerProvider::GetInstance()->GetToolManager()->GetTools().size();
for(unsigned int i = 0; i < numberOfExistingTools; i++)
{
manualSegmentationTool = dynamic_cast<mitk::SegTool2D*>(mitk::ToolManagerProvider::GetInstance()->GetToolManager()->GetToolById(i));
if (manualSegmentationTool)
{
if(state == true)
{
manualSegmentationTool->SetShowMarkerNodes( true );
}
else
{
manualSegmentationTool->SetShowMarkerNodes( false );
}
}
}
}
void QmitkSegmentationView::OnSelectionChanged(mitk::DataNode* node)
{
std::vector<mitk::DataNode*> nodes;
nodes.push_back( node );
this->OnSelectionChanged( nodes );
}
void QmitkSegmentationView::OnSelectionChanged(std::vector<mitk::DataNode*> nodes)
{
if (nodes.size() != 0)
{
std::string markerName = "Position";
unsigned int numberOfNodes = nodes.size();
std::string nodeName = nodes.at( 0 )->GetName();
if ( ( numberOfNodes == 1 ) && ( nodeName.find( markerName ) == 0) )
{
this->OnContourMarkerSelected( nodes.at( 0 ) );
return;
}
}
if (m_AutoSelectionEnabled && this->IsActivated())
{
if (nodes.size() == 0 && m_Controls->patImageSelector->GetSelectedNode().IsNull())
{
SetToolManagerSelection(NULL,NULL);
}
else if (nodes.size() == 1)
{
mitk::DataNode::Pointer selectedNode = nodes.at(0);
if(selectedNode.IsNull())
{
return;
}
mitk::Image::Pointer selectedImage = dynamic_cast<mitk::Image*>(selectedNode->GetData());
if (selectedImage.IsNull())
{
SetToolManagerSelection(NULL,NULL);
return;
}
else
{
bool isASegmentation(false);
selectedNode->GetBoolProperty("binary", isASegmentation);
if (isASegmentation)
{
//If a segmentation is selected find a possible reference image:
mitk::DataStorage::SetOfObjects::ConstPointer sources = this->GetDataStorage()->GetSources(selectedNode, m_IsNotABinaryImagePredicate);
mitk::DataNode::Pointer refNode;
if (sources->Size() != 0)
{
refNode = sources->ElementAt(0);
refNode->SetVisibility(true);
selectedNode->SetVisibility(true);
SetToolManagerSelection(refNode,selectedNode);
mitk::DataStorage::SetOfObjects::ConstPointer otherSegmentations = this->GetDataStorage()->GetSubset(m_IsABinaryImagePredicate);
for(mitk::DataStorage::SetOfObjects::const_iterator iter = otherSegmentations->begin(); iter != otherSegmentations->end(); ++iter)
{
mitk::DataNode* node = *iter;
if (dynamic_cast<mitk::Image*>(node->GetData()) != selectedImage.GetPointer())
node->SetVisibility(false);
}
mitk::DataStorage::SetOfObjects::ConstPointer otherPatientImages = this->GetDataStorage()->GetSubset(m_IsNotABinaryImagePredicate);
for(mitk::DataStorage::SetOfObjects::const_iterator iter = otherPatientImages->begin(); iter != otherPatientImages->end(); ++iter)
{
mitk::DataNode* node = *iter;
if (dynamic_cast<mitk::Image*>(node->GetData()) != dynamic_cast<mitk::Image*>(refNode->GetData()))
node->SetVisibility(false);
}
}
else
{
mitk::DataStorage::SetOfObjects::ConstPointer possiblePatientImages = this->GetDataStorage()->GetSubset(m_IsNotABinaryImagePredicate);
for (mitk::DataStorage::SetOfObjects::ConstIterator it = possiblePatientImages->Begin(); it != possiblePatientImages->End(); it++)
{
refNode = it->Value();
if (this->CheckForSameGeometry(selectedNode, it->Value()))
{
refNode->SetVisibility(true);
selectedNode->SetVisibility(true);
mitk::DataStorage::SetOfObjects::ConstPointer otherSegmentations = this->GetDataStorage()->GetSubset(m_IsABinaryImagePredicate);
for(mitk::DataStorage::SetOfObjects::const_iterator iter = otherSegmentations->begin(); iter != otherSegmentations->end(); ++iter)
{
mitk::DataNode* node = *iter;
if (dynamic_cast<mitk::Image*>(node->GetData()) != selectedImage.GetPointer())
node->SetVisibility(false);
}
mitk::DataStorage::SetOfObjects::ConstPointer otherPatientImages = this->GetDataStorage()->GetSubset(m_IsNotABinaryImagePredicate);
for(mitk::DataStorage::SetOfObjects::const_iterator iter = otherPatientImages->begin(); iter != otherPatientImages->end(); ++iter)
{
mitk::DataNode* node = *iter;
if (dynamic_cast<mitk::Image*>(node->GetData()) != dynamic_cast<mitk::Image*>(refNode->GetData()))
node->SetVisibility(false);
}
this->SetToolManagerSelection(refNode, selectedNode);
//Doing this we can assure that the segmenation is always visible if the segmentation and the patient image are at the
//same level in the datamanager
int layer(10);
refNode->GetIntProperty("layer", layer);
layer++;
selectedNode->SetProperty("layer", mitk::IntProperty::New(layer));
return;
}
}
this->SetToolManagerSelection(NULL, selectedNode);
}
}
else
{
if (mitk::ToolManagerProvider::GetInstance()->GetToolManager()->GetReferenceData(0) != selectedNode)
{
SetToolManagerSelection(selectedNode, NULL);
//May be a bug in the selection services. A node which is deselected will be passed as selected node to the OnSelectionChanged function
if (!selectedNode->IsVisible(mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget1"))))
selectedNode->SetVisibility(true);
this->UpdateWarningLabel("The selected patient image does not\nmatchwith the selected segmentation!");
this->SetToolSelectionBoxesEnabled( false );
}
}
}
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
void QmitkSegmentationView::OnContourMarkerSelected(const mitk::DataNode *node)
{
QmitkRenderWindow* selectedRenderWindow = 0;
QmitkRenderWindow* RenderWindow1 =
this->GetActiveStdMultiWidget()->GetRenderWindow1();
QmitkRenderWindow* RenderWindow2 =
this->GetActiveStdMultiWidget()->GetRenderWindow2();
QmitkRenderWindow* RenderWindow3 =
this->GetActiveStdMultiWidget()->GetRenderWindow3();
QmitkRenderWindow* RenderWindow4 =
this->GetActiveStdMultiWidget()->GetRenderWindow4();
bool PlanarFigureInitializedWindow = false;
// find initialized renderwindow
if (node->GetBoolProperty("PlanarFigureInitializedWindow",
PlanarFigureInitializedWindow, RenderWindow1->GetRenderer()))
{
selectedRenderWindow = RenderWindow1;
}
if (!selectedRenderWindow && node->GetBoolProperty(
"PlanarFigureInitializedWindow", PlanarFigureInitializedWindow,
RenderWindow2->GetRenderer()))
{
selectedRenderWindow = RenderWindow2;
}
if (!selectedRenderWindow && node->GetBoolProperty(
"PlanarFigureInitializedWindow", PlanarFigureInitializedWindow,
RenderWindow3->GetRenderer()))
{
selectedRenderWindow = RenderWindow3;
}
if (!selectedRenderWindow && node->GetBoolProperty(
"PlanarFigureInitializedWindow", PlanarFigureInitializedWindow,
RenderWindow4->GetRenderer()))
{
selectedRenderWindow = RenderWindow4;
}
// make node visible
if (selectedRenderWindow)
{
std::string nodeName = node->GetName();
unsigned int t = nodeName.find_last_of(" ");
unsigned int id = atof(nodeName.substr(t+1).c_str())-1;
{
ctkPluginContext* context = mitk::PluginActivator::getContext();
ctkServiceReference ppmRef = context->getServiceReference<mitk::PlanePositionManagerService>();
mitk::PlanePositionManagerService* service = context->getService<mitk::PlanePositionManagerService>(ppmRef);
selectedRenderWindow->GetSliceNavigationController()->ExecuteOperation(service->GetPlanePosition(id));
context->ungetService(ppmRef);
}
selectedRenderWindow->GetRenderer()->GetDisplayGeometry()->Fit();
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
void QmitkSegmentationView::OnTabWidgetChanged(int id)
{
//always disable tools on tab changed
mitk::ToolManagerProvider::GetInstance()->GetToolManager()->ActivateTool(-1);
//2D Tab ID = 0
//3D Tab ID = 1
if (id == 0)
{
//Hide 3D selection box, show 2D selection box
m_Controls->m_ManualToolSelectionBox3D->hide();
m_Controls->m_ManualToolSelectionBox2D->show();
//Deactivate possible active tool
//TODO Remove possible visible interpolations -> Maybe changes in SlicesInterpolator
}
else
{
//Hide 3D selection box, show 2D selection box
m_Controls->m_ManualToolSelectionBox2D->hide();
m_Controls->m_ManualToolSelectionBox3D->show();
//Deactivate possible active tool
}
}
void QmitkSegmentationView::SetToolManagerSelection(const mitk::DataNode* referenceData, const mitk::DataNode* workingData)
{
// called as a result of new BlueBerry selections
// tells the ToolManager for manual segmentation about new selections
// updates GUI information about what the user should select
mitk::ToolManager* toolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager();
toolManager->SetReferenceData(const_cast<mitk::DataNode*>(referenceData));
toolManager->SetWorkingData( const_cast<mitk::DataNode*>(workingData));
// check original image
m_Controls->btnNewSegmentation->setEnabled(referenceData != NULL);
if (referenceData)
{
this->UpdateWarningLabel("");
disconnect( m_Controls->patImageSelector, SIGNAL( OnSelectionChanged( const mitk::DataNode* ) ),
this, SLOT( OnPatientComboBoxSelectionChanged( const mitk::DataNode* ) ) );
m_Controls->patImageSelector->setCurrentIndex( m_Controls->patImageSelector->Find(referenceData) );
connect( m_Controls->patImageSelector, SIGNAL( OnSelectionChanged( const mitk::DataNode* ) ),
this, SLOT( OnPatientComboBoxSelectionChanged( const mitk::DataNode* ) ) );
}
// check segmentation
if (referenceData)
{
if (workingData)
{
this->FireNodeSelected(const_cast<mitk::DataNode*>(workingData));
// if( m_Controls->widgetStack->currentIndex() == 0 )
// {
disconnect( m_Controls->segImageSelector, SIGNAL( OnSelectionChanged( const mitk::DataNode* ) ),
this, SLOT( OnSegmentationComboBoxSelectionChanged( const mitk::DataNode* ) ) );
m_Controls->segImageSelector->setCurrentIndex(m_Controls->segImageSelector->Find(workingData));
connect( m_Controls->segImageSelector, SIGNAL( OnSelectionChanged( const mitk::DataNode* ) ),
this, SLOT( OnSegmentationComboBoxSelectionChanged(const mitk::DataNode*)) );
// }
}
}
}
void QmitkSegmentationView::ForceDisplayPreferencesUponAllImages()
{
if (!m_Parent || !m_Parent->isVisible()) return;
// check all images and segmentations in DataStorage:
// (items in brackets are implicitly done by previous steps)
// 1.
// if a reference image is selected,
// show the reference image
// and hide all other images (orignal and segmentation),
// (and hide all segmentations of the other original images)
// and show all the reference's segmentations
// if no reference image is selected, do do nothing
//
// 2.
// if a segmentation is selected,
// show it
// (and hide all all its siblings (childs of the same parent, incl, NULL parent))
// if no segmentation is selected, do nothing
if (!m_Controls)
return; // might happen on initialization (preferences loaded)
mitk::ToolManager* toolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager();
mitk::DataNode::Pointer referenceData = toolManager->GetReferenceData(0);
mitk::DataNode::Pointer workingData = toolManager->GetWorkingData(0);
// 1.
if (referenceData.IsNotNull())
{
// iterate all images
mitk::DataStorage::SetOfObjects::ConstPointer allImages = this->GetDefaultDataStorage()->GetSubset( m_IsABinaryImagePredicate );
for ( mitk::DataStorage::SetOfObjects::const_iterator iter = allImages->begin(); iter != allImages->end(); ++iter)
{
mitk::DataNode* node = *iter;
// apply display preferences
ApplyDisplayOptions(node);
// set visibility
node->SetVisibility(node == referenceData);
}
}
// 2.
if (workingData.IsNotNull())
workingData->SetVisibility(true);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkSegmentationView::ApplyDisplayOptions(mitk::DataNode* node)
{
if (!node) return;
bool isBinary(false);
node->GetPropertyValue("binary", isBinary);
if (isBinary)
{
node->SetProperty( "outline binary", mitk::BoolProperty::New( this->GetPreferences()->GetBool("draw outline", true)) );
node->SetProperty( "outline width", mitk::FloatProperty::New( 2.0 ) );
node->SetProperty( "opacity", mitk::FloatProperty::New( this->GetPreferences()->GetBool("draw outline", true) ? 1.0 : 0.3 ) );
node->SetProperty( "volumerendering", mitk::BoolProperty::New( this->GetPreferences()->GetBool("volume rendering", false) ) );
}
}
void QmitkSegmentationView::RenderingManagerReinitialized()
{
if ( ! m_MultiWidget ) { return; }
/*
* Here we check whether the geometry of the selected segmentation image if aligned with the worldgeometry
* At the moment it is not supported to use a geometry different from the selected image for reslicing.
* For further information see Bug 16063
*/
mitk::DataNode* workingNode = m_Controls->segImageSelector->GetSelectedNode();
- const mitk::Geometry3D* worldGeo = m_MultiWidget->GetRenderWindow4()->GetSliceNavigationController()->GetCurrentGeometry3D();
+ const mitk::BaseGeometry* worldGeo = m_MultiWidget->GetRenderWindow4()->GetSliceNavigationController()->GetCurrentGeometry3D();
if (workingNode && worldGeo)
{
- const mitk::Geometry3D* workingNodeGeo = workingNode->GetData()->GetGeometry();
+ const mitk::BaseGeometry* workingNodeGeo = workingNode->GetData()->GetGeometry();
if (mitk::Equal(workingNodeGeo->GetBoundingBox(), worldGeo->GetBoundingBox(), mitk::eps, true))
{
this->SetToolManagerSelection(m_Controls->patImageSelector->GetSelectedNode(), workingNode);
this->SetToolSelectionBoxesEnabled(true);
this->UpdateWarningLabel("");
}
else
{
this->SetToolManagerSelection(m_Controls->patImageSelector->GetSelectedNode(), NULL);
this->SetToolSelectionBoxesEnabled(false);
this->UpdateWarningLabel("Please perform a reinit on the segmentation image!");
}
}
}
bool QmitkSegmentationView::CheckForSameGeometry(const mitk::DataNode *node1, const mitk::DataNode *node2) const
{
bool isSameGeometry(true);
mitk::Image* image1 = dynamic_cast<mitk::Image*>(node1->GetData());
mitk::Image* image2 = dynamic_cast<mitk::Image*>(node2->GetData());
if (image1 && image2)
{
- mitk::Geometry3D* geo1 = image1->GetGeometry();
- mitk::Geometry3D* geo2 = image2->GetGeometry();
+ mitk::BaseGeometry* geo1 = image1->GetGeometry();
+ mitk::BaseGeometry* geo2 = image2->GetGeometry();
isSameGeometry = isSameGeometry && mitk::Equal(geo1->GetOrigin(), geo2->GetOrigin());
isSameGeometry = isSameGeometry && mitk::Equal(geo1->GetExtent(0), geo2->GetExtent(0));
isSameGeometry = isSameGeometry && mitk::Equal(geo1->GetExtent(1), geo2->GetExtent(1));
isSameGeometry = isSameGeometry && mitk::Equal(geo1->GetExtent(2), geo2->GetExtent(2));
isSameGeometry = isSameGeometry && mitk::Equal(geo1->GetSpacing(), geo2->GetSpacing());
isSameGeometry = isSameGeometry && mitk::MatrixEqualElementWise(geo1->GetIndexToWorldTransform()->GetMatrix(), geo2->GetIndexToWorldTransform()->GetMatrix());
return isSameGeometry;
}
else
{
return false;
}
}
void QmitkSegmentationView::UpdateWarningLabel(QString text)
{
if (text.size() == 0)
m_Controls->lblSegmentationWarnings->hide();
else
m_Controls->lblSegmentationWarnings->show();
m_Controls->lblSegmentationWarnings->setText(text);
}
void QmitkSegmentationView::CreateQtPartControl(QWidget* parent)
{
// setup the basic GUI of this view
m_Parent = parent;
m_Controls = new Ui::QmitkSegmentationControls;
m_Controls->setupUi(parent);
m_Controls->patImageSelector->SetDataStorage(this->GetDefaultDataStorage());
m_Controls->patImageSelector->SetPredicate(m_IsNotABinaryImagePredicate);
this->UpdateWarningLabel("Please load an image");
if( m_Controls->patImageSelector->GetSelectedNode().IsNotNull() )
this->UpdateWarningLabel("Select or create a new segmentation");
m_Controls->segImageSelector->SetDataStorage(this->GetDefaultDataStorage());
m_Controls->segImageSelector->SetPredicate(m_IsABinaryImagePredicate);
if( m_Controls->segImageSelector->GetSelectedNode().IsNotNull() )
this->UpdateWarningLabel("");
mitk::ToolManager* toolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager();
assert ( toolManager );
toolManager->SetDataStorage( *(this->GetDefaultDataStorage()) );
toolManager->InitializeTools();
// all part of open source MITK
m_Controls->m_ManualToolSelectionBox2D->SetGenerateAccelerators(true);
m_Controls->m_ManualToolSelectionBox2D->SetToolGUIArea( m_Controls->m_ManualToolGUIContainer2D );
m_Controls->m_ManualToolSelectionBox2D->SetDisplayedToolGroups("Add Subtract Correction Paint Wipe 'Region Growing' Fill Erase 'Live Wire' '2D Fast Marching'");
m_Controls->m_ManualToolSelectionBox2D->SetLayoutColumns(3);
m_Controls->m_ManualToolSelectionBox2D->SetEnabledMode( QmitkToolSelectionBox::EnabledWithReferenceAndWorkingDataVisible );
connect( m_Controls->m_ManualToolSelectionBox2D, SIGNAL(ToolSelected(int)), this, SLOT(OnManualTool2DSelected(int)) );
//setup 3D Tools
m_Controls->m_ManualToolSelectionBox3D->SetGenerateAccelerators(true);
m_Controls->m_ManualToolSelectionBox3D->SetToolGUIArea( m_Controls->m_ManualToolGUIContainer3D );
//specify tools to be added to 3D Tool area
m_Controls->m_ManualToolSelectionBox3D->SetDisplayedToolGroups("Threshold 'UL Threshold' Otsu 'Fast Marching 3D' 'Region Growing 3D' Watershed Picking");
m_Controls->m_ManualToolSelectionBox3D->SetLayoutColumns(3);
m_Controls->m_ManualToolSelectionBox3D->SetEnabledMode( QmitkToolSelectionBox::EnabledWithReferenceAndWorkingDataVisible );
//Hide 3D selection box, show 2D selection box
m_Controls->m_ManualToolSelectionBox3D->hide();
m_Controls->m_ManualToolSelectionBox2D->show();
toolManager->NewNodesGenerated +=
mitk::MessageDelegate<QmitkSegmentationView>( this, &QmitkSegmentationView::NewNodesGenerated ); // update the list of segmentations
toolManager->NewNodeObjectsGenerated +=
mitk::MessageDelegate1<QmitkSegmentationView, mitk::ToolManager::DataVectorType*>( this, &QmitkSegmentationView::NewNodeObjectsGenerated ); // update the list of segmentations
// create signal/slot connections
connect( m_Controls->patImageSelector, SIGNAL( OnSelectionChanged( const mitk::DataNode* ) ),
this, SLOT( OnPatientComboBoxSelectionChanged( const mitk::DataNode* ) ) );
connect( m_Controls->segImageSelector, SIGNAL( OnSelectionChanged( const mitk::DataNode* ) ),
this, SLOT( OnSegmentationComboBoxSelectionChanged( const mitk::DataNode* ) ) );
connect( m_Controls->btnNewSegmentation, SIGNAL(clicked()), this, SLOT(CreateNewSegmentation()) );
// connect( m_Controls->CreateSegmentationFromSurface, SIGNAL(clicked()), this, SLOT(CreateSegmentationFromSurface()) );
// connect( m_Controls->widgetStack, SIGNAL(currentChanged(int)), this, SLOT(ToolboxStackPageChanged(int)) );
connect( m_Controls->tabWidgetSegmentationTools, SIGNAL(currentChanged(int)), this, SLOT(OnTabWidgetChanged(int)));
// connect(m_Controls->MaskSurfaces, SIGNAL( OnSelectionChanged( const mitk::DataNode* ) ),
// this, SLOT( OnSurfaceSelectionChanged( ) ) );
connect(m_Controls->m_SlicesInterpolator, SIGNAL(SignalShowMarkerNodes(bool)), this, SLOT(OnShowMarkerNodes(bool)));
// m_Controls->MaskSurfaces->SetDataStorage(this->GetDefaultDataStorage());
// m_Controls->MaskSurfaces->SetPredicate(mitk::NodePredicateDataType::New("Surface"));
}
void QmitkSegmentationView::OnManualTool2DSelected(int id)
{
if (id >= 0)
{
std::string text = "Active Tool: \"";
mitk::ToolManager* toolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager();
text += toolManager->GetToolById(id)->GetName();
text += "\"";
mitk::StatusBar::GetInstance()->DisplayText(text.c_str());
us::ModuleResource resource = toolManager->GetToolById(id)->GetCursorIconResource();
this->SetMouseCursor(resource, 0, 0);
}
else
{
this->ResetMouseCursor();
mitk::StatusBar::GetInstance()->DisplayText("");
}
}
void QmitkSegmentationView::ResetMouseCursor()
{
if ( m_MouseCursorSet )
{
mitk::ApplicationCursor::GetInstance()->PopCursor();
m_MouseCursorSet = false;
}
}
void QmitkSegmentationView::SetMouseCursor( const us::ModuleResource& resource, int hotspotX, int hotspotY )
{
if (!resource) return;
// Remove previously set mouse cursor
if ( m_MouseCursorSet )
{
mitk::ApplicationCursor::GetInstance()->PopCursor();
}
us::ModuleResourceStream cursor(resource, std::ios::binary);
mitk::ApplicationCursor::GetInstance()->PushCursor( cursor, hotspotX, hotspotY );
m_MouseCursorSet = true;
}
void QmitkSegmentationView::SetToolSelectionBoxesEnabled(bool status)
{
m_Controls->m_ManualToolSelectionBox2D->setEnabled(status);
m_Controls->m_ManualToolSelectionBox3D->setEnabled(status);
m_Controls->m_SlicesInterpolator->setEnabled(status);
}
// ATTENTION some methods for handling the known list of (organ names, colors) are defined in QmitkSegmentationOrganNamesHandling.cpp

File Metadata

Mime Type
application/octet-stream
Expires
Tue, Oct 8, 7:22 PM (1 d, 21 h)
Storage Engine
chunks
Storage Format
Chunks
Storage Handle
RGuMW1NPUD6C
Default Alt Text
(4 MB)

Event Timeline