1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkAngularPeriodicDataArray.txx
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 
16 #include "vtkMath.h"
17 #include "vtkMatrix3x3.h"
18 #include "vtkObjectFactory.h"
19 
20 #include <algorithm>
21 
22 //------------------------------------------------------------------------------
23 // Can't use vtkStandardNewMacro on a templated class.
24 template <class Scalar>
New()25 vtkAngularPeriodicDataArray<Scalar>* vtkAngularPeriodicDataArray<Scalar>::New()
26 {
27   VTK_STANDARD_NEW_BODY(vtkAngularPeriodicDataArray<Scalar>);
28 }
29 
30 //------------------------------------------------------------------------------
31 template <class Scalar>
PrintSelf(ostream & os,vtkIndent indent)32 void vtkAngularPeriodicDataArray<Scalar>::PrintSelf(ostream& os, vtkIndent indent)
33 {
34   this->vtkAngularPeriodicDataArray<Scalar>::Superclass::PrintSelf(os, indent);
35   os << indent << "Axis: " << this->Axis << "\n";
36   os << indent << "Angle: " << this->Angle << "\n";
37   os << indent << "Center: " << this->Center[0] << " " << this->Center[1] << " " << this->Center[2]
38      << "\n";
39 }
40 
41 //------------------------------------------------------------------------------
42 template <class Scalar>
InitializeArray(vtkAOSDataArrayTemplate<Scalar> * data)43 void vtkAngularPeriodicDataArray<Scalar>::InitializeArray(vtkAOSDataArrayTemplate<Scalar>* data)
44 {
45   this->Initialize();
46   if (!data)
47   {
48     vtkErrorMacro(<< "No original data provided.");
49     return;
50   }
51 
52   if (data->GetNumberOfComponents() != 3 && data->GetNumberOfComponents() != 6 &&
53     data->GetNumberOfComponents() != 9)
54   {
55     vtkWarningMacro(<< "Original data has " << data->GetNumberOfComponents()
56                     << " components, Expecting 3 or 9.");
57     return;
58   }
59 
60   this->Superclass::InitializeArray(data);
61 }
62 
63 //------------------------------------------------------------------------------
64 template <class Scalar>
SetAngle(double angle)65 void vtkAngularPeriodicDataArray<Scalar>::SetAngle(double angle)
66 {
67   if (this->Angle != angle)
68   {
69     this->Angle = angle;
70     this->AngleInRadians = vtkMath::RadiansFromDegrees(angle);
71     this->InvalidateRange();
72     this->UpdateRotationMatrix();
73     this->Modified();
74   }
75 }
76 
77 //------------------------------------------------------------------------------
78 template <class Scalar>
SetAxis(int axis)79 void vtkAngularPeriodicDataArray<Scalar>::SetAxis(int axis)
80 {
81   if (this->Axis != axis)
82   {
83     this->Axis = axis;
84     this->InvalidateRange();
85     this->UpdateRotationMatrix();
86     this->Modified();
87   }
88 }
89 
90 //------------------------------------------------------------------------------
91 template <class Scalar>
SetCenter(double * center)92 void vtkAngularPeriodicDataArray<Scalar>::SetCenter(double* center)
93 {
94   if (center)
95   {
96     bool diff = false;
97     for (int i = 0; i < 3; i++)
98     {
99       if (this->Center[i] != center[i])
100       {
101         this->Center[i] = center[i];
102         diff = true;
103       }
104     }
105     if (diff)
106     {
107       this->InvalidateRange();
108       this->Modified();
109     }
110   }
111 }
112 
113 //------------------------------------------------------------------------------
114 template <class Scalar>
Transform(Scalar * pos) const115 void vtkAngularPeriodicDataArray<Scalar>::Transform(Scalar* pos) const
116 {
117   if (this->NumberOfComponents == 3)
118   {
119     // Axis rotation
120     int axis0 = (this->Axis + 1) % this->NumberOfComponents;
121     int axis1 = (this->Axis + 2) % this->NumberOfComponents;
122     double posx = static_cast<double>(pos[axis0]) - this->Center[axis0];
123     double posy = static_cast<double>(pos[axis1]) - this->Center[axis1];
124 
125     pos[axis0] = this->Center[axis0] +
126       static_cast<Scalar>(cos(this->AngleInRadians) * posx - sin(this->AngleInRadians) * posy);
127     pos[axis1] = this->Center[axis1] +
128       static_cast<Scalar>(sin(this->AngleInRadians) * posx + cos(this->AngleInRadians) * posy);
129     if (this->Normalize)
130     {
131       vtkMath::Normalize(pos);
132     }
133   }
134   else if (this->NumberOfComponents == 9 || this->NumberOfComponents == 6)
135   {
136     // Template type force a copy to a double array for tensor
137     double localPos[9];
138     double tmpMat[9];
139     double tmpMat2[9];
140     std::copy(pos, pos + this->NumberOfComponents, localPos);
141     if (this->NumberOfComponents == 6)
142     {
143       vtkMath::TensorFromSymmetricTensor(localPos);
144     }
145 
146     vtkMatrix3x3::Transpose(this->RotationMatrix->GetData(), tmpMat);
147     vtkMatrix3x3::Multiply3x3(this->RotationMatrix->GetData(), localPos, tmpMat2);
148     vtkMatrix3x3::Multiply3x3(tmpMat2, tmpMat, localPos);
149     std::copy(localPos, localPos + this->NumberOfComponents, pos);
150   }
151 }
152 
153 //------------------------------------------------------------------------------
154 template <class Scalar>
UpdateRotationMatrix()155 void vtkAngularPeriodicDataArray<Scalar>::UpdateRotationMatrix()
156 {
157   int axis0 = (this->Axis + 1) % 3;
158   int axis1 = (this->Axis + 2) % 3;
159   this->RotationMatrix->Identity();
160   this->RotationMatrix->SetElement(this->Axis, this->Axis, 1.);
161   this->RotationMatrix->SetElement(axis0, axis0, cos(this->AngleInRadians));
162   this->RotationMatrix->SetElement(axis0, axis1, -sin(this->AngleInRadians));
163   this->RotationMatrix->SetElement(axis1, axis0, sin(this->AngleInRadians));
164   this->RotationMatrix->SetElement(axis1, axis1, cos(this->AngleInRadians));
165 }
166 
167 //------------------------------------------------------------------------------
168 template <class Scalar>
vtkAngularPeriodicDataArray()169 vtkAngularPeriodicDataArray<Scalar>::vtkAngularPeriodicDataArray()
170 {
171   this->Axis = VTK_PERIODIC_ARRAY_AXIS_X;
172   this->Angle = 0.0;
173   this->AngleInRadians = 0.0;
174   this->Center[0] = 0.0;
175   this->Center[1] = 0.0;
176   this->Center[2] = 0.0;
177 
178   this->RotationMatrix = vtkMatrix3x3::New();
179   this->RotationMatrix->Identity();
180 }
181 
182 //------------------------------------------------------------------------------
183 template <class Scalar>
~vtkAngularPeriodicDataArray()184 vtkAngularPeriodicDataArray<Scalar>::~vtkAngularPeriodicDataArray()
185 {
186   this->RotationMatrix->Delete();
187 }
188