| 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 |