00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "mitkExtractDirectedPlaneImageFilter.h"
00020 #include "mitkAbstractTransformGeometry.h"
00021 #include "mitkImageMapperGL2D.h"
00022
00023 #include <vtkTransform.h>
00024 #include <vtkGeneralTransform.h>
00025 #include <vtkImageData.h>
00026 #include <vtkImageChangeInformation.h>
00027 #include <vtkPoints.h>
00028
00029 #include "pic2vtk.h"
00030 #include "picimage.h"
00031
00032
00033
00034 mitk::ExtractDirectedPlaneImageFilter::ExtractDirectedPlaneImageFilter()
00035 : m_WorldGeometry(NULL)
00036 {
00037 m_Reslicer = vtkImageReslice::New();
00038 m_TargetTimestep = 0;
00039 m_InPlaneResampleExtentByGeometry = false;
00040 }
00041
00042 mitk::ExtractDirectedPlaneImageFilter::~ExtractDirectedPlaneImageFilter()
00043 {
00044 m_WorldGeometry = NULL;
00045 m_Reslicer->Delete();
00046 }
00047
00048 void mitk::ExtractDirectedPlaneImageFilter::GenerateData()
00049 {
00050
00051 if ( m_WorldGeometry == NULL )
00052 {
00053 itkWarningMacro(<<"No world geometry has been set. Returning.");
00054 return;
00055 }
00056
00057 Image *input = const_cast< ImageToImageFilter::InputImageType* >( this->GetInput() );
00058 input->Update();
00059
00060 if ( input == NULL )
00061 {
00062 itkWarningMacro(<<"No input set.");
00063 return;
00064 }
00065
00066 const TimeSlicedGeometry *inputTimeGeometry = input->GetTimeSlicedGeometry();
00067 if ( ( inputTimeGeometry == NULL )
00068 || ( inputTimeGeometry->GetTimeSteps() == 0 ) )
00069 {
00070 itkWarningMacro(<<"Error reading input image geometry.");
00071 return;
00072 }
00073
00074
00075 unsigned int timestep = 0;
00076 if ( ! m_TargetTimestep )
00077 {
00078 ScalarType time = m_WorldGeometry->GetTimeBounds()[0];
00079 if ( time > ScalarTypeNumericTraits::NonpositiveMin() )
00080 {
00081 timestep = inputTimeGeometry->MSToTimeStep( time );
00082 }
00083 }
00084 else timestep = m_TargetTimestep;
00085
00086 if ( inputTimeGeometry->IsValidTime( timestep ) == false )
00087 {
00088 itkWarningMacro(<<"This is not a valid timestep: "<<timestep);
00089 return;
00090 }
00091
00092
00093 if ( ! input->IsVolumeSet( timestep ) )
00094 {
00095 itkWarningMacro(<<"No volume data existent at given timestep "<<timestep);
00096 return;
00097 }
00098
00099 Image::RegionType requestedRegion = input->GetLargestPossibleRegion();
00100 requestedRegion.SetIndex( 3, timestep );
00101 requestedRegion.SetSize( 3, 1 );
00102 requestedRegion.SetSize( 4, 1 );
00103 input->SetRequestedRegion( &requestedRegion );
00104 input->Update();
00105
00106 vtkImageData* inputData = input->GetVtkImageData( timestep );
00107
00108 if ( inputData == NULL )
00109 {
00110 itkWarningMacro(<<"Could not extract vtk image data for given timestep"<<timestep);
00111 return;
00112 }
00113
00114 vtkFloatingPointType spacing[3];
00115 inputData->GetSpacing( spacing );
00116
00117
00118 mitk::ScalarType widthInMM, heightInMM;
00119
00120
00121 Point3D origin;
00122 Vector3D right, bottom, normal;
00123 Vector3D rightInIndex, bottomInIndex;
00124
00125 assert( input->GetTimeSlicedGeometry() == inputTimeGeometry );
00126
00127
00128 Geometry3D* inputGeometry = inputTimeGeometry->GetGeometry3D( timestep );
00129 if ( inputGeometry == NULL )
00130 {
00131 itkWarningMacro(<<"There is no Geometry3D at given timestep "<<timestep);
00132 return;
00133 }
00134
00135 ScalarType mmPerPixel[2];
00136
00137
00138
00139 vtkFloatingPointType bounds[6];
00140 bool boundsInitialized = false;
00141
00142 for ( int i = 0; i < 6; ++i )
00143 {
00144 bounds[i] = 0.0;
00145 }
00146
00147 Vector2D extent; extent.Fill( 0.0 );
00148
00149
00150 if ( dynamic_cast< const PlaneGeometry * >( m_WorldGeometry ) != NULL )
00151 {
00152 const PlaneGeometry *planeGeometry =
00153 static_cast< const PlaneGeometry * >( m_WorldGeometry );
00154
00155 origin = planeGeometry->GetOrigin();
00156 right = planeGeometry->GetAxisVector( 0 );
00157 bottom = planeGeometry->GetAxisVector( 1 );
00158 normal = planeGeometry->GetNormal();
00159
00160 if ( m_InPlaneResampleExtentByGeometry )
00161 {
00162
00163
00164
00165
00166 extent[0] = m_WorldGeometry->GetExtent( 0 );
00167 extent[1] = m_WorldGeometry->GetExtent( 1 );
00168 }
00169 else
00170 {
00171
00172
00173
00174
00175 inputGeometry->WorldToIndex( origin, right, rightInIndex );
00176 inputGeometry->WorldToIndex( origin, bottom, bottomInIndex );
00177 extent[0] = rightInIndex.GetNorm();
00178 extent[1] = bottomInIndex.GetNorm();
00179 }
00180
00181
00182
00183 widthInMM = m_WorldGeometry->GetExtentInMM( 0 );
00184 heightInMM = m_WorldGeometry->GetExtentInMM( 1 );
00185
00186 mmPerPixel[0] = widthInMM / extent[0];
00187 mmPerPixel[1] = heightInMM / extent[1];
00188
00189 right.Normalize();
00190 bottom.Normalize();
00191 normal.Normalize();
00192
00193 origin += right * ( mmPerPixel[0] * 0.5 );
00194 origin += bottom * ( mmPerPixel[1] * 0.5 );
00195
00196 widthInMM -= mmPerPixel[0];
00197 heightInMM -= mmPerPixel[1];
00198
00199
00200 m_Reslicer->SetResliceTransform(
00201 inputGeometry->GetVtkTransform()->GetLinearInverse() );
00202
00203
00204 m_Reslicer->SetBackgroundLevel( -32768 );
00205
00206
00207
00208
00209
00210 if ( m_WorldGeometry->GetReferenceGeometry() )
00211 {
00212
00213
00214
00215 boundsInitialized = this->CalculateClippedPlaneBounds(
00216 m_WorldGeometry->GetReferenceGeometry(), planeGeometry, bounds );
00217 }
00218 }
00219
00220
00221 else if ( dynamic_cast< const AbstractTransformGeometry * >( m_WorldGeometry ) )
00222 {
00223 const mitk::AbstractTransformGeometry* abstractGeometry =
00224 dynamic_cast< const AbstractTransformGeometry * >(m_WorldGeometry);
00225
00226 extent[0] = abstractGeometry->GetParametricExtent(0);
00227 extent[1] = abstractGeometry->GetParametricExtent(1);
00228
00229 widthInMM = abstractGeometry->GetParametricExtentInMM(0);
00230 heightInMM = abstractGeometry->GetParametricExtentInMM(1);
00231
00232 mmPerPixel[0] = widthInMM / extent[0];
00233 mmPerPixel[1] = heightInMM / extent[1];
00234
00235 origin = abstractGeometry->GetPlane()->GetOrigin();
00236
00237 right = abstractGeometry->GetPlane()->GetAxisVector(0);
00238 right.Normalize();
00239
00240 bottom = abstractGeometry->GetPlane()->GetAxisVector(1);
00241 bottom.Normalize();
00242
00243 normal = abstractGeometry->GetPlane()->GetNormal();
00244 normal.Normalize();
00245
00246
00247
00248 vtkGeneralTransform *composedResliceTransform = vtkGeneralTransform::New();
00249 composedResliceTransform->Identity();
00250 composedResliceTransform->Concatenate(
00251 inputGeometry->GetVtkTransform()->GetLinearInverse() );
00252 composedResliceTransform->Concatenate(
00253 abstractGeometry->GetVtkAbstractTransform()
00254 );
00255
00256 m_Reslicer->SetResliceTransform( composedResliceTransform );
00257
00258
00259
00260 m_Reslicer->SetBackgroundLevel( -1023 );
00261 composedResliceTransform->Delete();
00262 }
00263 else
00264 {
00265 itkWarningMacro(<<"World Geometry has to be a PlaneGeometry or an AbstractTransformGeometry.");
00266 return;
00267 }
00268
00269
00270 if ( (extent[0] <= 2) && (extent[1] <= 2) )
00271 {
00272 itkWarningMacro(<<"Image is too small to be resliced...");
00273 return;
00274 }
00275
00276 vtkImageChangeInformation * unitSpacingImageFilter = vtkImageChangeInformation::New() ;
00277 unitSpacingImageFilter->SetOutputSpacing( 1.0, 1.0, 1.0 );
00278 unitSpacingImageFilter->SetInput( inputData );
00279
00280 m_Reslicer->SetInput( unitSpacingImageFilter->GetOutput() );
00281 unitSpacingImageFilter->Delete();
00282 m_Reslicer->SetOutputDimensionality( 2 );
00283 m_Reslicer->SetOutputOrigin( 0.0, 0.0, 0.0 );
00284
00285 Vector2D pixelsPerMM;
00286 pixelsPerMM[0] = 1.0 / mmPerPixel[0];
00287 pixelsPerMM[1] = 1.0 / mmPerPixel[1];
00288
00289
00290 double originArray[3];
00291 itk2vtk( origin, originArray );
00292
00293 m_Reslicer->SetResliceAxesOrigin( originArray );
00294
00295 double cosines[9];
00296
00297
00298 vnl2vtk( right.Get_vnl_vector(), cosines );
00299
00300
00301 vnl2vtk( bottom.Get_vnl_vector(), cosines + 3 );
00302
00303
00304 vnl2vtk( normal.Get_vnl_vector(), cosines + 6 );
00305
00306 m_Reslicer->SetResliceAxesDirectionCosines( cosines );
00307
00308
00309 ScalarType size[2];
00310 size[0] = (bounds[1] - bounds[0]) / mmPerPixel[0];
00311 size[1] = (bounds[3] - bounds[2]) / mmPerPixel[1];
00312
00313 int xMin, xMax, yMin, yMax;
00314 if ( boundsInitialized )
00315 {
00316 xMin = static_cast< int >( bounds[0] / mmPerPixel[0] + 0.5 );
00317 xMax = static_cast< int >( bounds[1] / mmPerPixel[0] + 0.5 );
00318 yMin = static_cast< int >( bounds[2] / mmPerPixel[1] + 0.5 );
00319 yMax = static_cast< int >( bounds[3] / mmPerPixel[1] + 0.5 );
00320 }
00321 else
00322 {
00323
00324
00325
00326 xMin = yMin = 0;
00327 xMax = static_cast< int >( extent[0] - pixelsPerMM[0] + 0.5 );
00328 yMax = static_cast< int >( extent[1] - pixelsPerMM[1] + 0.5 );
00329 }
00330
00331 m_Reslicer->SetOutputSpacing( mmPerPixel[0], mmPerPixel[1], 1.0 );
00332
00333
00334
00335 m_Reslicer->SetOutputExtent( xMin, xMax-1, yMin, yMax-1, 0, 1 );
00336
00337
00338
00339
00340 m_Reslicer->Modified();
00341 m_Reslicer->ReleaseDataFlagOn();
00342
00343 m_Reslicer->Update();
00344
00345
00346 vtkImageData* reslicedImage = m_Reslicer->GetOutput();
00347
00348 mitkIpPicDescriptor *pic = Pic2vtk::convert( reslicedImage );
00349
00350 if((reslicedImage == NULL) || (reslicedImage->GetDataDimension() < 1))
00351 {
00352 itkWarningMacro(<<"Reslicer returned empty image");
00353 return;
00354 }
00355
00356 unsigned int dimensions[2];
00357 dimensions[0] = (unsigned int)extent[0]; dimensions[1] = (unsigned int)extent[1];
00358 Vector3D spacingVector;
00359 FillVector3D(spacingVector, mmPerPixel[0], mmPerPixel[1], 1.0);
00360
00361 mitk::Image::Pointer resultImage = this->GetOutput();
00362 resultImage->Initialize( pic );
00363 resultImage->SetSpacing( spacingVector );
00364 resultImage->SetPicVolume( pic );
00365
00366 mitkIpPicFree(pic);
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378 }
00379
00380
00381 void mitk::ExtractDirectedPlaneImageFilter::GenerateOutputInformation()
00382 {
00383 Superclass::GenerateOutputInformation();
00384 }
00385
00386
00387 bool mitk::ExtractDirectedPlaneImageFilter
00388 ::CalculateClippedPlaneBounds( const Geometry3D *boundingGeometry,
00389 const PlaneGeometry *planeGeometry, vtkFloatingPointType *bounds )
00390 {
00391
00392
00393
00394
00395
00396 const BoundingBox *boundingBox = boundingGeometry->GetBoundingBox();
00397
00398 BoundingBox::PointType bbMin = boundingBox->GetMinimum();
00399 BoundingBox::PointType bbMax = boundingBox->GetMaximum();
00400 BoundingBox::PointType bbCenter = boundingBox->GetCenter();
00401
00402 vtkPoints *points = vtkPoints::New();
00403 if(boundingGeometry->GetImageGeometry())
00404 {
00405 points->InsertPoint( 0, bbMin[0]-0.5, bbMin[1]-0.5, bbMin[2]-0.5 );
00406 points->InsertPoint( 1, bbMin[0]-0.5, bbMin[1]-0.5, bbMax[2]-0.5 );
00407 points->InsertPoint( 2, bbMin[0]-0.5, bbMax[1]-0.5, bbMax[2]-0.5 );
00408 points->InsertPoint( 3, bbMin[0]-0.5, bbMax[1]-0.5, bbMin[2]-0.5 );
00409 points->InsertPoint( 4, bbMax[0]-0.5, bbMin[1]-0.5, bbMin[2]-0.5 );
00410 points->InsertPoint( 5, bbMax[0]-0.5, bbMin[1]-0.5, bbMax[2]-0.5 );
00411 points->InsertPoint( 6, bbMax[0]-0.5, bbMax[1]-0.5, bbMax[2]-0.5 );
00412 points->InsertPoint( 7, bbMax[0]-0.5, bbMax[1]-0.5, bbMin[2]-0.5 );
00413 }
00414 else
00415 {
00416 points->InsertPoint( 0, bbMin[0], bbMin[1], bbMin[2] );
00417 points->InsertPoint( 1, bbMin[0], bbMin[1], bbMax[2] );
00418 points->InsertPoint( 2, bbMin[0], bbMax[1], bbMax[2] );
00419 points->InsertPoint( 3, bbMin[0], bbMax[1], bbMin[2] );
00420 points->InsertPoint( 4, bbMax[0], bbMin[1], bbMin[2] );
00421 points->InsertPoint( 5, bbMax[0], bbMin[1], bbMax[2] );
00422 points->InsertPoint( 6, bbMax[0], bbMax[1], bbMax[2] );
00423 points->InsertPoint( 7, bbMax[0], bbMax[1], bbMin[2] );
00424 }
00425
00426 vtkPoints *newPoints = vtkPoints::New();
00427
00428 vtkTransform *transform = vtkTransform::New();
00429 transform->Identity();
00430 transform->Concatenate(
00431 planeGeometry->GetVtkTransform()->GetLinearInverse()
00432 );
00433
00434 transform->Concatenate( boundingGeometry->GetVtkTransform() );
00435
00436 transform->TransformPoints( points, newPoints );
00437 transform->Delete();
00438
00439 bounds[0] = bounds[2] = 10000000.0;
00440 bounds[1] = bounds[3] = -10000000.0;
00441 bounds[4] = bounds[5] = 0.0;
00442
00443 this->LineIntersectZero( newPoints, 0, 1, bounds );
00444 this->LineIntersectZero( newPoints, 1, 2, bounds );
00445 this->LineIntersectZero( newPoints, 2, 3, bounds );
00446 this->LineIntersectZero( newPoints, 3, 0, bounds );
00447 this->LineIntersectZero( newPoints, 0, 4, bounds );
00448 this->LineIntersectZero( newPoints, 1, 5, bounds );
00449 this->LineIntersectZero( newPoints, 2, 6, bounds );
00450 this->LineIntersectZero( newPoints, 3, 7, bounds );
00451 this->LineIntersectZero( newPoints, 4, 5, bounds );
00452 this->LineIntersectZero( newPoints, 5, 6, bounds );
00453 this->LineIntersectZero( newPoints, 6, 7, bounds );
00454 this->LineIntersectZero( newPoints, 7, 4, bounds );
00455
00456
00457 points->Delete();
00458 newPoints->Delete();
00459
00460 if ( (bounds[0] > 9999999.0) || (bounds[2] > 9999999.0)
00461 || (bounds[1] < -9999999.0) || (bounds[3] < -9999999.0) )
00462 {
00463 return false;
00464 }
00465 else
00466 {
00467
00468
00469 const float *planeSpacing = planeGeometry->GetFloatSpacing();
00470 bounds[0] *= planeSpacing[0];
00471 bounds[1] *= planeSpacing[0];
00472 bounds[2] *= planeSpacing[1];
00473 bounds[3] *= planeSpacing[1];
00474 bounds[4] *= planeSpacing[2];
00475 bounds[5] *= planeSpacing[2];
00476 return true;
00477 }
00478 }
00479
00480 bool mitk::ExtractDirectedPlaneImageFilter
00481 ::LineIntersectZero( vtkPoints *points, int p1, int p2,
00482 vtkFloatingPointType *bounds )
00483 {
00484 vtkFloatingPointType point1[3];
00485 vtkFloatingPointType point2[3];
00486 points->GetPoint( p1, point1 );
00487 points->GetPoint( p2, point2 );
00488
00489 if ( (point1[2] * point2[2] <= 0.0) && (point1[2] != point2[2]) )
00490 {
00491 double x, y;
00492 x = ( point1[0] * point2[2] - point1[2] * point2[0] ) / ( point2[2] - point1[2] );
00493 y = ( point1[1] * point2[2] - point1[2] * point2[1] ) / ( point2[2] - point1[2] );
00494
00495 if ( x < bounds[0] ) { bounds[0] = x; }
00496 if ( x > bounds[1] ) { bounds[1] = x; }
00497 if ( y < bounds[2] ) { bounds[2] = y; }
00498 if ( y > bounds[3] ) { bounds[3] = y; }
00499 bounds[4] = bounds[5] = 0.0;
00500 return true;
00501 }
00502 return false;
00503 }