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/testing/Testing.h>
22 
23 #include <vtkm/ImplicitFunction.h>
24 
25 #include <vector>
26 
27 using Coord3D = vtkm::Vec3f;
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 
73   std::vector<vtkm::Float32> values;
74   values.push_back(1.0);
75   values.push_back(2.0);
76   values.push_back(1.0);
77   values.push_back(0.0);
78   ds.AddPointField("scalars", values);
79 
80   values.clear();
81   values.push_back(100.f);
82   values.push_back(-100.f);
83   ds.AddCellField("cellvar", values);
84 
85   return ds;
86 }
87 
MakeTestDatasetStructured()88 vtkm::cont::DataSet MakeTestDatasetStructured()
89 {
90   static constexpr vtkm::Id xdim = 3, ydim = 3;
91   static const vtkm::Id2 dim(xdim, ydim);
92   static constexpr vtkm::Id numVerts = xdim * ydim;
93 
94   vtkm::Float32 scalars[numVerts];
95   for (vtkm::Id i = 0; i < numVerts; ++i)
96   {
97     scalars[i] = 1.0f;
98   }
99   scalars[4] = 0.0f;
100 
101   vtkm::cont::DataSet ds;
102   vtkm::cont::DataSetBuilderUniform builder;
103   ds = builder.Create(dim);
104 
105   ds.AddPointField("scalars", scalars, numVerts);
106 
107   std::vector<vtkm::Float32> cellvar = { -100.f, 100.f, 30.f, -30.f };
108   ds.AddCellField("cellvar", cellvar);
109 
110   return ds;
111 }
112 
TestClippingExplicit()113 void TestClippingExplicit()
114 {
115   vtkm::cont::DataSet ds = MakeTestDatasetExplicit();
116   vtkm::worklet::Clip clip;
117   bool invertClip = false;
118   vtkm::cont::CellSetExplicit<> outputCellSet =
119     clip.Run(ds.GetCellSet(),
120              ds.GetField("scalars").GetData().ResetTypes(vtkm::TypeListFieldScalar{},
121                                                          VTKM_DEFAULT_STORAGE_LIST{}),
122              clipValue,
123              invertClip);
124 
125   auto coordsIn = ds.GetCoordinateSystem("coords").GetDataAsMultiplexer();
126   vtkm::cont::ArrayHandle<Coord3D> coords = clip.ProcessPointField(coordsIn);
127 
128   vtkm::cont::ArrayHandle<vtkm::Float32> scalarsIn;
129   ds.GetField("scalars").GetData().AsArrayHandle(scalarsIn);
130   vtkm::cont::ArrayHandle<vtkm::Float32> scalars = clip.ProcessPointField(scalarsIn);
131 
132   vtkm::cont::ArrayHandle<vtkm::Float32> cellvarIn;
133   ds.GetField("cellvar").GetData().AsArrayHandle(cellvarIn);
134   vtkm::cont::ArrayHandle<vtkm::Float32> cellvar = clip.ProcessCellField(cellvarIn);
135 
136   vtkm::Id connectivitySize = 8;
137   vtkm::Id fieldSize = 7;
138   vtkm::Id expectedConnectivity[] = { 0, 1, 5, 4, 1, 2, 6, 5 };
139   Coord3D expectedCoords[] = {
140     Coord3D(0.00f, 0.00f, 0.0f), Coord3D(1.00f, 0.00f, 0.0f), Coord3D(1.00f, 1.00f, 0.0f),
141     Coord3D(0.00f, 1.00f, 0.0f), Coord3D(0.00f, 0.50f, 0.0f), Coord3D(0.25f, 0.75f, 0.0f),
142     Coord3D(0.50f, 1.00f, 0.0f),
143   };
144   vtkm::Float32 expectedScalars[] = { 1, 2, 1, 0, 0.5, 0.5, 0.5 };
145   std::vector<vtkm::Float32> expectedCellvar = { 100.f, -100.f };
146 
147   VTKM_TEST_ASSERT(outputCellSet.GetNumberOfPoints() == fieldSize,
148                    "Wrong number of points in cell set.");
149 
150   VTKM_TEST_ASSERT(
151     TestArrayHandle(outputCellSet.GetConnectivityArray(vtkm::TopologyElementTagCell(),
152                                                        vtkm::TopologyElementTagPoint()),
153                     expectedConnectivity,
154                     connectivitySize),
155     "Got incorrect conectivity");
156 
157   VTKM_TEST_ASSERT(TestArrayHandle(coords, expectedCoords, fieldSize), "Got incorrect coordinates");
158 
159   VTKM_TEST_ASSERT(TestArrayHandle(scalars, expectedScalars, fieldSize), "Got incorrect scalars");
160 
161   VTKM_TEST_ASSERT(
162     TestArrayHandle(cellvar, expectedCellvar.data(), static_cast<vtkm::Id>(expectedCellvar.size())),
163     "Got incorrect cellvar");
164 }
165 
TestClippingStructured()166 void TestClippingStructured()
167 {
168   using CoordsValueType = vtkm::cont::ArrayHandleUniformPointCoordinates::ValueType;
169   using CoordsOutType = vtkm::cont::ArrayHandle<CoordsValueType>;
170 
171   vtkm::cont::DataSet ds = MakeTestDatasetStructured();
172 
173   bool invertClip = false;
174   vtkm::worklet::Clip clip;
175   vtkm::cont::CellSetExplicit<> outputCellSet =
176     clip.Run(ds.GetCellSet(),
177              ds.GetField("scalars").GetData().ResetTypes(vtkm::TypeListFieldScalar{},
178                                                          VTKM_DEFAULT_STORAGE_LIST{}),
179              clipValue,
180              invertClip);
181 
182   auto coordsIn = ds.GetCoordinateSystem("coords").GetDataAsMultiplexer();
183   CoordsOutType coords = clip.ProcessPointField(coordsIn);
184 
185   vtkm::cont::ArrayHandle<vtkm::Float32> scalarsIn;
186   ds.GetField("scalars").GetData().AsArrayHandle(scalarsIn);
187   vtkm::cont::ArrayHandle<vtkm::Float32> scalars = clip.ProcessPointField(scalarsIn);
188 
189   vtkm::cont::ArrayHandle<vtkm::Float32> cellvarIn;
190   ds.GetField("cellvar").GetData().AsArrayHandle(cellvarIn);
191   vtkm::cont::ArrayHandle<vtkm::Float32> cellvar = clip.ProcessCellField(cellvarIn);
192 
193 
194   vtkm::Id connectivitySize = 28;
195   vtkm::Id fieldSize = 13;
196   vtkm::Id expectedConnectivity[] = { 9,  10, 3, 1, 1, 3, 0, 11, 9,  1, 5, 5, 1, 2,
197                                       10, 12, 7, 3, 3, 7, 6, 12, 11, 5, 7, 7, 5, 8 };
198 
199   Coord3D expectedCoords[] = {
200     Coord3D(0.0f, 0.0f, 0.0f), Coord3D(1.0f, 0.0f, 0.0f), Coord3D(2.0f, 0.0f, 0.0f),
201     Coord3D(0.0f, 1.0f, 0.0f), Coord3D(1.0f, 1.0f, 0.0f), Coord3D(2.0f, 1.0f, 0.0f),
202     Coord3D(0.0f, 2.0f, 0.0f), Coord3D(1.0f, 2.0f, 0.0f), Coord3D(2.0f, 2.0f, 0.0f),
203     Coord3D(1.0f, 0.5f, 0.0f), Coord3D(0.5f, 1.0f, 0.0f), Coord3D(1.5f, 1.0f, 0.0f),
204     Coord3D(1.0f, 1.5f, 0.0f),
205   };
206   vtkm::Float32 expectedScalars[] = { 1, 1, 1, 1, 0, 1, 1, 1, 1, 0.5, 0.5, 0.5, 0.5 };
207   std::vector<vtkm::Float32> expectedCellvar = { -100.f, -100.f, 100.f, 100.f,
208                                                  30.f,   30.f,   -30.f, -30.f };
209 
210   VTKM_TEST_ASSERT(outputCellSet.GetNumberOfPoints() == fieldSize,
211                    "Wrong number of points in cell set.");
212 
213   VTKM_TEST_ASSERT(
214     TestArrayHandle(outputCellSet.GetConnectivityArray(vtkm::TopologyElementTagCell(),
215                                                        vtkm::TopologyElementTagPoint()),
216                     expectedConnectivity,
217                     connectivitySize),
218     "Got incorrect conectivity");
219 
220   VTKM_TEST_ASSERT(TestArrayHandle(coords, expectedCoords, fieldSize), "Got incorrect coordinates");
221 
222   VTKM_TEST_ASSERT(TestArrayHandle(scalars, expectedScalars, fieldSize), "Got incorrect scalars");
223 
224   VTKM_TEST_ASSERT(
225     TestArrayHandle(cellvar, expectedCellvar.data(), static_cast<vtkm::Id>(expectedCellvar.size())),
226     "Got incorrect cellvar");
227 }
228 
TestClippingWithImplicitFunction()229 void TestClippingWithImplicitFunction()
230 {
231   vtkm::Vec3f center(1, 1, 0);
232   vtkm::FloatDefault radius(0.5);
233 
234   vtkm::cont::DataSet ds = MakeTestDatasetStructured();
235 
236   bool invertClip = false;
237   vtkm::worklet::Clip clip;
238   vtkm::cont::CellSetExplicit<> outputCellSet = clip.Run(
239     ds.GetCellSet(), vtkm::Sphere(center, radius), ds.GetCoordinateSystem("coords"), invertClip);
240 
241   auto coordsIn = ds.GetCoordinateSystem("coords").GetDataAsMultiplexer();
242   vtkm::cont::ArrayHandle<Coord3D> coords = clip.ProcessPointField(coordsIn);
243 
244   vtkm::cont::ArrayHandle<vtkm::Float32> scalarsIn;
245   ds.GetField("scalars").GetData().AsArrayHandle(scalarsIn);
246   vtkm::cont::ArrayHandle<vtkm::Float32> scalars = clip.ProcessPointField(scalarsIn);
247 
248   vtkm::cont::ArrayHandle<vtkm::Float32> cellvarIn;
249   ds.GetField("cellvar").GetData().AsArrayHandle(cellvarIn);
250   vtkm::cont::ArrayHandle<vtkm::Float32> cellvar = clip.ProcessCellField(cellvarIn);
251 
252   vtkm::Id connectivitySize = 28;
253   vtkm::Id fieldSize = 13;
254 
255   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   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   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::Vec3f 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 = clip.Run(
295     ds.GetCellSet(), vtkm::Sphere(center, radius), ds.GetCoordinateSystem("coords"), invertClip);
296 
297   auto coordsIn = ds.GetCoordinateSystem("coords").GetDataAsMultiplexer();
298   vtkm::cont::ArrayHandle<Coord3D> coords = clip.ProcessPointField(coordsIn);
299 
300   vtkm::cont::ArrayHandle<vtkm::Float32> scalarsIn;
301   ds.GetField("scalars").GetData().AsArrayHandle(scalarsIn);
302   vtkm::cont::ArrayHandle<vtkm::Float32> scalars = clip.ProcessPointField(scalarsIn);
303 
304   vtkm::cont::ArrayHandle<vtkm::Float32> cellvarIn;
305   ds.GetField("cellvar").GetData().AsArrayHandle(cellvarIn);
306   vtkm::cont::ArrayHandle<vtkm::Float32> cellvar = clip.ProcessCellField(cellvarIn);
307 
308   vtkm::Id connectivitySize = 12;
309   vtkm::Id fieldSize = 13;
310   vtkm::Id expectedConnectivity[] = { 10, 9, 4, 9, 11, 4, 12, 10, 4, 11, 12, 4 };
311   Coord3D expectedCoords[] = {
312     Coord3D(0.0f, 0.0f, 0.0f),  Coord3D(1.0f, 0.0f, 0.0f),  Coord3D(2.0f, 0.0f, 0.0f),
313     Coord3D(0.0f, 1.0f, 0.0f),  Coord3D(1.0f, 1.0f, 0.0f),  Coord3D(2.0f, 1.0f, 0.0f),
314     Coord3D(0.0f, 2.0f, 0.0f),  Coord3D(1.0f, 2.0f, 0.0f),  Coord3D(2.0f, 2.0f, 0.0f),
315     Coord3D(1.0f, 0.75f, 0.0f), Coord3D(0.75f, 1.0f, 0.0f), Coord3D(1.25f, 1.0f, 0.0f),
316     Coord3D(1.0f, 1.25f, 0.0f),
317   };
318   vtkm::Float32 expectedScalars[] = { 1, 1, 1, 1, 0, 1, 1, 1, 1, 0.25, 0.25, 0.25, 0.25 };
319   std::vector<vtkm::Float32> expectedCellvar = { -100.f, 100.f, 30.f, -30.f };
320 
321   VTKM_TEST_ASSERT(
322     TestArrayHandle(outputCellSet.GetConnectivityArray(vtkm::TopologyElementTagCell(),
323                                                        vtkm::TopologyElementTagPoint()),
324                     expectedConnectivity,
325                     connectivitySize),
326     "Got incorrect conectivity");
327 
328   VTKM_TEST_ASSERT(TestArrayHandle(coords, expectedCoords, fieldSize), "Got incorrect coordinates");
329 
330   VTKM_TEST_ASSERT(TestArrayHandle(scalars, expectedScalars, fieldSize), "Got incorrect scalars");
331 
332   VTKM_TEST_ASSERT(
333     TestArrayHandle(cellvar, expectedCellvar.data(), static_cast<vtkm::Id>(expectedCellvar.size())),
334     "Got incorrect cellvar");
335 }
336 
TestClipping()337 void TestClipping()
338 {
339   std::cout << "Testing explicit dataset:" << std::endl;
340   TestClippingExplicit();
341   std::cout << "Testing structured dataset:" << std::endl;
342   TestClippingStructured();
343   std::cout << "Testing clipping with implicit function (sphere):" << std::endl;
344   TestClippingWithImplicitFunction();
345   TestClippingWithImplicitFunctionInverted();
346 }
347 
UnitTestClipping(int argc,char * argv[])348 int UnitTestClipping(int argc, char* argv[])
349 {
350   return vtkm::cont::testing::Testing::Run(TestClipping, argc, argv);
351 }
352