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 "vtkImageData.h"
18 #include "vtkImageProgressIterator.h"
19 #include "vtkMath.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, vtkImageData* inData,
38   vtkImageData* outData, int outExt[6], int id, T*)
39 {
40   vtkImageIterator<T> inIt(inData, outExt);
41   vtkImageProgressIterator<T> outIt(outData, outExt, self, id);
42   double X, Y, Theta, R;
43   double thetaMax = self->GetThetaMaximum();
44 
45   // find the region to loop over
46   int maxC = inData->GetNumberOfScalarComponents();
47 
48   // Loop through output pixels
49   while (!outIt.IsAtEnd())
50   {
51     T* inSI = inIt.BeginSpan();
52     T* outSI = outIt.BeginSpan();
53     T* outSIEnd = outIt.EndSpan();
54     while (outSI != outSIEnd)
55     {
56       // Pixel operation
57       X = static_cast<double>(*inSI);
58       Y = static_cast<double>(inSI[1]);
59 
60       if ((X == 0.0) && (Y == 0.0))
61       {
62         Theta = 0.0;
63         R = 0.0;
64       }
65       else
66       {
67         Theta = atan2(Y, X) * thetaMax / (2.0 * vtkMath::Pi());
68         if (Theta < 0.0)
69         {
70           Theta += thetaMax;
71         }
72         R = sqrt(X * X + Y * Y);
73       }
74 
75       *outSI = static_cast<T>(Theta);
76       outSI[1] = static_cast<T>(R);
77       inSI += maxC;
78       outSI += maxC;
79     }
80     inIt.NextSpan();
81     outIt.NextSpan();
82   }
83 }
84 
85 //------------------------------------------------------------------------------
ThreadedExecute(vtkImageData * inData,vtkImageData * outData,int outExt[6],int id)86 void vtkImageEuclideanToPolar::ThreadedExecute(
87   vtkImageData* inData, vtkImageData* outData, int outExt[6], int id)
88 {
89   vtkDebugMacro(<< "Execute: inData = " << inData << ", outData = " << outData);
90 
91   // this filter expects that input is the same type as output.
92   if (inData->GetScalarType() != outData->GetScalarType())
93   {
94     vtkErrorMacro(<< "Execute: input ScalarType, " << inData->GetScalarType()
95                   << ", must match out ScalarType " << outData->GetScalarType());
96     return;
97   }
98 
99   // input must have at least two components
100   if (inData->GetNumberOfScalarComponents() < 2)
101   {
102     vtkErrorMacro(<< "Execute: input does not have at least two components");
103     return;
104   }
105 
106   switch (inData->GetScalarType())
107   {
108     vtkTemplateMacro(vtkImageEuclideanToPolarExecute(
109       this, inData, outData, outExt, id, static_cast<VTK_TT*>(nullptr)));
110     default:
111       vtkErrorMacro(<< "Execute: Unknown ScalarType");
112       return;
113   }
114 }
115 
PrintSelf(ostream & os,vtkIndent indent)116 void vtkImageEuclideanToPolar::PrintSelf(ostream& os, vtkIndent indent)
117 {
118   this->Superclass::PrintSelf(os, indent);
119 
120   os << indent << "Maximum Angle: " << this->ThetaMaximum << "\n";
121 }
122