PlusLib  2.9.0
Software library for tracked ultrasound image acquisition, calibration, and processing.
vtkPlusUsScanConvertCurvilinear.cxx
Go to the documentation of this file.
1 /*=Plus=header=begin======================================================
2 Program: Plus
3 Copyright (c) Laboratory for Percutaneous Surgery. All rights reserved.
4 See License.txt for details.
5 =========================================================Plus=header=end*/
6 
7 /*
8 Based on the fast interpolation program (fast_int_uint32.c) by Joergen Arendt Jensen.
9 Version 1.30, downloaded on June 29, 2012 from
10 http://server.elektro.dtu.dk/personal/jaj/31545/exercises/exercise1/programs/
11 With permission from the author: "You are allowed to include the source code on
12 non-commercial terms in your toolbox and distribute it."
13 */
14 
15 #include "PlusConfigure.h"
16 #include "igsioCommon.h"
17 
19 
20 #include "vtkXMLDataElement.h"
21 
22 #include "vtkMath.h"
23 #include "vtkImageData.h"
24 #include "vtkInformation.h"
25 #include "vtkInformationVector.h"
26 #include "vtkObjectFactory.h"
27 #include "vtkStreamingDemandDrivenPipeline.h"
28 
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <math.h>
32 #include <string.h>
33 #include <ctype.h>
34 
36 
37 //----------------------------------------------------------------------------
39 {
40  this->OutputImageStartDepthMm = -10;
41  this->RadiusStartMm = 15.0;
42  this->RadiusStopMm = 70.0;
43  this->ThetaStartDeg = -30.0;
44  this->ThetaStopDeg = 30.0;
45  this->OutputIntensityScaling = 1.0;
46 
47  // Values that are used for computing the InterpolatedPointArray
48  this->InterpInputImageExtent[0] = 0;
49  this->InterpInputImageExtent[1] = -1;
50  this->InterpInputImageExtent[2] = 0;
51  this->InterpInputImageExtent[3] = -1;
52  this->InterpInputImageExtent[4] = 0;
53  this->InterpInputImageExtent[5] = -1;
54  this->InterpRadiusStartMm = 0.0;
55  this->InterpRadiusStopMm = 0.0;
56  this->InterpThetaStartDeg = 0.0;
57  this->InterpThetaStopDeg = 0.0;
58  this->InterpOutputImageExtent[0] = 0;
59  this->InterpOutputImageExtent[1] = -1;
60  this->InterpOutputImageExtent[2] = 0;
61  this->InterpOutputImageExtent[3] = -1;
62  this->InterpOutputImageExtent[4] = 0;
63  this->InterpOutputImageExtent[5] = -1;
64  this->InterpOutputImageSpacing[0] = 0.0;
65  this->InterpOutputImageSpacing[1] = 0.0;
66  this->InterpOutputImageSpacing[2] = 0.0;
67  this->InterpTransducerCenterPixel[0] = 0.0;
68  this->InterpTransducerCenterPixel[1] = 0.0;
69  this->InterpIntensityScaling = 0.0;
70 }
71 
72 //----------------------------------------------------------------------------
74 {
75 }
76 
77 //----------------------------------------------------------------------------
79  int* inputImageExtent, double radiusStartMm, double radiusStopMm, double thetaStartDeg, double thetaStopDeg,
80  int* outputImageExtent, double* outputImageSpacing, double* transducerCenterPixel, double intensityScaling )
81 {
82  // Computing the point array is a costly operation, so perform it only if a scan conversion parameter has been changed
83 
84  // Check if any scan conversion parameter has been changed
85  bool modifiedScanConversionParams = false;
86  for ( int i = 0; i < 6; i++ )
87  {
88  if ( this->InterpInputImageExtent[i] != inputImageExtent[i] )
89  {
90  modifiedScanConversionParams = true;
91  }
92  if ( this->OutputImageExtent[i] != outputImageExtent[i] )
93  {
94  modifiedScanConversionParams = true;
95  }
96  }
97  for ( int i = 0; i < 3; i++ )
98  {
99  if ( this->InterpOutputImageSpacing[i] != outputImageSpacing[i] )
100  {
101  modifiedScanConversionParams = true;
102  }
103  }
104  if ( ( this->InterpRadiusStartMm != radiusStartMm )
105  || ( this->InterpRadiusStopMm != radiusStopMm )
106  || ( this->InterpThetaStartDeg != thetaStartDeg )
107  || ( this->InterpThetaStopDeg != thetaStopDeg )
108  || ( this->InterpTransducerCenterPixel[0] != transducerCenterPixel[0] )
109  || ( this->InterpTransducerCenterPixel[1] != transducerCenterPixel[1] )
110  || ( this->InterpIntensityScaling != intensityScaling ) )
111  {
112  modifiedScanConversionParams = true;
113  }
114 
115  if ( !modifiedScanConversionParams )
116  {
117  // scan conversion parameters haven't been modified since the InterpolatedPointArray was last computed
118  // there is no need to recompute, just return
119  return;
120  }
121 
122  // remember the current scan conversion parameters that are used to compute the interpolated point array
123  for ( int i = 0; i < 6; i++ )
124  {
125  this->InterpInputImageExtent[i] = inputImageExtent[i];
126  this->OutputImageExtent[i] = outputImageExtent[i];
127  }
128  for ( int i = 0; i < 3; i++ )
129  {
130  this->InterpOutputImageSpacing[i] = outputImageSpacing[i];
131  }
132  this->InterpRadiusStartMm = radiusStartMm;
133  this->InterpRadiusStopMm = radiusStopMm;
134  this->InterpThetaStartDeg = thetaStartDeg;
135  this->InterpThetaStopDeg = thetaStopDeg;
136  this->InterpTransducerCenterPixel[0] = transducerCenterPixel[0];
137  this->InterpTransducerCenterPixel[1] = transducerCenterPixel[1];
138  this->InterpIntensityScaling = intensityScaling;
139 
140  // Compute the interpolated point array now
141 
142  this->InterpolatedPointArray.clear();
143 
144  int numberOfSamples = inputImageExtent[1] - inputImageExtent[0] + 1;
145  int numberOfLines = inputImageExtent[3] - inputImageExtent[2] + 1;
146  double radiusDeltaMm = ( radiusStopMm - radiusStartMm ) / numberOfSamples;
147  double thetaStartRad = vtkMath::RadiansFromDegrees( thetaStartDeg );
148  double thetaDeltaRad = 0;
149  if ( numberOfLines > 1 )
150  {
151  thetaDeltaRad = vtkMath::RadiansFromDegrees( ( thetaStopDeg - thetaStartDeg ) / ( numberOfLines - 1 ) );
152  }
153  int outputImageSizePixelsX = outputImageExtent[1] - outputImageExtent[0] + 1;
154  int outputImageSizePixelsY = outputImageExtent[3] - outputImageExtent[2] + 1;
155 
156  // Increments in image coordinates in mm
157  double dx = outputImageSpacing[0];
158  double dz = outputImageSpacing[1];
159 
160  // Starting depth in image coordinates in mm
161  double z = radiusStartMm - this->InterpTransducerCenterPixel[1] * dz;
162  for ( int i = 0; i < outputImageSizePixelsY; i++ )
163  {
164  double x = -( this->InterpTransducerCenterPixel[0] - 0.5 ) * dx; // image coordinate, in mm
165  double z2 = z * z;
166 
167  for ( int j = 0; j < outputImageSizePixelsX; j++ )
168  {
169  // Find which samples to select from the envelope array
170  double radius = sqrt( z2 + x * x ); // Radial distance
171  double theta = atan2 ( x, z ); // Angle in degrees
172  double samp = ( radius - radiusStartMm ) / radiusDeltaMm; // Sample number for interpolation
173  double line = ( theta - thetaStartRad ) / thetaDeltaRad; // Line number for interpolation
174  int index_samp = floor( samp ); // Index for the data sample number
175  int index_line = floor( line ); // Index for the data line number
176 
177  if ( ( index_samp >= 0 ) && ( index_samp + 1 < numberOfSamples ) &&
178  ( index_line >= 0 ) && ( index_line + 1 < numberOfLines ) )
179  {
180  // The sample is inside the input image, so it can be computed
182  double samp_val = samp - index_samp; // Sub-sample fraction for interpolation
183  double line_val = line - index_line; // Sub-line fraction for interpolation
184 
185  // Calculate the coefficients
186  ip.weightCoefficients[0] = ( 1 - samp_val ) * ( 1 - line_val ) * intensityScaling;
187  ip.weightCoefficients[1] = samp_val * ( 1 - line_val ) * intensityScaling;
188  ip.weightCoefficients[2] = ( 1 - samp_val ) * line_val * intensityScaling;
189  ip.weightCoefficients[3] = samp_val * line_val * intensityScaling;
190 
191  ip.inputPixelIndex = index_samp + index_line * numberOfSamples;
192  ip.outputPixelIndex = j + outputImageSizePixelsX * i;
193 
194  this->InterpolatedPointArray.push_back( ip );
195  }
196 
197  x = x + dx;
198  }
199  z = z + dz;
200  }
201 
202 }
203 
204 //----------------------------------------------------------------------------
205 // Computes any global image information associated with regions.
206 int vtkPlusUsScanConvertCurvilinear::RequestInformation ( vtkInformation* vtkNotUsed( request ), vtkInformationVector** inputVector, vtkInformationVector* outputVector )
207 {
208  // get the info objects
209  vtkInformation* outInfo = outputVector->GetInformationObject( 0 );
210  vtkInformation* inInfo = inputVector[0]->GetInformationObject( 0 );
211 
212  outInfo->Set( vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), this->OutputImageExtent, 6 );
213 
214  // In Plus the convention is that the image coordinate system has always unit spacing and zero origin
215  double spacing[3] = {1.0, 1.0, 1.0};
216  outInfo->Set( vtkDataObject::SPACING(), spacing, 3 );
217  double origin[3] = {0, 0, 0};
218  outInfo->Set( vtkDataObject::ORIGIN(), origin, 3 );
219 
220  int inExtent[6] = {0};
221  inInfo->Get( vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), inExtent );
222  //inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),inExtent, 6);
223 
224  // Create the interpolation table. It is recomputed only if the scan conversion parameters change.
227 
228  return 1;
229 }
230 
231 //----------------------------------------------------------------------------
232 int vtkPlusUsScanConvertCurvilinear::RequestUpdateExtent ( vtkInformation* vtkNotUsed( request ), vtkInformationVector** inputVector, vtkInformationVector* vtkNotUsed( outputVector ) )
233 {
234  // Use the whole extent as the update extent (by default it would use the output extent, which would not be correct)
235  vtkInformation* inInfo = inputVector[0]->GetInformationObject( 0 );
236  int extent[6] = {0, -1, 0, -1, 0, -1};
237  inInfo->Get( vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), extent );
238  inInfo->Set( vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), extent, 6 );
239  return 1;
240 }
241 
242 //----------------------------------------------------------------------------
243 void vtkPlusUsScanConvertCurvilinear::AllocateOutputData( vtkImageData* output, vtkInformation* outInfo, int* uExtent )
244 {
245  // The multithreaded algorithm sets only the non-zero voxels.
246  // We need to initialize the rest of the voxels to zero.
247 
248  // Make sure the output is allocated
249  Superclass::AllocateOutputData( output, outInfo, uExtent );
250 
251  // Initialize voxels to zero now.
252 
253  unsigned char* outPtrZ = static_cast<unsigned char*>( output->GetScalarPointerForExtent( uExtent ) );
254 
255  // Get increments to march through data
256  vtkIdType outIncX, outIncY, outIncZ;
257  output->GetIncrements( outIncX, outIncY, outIncZ );
258  int typeSize = output->GetScalarSize();
259  outIncX *= typeSize;
260  outIncY *= typeSize;
261  outIncZ *= typeSize;
262 
263  // Find the region to loop over
264  int rowLength = ( uExtent[1] - uExtent[0] + 1 ) * output->GetNumberOfScalarComponents();
265  rowLength *= typeSize;
266  int maxY = uExtent[3] - uExtent[2];
267  int maxZ = uExtent[5] - uExtent[4];
268 
269  // Loop through input pixels
270  for ( int idxZ = 0; idxZ <= maxZ; idxZ++ )
271  {
272  unsigned char* outPtrY = outPtrZ;
273  for ( int idxY = 0; idxY <= maxY; idxY++ )
274  {
275  memset( outPtrY, 0, rowLength );
276  outPtrY += outIncY;
277  }
278  outPtrZ += outIncZ;
279  }
280 }
281 
282 //----------------------------------------------------------------------------
283 // The templated execute function handles all the data types.
284 // T: originally developed for unsigned int
285 template <class T>
287  vtkImageData* inData, T* inPtr,
288  vtkImageData* outData, T* outPtr,
289  int interpolationTableExt[6], int id )
290 {
291  T* envelope_data = inPtr; // The envelope detected and log-compressed data
292  int numberOfSamples = inData->GetExtent()[1] - inData->GetExtent()[0] + 1; // Number of samples in one envelope line
293 
294  T* image = outPtr; // The resulting image
295 
296  std::vector<vtkPlusUsScanConvertCurvilinear::InterpolatedPoint>::const_iterator firstPoint = self->GetInterpolatedPointArray().begin() + interpolationTableExt[0];
297  std::vector<vtkPlusUsScanConvertCurvilinear::InterpolatedPoint>::const_iterator afterLastPoint = self->GetInterpolatedPointArray().begin() + interpolationTableExt[1] + 1;
298  for ( std::vector<vtkPlusUsScanConvertCurvilinear::InterpolatedPoint>::const_iterator it = firstPoint; it != afterLastPoint; ++it )
299  {
300  T* env_pointer = ( T* ) & ( envelope_data[it->inputPixelIndex] ); // Pointer to the envelope data
301  image[it->outputPixelIndex] =
302  it->weightCoefficients[0] * env_pointer[0] // (+0, +0)
303  + it->weightCoefficients[1] * env_pointer[1] // (+1, +0)
304  + it->weightCoefficients[2] * env_pointer[numberOfSamples] // (+0, +1)
305  + it->weightCoefficients[3] * env_pointer[numberOfSamples + 1] // (+1, +1)
306  + 0.5; // for rounding
307  }
308 }
309 
310 //----------------------------------------------------------------------------
312  vtkInformation* vtkNotUsed( request ),
313  vtkInformationVector** vtkNotUsed( inputVector ),
314  vtkInformationVector* vtkNotUsed( outputVector ),
315  vtkImageData** *inData,
316  vtkImageData** outData,
317  int outExt[6], int id )
318 {
319 
320  void* inPtr = inData[0][0]->GetScalarPointer();
321  void* outPtr = outData[0]->GetScalarPointer();
322 
323  // this filter expects that input is the same type as output.
324  if ( inData[0][0]->GetScalarType() != outData[0]->GetScalarType() )
325  {
326  vtkErrorMacro( "Execute: input ScalarType, "
327  << inData[0][0]->GetScalarType()
328  << ", must match out ScalarType "
329  << outData[0]->GetScalarType() );
330  return;
331  }
332 
333  switch ( inData[0][0]->GetScalarType() )
334  {
335  vtkTemplateMacro(
336  vtkPlusUsScanConvertExecute( this, inData[0][0],
337  static_cast<VTK_TT*>( inPtr ), outData[0],
338  static_cast<VTK_TT*>( outPtr ),
339  outExt, id ) );
340  default:
341  vtkErrorMacro( << "Execute: Unknown ScalarType" );
342  return;
343  }
344 }
345 
346 //----------------------------------------------------------------------------
347 void vtkPlusUsScanConvertCurvilinear::PrintSelf( ostream& os, vtkIndent indent )
348 {
349  this->Superclass::PrintSelf( os, indent );
350 
351  os << indent << "TransducerCenterPixel: " << this->TransducerCenterPixel[0] << "; " << this->TransducerCenterPixel[1] << "\n";
352  os << indent << "RadiusStartMm: " << this->RadiusStartMm << "\n";
353  os << indent << "RadiusStopMm: " << this->RadiusStopMm << "\n";
354  os << indent << "ThetaStartDeg: " << this->ThetaStartDeg << "\n";
355  os << indent << "ThetaStopDeg: " << this->ThetaStopDeg << "\n";
356  os << indent << "OutputIntensityScaling: " << this->OutputIntensityScaling << "\n";
357  os << indent << "InterpolatedPointArraySize: " << this->InterpolatedPointArray.size() << "\n";
358 
359 }
360 
361 //----------------------------------------------------------------------------
362 // Splits data into num pieces for processing by each thread.
363 // Usually the output extent is split into pieces, but in our case
364 // we need to split the interpolation table.
365 // This method returns the number of pieces resulting from a successful split.
366 // This can be from 1 to "total".
367 // If 1 is returned, the extent cannot be split.
368 int vtkPlusUsScanConvertCurvilinear::SplitExtent( int splitExt[6], int startExt[6], int num, int total )
369 {
370  // startExt is not used, because we split the interpolation table
371 
372  // Starting extent
373  int min = 0;
374  int max = this->InterpolatedPointArray.size() - 1;
375 
376  splitExt[0] = min;
377  splitExt[1] = max;
378  splitExt[2] = 0;
379  splitExt[3] = 0;
380  splitExt[4] = 0;
381  splitExt[5] = 0;
382 
383  if ( min >= max )
384  {
385  // Cannot split interpolation table, as it's empty or has only one element
386  return 1;
387  }
388 
389  // determine the actual number of pieces that will be generated
390  int range = max - min + 1;
391  int valuesPerThread = static_cast<int>( ceil( range / static_cast<double>( total ) ) );
392  int maxThreadIdUsed = static_cast<int>( ceil( range / static_cast<double>( valuesPerThread ) ) ) - 1;
393  if ( num < maxThreadIdUsed )
394  {
395  splitExt[0] = splitExt[0] + num * valuesPerThread;
396  splitExt[1] = splitExt[0] + valuesPerThread - 1;
397  }
398  if ( num == maxThreadIdUsed )
399  {
400  splitExt[0] = splitExt[0] + num * valuesPerThread;
401  }
402 
403  vtkDebugMacro( " Split Piece: ( " << splitExt[0] << ", " << splitExt[1] << ", "
404  << splitExt[2] << ", " << splitExt[3] << ", "
405  << splitExt[4] << ", " << splitExt[5] << ")" );
406 
407  return maxThreadIdUsed + 1;
408 }
409 
410 //-----------------------------------------------------------------------------
411 PlusStatus vtkPlusUsScanConvertCurvilinear::ReadConfiguration( vtkXMLDataElement* scanConversionElement )
412 {
413  LOG_TRACE( "vtkPlusUsScanConvertCurvilinear::ReadConfiguration" );
414  if ( this->Superclass::ReadConfiguration( scanConversionElement ) != PLUS_SUCCESS )
415  {
416  return PLUS_FAIL;
417  }
418 
419  XML_READ_SCALAR_ATTRIBUTE_OPTIONAL( double, RadiusStartMm, scanConversionElement );
420  XML_READ_SCALAR_ATTRIBUTE_OPTIONAL( double, RadiusStopMm, scanConversionElement );
421 
422  // this->TransducerCenterPixel values will be used in this file, so set them to meaningful default values if the user has not specified them
423  if ( !this->TransducerCenterPixelSpecified )
424  {
425  this->TransducerCenterPixel[0] = double( this->OutputImageExtent[1] - this->OutputImageExtent[0] + 1 ) / 2.0;
426  this->TransducerCenterPixel[1] = this->RadiusStartMm / this->OutputImageSpacing[1];
427  }
428 
429  // Fill the TransducerCenterPixel from the deprecated OutputImageStartDepthMm element
430  double outputImageStartDepthMm = 0;
431  if ( scanConversionElement->GetScalarAttribute( "OutputImageStartDepthMm", outputImageStartDepthMm ) )
432  {
433  if ( this->TransducerCenterPixelSpecified )
434  {
435  LOG_WARNING( "Transducer center position in the image is specified by the TransducerCenterPixel attribute, therefore the OutputImageStartDepthMm will be ignored. Please remove the OutputImageStartDepthMm attribute from the configuration." );
436  }
437  else
438  {
439  this->TransducerCenterPixel[0] = double( this->OutputImageExtent[1] - this->OutputImageExtent[0] + 1 ) / 2.0; // image center
440  this->TransducerCenterPixel[1] = ( this->RadiusStartMm - outputImageStartDepthMm ) / this->OutputImageSpacing[1]; // row index of the centerpoint of the curvature circle
441  this->TransducerCenterPixelSpecified = true;
442  LOG_WARNING( "OutputImageStartDepthMm is deprecated. Use the following equivalent attribute instead: TransducerCenterPixel=\""
443  << this->TransducerCenterPixel[0] << " " << this->TransducerCenterPixel[1] << "\"" );
444  }
445  }
446 
447  XML_READ_SCALAR_ATTRIBUTE_OPTIONAL( double, ThetaStartDeg, scanConversionElement );
448  XML_READ_SCALAR_ATTRIBUTE_OPTIONAL( double, ThetaStopDeg, scanConversionElement );
449 
450  return PLUS_SUCCESS;
451 }
452 
453 //-----------------------------------------------------------------------------
454 PlusStatus vtkPlusUsScanConvertCurvilinear::WriteConfiguration( vtkXMLDataElement* scanConversionElement )
455 {
456  LOG_TRACE( "vtkPlusUsScanConvertCurvilinear::WriteConfiguration" );
457  if ( this->Superclass::WriteConfiguration( scanConversionElement ) != PLUS_SUCCESS )
458  {
459  return PLUS_FAIL;
460  }
461 
462  scanConversionElement->SetDoubleAttribute( "RadiusStartMm", this->RadiusStartMm );
463  scanConversionElement->SetDoubleAttribute( "RadiusStopMm", this->RadiusStopMm );
464 
465  scanConversionElement->SetDoubleAttribute( "ThetaStartDeg", this->ThetaStartDeg );
466  scanConversionElement->SetDoubleAttribute( "ThetaStopDeg", this->ThetaStopDeg );
467 
468  return PLUS_SUCCESS;
469 }
470 
471 //-----------------------------------------------------------------------------
472 PlusStatus vtkPlusUsScanConvertCurvilinear::GetScanLineEndPoints( int scanLineIndex, double scanlineStartPoint_OutputImage[4], double scanlineEndPoint_OutputImage[4] )
473 {
474  // (imagecenter,0) is in the pixel centerpoint
475  double fanOriginPosition_OutputImage[2] = { this->TransducerCenterPixel[0], this->TransducerCenterPixel[1] - this->RadiusStartMm / this->OutputImageSpacing[1]};
476 
477  int numberOfLines = this->InputImageExtent[3] - this->InputImageExtent[2] + 1;
478 
479  double thetaDeltaDeg = 0; // angle between two scanlines
480  if ( numberOfLines > 1 )
481  {
482  thetaDeltaDeg = ( ( this->ThetaStopDeg - this->ThetaStartDeg ) / ( numberOfLines - 1 ) );
483  }
484  double thetaRad = vtkMath::RadiansFromDegrees( this->ThetaStartDeg + scanLineIndex * thetaDeltaDeg );
485 
486  scanlineStartPoint_OutputImage[0] = fanOriginPosition_OutputImage[0] + this->RadiusStartMm * sin( thetaRad ) / this->OutputImageSpacing[0];
487  scanlineStartPoint_OutputImage[1] = fanOriginPosition_OutputImage[1] + this->RadiusStartMm * cos( thetaRad ) / this->OutputImageSpacing[1];
488  scanlineStartPoint_OutputImage[2] = 0;
489  scanlineStartPoint_OutputImage[3] = 1;
490 
491  scanlineEndPoint_OutputImage[0] = fanOriginPosition_OutputImage[0] + this->RadiusStopMm * sin( thetaRad ) / this->OutputImageSpacing[0];
492  scanlineEndPoint_OutputImage[1] = fanOriginPosition_OutputImage[1] + this->RadiusStopMm * cos( thetaRad ) / this->OutputImageSpacing[1];
493  scanlineEndPoint_OutputImage[2] = 0;
494  scanlineEndPoint_OutputImage[3] = 1;
495 
496  return PLUS_FAIL;
497 }
498 
499 //-----------------------------------------------------------------------------
501 {
502  int scanLineLengthPixels = this->InputImageExtent[1] - this->InputImageExtent[0] + 1;
503  if ( scanLineLengthPixels < 1 )
504  {
505  LOG_ERROR( "Cannot determine DistanceBetweenScanlineSamplePointsMm because scanLineLengthPixels=" << scanLineLengthPixels << " is invalid" );
506  return 0.0;
507  }
508  double distanceBetweenScanlineSamplePointsMm = ( this->RadiusStopMm - this->RadiusStartMm ) / double( scanLineLengthPixels );
509  return distanceBetweenScanlineSamplePointsMm;
510 }
511 
512 //-----------------------------------------------------------------------------
514 {
515  return vtkImageAlgorithm::GetOutput();
516 }
virtual PlusStatus WriteConfiguration(vtkXMLDataElement *scanConversionElement)
virtual void ThreadedRequestData(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector, vtkImageData ***inData, vtkImageData **outData, int outExt[6], int id)
const char int line
Definition: phidget22.h:2458
igsioStatus PlusStatus
Definition: PlusCommon.h:40
void ComputeInterpolatedPointArray(int *inputImageExtent, double radiusStartMm, double radiusStopMm, double thetaStartDeg, double thetaStopDeg, int *outputImageExtent, double *outputImageSpacing, double *transducerCenterPixel, double intensityScaling)
virtual void PrintSelf(ostream &os, vtkIndent indent) VTK_OVERRIDE
for i
virtual void AllocateOutputData(vtkImageData *output, vtkInformation *outInfo, int *uExtent)
virtual PlusStatus ReadConfiguration(vtkXMLDataElement *scanConversionElement)
#define PLUS_FAIL
Definition: PlusCommon.h:43
virtual PlusStatus WriteConfiguration(vtkXMLDataElement *scanConversionElement)
void vtkPlusUsScanConvertExecute(vtkPlusUsScanConvertCurvilinear *self, vtkImageData *inData, T *inPtr, vtkImageData *outData, T *outPtr, int interpolationTableExt[6], int id)
std::vector< InterpolatedPoint > InterpolatedPointArray
#define PLUS_SUCCESS
Definition: PlusCommon.h:44
PlusStatus GetScanLineEndPoints(int scanLineIndex, double scanlineStartPoint_OutputImage[4], double scanlineEndPoint_OutputImage[4])
int x
Definition: phidget22.h:4265
virtual int SplitExtent(int splitExt[6], int startExt[6], int num, int total)
virtual void PrintSelf(ostream &os, vtkIndent indent) VTK_OVERRIDE
This class performs scan conversion from scan lines for curvilinear probes.
vtkStandardNewMacro(vtkPlusUsScanConvertCurvilinear)
virtual int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *)
virtual int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *)
virtual PlusStatus ReadConfiguration(vtkXMLDataElement *scanConversionElement)