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/worklet/Clip.h>
12
13 #include <vtkm/cont/CellSet.h>
14 #include <vtkm/cont/CellSetExplicit.h>
15 #include <vtkm/cont/CellSetStructured.h>
16 #include <vtkm/cont/CoordinateSystem.h>
17 #include <vtkm/cont/DataSet.h>
18 #include <vtkm/cont/DataSetBuilderExplicit.h>
19 #include <vtkm/cont/DataSetBuilderUniform.h>
20 #include <vtkm/cont/Field.h>
21 #include <vtkm/cont/ImplicitFunctionHandle.h>
22 #include <vtkm/cont/testing/Testing.h>
23
24
25 #include <vector>
26
27 using Coord3D = vtkm::Vec<vtkm::FloatDefault, 3>;
28
29 const vtkm::Float32 clipValue = 0.5;
30
31 template <typename T, typename Storage>
TestArrayHandle(const vtkm::cont::ArrayHandle<T,Storage> & ah,const T * expected,vtkm::Id size)32 bool TestArrayHandle(const vtkm::cont::ArrayHandle<T, Storage>& ah,
33 const T* expected,
34 vtkm::Id size)
35 {
36 if (size != ah.GetNumberOfValues())
37 {
38 return false;
39 }
40
41 for (vtkm::Id i = 0; i < size; ++i)
42 {
43 if (ah.ReadPortal().Get(i) != expected[i])
44 {
45 return false;
46 }
47 }
48
49 return true;
50 }
51
MakeTestDatasetExplicit()52 vtkm::cont::DataSet MakeTestDatasetExplicit()
53 {
54 std::vector<Coord3D> coords;
55 coords.push_back(Coord3D(0.0f, 0.0f, 0.0f));
56 coords.push_back(Coord3D(1.0f, 0.0f, 0.0f));
57 coords.push_back(Coord3D(1.0f, 1.0f, 0.0f));
58 coords.push_back(Coord3D(0.0f, 1.0f, 0.0f));
59
60 std::vector<vtkm::Id> connectivity;
61 connectivity.push_back(0);
62 connectivity.push_back(1);
63 connectivity.push_back(3);
64 connectivity.push_back(3);
65 connectivity.push_back(1);
66 connectivity.push_back(2);
67
68 vtkm::cont::DataSet ds;
69 vtkm::cont::DataSetBuilderExplicit builder;
70 ds = builder.Create(coords, vtkm::CellShapeTagTriangle(), 3, connectivity, "coords");
71
72 std::vector<vtkm::Float32> values;
73 values.push_back(1.0);
74 values.push_back(2.0);
75 values.push_back(1.0);
76 values.push_back(0.0);
77 ds.AddPointField("scalars", values);
78
79 values.clear();
80 values.push_back(100.f);
81 values.push_back(-100.f);
82 ds.AddCellField("cellvar", values);
83
84 return ds;
85 }
86
MakeTestDatasetStructured()87 vtkm::cont::DataSet MakeTestDatasetStructured()
88 {
89 static constexpr vtkm::Id xdim = 3, ydim = 3;
90 static const vtkm::Id2 dim(xdim, ydim);
91 static constexpr vtkm::Id numVerts = xdim * ydim;
92
93 vtkm::Float32 scalars[numVerts];
94 for (vtkm::Id i = 0; i < numVerts; ++i)
95 {
96 scalars[i] = 1.0f;
97 }
98 scalars[4] = 0.0f;
99
100 vtkm::cont::DataSet ds;
101 vtkm::cont::DataSetBuilderUniform builder;
102 ds = builder.Create(dim);
103
104 ds.AddPointField("scalars", scalars, numVerts);
105
106 std::vector<vtkm::Float32> cellvar = { -100.f, 100.f, 30.f, -30.f };
107 ds.AddCellField("cellvar", cellvar);
108
109 return ds;
110 }
111
TestClippingExplicit()112 void TestClippingExplicit()
113 {
114 vtkm::cont::DataSet ds = MakeTestDatasetExplicit();
115 vtkm::worklet::Clip clip;
116 bool invertClip = false;
117 vtkm::cont::CellSetExplicit<> outputCellSet =
118 clip.Run(ds.GetCellSet(),
119 ds.GetField("scalars").GetData().ResetTypes(vtkm::TypeListFieldScalar()),
120 clipValue,
121 invertClip);
122
123 auto coordsIn = ds.GetCoordinateSystem("coords").GetData();
124 vtkm::cont::ArrayHandle<Coord3D> coords = clip.ProcessPointField(coordsIn);
125
126 vtkm::cont::ArrayHandle<vtkm::Float32> scalarsIn;
127 ds.GetField("scalars").GetData().CopyTo(scalarsIn);
128 vtkm::cont::ArrayHandle<vtkm::Float32> scalars = clip.ProcessPointField(scalarsIn);
129
130 vtkm::cont::ArrayHandle<vtkm::Float32> cellvarIn;
131 ds.GetField("cellvar").GetData().CopyTo(cellvarIn);
132 vtkm::cont::ArrayHandle<vtkm::Float32> cellvar = clip.ProcessCellField(cellvarIn);
133
134 vtkm::Id connectivitySize = 8;
135 vtkm::Id fieldSize = 7;
136 vtkm::Id expectedConnectivity[] = { 0, 1, 5, 4, 1, 2, 6, 5 };
137 const Coord3D expectedCoords[] = {
138 Coord3D(0.00f, 0.00f, 0.0f), Coord3D(1.00f, 0.00f, 0.0f), Coord3D(1.00f, 1.00f, 0.0f),
139 Coord3D(0.00f, 1.00f, 0.0f), Coord3D(0.00f, 0.50f, 0.0f), Coord3D(0.25f, 0.75f, 0.0f),
140 Coord3D(0.50f, 1.00f, 0.0f),
141 };
142 const vtkm::Float32 expectedScalars[] = { 1, 2, 1, 0, 0.5, 0.5, 0.5 };
143 std::vector<vtkm::Float32> expectedCellvar = { 100.f, -100.f };
144
145 VTKM_TEST_ASSERT(outputCellSet.GetNumberOfPoints() == fieldSize,
146 "Wrong number of points in cell set.");
147
148 VTKM_TEST_ASSERT(
149 TestArrayHandle(outputCellSet.GetConnectivityArray(vtkm::TopologyElementTagCell(),
150 vtkm::TopologyElementTagPoint()),
151 expectedConnectivity,
152 connectivitySize),
153 "Got incorrect conectivity");
154
155 VTKM_TEST_ASSERT(TestArrayHandle(coords, expectedCoords, fieldSize), "Got incorrect coordinates");
156
157 VTKM_TEST_ASSERT(TestArrayHandle(scalars, expectedScalars, fieldSize), "Got incorrect scalars");
158
159 VTKM_TEST_ASSERT(
160 TestArrayHandle(cellvar, expectedCellvar.data(), static_cast<vtkm::Id>(expectedCellvar.size())),
161 "Got incorrect cellvar");
162 }
163
TestClippingStructured()164 void TestClippingStructured()
165 {
166 using CoordsValueType = vtkm::cont::ArrayHandleUniformPointCoordinates::ValueType;
167 using CoordsOutType = vtkm::cont::ArrayHandle<CoordsValueType>;
168
169 vtkm::cont::DataSet ds = MakeTestDatasetStructured();
170
171 bool invertClip = false;
172 vtkm::worklet::Clip clip;
173 vtkm::cont::CellSetExplicit<> outputCellSet =
174 clip.Run(ds.GetCellSet(),
175 ds.GetField("scalars").GetData().ResetTypes(vtkm::TypeListFieldScalar()),
176 clipValue,
177 invertClip);
178
179 auto coordsIn = ds.GetCoordinateSystem("coords").GetData();
180 CoordsOutType coords = clip.ProcessPointField(coordsIn);
181
182 vtkm::cont::ArrayHandle<vtkm::Float32> scalarsIn;
183 ds.GetField("scalars").GetData().CopyTo(scalarsIn);
184 vtkm::cont::ArrayHandle<vtkm::Float32> scalars = clip.ProcessPointField(scalarsIn);
185
186 vtkm::cont::ArrayHandle<vtkm::Float32> cellvarIn;
187 ds.GetField("cellvar").GetData().CopyTo(cellvarIn);
188 vtkm::cont::ArrayHandle<vtkm::Float32> cellvar = clip.ProcessCellField(cellvarIn);
189
190
191 vtkm::Id connectivitySize = 28;
192 vtkm::Id fieldSize = 13;
193 const vtkm::Id expectedConnectivity[] = { 9, 10, 3, 1, 1, 3, 0, 11, 9, 1, 5, 5, 1, 2,
194 10, 12, 7, 3, 3, 7, 6, 12, 11, 5, 7, 7, 5, 8 };
195
196 const Coord3D expectedCoords[] = {
197 Coord3D(0.0f, 0.0f, 0.0f), Coord3D(1.0f, 0.0f, 0.0f), Coord3D(2.0f, 0.0f, 0.0f),
198 Coord3D(0.0f, 1.0f, 0.0f), Coord3D(1.0f, 1.0f, 0.0f), Coord3D(2.0f, 1.0f, 0.0f),
199 Coord3D(0.0f, 2.0f, 0.0f), Coord3D(1.0f, 2.0f, 0.0f), Coord3D(2.0f, 2.0f, 0.0f),
200 Coord3D(1.0f, 0.5f, 0.0f), Coord3D(0.5f, 1.0f, 0.0f), Coord3D(1.5f, 1.0f, 0.0f),
201 Coord3D(1.0f, 1.5f, 0.0f),
202 };
203 const vtkm::Float32 expectedScalars[] = { 1, 1, 1, 1, 0, 1, 1, 1, 1, 0.5, 0.5, 0.5, 0.5 };
204 std::vector<vtkm::Float32> expectedCellvar = { -100.f, -100.f, 100.f, 100.f,
205 30.f, 30.f, -30.f, -30.f };
206
207 VTKM_TEST_ASSERT(outputCellSet.GetNumberOfPoints() == fieldSize,
208 "Wrong number of points in cell set.");
209
210 VTKM_TEST_ASSERT(
211 TestArrayHandle(outputCellSet.GetConnectivityArray(vtkm::TopologyElementTagCell(),
212 vtkm::TopologyElementTagPoint()),
213 expectedConnectivity,
214 connectivitySize),
215 "Got incorrect conectivity");
216
217 VTKM_TEST_ASSERT(TestArrayHandle(coords, expectedCoords, fieldSize), "Got incorrect coordinates");
218
219 VTKM_TEST_ASSERT(TestArrayHandle(scalars, expectedScalars, fieldSize), "Got incorrect scalars");
220
221 VTKM_TEST_ASSERT(
222 TestArrayHandle(cellvar, expectedCellvar.data(), static_cast<vtkm::Id>(expectedCellvar.size())),
223 "Got incorrect cellvar");
224 }
225
TestClippingWithImplicitFunction()226 void TestClippingWithImplicitFunction()
227 {
228 vtkm::Vec<vtkm::FloatDefault, 3> center(1, 1, 0);
229 vtkm::FloatDefault radius(0.5);
230
231 vtkm::cont::DataSet ds = MakeTestDatasetStructured();
232
233 bool invertClip = false;
234 vtkm::worklet::Clip clip;
235 vtkm::cont::CellSetExplicit<> outputCellSet =
236 clip.Run(ds.GetCellSet(),
237 vtkm::cont::make_ImplicitFunctionHandle<vtkm::Sphere>(center, radius),
238 ds.GetCoordinateSystem("coords"),
239 invertClip);
240
241 auto coordsIn = ds.GetCoordinateSystem("coords").GetData();
242 vtkm::cont::ArrayHandle<Coord3D> coords = clip.ProcessPointField(coordsIn);
243
244 vtkm::cont::ArrayHandle<vtkm::Float32> scalarsIn;
245 ds.GetField("scalars").GetData().CopyTo(scalarsIn);
246 vtkm::cont::ArrayHandle<vtkm::Float32> scalars = clip.ProcessPointField(scalarsIn);
247
248 vtkm::cont::ArrayHandle<vtkm::Float32> cellvarIn;
249 ds.GetField("cellvar").GetData().CopyTo(cellvarIn);
250 vtkm::cont::ArrayHandle<vtkm::Float32> cellvar = clip.ProcessCellField(cellvarIn);
251
252 vtkm::Id connectivitySize = 28;
253 vtkm::Id fieldSize = 13;
254
255 const vtkm::Id expectedConnectivity[] = { 9, 10, 3, 1, 1, 3, 0, 11, 9, 1, 5, 5, 1, 2,
256 10, 12, 7, 3, 3, 7, 6, 12, 11, 5, 7, 7, 5, 8 };
257
258 const Coord3D expectedCoords[] = {
259 Coord3D(0.0f, 0.0f, 0.0f), Coord3D(1.0f, 0.0f, 0.0f), Coord3D(2.0f, 0.0f, 0.0f),
260 Coord3D(0.0f, 1.0f, 0.0f), Coord3D(1.0f, 1.0f, 0.0f), Coord3D(2.0f, 1.0f, 0.0f),
261 Coord3D(0.0f, 2.0f, 0.0f), Coord3D(1.0f, 2.0f, 0.0f), Coord3D(2.0f, 2.0f, 0.0f),
262 Coord3D(1.0f, 0.75f, 0.0f), Coord3D(0.75f, 1.0f, 0.0f), Coord3D(1.25f, 1.0f, 0.0f),
263 Coord3D(1.0f, 1.25f, 0.0f),
264 };
265 const vtkm::Float32 expectedScalars[] = { 1, 1, 1, 1, 0, 1, 1, 1, 1, 0.25, 0.25, 0.25, 0.25 };
266 std::vector<vtkm::Float32> expectedCellvar = { -100.f, -100.f, 100.f, 100.f,
267 30.f, 30.f, -30.f, -30.f };
268
269 VTKM_TEST_ASSERT(
270 TestArrayHandle(outputCellSet.GetConnectivityArray(vtkm::TopologyElementTagCell(),
271 vtkm::TopologyElementTagPoint()),
272 expectedConnectivity,
273 connectivitySize),
274 "Got incorrect conectivity");
275
276 VTKM_TEST_ASSERT(TestArrayHandle(coords, expectedCoords, fieldSize), "Got incorrect coordinates");
277
278 VTKM_TEST_ASSERT(TestArrayHandle(scalars, expectedScalars, fieldSize), "Got incorrect scalars");
279
280 VTKM_TEST_ASSERT(
281 TestArrayHandle(cellvar, expectedCellvar.data(), static_cast<vtkm::Id>(expectedCellvar.size())),
282 "Got incorrect cellvar");
283 }
284
TestClippingWithImplicitFunctionInverted()285 void TestClippingWithImplicitFunctionInverted()
286 {
287 vtkm::Vec<vtkm::FloatDefault, 3> center(1, 1, 0);
288 vtkm::FloatDefault radius(0.5);
289
290 vtkm::cont::DataSet ds = MakeTestDatasetStructured();
291
292 bool invertClip = true;
293 vtkm::worklet::Clip clip;
294 vtkm::cont::CellSetExplicit<> outputCellSet =
295 clip.Run(ds.GetCellSet(),
296 vtkm::cont::make_ImplicitFunctionHandle<vtkm::Sphere>(center, radius),
297 ds.GetCoordinateSystem("coords"),
298 invertClip);
299
300 auto coordsIn = ds.GetCoordinateSystem("coords").GetData();
301 vtkm::cont::ArrayHandle<Coord3D> coords = clip.ProcessPointField(coordsIn);
302
303 vtkm::cont::ArrayHandle<vtkm::Float32> scalarsIn;
304 ds.GetField("scalars").GetData().CopyTo(scalarsIn);
305 vtkm::cont::ArrayHandle<vtkm::Float32> scalars = clip.ProcessPointField(scalarsIn);
306
307 vtkm::cont::ArrayHandle<vtkm::Float32> cellvarIn;
308 ds.GetField("cellvar").GetData().CopyTo(cellvarIn);
309 vtkm::cont::ArrayHandle<vtkm::Float32> cellvar = clip.ProcessCellField(cellvarIn);
310
311 vtkm::Id connectivitySize = 12;
312 vtkm::Id fieldSize = 13;
313 vtkm::Id expectedConnectivity[] = { 10, 9, 4, 9, 11, 4, 12, 10, 4, 11, 12, 4 };
314 const Coord3D expectedCoords[] = {
315 Coord3D(0.0f, 0.0f, 0.0f), Coord3D(1.0f, 0.0f, 0.0f), Coord3D(2.0f, 0.0f, 0.0f),
316 Coord3D(0.0f, 1.0f, 0.0f), Coord3D(1.0f, 1.0f, 0.0f), Coord3D(2.0f, 1.0f, 0.0f),
317 Coord3D(0.0f, 2.0f, 0.0f), Coord3D(1.0f, 2.0f, 0.0f), Coord3D(2.0f, 2.0f, 0.0f),
318 Coord3D(1.0f, 0.75f, 0.0f), Coord3D(0.75f, 1.0f, 0.0f), Coord3D(1.25f, 1.0f, 0.0f),
319 Coord3D(1.0f, 1.25f, 0.0f),
320 };
321 vtkm::Float32 expectedScalars[] = { 1, 1, 1, 1, 0, 1, 1, 1, 1, 0.25, 0.25, 0.25, 0.25 };
322 std::vector<vtkm::Float32> expectedCellvar = { -100.f, 100.f, 30.f, -30.f };
323
324 VTKM_TEST_ASSERT(
325 TestArrayHandle(outputCellSet.GetConnectivityArray(vtkm::TopologyElementTagCell(),
326 vtkm::TopologyElementTagPoint()),
327 expectedConnectivity,
328 connectivitySize),
329 "Got incorrect conectivity");
330
331 VTKM_TEST_ASSERT(TestArrayHandle(coords, expectedCoords, fieldSize), "Got incorrect coordinates");
332
333 VTKM_TEST_ASSERT(TestArrayHandle(scalars, expectedScalars, fieldSize), "Got incorrect scalars");
334
335 VTKM_TEST_ASSERT(
336 TestArrayHandle(cellvar, expectedCellvar.data(), static_cast<vtkm::Id>(expectedCellvar.size())),
337 "Got incorrect cellvar");
338 }
339
TestClippingWithFunction()340 void TestClippingWithFunction()
341 {
342 std::cout << "Testing clipping with implicit function (sphere):" << std::endl;
343 TestClippingWithImplicitFunction();
344 TestClippingWithImplicitFunctionInverted();
345 }
346
UnitTestClippingWithFunction(int argc,char * argv[])347 int UnitTestClippingWithFunction(int argc, char* argv[])
348 {
349 return vtkm::cont::testing::Testing::Run(TestClippingWithFunction, argc, argv);
350 }
351