1 //=============================================================================
2 //
3 //  Copyright (c) Kitware, Inc.
4 //  All rights reserved.
5 //  See LICENSE.txt for details.
6 //
7 //  This software is distributed WITHOUT ANY WARRANTY; without even
8 //  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
9 //  PURPOSE.  See the above copyright notice for more information.
10 //
11 //  Copyright 2016 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
12 //  Copyright 2016 UT-Battelle, LLC.
13 //  Copyright 2016 Los Alamos National Security.
14 //
15 //  Under the terms of Contract DE-NA0003525 with NTESS,
16 //  the U.S. Government retains certain rights in this software.
17 //  Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
18 //  Laboratory (LANL), the U.S. Government retains certain rights in
19 //  this software.
20 //
21 //=============================================================================
22 
23 #include <vtkm/Transform3D.h>
24 
25 #include <vtkm/testing/Testing.h>
26 
27 #include <ctime>
28 #include <random>
29 
30 namespace
31 {
32 
33 std::mt19937 g_RandomGenerator;
34 
35 template <typename T>
36 struct TransformTests
37 {
38   std::uniform_real_distribution<T> RandomDistribution;
TransformTests__anon27c7b8210111::TransformTests39   TransformTests()
40     : RandomDistribution(0.0f, 1.0f)
41   {
42   }
43 
RandomNum__anon27c7b8210111::TransformTests44   T RandomNum() { return this->RandomDistribution(g_RandomGenerator); }
45 
46   using Vec = vtkm::Vec<T, 3>;
47   using Transform = vtkm::Matrix<T, 4, 4>;
48 
RandomVector__anon27c7b8210111::TransformTests49   Vec RandomVector()
50   {
51     Vec vec(this->RandomNum(), this->RandomNum(), this->RandomNum());
52     return T(2) * vec - Vec(1);
53   }
54 
CheckTranslate__anon27c7b8210111::TransformTests55   void CheckTranslate()
56   {
57     std::cout << "--- Checking translate" << std::endl;
58 
59     Vec startPoint = this->RandomVector();
60     std::cout << " Starting point: " << startPoint << std::endl;
61 
62     Vec translateAmount = this->RandomVector();
63     std::cout << " Translation amount: " << translateAmount << std::endl;
64 
65     Transform translate = vtkm::Transform3DTranslate(translateAmount);
66 
67     Vec translated1 = vtkm::Transform3DPoint(translate, startPoint);
68     std::cout << " First translation: " << translated1 << std::endl;
69     VTKM_TEST_ASSERT(test_equal(translated1, startPoint + translateAmount), "Bad translation.");
70 
71     Vec translated2 = vtkm::Transform3DPoint(translate, translated1);
72     std::cout << " Second translation: " << translated2 << std::endl;
73     VTKM_TEST_ASSERT(test_equal(translated2, startPoint + T(2) * translateAmount),
74                      "Bad translation.");
75 
76     // Vectors should be invariant to translation.
77     translated1 = vtkm::Transform3DVector(translate, startPoint);
78     std::cout << " Translated vector: " << translated1 << std::endl;
79     VTKM_TEST_ASSERT(test_equal(translated1, startPoint), "Bad translation.");
80   }
81 
CheckScale__anon27c7b8210111::TransformTests82   void CheckScale()
83   {
84     std::cout << "--- Checking scale" << std::endl;
85 
86     Vec startPoint = this->RandomVector();
87     std::cout << " Starting point: " << startPoint << std::endl;
88 
89     Vec scaleAmount = this->RandomVector();
90     std::cout << " Scale amount: " << scaleAmount << std::endl;
91 
92     Transform scale = vtkm::Transform3DScale(scaleAmount);
93 
94     Vec scaled1 = vtkm::Transform3DPoint(scale, startPoint);
95     std::cout << " First scale: " << scaled1 << std::endl;
96     VTKM_TEST_ASSERT(test_equal(scaled1, startPoint * scaleAmount), "Bad scale.");
97 
98     Vec scaled2 = vtkm::Transform3DPoint(scale, scaled1);
99     std::cout << " Second scale: " << scaled2 << std::endl;
100     VTKM_TEST_ASSERT(test_equal(scaled2, startPoint * scaleAmount * scaleAmount), "Bad scale.");
101 
102     // Vectors should scale the same as points.
103     scaled1 = vtkm::Transform3DVector(scale, startPoint);
104     std::cout << " Scaled vector: " << scaled1 << std::endl;
105     VTKM_TEST_ASSERT(test_equal(scaled1, startPoint * scaleAmount), "Bad scale.");
106   }
107 
CheckRotate__anon27c7b8210111::TransformTests108   void CheckRotate()
109   {
110     std::cout << "--- Checking rotate" << std::endl;
111 
112     Vec startPoint = this->RandomVector();
113     std::cout << " Starting point: " << startPoint << std::endl;
114 
115     const T ninetyDegrees = T(90);
116 
117     std::cout << "--Rotate 90 degrees around X" << std::endl;
118     Transform rotateX = vtkm::Transform3DRotateX(ninetyDegrees);
119 
120     Vec rotated1 = vtkm::Transform3DPoint(rotateX, startPoint);
121     std::cout << " First rotate: " << rotated1 << std::endl;
122     VTKM_TEST_ASSERT(test_equal(rotated1, Vec(startPoint[0], -startPoint[2], startPoint[1])),
123                      "Bad rotate.");
124 
125     Vec rotated2 = vtkm::Transform3DPoint(rotateX, rotated1);
126     std::cout << " Second rotate: " << rotated2 << std::endl;
127     VTKM_TEST_ASSERT(test_equal(rotated2, Vec(startPoint[0], -startPoint[1], -startPoint[2])),
128                      "Bad rotate.");
129 
130     // Vectors should rotate the same as points.
131     rotated1 = vtkm::Transform3DVector(rotateX, startPoint);
132     std::cout << " Vector rotate: " << rotated1 << std::endl;
133     VTKM_TEST_ASSERT(test_equal(rotated1, Vec(startPoint[0], -startPoint[2], startPoint[1])),
134                      "Bad rotate.");
135 
136     std::cout << "--Rotate 90 degrees around Y" << std::endl;
137     Transform rotateY = vtkm::Transform3DRotateY(ninetyDegrees);
138 
139     rotated1 = vtkm::Transform3DPoint(rotateY, startPoint);
140     std::cout << " First rotate: " << rotated1 << std::endl;
141     VTKM_TEST_ASSERT(test_equal(rotated1, Vec(startPoint[2], startPoint[1], -startPoint[0])),
142                      "Bad rotate.");
143 
144     rotated2 = vtkm::Transform3DPoint(rotateY, rotated1);
145     std::cout << " Second rotate: " << rotated2 << std::endl;
146     VTKM_TEST_ASSERT(test_equal(rotated2, Vec(-startPoint[0], startPoint[1], -startPoint[2])),
147                      "Bad rotate.");
148 
149     // Vectors should rotate the same as points.
150     rotated1 = vtkm::Transform3DVector(rotateY, startPoint);
151     std::cout << " Vector rotate: " << rotated1 << std::endl;
152     VTKM_TEST_ASSERT(test_equal(rotated1, Vec(startPoint[2], startPoint[1], -startPoint[0])),
153                      "Bad rotate.");
154 
155     std::cout << "--Rotate 90 degrees around Z" << std::endl;
156     Transform rotateZ = vtkm::Transform3DRotateZ(ninetyDegrees);
157 
158     rotated1 = vtkm::Transform3DPoint(rotateZ, startPoint);
159     std::cout << " First rotate: " << rotated1 << std::endl;
160     VTKM_TEST_ASSERT(test_equal(rotated1, Vec(-startPoint[1], startPoint[0], startPoint[2])),
161                      "Bad rotate.");
162 
163     rotated2 = vtkm::Transform3DPoint(rotateZ, rotated1);
164     std::cout << " Second rotate: " << rotated2 << std::endl;
165     VTKM_TEST_ASSERT(test_equal(rotated2, Vec(-startPoint[0], -startPoint[1], startPoint[2])),
166                      "Bad rotate.");
167 
168     // Vectors should rotate the same as points.
169     rotated1 = vtkm::Transform3DVector(rotateZ, startPoint);
170     std::cout << " Vector rotate: " << rotated1 << std::endl;
171     VTKM_TEST_ASSERT(test_equal(rotated1, Vec(-startPoint[1], startPoint[0], startPoint[2])),
172                      "Bad rotate.");
173   }
174 
CheckPerspective__anon27c7b8210111::TransformTests175   void CheckPerspective()
176   {
177     std::cout << "--- Checking Perspective" << std::endl;
178 
179     Vec startPoint = this->RandomVector();
180     std::cout << " Starting point: " << startPoint << std::endl;
181 
182     Transform perspective(0);
183     perspective(0, 0) = 1;
184     perspective(1, 1) = 1;
185     perspective(2, 2) = 1;
186     perspective(3, 2) = 1;
187 
188     Vec projected = vtkm::Transform3DPointPerspective(perspective, startPoint);
189     std::cout << " Projected: " << projected << std::endl;
190     VTKM_TEST_ASSERT(test_equal(projected, startPoint / startPoint[2]), "Bad perspective.");
191   }
192 };
193 
194 struct TryTransformsFunctor
195 {
196   template <typename T>
operator ()__anon27c7b8210111::TryTransformsFunctor197   void operator()(T) const
198   {
199     TransformTests<T> tests;
200     tests.CheckTranslate();
201     tests.CheckScale();
202     tests.CheckRotate();
203   }
204 };
205 
TestTransforms()206 void TestTransforms()
207 {
208   vtkm::UInt32 seed = static_cast<vtkm::UInt32>(std::time(nullptr));
209   std::cout << "Seed: " << seed << std::endl;
210   g_RandomGenerator.seed(seed);
211 
212   vtkm::testing::Testing::TryTypes(TryTransformsFunctor(), vtkm::TypeListTagFieldScalar());
213 }
214 
215 } // anonymous namespace
216 
UnitTestTransform3D(int,char * [])217 int UnitTestTransform3D(int, char* [])
218 {
219   return vtkm::testing::Testing::Run(TestTransforms);
220 }
221