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 #include <vtkm/filter/CellAverage.h>
11 #include <vtkm/filter/Contour.h>
12 #include <vtkm/filter/SplitSharpEdges.h>
13 #include <vtkm/filter/SurfaceNormals.h>
14
15 #include <vtkm/cont/testing/MakeTestDataSet.h>
16 #include <vtkm/cont/testing/Testing.h>
17
18 #include <vtkm/source/Wavelet.h>
19
20 namespace
21 {
22
23 using NormalsArrayHandle = vtkm::cont::ArrayHandle<vtkm::Vec3f>;
24
25 const vtkm::Vec3f expectedCoords[24] = {
26 { 0.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 1.0, 0.0, 1.0 }, { 0.0, 0.0, 1.0 }, { 0.0, 1.0, 0.0 },
27 { 1.0, 1.0, 0.0 }, { 1.0, 1.0, 1.0 }, { 0.0, 1.0, 1.0 }, { 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0 },
28 { 1.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 1.0, 0.0, 1.0 }, { 1.0, 0.0, 1.0 }, { 0.0, 0.0, 1.0 },
29 { 0.0, 0.0, 1.0 }, { 0.0, 1.0, 0.0 }, { 0.0, 1.0, 0.0 }, { 1.0, 1.0, 0.0 }, { 1.0, 1.0, 0.0 },
30 { 1.0, 1.0, 1.0 }, { 1.0, 1.0, 1.0 }, { 0.0, 1.0, 1.0 }, { 0.0, 1.0, 1.0 }
31 };
32
33 const std::vector<vtkm::Id> expectedConnectivityArray91{ 0, 1, 5, 4, 1, 2, 6, 5, 2, 3, 7, 6,
34 3, 0, 4, 7, 4, 5, 6, 7, 0, 3, 2, 1 };
35 const std::vector<vtkm::FloatDefault> expectedPointvar{ 10.1f, 20.1f, 30.2f, 40.2f, 50.3f, 60.3f,
36 70.3f, 80.3f, 10.1f, 10.1f, 20.1f, 20.1f,
37 30.2f, 30.2f, 40.2f, 40.2f, 50.3f, 50.3f,
38 60.3f, 60.3f, 70.3f, 70.3f, 80.3f, 80.3f };
39
Make3DExplicitSimpleCube()40 vtkm::cont::DataSet Make3DExplicitSimpleCube()
41 {
42 vtkm::cont::DataSet dataSet;
43 vtkm::cont::DataSetBuilderExplicit dsb;
44
45 const int nVerts = 8;
46 const int nCells = 6;
47 using CoordType = vtkm::Vec3f;
48 std::vector<CoordType> coords = {
49 CoordType(0, 0, 0), // 0
50 CoordType(1, 0, 0), // 1
51 CoordType(1, 0, 1), // 2
52 CoordType(0, 0, 1), // 3
53 CoordType(0, 1, 0), // 4
54 CoordType(1, 1, 0), // 5
55 CoordType(1, 1, 1), // 6
56 CoordType(0, 1, 1) // 7
57 };
58
59 //Connectivity
60 std::vector<vtkm::UInt8> shapes;
61 std::vector<vtkm::IdComponent> numIndices;
62 for (size_t i = 0; i < 6; i++)
63 {
64 shapes.push_back(vtkm::CELL_SHAPE_QUAD);
65 numIndices.push_back(4);
66 }
67
68
69 std::vector<vtkm::Id> conn;
70 // Down face
71 conn.push_back(0);
72 conn.push_back(1);
73 conn.push_back(5);
74 conn.push_back(4);
75 // Right face
76 conn.push_back(1);
77 conn.push_back(2);
78 conn.push_back(6);
79 conn.push_back(5);
80 // Top face
81 conn.push_back(2);
82 conn.push_back(3);
83 conn.push_back(7);
84 conn.push_back(6);
85 // Left face
86 conn.push_back(3);
87 conn.push_back(0);
88 conn.push_back(4);
89 conn.push_back(7);
90 // Front face
91 conn.push_back(4);
92 conn.push_back(5);
93 conn.push_back(6);
94 conn.push_back(7);
95 // Back face
96 conn.push_back(0);
97 conn.push_back(3);
98 conn.push_back(2);
99 conn.push_back(1);
100
101 //Create the dataset.
102 dataSet = dsb.Create(coords, shapes, numIndices, conn, "coordinates");
103
104 vtkm::FloatDefault vars[nVerts] = { 10.1f, 20.1f, 30.2f, 40.2f, 50.3f, 60.3f, 70.3f, 80.3f };
105 vtkm::FloatDefault cellvar[nCells] = { 100.1f, 200.2f, 300.3f, 400.4f, 500.5f, 600.6f };
106
107 dataSet.AddPointField("pointvar", vars, nVerts);
108 dataSet.AddCellField("cellvar", cellvar, nCells);
109
110 return dataSet;
111 }
112
Make3DWavelet()113 vtkm::cont::DataSet Make3DWavelet()
114 {
115
116 vtkm::source::Wavelet wavelet({ -25 }, { 25 });
117 wavelet.SetFrequency({ 60, 30, 40 });
118 wavelet.SetMagnitude({ 5 });
119
120 vtkm::cont::DataSet result = wavelet.Execute();
121 return result;
122 }
123
124
TestSplitSharpEdgesFilterSplitEveryEdge(vtkm::cont::DataSet & simpleCubeWithSN,vtkm::filter::SplitSharpEdges & splitSharpEdgesFilter)125 void TestSplitSharpEdgesFilterSplitEveryEdge(vtkm::cont::DataSet& simpleCubeWithSN,
126 vtkm::filter::SplitSharpEdges& splitSharpEdgesFilter)
127 {
128 // Split every edge
129 vtkm::FloatDefault featureAngle = 89.0;
130 splitSharpEdgesFilter.SetFeatureAngle(featureAngle);
131 splitSharpEdgesFilter.SetActiveField("Normals", vtkm::cont::Field::Association::CELL_SET);
132 vtkm::cont::DataSet result = splitSharpEdgesFilter.Execute(simpleCubeWithSN);
133
134 auto newCoords = result.GetCoordinateSystem().GetDataAsMultiplexer();
135 auto newCoordsP = newCoords.ReadPortal();
136 vtkm::cont::ArrayHandle<vtkm::FloatDefault> newPointvarField;
137 result.GetField("pointvar").GetData().AsArrayHandle(newPointvarField);
138
139 for (vtkm::IdComponent i = 0; i < newCoords.GetNumberOfValues(); i++)
140 {
141 VTKM_TEST_ASSERT(test_equal(newCoordsP.Get(i)[0], expectedCoords[i][0]),
142 "result value does not match expected value");
143 VTKM_TEST_ASSERT(test_equal(newCoordsP.Get(i)[1], expectedCoords[i][1]),
144 "result value does not match expected value");
145 VTKM_TEST_ASSERT(test_equal(newCoordsP.Get(i)[2], expectedCoords[i][2]),
146 "result value does not match expected value");
147 }
148
149 auto newPointvarFieldPortal = newPointvarField.ReadPortal();
150 for (vtkm::IdComponent i = 0; i < newPointvarField.GetNumberOfValues(); i++)
151 {
152 VTKM_TEST_ASSERT(test_equal(newPointvarFieldPortal.Get(static_cast<vtkm::Id>(i)),
153 expectedPointvar[static_cast<unsigned long>(i)]),
154 "point field array result does not match expected value");
155 }
156 }
157
TestSplitSharpEdgesFilterNoSplit(vtkm::cont::DataSet & simpleCubeWithSN,vtkm::filter::SplitSharpEdges & splitSharpEdgesFilter)158 void TestSplitSharpEdgesFilterNoSplit(vtkm::cont::DataSet& simpleCubeWithSN,
159 vtkm::filter::SplitSharpEdges& splitSharpEdgesFilter)
160 {
161 // Do nothing
162 vtkm::FloatDefault featureAngle = 91.0;
163 splitSharpEdgesFilter.SetFeatureAngle(featureAngle);
164 splitSharpEdgesFilter.SetActiveField("Normals", vtkm::cont::Field::Association::CELL_SET);
165 vtkm::cont::DataSet result = splitSharpEdgesFilter.Execute(simpleCubeWithSN);
166
167 auto newCoords = result.GetCoordinateSystem().GetDataAsMultiplexer();
168 vtkm::cont::CellSetExplicit<>& newCellset =
169 result.GetCellSet().Cast<vtkm::cont::CellSetExplicit<>>();
170 auto newCoordsP = newCoords.ReadPortal();
171 vtkm::cont::ArrayHandle<vtkm::FloatDefault> newPointvarField;
172 result.GetField("pointvar").GetData().AsArrayHandle(newPointvarField);
173
174 for (vtkm::IdComponent i = 0; i < newCoords.GetNumberOfValues(); i++)
175 {
176 VTKM_TEST_ASSERT(test_equal(newCoordsP.Get(i)[0], expectedCoords[i][0]),
177 "result value does not match expected value");
178 VTKM_TEST_ASSERT(test_equal(newCoordsP.Get(i)[1], expectedCoords[i][1]),
179 "result value does not match expected value");
180 VTKM_TEST_ASSERT(test_equal(newCoordsP.Get(i)[2], expectedCoords[i][2]),
181 "result value does not match expected value");
182 }
183
184 const auto& connectivityArray = newCellset.GetConnectivityArray(vtkm::TopologyElementTagCell(),
185 vtkm::TopologyElementTagPoint());
186 auto connectivityArrayPortal = connectivityArray.ReadPortal();
187 for (vtkm::IdComponent i = 0; i < connectivityArray.GetNumberOfValues(); i++)
188 {
189 VTKM_TEST_ASSERT(connectivityArrayPortal.Get(static_cast<vtkm::Id>(i)) ==
190 expectedConnectivityArray91[static_cast<unsigned long>(i)],
191 "connectivity array result does not match expected value");
192 }
193
194 auto newPointvarFieldPortal = newPointvarField.ReadPortal();
195 for (vtkm::IdComponent i = 0; i < newPointvarField.GetNumberOfValues(); i++)
196 {
197 VTKM_TEST_ASSERT(test_equal(newPointvarFieldPortal.Get(static_cast<vtkm::Id>(i)),
198 expectedPointvar[static_cast<unsigned long>(i)]),
199 "point field array result does not match expected value");
200 }
201 }
202
TestWithExplicitData()203 void TestWithExplicitData()
204 {
205 vtkm::cont::DataSet simpleCube = Make3DExplicitSimpleCube();
206
207 // Generate surface normal field
208 vtkm::filter::SurfaceNormals surfaceNormalsFilter;
209 surfaceNormalsFilter.SetGenerateCellNormals(true);
210 vtkm::cont::DataSet simpleCubeWithSN = surfaceNormalsFilter.Execute(simpleCube);
211 VTKM_TEST_ASSERT(simpleCubeWithSN.HasCellField("Normals"), "Cell normals missing.");
212 VTKM_TEST_ASSERT(simpleCubeWithSN.HasPointField("pointvar"), "point field pointvar missing.");
213
214
215 vtkm::filter::SplitSharpEdges splitSharpEdgesFilter;
216
217 TestSplitSharpEdgesFilterSplitEveryEdge(simpleCubeWithSN, splitSharpEdgesFilter);
218 TestSplitSharpEdgesFilterNoSplit(simpleCubeWithSN, splitSharpEdgesFilter);
219 }
220
221
TestWithStructuredData()222 void TestWithStructuredData()
223 {
224 // Generate a wavelet:
225 vtkm::cont::DataSet dataSet = Make3DWavelet();
226
227 // Cut a contour:
228 vtkm::filter::Contour contour;
229 contour.SetActiveField("scalars", vtkm::cont::Field::Association::POINTS);
230 contour.SetNumberOfIsoValues(1);
231 contour.SetIsoValue(192);
232 contour.SetMergeDuplicatePoints(true);
233 contour.SetGenerateNormals(true);
234 contour.SetComputeFastNormalsForStructured(true);
235 contour.SetNormalArrayName("normals");
236 dataSet = contour.Execute(dataSet);
237
238 // Compute cell normals:
239 vtkm::filter::CellAverage cellNormals;
240 cellNormals.SetActiveField("normals", vtkm::cont::Field::Association::POINTS);
241 dataSet = cellNormals.Execute(dataSet);
242
243 // Split sharp edges:
244 std::cout << dataSet.GetNumberOfCells() << std::endl;
245 std::cout << dataSet.GetNumberOfPoints() << std::endl;
246 vtkm::filter::SplitSharpEdges split;
247 split.SetActiveField("normals", vtkm::cont::Field::Association::CELL_SET);
248 dataSet = split.Execute(dataSet);
249 }
250
251
TestSplitSharpEdgesFilter()252 void TestSplitSharpEdgesFilter()
253 {
254 TestWithExplicitData();
255 TestWithStructuredData();
256 }
257
258 } // anonymous namespace
259
UnitTestSplitSharpEdgesFilter(int argc,char * argv[])260 int UnitTestSplitSharpEdgesFilter(int argc, char* argv[])
261 {
262 return vtkm::cont::testing::Testing::Run(TestSplitSharpEdgesFilter, argc, argv);
263 }
264