Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "mitkHeightFieldSurfaceClipImageFilter.h"
00020 #include "mitkImageTimeSelector.h"
00021 #include "mitkTimeHelper.h"
00022 #include "mitkProperties.h"
00023
00024 #include "mitkImageToItk.h"
00025 #include "mitkImageAccessByItk.h"
00026
00027 #include <itkImageRegionConstIterator.h>
00028 #include <itkImageRegionIteratorWithIndex.h>
00029 #include <itkImageSliceConstIteratorWithIndex.h>
00030
00031 #include <vtkPolyData.h>
00032 #include <vtkCellLocator.h>
00033
00034 #include <limits>
00035
00036
00037 namespace mitk
00038 {
00039
00040 HeightFieldSurfaceClipImageFilter::HeightFieldSurfaceClipImageFilter()
00041 : m_ClippingMode( CLIPPING_MODE_CONSTANT ),
00042 m_ClippingConstant( 0.0 ),
00043 m_MultiplicationFactor( 2.0 ),
00044 m_HeightFieldResolutionX( 256 ),
00045 m_HeightFieldResolutionY( 256 ),
00046 m_MaxHeight( 1024.0 )
00047 {
00048 this->SetNumberOfInputs(2);
00049 this->SetNumberOfRequiredInputs(2);
00050
00051 m_InputTimeSelector = ImageTimeSelector::New();
00052 m_OutputTimeSelector = ImageTimeSelector::New();
00053 }
00054
00055
00056 HeightFieldSurfaceClipImageFilter::~HeightFieldSurfaceClipImageFilter()
00057 {
00058 }
00059
00060
00061 void HeightFieldSurfaceClipImageFilter::SetClippingSurface(
00062 Surface *clippingSurface )
00063 {
00064 this->SetNthInput( 1, clippingSurface );
00065 }
00066
00067
00068 const Surface* HeightFieldSurfaceClipImageFilter::GetClippingSurface() const
00069 {
00070 return dynamic_cast< const Surface * >( itk::ProcessObject::GetInput( 1 ) );
00071 }
00072
00073
00074 void HeightFieldSurfaceClipImageFilter::SetClippingMode( int mode )
00075 {
00076 m_ClippingMode = mode;
00077 }
00078
00079
00080 int HeightFieldSurfaceClipImageFilter::GetClippingMode()
00081 {
00082 return m_ClippingMode;
00083 }
00084
00085
00086 void HeightFieldSurfaceClipImageFilter::SetClippingModeToConstant()
00087 {
00088 m_ClippingMode = CLIPPING_MODE_CONSTANT;
00089 }
00090
00091
00092 void HeightFieldSurfaceClipImageFilter::SetClippingModeToMultiplyByFactor()
00093 {
00094 m_ClippingMode = CLIPPING_MODE_MULTIPLYBYFACTOR;
00095 }
00096
00097
00098 void HeightFieldSurfaceClipImageFilter::GenerateInputRequestedRegion()
00099 {
00100 Image *outputImage = this->GetOutput();
00101 Image *inputImage = const_cast< Image * >( this->GetInput( 0 ) );
00102 const Surface *inputSurface = dynamic_cast< const Surface * >( this->GetInput( 1 ) );
00103
00104 if ( !outputImage->IsInitialized() || inputSurface == NULL )
00105 {
00106 return;
00107 }
00108
00109 inputImage->SetRequestedRegionToLargestPossibleRegion();
00110
00111 GenerateTimeInInputRegion( outputImage, inputImage );
00112 }
00113
00114
00115 void HeightFieldSurfaceClipImageFilter::GenerateOutputInformation()
00116 {
00117 const Image *inputImage = this->GetInput( 0 );
00118 Image *outputImage = this->GetOutput();
00119
00120 if ( outputImage->IsInitialized()
00121 && (this->GetMTime() <= m_TimeOfHeaderInitialization.GetMTime()) )
00122 {
00123 return;
00124 }
00125
00126 itkDebugMacro(<<"GenerateOutputInformation()");
00127
00128 unsigned int i;
00129 unsigned int *tmpDimensions = new unsigned int[inputImage->GetDimension()];
00130
00131 for ( i = 0; i < inputImage->GetDimension(); ++i )
00132 {
00133 tmpDimensions[i] = inputImage->GetDimension( i );
00134 }
00135
00136 outputImage->Initialize( inputImage->GetPixelType(),
00137 inputImage->GetDimension(),
00138 tmpDimensions,
00139 inputImage->GetNumberOfChannels() );
00140
00141 delete[] tmpDimensions;
00142
00143 outputImage->SetGeometry(
00144 static_cast< Geometry3D * >( inputImage->GetGeometry()->Clone().GetPointer() ) );
00145
00146 outputImage->SetPropertyList( inputImage->GetPropertyList()->Clone() );
00147
00148 m_TimeOfHeaderInitialization.Modified();
00149 }
00150
00151
00152 template < typename TPixel, unsigned int VImageDimension >
00153 void HeightFieldSurfaceClipImageFilter::_InternalComputeClippedImage(
00154 itk::Image< TPixel, VImageDimension > *inputItkImage,
00155 HeightFieldSurfaceClipImageFilter *clipImageFilter,
00156 vtkPolyData *clippingPolyData,
00157 AffineTransform3D *imageToPlaneTransform )
00158 {
00159 typedef itk::Image< TPixel, VImageDimension > ItkInputImageType;
00160 typedef itk::Image< TPixel, VImageDimension > ItkOutputImageType;
00161
00162 typedef itk::ImageSliceConstIteratorWithIndex< ItkInputImageType > ItkInputImageIteratorType;
00163 typedef itk::ImageRegionIteratorWithIndex< ItkOutputImageType > ItkOutputImageIteratorType;
00164
00165 typename ImageToItk<ItkOutputImageType >::Pointer outputimagetoitk =
00166 ImageToItk<ItkOutputImageType>::New();
00167 outputimagetoitk->SetInput( clipImageFilter->m_OutputTimeSelector->GetOutput() );
00168 outputimagetoitk->Update();
00169
00170 typename ItkOutputImageType::Pointer outputItkImage = outputimagetoitk->GetOutput();
00171
00172
00173
00174 typename ItkInputImageType::RegionType inputRegionOfInterest =
00175 inputItkImage->GetLargestPossibleRegion();
00176 ItkInputImageIteratorType inputIt( inputItkImage, inputRegionOfInterest );
00177 ItkOutputImageIteratorType outputIt( outputItkImage, inputRegionOfInterest );
00178
00179
00180 clippingPolyData->ComputeBounds();
00181 vtkFloatingPointType *bounds = clippingPolyData->GetBounds();
00182
00183 double xWidth = bounds[1] - bounds[0];
00184 double yWidth = bounds[3] - bounds[2];
00185
00186
00187 vtkCellLocator *cellLocator = vtkCellLocator::New();
00188 cellLocator->SetDataSet( clippingPolyData );
00189 cellLocator->CacheCellBoundsOn();
00190 cellLocator->AutomaticOn();
00191 cellLocator->BuildLocator();
00192
00193
00194
00195 double *heightField = new double[m_HeightFieldResolutionX * m_HeightFieldResolutionY];
00196
00197
00198
00199
00200
00201 MITK_INFO << "Calculating Height Field..." << std::endl;
00202 for ( unsigned int y = 0; y < m_HeightFieldResolutionY; ++y )
00203 {
00204 for ( unsigned int x = 0; x < m_HeightFieldResolutionX; ++x )
00205 {
00206 vtkFloatingPointType p0[3], p1[3], surfacePoint[3], pcoords[3];
00207 p0[0] = bounds[0] + xWidth * x / (double) m_HeightFieldResolutionX;
00208 p0[1] = bounds[2] + yWidth * y / (double) m_HeightFieldResolutionY;
00209 p0[2] = -m_MaxHeight;
00210
00211 p1[0] = p0[0];
00212 p1[1] = p0[1];
00213 p1[2] = m_MaxHeight;
00214
00215 double t, distance;
00216 int subId;
00217 if ( cellLocator->IntersectWithLine( p0, p1, 0.1, t, surfacePoint, pcoords, subId ) )
00218 {
00219 distance = (2.0 * t - 1.0) * m_MaxHeight;
00220 }
00221 else
00222 {
00223 distance = -65536.0;
00224 }
00225 heightField[y * m_HeightFieldResolutionX + x] = distance;
00226 }
00227 }
00228
00229
00230
00231
00232 MITK_INFO << "Performing clipping..." << std::endl;
00233
00234 TPixel factor = static_cast< TPixel >( clipImageFilter->m_MultiplicationFactor );
00235 TPixel clippingConstant = clipImageFilter->m_ClippingConstant;
00236
00237 inputIt.SetFirstDirection( 0 );
00238 inputIt.SetSecondDirection( 1 );
00239
00240 for ( inputIt.GoToBegin(), outputIt.GoToBegin();
00241 !inputIt.IsAtEnd();
00242 inputIt.NextSlice() )
00243 {
00244 for ( ; !inputIt.IsAtEndOfSlice(); inputIt.NextLine() )
00245 {
00246 Point3D imageP0, planeP0;
00247 imageP0[0] = inputIt.GetIndex()[0];
00248 imageP0[1] = inputIt.GetIndex()[1];
00249 imageP0[2] = inputIt.GetIndex()[2];
00250 planeP0 = imageToPlaneTransform->TransformPoint( imageP0 );
00251
00252 Point3D imageP1, planeP1;
00253 imageP1[0] = imageP0[0] + inputRegionOfInterest.GetSize( 0 );
00254 imageP1[1] = imageP0[1];
00255 imageP1[2] = imageP0[2];
00256 planeP1 = imageToPlaneTransform->TransformPoint( imageP1 );
00257
00258 Vector3D step = (planeP1 - planeP0) / (double) inputRegionOfInterest.GetSize( 0 );
00259
00260
00261 for ( ; !inputIt.IsAtEndOfLine(); ++inputIt, ++outputIt, planeP0 += step )
00262 {
00263 if ( (clipImageFilter->m_ClippingMode == CLIPPING_MODE_CONSTANT)
00264 && ((TPixel)inputIt.Get() == clippingConstant ) )
00265 {
00266 outputIt.Set( clippingConstant );
00267 }
00268 else
00269 {
00270 int x0 = (int) ((double)(m_HeightFieldResolutionX) * (planeP0[0] - bounds[0]) / xWidth);
00271 int y0 = (int) ((double)(m_HeightFieldResolutionY) * (planeP0[1] - bounds[2]) / yWidth);
00272
00273 bool clip;
00274 if ( (x0 < 0) || (x0 >= (int)m_HeightFieldResolutionX)
00275 || (y0 < 0) || (y0 >= (int)m_HeightFieldResolutionY) )
00276 {
00277 clip = true;
00278 }
00279 else
00280 {
00281
00282 int x1 = x0 + 1;
00283 int y1 = y0 + 1;
00284 if ( x1 >= (int)m_HeightFieldResolutionX ) { x1 = x0; }
00285 if ( y1 >= (int)m_HeightFieldResolutionY ) { y1 = y0; }
00286
00287 ScalarType q00, q01, q10, q11;
00288 q00 = heightField[y0 * m_HeightFieldResolutionX + x0];
00289 q01 = heightField[y0 * m_HeightFieldResolutionX + x1];
00290 q10 = heightField[y1 * m_HeightFieldResolutionX + x0];
00291 q11 = heightField[y1 * m_HeightFieldResolutionX + x1];
00292
00293 ScalarType q =
00294 q00 * ((double) x1 - planeP0[0]) * ((double) y1 - planeP0[1])
00295 + q01 * (planeP0[0] - (double) x0) * ((double) y1 - planeP0[1])
00296 + q10 * ((double) x1 - planeP0[0]) * (planeP0[1] - (double) y0)
00297 + q11 * (planeP0[0] - (double) x0) * (planeP0[1] - (double) y0);
00298
00299 if ( q - planeP0[2] < 0 )
00300 {
00301 clip = true;
00302 }
00303 else
00304 {
00305 clip = false;
00306 }
00307 }
00308
00309 if ( clip )
00310 {
00311 if ( clipImageFilter->m_ClippingMode == CLIPPING_MODE_CONSTANT )
00312 {
00313 outputIt.Set( clipImageFilter->m_ClippingConstant );
00314 }
00315 else if ( clipImageFilter->m_ClippingMode == CLIPPING_MODE_MULTIPLYBYFACTOR )
00316 {
00317 outputIt.Set( inputIt.Get() * factor );
00318 }
00319 }
00320 else
00321 {
00322 outputIt.Set( inputIt.Get() );
00323 }
00324 }
00325 }
00326 }
00327 }
00328
00329 MITK_INFO << "DONE!" << std::endl;
00330
00331
00332
00333 cellLocator->Delete();
00334 }
00335
00336
00337 void HeightFieldSurfaceClipImageFilter::GenerateData()
00338 {
00339 const Image *inputImage = this->GetInput( 0 );
00340 Surface *inputSurface = const_cast< Surface * >(
00341 dynamic_cast< Surface * >( itk::ProcessObject::GetInput( 1 ) ) );
00342
00343 const Image *outputImage = this->GetOutput();
00344
00345 MITK_INFO << "Clipping: Start\n";
00346
00347 if ( !outputImage->IsInitialized() || inputSurface == NULL )
00348 return;
00349
00350
00351
00352
00353 m_InputTimeSelector->SetInput( inputImage );
00354 m_OutputTimeSelector->SetInput( outputImage );
00355
00356 Image::RegionType outputRegion = outputImage->GetRequestedRegion();
00357 const TimeSlicedGeometry *outputTimeGeometry = outputImage->GetTimeSlicedGeometry();
00358 const TimeSlicedGeometry *inputTimeGeometry = inputImage->GetTimeSlicedGeometry();
00359 ScalarType timeInMS;
00360
00361 int timestep = 0;
00362 int tstart = outputRegion.GetIndex( 3 );
00363 int tmax = tstart + outputRegion.GetSize( 3 );
00364
00365 int t;
00366 for( t = tstart; t < tmax; ++t )
00367 {
00368 timeInMS = outputTimeGeometry->TimeStepToMS( t );
00369 timestep = inputTimeGeometry->MSToTimeStep( timeInMS );
00370
00371 m_InputTimeSelector->SetTimeNr( timestep );
00372 m_InputTimeSelector->UpdateLargestPossibleRegion();
00373 m_OutputTimeSelector->SetTimeNr( t );
00374 m_OutputTimeSelector->UpdateLargestPossibleRegion();
00375
00376
00377
00378 AffineTransform3D::Pointer planeWorldToIndexTransform = AffineTransform3D::New();
00379 inputSurface->GetGeometry( t )->GetIndexToWorldTransform()
00380 ->GetInverse( planeWorldToIndexTransform );
00381
00382 AffineTransform3D::Pointer imageToPlaneTransform =
00383 AffineTransform3D::New();
00384 imageToPlaneTransform->SetIdentity();
00385
00386 imageToPlaneTransform->Compose(
00387 inputTimeGeometry->GetGeometry3D( t )->GetIndexToWorldTransform() );
00388 imageToPlaneTransform->Compose( planeWorldToIndexTransform );
00389
00390 MITK_INFO << "Accessing ITK function...\n";
00391 AccessByItk_3(
00392 m_InputTimeSelector->GetOutput(),
00393 _InternalComputeClippedImage,
00394 this,
00395 inputSurface->GetVtkPolyData( t ),
00396 imageToPlaneTransform );
00397 }
00398
00399 m_TimeOfHeaderInitialization.Modified();
00400 }
00401
00402 }