17 #ifndef __itkFastMarchingImageFilter_txx
18 #define __itkFastMarchingImageFilter_txx
22 #include "itkNumericTraits.h"
23 #include "vnl/vnl_math.h"
29 template <
class TLevelSet,
class TSpeedImage>
38 outputSize.Fill( 16 );
39 typename LevelSetImageType::IndexType outputIndex;
40 outputIndex.Fill( 0 );
42 m_OutputRegion.SetSize( outputSize );
43 m_OutputRegion.SetIndex( outputIndex );
45 m_OutputOrigin.Fill( 0.0 );
46 m_OutputSpacing.Fill( 1.0 );
47 m_OutputDirection.SetIdentity();
48 m_OverrideOutputInformation =
false;
52 m_ProcessedPoints =
NULL;
54 m_SpeedConstant = 1.0;
55 m_InverseSpeed = -1.0;
56 m_LabelImage = LabelImageType::New();
59 m_StoppingValue =
static_cast<double>( m_LargeValue );
60 m_CollectPoints =
false;
62 m_NormalizationFactor = 1.0;
65 template <
class TLevelSet,
class TSpeedImage>
70 Superclass::PrintSelf(os,indent);
71 os << indent <<
"Alive points: " << m_AlivePoints.GetPointer() << std::endl;
72 os << indent <<
"Trial points: " << m_TrialPoints.GetPointer() << std::endl;
73 os << indent <<
"Speed constant: " << m_SpeedConstant << std::endl;
74 os << indent <<
"Stopping value: " << m_StoppingValue << std::endl;
75 os << indent <<
"Large Value: "
78 os << indent <<
"Normalization Factor: " << m_NormalizationFactor << std::endl;
79 os << indent <<
"Collect points: " << m_CollectPoints << std::endl;
80 os << indent <<
"OverrideOutputInformation: ";
81 os << m_OverrideOutputInformation << std::endl;
82 os << indent <<
"OutputRegion: " << m_OutputRegion << std::endl;
83 os << indent <<
"OutputOrigin: " << m_OutputOrigin << std::endl;
84 os << indent <<
"OutputSpacing: " << m_OutputSpacing << std::endl;
85 os << indent <<
"OutputDirection: " << m_OutputDirection << std::endl;
88 template <
class TLevelSet,
class TSpeedImage>
95 Superclass::GenerateOutputInformation();
98 if ( this->GetInput() ==
NULL || m_OverrideOutputInformation )
101 output->SetLargestPossibleRegion( m_OutputRegion );
102 output->SetOrigin( m_OutputOrigin );
103 output->SetSpacing( m_OutputSpacing );
104 output->SetDirection( m_OutputDirection );
108 template <
class TLevelSet,
class TSpeedImage>
118 imgData =
dynamic_cast<TLevelSet*
>( output );
121 imgData->SetRequestedRegionToLargestPossibleRegion();
126 itkWarningMacro(<<
"itk::FastMarchingImageFilter" <<
127 "::EnlargeOutputRequestedRegion cannot cast "
128 <<
typeid(output).name() <<
" to "
129 <<
typeid(TLevelSet*).name() );
134 template <
class TLevelSet,
class TSpeedImage>
141 output->SetBufferedRegion( output->GetRequestedRegion() );
145 m_BufferedRegion = output->GetBufferedRegion();
146 m_StartIndex = m_BufferedRegion.GetIndex();
147 m_LastIndex = m_StartIndex + m_BufferedRegion.GetSize();
148 typename LevelSetImageType::OffsetType offset;
150 m_LastIndex -= offset;
153 m_LabelImage->CopyInformation( output );
154 m_LabelImage->SetBufferedRegion(
155 output->GetBufferedRegion() );
156 m_LabelImage->Allocate();
162 OutputIterator outIt ( output, output->GetBufferedRegion() );
165 outputPixel = m_LargeValue;
167 for ( outIt.GoToBegin(); !outIt.IsAtEnd(); ++outIt )
169 outIt.
Set( outputPixel );
176 LabelIterator typeIt( m_LabelImage,
177 m_LabelImage->GetBufferedRegion() );
179 for ( typeIt.GoToBegin(); !typeIt.IsAtEnd(); ++typeIt )
181 typeIt.
Set( FarPoint );
193 for (; pointsIter != pointsEnd; ++pointsIter )
197 node = pointsIter.
Value();
200 if ( !m_BufferedRegion.IsInside( node.
GetIndex() ) )
206 m_LabelImage->SetPixel( node.
GetIndex(), AlivePoint );
209 output->SetPixel( node.
GetIndex(), outputPixel );
216 while ( !m_TrialHeap.empty() )
228 for (; pointsIter != pointsEnd; ++pointsIter )
232 node = pointsIter.
Value();
235 if ( !m_BufferedRegion.IsInside( node.
GetIndex() ) )
240 #ifdef ITK_USE_DEPRECATED_FAST_MARCHING
242 m_LabelImage->SetPixel( node.
GetIndex(), TrialPoint );
245 m_LabelImage->SetPixel( node.
GetIndex(), InitialTrialPoint );
249 output->SetPixel( node.
GetIndex(), outputPixel );
251 m_TrialHeap.push( node );
258 template <
class TLevelSet,
class TSpeedImage>
267 this->Initialize( output );
269 if ( m_CollectPoints )
271 m_ProcessedPoints = NodeContainer::New();
277 double oldProgress = 0;
279 this->UpdateProgress( 0.0 );
281 while ( !m_TrialHeap.empty() )
284 node = m_TrialHeap.top();
288 currentValue = (double) output->GetPixel( node.
GetIndex() );
290 if ( node.
GetValue() != currentValue )
296 #ifdef ITK_USE_DEPRECATED_FAST_MARCHING
297 if ( m_LabelImage->GetPixel( node.
GetIndex() ) != TrialPoint )
299 if ( m_LabelImage->GetPixel( node.
GetIndex() ) == AlivePoint )
305 if ( currentValue > m_StoppingValue )
307 this->UpdateProgress( 1.0 );
311 if ( m_CollectPoints )
313 m_ProcessedPoints->InsertElement( m_ProcessedPoints->Size(), node );
317 m_LabelImage->SetPixel( node.
GetIndex(), AlivePoint );
320 this->UpdateNeighbors( node.
GetIndex(), speedImage, output );
324 const double newProgress = currentValue / m_StoppingValue;
325 if( newProgress - oldProgress > 0.01 )
327 this->UpdateProgress( newProgress );
328 oldProgress = newProgress;
329 if( this->GetAbortGenerateData() )
332 this->ResetPipeline();
344 template <
class TLevelSet,
class TSpeedImage>
354 for (
unsigned int j = 0; j < SetDimension; j++ )
357 if( index[j] > m_StartIndex[j] )
359 neighIndex[j] = index[j] - 1;
361 #ifdef ITK_USE_DEPRECATED_FAST_MARCHING
362 if ( m_LabelImage->GetPixel( neighIndex ) != AlivePoint )
364 unsigned char label = m_LabelImage->GetPixel( neighIndex );
365 if ( label != AlivePoint && label != InitialTrialPoint )
368 this->UpdateValue( neighIndex, speedImage, output );
372 if ( index[j] < m_LastIndex[j] )
374 neighIndex[j] = index[j] + 1;
376 #ifdef ITK_USE_DEPRECATED_FAST_MARCHING
377 if ( m_LabelImage->GetPixel( neighIndex ) != AlivePoint )
379 label = m_LabelImage->GetPixel( neighIndex );
380 if ( label != AlivePoint && label != InitialTrialPoint )
383 this->UpdateValue( neighIndex, speedImage, output );
387 neighIndex[j] = index[j];
393 template <
class TLevelSet,
class TSpeedImage>
403 typename TLevelSet::PixelType neighValue;
407 for (
unsigned int j = 0; j < SetDimension; j++ )
412 for(
int s = -1; s < 2; s = s + 2 )
414 neighIndex[j] = index[j] + s;
416 if( neighIndex[j] > m_LastIndex[j] ||
417 neighIndex[j] < m_StartIndex[j] )
422 if ( m_LabelImage->GetPixel( neighIndex ) == AlivePoint )
424 outputPixel = output->GetPixel( neighIndex );
425 neighValue = outputPixel;
437 m_NodesUsed[j] = node;
441 neighIndex[j] = index[j];
445 std::sort( m_NodesUsed, m_NodesUsed + SetDimension );
449 double solution = m_LargeValue;
455 typedef typename SpeedImageType::PixelType SpeedPixelType;
456 cc = (double) speedImage->GetPixel( index ) / m_NormalizationFactor;
457 cc = -1.0 * vnl_math_sqr( 1.0 / cc );
468 for (
unsigned int j = 0; j < SetDimension; j++ )
470 node = m_NodesUsed[j];
474 const int axis = node.
GetAxis();
475 const double spaceFactor = vnl_math_sqr( 1.0 / spacing[axis] );
476 const double value = double(node.
GetValue());
478 bb += value * spaceFactor;
479 cc += vnl_math_sqr( value ) * spaceFactor;
481 discrim = vnl_math_sqr( bb ) - aa * cc;
487 err.
SetDescription(
"Discriminant of quadratic equation is negative" );
491 solution = ( vcl_sqrt( discrim ) + bb ) / aa;
499 if ( solution < m_LargeValue )
502 outputPixel =
static_cast<PixelType>( solution );
503 output->SetPixel( index, outputPixel );
506 m_LabelImage->SetPixel( index, TrialPoint );
507 node.
SetValue( static_cast<PixelType>( solution ) );
509 m_TrialHeap.push( node );