GCC Code Coverage Report


Directory: ./
File: openvdb/openvdb/tools/GridOperators.h
Date: 2022-07-25 17:40:05
Exec Total Coverage
Lines: 206 217 94.9%
Functions: 113 2127 5.3%
Branches: 121 3279 3.7%

Line Branch Exec Source
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3
4 /// @file tools/GridOperators.h
5 ///
6 /// @brief Apply an operator to an input grid to produce an output grid
7 /// with the same active voxel topology but a potentially different value type.
8
9 #ifndef OPENVDB_TOOLS_GRID_OPERATORS_HAS_BEEN_INCLUDED
10 #define OPENVDB_TOOLS_GRID_OPERATORS_HAS_BEEN_INCLUDED
11
12 #include "openvdb/Grid.h"
13 #include "openvdb/math/Operators.h"
14 #include "openvdb/util/NullInterrupter.h"
15 #include "openvdb/thread/Threading.h"
16 #include "openvdb/tree/LeafManager.h"
17 #include "openvdb/tree/ValueAccessor.h"
18 #include "ValueTransformer.h" // for tools::foreach()
19 #include <openvdb/openvdb.h>
20
21 #include <tbb/parallel_for.h>
22
23 namespace openvdb {
24 OPENVDB_USE_VERSION_NAMESPACE
25 namespace OPENVDB_VERSION_NAME {
26 namespace tools {
27
28 /// @brief VectorToScalarConverter<VectorGridType>::Type is the type of a grid
29 /// having the same tree configuration as VectorGridType but a scalar value type, T,
30 /// where T is the type of the original vector components.
31 /// @details For example, VectorToScalarConverter<Vec3DGrid>::Type is equivalent to DoubleGrid.
32 template<typename VectorGridType> struct VectorToScalarConverter {
33 typedef typename VectorGridType::ValueType::value_type VecComponentValueT;
34 typedef typename VectorGridType::template ValueConverter<VecComponentValueT>::Type Type;
35 };
36
37 /// @brief ScalarToVectorConverter<ScalarGridType>::Type is the type of a grid
38 /// having the same tree configuration as ScalarGridType but value type Vec3<T>
39 /// where T is ScalarGridType::ValueType.
40 /// @details For example, ScalarToVectorConverter<DoubleGrid>::Type is equivalent to Vec3DGrid.
41 template<typename ScalarGridType> struct ScalarToVectorConverter {
42 typedef math::Vec3<typename ScalarGridType::ValueType> VectorValueT;
43 typedef typename ScalarGridType::template ValueConverter<VectorValueT>::Type Type;
44 };
45
46
47 /// @brief Compute the Closest-Point Transform (CPT) from a distance field.
48 /// @return a new vector-valued grid with the same numerical precision as the input grid
49 /// (for example, if the input grid is a DoubleGrid, the output grid will be a Vec3DGrid)
50 /// @details When a mask grid is specified, the solution is calculated only in
51 /// the intersection of the mask active topology and the input active topology
52 /// independent of the transforms associated with either grid.
53 template<typename GridType, typename InterruptT>
54 typename ScalarToVectorConverter<GridType>::Type::Ptr
55 cpt(const GridType& grid, bool threaded, InterruptT* interrupt);
56
57 template<typename GridType, typename MaskT, typename InterruptT>
58 typename ScalarToVectorConverter<GridType>::Type::Ptr
59 cpt(const GridType& grid, const MaskT& mask, bool threaded, InterruptT* interrupt);
60
61 template<typename GridType>
62 typename ScalarToVectorConverter<GridType>::Type::Ptr
63 cpt(const GridType& grid, bool threaded = true)
64 {
65 return cpt<GridType, util::NullInterrupter>(grid, threaded, nullptr);
66 }
67
68 template<typename GridType, typename MaskT>
69 typename ScalarToVectorConverter<GridType>::Type::Ptr
70 cpt(const GridType& grid, const MaskT& mask, bool threaded = true)
71 {
72 return cpt<GridType, MaskT, util::NullInterrupter>(grid, mask, threaded, nullptr);
73 }
74
75
76 /// @brief Compute the curl of the given vector-valued grid.
77 /// @return a new vector-valued grid
78 /// @details When a mask grid is specified, the solution is calculated only in
79 /// the intersection of the mask active topology and the input active topology
80 /// independent of the transforms associated with either grid.
81 template<typename GridType, typename InterruptT>
82 typename GridType::Ptr
83 curl(const GridType& grid, bool threaded, InterruptT* interrupt);
84
85 template<typename GridType, typename MaskT, typename InterruptT>
86 typename GridType::Ptr
87 curl(const GridType& grid, const MaskT& mask, bool threaded, InterruptT* interrupt);
88
89 template<typename GridType>
90 typename GridType::Ptr
91 5 curl(const GridType& grid, bool threaded = true)
92 {
93 5 return curl<GridType, util::NullInterrupter>(grid, threaded, nullptr);
94 }
95
96 template<typename GridType, typename MaskT>
97 typename GridType::Ptr
98 1 curl(const GridType& grid, const MaskT& mask, bool threaded = true)
99 {
100 1 return curl<GridType, MaskT, util::NullInterrupter>(grid, mask, threaded, nullptr);
101 }
102
103
104 /// @brief Compute the divergence of the given vector-valued grid.
105 /// @return a new scalar-valued grid with the same numerical precision as the input grid
106 /// (for example, if the input grid is a Vec3DGrid, the output grid will be a DoubleGrid)
107 /// @details When a mask grid is specified, the solution is calculated only in
108 /// the intersection of the mask active topology and the input active topology
109 /// independent of the transforms associated with either grid.
110 template<typename GridType, typename InterruptT>
111 typename VectorToScalarConverter<GridType>::Type::Ptr
112 divergence(const GridType& grid, bool threaded, InterruptT* interrupt);
113
114 template<typename GridType, typename MaskT, typename InterruptT>
115 typename VectorToScalarConverter<GridType>::Type::Ptr
116 divergence(const GridType& grid, const MaskT& mask, bool threaded, InterruptT* interrupt);
117
118 template<typename GridType>
119 typename VectorToScalarConverter<GridType>::Type::Ptr
120 2 divergence(const GridType& grid, bool threaded = true)
121 {
122 2 return divergence<GridType, util::NullInterrupter>(grid, threaded, nullptr);
123 }
124
125 template<typename GridType, typename MaskT>
126 typename VectorToScalarConverter<GridType>::Type::Ptr
127 2 divergence(const GridType& grid, const MaskT& mask, bool threaded = true)
128 {
129 2 return divergence<GridType, MaskT, util::NullInterrupter>(grid, mask, threaded, nullptr);
130 }
131
132
133 /// @brief Compute the gradient of the given scalar grid.
134 /// @return a new vector-valued grid with the same numerical precision as the input grid
135 /// (for example, if the input grid is a DoubleGrid, the output grid will be a Vec3DGrid)
136 /// @details When a mask grid is specified, the solution is calculated only in
137 /// the intersection of the mask active topology and the input active topology
138 /// independent of the transforms associated with either grid.
139 template<typename GridType, typename InterruptT>
140 typename ScalarToVectorConverter<GridType>::Type::Ptr
141 gradient(const GridType& grid, bool threaded, InterruptT* interrupt);
142
143 template<typename GridType, typename MaskT, typename InterruptT>
144 typename ScalarToVectorConverter<GridType>::Type::Ptr
145 gradient(const GridType& grid, const MaskT& mask, bool threaded, InterruptT* interrupt);
146
147 template<typename GridType>
148 typename ScalarToVectorConverter<GridType>::Type::Ptr
149 16 gradient(const GridType& grid, bool threaded = true)
150 {
151 16 return gradient<GridType, util::NullInterrupter>(grid, threaded, nullptr);
152 }
153
154 template<typename GridType, typename MaskT>
155 typename ScalarToVectorConverter<GridType>::Type::Ptr
156 1 gradient(const GridType& grid, const MaskT& mask, bool threaded = true)
157 {
158 1 return gradient<GridType, MaskT, util::NullInterrupter>(grid, mask, threaded, nullptr);
159 }
160
161
162 /// @brief Compute the Laplacian of the given scalar grid.
163 /// @return a new scalar grid
164 /// @details When a mask grid is specified, the solution is calculated only in
165 /// the intersection of the mask active topology and the input active topology
166 /// independent of the transforms associated with either grid.
167 template<typename GridType, typename InterruptT>
168 typename GridType::Ptr
169 laplacian(const GridType& grid, bool threaded, InterruptT* interrupt);
170
171 template<typename GridType, typename MaskT, typename InterruptT>
172 typename GridType::Ptr
173 laplacian(const GridType& grid, const MaskT& mask, bool threaded, InterruptT* interrupt);
174
175 template<typename GridType>
176 typename GridType::Ptr
177 1 laplacian(const GridType& grid, bool threaded = true)
178 {
179 1 return laplacian<GridType, util::NullInterrupter>(grid, threaded, nullptr);
180 }
181
182 template<typename GridType, typename MaskT>
183 typename GridType::Ptr
184 3 laplacian(const GridType& grid, const MaskT& mask, bool threaded = true)
185 {
186 3 return laplacian<GridType, MaskT, util::NullInterrupter>(grid, mask, threaded, nullptr);
187 }
188
189
190 /// @brief Compute the mean curvature of the given grid.
191 /// @return a new grid
192 /// @details When a mask grid is specified, the solution is calculated only in
193 /// the intersection of the mask active topology and the input active topology
194 /// independent of the transforms associated with either grid.
195 template<typename GridType, typename InterruptT>
196 typename GridType::Ptr
197 meanCurvature(const GridType& grid, bool threaded, InterruptT* interrupt);
198
199 template<typename GridType, typename MaskT, typename InterruptT>
200 typename GridType::Ptr
201 meanCurvature(const GridType& grid, const MaskT& mask, bool threaded, InterruptT* interrupt);
202
203 template<typename GridType>
204 typename GridType::Ptr
205 1 meanCurvature(const GridType& grid, bool threaded = true)
206 {
207 1 return meanCurvature<GridType, util::NullInterrupter>(grid, threaded, nullptr);
208 }
209
210 template<typename GridType, typename MaskT>
211 typename GridType::Ptr
212 1 meanCurvature(const GridType& grid, const MaskT& mask, bool threaded = true)
213 {
214 1 return meanCurvature<GridType, MaskT, util::NullInterrupter>(grid, mask, threaded, nullptr);
215 }
216
217
218 /// @brief Compute the magnitudes of the vectors of the given vector-valued grid.
219 /// @return a new scalar-valued grid with the same numerical precision as the input grid
220 /// (for example, if the input grid is a Vec3DGrid, the output grid will be a DoubleGrid)
221 /// @details When a mask grid is specified, the solution is calculated only in
222 /// the intersection of the mask active topology and the input active topology
223 /// independent of the transforms associated with either grid.
224 template<typename GridType, typename InterruptT>
225 typename VectorToScalarConverter<GridType>::Type::Ptr
226 magnitude(const GridType& grid, bool threaded, InterruptT* interrupt);
227
228 template<typename GridType, typename MaskT, typename InterruptT>
229 typename VectorToScalarConverter<GridType>::Type::Ptr
230 magnitude(const GridType& grid, const MaskT& mask, bool threaded, InterruptT* interrupt);
231
232 template<typename GridType>
233 typename VectorToScalarConverter<GridType>::Type::Ptr
234 2 magnitude(const GridType& grid, bool threaded = true)
235 {
236 2 return magnitude<GridType, util::NullInterrupter>(grid, threaded, nullptr);
237 }
238
239 template<typename GridType, typename MaskT>
240 typename VectorToScalarConverter<GridType>::Type::Ptr
241 2 magnitude(const GridType& grid, const MaskT& mask, bool threaded = true)
242 {
243 2 return magnitude<GridType, MaskT, util::NullInterrupter>(grid, mask, threaded, nullptr);
244 }
245
246
247 /// @brief Normalize the vectors of the given vector-valued grid.
248 /// @return a new vector-valued grid
249 /// @details When a mask grid is specified, the solution is calculated only in
250 /// the intersection of the mask active topology and the input active topology
251 /// independent of the transforms associated with either grid.
252 template<typename GridType, typename InterruptT>
253 typename GridType::Ptr
254 normalize(const GridType& grid, bool threaded, InterruptT* interrupt);
255
256 template<typename GridType, typename MaskT, typename InterruptT>
257 typename GridType::Ptr
258 normalize(const GridType& grid, const MaskT& mask, bool threaded, InterruptT* interrupt);
259
260 template<typename GridType>
261 typename GridType::Ptr
262 1 normalize(const GridType& grid, bool threaded = true)
263 {
264 1 return normalize<GridType, util::NullInterrupter>(grid, threaded, nullptr);
265 }
266
267 template<typename GridType, typename MaskT>
268 typename GridType::Ptr
269 1 normalize(const GridType& grid, const MaskT& mask, bool threaded = true)
270 {
271 1 return normalize<GridType, MaskT, util::NullInterrupter>(grid, mask, threaded, nullptr);
272 }
273
274
275 ////////////////////////////////////////
276
277
278 namespace gridop {
279
280 /// @brief ToMaskGrid<T>::Type is the type of a grid having the same
281 /// tree hierarchy as grid type T but a value equal to its active state.
282 /// @details For example, ToMaskGrid<FloatGrid>::Type is equivalent to MaskGrid.
283 template<typename GridType>
284 struct ToMaskGrid {
285 typedef Grid<typename GridType::TreeType::template ValueConverter<ValueMask>::Type> Type;
286 };
287
288
289 /// @brief Apply an operator to an input grid to produce an output grid
290 /// with the same active voxel topology but a potentially different value type.
291 /// @details To facilitate inlining, this class is also templated on a Map type.
292 ///
293 /// @note This is a helper class and should never be used directly.
294 template<
295 typename InGridT,
296 typename MaskGridType,
297 typename OutGridT,
298 typename MapT,
299 typename OperatorT,
300 typename InterruptT = util::NullInterrupter>
301 class GridOperator
302 {
303 public:
304 typedef typename OutGridT::TreeType OutTreeT;
305 typedef typename OutTreeT::LeafNodeType OutLeafT;
306 typedef typename tree::LeafManager<OutTreeT> LeafManagerT;
307
308 41 GridOperator(const InGridT& grid, const MaskGridType* mask, const MapT& map,
309 InterruptT* interrupt = nullptr, bool densify = true)
310 : mAcc(grid.getConstAccessor())
311 , mMap(map)
312 , mInterrupt(interrupt)
313 , mMask(mask)
314 82 , mDensify(densify) ///< @todo consider adding a "NeedsDensification" operator trait
315 {
316 }
317
19/1008
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 66 not taken.
✗ Branch 67 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 74 not taken.
✗ Branch 75 not taken.
✗ Branch 78 not taken.
✗ Branch 79 not taken.
✗ Branch 82 not taken.
✗ Branch 83 not taken.
✗ Branch 86 not taken.
✗ Branch 87 not taken.
✗ Branch 90 not taken.
✗ Branch 91 not taken.
✗ Branch 94 not taken.
✗ Branch 95 not taken.
✗ Branch 98 not taken.
✗ Branch 99 not taken.
✗ Branch 102 not taken.
✗ Branch 103 not taken.
✗ Branch 106 not taken.
✗ Branch 107 not taken.
✗ Branch 110 not taken.
✗ Branch 111 not taken.
✗ Branch 114 not taken.
✗ Branch 115 not taken.
✗ Branch 118 not taken.
✗ Branch 119 not taken.
✓ Branch 122 taken 1 times.
✗ Branch 123 not taken.
✗ Branch 126 not taken.
✗ Branch 127 not taken.
✗ Branch 130 not taken.
✗ Branch 131 not taken.
✗ Branch 134 not taken.
✗ Branch 135 not taken.
✗ Branch 138 not taken.
✗ Branch 139 not taken.
✗ Branch 142 not taken.
✗ Branch 143 not taken.
✗ Branch 146 not taken.
✗ Branch 147 not taken.
✗ Branch 150 not taken.
✗ Branch 151 not taken.
✗ Branch 154 not taken.
✗ Branch 155 not taken.
✗ Branch 158 not taken.
✗ Branch 159 not taken.
✗ Branch 162 not taken.
✗ Branch 163 not taken.
✗ Branch 166 not taken.
✗ Branch 167 not taken.
✗ Branch 170 not taken.
✗ Branch 171 not taken.
✗ Branch 174 not taken.
✗ Branch 175 not taken.
✗ Branch 178 not taken.
✗ Branch 179 not taken.
✗ Branch 182 not taken.
✗ Branch 183 not taken.
✓ Branch 186 taken 1 times.
✗ Branch 187 not taken.
✗ Branch 190 not taken.
✗ Branch 191 not taken.
✗ Branch 930 not taken.
✗ Branch 931 not taken.
✗ Branch 934 not taken.
✗ Branch 935 not taken.
✗ Branch 938 not taken.
✗ Branch 939 not taken.
✗ Branch 942 not taken.
✗ Branch 943 not taken.
✗ Branch 946 not taken.
✗ Branch 947 not taken.
✗ Branch 950 not taken.
✗ Branch 951 not taken.
✗ Branch 954 not taken.
✗ Branch 955 not taken.
✗ Branch 958 not taken.
✗ Branch 959 not taken.
✗ Branch 962 not taken.
✗ Branch 963 not taken.
✗ Branch 966 not taken.
✗ Branch 967 not taken.
✗ Branch 970 not taken.
✗ Branch 971 not taken.
✗ Branch 974 not taken.
✗ Branch 975 not taken.
✗ Branch 978 not taken.
✗ Branch 979 not taken.
✗ Branch 982 not taken.
✗ Branch 983 not taken.
✗ Branch 986 not taken.
✗ Branch 987 not taken.
✗ Branch 990 not taken.
✗ Branch 991 not taken.
✗ Branch 994 not taken.
✗ Branch 995 not taken.
✗ Branch 998 not taken.
✗ Branch 999 not taken.
✗ Branch 1002 not taken.
✗ Branch 1003 not taken.
✗ Branch 1006 not taken.
✗ Branch 1007 not taken.
✗ Branch 1010 not taken.
✗ Branch 1011 not taken.
✗ Branch 1014 not taken.
✗ Branch 1015 not taken.
✗ Branch 1018 not taken.
✗ Branch 1019 not taken.
✓ Branch 1022 taken 1 times.
✗ Branch 1023 not taken.
✗ Branch 1026 not taken.
✗ Branch 1027 not taken.
✗ Branch 1030 not taken.
✗ Branch 1031 not taken.
✗ Branch 1034 not taken.
✗ Branch 1035 not taken.
✗ Branch 1038 not taken.
✗ Branch 1039 not taken.
✗ Branch 1042 not taken.
✗ Branch 1043 not taken.
✗ Branch 1046 not taken.
✗ Branch 1047 not taken.
✗ Branch 1050 not taken.
✗ Branch 1051 not taken.
✗ Branch 1054 not taken.
✗ Branch 1055 not taken.
✗ Branch 1058 not taken.
✗ Branch 1059 not taken.
✗ Branch 1062 not taken.
✗ Branch 1063 not taken.
✗ Branch 1066 not taken.
✗ Branch 1067 not taken.
✗ Branch 1070 not taken.
✗ Branch 1071 not taken.
✗ Branch 1074 not taken.
✗ Branch 1075 not taken.
✗ Branch 1078 not taken.
✗ Branch 1079 not taken.
✗ Branch 1082 not taken.
✗ Branch 1083 not taken.
✗ Branch 1086 not taken.
✗ Branch 1087 not taken.
✗ Branch 1090 not taken.
✗ Branch 1091 not taken.
✗ Branch 1094 not taken.
✗ Branch 1095 not taken.
✗ Branch 1098 not taken.
✗ Branch 1099 not taken.
✗ Branch 1102 not taken.
✗ Branch 1103 not taken.
✗ Branch 1106 not taken.
✗ Branch 1107 not taken.
✗ Branch 1110 not taken.
✗ Branch 1111 not taken.
✗ Branch 1114 not taken.
✗ Branch 1115 not taken.
✓ Branch 1118 taken 1 times.
✗ Branch 1119 not taken.
✗ Branch 1122 not taken.
✗ Branch 1123 not taken.
✗ Branch 1126 not taken.
✗ Branch 1127 not taken.
✗ Branch 1130 not taken.
✗ Branch 1131 not taken.
✗ Branch 1134 not taken.
✗ Branch 1135 not taken.
✗ Branch 1138 not taken.
✗ Branch 1139 not taken.
✗ Branch 1142 not taken.
✗ Branch 1143 not taken.
✗ Branch 1146 not taken.
✗ Branch 1147 not taken.
✗ Branch 1150 not taken.
✗ Branch 1151 not taken.
✗ Branch 1154 not taken.
✗ Branch 1155 not taken.
✗ Branch 1158 not taken.
✗ Branch 1159 not taken.
✗ Branch 1162 not taken.
✗ Branch 1163 not taken.
✗ Branch 1166 not taken.
✗ Branch 1167 not taken.
✗ Branch 1170 not taken.
✗ Branch 1171 not taken.
✗ Branch 1174 not taken.
✗ Branch 1175 not taken.
✗ Branch 1178 not taken.
✗ Branch 1179 not taken.
✗ Branch 1182 not taken.
✗ Branch 1183 not taken.
✗ Branch 1186 not taken.
✗ Branch 1187 not taken.
✗ Branch 1190 not taken.
✗ Branch 1191 not taken.
✗ Branch 1194 not taken.
✗ Branch 1195 not taken.
✗ Branch 1198 not taken.
✗ Branch 1199 not taken.
✗ Branch 1202 not taken.
✗ Branch 1203 not taken.
✗ Branch 1206 not taken.
✗ Branch 1207 not taken.
✗ Branch 1210 not taken.
✗ Branch 1211 not taken.
✓ Branch 1214 taken 1 times.
✗ Branch 1215 not taken.
✗ Branch 1218 not taken.
✗ Branch 1219 not taken.
✗ Branch 1222 not taken.
✗ Branch 1223 not taken.
✗ Branch 1226 not taken.
✗ Branch 1227 not taken.
✗ Branch 1230 not taken.
✗ Branch 1231 not taken.
✗ Branch 1234 not taken.
✗ Branch 1235 not taken.
✗ Branch 1238 not taken.
✗ Branch 1239 not taken.
✗ Branch 1242 not taken.
✗ Branch 1243 not taken.
✗ Branch 1246 not taken.
✗ Branch 1247 not taken.
✗ Branch 1250 not taken.
✗ Branch 1251 not taken.
✗ Branch 1254 not taken.
✗ Branch 1255 not taken.
✗ Branch 1258 not taken.
✗ Branch 1259 not taken.
✗ Branch 1262 not taken.
✗ Branch 1263 not taken.
✗ Branch 1266 not taken.
✗ Branch 1267 not taken.
✗ Branch 1270 not taken.
✗ Branch 1271 not taken.
✗ Branch 1274 not taken.
✗ Branch 1275 not taken.
✗ Branch 1278 not taken.
✗ Branch 1279 not taken.
✗ Branch 1282 not taken.
✗ Branch 1283 not taken.
✗ Branch 1286 not taken.
✗ Branch 1287 not taken.
✗ Branch 1290 not taken.
✗ Branch 1291 not taken.
✗ Branch 1294 not taken.
✗ Branch 1295 not taken.
✗ Branch 1298 not taken.
✗ Branch 1299 not taken.
✗ Branch 1302 not taken.
✗ Branch 1303 not taken.
✗ Branch 1306 not taken.
✗ Branch 1307 not taken.
✓ Branch 1310 taken 1 times.
✗ Branch 1311 not taken.
✗ Branch 1314 not taken.
✗ Branch 1315 not taken.
✗ Branch 1318 not taken.
✗ Branch 1319 not taken.
✗ Branch 1322 not taken.
✗ Branch 1323 not taken.
✗ Branch 1326 not taken.
✗ Branch 1327 not taken.
✗ Branch 1330 not taken.
✗ Branch 1331 not taken.
✗ Branch 1334 not taken.
✗ Branch 1335 not taken.
✗ Branch 1338 not taken.
✗ Branch 1339 not taken.
✗ Branch 1342 not taken.
✗ Branch 1343 not taken.
✗ Branch 1346 not taken.
✗ Branch 1347 not taken.
✗ Branch 1350 not taken.
✗ Branch 1351 not taken.
✗ Branch 1354 not taken.
✗ Branch 1355 not taken.
✗ Branch 1358 not taken.
✗ Branch 1359 not taken.
✗ Branch 1362 not taken.
✗ Branch 1363 not taken.
✗ Branch 1366 not taken.
✗ Branch 1367 not taken.
✗ Branch 1370 not taken.
✗ Branch 1371 not taken.
✓ Branch 1374 taken 1 times.
✗ Branch 1375 not taken.
✗ Branch 1378 not taken.
✗ Branch 1379 not taken.
✗ Branch 1382 not taken.
✗ Branch 1383 not taken.
✗ Branch 1386 not taken.
✗ Branch 1387 not taken.
✗ Branch 1390 not taken.
✗ Branch 1391 not taken.
✗ Branch 1394 not taken.
✗ Branch 1395 not taken.
✗ Branch 1398 not taken.
✗ Branch 1399 not taken.
✗ Branch 1402 not taken.
✗ Branch 1403 not taken.
✗ Branch 1406 not taken.
✗ Branch 1407 not taken.
✗ Branch 1410 not taken.
✗ Branch 1411 not taken.
✗ Branch 1414 not taken.
✗ Branch 1415 not taken.
✗ Branch 1418 not taken.
✗ Branch 1419 not taken.
✗ Branch 1422 not taken.
✗ Branch 1423 not taken.
✗ Branch 1426 not taken.
✗ Branch 1427 not taken.
✗ Branch 1430 not taken.
✗ Branch 1431 not taken.
✗ Branch 1434 not taken.
✗ Branch 1435 not taken.
✗ Branch 1438 not taken.
✗ Branch 1439 not taken.
✗ Branch 1442 not taken.
✗ Branch 1443 not taken.
✗ Branch 1446 not taken.
✗ Branch 1447 not taken.
✗ Branch 1450 not taken.
✗ Branch 1451 not taken.
✗ Branch 1454 not taken.
✗ Branch 1455 not taken.
✗ Branch 1458 not taken.
✗ Branch 1459 not taken.
✗ Branch 1462 not taken.
✗ Branch 1463 not taken.
✗ Branch 1466 not taken.
✗ Branch 1467 not taken.
✗ Branch 1470 not taken.
✗ Branch 1471 not taken.
✗ Branch 1474 not taken.
✗ Branch 1475 not taken.
✗ Branch 1478 not taken.
✗ Branch 1479 not taken.
✗ Branch 1482 not taken.
✗ Branch 1483 not taken.
✗ Branch 1486 not taken.
✗ Branch 1487 not taken.
✗ Branch 1490 not taken.
✗ Branch 1491 not taken.
✗ Branch 1494 not taken.
✗ Branch 1495 not taken.
✗ Branch 1498 not taken.
✗ Branch 1499 not taken.
✓ Branch 1502 taken 1 times.
✗ Branch 1503 not taken.
✗ Branch 1506 not taken.
✗ Branch 1507 not taken.
✗ Branch 1510 not taken.
✗ Branch 1511 not taken.
✗ Branch 1514 not taken.
✗ Branch 1515 not taken.
✗ Branch 1518 not taken.
✗ Branch 1519 not taken.
✗ Branch 1522 not taken.
✗ Branch 1523 not taken.
✗ Branch 1526 not taken.
✗ Branch 1527 not taken.
✗ Branch 1530 not taken.
✗ Branch 1531 not taken.
✗ Branch 1534 not taken.
✗ Branch 1535 not taken.
✗ Branch 1538 not taken.
✗ Branch 1539 not taken.
✗ Branch 1542 not taken.
✗ Branch 1543 not taken.
✗ Branch 1546 not taken.
✗ Branch 1547 not taken.
✗ Branch 1550 not taken.
✗ Branch 1551 not taken.
✗ Branch 1554 not taken.
✗ Branch 1555 not taken.
✗ Branch 1558 not taken.
✗ Branch 1559 not taken.
✗ Branch 1562 not taken.
✗ Branch 1563 not taken.
✗ Branch 1566 not taken.
✗ Branch 1567 not taken.
✗ Branch 1570 not taken.
✗ Branch 1571 not taken.
✗ Branch 1574 not taken.
✗ Branch 1575 not taken.
✗ Branch 1578 not taken.
✗ Branch 1579 not taken.
✗ Branch 1582 not taken.
✗ Branch 1583 not taken.
✗ Branch 1586 not taken.
✗ Branch 1587 not taken.
✗ Branch 1590 not taken.
✗ Branch 1591 not taken.
✗ Branch 1594 not taken.
✗ Branch 1595 not taken.
✓ Branch 1598 taken 1 times.
✗ Branch 1599 not taken.
✗ Branch 1602 not taken.
✗ Branch 1603 not taken.
✗ Branch 1606 not taken.
✗ Branch 1607 not taken.
✗ Branch 1610 not taken.
✗ Branch 1611 not taken.
✗ Branch 1614 not taken.
✗ Branch 1615 not taken.
✗ Branch 1618 not taken.
✗ Branch 1619 not taken.
✗ Branch 1622 not taken.
✗ Branch 1623 not taken.
✗ Branch 1626 not taken.
✗ Branch 1627 not taken.
✓ Branch 1630 taken 2 times.
✗ Branch 1631 not taken.
✗ Branch 1634 not taken.
✗ Branch 1635 not taken.
✗ Branch 1638 not taken.
✗ Branch 1639 not taken.
✗ Branch 1642 not taken.
✗ Branch 1643 not taken.
✗ Branch 1646 not taken.
✗ Branch 1647 not taken.
✗ Branch 1650 not taken.
✗ Branch 1651 not taken.
✗ Branch 1654 not taken.
✗ Branch 1655 not taken.
✗ Branch 1658 not taken.
✗ Branch 1659 not taken.
✗ Branch 1662 not taken.
✗ Branch 1663 not taken.
✗ Branch 1666 not taken.
✗ Branch 1667 not taken.
✗ Branch 1670 not taken.
✗ Branch 1671 not taken.
✗ Branch 1674 not taken.
✗ Branch 1675 not taken.
✗ Branch 1678 not taken.
✗ Branch 1679 not taken.
✗ Branch 1682 not taken.
✗ Branch 1683 not taken.
✗ Branch 1686 not taken.
✗ Branch 1687 not taken.
✗ Branch 1690 not taken.
✗ Branch 1691 not taken.
✗ Branch 1694 not taken.
✗ Branch 1695 not taken.
✗ Branch 1698 not taken.
✗ Branch 1699 not taken.
✗ Branch 1702 not taken.
✗ Branch 1703 not taken.
✗ Branch 1706 not taken.
✗ Branch 1707 not taken.
✗ Branch 1710 not taken.
✗ Branch 1711 not taken.
✗ Branch 1714 not taken.
✗ Branch 1715 not taken.
✗ Branch 1718 not taken.
✗ Branch 1719 not taken.
✗ Branch 1722 not taken.
✗ Branch 1723 not taken.
✗ Branch 1726 not taken.
✗ Branch 1727 not taken.
✗ Branch 1730 not taken.
✗ Branch 1731 not taken.
✗ Branch 1734 not taken.
✗ Branch 1735 not taken.
✗ Branch 1738 not taken.
✗ Branch 1739 not taken.
✗ Branch 1742 not taken.
✗ Branch 1743 not taken.
✗ Branch 1746 not taken.
✗ Branch 1747 not taken.
✗ Branch 1750 not taken.
✗ Branch 1751 not taken.
✗ Branch 1754 not taken.
✗ Branch 1755 not taken.
✓ Branch 1758 taken 1 times.
✗ Branch 1759 not taken.
✗ Branch 1762 not taken.
✗ Branch 1763 not taken.
✗ Branch 1766 not taken.
✗ Branch 1767 not taken.
✗ Branch 1770 not taken.
✗ Branch 1771 not taken.
✗ Branch 1774 not taken.
✗ Branch 1775 not taken.
✗ Branch 1778 not taken.
✗ Branch 1779 not taken.
✗ Branch 1782 not taken.
✗ Branch 1783 not taken.
✗ Branch 1786 not taken.
✗ Branch 1787 not taken.
✗ Branch 1790 not taken.
✗ Branch 1791 not taken.
✗ Branch 1794 not taken.
✗ Branch 1795 not taken.
✗ Branch 1798 not taken.
✗ Branch 1799 not taken.
✗ Branch 1802 not taken.
✗ Branch 1803 not taken.
✗ Branch 1806 not taken.
✗ Branch 1807 not taken.
✗ Branch 1810 not taken.
✗ Branch 1811 not taken.
✗ Branch 1814 not taken.
✗ Branch 1815 not taken.
✗ Branch 1818 not taken.
✗ Branch 1819 not taken.
✗ Branch 1822 not taken.
✗ Branch 1823 not taken.
✗ Branch 1826 not taken.
✗ Branch 1827 not taken.
✗ Branch 1830 not taken.
✗ Branch 1831 not taken.
✗ Branch 1834 not taken.
✗ Branch 1835 not taken.
✗ Branch 1838 not taken.
✗ Branch 1839 not taken.
✗ Branch 1842 not taken.
✗ Branch 1843 not taken.
✗ Branch 1846 not taken.
✗ Branch 1847 not taken.
✗ Branch 1850 not taken.
✗ Branch 1851 not taken.
✗ Branch 1854 not taken.
✗ Branch 1855 not taken.
✗ Branch 1858 not taken.
✗ Branch 1859 not taken.
✗ Branch 1862 not taken.
✗ Branch 1863 not taken.
✗ Branch 1866 not taken.
✗ Branch 1867 not taken.
✗ Branch 1870 not taken.
✗ Branch 1871 not taken.
✗ Branch 1874 not taken.
✗ Branch 1875 not taken.
✗ Branch 1878 not taken.
✗ Branch 1879 not taken.
✗ Branch 1882 not taken.
✗ Branch 1883 not taken.
✓ Branch 1886 taken 1 times.
✗ Branch 1887 not taken.
✗ Branch 1890 not taken.
✗ Branch 1891 not taken.
✗ Branch 1894 not taken.
✗ Branch 1895 not taken.
✗ Branch 1898 not taken.
✗ Branch 1899 not taken.
✗ Branch 1902 not taken.
✗ Branch 1903 not taken.
✗ Branch 1906 not taken.
✗ Branch 1907 not taken.
✗ Branch 1910 not taken.
✗ Branch 1911 not taken.
✗ Branch 1914 not taken.
✗ Branch 1915 not taken.
✓ Branch 1918 taken 4 times.
✗ Branch 1919 not taken.
✗ Branch 1922 not taken.
✗ Branch 1923 not taken.
✗ Branch 1926 not taken.
✗ Branch 1927 not taken.
✗ Branch 1930 not taken.
✗ Branch 1931 not taken.
✗ Branch 1934 not taken.
✗ Branch 1935 not taken.
✗ Branch 1938 not taken.
✗ Branch 1939 not taken.
✗ Branch 1942 not taken.
✗ Branch 1943 not taken.
✗ Branch 1946 not taken.
✗ Branch 1947 not taken.
✓ Branch 1950 taken 12 times.
✗ Branch 1951 not taken.
✗ Branch 1954 not taken.
✗ Branch 1955 not taken.
✗ Branch 1958 not taken.
✗ Branch 1959 not taken.
✗ Branch 1962 not taken.
✗ Branch 1963 not taken.
✗ Branch 1966 not taken.
✗ Branch 1967 not taken.
✗ Branch 1970 not taken.
✗ Branch 1971 not taken.
✗ Branch 1974 not taken.
✗ Branch 1975 not taken.
✗ Branch 1978 not taken.
✗ Branch 1979 not taken.
✗ Branch 1982 not taken.
✗ Branch 1983 not taken.
✗ Branch 1986 not taken.
✗ Branch 1987 not taken.
✗ Branch 1990 not taken.
✗ Branch 1991 not taken.
✗ Branch 1994 not taken.
✗ Branch 1995 not taken.
✗ Branch 1998 not taken.
✗ Branch 1999 not taken.
✗ Branch 2002 not taken.
✗ Branch 2003 not taken.
✗ Branch 2006 not taken.
✗ Branch 2007 not taken.
✗ Branch 2010 not taken.
✗ Branch 2011 not taken.
✗ Branch 2014 not taken.
✗ Branch 2015 not taken.
✗ Branch 2018 not taken.
✗ Branch 2019 not taken.
✗ Branch 2022 not taken.
✗ Branch 2023 not taken.
✗ Branch 2026 not taken.
✗ Branch 2027 not taken.
✗ Branch 2030 not taken.
✗ Branch 2031 not taken.
✗ Branch 2034 not taken.
✗ Branch 2035 not taken.
✗ Branch 2038 not taken.
✗ Branch 2039 not taken.
✗ Branch 2042 not taken.
✗ Branch 2043 not taken.
✗ Branch 2046 not taken.
✗ Branch 2047 not taken.
✗ Branch 2050 not taken.
✗ Branch 2051 not taken.
✗ Branch 2054 not taken.
✗ Branch 2055 not taken.
✗ Branch 2058 not taken.
✗ Branch 2059 not taken.
✗ Branch 2062 not taken.
✗ Branch 2063 not taken.
✗ Branch 2066 not taken.
✗ Branch 2067 not taken.
✗ Branch 2070 not taken.
✗ Branch 2071 not taken.
✗ Branch 2074 not taken.
✗ Branch 2075 not taken.
✗ Branch 2078 not taken.
✗ Branch 2079 not taken.
✗ Branch 2082 not taken.
✗ Branch 2083 not taken.
✗ Branch 2086 not taken.
✗ Branch 2087 not taken.
✗ Branch 2090 not taken.
✗ Branch 2091 not taken.
✗ Branch 2094 not taken.
✗ Branch 2095 not taken.
✗ Branch 2098 not taken.
✗ Branch 2099 not taken.
✗ Branch 2102 not taken.
✗ Branch 2103 not taken.
✗ Branch 2106 not taken.
✗ Branch 2107 not taken.
✓ Branch 2110 taken 2 times.
✗ Branch 2111 not taken.
✗ Branch 2114 not taken.
✗ Branch 2115 not taken.
✗ Branch 2118 not taken.
✗ Branch 2119 not taken.
✗ Branch 2122 not taken.
✗ Branch 2123 not taken.
✗ Branch 2126 not taken.
✗ Branch 2127 not taken.
✗ Branch 2130 not taken.
✗ Branch 2131 not taken.
✗ Branch 2134 not taken.
✗ Branch 2135 not taken.
✗ Branch 2138 not taken.
✗ Branch 2139 not taken.
✗ Branch 2142 not taken.
✗ Branch 2143 not taken.
✗ Branch 2146 not taken.
✗ Branch 2147 not taken.
✗ Branch 2150 not taken.
✗ Branch 2151 not taken.
✗ Branch 2154 not taken.
✗ Branch 2155 not taken.
✗ Branch 2158 not taken.
✗ Branch 2159 not taken.
✗ Branch 2162 not taken.
✗ Branch 2163 not taken.
✗ Branch 2166 not taken.
✗ Branch 2167 not taken.
✗ Branch 2170 not taken.
✗ Branch 2171 not taken.
✗ Branch 2174 not taken.
✗ Branch 2175 not taken.
✗ Branch 2178 not taken.
✗ Branch 2179 not taken.
✗ Branch 2182 not taken.
✗ Branch 2183 not taken.
✗ Branch 2186 not taken.
✗ Branch 2187 not taken.
✗ Branch 2190 not taken.
✗ Branch 2191 not taken.
✗ Branch 2194 not taken.
✗ Branch 2195 not taken.
✗ Branch 2198 not taken.
✗ Branch 2199 not taken.
✗ Branch 2202 not taken.
✗ Branch 2203 not taken.
✗ Branch 2206 not taken.
✗ Branch 2207 not taken.
✗ Branch 2210 not taken.
✗ Branch 2211 not taken.
✗ Branch 2214 not taken.
✗ Branch 2215 not taken.
✗ Branch 2218 not taken.
✗ Branch 2219 not taken.
✗ Branch 2222 not taken.
✗ Branch 2223 not taken.
✗ Branch 2226 not taken.
✗ Branch 2227 not taken.
✗ Branch 2230 not taken.
✗ Branch 2231 not taken.
✗ Branch 2234 not taken.
✗ Branch 2235 not taken.
✗ Branch 2238 not taken.
✗ Branch 2239 not taken.
✗ Branch 2242 not taken.
✗ Branch 2243 not taken.
✗ Branch 2246 not taken.
✗ Branch 2247 not taken.
✗ Branch 2250 not taken.
✗ Branch 2251 not taken.
✗ Branch 2254 not taken.
✗ Branch 2255 not taken.
✗ Branch 2258 not taken.
✗ Branch 2259 not taken.
✗ Branch 2262 not taken.
✗ Branch 2263 not taken.
✗ Branch 2266 not taken.
✗ Branch 2267 not taken.
✗ Branch 2270 not taken.
✗ Branch 2271 not taken.
✗ Branch 2274 not taken.
✗ Branch 2275 not taken.
✗ Branch 2278 not taken.
✗ Branch 2279 not taken.
✗ Branch 2282 not taken.
✗ Branch 2283 not taken.
✗ Branch 2286 not taken.
✗ Branch 2287 not taken.
✗ Branch 2290 not taken.
✗ Branch 2291 not taken.
✗ Branch 2294 not taken.
✗ Branch 2295 not taken.
✗ Branch 2298 not taken.
✗ Branch 2299 not taken.
✓ Branch 2302 taken 1 times.
✗ Branch 2303 not taken.
✗ Branch 2306 not taken.
✗ Branch 2307 not taken.
✗ Branch 2310 not taken.
✗ Branch 2311 not taken.
✗ Branch 2314 not taken.
✗ Branch 2315 not taken.
✗ Branch 2318 not taken.
✗ Branch 2319 not taken.
✗ Branch 2322 not taken.
✗ Branch 2323 not taken.
✗ Branch 2326 not taken.
✗ Branch 2327 not taken.
✗ Branch 2330 not taken.
✗ Branch 2331 not taken.
✓ Branch 2334 taken 1 times.
✗ Branch 2335 not taken.
✗ Branch 2338 not taken.
✗ Branch 2339 not taken.
✗ Branch 2342 not taken.
✗ Branch 2343 not taken.
✗ Branch 2346 not taken.
✗ Branch 2347 not taken.
✗ Branch 2350 not taken.
✗ Branch 2351 not taken.
✗ Branch 2354 not taken.
✗ Branch 2355 not taken.
✗ Branch 2358 not taken.
✗ Branch 2359 not taken.
✗ Branch 2362 not taken.
✗ Branch 2363 not taken.
✗ Branch 2366 not taken.
✗ Branch 2367 not taken.
✗ Branch 2370 not taken.
✗ Branch 2371 not taken.
✗ Branch 2374 not taken.
✗ Branch 2375 not taken.
✗ Branch 2378 not taken.
✗ Branch 2379 not taken.
✗ Branch 2382 not taken.
✗ Branch 2383 not taken.
✗ Branch 2386 not taken.
✗ Branch 2387 not taken.
✗ Branch 2390 not taken.
✗ Branch 2391 not taken.
✗ Branch 2394 not taken.
✗ Branch 2395 not taken.
✗ Branch 2398 not taken.
✗ Branch 2399 not taken.
✗ Branch 2402 not taken.
✗ Branch 2403 not taken.
✗ Branch 2406 not taken.
✗ Branch 2407 not taken.
✗ Branch 2410 not taken.
✗ Branch 2411 not taken.
✗ Branch 2414 not taken.
✗ Branch 2415 not taken.
✗ Branch 2418 not taken.
✗ Branch 2419 not taken.
✗ Branch 2422 not taken.
✗ Branch 2423 not taken.
✗ Branch 2426 not taken.
✗ Branch 2427 not taken.
✓ Branch 2430 taken 1 times.
✗ Branch 2431 not taken.
✗ Branch 2434 not taken.
✗ Branch 2435 not taken.
✗ Branch 2438 not taken.
✗ Branch 2439 not taken.
✗ Branch 2442 not taken.
✗ Branch 2443 not taken.
✗ Branch 2446 not taken.
✗ Branch 2447 not taken.
✗ Branch 2450 not taken.
✗ Branch 2451 not taken.
✗ Branch 2454 not taken.
✗ Branch 2455 not taken.
✗ Branch 2458 not taken.
✗ Branch 2459 not taken.
✗ Branch 2462 not taken.
✗ Branch 2463 not taken.
✗ Branch 2466 not taken.
✗ Branch 2467 not taken.
✗ Branch 2470 not taken.
✗ Branch 2471 not taken.
✗ Branch 2474 not taken.
✗ Branch 2475 not taken.
✗ Branch 2478 not taken.
✗ Branch 2479 not taken.
✗ Branch 2482 not taken.
✗ Branch 2483 not taken.
✗ Branch 2486 not taken.
✗ Branch 2487 not taken.
✗ Branch 2490 not taken.
✗ Branch 2491 not taken.
✗ Branch 2494 not taken.
✗ Branch 2495 not taken.
✗ Branch 2498 not taken.
✗ Branch 2499 not taken.
✗ Branch 2502 not taken.
✗ Branch 2503 not taken.
✗ Branch 2506 not taken.
✗ Branch 2507 not taken.
✗ Branch 2510 not taken.
✗ Branch 2511 not taken.
✗ Branch 2514 not taken.
✗ Branch 2515 not taken.
✗ Branch 2518 not taken.
✗ Branch 2519 not taken.
✗ Branch 2522 not taken.
✗ Branch 2523 not taken.
✓ Branch 2526 taken 5 times.
✗ Branch 2527 not taken.
✗ Branch 2530 not taken.
✗ Branch 2531 not taken.
✗ Branch 2534 not taken.
✗ Branch 2535 not taken.
✗ Branch 2538 not taken.
✗ Branch 2539 not taken.
✗ Branch 2542 not taken.
✗ Branch 2543 not taken.
✗ Branch 2546 not taken.
✗ Branch 2547 not taken.
✗ Branch 2550 not taken.
✗ Branch 2551 not taken.
✗ Branch 2554 not taken.
✗ Branch 2555 not taken.
✗ Branch 2558 not taken.
✗ Branch 2559 not taken.
✗ Branch 2562 not taken.
✗ Branch 2563 not taken.
✗ Branch 2566 not taken.
✗ Branch 2567 not taken.
✗ Branch 2570 not taken.
✗ Branch 2571 not taken.
✗ Branch 2574 not taken.
✗ Branch 2575 not taken.
✗ Branch 2578 not taken.
✗ Branch 2579 not taken.
✗ Branch 2582 not taken.
✗ Branch 2583 not taken.
✗ Branch 2586 not taken.
✗ Branch 2587 not taken.
✗ Branch 2590 not taken.
✗ Branch 2591 not taken.
✗ Branch 2594 not taken.
✗ Branch 2595 not taken.
✗ Branch 2598 not taken.
✗ Branch 2599 not taken.
✗ Branch 2602 not taken.
✗ Branch 2603 not taken.
✗ Branch 2606 not taken.
✗ Branch 2607 not taken.
✗ Branch 2610 not taken.
✗ Branch 2611 not taken.
✗ Branch 2614 not taken.
✗ Branch 2615 not taken.
✗ Branch 2618 not taken.
✗ Branch 2619 not taken.
✗ Branch 2622 not taken.
✗ Branch 2623 not taken.
✗ Branch 2626 not taken.
✗ Branch 2627 not taken.
✗ Branch 2630 not taken.
✗ Branch 2631 not taken.
✗ Branch 2634 not taken.
✗ Branch 2635 not taken.
✗ Branch 2638 not taken.
✗ Branch 2639 not taken.
✗ Branch 2642 not taken.
✗ Branch 2643 not taken.
✗ Branch 2646 not taken.
✗ Branch 2647 not taken.
✗ Branch 2650 not taken.
✗ Branch 2651 not taken.
✗ Branch 2654 not taken.
✗ Branch 2655 not taken.
✗ Branch 2658 not taken.
✗ Branch 2659 not taken.
✗ Branch 2662 not taken.
✗ Branch 2663 not taken.
✗ Branch 2666 not taken.
✗ Branch 2667 not taken.
✗ Branch 2670 not taken.
✗ Branch 2671 not taken.
✗ Branch 2674 not taken.
✗ Branch 2675 not taken.
✗ Branch 2678 not taken.
✗ Branch 2679 not taken.
✗ Branch 2682 not taken.
✗ Branch 2683 not taken.
✗ Branch 2686 not taken.
✗ Branch 2687 not taken.
✗ Branch 2690 not taken.
✗ Branch 2691 not taken.
✗ Branch 2694 not taken.
✗ Branch 2695 not taken.
✗ Branch 2698 not taken.
✗ Branch 2699 not taken.
✗ Branch 2702 not taken.
✗ Branch 2703 not taken.
✗ Branch 2706 not taken.
✗ Branch 2707 not taken.
✗ Branch 2710 not taken.
✗ Branch 2711 not taken.
✗ Branch 2714 not taken.
✗ Branch 2715 not taken.
✗ Branch 2718 not taken.
✗ Branch 2719 not taken.
✗ Branch 2722 not taken.
✗ Branch 2723 not taken.
✗ Branch 2726 not taken.
✗ Branch 2727 not taken.
✗ Branch 2730 not taken.
✗ Branch 2731 not taken.
✗ Branch 2734 not taken.
✗ Branch 2735 not taken.
✗ Branch 2738 not taken.
✗ Branch 2739 not taken.
✗ Branch 2742 not taken.
✗ Branch 2743 not taken.
✗ Branch 2746 not taken.
✗ Branch 2747 not taken.
✗ Branch 2750 not taken.
✗ Branch 2751 not taken.
✗ Branch 2754 not taken.
✗ Branch 2755 not taken.
✗ Branch 2758 not taken.
✗ Branch 2759 not taken.
✗ Branch 2762 not taken.
✗ Branch 2763 not taken.
✗ Branch 2766 not taken.
✗ Branch 2767 not taken.
✗ Branch 2770 not taken.
✗ Branch 2771 not taken.
✗ Branch 2774 not taken.
✗ Branch 2775 not taken.
✗ Branch 2778 not taken.
✗ Branch 2779 not taken.
✗ Branch 2782 not taken.
✗ Branch 2783 not taken.
834 GridOperator(const GridOperator&) = default;
318 GridOperator& operator=(const GridOperator&) = default;
319 virtual ~GridOperator() = default;
320
321 82 typename OutGridT::Ptr process(bool threaded = true)
322 {
323
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
82 if (mInterrupt) mInterrupt->start("Processing grid");
324
325 // Derive background value of the output grid
326 164 typename InGridT::TreeType tmp(mAcc.tree().background());
327
2/5
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 39 times.
82 typename OutGridT::ValueType backg = OperatorT::result(mMap, tmp, math::Coord(0));
328
329 // The output tree is topology copy, optionally densified, of the input tree.
330 // (Densification is necessary for some operators because applying the operator to
331 // a constant tile produces distinct output values, particularly along tile borders.)
332 /// @todo Can tiles be handled correctly without densification, or by densifying
333 /// only to the width of the operator stencil?
334
2/4
✓ Branch 1 taken 41 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 41 times.
✗ Branch 5 not taken.
82 typename OutTreeT::Ptr tree(new OutTreeT(mAcc.tree(), backg, TopologyCopy()));
335
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 8 times.
82 if (mDensify) tree->voxelizeActiveTiles();
336
337 // create grid with output tree and unit transform
338
2/6
✓ Branch 1 taken 41 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 41 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
82 typename OutGridT::Ptr result(new OutGridT(tree));
339
340 // Modify the solution area if a mask was supplied.
341
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 29 times.
82 if (mMask) {
342 result->topologyIntersection(*mMask);
343 }
344
345 // transform of output grid = transform of input grid
346
6/16
✓ Branch 1 taken 41 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 41 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 41 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 41 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 41 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 41 times.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
328 result->setTransform(math::Transform::Ptr(new math::Transform( mMap.copy() )));
347
348
1/2
✓ Branch 1 taken 41 times.
✗ Branch 2 not taken.
164 LeafManagerT leafManager(*tree);
349
350
1/2
✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
82 if (threaded) {
351
1/2
✓ Branch 1 taken 41 times.
✗ Branch 2 not taken.
82 tbb::parallel_for(leafManager.leafRange(), *this);
352 } else {
353 (*this)(leafManager.leafRange());
354 }
355
356 // If the tree wasn't densified, it might have active tiles that need to be processed.
357
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 33 times.
82 if (!mDensify) {
358 using TileIter = typename OutTreeT::ValueOnIter;
359
360 TileIter tileIter = tree->beginValueOn();
361
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
16 tileIter.setMaxDepth(tileIter.getLeafDepth() - 1); // skip leaf values (i.e., voxels)
362
363 AccessorT inAcc = mAcc; // each thread needs its own accessor, captured by value
364
2/4
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
✗ Branch 4 not taken.
45 auto tileOp = [this, inAcc](const TileIter& it) {
365 // Apply the operator to the input grid's tile value at the iterator's
366 // current coordinates, and set the output tile's value to the result.
367 3 it.setValue(OperatorT::result(this->mMap, inAcc, it.getCoord()));
368 };
369
370 // Apply the operator to tile values, optionally in parallel.
371 // (But don't share the functor; each thread needs its own accessor.)
372
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
16 tools::foreach(tileIter, tileOp, threaded, /*shareFunctor=*/false);
373 }
374
375
3/4
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 8 times.
✓ Branch 3 taken 29 times.
✗ Branch 4 not taken.
102 if (mDensify) tree->prune();
376
377
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
82 if (mInterrupt) mInterrupt->end();
378 82 return result;
379 }
380
381 /// @brief Iterate sequentially over LeafNodes and voxels in the output
382 /// grid and apply the operator using a value accessor for the input grid.
383 ///
384 /// @note Never call this public method directly - it is called by
385 /// TBB threads only!
386 6056 void operator()(const typename LeafManagerT::LeafRange& range) const
387 {
388
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3028 times.
6056 if (util::wasInterrupted(mInterrupt)) {
389 thread::cancelGroupExecution();
390 }
391
392
2/2
✓ Branch 1 taken 23360 times.
✓ Branch 2 taken 3028 times.
52776 for (typename LeafManagerT::LeafRange::Iterator leaf=range.begin(); leaf; ++leaf) {
393
2/2
✓ Branch 0 taken 10395072 times.
✓ Branch 1 taken 23360 times.
20836864 for (typename OutLeafT::ValueOnIter value=leaf->beginValueOn(); value; ++value) {
394 21316448 value.setValue(OperatorT::result(mMap, mAcc, value.getCoord()));
395 }
396 }
397 }
398
399 protected:
400 typedef typename InGridT::ConstAccessor AccessorT;
401 mutable AccessorT mAcc;
402 const MapT& mMap;
403 InterruptT* mInterrupt;
404 const MaskGridType* mMask;
405 const bool mDensify;
406 }; // end of GridOperator class
407
408 } // namespace gridop
409
410
411 ////////////////////////////////////////
412
413
414 /// @brief Compute the closest-point transform of a scalar grid.
415 template<
416 typename InGridT,
417 typename MaskGridType = typename gridop::ToMaskGrid<InGridT>::Type,
418 typename InterruptT = util::NullInterrupter>
419 class Cpt
420 {
421 public:
422 typedef InGridT InGridType;
423 typedef typename ScalarToVectorConverter<InGridT>::Type OutGridType;
424
425 1 Cpt(const InGridType& grid, InterruptT* interrupt = nullptr):
426
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 mInputGrid(grid), mInterrupt(interrupt), mMask(nullptr)
427 {
428 }
429
430 1 Cpt(const InGridType& grid, const MaskGridType& mask, InterruptT* interrupt = nullptr):
431
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 mInputGrid(grid), mInterrupt(interrupt), mMask(&mask)
432 {
433 }
434
435 4 typename OutGridType::Ptr process(bool threaded = true, bool useWorldTransform = true)
436 {
437 4 Functor functor(mInputGrid, mMask, threaded, useWorldTransform, mInterrupt);
438
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 processTypedMap(mInputGrid.transform(), functor);
439
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
4 if (functor.mOutputGrid) functor.mOutputGrid->setVectorType(VEC_CONTRAVARIANT_ABSOLUTE);
440 4 return functor.mOutputGrid;
441 }
442
443 private:
444 struct IsOpT
445 {
446 template<typename MapT, typename AccT>
447 static typename OutGridType::ValueType
448 result(const MapT& map, const AccT& acc, const Coord& xyz)
449 {
450
2/72
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✓ Branch 45 taken 1 times.
✗ Branch 46 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 65 not taken.
✗ Branch 66 not taken.
✗ Branch 69 not taken.
✗ Branch 70 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✓ Branch 77 taken 1 times.
✗ Branch 78 not taken.
✗ Branch 81 not taken.
✗ Branch 82 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 89 not taken.
✗ Branch 90 not taken.
✗ Branch 93 not taken.
✗ Branch 94 not taken.
✗ Branch 97 not taken.
✗ Branch 98 not taken.
✗ Branch 101 not taken.
✗ Branch 102 not taken.
✗ Branch 105 not taken.
✗ Branch 106 not taken.
✗ Branch 109 not taken.
✗ Branch 110 not taken.
✗ Branch 113 not taken.
✗ Branch 114 not taken.
✗ Branch 117 not taken.
✗ Branch 118 not taken.
✗ Branch 121 not taken.
✗ Branch 122 not taken.
✗ Branch 125 not taken.
✗ Branch 126 not taken.
✗ Branch 129 not taken.
✗ Branch 130 not taken.
✗ Branch 133 not taken.
✗ Branch 134 not taken.
✗ Branch 137 not taken.
✗ Branch 138 not taken.
✗ Branch 141 not taken.
✗ Branch 142 not taken.
✗ Branch 145 not taken.
✗ Branch 146 not taken.
✗ Branch 149 not taken.
✗ Branch 150 not taken.
✗ Branch 153 not taken.
✗ Branch 154 not taken.
✗ Branch 157 not taken.
✗ Branch 158 not taken.
263154 return math::CPT<MapT, math::CD_2ND>::result(map, acc, xyz);
451 }
452 };
453 struct WsOpT
454 {
455 template<typename MapT, typename AccT>
456 static typename OutGridType::ValueType
457 result(const MapT& map, const AccT& acc, const Coord& xyz)
458 {
459 return math::CPT_RANGE<MapT, math::CD_2ND>::result(map, acc, xyz);
460 }
461 };
462 struct Functor
463 {
464 2 Functor(const InGridType& grid, const MaskGridType* mask,
465 bool threaded, bool worldspace, InterruptT* interrupt)
466 : mThreaded(threaded)
467 , mWorldSpace(worldspace)
468 , mInputGrid(grid)
469 , mInterrupt(interrupt)
470
2/8
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
2 , mMask(mask)
471 {}
472
473 template<typename MapT>
474 4 void operator()(const MapT& map)
475 {
476
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
4 if (mWorldSpace) {
477 gridop::GridOperator<InGridType, MaskGridType, OutGridType, MapT, WsOpT, InterruptT>
478 op(mInputGrid, mMask, map, mInterrupt, /*densify=*/false);
479 mOutputGrid = op.process(mThreaded); // cache the result
480 } else {
481 gridop::GridOperator<InGridType, MaskGridType, OutGridType, MapT, IsOpT, InterruptT>
482 4 op(mInputGrid, mMask, map, mInterrupt, /*densify=*/false);
483
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
8 mOutputGrid = op.process(mThreaded); // cache the result
484 }
485 }
486 const bool mThreaded;
487 const bool mWorldSpace;
488 const InGridType& mInputGrid;
489 typename OutGridType::Ptr mOutputGrid;
490 InterruptT* mInterrupt;
491 const MaskGridType* mMask;
492 };
493 const InGridType& mInputGrid;
494 InterruptT* mInterrupt;
495 const MaskGridType* mMask;
496 }; // end of Cpt class
497
498
499 ////////////////////////////////////////
500
501
502 /// @brief Compute the curl of a vector grid.
503 template<
504 typename GridT,
505 typename MaskGridType = typename gridop::ToMaskGrid<GridT>::Type,
506 typename InterruptT = util::NullInterrupter>
507 class Curl
508 {
509 public:
510 typedef GridT InGridType;
511 typedef GridT OutGridType;
512
513 5 Curl(const GridT& grid, InterruptT* interrupt = nullptr):
514 5 mInputGrid(grid), mInterrupt(interrupt), mMask(nullptr)
515 {
516 }
517
518 1 Curl(const GridT& grid, const MaskGridType& mask, InterruptT* interrupt = nullptr):
519 1 mInputGrid(grid), mInterrupt(interrupt), mMask(&mask)
520 {
521 }
522
523 12 typename GridT::Ptr process(bool threaded = true)
524 {
525 12 Functor functor(mInputGrid, mMask, threaded, mInterrupt);
526
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
12 processTypedMap(mInputGrid.transform(), functor);
527
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
12 if (functor.mOutputGrid) functor.mOutputGrid->setVectorType(VEC_COVARIANT);
528 12 return functor.mOutputGrid;
529 }
530
531 private:
532 struct Functor
533 {
534 6 Functor(const GridT& grid, const MaskGridType* mask,
535 bool threaded, InterruptT* interrupt):
536
2/12
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 16 taken 5 times.
✗ Branch 17 not taken.
6 mThreaded(threaded), mInputGrid(grid), mInterrupt(interrupt), mMask(mask) {}
537
538 template<typename MapT>
539 12 void operator()(const MapT& map)
540 {
541 typedef math::Curl<MapT, math::CD_2ND> OpT;
542 gridop::GridOperator<GridT, MaskGridType, GridT, MapT, OpT, InterruptT>
543 12 op(mInputGrid, mMask, map, mInterrupt);
544
2/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
24 mOutputGrid = op.process(mThreaded); // cache the result
545 }
546
547 const bool mThreaded;
548 const GridT& mInputGrid;
549 typename GridT::Ptr mOutputGrid;
550 InterruptT* mInterrupt;
551 const MaskGridType* mMask;
552 }; // Private Functor
553
554 const GridT& mInputGrid;
555 InterruptT* mInterrupt;
556 const MaskGridType* mMask;
557 }; // end of Curl class
558
559
560 ////////////////////////////////////////
561
562
563 /// @brief Compute the divergence of a vector grid.
564 template<
565 typename InGridT,
566 typename MaskGridType = typename gridop::ToMaskGrid<InGridT>::Type,
567 typename InterruptT = util::NullInterrupter>
568 class Divergence
569 {
570 public:
571 typedef InGridT InGridType;
572 typedef typename VectorToScalarConverter<InGridT>::Type OutGridType;
573
574 2 Divergence(const InGridT& grid, InterruptT* interrupt = nullptr):
575 2 mInputGrid(grid), mInterrupt(interrupt), mMask(nullptr)
576 {
577 }
578
579 2 Divergence(const InGridT& grid, const MaskGridType& mask, InterruptT* interrupt = nullptr):
580 2 mInputGrid(grid), mInterrupt(interrupt), mMask(&mask)
581 {
582 }
583
584 8 typename OutGridType::Ptr process(bool threaded = true)
585 {
586
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 3 times.
8 if (mInputGrid.getGridClass() == GRID_STAGGERED) {
587 2 Functor<math::FD_1ST> functor(mInputGrid, mMask, threaded, mInterrupt);
588
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 processTypedMap(mInputGrid.transform(), functor);
589 return functor.mOutputGrid;
590 } else {
591 6 Functor<math::CD_2ND> functor(mInputGrid, mMask, threaded, mInterrupt);
592
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
6 processTypedMap(mInputGrid.transform(), functor);
593 return functor.mOutputGrid;
594 }
595 }
596
597 protected:
598 template<math::DScheme DiffScheme>
599 struct Functor
600 {
601 4 Functor(const InGridT& grid, const MaskGridType* mask,
602 bool threaded, InterruptT* interrupt):
603
3/24
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 16 taken 2 times.
✗ Branch 17 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✓ Branch 31 taken 1 times.
✗ Branch 32 not taken.
✓ Branch 34 taken 1 times.
✗ Branch 35 not taken.
4 mThreaded(threaded), mInputGrid(grid), mInterrupt(interrupt), mMask(mask) {}
604
605 template<typename MapT>
606 8 void operator()(const MapT& map)
607 {
608 typedef math::Divergence<MapT, DiffScheme> OpT;
609 gridop::GridOperator<InGridType, MaskGridType, OutGridType, MapT, OpT, InterruptT>
610 8 op(mInputGrid, mMask, map, mInterrupt);
611
2/4
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
16 mOutputGrid = op.process(mThreaded); // cache the result
612 }
613
614 const bool mThreaded;
615 const InGridType& mInputGrid;
616 typename OutGridType::Ptr mOutputGrid;
617 InterruptT* mInterrupt;
618 const MaskGridType* mMask;
619 }; // Private Functor
620
621 const InGridType& mInputGrid;
622 InterruptT* mInterrupt;
623 const MaskGridType* mMask;
624 }; // end of Divergence class
625
626
627 ////////////////////////////////////////
628
629
630 /// @brief Compute the gradient of a scalar grid.
631 template<
632 typename InGridT,
633 typename MaskGridType = typename gridop::ToMaskGrid<InGridT>::Type,
634 typename InterruptT = util::NullInterrupter>
635 class Gradient
636 {
637 public:
638 typedef InGridT InGridType;
639 typedef typename ScalarToVectorConverter<InGridT>::Type OutGridType;
640
641 16 Gradient(const InGridT& grid, InterruptT* interrupt = nullptr):
642 16 mInputGrid(grid), mInterrupt(interrupt), mMask(nullptr)
643 {
644 }
645
646 1 Gradient(const InGridT& grid, const MaskGridType& mask, InterruptT* interrupt = nullptr):
647 1 mInputGrid(grid), mInterrupt(interrupt), mMask(&mask)
648 {
649 }
650
651 34 typename OutGridType::Ptr process(bool threaded = true)
652 {
653 34 Functor functor(mInputGrid, mMask, threaded, mInterrupt);
654
1/2
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
34 processTypedMap(mInputGrid.transform(), functor);
655
2/4
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 17 times.
✗ Branch 4 not taken.
34 if (functor.mOutputGrid) functor.mOutputGrid->setVectorType(VEC_COVARIANT);
656 34 return functor.mOutputGrid;
657 }
658
659 protected:
660 struct Functor
661 {
662 17 Functor(const InGridT& grid, const MaskGridType* mask,
663 bool threaded, InterruptT* interrupt):
664
3/8
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 12 times.
✗ Branch 11 not taken.
17 mThreaded(threaded), mInputGrid(grid), mInterrupt(interrupt), mMask(mask) {}
665
666 template<typename MapT>
667 34 void operator()(const MapT& map)
668 {
669 typedef math::Gradient<MapT, math::CD_2ND> OpT;
670 gridop::GridOperator<InGridType, MaskGridType, OutGridType, MapT, OpT, InterruptT>
671 34 op(mInputGrid, mMask, map, mInterrupt);
672
2/4
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 17 times.
✗ Branch 4 not taken.
68 mOutputGrid = op.process(mThreaded); // cache the result
673 }
674
675 const bool mThreaded;
676 const InGridT& mInputGrid;
677 typename OutGridType::Ptr mOutputGrid;
678 InterruptT* mInterrupt;
679 const MaskGridType* mMask;
680 }; // Private Functor
681
682 const InGridT& mInputGrid;
683 InterruptT* mInterrupt;
684 const MaskGridType* mMask;
685 }; // end of Gradient class
686
687
688 ////////////////////////////////////////
689
690
691 template<
692 typename GridT,
693 typename MaskGridType = typename gridop::ToMaskGrid<GridT>::Type,
694 typename InterruptT = util::NullInterrupter>
695 class Laplacian
696 {
697 public:
698 typedef GridT InGridType;
699 typedef GridT OutGridType;
700
701 1 Laplacian(const GridT& grid, InterruptT* interrupt = nullptr):
702 1 mInputGrid(grid), mInterrupt(interrupt), mMask(nullptr)
703 {
704 }
705
706 3 Laplacian(const GridT& grid, const MaskGridType& mask, InterruptT* interrupt = nullptr):
707 3 mInputGrid(grid), mInterrupt(interrupt), mMask(&mask)
708 {
709 }
710
711 8 typename GridT::Ptr process(bool threaded = true)
712 {
713 8 Functor functor(mInputGrid, mMask, threaded, mInterrupt);
714
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
8 processTypedMap(mInputGrid.transform(), functor);
715
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
8 if (functor.mOutputGrid) functor.mOutputGrid->setVectorType(VEC_COVARIANT);
716 8 return functor.mOutputGrid;
717 }
718
719 protected:
720 struct Functor
721 {
722 4 Functor(const GridT& grid, const MaskGridType* mask, bool threaded, InterruptT* interrupt):
723
3/16
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
4 mThreaded(threaded), mInputGrid(grid), mInterrupt(interrupt), mMask(mask) {}
724
725 template<typename MapT>
726 8 void operator()(const MapT& map)
727 {
728 typedef math::Laplacian<MapT, math::CD_SECOND> OpT;
729 gridop::GridOperator<GridT, MaskGridType, GridT, MapT, OpT, InterruptT>
730 8 op(mInputGrid, mMask, map, mInterrupt);
731
2/4
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
16 mOutputGrid = op.process(mThreaded); // cache the result
732 }
733
734 const bool mThreaded;
735 const GridT& mInputGrid;
736 typename GridT::Ptr mOutputGrid;
737 InterruptT* mInterrupt;
738 const MaskGridType* mMask;
739 }; // Private Functor
740
741 const GridT& mInputGrid;
742 InterruptT* mInterrupt;
743 const MaskGridType* mMask;
744 }; // end of Laplacian class
745
746
747 ////////////////////////////////////////
748
749
750 template<
751 typename GridT,
752 typename MaskGridType = typename gridop::ToMaskGrid<GridT>::Type,
753 typename InterruptT = util::NullInterrupter>
754 class MeanCurvature
755 {
756 public:
757 typedef GridT InGridType;
758 typedef GridT OutGridType;
759
760 1 MeanCurvature(const GridT& grid, InterruptT* interrupt = nullptr):
761 1 mInputGrid(grid), mInterrupt(interrupt), mMask(nullptr)
762 {
763 }
764
765 1 MeanCurvature(const GridT& grid, const MaskGridType& mask, InterruptT* interrupt = nullptr):
766 1 mInputGrid(grid), mInterrupt(interrupt), mMask(&mask)
767 {
768 }
769
770 4 typename GridT::Ptr process(bool threaded = true)
771 {
772 4 Functor functor(mInputGrid, mMask, threaded, mInterrupt);
773
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 processTypedMap(mInputGrid.transform(), functor);
774
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
4 if (functor.mOutputGrid) functor.mOutputGrid->setVectorType(VEC_COVARIANT);
775 4 return functor.mOutputGrid;
776 }
777
778 protected:
779 struct Functor
780 {
781 2 Functor(const GridT& grid, const MaskGridType* mask, bool threaded, InterruptT* interrupt):
782
2/16
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
2 mThreaded(threaded), mInputGrid(grid), mInterrupt(interrupt), mMask(mask) {}
783
784 template<typename MapT>
785 4 void operator()(const MapT& map)
786 {
787 typedef math::MeanCurvature<MapT, math::CD_SECOND, math::CD_2ND> OpT;
788 gridop::GridOperator<GridT, MaskGridType, GridT, MapT, OpT, InterruptT>
789 4 op(mInputGrid, mMask, map, mInterrupt);
790
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
8 mOutputGrid = op.process(mThreaded); // cache the result
791 }
792
793 const bool mThreaded;
794 const GridT& mInputGrid;
795 typename GridT::Ptr mOutputGrid;
796 InterruptT* mInterrupt;
797 const MaskGridType* mMask;
798 }; // Private Functor
799
800 const GridT& mInputGrid;
801 InterruptT* mInterrupt;
802 const MaskGridType* mMask;
803 }; // end of MeanCurvature class
804
805
806 ////////////////////////////////////////
807
808
809 template<
810 typename InGridT,
811 typename MaskGridType = typename gridop::ToMaskGrid<InGridT>::Type,
812 typename InterruptT = util::NullInterrupter>
813 class Magnitude
814 {
815 public:
816 typedef InGridT InGridType;
817 typedef typename VectorToScalarConverter<InGridT>::Type OutGridType;
818
819 2 Magnitude(const InGridType& grid, InterruptT* interrupt = nullptr):
820 2 mInputGrid(grid), mInterrupt(interrupt), mMask(nullptr)
821 {
822 }
823
824 2 Magnitude(const InGridType& grid, const MaskGridType& mask, InterruptT* interrupt = nullptr):
825 2 mInputGrid(grid), mInterrupt(interrupt), mMask(&mask)
826 {
827 }
828
829 8 typename OutGridType::Ptr process(bool threaded = true)
830 {
831 8 Functor functor(mInputGrid, mMask, threaded, mInterrupt);
832
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
8 processTypedMap(mInputGrid.transform(), functor);
833 8 return functor.mOutputGrid;
834 }
835
836 protected:
837 struct OpT
838 {
839 template<typename MapT, typename AccT>
840 static typename OutGridType::ValueType
841 526318 result(const MapT&, const AccT& acc, const Coord& xyz) { return acc.getValue(xyz).length();}
842 };
843 struct Functor
844 {
845 4 Functor(const InGridT& grid, const MaskGridType* mask,
846 bool threaded, InterruptT* interrupt):
847
2/12
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 16 taken 2 times.
✗ Branch 17 not taken.
4 mThreaded(threaded), mInputGrid(grid), mInterrupt(interrupt), mMask(mask) {}
848
849 template<typename MapT>
850 8 void operator()(const MapT& map)
851 {
852 gridop::GridOperator<InGridType, MaskGridType, OutGridType, MapT, OpT, InterruptT>
853 8 op(mInputGrid, mMask, map, mInterrupt, /*densify=*/false);
854
2/4
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
16 mOutputGrid = op.process(mThreaded); // cache the result
855 }
856
857 const bool mThreaded;
858 const InGridType& mInputGrid;
859 typename OutGridType::Ptr mOutputGrid;
860 InterruptT* mInterrupt;
861 const MaskGridType* mMask;
862 }; // Private Functor
863
864 const InGridType& mInputGrid;
865 InterruptT* mInterrupt;
866 const MaskGridType* mMask;
867 }; // end of Magnitude class
868
869
870 ////////////////////////////////////////
871
872
873 template<
874 typename GridT,
875 typename MaskGridType = typename gridop::ToMaskGrid<GridT>::Type,
876 typename InterruptT = util::NullInterrupter>
877 class Normalize
878 {
879 public:
880 typedef GridT InGridType;
881 typedef GridT OutGridType;
882
883 1 Normalize(const GridT& grid, InterruptT* interrupt = nullptr):
884 1 mInputGrid(grid), mInterrupt(interrupt), mMask(nullptr)
885 {
886 }
887
888 1 Normalize(const GridT& grid, const MaskGridType& mask, InterruptT* interrupt = nullptr):
889 1 mInputGrid(grid), mInterrupt(interrupt), mMask(&mask)
890 {
891 }
892
893 4 typename GridT::Ptr process(bool threaded = true)
894 {
895 4 Functor functor(mInputGrid, mMask, threaded, mInterrupt);
896
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 processTypedMap(mInputGrid.transform(), functor);
897
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
4 if (typename GridT::Ptr outGrid = functor.mOutputGrid) {
898
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 const VecType vecType = mInputGrid.getVectorType();
899
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
4 if (vecType == VEC_COVARIANT) {
900
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 outGrid->setVectorType(VEC_COVARIANT_NORMALIZE);
901 } else {
902 outGrid->setVectorType(vecType);
903 }
904 }
905 4 return functor.mOutputGrid;
906 }
907
908 protected:
909 struct OpT
910 {
911 template<typename MapT, typename AccT>
912 static typename OutGridType::ValueType
913 526308 result(const MapT&, const AccT& acc, const Coord& xyz)
914 {
915 526308 typename OutGridType::ValueType vec = acc.getValue(xyz);
916
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 263150 times.
526308 if ( !vec.normalize() ) vec.setZero();
917 526308 return vec;
918 }
919 };
920 struct Functor
921 {
922 2 Functor(const GridT& grid, const MaskGridType* mask, bool threaded, InterruptT* interrupt):
923
2/12
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
2 mThreaded(threaded), mInputGrid(grid), mInterrupt(interrupt), mMask(mask) {}
924
925 template<typename MapT>
926 4 void operator()(const MapT& map)
927 {
928 gridop::GridOperator<GridT, MaskGridType, GridT, MapT, OpT, InterruptT>
929 4 op(mInputGrid, mMask, map, mInterrupt, /*densify=*/false);
930
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
8 mOutputGrid = op.process(mThreaded); // cache the result
931 }
932
933 const bool mThreaded;
934 const GridT& mInputGrid;
935 typename GridT::Ptr mOutputGrid;
936 InterruptT* mInterrupt;
937 const MaskGridType* mMask;
938 }; // Private Functor
939
940 const GridT& mInputGrid;
941 InterruptT* mInterrupt;
942 const MaskGridType* mMask;
943 }; // end of Normalize class
944
945
946 ////////////////////////////////////////
947
948
949 template<typename GridType, typename InterruptT>
950 typename ScalarToVectorConverter<GridType>::Type::Ptr
951 cpt(const GridType& grid, bool threaded, InterruptT* interrupt)
952 {
953 Cpt<GridType, typename gridop::ToMaskGrid<GridType>::Type, InterruptT> op(grid, interrupt);
954 return op.process(threaded);
955 }
956
957 template<typename GridType, typename MaskT, typename InterruptT>
958 typename ScalarToVectorConverter<GridType>::Type::Ptr
959 cpt(const GridType& grid, const MaskT& mask, bool threaded, InterruptT* interrupt)
960 {
961 Cpt<GridType, MaskT, InterruptT> op(grid, mask, interrupt);
962 return op.process(threaded);
963 }
964
965 template<typename GridType, typename InterruptT>
966 typename GridType::Ptr
967 10 curl(const GridType& grid, bool threaded, InterruptT* interrupt)
968 {
969 Curl<GridType, typename gridop::ToMaskGrid<GridType>::Type, InterruptT> op(grid, interrupt);
970 10 return op.process(threaded);
971 }
972
973 template<typename GridType, typename MaskT, typename InterruptT>
974 typename GridType::Ptr
975 2 curl(const GridType& grid, const MaskT& mask, bool threaded, InterruptT* interrupt)
976 {
977 Curl<GridType, MaskT, InterruptT> op(grid, mask, interrupt);
978 2 return op.process(threaded);
979 }
980
981 template<typename GridType, typename InterruptT>
982 typename VectorToScalarConverter<GridType>::Type::Ptr
983 4 divergence(const GridType& grid, bool threaded, InterruptT* interrupt)
984 {
985 Divergence<GridType, typename gridop::ToMaskGrid<GridType>::Type, InterruptT>
986 op(grid, interrupt);
987 4 return op.process(threaded);
988 }
989
990 template<typename GridType, typename MaskT, typename InterruptT>
991 typename VectorToScalarConverter<GridType>::Type::Ptr
992 4 divergence(const GridType& grid, const MaskT& mask, bool threaded, InterruptT* interrupt)
993 {
994 Divergence<GridType, MaskT, InterruptT> op(grid, mask, interrupt);
995 4 return op.process(threaded);
996 }
997
998 template<typename GridType, typename InterruptT>
999 typename ScalarToVectorConverter<GridType>::Type::Ptr
1000 32 gradient(const GridType& grid, bool threaded, InterruptT* interrupt)
1001 {
1002 Gradient<GridType, typename gridop::ToMaskGrid<GridType>::Type, InterruptT>
1003 op(grid, interrupt);
1004 32 return op.process(threaded);
1005 }
1006
1007 template<typename GridType, typename MaskT, typename InterruptT>
1008 typename ScalarToVectorConverter<GridType>::Type::Ptr
1009 2 gradient(const GridType& grid, const MaskT& mask, bool threaded, InterruptT* interrupt)
1010 {
1011 Gradient<GridType, MaskT, InterruptT> op(grid, mask, interrupt);
1012 2 return op.process(threaded);
1013 }
1014
1015 template<typename GridType, typename InterruptT>
1016 typename GridType::Ptr
1017 2 laplacian(const GridType& grid, bool threaded, InterruptT* interrupt)
1018 {
1019 Laplacian<GridType, typename gridop::ToMaskGrid<GridType>::Type, InterruptT>
1020 op(grid, interrupt);
1021 2 return op.process(threaded);
1022 }
1023
1024 template<typename GridType, typename MaskT, typename InterruptT>
1025 typename GridType::Ptr
1026 6 laplacian(const GridType& grid, const MaskT& mask, bool threaded, InterruptT* interrupt)
1027 {
1028 Laplacian<GridType, MaskT, InterruptT> op(grid, mask, interrupt);
1029 6 return op.process(threaded);
1030 }
1031
1032 template<typename GridType, typename InterruptT>
1033 typename GridType::Ptr
1034 2 meanCurvature(const GridType& grid, bool threaded, InterruptT* interrupt)
1035 {
1036 MeanCurvature<GridType, typename gridop::ToMaskGrid<GridType>::Type, InterruptT>
1037 op(grid, interrupt);
1038 2 return op.process(threaded);
1039 }
1040
1041 template<typename GridType, typename MaskT, typename InterruptT>
1042 typename GridType::Ptr
1043 2 meanCurvature(const GridType& grid, const MaskT& mask, bool threaded, InterruptT* interrupt)
1044 {
1045 MeanCurvature<GridType, MaskT, InterruptT> op(grid, mask, interrupt);
1046 2 return op.process(threaded);
1047 }
1048
1049 template<typename GridType, typename InterruptT>
1050 typename VectorToScalarConverter<GridType>::Type::Ptr
1051 4 magnitude(const GridType& grid, bool threaded, InterruptT* interrupt)
1052 {
1053 Magnitude<GridType, typename gridop::ToMaskGrid<GridType>::Type, InterruptT>
1054 op(grid, interrupt);
1055 4 return op.process(threaded);
1056 }
1057
1058 template<typename GridType, typename MaskT, typename InterruptT>
1059 typename VectorToScalarConverter<GridType>::Type::Ptr
1060 4 magnitude(const GridType& grid, const MaskT& mask, bool threaded, InterruptT* interrupt)
1061 {
1062 Magnitude<GridType, MaskT, InterruptT> op(grid, mask, interrupt);
1063 4 return op.process(threaded);
1064 }
1065
1066 template<typename GridType, typename InterruptT>
1067 typename GridType::Ptr
1068 2 normalize(const GridType& grid, bool threaded, InterruptT* interrupt)
1069 {
1070 Normalize<GridType, typename gridop::ToMaskGrid<GridType>::Type, InterruptT>
1071 op(grid, interrupt);
1072 2 return op.process(threaded);
1073 }
1074
1075 template<typename GridType, typename MaskT, typename InterruptT>
1076 typename GridType::Ptr
1077 1 normalize(const GridType& grid, const MaskT& mask, bool threaded, InterruptT* interrupt)
1078 {
1079 Normalize<GridType, MaskT, InterruptT> op(grid, mask, interrupt);
1080 1 return op.process(threaded);
1081 }
1082
1083 ////////////////////////////////////////
1084
1085
1086 // Explicit Template Instantiation
1087
1088 #ifdef OPENVDB_USE_EXPLICIT_INSTANTIATION
1089
1090 #ifdef OPENVDB_INSTANTIATE_GRIDOPERATORS
1091 #include <openvdb/util/ExplicitInstantiation.h>
1092 #endif
1093
1094 #define _FUNCTION(TreeT) \
1095 ScalarToVectorConverter<Grid<TreeT>>::Type::Ptr cpt(const Grid<TreeT>&, bool, util::NullInterrupter*)
1096 OPENVDB_REAL_TREE_INSTANTIATE(_FUNCTION)
1097 #undef _FUNCTION
1098
1099 #define _FUNCTION(TreeT) \
1100 ScalarToVectorConverter<Grid<TreeT>>::Type::Ptr cpt(const Grid<TreeT>&, const BoolGrid&, bool, util::NullInterrupter*)
1101 OPENVDB_REAL_TREE_INSTANTIATE(_FUNCTION)
1102 #undef _FUNCTION
1103
1104 #define _FUNCTION(TreeT) \
1105 Grid<TreeT>::Ptr curl(const Grid<TreeT>&, bool, util::NullInterrupter*)
1106 OPENVDB_VEC3_TREE_INSTANTIATE(_FUNCTION)
1107 #undef _FUNCTION
1108
1109 #define _FUNCTION(TreeT) \
1110 Grid<TreeT>::Ptr curl(const Grid<TreeT>&, const BoolGrid&, bool, util::NullInterrupter*)
1111 OPENVDB_VEC3_TREE_INSTANTIATE(_FUNCTION)
1112 #undef _FUNCTION
1113
1114 #define _FUNCTION(TreeT) \
1115 VectorToScalarConverter<Grid<TreeT>>::Type::Ptr divergence(const Grid<TreeT>&, bool, util::NullInterrupter*)
1116 OPENVDB_VEC3_TREE_INSTANTIATE(_FUNCTION)
1117 #undef _FUNCTION
1118
1119 #define _FUNCTION(TreeT) \
1120 VectorToScalarConverter<Grid<TreeT>>::Type::Ptr divergence(const Grid<TreeT>&, const BoolGrid&, bool, util::NullInterrupter*)
1121 OPENVDB_VEC3_TREE_INSTANTIATE(_FUNCTION)
1122 #undef _FUNCTION
1123
1124 #define _FUNCTION(TreeT) \
1125 ScalarToVectorConverter<Grid<TreeT>>::Type::Ptr gradient(const Grid<TreeT>&, bool, util::NullInterrupter*)
1126 OPENVDB_REAL_TREE_INSTANTIATE(_FUNCTION)
1127 #undef _FUNCTION
1128
1129 #define _FUNCTION(TreeT) \
1130 ScalarToVectorConverter<Grid<TreeT>>::Type::Ptr gradient(const Grid<TreeT>&, const BoolGrid&, bool, util::NullInterrupter*)
1131 OPENVDB_REAL_TREE_INSTANTIATE(_FUNCTION)
1132 #undef _FUNCTION
1133
1134 #define _FUNCTION(TreeT) \
1135 Grid<TreeT>::Ptr laplacian(const Grid<TreeT>&, bool, util::NullInterrupter*)
1136 OPENVDB_NUMERIC_TREE_INSTANTIATE(_FUNCTION)
1137 #undef _FUNCTION
1138
1139 #define _FUNCTION(TreeT) \
1140 Grid<TreeT>::Ptr laplacian(const Grid<TreeT>&, const BoolGrid&, bool, util::NullInterrupter*)
1141 OPENVDB_NUMERIC_TREE_INSTANTIATE(_FUNCTION)
1142 #undef _FUNCTION
1143
1144 #define _FUNCTION(TreeT) \
1145 Grid<TreeT>::Ptr meanCurvature(const Grid<TreeT>&, bool, util::NullInterrupter*)
1146 OPENVDB_NUMERIC_TREE_INSTANTIATE(_FUNCTION)
1147 #undef _FUNCTION
1148
1149 #define _FUNCTION(TreeT) \
1150 Grid<TreeT>::Ptr meanCurvature(const Grid<TreeT>&, const BoolGrid&, bool, util::NullInterrupter*)
1151 OPENVDB_NUMERIC_TREE_INSTANTIATE(_FUNCTION)
1152 #undef _FUNCTION
1153
1154 #define _FUNCTION(TreeT) \
1155 VectorToScalarConverter<Grid<TreeT>>::Type::Ptr magnitude(const Grid<TreeT>&, bool, util::NullInterrupter*)
1156 OPENVDB_VEC3_TREE_INSTANTIATE(_FUNCTION)
1157 #undef _FUNCTION
1158
1159 #define _FUNCTION(TreeT) \
1160 VectorToScalarConverter<Grid<TreeT>>::Type::Ptr magnitude(const Grid<TreeT>&, const BoolGrid&, bool, util::NullInterrupter*)
1161 OPENVDB_VEC3_TREE_INSTANTIATE(_FUNCTION)
1162 #undef _FUNCTION
1163
1164 #define _FUNCTION(TreeT) \
1165 Grid<TreeT>::Ptr normalize(const Grid<TreeT>&, bool, util::NullInterrupter*)
1166 OPENVDB_VEC3_TREE_INSTANTIATE(_FUNCTION)
1167 #undef _FUNCTION
1168
1169 #define _FUNCTION(TreeT) \
1170 Grid<TreeT>::Ptr normalize(const Grid<TreeT>&, const BoolGrid&, bool, util::NullInterrupter*)
1171 OPENVDB_VEC3_TREE_INSTANTIATE(_FUNCTION)
1172 #undef _FUNCTION
1173
1174 #endif // OPENVDB_USE_EXPLICIT_INSTANTIATION
1175
1176
1177 } // namespace tools
1178 } // namespace OPENVDB_VERSION_NAME
1179 } // namespace openvdb
1180
1181 #endif // OPENVDB_TOOLS_GRID_OPERATORS_HAS_BEEN_INCLUDED
1182