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