1 //============================================================================
2 // Copyright (c) Kitware, Inc.
3 // All rights reserved.
4 // See LICENSE.txt for details.
5 //
6 // This software is distributed WITHOUT ANY WARRANTY; without even
7 // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
8 // PURPOSE. See the above copyright notice for more information.
9 //============================================================================
10
11 #include <vtkm/cont/testing/Testing.h>
12 #include <vtkm/filter/PointTransform.h>
13
14 #include <random>
15 #include <string>
16 #include <vector>
17
18 namespace
19 {
20 std::mt19937 randGenerator;
21
MakePointTransformTestDataSet()22 vtkm::cont::DataSet MakePointTransformTestDataSet()
23 {
24 vtkm::cont::DataSet dataSet;
25
26 std::vector<vtkm::Vec3f> coordinates;
27 const vtkm::Id dim = 5;
28 for (vtkm::Id j = 0; j < dim; ++j)
29 {
30 vtkm::FloatDefault z =
31 static_cast<vtkm::FloatDefault>(j) / static_cast<vtkm::FloatDefault>(dim - 1);
32 for (vtkm::Id i = 0; i < dim; ++i)
33 {
34 vtkm::FloatDefault x =
35 static_cast<vtkm::FloatDefault>(i) / static_cast<vtkm::FloatDefault>(dim - 1);
36 vtkm::FloatDefault y = (x * x + z * z) / 2.0f;
37 coordinates.push_back(vtkm::make_Vec(x, y, z));
38 }
39 }
40
41 vtkm::Id numCells = (dim - 1) * (dim - 1);
42 dataSet.AddCoordinateSystem(
43 vtkm::cont::make_CoordinateSystem("coordinates", coordinates, vtkm::CopyFlag::On));
44
45 vtkm::cont::CellSetExplicit<> cellSet;
46 cellSet.PrepareToAddCells(numCells, numCells * 4);
47 for (vtkm::Id j = 0; j < dim - 1; ++j)
48 {
49 for (vtkm::Id i = 0; i < dim - 1; ++i)
50 {
51 cellSet.AddCell(vtkm::CELL_SHAPE_QUAD,
52 4,
53 vtkm::make_Vec<vtkm::Id>(
54 j * dim + i, j * dim + i + 1, (j + 1) * dim + i + 1, (j + 1) * dim + i));
55 }
56 }
57 cellSet.CompleteAddingCells(vtkm::Id(coordinates.size()));
58
59 dataSet.SetCellSet(cellSet);
60 return dataSet;
61 }
62
ValidatePointTransform(const vtkm::cont::CoordinateSystem & coords,const std::string fieldName,const vtkm::cont::DataSet & result,const vtkm::Matrix<vtkm::FloatDefault,4,4> & matrix)63 void ValidatePointTransform(const vtkm::cont::CoordinateSystem& coords,
64 const std::string fieldName,
65 const vtkm::cont::DataSet& result,
66 const vtkm::Matrix<vtkm::FloatDefault, 4, 4>& matrix)
67 {
68 //verify the result
69 VTKM_TEST_ASSERT(result.HasField(fieldName, vtkm::cont::Field::Association::POINTS),
70 "Output field missing.");
71
72 vtkm::cont::ArrayHandle<vtkm::Vec3f> resultArrayHandle;
73 result.GetField(fieldName, vtkm::cont::Field::Association::POINTS)
74 .GetData()
75 .AsArrayHandle(resultArrayHandle);
76
77 auto outPointsArrayHandle = result.GetCoordinateSystem().GetDataAsMultiplexer();
78
79 auto points = coords.GetDataAsMultiplexer();
80 VTKM_TEST_ASSERT(points.GetNumberOfValues() == resultArrayHandle.GetNumberOfValues(),
81 "Incorrect number of points in point transform");
82
83 auto pointsPortal = points.ReadPortal();
84 auto resultsPortal = resultArrayHandle.ReadPortal();
85 auto outPointsPortal = outPointsArrayHandle.ReadPortal();
86
87 for (vtkm::Id i = 0; i < points.GetNumberOfValues(); i++)
88 {
89 VTKM_TEST_ASSERT(
90 test_equal(resultsPortal.Get(i), vtkm::Transform3DPoint(matrix, pointsPortal.Get(i))),
91 "Wrong result for PointTransform worklet");
92 VTKM_TEST_ASSERT(
93 test_equal(outPointsPortal.Get(i), vtkm::Transform3DPoint(matrix, pointsPortal.Get(i))),
94 "Wrong result for PointTransform worklet");
95 }
96 }
97
98
TestPointTransformTranslation(const vtkm::cont::DataSet & ds,const vtkm::Vec3f & trans)99 void TestPointTransformTranslation(const vtkm::cont::DataSet& ds, const vtkm::Vec3f& trans)
100 {
101 vtkm::filter::PointTransform filter;
102
103 filter.SetOutputFieldName("translation");
104 filter.SetTranslation(trans);
105 vtkm::cont::DataSet result = filter.Execute(ds);
106
107 ValidatePointTransform(
108 ds.GetCoordinateSystem(), "translation", result, Transform3DTranslate(trans));
109 }
110
TestPointTransformScale(const vtkm::cont::DataSet & ds,const vtkm::Vec3f & scale)111 void TestPointTransformScale(const vtkm::cont::DataSet& ds, const vtkm::Vec3f& scale)
112 {
113 vtkm::filter::PointTransform filter;
114
115 filter.SetOutputFieldName("scale");
116 filter.SetScale(scale);
117 vtkm::cont::DataSet result = filter.Execute(ds);
118
119 ValidatePointTransform(ds.GetCoordinateSystem(), "scale", result, Transform3DScale(scale));
120 }
121
TestPointTransformRotation(const vtkm::cont::DataSet & ds,const vtkm::FloatDefault & angle,const vtkm::Vec3f & axis)122 void TestPointTransformRotation(const vtkm::cont::DataSet& ds,
123 const vtkm::FloatDefault& angle,
124 const vtkm::Vec3f& axis)
125 {
126 vtkm::filter::PointTransform filter;
127
128 filter.SetOutputFieldName("rotation");
129 filter.SetRotation(angle, axis);
130 vtkm::cont::DataSet result = filter.Execute(ds);
131
132 ValidatePointTransform(
133 ds.GetCoordinateSystem(), "rotation", result, Transform3DRotate(angle, axis));
134 }
135 }
136
TestPointTransform()137 void TestPointTransform()
138 {
139 std::cout << "Testing PointTransform Worklet" << std::endl;
140
141 vtkm::cont::DataSet ds = MakePointTransformTestDataSet();
142 int N = 41;
143
144 //Test translation
145 TestPointTransformTranslation(ds, vtkm::Vec3f(0, 0, 0));
146 TestPointTransformTranslation(ds, vtkm::Vec3f(1, 1, 1));
147 TestPointTransformTranslation(ds, vtkm::Vec3f(-1, -1, -1));
148
149 std::uniform_real_distribution<vtkm::FloatDefault> transDist(-100, 100);
150 for (int i = 0; i < N; i++)
151 TestPointTransformTranslation(
152 ds,
153 vtkm::Vec3f(transDist(randGenerator), transDist(randGenerator), transDist(randGenerator)));
154
155 //Test scaling
156 TestPointTransformScale(ds, vtkm::Vec3f(1, 1, 1));
157 TestPointTransformScale(ds, vtkm::Vec3f(.23f, .23f, .23f));
158 TestPointTransformScale(ds, vtkm::Vec3f(1, 2, 3));
159 TestPointTransformScale(ds, vtkm::Vec3f(3.23f, 9.23f, 4.23f));
160
161 std::uniform_real_distribution<vtkm::FloatDefault> scaleDist(0.0001f, 100);
162 for (int i = 0; i < N; i++)
163 {
164 TestPointTransformScale(ds, vtkm::Vec3f(scaleDist(randGenerator)));
165 TestPointTransformScale(
166 ds,
167 vtkm::Vec3f(scaleDist(randGenerator), scaleDist(randGenerator), scaleDist(randGenerator)));
168 }
169
170 //Test rotation
171 std::vector<vtkm::FloatDefault> angles;
172 std::uniform_real_distribution<vtkm::FloatDefault> angleDist(0, 360);
173 for (int i = 0; i < N; i++)
174 angles.push_back(angleDist(randGenerator));
175
176 std::vector<vtkm::Vec3f> axes;
177 axes.push_back(vtkm::Vec3f(1, 0, 0));
178 axes.push_back(vtkm::Vec3f(0, 1, 0));
179 axes.push_back(vtkm::Vec3f(0, 0, 1));
180 axes.push_back(vtkm::Vec3f(1, 1, 1));
181 axes.push_back(-axes[0]);
182 axes.push_back(-axes[1]);
183 axes.push_back(-axes[2]);
184 axes.push_back(-axes[3]);
185
186 std::uniform_real_distribution<vtkm::FloatDefault> axisDist(-1, 1);
187 for (int i = 0; i < N; i++)
188 axes.push_back(
189 vtkm::Vec3f(axisDist(randGenerator), axisDist(randGenerator), axisDist(randGenerator)));
190
191 for (std::size_t i = 0; i < angles.size(); i++)
192 for (std::size_t j = 0; j < axes.size(); j++)
193 TestPointTransformRotation(ds, angles[i], axes[j]);
194 }
195
196
UnitTestPointTransform(int argc,char * argv[])197 int UnitTestPointTransform(int argc, char* argv[])
198 {
199 return vtkm::cont::testing::Testing::Run(TestPointTransform, argc, argv);
200 }
201