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