1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkImageEuclideanToPolar.cxx
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 #include "vtkImageEuclideanToPolar.h"
16 
17 #include "vtkMath.h"
18 #include "vtkImageData.h"
19 #include "vtkImageProgressIterator.h"
20 #include "vtkObjectFactory.h"
21 
22 #include <cmath>
23 
24 vtkStandardNewMacro(vtkImageEuclideanToPolar);
25 
26 //----------------------------------------------------------------------------
vtkImageEuclideanToPolar()27 vtkImageEuclideanToPolar::vtkImageEuclideanToPolar()
28 {
29   this->SetNumberOfInputPorts(1);
30   this->SetNumberOfOutputPorts(1);
31   this->ThetaMaximum = 255.0;
32 }
33 
34 //----------------------------------------------------------------------------
35 // This templated function executes the filter for any type of data.
36 template <class T>
vtkImageEuclideanToPolarExecute(vtkImageEuclideanToPolar * self,vtkImageData * inData,vtkImageData * outData,int outExt[6],int id,T *)37 void vtkImageEuclideanToPolarExecute(vtkImageEuclideanToPolar *self,
38                                      vtkImageData *inData,
39                                      vtkImageData *outData,
40                                      int outExt[6], int id, T *)
41 {
42   vtkImageIterator<T> inIt(inData, outExt);
43   vtkImageProgressIterator<T> outIt(outData, outExt, self, id);
44   double X, Y, Theta, R;
45   double thetaMax = self->GetThetaMaximum();
46 
47   // find the region to loop over
48   int maxC = inData->GetNumberOfScalarComponents();
49 
50   // Loop through output pixels
51   while (!outIt.IsAtEnd())
52   {
53     T* inSI = inIt.BeginSpan();
54     T* outSI = outIt.BeginSpan();
55     T* outSIEnd = outIt.EndSpan();
56     while (outSI != outSIEnd)
57     {
58       // Pixel operation
59       X = static_cast<double>(*inSI);
60       Y = static_cast<double>(inSI[1]);
61 
62       if ((X == 0.0) && (Y == 0.0))
63       {
64         Theta = 0.0;
65         R = 0.0;
66       }
67       else
68       {
69         Theta = atan2(Y, X) * thetaMax / (2.0 * vtkMath::Pi());
70         if (Theta < 0.0)
71         {
72           Theta += thetaMax;
73         }
74         R = sqrt(X*X + Y*Y);
75       }
76 
77       *outSI = static_cast<T>(Theta);
78       outSI[1] = static_cast<T>(R);
79       inSI += maxC;
80       outSI += maxC;
81     }
82     inIt.NextSpan();
83     outIt.NextSpan();
84   }
85 }
86 
87 //----------------------------------------------------------------------------
ThreadedExecute(vtkImageData * inData,vtkImageData * outData,int outExt[6],int id)88 void vtkImageEuclideanToPolar::ThreadedExecute (vtkImageData *inData,
89                                        vtkImageData *outData,
90                                        int outExt[6], int id)
91 {
92   vtkDebugMacro(<< "Execute: inData = " << inData
93                 << ", outData = " << outData);
94 
95   // this filter expects that input is the same type as output.
96   if (inData->GetScalarType() != outData->GetScalarType())
97   {
98     vtkErrorMacro(<< "Execute: input ScalarType, "
99                   << inData->GetScalarType()
100                   << ", must match out ScalarType "
101                   << outData->GetScalarType());
102     return;
103   }
104 
105   // input must have at least two components
106   if (inData->GetNumberOfScalarComponents() < 2)
107   {
108     vtkErrorMacro(<< "Execute: input does not have at least two components");
109     return;
110   }
111 
112   switch (inData->GetScalarType())
113   {
114     vtkTemplateMacro(
115       vtkImageEuclideanToPolarExecute( this,
116                                        inData, outData, outExt, id,
117                                        static_cast<VTK_TT *>(nullptr)));
118     default:
119       vtkErrorMacro(<< "Execute: Unknown ScalarType");
120       return;
121   }
122 }
123 
PrintSelf(ostream & os,vtkIndent indent)124 void vtkImageEuclideanToPolar::PrintSelf(ostream& os, vtkIndent indent)
125 {
126   this->Superclass::PrintSelf(os,indent);
127 
128   os << indent << "Maximum Angle: " << this->ThetaMaximum << "\n";
129 }
130