Line | Branch | Exec | Source |
---|---|---|---|
1 | // Copyright Contributors to the OpenVDB Project | ||
2 | // SPDX-License-Identifier: MPL-2.0 | ||
3 | |||
4 | /// @file math/Maps.h | ||
5 | |||
6 | #ifndef OPENVDB_MATH_MAPS_HAS_BEEN_INCLUDED | ||
7 | #define OPENVDB_MATH_MAPS_HAS_BEEN_INCLUDED | ||
8 | |||
9 | #include "Math.h" | ||
10 | #include "Mat4.h" | ||
11 | #include "Vec3.h" | ||
12 | #include "BBox.h" | ||
13 | #include "Coord.h" | ||
14 | #include <openvdb/io/io.h> // for io::getFormatVersion() | ||
15 | #include <openvdb/util/Name.h> | ||
16 | #include <openvdb/Types.h> | ||
17 | #include <cmath> // for std::abs() | ||
18 | #include <iostream> | ||
19 | #include <map> | ||
20 | #include <string> | ||
21 | |||
22 | namespace openvdb { | ||
23 | OPENVDB_USE_VERSION_NAMESPACE | ||
24 | namespace OPENVDB_VERSION_NAME { | ||
25 | namespace math { | ||
26 | |||
27 | |||
28 | //////////////////////////////////////// | ||
29 | |||
30 | /// Forward declarations of the different map types | ||
31 | |||
32 | class MapBase; | ||
33 | class ScaleMap; | ||
34 | class TranslationMap; | ||
35 | class ScaleTranslateMap; | ||
36 | class UniformScaleMap; | ||
37 | class UniformScaleTranslateMap; | ||
38 | class AffineMap; | ||
39 | class UnitaryMap; | ||
40 | class NonlinearFrustumMap; | ||
41 | |||
42 | template<typename T1, typename T2> class CompoundMap; | ||
43 | |||
44 | using UnitaryAndTranslationMap = CompoundMap<UnitaryMap, TranslationMap>; | ||
45 | using SpectralDecomposedMap = CompoundMap<CompoundMap<UnitaryMap, ScaleMap>, UnitaryMap>; | ||
46 | using SymmetricMap = SpectralDecomposedMap; | ||
47 | using FullyDecomposedMap = CompoundMap<SymmetricMap, UnitaryAndTranslationMap>; | ||
48 | using PolarDecomposedMap = CompoundMap<SymmetricMap, UnitaryMap>; | ||
49 | |||
50 | |||
51 | //////////////////////////////////////// | ||
52 | |||
53 | /// Map traits | ||
54 | |||
55 | template<typename T> struct is_linear { static const bool value = false; }; | ||
56 | template<> struct is_linear<AffineMap> { static const bool value = true; }; | ||
57 | template<> struct is_linear<ScaleMap> { static const bool value = true; }; | ||
58 | template<> struct is_linear<UniformScaleMap> { static const bool value = true; }; | ||
59 | template<> struct is_linear<UnitaryMap> { static const bool value = true; }; | ||
60 | template<> struct is_linear<TranslationMap> { static const bool value = true; }; | ||
61 | template<> struct is_linear<ScaleTranslateMap> { static const bool value = true; }; | ||
62 | template<> struct is_linear<UniformScaleTranslateMap> { static const bool value = true; }; | ||
63 | |||
64 | template<typename T1, typename T2> struct is_linear<CompoundMap<T1, T2> > { | ||
65 | static const bool value = is_linear<T1>::value && is_linear<T2>::value; | ||
66 | }; | ||
67 | |||
68 | |||
69 | template<typename T> struct is_uniform_scale { static const bool value = false; }; | ||
70 | template<> struct is_uniform_scale<UniformScaleMap> { static const bool value = true; }; | ||
71 | |||
72 | template<typename T> struct is_uniform_scale_translate { static const bool value = false; }; | ||
73 | template<> struct is_uniform_scale_translate<TranslationMap> { static const bool value = true; }; | ||
74 | template<> struct is_uniform_scale_translate<UniformScaleTranslateMap> { | ||
75 | static const bool value = true; | ||
76 | }; | ||
77 | |||
78 | |||
79 | template<typename T> struct is_scale { static const bool value = false; }; | ||
80 | template<> struct is_scale<ScaleMap> { static const bool value = true; }; | ||
81 | |||
82 | template<typename T> struct is_scale_translate { static const bool value = false; }; | ||
83 | template<> struct is_scale_translate<ScaleTranslateMap> { static const bool value = true; }; | ||
84 | |||
85 | |||
86 | template<typename T> struct is_uniform_diagonal_jacobian { | ||
87 | static const bool value = is_uniform_scale<T>::value || is_uniform_scale_translate<T>::value; | ||
88 | }; | ||
89 | |||
90 | template<typename T> struct is_diagonal_jacobian { | ||
91 | static const bool value = is_scale<T>::value || is_scale_translate<T>::value; | ||
92 | }; | ||
93 | |||
94 | |||
95 | //////////////////////////////////////// | ||
96 | |||
97 | /// Utility methods | ||
98 | |||
99 | /// @brief Create a SymmetricMap from a symmetric matrix. | ||
100 | /// Decomposes the map into Rotation Diagonal Rotation^T | ||
101 | OPENVDB_API SharedPtr<SymmetricMap> createSymmetricMap(const Mat3d& m); | ||
102 | |||
103 | |||
104 | /// @brief General decomposition of a Matrix into a Unitary (e.g. rotation) | ||
105 | /// following a Symmetric (e.g. stretch & shear) | ||
106 | OPENVDB_API SharedPtr<FullyDecomposedMap> createFullyDecomposedMap(const Mat4d& m); | ||
107 | |||
108 | |||
109 | /// @brief Decomposes a general linear into translation following polar decomposition. | ||
110 | /// | ||
111 | /// T U S where: | ||
112 | /// | ||
113 | /// T: Translation | ||
114 | /// U: Unitary (rotation or reflection) | ||
115 | /// S: Symmetric | ||
116 | /// | ||
117 | /// @note: the Symmetric is automatically decomposed into Q D Q^T, where | ||
118 | /// Q is rotation and D is diagonal. | ||
119 | OPENVDB_API SharedPtr<PolarDecomposedMap> createPolarDecomposedMap(const Mat3d& m); | ||
120 | |||
121 | |||
122 | /// @brief reduces an AffineMap to a ScaleMap or a ScaleTranslateMap when it can | ||
123 | OPENVDB_API SharedPtr<MapBase> simplify(SharedPtr<AffineMap> affine); | ||
124 | |||
125 | /// @brief Returns the left pseudoInverse of the input matrix when the 3x3 part is symmetric | ||
126 | /// otherwise it zeros the 3x3 and reverses the translation. | ||
127 | OPENVDB_API Mat4d approxInverse(const Mat4d& mat); | ||
128 | |||
129 | |||
130 | //////////////////////////////////////// | ||
131 | |||
132 | |||
133 | /// @brief Abstract base class for maps | ||
134 | class OPENVDB_API MapBase | ||
135 | { | ||
136 | public: | ||
137 | using Ptr = SharedPtr<MapBase>; | ||
138 | using ConstPtr = SharedPtr<const MapBase>; | ||
139 | using MapFactory = Ptr (*)(); | ||
140 | |||
141 | 21965 | MapBase(const MapBase&) = default; | |
142 | virtual ~MapBase() = default; | ||
143 | |||
144 | virtual SharedPtr<AffineMap> getAffineMap() const = 0; | ||
145 | |||
146 | /// Return the name of this map's concrete type (e.g., @c "AffineMap"). | ||
147 | virtual Name type() const = 0; | ||
148 | |||
149 | /// Return @c true if this map is of concrete type @c MapT (e.g., AffineMap). | ||
150 | 119152 | template<typename MapT> bool isType() const { return this->type() == MapT::mapType(); } | |
151 | |||
152 | /// Return @c true if this map is equal to the given map. | ||
153 | virtual bool isEqual(const MapBase& other) const = 0; | ||
154 | |||
155 | /// Return @c true if this map is linear. | ||
156 | virtual bool isLinear() const = 0; | ||
157 | /// Return @c true if the spacing between the image of latice is uniform in all directions | ||
158 | virtual bool hasUniformScale() const = 0; | ||
159 | |||
160 | virtual Vec3d applyMap(const Vec3d& in) const = 0; | ||
161 | virtual Vec3d applyInverseMap(const Vec3d& in) const = 0; | ||
162 | |||
163 | //@{ | ||
164 | /// @brief Apply the Inverse Jacobian Transpose of this map to a vector. | ||
165 | /// For a linear map this is equivalent to applying the transpose of | ||
166 | /// inverse map excluding translation. | ||
167 | virtual Vec3d applyIJT(const Vec3d& in) const = 0; | ||
168 | virtual Vec3d applyIJT(const Vec3d& in, const Vec3d& domainPos) const = 0; | ||
169 | //@} | ||
170 | |||
171 | virtual Mat3d applyIJC(const Mat3d& m) const = 0; | ||
172 | virtual Mat3d applyIJC(const Mat3d& m, const Vec3d& v, const Vec3d& domainPos) const = 0; | ||
173 | |||
174 | |||
175 | virtual double determinant() const = 0; | ||
176 | virtual double determinant(const Vec3d&) const = 0; | ||
177 | |||
178 | |||
179 | //@{ | ||
180 | /// @brief Method to return the local size of a voxel. | ||
181 | /// When a location is specified as an argument, it is understood to be | ||
182 | /// be in the domain of the map (i.e. index space) | ||
183 | virtual Vec3d voxelSize() const = 0; | ||
184 | virtual Vec3d voxelSize(const Vec3d&) const = 0; | ||
185 | //@} | ||
186 | |||
187 | virtual void read(std::istream&) = 0; | ||
188 | virtual void write(std::ostream&) const = 0; | ||
189 | |||
190 | virtual std::string str() const = 0; | ||
191 | |||
192 | virtual MapBase::Ptr copy() const = 0; | ||
193 | |||
194 | //@{ | ||
195 | /// @brief Methods to update the map | ||
196 | virtual MapBase::Ptr preRotate(double radians, Axis axis = X_AXIS) const = 0; | ||
197 | virtual MapBase::Ptr preTranslate(const Vec3d&) const = 0; | ||
198 | virtual MapBase::Ptr preScale(const Vec3d&) const = 0; | ||
199 | virtual MapBase::Ptr preShear(double shear, Axis axis0, Axis axis1) const = 0; | ||
200 | |||
201 | virtual MapBase::Ptr postRotate(double radians, Axis axis = X_AXIS) const = 0; | ||
202 | virtual MapBase::Ptr postTranslate(const Vec3d&) const = 0; | ||
203 | virtual MapBase::Ptr postScale(const Vec3d&) const = 0; | ||
204 | virtual MapBase::Ptr postShear(double shear, Axis axis0, Axis axis1) const = 0; | ||
205 | //@} | ||
206 | |||
207 | //@{ | ||
208 | /// @brief Apply the Jacobian of this map to a vector. | ||
209 | /// For a linear map this is equivalent to applying the map excluding translation. | ||
210 | /// @warning Houdini 12.5 uses an earlier version of OpenVDB, and maps created | ||
211 | /// with that version lack a virtual table entry for this method. Do not call | ||
212 | /// this method from Houdini 12.5. | ||
213 | virtual Vec3d applyJacobian(const Vec3d& in) const = 0; | ||
214 | virtual Vec3d applyJacobian(const Vec3d& in, const Vec3d& domainPos) const = 0; | ||
215 | //@} | ||
216 | |||
217 | //@{ | ||
218 | /// @brief Apply the InverseJacobian of this map to a vector. | ||
219 | /// For a linear map this is equivalent to applying the map inverse excluding translation. | ||
220 | /// @warning Houdini 12.5 uses an earlier version of OpenVDB, and maps created | ||
221 | /// with that version lack a virtual table entry for this method. Do not call | ||
222 | /// this method from Houdini 12.5. | ||
223 | virtual Vec3d applyInverseJacobian(const Vec3d& in) const = 0; | ||
224 | virtual Vec3d applyInverseJacobian(const Vec3d& in, const Vec3d& domainPos) const = 0; | ||
225 | //@} | ||
226 | |||
227 | |||
228 | //@{ | ||
229 | /// @brief Apply the Jacobian transpose of this map to a vector. | ||
230 | /// For a linear map this is equivalent to applying the transpose of the map | ||
231 | /// excluding translation. | ||
232 | /// @warning Houdini 12.5 uses an earlier version of OpenVDB, and maps created | ||
233 | /// with that version lack a virtual table entry for this method. Do not call | ||
234 | /// this method from Houdini 12.5. | ||
235 | virtual Vec3d applyJT(const Vec3d& in) const = 0; | ||
236 | virtual Vec3d applyJT(const Vec3d& in, const Vec3d& domainPos) const = 0; | ||
237 | //@} | ||
238 | |||
239 | /// @brief Return a new map representing the inverse of this map. | ||
240 | /// @throw NotImplementedError if the map is a NonlinearFrustumMap. | ||
241 | /// @warning Houdini 12.5 uses an earlier version of OpenVDB, and maps created | ||
242 | /// with that version lack a virtual table entry for this method. Do not call | ||
243 | /// this method from Houdini 12.5. | ||
244 | virtual MapBase::Ptr inverseMap() const = 0; | ||
245 | |||
246 | protected: | ||
247 | 53841 | MapBase() {} | |
248 | |||
249 | template<typename MapT> | ||
250 | 12498 | static bool isEqualBase(const MapT& self, const MapBase& other) | |
251 | { | ||
252 |
4/5✓ Branch 1 taken 6244 times.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 3 times.
|
12498 | return other.isType<MapT>() && (self == *static_cast<const MapT*>(&other)); |
253 | } | ||
254 | }; | ||
255 | |||
256 | |||
257 | //////////////////////////////////////// | ||
258 | |||
259 | |||
260 | /// @brief Threadsafe singleton object for accessing the map type-name dictionary. | ||
261 | /// Associates a map type-name with a factory function. | ||
262 | class OPENVDB_API MapRegistry | ||
263 | { | ||
264 | public: | ||
265 | using MapDictionary = std::map<Name, MapBase::MapFactory>; | ||
266 | |||
267 | static MapRegistry* instance(); | ||
268 | |||
269 | /// Create a new map of the given (registered) type name. | ||
270 | static MapBase::Ptr createMap(const Name&); | ||
271 | |||
272 | /// Return @c true if the given map type name is registered. | ||
273 | static bool isRegistered(const Name&); | ||
274 | |||
275 | /// Register a map type along with a factory function. | ||
276 | static void registerMap(const Name&, MapBase::MapFactory); | ||
277 | |||
278 | /// Remove a map type from the registry. | ||
279 | static void unregisterMap(const Name&); | ||
280 | |||
281 | /// Clear the map type registry. | ||
282 | static void clear(); | ||
283 | |||
284 | private: | ||
285 | MapRegistry() {} | ||
286 | |||
287 | static MapRegistry* staticInstance(); | ||
288 | |||
289 | MapDictionary mMap; | ||
290 | }; | ||
291 | |||
292 | |||
293 | //////////////////////////////////////// | ||
294 | |||
295 | |||
296 | /// @note Macro to use a final specifier from ABI=8 onwards. | ||
297 | #if OPENVDB_ABI_VERSION_NUMBER >= 8 | ||
298 | #define OPENVDB_MAP_CLASS_SPECIFIER final | ||
299 | #define OPENVDB_MAP_FUNC_SPECIFIER final | ||
300 | #else | ||
301 | #define OPENVDB_MAP_CLASS_SPECIFIER | ||
302 | #define OPENVDB_MAP_FUNC_SPECIFIER override | ||
303 | #endif | ||
304 | |||
305 | |||
306 | /// @brief A general linear transform using homogeneous coordinates to perform | ||
307 | /// rotation, scaling, shear and translation | ||
308 | /// @note This class is marked final with ABI=8 | ||
309 | class OPENVDB_API AffineMap OPENVDB_MAP_CLASS_SPECIFIER: public MapBase | ||
310 | { | ||
311 | public: | ||
312 | using Ptr = SharedPtr<AffineMap>; | ||
313 | using ConstPtr = SharedPtr<const AffineMap>; | ||
314 | |||
315 | 86 | AffineMap(): | |
316 | 86 | mMatrix(Mat4d::identity()), | |
317 | 86 | mMatrixInv(Mat4d::identity()), | |
318 | 86 | mJacobianInv(Mat3d::identity()), | |
319 | mDeterminant(1), | ||
320 | mVoxelSize(Vec3d(1,1,1)), | ||
321 | mIsDiagonal(true), | ||
322 | 86 | mIsIdentity(true) | |
323 | // the default constructor for translation is zero | ||
324 | { | ||
325 | 86 | } | |
326 | |||
327 | 11 | AffineMap(const Mat3d& m) | |
328 | 11 | { | |
329 | 11 | Mat4d mat4(Mat4d::identity()); | |
330 | mat4.setMat3(m); | ||
331 | 11 | mMatrix = mat4; | |
332 | 11 | updateAcceleration(); | |
333 | 11 | } | |
334 | |||
335 |
1/2✓ Branch 0 taken 117 times.
✗ Branch 1 not taken.
|
117 | AffineMap(const Mat4d& m): mMatrix(m) |
336 | { | ||
337 | if (!isAffine(m)) { | ||
338 | ✗ | OPENVDB_THROW(ArithmeticError, | |
339 | "Tried to initialize an affine transform from a non-affine 4x4 matrix"); | ||
340 | } | ||
341 | 117 | updateAcceleration(); | |
342 | 117 | } | |
343 | |||
344 | 21955 | AffineMap(const AffineMap& other): | |
345 | MapBase(other), | ||
346 | mMatrix(other.mMatrix), | ||
347 | mMatrixInv(other.mMatrixInv), | ||
348 | mJacobianInv(other.mJacobianInv), | ||
349 | 21955 | mDeterminant(other.mDeterminant), | |
350 | mVoxelSize(other.mVoxelSize), | ||
351 | 21955 | mIsDiagonal(other.mIsDiagonal), | |
352 | 21955 | mIsIdentity(other.mIsIdentity) | |
353 | { | ||
354 | 21955 | } | |
355 | |||
356 | /// @brief constructor that merges the matrixes for two affine maps | ||
357 | 5 | AffineMap(const AffineMap& first, const AffineMap& second): | |
358 | 5 | mMatrix(first.mMatrix * second.mMatrix) | |
359 | { | ||
360 | 5 | updateAcceleration(); | |
361 | 5 | } | |
362 | |||
363 |
3/8✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
|
318 | ~AffineMap() override = default; |
364 | |||
365 | /// Return a MapBase::Ptr to a new AffineMap | ||
366 | 1 | static MapBase::Ptr create() { return MapBase::Ptr(new AffineMap()); } | |
367 | /// Return a MapBase::Ptr to a deep copy of this map | ||
368 | 38 | MapBase::Ptr copy() const override { return MapBase::Ptr(new AffineMap(*this)); } | |
369 | |||
370 | ✗ | MapBase::Ptr inverseMap() const override { return MapBase::Ptr(new AffineMap(mMatrixInv)); } | |
371 | |||
372 | 3 | static bool isRegistered() { return MapRegistry::isRegistered(AffineMap::mapType()); } | |
373 | |||
374 | 338 | static void registerMap() | |
375 | { | ||
376 | 338 | MapRegistry::registerMap( | |
377 | 338 | AffineMap::mapType(), | |
378 | AffineMap::create); | ||
379 | 338 | } | |
380 | |||
381 | 150 | Name type() const override { return mapType(); } | |
382 |
10/120✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 3 times.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 335 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 3 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 18 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✓ Branch 25 taken 6 times.
✗ 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 not taken.
✗ 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 not taken.
✗ 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.
✗ Branch 161 not taken.
✗ Branch 162 not taken.
✗ Branch 165 not taken.
✗ Branch 166 not taken.
✗ Branch 169 not taken.
✗ Branch 170 not taken.
✗ Branch 173 not taken.
✗ Branch 174 not taken.
✗ Branch 177 not taken.
✗ Branch 178 not taken.
✗ Branch 181 not taken.
✗ Branch 182 not taken.
✗ Branch 185 not taken.
✗ Branch 186 not taken.
✗ Branch 189 not taken.
✗ Branch 190 not taken.
✗ Branch 193 not taken.
✗ Branch 194 not taken.
✗ Branch 197 not taken.
✗ Branch 198 not taken.
✗ Branch 201 not taken.
✗ Branch 202 not taken.
✗ Branch 205 not taken.
✗ Branch 206 not taken.
✗ Branch 209 not taken.
✗ Branch 210 not taken.
✗ Branch 213 not taken.
✗ Branch 214 not taken.
✗ Branch 217 not taken.
✗ Branch 218 not taken.
✗ Branch 222 not taken.
✗ Branch 223 not taken.
✗ Branch 225 not taken.
✗ Branch 226 not taken.
|
430 | static Name mapType() { return Name("AffineMap"); } |
383 | |||
384 | /// Return @c true (an AffineMap is always linear). | ||
385 | 95 | bool isLinear() const override { return true; } | |
386 | |||
387 | /// Return @c false ( test if this is unitary with translation ) | ||
388 | 4 | bool hasUniformScale() const override | |
389 | { | ||
390 | Mat3d mat = mMatrix.getMat3(); | ||
391 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | const double det = mat.det(); |
392 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | if (isApproxEqual(det, double(0))) { |
393 | return false; | ||
394 | } else { | ||
395 | 4 | mat *= (1.0 / pow(std::abs(det), 1.0/3.0)); | |
396 | 4 | return isUnitary(mat); | |
397 | } | ||
398 | } | ||
399 | |||
400 | 1 | bool isEqual(const MapBase& other) const override { return isEqualBase(*this, other); } | |
401 | |||
402 | 5 | bool operator==(const AffineMap& other) const | |
403 | { | ||
404 | // the Mat.eq() is approximate | ||
405 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
|
5 | if (!mMatrix.eq(other.mMatrix)) { return false; } |
406 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (!mMatrixInv.eq(other.mMatrixInv)) { return false; } |
407 | return true; | ||
408 | } | ||
409 | |||
410 | 2 | bool operator!=(const AffineMap& other) const { return !(*this == other); } | |
411 | |||
412 | AffineMap& operator=(const AffineMap& other) | ||
413 | { | ||
414 | 53 | mMatrix = other.mMatrix; | |
415 | 53 | mMatrixInv = other.mMatrixInv; | |
416 | |||
417 | 53 | mJacobianInv = other.mJacobianInv; | |
418 | 53 | mDeterminant = other.mDeterminant; | |
419 | 53 | mVoxelSize = other.mVoxelSize; | |
420 | 53 | mIsDiagonal = other.mIsDiagonal; | |
421 |
1/4✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 34 times.
✗ Branch 3 not taken.
|
42 | mIsIdentity = other.mIsIdentity; |
422 | return *this; | ||
423 | } | ||
424 | /// Return the image of @c in under the map | ||
425 | 2500069229 | Vec3d applyMap(const Vec3d& in) const override { return in * mMatrix; } | |
426 | /// Return the pre-image of @c in under the map | ||
427 | 322200 | Vec3d applyInverseMap(const Vec3d& in) const override {return in * mMatrixInv; } | |
428 | |||
429 | /// Return the Jacobian of the map applied to @a in. | ||
430 | ✗ | Vec3d applyJacobian(const Vec3d& in, const Vec3d&) const override { return applyJacobian(in); } | |
431 | /// Return the Jacobian of the map applied to @a in. | ||
432 | 12 | Vec3d applyJacobian(const Vec3d& in) const override { return mMatrix.transform3x3(in); } | |
433 | |||
434 | /// @brief Return the Inverse Jacobian of the map applied to @a in | ||
435 | /// (i.e. inverse map with out translation) | ||
436 | ✗ | Vec3d applyInverseJacobian(const Vec3d& in, const Vec3d&) const override { | |
437 | ✗ | return applyInverseJacobian(in); | |
438 | } | ||
439 | /// @brief Return the Inverse Jacobian of the map applied to @a in | ||
440 | /// (i.e. inverse map with out translation) | ||
441 | ✗ | Vec3d applyInverseJacobian(const Vec3d& in) const override { | |
442 | 11 | return mMatrixInv.transform3x3(in); | |
443 | } | ||
444 | |||
445 | /// Return the Jacobian Transpose of the map applied to @a in. | ||
446 | /// This tranforms range-space gradients to domain-space gradients | ||
447 | ✗ | Vec3d applyJT(const Vec3d& in, const Vec3d&) const override { return applyJT(in); } | |
448 | /// Return the Jacobian Transpose of the map applied to @a in. | ||
449 | ✗ | Vec3d applyJT(const Vec3d& in) const override { | |
450 | const double* m = mMatrix.asPointer(); | ||
451 | ✗ | return Vec3d( m[ 0] * in[0] + m[ 1] * in[1] + m[ 2] * in[2], | |
452 | ✗ | m[ 4] * in[0] + m[ 5] * in[1] + m[ 6] * in[2], | |
453 | ✗ | m[ 8] * in[0] + m[ 9] * in[1] + m[10] * in[2] ); | |
454 | } | ||
455 | |||
456 | /// Return the transpose of the inverse Jacobian of the map applied to @a in. | ||
457 | 4 | Vec3d applyIJT(const Vec3d& in, const Vec3d&) const override { return applyIJT(in); } | |
458 | /// Return the transpose of the inverse Jacobian of the map applied to @c in | ||
459 | 314998 | Vec3d applyIJT(const Vec3d& in) const override { return in * mJacobianInv; } | |
460 | /// Return the Jacobian Curvature: zero for a linear map | ||
461 | 32 | Mat3d applyIJC(const Mat3d& m) const override { | |
462 | 32 | return mJacobianInv.transpose()* m * mJacobianInv; | |
463 | } | ||
464 | 2 | Mat3d applyIJC(const Mat3d& in, const Vec3d& , const Vec3d& ) const override { | |
465 | 2 | return applyIJC(in); | |
466 | } | ||
467 | /// Return the determinant of the Jacobian, ignores argument | ||
468 | ✗ | double determinant(const Vec3d& ) const override { return determinant(); } | |
469 | /// Return the determinant of the Jacobian | ||
470 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | double determinant() const override { return mDeterminant; } |
471 | |||
472 | //@{ | ||
473 | /// @brief Return the lengths of the images of the segments | ||
474 | /// (0,0,0)-(1,0,0), (0,0,0)-(0,1,0) and (0,0,0)-(0,0,1). | ||
475 | 333005 | Vec3d voxelSize() const override { return mVoxelSize; } | |
476 | ✗ | Vec3d voxelSize(const Vec3d&) const override { return voxelSize(); } | |
477 | //@} | ||
478 | |||
479 | /// Return @c true if the underlying matrix is approximately an identity | ||
480 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | bool isIdentity() const { return mIsIdentity; } |
481 | /// Return @c true if the underylying matrix is diagonal | ||
482 |
2/2✓ Branch 0 taken 21 times.
✓ Branch 1 taken 101 times.
|
122 | bool isDiagonal() const { return mIsDiagonal; } |
483 | /// Return @c true if the map is equivalent to a ScaleMap | ||
484 | bool isScale() const { return isDiagonal(); } | ||
485 | /// Return @c true if the map is equivalent to a ScaleTranslateMap | ||
486 | 101 | bool isScaleTranslate() const { return math::isDiagonal(mMatrix.getMat3()); } | |
487 | |||
488 | |||
489 | // Methods that modify the existing affine map | ||
490 | |||
491 | //@{ | ||
492 | /// @brief Modify the existing affine map by pre-applying the given operation. | ||
493 | void accumPreRotation(Axis axis, double radians) | ||
494 | { | ||
495 | 24 | mMatrix.preRotate(axis, radians); | |
496 |
3/10✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 7 taken 16 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
|
24 | updateAcceleration(); |
497 | 21 | } | |
498 | void accumPreScale(const Vec3d& v) | ||
499 | { | ||
500 | 20 | mMatrix.preScale(v); | |
501 |
1/8✓ Branch 1 taken 14 times.
✗ 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.
|
20 | updateAcceleration(); |
502 | 14 | } | |
503 | void accumPreTranslation(const Vec3d& v) | ||
504 | { | ||
505 | 4 | mMatrix.preTranslate(v); | |
506 |
1/4✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
4 | updateAcceleration(); |
507 | 4 | } | |
508 | void accumPreShear(Axis axis0, Axis axis1, double shear) | ||
509 | { | ||
510 | 7 | mMatrix.preShear(axis0, axis1, shear); | |
511 |
3/10✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
|
7 | updateAcceleration(); |
512 | 7 | } | |
513 | //@} | ||
514 | |||
515 | |||
516 | //@{ | ||
517 | /// @brief Modify the existing affine map by post-applying the given operation. | ||
518 | void accumPostRotation(Axis axis, double radians) | ||
519 | { | ||
520 | 24 | mMatrix.postRotate(axis, radians); | |
521 |
3/13✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 6 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
|
24 | updateAcceleration(); |
522 | 23 | } | |
523 | void accumPostScale(const Vec3d& v) | ||
524 | { | ||
525 | 3 | mMatrix.postScale(v); | |
526 |
1/6✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
3 | updateAcceleration(); |
527 | 2 | } | |
528 | void accumPostTranslation(const Vec3d& v) | ||
529 | { | ||
530 | 12 | mMatrix.postTranslate(v); | |
531 |
2/8✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
38 | updateAcceleration(); |
532 | 35 | } | |
533 | void accumPostShear(Axis axis0, Axis axis1, double shear) | ||
534 | { | ||
535 | 7 | mMatrix.postShear(axis0, axis1, shear); | |
536 |
3/10✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
|
7 | updateAcceleration(); |
537 | 7 | } | |
538 | //@} | ||
539 | |||
540 | |||
541 | /// read serialization | ||
542 | 1 | void read(std::istream& is) override { mMatrix.read(is); updateAcceleration(); } | |
543 | /// write serialization | ||
544 | 1 | void write(std::ostream& os) const override { mMatrix.write(os); } | |
545 | /// string serialization, useful for debugging | ||
546 | ✗ | std::string str() const override | |
547 | { | ||
548 | ✗ | std::ostringstream buffer; | |
549 | ✗ | buffer << " - mat4:\n" << mMatrix.str() << std::endl; | |
550 | ✗ | buffer << " - voxel dimensions: " << mVoxelSize << std::endl; | |
551 | ✗ | return buffer.str(); | |
552 | } | ||
553 | |||
554 | /// on-demand decomposition of the affine map | ||
555 | SharedPtr<FullyDecomposedMap> createDecomposedMap() | ||
556 | { | ||
557 | return createFullyDecomposedMap(mMatrix); | ||
558 | } | ||
559 | |||
560 | /// Return AffineMap::Ptr to a deep copy of the current AffineMap | ||
561 | 165 | AffineMap::Ptr getAffineMap() const override { return AffineMap::Ptr(new AffineMap(*this)); } | |
562 | |||
563 | /// Return AffineMap::Ptr to the inverse of this map | ||
564 | AffineMap::Ptr inverse() const { return AffineMap::Ptr(new AffineMap(mMatrixInv)); } | ||
565 | |||
566 | |||
567 | //@{ | ||
568 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
569 | /// of prepending the appropraite operation. | ||
570 | 2 | MapBase::Ptr preRotate(double radians, Axis axis = X_AXIS) const override | |
571 | { | ||
572 | 2 | AffineMap::Ptr affineMap = getAffineMap(); | |
573 | affineMap->accumPreRotation(axis, radians); | ||
574 |
2/6✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
6 | return simplify(affineMap); |
575 | } | ||
576 | 4 | MapBase::Ptr preTranslate(const Vec3d& t) const override | |
577 | { | ||
578 | 4 | AffineMap::Ptr affineMap = getAffineMap(); | |
579 | affineMap->accumPreTranslation(t); | ||
580 | 4 | return StaticPtrCast<MapBase, AffineMap>(affineMap); | |
581 | } | ||
582 | 14 | MapBase::Ptr preScale(const Vec3d& s) const override | |
583 | { | ||
584 | 14 | AffineMap::Ptr affineMap = getAffineMap(); | |
585 | affineMap->accumPreScale(s); | ||
586 | 14 | return StaticPtrCast<MapBase, AffineMap>(affineMap); | |
587 | } | ||
588 | 3 | MapBase::Ptr preShear(double shear, Axis axis0, Axis axis1) const override | |
589 | { | ||
590 | 3 | AffineMap::Ptr affineMap = getAffineMap(); | |
591 | affineMap->accumPreShear(axis0, axis1, shear); | ||
592 |
2/6✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
9 | return simplify(affineMap); |
593 | } | ||
594 | //@} | ||
595 | |||
596 | |||
597 | //@{ | ||
598 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
599 | /// of postfixing the appropraite operation. | ||
600 | 6 | MapBase::Ptr postRotate(double radians, Axis axis = X_AXIS) const override | |
601 | { | ||
602 | 6 | AffineMap::Ptr affineMap = getAffineMap(); | |
603 | affineMap->accumPostRotation(axis, radians); | ||
604 |
2/6✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
18 | return simplify(affineMap); |
605 | } | ||
606 | 9 | MapBase::Ptr postTranslate(const Vec3d& t) const override | |
607 | { | ||
608 | 9 | AffineMap::Ptr affineMap = getAffineMap(); | |
609 | affineMap->accumPostTranslation(t); | ||
610 | 9 | return StaticPtrCast<MapBase, AffineMap>(affineMap); | |
611 | } | ||
612 | 2 | MapBase::Ptr postScale(const Vec3d& s) const override | |
613 | { | ||
614 | 2 | AffineMap::Ptr affineMap = getAffineMap(); | |
615 | affineMap->accumPostScale(s); | ||
616 | 2 | return StaticPtrCast<MapBase, AffineMap>(affineMap); | |
617 | } | ||
618 | 3 | MapBase::Ptr postShear(double shear, Axis axis0, Axis axis1) const override | |
619 | { | ||
620 | 3 | AffineMap::Ptr affineMap = getAffineMap(); | |
621 | affineMap->accumPostShear(axis0, axis1, shear); | ||
622 |
2/6✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
9 | return simplify(affineMap); |
623 | } | ||
624 | //@} | ||
625 | |||
626 | /// Return the matrix representation of this AffineMap | ||
627 |
8/52✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 3 times.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ 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 not taken.
✗ 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 not taken.
✗ 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.
|
19 | Mat4d getMat4() const { return mMatrix;} |
628 | const Mat4d& getConstMat4() const {return mMatrix;} | ||
629 | const Mat3d& getConstJacobianInv() const {return mJacobianInv;} | ||
630 | |||
631 | private: | ||
632 | 261 | void updateAcceleration() { | |
633 | Mat3d mat3 = mMatrix.getMat3(); | ||
634 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 261 times.
|
261 | mDeterminant = mat3.det(); |
635 | |||
636 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 261 times.
|
261 | if (std::abs(mDeterminant) < (3.0 * math::Tolerance<double>::value())) { |
637 | ✗ | OPENVDB_THROW(ArithmeticError, | |
638 | "Tried to initialize an affine transform from a nearly singular matrix"); | ||
639 | } | ||
640 | 261 | mMatrixInv = mMatrix.inverse(); | |
641 | 261 | mJacobianInv = mat3.inverse().transpose(); | |
642 | 261 | mIsDiagonal = math::isDiagonal(mMatrix); | |
643 | 261 | mIsIdentity = math::isIdentity(mMatrix); | |
644 | 261 | Vec3d pos = applyMap(Vec3d(0,0,0)); | |
645 | 261 | mVoxelSize(0) = (applyMap(Vec3d(1,0,0)) - pos).length(); | |
646 | 261 | mVoxelSize(1) = (applyMap(Vec3d(0,1,0)) - pos).length(); | |
647 | 261 | mVoxelSize(2) = (applyMap(Vec3d(0,0,1)) - pos).length(); | |
648 | 261 | } | |
649 | |||
650 | // the underlying matrix | ||
651 | Mat4d mMatrix; | ||
652 | |||
653 | // stored for acceleration | ||
654 | Mat4d mMatrixInv; | ||
655 | Mat3d mJacobianInv; | ||
656 | double mDeterminant; | ||
657 | Vec3d mVoxelSize; | ||
658 | bool mIsDiagonal, mIsIdentity; | ||
659 | }; // class AffineMap | ||
660 | |||
661 | |||
662 | //////////////////////////////////////// | ||
663 | |||
664 | |||
665 | /// @brief A specialized Affine transform that scales along the principal axis | ||
666 | /// the scaling need not be uniform in the three-directions | ||
667 | /// @note This class is not marked final because UniformScaleMap inherits from it, | ||
668 | /// so some of the member methods are marked final instead. | ||
669 | class OPENVDB_API ScaleMap: public MapBase | ||
670 | { | ||
671 | public: | ||
672 | using Ptr = SharedPtr<ScaleMap>; | ||
673 | using ConstPtr = SharedPtr<const ScaleMap>; | ||
674 | |||
675 | 5 | ScaleMap(): MapBase(), mScaleValues(Vec3d(1,1,1)), mVoxelSize(Vec3d(1,1,1)), | |
676 | mScaleValuesInverse(Vec3d(1,1,1)), | ||
677 | 13 | mInvScaleSqr(1,1,1), mInvTwiceScale(0.5,0.5,0.5){} | |
678 | |||
679 | 25898 | ScaleMap(const Vec3d& scale): | |
680 | MapBase(), | ||
681 | mScaleValues(scale), | ||
682 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 25898 times.
|
25898 | mVoxelSize(Vec3d(std::abs(scale(0)),std::abs(scale(1)), std::abs(scale(2)))) |
683 | { | ||
684 | 25898 | double determinant = scale[0]* scale[1] * scale[2]; | |
685 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 25898 times.
|
25898 | if (std::abs(determinant) < 3.0 * math::Tolerance<double>::value()) { |
686 | ✗ | OPENVDB_THROW(ArithmeticError, "Non-zero scale values required"); | |
687 | } | ||
688 | 25898 | mScaleValuesInverse = 1.0 / mScaleValues; | |
689 | 25898 | mInvScaleSqr = mScaleValuesInverse * mScaleValuesInverse; | |
690 | 25898 | mInvTwiceScale = mScaleValuesInverse / 2; | |
691 | 25898 | } | |
692 | |||
693 | 5854 | ScaleMap(const ScaleMap& other): | |
694 | MapBase(), | ||
695 | mScaleValues(other.mScaleValues), | ||
696 | mVoxelSize(other.mVoxelSize), | ||
697 | mScaleValuesInverse(other.mScaleValuesInverse), | ||
698 | mInvScaleSqr(other.mInvScaleSqr), | ||
699 | 1 | mInvTwiceScale(other.mInvTwiceScale) | |
700 | { | ||
701 | } | ||
702 | |||
703 |
2/6✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
79 | ~ScaleMap() override = default; |
704 | |||
705 | /// Return a MapBase::Ptr to a new ScaleMap | ||
706 | ✗ | static MapBase::Ptr create() { return MapBase::Ptr(new ScaleMap()); } | |
707 | /// Return a MapBase::Ptr to a deep copy of this map | ||
708 | 1 | MapBase::Ptr copy() const override { return MapBase::Ptr(new ScaleMap(*this)); } | |
709 | |||
710 | 1 | MapBase::Ptr inverseMap() const override { | |
711 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
2 | return MapBase::Ptr(new ScaleMap(mScaleValuesInverse)); |
712 | } | ||
713 | |||
714 | 3 | static bool isRegistered() { return MapRegistry::isRegistered(ScaleMap::mapType()); } | |
715 | |||
716 | 338 | static void registerMap() | |
717 | { | ||
718 | 338 | MapRegistry::registerMap( | |
719 | 338 | ScaleMap::mapType(), | |
720 | ScaleMap::create); | ||
721 | 338 | } | |
722 | |||
723 | 28 | Name type() const override { return mapType(); } | |
724 |
5/116✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 335 times.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 13 taken 6 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ 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 not taken.
✗ 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 not taken.
✗ 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.
✗ Branch 161 not taken.
✗ Branch 162 not taken.
✗ Branch 165 not taken.
✗ Branch 166 not taken.
✗ Branch 169 not taken.
✗ Branch 170 not taken.
✗ Branch 173 not taken.
✗ Branch 174 not taken.
✗ Branch 177 not taken.
✗ Branch 178 not taken.
✗ Branch 181 not taken.
✗ Branch 182 not taken.
✗ Branch 185 not taken.
✗ Branch 186 not taken.
✗ Branch 189 not taken.
✗ Branch 190 not taken.
✗ Branch 193 not taken.
✗ Branch 194 not taken.
✗ Branch 197 not taken.
✗ Branch 198 not taken.
✗ Branch 201 not taken.
✗ Branch 202 not taken.
✗ Branch 205 not taken.
✗ Branch 206 not taken.
✗ Branch 209 not taken.
✗ Branch 210 not taken.
✗ Branch 213 not taken.
✗ Branch 214 not taken.
✗ Branch 217 not taken.
✗ Branch 218 not taken.
✗ Branch 222 not taken.
✗ Branch 223 not taken.
|
359 | static Name mapType() { return Name("ScaleMap"); } |
725 | |||
726 | /// Return @c true (a ScaleMap is always linear). | ||
727 | 1050231 | bool isLinear() const OPENVDB_MAP_FUNC_SPECIFIER { return true; } | |
728 | |||
729 | /// Return @c true if the values have the same magitude (eg. -1, 1, -1 would be a rotation). | ||
730 |
2/2✓ Branch 0 taken 806 times.
✓ Branch 1 taken 2 times.
|
808 | bool hasUniformScale() const OPENVDB_MAP_FUNC_SPECIFIER |
731 | { | ||
732 | bool value = isApproxEqual( | ||
733 | std::abs(mScaleValues.x()), std::abs(mScaleValues.y()), double(5e-7)); | ||
734 |
3/4✓ Branch 0 taken 806 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 806 times.
|
808 | value = value && isApproxEqual( |
735 | std::abs(mScaleValues.x()), std::abs(mScaleValues.z()), double(5e-7)); | ||
736 | 808 | return value; | |
737 | } | ||
738 | |||
739 | /// Return the image of @c in under the map | ||
740 | 4372430807 | Vec3d applyMap(const Vec3d& in) const OPENVDB_MAP_FUNC_SPECIFIER | |
741 | { | ||
742 | return Vec3d( | ||
743 | in.x() * mScaleValues.x(), | ||
744 | in.y() * mScaleValues.y(), | ||
745 |
0/60✗ 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 not taken.
✗ 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 not taken.
✗ Branch 32 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ Branch 67 not taken.
✗ Branch 68 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 76 not taken.
✗ Branch 77 not taken.
✗ Branch 79 not taken.
✗ Branch 80 not taken.
✗ Branch 82 not taken.
✗ Branch 83 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 88 not taken.
✗ Branch 89 not taken.
|
4372636682 | in.z() * mScaleValues.z()); |
746 | } | ||
747 | /// Return the pre-image of @c in under the map | ||
748 | 4474252314 | Vec3d applyInverseMap(const Vec3d& in) const OPENVDB_MAP_FUNC_SPECIFIER | |
749 | { | ||
750 | return Vec3d( | ||
751 | in.x() * mScaleValuesInverse.x(), | ||
752 | in.y() * mScaleValuesInverse.y(), | ||
753 |
0/16✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
|
4480744178 | in.z() * mScaleValuesInverse.z()); |
754 | } | ||
755 | /// Return the Jacobian of the map applied to @a in. | ||
756 | ✗ | Vec3d applyJacobian(const Vec3d& in, const Vec3d&) const OPENVDB_MAP_FUNC_SPECIFIER { | |
757 | ✗ | return applyJacobian(in); | |
758 | } | ||
759 | /// Return the Jacobian of the map applied to @a in. | ||
760 | 205869 | Vec3d applyJacobian(const Vec3d& in) const OPENVDB_MAP_FUNC_SPECIFIER { return applyMap(in); } | |
761 | |||
762 | /// @brief Return the Inverse Jacobian of the map applied to @a in | ||
763 | /// (i.e. inverse map with out translation) | ||
764 | ✗ | Vec3d applyInverseJacobian(const Vec3d& in, const Vec3d&) const OPENVDB_MAP_FUNC_SPECIFIER { | |
765 | ✗ | return applyInverseJacobian(in); | |
766 | } | ||
767 | /// @brief Return the Inverse Jacobian of the map applied to @a in | ||
768 | /// (i.e. inverse map with out translation) | ||
769 | 1048584 | Vec3d applyInverseJacobian(const Vec3d& in) const OPENVDB_MAP_FUNC_SPECIFIER { | |
770 | 1048584 | return applyInverseMap(in); | |
771 | } | ||
772 | |||
773 | /// @brief Return the Jacobian Transpose of the map applied to @a in. | ||
774 | /// @details This tranforms range-space gradients to domain-space gradients | ||
775 | ✗ | Vec3d applyJT(const Vec3d& in, const Vec3d&) const OPENVDB_MAP_FUNC_SPECIFIER { return applyJT(in); } | |
776 | /// Return the Jacobian Transpose of the map applied to @a in. | ||
777 | ✗ | Vec3d applyJT(const Vec3d& in) const OPENVDB_MAP_FUNC_SPECIFIER { return applyMap(in); } | |
778 | |||
779 | /// @brief Return the transpose of the inverse Jacobian of the map applied to @a in. | ||
780 | /// @details Ignores second argument | ||
781 | 4 | Vec3d applyIJT(const Vec3d& in, const Vec3d&) const OPENVDB_MAP_FUNC_SPECIFIER { | |
782 | 4 | return applyIJT(in); | |
783 | } | ||
784 | /// Return the transpose of the inverse Jacobian of the map applied to @c in | ||
785 | ✗ | Vec3d applyIJT(const Vec3d& in) const OPENVDB_MAP_FUNC_SPECIFIER { return applyInverseMap(in); } | |
786 | /// Return the Jacobian Curvature: zero for a linear map | ||
787 | 6 | Mat3d applyIJC(const Mat3d& in) const OPENVDB_MAP_FUNC_SPECIFIER | |
788 | { | ||
789 | Mat3d tmp; | ||
790 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 18 times.
|
24 | for (int i = 0; i < 3; i++) { |
791 | tmp.setRow(i, in.row(i) * mScaleValuesInverse(i)); | ||
792 | } | ||
793 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 6 times.
|
24 | for (int i = 0; i < 3; i++) { |
794 | tmp.setCol(i, tmp.col(i) * mScaleValuesInverse(i)); | ||
795 | } | ||
796 | 6 | return tmp; | |
797 | } | ||
798 | 6 | Mat3d applyIJC(const Mat3d& in, const Vec3d&, const Vec3d&) const OPENVDB_MAP_FUNC_SPECIFIER { | |
799 | 6 | return applyIJC(in); | |
800 | } | ||
801 | /// Return the product of the scale values, ignores argument | ||
802 | ✗ | double determinant(const Vec3d&) const OPENVDB_MAP_FUNC_SPECIFIER { return determinant(); } | |
803 | /// Return the product of the scale values | ||
804 | 11 | double determinant() const OPENVDB_MAP_FUNC_SPECIFIER { | |
805 | 11 | return mScaleValues.x() * mScaleValues.y() * mScaleValues.z(); | |
806 | } | ||
807 | |||
808 | /// Return the scale values that define the map | ||
809 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | const Vec3d& getScale() const {return mScaleValues;} |
810 | |||
811 | /// Return the square of the scale. Used to optimize some finite difference calculations | ||
812 | const Vec3d& getInvScaleSqr() const { return mInvScaleSqr; } | ||
813 | /// Return 1/(2 scale). Used to optimize some finite difference calculations | ||
814 | const Vec3d& getInvTwiceScale() const { return mInvTwiceScale; } | ||
815 | /// Return 1/(scale) | ||
816 | const Vec3d& getInvScale() const { return mScaleValuesInverse; } | ||
817 | |||
818 | //@{ | ||
819 | /// @brief Return the lengths of the images of the segments | ||
820 | /// (0,0,0) − 1,0,0), (0,0,0) − (0,1,0) and (0,0,0) − (0,0,1). | ||
821 | /// @details This is equivalent to the absolute values of the scale values | ||
822 | 396662 | Vec3d voxelSize() const OPENVDB_MAP_FUNC_SPECIFIER { return mVoxelSize; } | |
823 | 62 | Vec3d voxelSize(const Vec3d&) const OPENVDB_MAP_FUNC_SPECIFIER { return voxelSize(); } | |
824 | //@} | ||
825 | |||
826 | /// read serialization | ||
827 | 135 | void read(std::istream& is) override | |
828 | { | ||
829 | mScaleValues.read(is); | ||
830 | mVoxelSize.read(is); | ||
831 | mScaleValuesInverse.read(is); | ||
832 | mInvScaleSqr.read(is); | ||
833 | mInvTwiceScale.read(is); | ||
834 | 135 | } | |
835 | /// write serialization | ||
836 | 164 | void write(std::ostream& os) const override | |
837 | { | ||
838 | mScaleValues.write(os); | ||
839 | mVoxelSize.write(os); | ||
840 | mScaleValuesInverse.write(os); | ||
841 | mInvScaleSqr.write(os); | ||
842 | mInvTwiceScale.write(os); | ||
843 | 164 | } | |
844 | /// string serialization, useful for debuging | ||
845 | ✗ | std::string str() const override | |
846 | { | ||
847 | ✗ | std::ostringstream buffer; | |
848 | ✗ | buffer << " - scale: " << mScaleValues << std::endl; | |
849 | ✗ | buffer << " - voxel dimensions: " << mVoxelSize << std::endl; | |
850 | ✗ | return buffer.str(); | |
851 | } | ||
852 | |||
853 | 1 | bool isEqual(const MapBase& other) const override { return isEqualBase(*this, other); } | |
854 | |||
855 | bool operator==(const ScaleMap& other) const | ||
856 | { | ||
857 | // ::eq() uses a tolerance | ||
858 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 6236 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
|
6237 | if (!mScaleValues.eq(other.mScaleValues)) { return false; } |
859 | return true; | ||
860 | } | ||
861 | |||
862 | bool operator!=(const ScaleMap& other) const { return !(*this == other); } | ||
863 | |||
864 | /// Return a AffineMap equivalent to this map | ||
865 | 46 | AffineMap::Ptr getAffineMap() const override | |
866 | { | ||
867 |
1/2✓ Branch 3 taken 46 times.
✗ Branch 4 not taken.
|
92 | return AffineMap::Ptr(new AffineMap(math::scale<Mat4d>(mScaleValues))); |
868 | } | ||
869 | |||
870 | |||
871 | |||
872 | //@{ | ||
873 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
874 | /// of prepending the appropraite operation to the existing map | ||
875 | 16 | MapBase::Ptr preRotate(double radians, Axis axis) const override | |
876 | { | ||
877 | 16 | AffineMap::Ptr affineMap = getAffineMap(); | |
878 | affineMap->accumPreRotation(axis, radians); | ||
879 |
2/6✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 16 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
48 | return simplify(affineMap); |
880 | } | ||
881 | |||
882 | MapBase::Ptr preTranslate(const Vec3d&) const override; | ||
883 | MapBase::Ptr preScale(const Vec3d&) const override; | ||
884 | 2 | MapBase::Ptr preShear(double shear, Axis axis0, Axis axis1) const override | |
885 | { | ||
886 | 2 | AffineMap::Ptr affineMap = getAffineMap(); | |
887 | affineMap->accumPreShear(axis0, axis1, shear); | ||
888 |
2/6✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
6 | return simplify(affineMap); |
889 | } | ||
890 | //@} | ||
891 | |||
892 | |||
893 | //@{ | ||
894 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
895 | /// of prepending the appropraite operation to the existing map. | ||
896 | 4 | MapBase::Ptr postRotate(double radians, Axis axis) const override | |
897 | { | ||
898 | 4 | AffineMap::Ptr affineMap = getAffineMap(); | |
899 | affineMap->accumPostRotation(axis, radians); | ||
900 |
2/6✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
12 | return simplify(affineMap); |
901 | } | ||
902 | MapBase::Ptr postTranslate(const Vec3d&) const override; | ||
903 | MapBase::Ptr postScale(const Vec3d&) const override; | ||
904 | 2 | MapBase::Ptr postShear(double shear, Axis axis0, Axis axis1) const override | |
905 | { | ||
906 | 2 | AffineMap::Ptr affineMap = getAffineMap(); | |
907 | affineMap->accumPostShear(axis0, axis1, shear); | ||
908 |
2/6✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
6 | return simplify(affineMap); |
909 | } | ||
910 | //@} | ||
911 | |||
912 | private: | ||
913 | Vec3d mScaleValues, mVoxelSize, mScaleValuesInverse, mInvScaleSqr, mInvTwiceScale; | ||
914 | }; // class ScaleMap | ||
915 | |||
916 | |||
917 | /// @brief A specialized Affine transform that scales along the principal axis | ||
918 | /// the scaling is uniform in the three-directions | ||
919 | /// @note This class is marked final with ABI=8 | ||
920 | class OPENVDB_API UniformScaleMap OPENVDB_MAP_CLASS_SPECIFIER: public ScaleMap | ||
921 | { | ||
922 | public: | ||
923 | using Ptr = SharedPtr<UniformScaleMap>; | ||
924 | using ConstPtr = SharedPtr<const UniformScaleMap>; | ||
925 | |||
926 |
13/21✓ Branch 1 taken 138 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 1 times.
✓ Branch 19 taken 1 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 23 not taken.
|
154 | UniformScaleMap(): ScaleMap(Vec3d(1,1,1)) {} |
927 |
12/26✓ Branch 1 taken 25700 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 2 times.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
|
25707 | UniformScaleMap(double scale): ScaleMap(Vec3d(scale, scale, scale)) {} |
928 |
3/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
|
5842 | UniformScaleMap(const UniformScaleMap& other): ScaleMap(other) {} |
929 |
6/14✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
|
31683 | ~UniformScaleMap() override = default; |
930 | |||
931 | /// Return a MapBase::Ptr to a new UniformScaleMap | ||
932 | 270 | static MapBase::Ptr create() { return MapBase::Ptr(new UniformScaleMap()); } | |
933 | /// Return a MapBase::Ptr to a deep copy of this map | ||
934 | 5840 | MapBase::Ptr copy() const override { return MapBase::Ptr(new UniformScaleMap(*this)); } | |
935 | |||
936 | ✗ | MapBase::Ptr inverseMap() const override | |
937 | { | ||
938 | const Vec3d& invScale = getInvScale(); | ||
939 | ✗ | return MapBase::Ptr(new UniformScaleMap( invScale[0])); | |
940 | } | ||
941 | |||
942 | 1 | static bool isRegistered() { return MapRegistry::isRegistered(UniformScaleMap::mapType()); } | |
943 | 337 | static void registerMap() | |
944 | { | ||
945 | 337 | MapRegistry::registerMap( | |
946 | 337 | UniformScaleMap::mapType(), | |
947 | UniformScaleMap::create); | ||
948 | 337 | } | |
949 | |||
950 | 101120 | Name type() const override { return mapType(); } | |
951 |
27/146✓ Branch 2 taken 59629 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 32 times.
✓ Branch 7 taken 333 times.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✓ Branch 25 taken 6 times.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✓ Branch 37 taken 2 times.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✓ Branch 49 taken 2 times.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✓ Branch 57 taken 1 times.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 65 not taken.
✗ Branch 66 not taken.
✗ Branch 67 not taken.
✗ Branch 69 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✓ Branch 73 taken 1 times.
✗ Branch 74 not taken.
✗ Branch 75 not taken.
✗ Branch 77 not taken.
✗ Branch 78 not taken.
✗ Branch 79 not taken.
✗ Branch 81 not taken.
✗ Branch 82 not taken.
✗ Branch 83 not taken.
✓ Branch 85 taken 1 times.
✗ Branch 86 not taken.
✗ Branch 87 not taken.
✓ Branch 89 taken 2 times.
✗ Branch 90 not taken.
✗ Branch 91 not taken.
✗ Branch 93 not taken.
✗ Branch 94 not taken.
✗ Branch 95 not taken.
✗ Branch 97 not taken.
✗ Branch 98 not taken.
✗ Branch 99 not taken.
✗ Branch 101 not taken.
✗ Branch 102 not taken.
✗ Branch 103 not taken.
✓ Branch 105 taken 1 times.
✗ Branch 106 not taken.
✗ Branch 107 not taken.
✗ Branch 109 not taken.
✗ Branch 110 not taken.
✗ Branch 111 not taken.
✗ Branch 113 not taken.
✗ Branch 114 not taken.
✗ Branch 115 not taken.
✗ Branch 117 not taken.
✗ Branch 118 not taken.
✗ Branch 119 not taken.
✓ Branch 121 taken 1 times.
✗ Branch 122 not taken.
✗ Branch 123 not taken.
✓ Branch 125 taken 4 times.
✗ Branch 126 not taken.
✗ Branch 127 not taken.
✓ Branch 129 taken 12 times.
✗ 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 taken 2 times.
✗ Branch 150 not taken.
✗ Branch 153 not taken.
✗ Branch 154 not taken.
✗ Branch 157 not taken.
✗ Branch 158 not taken.
✗ Branch 161 not taken.
✗ Branch 162 not taken.
✗ Branch 165 not taken.
✗ Branch 166 not taken.
✗ Branch 169 not taken.
✗ Branch 170 not taken.
✓ Branch 173 taken 1 times.
✗ Branch 174 not taken.
✓ Branch 177 taken 1 times.
✗ Branch 178 not taken.
✗ Branch 181 not taken.
✗ Branch 182 not taken.
✗ Branch 185 not taken.
✗ Branch 186 not taken.
✓ Branch 189 taken 1 times.
✗ Branch 190 not taken.
✗ Branch 193 not taken.
✗ Branch 194 not taken.
✗ Branch 197 not taken.
✗ Branch 198 not taken.
✓ Branch 201 taken 5 times.
✗ Branch 202 not taken.
✗ Branch 205 not taken.
✗ Branch 206 not taken.
✗ Branch 209 not taken.
✗ Branch 210 not taken.
✗ Branch 213 not taken.
✗ Branch 214 not taken.
✗ Branch 217 not taken.
✗ Branch 218 not taken.
✗ Branch 222 not taken.
✗ Branch 223 not taken.
|
110603 | static Name mapType() { return Name("UniformScaleMap"); } |
952 | |||
953 | 6236 | bool isEqual(const MapBase& other) const override { return isEqualBase(*this, other); } | |
954 | |||
955 | bool operator==(const UniformScaleMap& other) const { return ScaleMap::operator==(other); } | ||
956 | bool operator!=(const UniformScaleMap& other) const { return !(*this == other); } | ||
957 | |||
958 | /// @brief Return a MapBase::Ptr to a UniformScaleTraslateMap that is the result of | ||
959 | /// pre-translation on this map | ||
960 | MapBase::Ptr preTranslate(const Vec3d&) const override; | ||
961 | |||
962 | /// @brief Return a MapBase::Ptr to a UniformScaleTraslateMap that is the result of | ||
963 | /// post-translation on this map | ||
964 | MapBase::Ptr postTranslate(const Vec3d&) const override; | ||
965 | |||
966 | }; // class UniformScaleMap | ||
967 | |||
968 | |||
969 | //////////////////////////////////////// | ||
970 | |||
971 | |||
972 | inline MapBase::Ptr | ||
973 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 8 times.
|
19 | ScaleMap::preScale(const Vec3d& v) const |
974 | { | ||
975 | const Vec3d new_scale(v * mScaleValues); | ||
976 |
4/4✓ Branch 0 taken 11 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 1 times.
|
19 | if (isApproxEqual(new_scale[0],new_scale[1]) && isApproxEqual(new_scale[0],new_scale[2])) { |
977 | 10 | return MapBase::Ptr(new UniformScaleMap(new_scale[0])); | |
978 | } else { | ||
979 |
1/2✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
|
9 | return MapBase::Ptr(new ScaleMap(new_scale)); |
980 | } | ||
981 | } | ||
982 | |||
983 | |||
984 | inline MapBase::Ptr | ||
985 | 1 | ScaleMap::postScale(const Vec3d& v) const | |
986 | { // pre-post Scale are the same for a scale map | ||
987 | 3 | return preScale(v); | |
988 | } | ||
989 | |||
990 | |||
991 | /// @brief A specialized linear transform that performs a translation | ||
992 | /// @note This class is marked final with ABI=8 | ||
993 | class OPENVDB_API TranslationMap OPENVDB_MAP_CLASS_SPECIFIER: public MapBase | ||
994 | { | ||
995 | public: | ||
996 | using Ptr = SharedPtr<TranslationMap>; | ||
997 | using ConstPtr = SharedPtr<const TranslationMap>; | ||
998 | |||
999 | // default constructor is a translation by zero. | ||
1000 |
3/5✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
|
6 | TranslationMap(): MapBase(), mTranslation(Vec3d(0,0,0)) {} |
1001 |
7/14✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 1 times.
✓ Branch 19 taken 1 times.
✗ Branch 20 not taken.
|
10 | TranslationMap(const Vec3d& t): MapBase(), mTranslation(t) {} |
1002 | ✗ | TranslationMap(const TranslationMap& other): MapBase(), mTranslation(other.mTranslation) {} | |
1003 | |||
1004 |
4/12✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
|
12 | ~TranslationMap() override = default; |
1005 | |||
1006 | /// Return a MapBase::Ptr to a new TranslationMap | ||
1007 | ✗ | static MapBase::Ptr create() { return MapBase::Ptr(new TranslationMap()); } | |
1008 | /// Return a MapBase::Ptr to a deep copy of this map | ||
1009 | ✗ | MapBase::Ptr copy() const override { return MapBase::Ptr(new TranslationMap(*this)); } | |
1010 | |||
1011 | 1 | MapBase::Ptr inverseMap() const override { | |
1012 | 1 | return MapBase::Ptr(new TranslationMap(-mTranslation)); | |
1013 | } | ||
1014 | |||
1015 | 3 | static bool isRegistered() { return MapRegistry::isRegistered(TranslationMap::mapType()); } | |
1016 | |||
1017 | 338 | static void registerMap() | |
1018 | { | ||
1019 | 338 | MapRegistry::registerMap( | |
1020 | 338 | TranslationMap::mapType(), | |
1021 | TranslationMap::create); | ||
1022 | 338 | } | |
1023 | |||
1024 | 2 | Name type() const override { return mapType(); } | |
1025 |
3/144✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 341 times.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 65 not taken.
✗ Branch 66 not taken.
✗ Branch 67 not taken.
✗ Branch 69 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 75 not taken.
✗ Branch 77 not taken.
✗ Branch 78 not taken.
✗ Branch 79 not taken.
✗ Branch 81 not taken.
✗ Branch 82 not taken.
✗ Branch 83 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 87 not taken.
✗ Branch 89 not taken.
✗ Branch 90 not taken.
✗ Branch 91 not taken.
✗ Branch 93 not taken.
✗ Branch 94 not taken.
✗ Branch 95 not taken.
✗ Branch 97 not taken.
✗ Branch 98 not taken.
✗ Branch 99 not taken.
✗ Branch 101 not taken.
✗ Branch 102 not taken.
✗ Branch 103 not taken.
✗ Branch 105 not taken.
✗ Branch 106 not taken.
✗ Branch 107 not taken.
✗ Branch 109 not taken.
✗ Branch 110 not taken.
✗ Branch 111 not taken.
✗ Branch 113 not taken.
✗ Branch 114 not taken.
✗ Branch 115 not taken.
✗ Branch 117 not taken.
✗ Branch 118 not taken.
✗ Branch 119 not taken.
✗ Branch 121 not taken.
✗ Branch 122 not taken.
✗ Branch 123 not taken.
✗ Branch 125 not taken.
✗ Branch 126 not taken.
✗ Branch 127 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.
✗ Branch 161 not taken.
✗ Branch 162 not taken.
✗ Branch 165 not taken.
✗ Branch 166 not taken.
✗ Branch 169 not taken.
✗ Branch 170 not taken.
✗ Branch 173 not taken.
✗ Branch 174 not taken.
✗ Branch 177 not taken.
✗ Branch 178 not taken.
✗ Branch 181 not taken.
✗ Branch 182 not taken.
✗ Branch 185 not taken.
✗ Branch 186 not taken.
✗ Branch 189 not taken.
✗ Branch 190 not taken.
✗ Branch 193 not taken.
✗ Branch 194 not taken.
✗ Branch 197 not taken.
✗ Branch 198 not taken.
✗ Branch 201 not taken.
✗ Branch 202 not taken.
✗ Branch 205 not taken.
✗ Branch 206 not taken.
✗ Branch 209 not taken.
✗ Branch 210 not taken.
✗ Branch 213 not taken.
✗ Branch 214 not taken.
✗ Branch 217 not taken.
✗ Branch 218 not taken.
✗ Branch 222 not taken.
✗ Branch 223 not taken.
|
343 | static Name mapType() { return Name("TranslationMap"); } |
1026 | |||
1027 | /// Return @c true (a TranslationMap is always linear). | ||
1028 | ✗ | bool isLinear() const override { return true; } | |
1029 | |||
1030 | /// Return @c false (by convention true) | ||
1031 | ✗ | bool hasUniformScale() const override { return true; } | |
1032 | |||
1033 | /// Return the image of @c in under the map | ||
1034 | 1 | Vec3d applyMap(const Vec3d& in) const override { return in + mTranslation; } | |
1035 | /// Return the pre-image of @c in under the map | ||
1036 | ✗ | Vec3d applyInverseMap(const Vec3d& in) const override { return in - mTranslation; } | |
1037 | /// Return the Jacobian of the map applied to @a in. | ||
1038 | ✗ | Vec3d applyJacobian(const Vec3d& in, const Vec3d&) const override { return applyJacobian(in); } | |
1039 | /// Return the Jacobian of the map applied to @a in. | ||
1040 | ✗ | Vec3d applyJacobian(const Vec3d& in) const override { return in; } | |
1041 | |||
1042 | /// @brief Return the Inverse Jacobian of the map applied to @a in | ||
1043 | /// (i.e. inverse map with out translation) | ||
1044 | ✗ | Vec3d applyInverseJacobian(const Vec3d& in, const Vec3d&) const override { | |
1045 | ✗ | return applyInverseJacobian(in); | |
1046 | } | ||
1047 | /// @brief Return the Inverse Jacobian of the map applied to @a in | ||
1048 | /// (i.e. inverse map with out translation) | ||
1049 | ✗ | Vec3d applyInverseJacobian(const Vec3d& in) const override { return in; } | |
1050 | |||
1051 | |||
1052 | /// @brief Return the Jacobian Transpose of the map applied to @a in. | ||
1053 | /// @details This tranforms range-space gradients to domain-space gradients | ||
1054 | ✗ | Vec3d applyJT(const Vec3d& in, const Vec3d&) const override { return applyJT(in); } | |
1055 | /// Return the Jacobian Transpose of the map applied to @a in. | ||
1056 | 1 | Vec3d applyJT(const Vec3d& in) const override { return in; } | |
1057 | |||
1058 | /// @brief Return the transpose of the inverse Jacobian (Identity for TranslationMap) | ||
1059 | /// of the map applied to @c in, ignores second argument | ||
1060 | ✗ | Vec3d applyIJT(const Vec3d& in, const Vec3d& ) const override { return applyIJT(in);} | |
1061 | /// @brief Return the transpose of the inverse Jacobian (Identity for TranslationMap) | ||
1062 | /// of the map applied to @c in | ||
1063 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | Vec3d applyIJT(const Vec3d& in) const override {return in;} |
1064 | /// Return the Jacobian Curvature: zero for a linear map | ||
1065 | ✗ | Mat3d applyIJC(const Mat3d& mat) const override {return mat;} | |
1066 | ✗ | Mat3d applyIJC(const Mat3d& mat, const Vec3d&, const Vec3d&) const override { | |
1067 | ✗ | return applyIJC(mat); | |
1068 | } | ||
1069 | |||
1070 | /// Return @c 1 | ||
1071 | ✗ | double determinant(const Vec3d& ) const override { return determinant(); } | |
1072 | /// Return @c 1 | ||
1073 | ✗ | double determinant() const override { return 1.0; } | |
1074 | |||
1075 | /// Return (1,1,1). | ||
1076 | ✗ | Vec3d voxelSize() const override { return Vec3d(1,1,1);} | |
1077 | /// Return (1,1,1). | ||
1078 | ✗ | Vec3d voxelSize(const Vec3d&) const override { return voxelSize();} | |
1079 | |||
1080 | /// Return the translation vector | ||
1081 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | const Vec3d& getTranslation() const { return mTranslation; } |
1082 | |||
1083 | /// read serialization | ||
1084 | ✗ | void read(std::istream& is) override { mTranslation.read(is); } | |
1085 | /// write serialization | ||
1086 | ✗ | void write(std::ostream& os) const override { mTranslation.write(os); } | |
1087 | /// string serialization, useful for debuging | ||
1088 | ✗ | std::string str() const override | |
1089 | { | ||
1090 | ✗ | std::ostringstream buffer; | |
1091 | ✗ | buffer << " - translation: " << mTranslation << std::endl; | |
1092 | ✗ | return buffer.str(); | |
1093 | } | ||
1094 | |||
1095 | ✗ | bool isEqual(const MapBase& other) const override { return isEqualBase(*this, other); } | |
1096 | |||
1097 | bool operator==(const TranslationMap& other) const | ||
1098 | { | ||
1099 | // ::eq() uses a tolerance | ||
1100 |
1/4✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
|
1 | return mTranslation.eq(other.mTranslation); |
1101 | } | ||
1102 | |||
1103 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | bool operator!=(const TranslationMap& other) const { return !(*this == other); } |
1104 | |||
1105 | /// Return AffineMap::Ptr to an AffineMap equivalent to *this | ||
1106 | 1 | AffineMap::Ptr getAffineMap() const override | |
1107 | { | ||
1108 | 1 | Mat4d matrix(Mat4d::identity()); | |
1109 | matrix.setTranslation(mTranslation); | ||
1110 | |||
1111 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | AffineMap::Ptr affineMap(new AffineMap(matrix)); |
1112 | 1 | return affineMap; | |
1113 | } | ||
1114 | |||
1115 | //@{ | ||
1116 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
1117 | /// of prepending the appropriate operation. | ||
1118 | ✗ | MapBase::Ptr preRotate(double radians, Axis axis) const override | |
1119 | { | ||
1120 | ✗ | AffineMap::Ptr affineMap = getAffineMap(); | |
1121 | affineMap->accumPreRotation(axis, radians); | ||
1122 | ✗ | return simplify(affineMap); | |
1123 | |||
1124 | } | ||
1125 | ✗ | MapBase::Ptr preTranslate(const Vec3d& t) const override | |
1126 | { | ||
1127 | ✗ | return MapBase::Ptr(new TranslationMap(t + mTranslation)); | |
1128 | } | ||
1129 | |||
1130 | MapBase::Ptr preScale(const Vec3d& v) const override; | ||
1131 | |||
1132 | ✗ | MapBase::Ptr preShear(double shear, Axis axis0, Axis axis1) const override | |
1133 | { | ||
1134 | ✗ | AffineMap::Ptr affineMap = getAffineMap(); | |
1135 | affineMap->accumPreShear(axis0, axis1, shear); | ||
1136 | ✗ | return simplify(affineMap); | |
1137 | } | ||
1138 | //@} | ||
1139 | |||
1140 | //@{ | ||
1141 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
1142 | /// of postfixing the appropriate operation. | ||
1143 | ✗ | MapBase::Ptr postRotate(double radians, Axis axis) const override | |
1144 | { | ||
1145 | ✗ | AffineMap::Ptr affineMap = getAffineMap(); | |
1146 | affineMap->accumPostRotation(axis, radians); | ||
1147 | ✗ | return simplify(affineMap); | |
1148 | |||
1149 | } | ||
1150 | ✗ | MapBase::Ptr postTranslate(const Vec3d& t) const override | |
1151 | { // post and pre are the same for this | ||
1152 | ✗ | return MapBase::Ptr(new TranslationMap(t + mTranslation)); | |
1153 | } | ||
1154 | |||
1155 | MapBase::Ptr postScale(const Vec3d& v) const override; | ||
1156 | |||
1157 | ✗ | MapBase::Ptr postShear(double shear, Axis axis0, Axis axis1) const override | |
1158 | { | ||
1159 | ✗ | AffineMap::Ptr affineMap = getAffineMap(); | |
1160 | affineMap->accumPostShear(axis0, axis1, shear); | ||
1161 | ✗ | return simplify(affineMap); | |
1162 | } | ||
1163 | //@} | ||
1164 | |||
1165 | private: | ||
1166 | Vec3d mTranslation; | ||
1167 | }; // class TranslationMap | ||
1168 | |||
1169 | |||
1170 | //////////////////////////////////////// | ||
1171 | |||
1172 | |||
1173 | /// @brief A specialized Affine transform that scales along the principal axis | ||
1174 | /// the scaling need not be uniform in the three-directions, and then | ||
1175 | /// translates the result. | ||
1176 | /// @note This class is not marked final because UniformScaleMap inherits from it, | ||
1177 | /// so some of the member methods are marked final instead. | ||
1178 | class OPENVDB_API ScaleTranslateMap: public MapBase | ||
1179 | { | ||
1180 | public: | ||
1181 | using Ptr = SharedPtr<ScaleTranslateMap>; | ||
1182 | using ConstPtr = SharedPtr<const ScaleTranslateMap>; | ||
1183 | |||
1184 | 1 | ScaleTranslateMap(): | |
1185 | MapBase(), | ||
1186 | mTranslation(Vec3d(0,0,0)), | ||
1187 | mScaleValues(Vec3d(1,1,1)), | ||
1188 | mVoxelSize(Vec3d(1,1,1)), | ||
1189 | mScaleValuesInverse(Vec3d(1,1,1)), | ||
1190 | mInvScaleSqr(1,1,1), | ||
1191 | 9 | mInvTwiceScale(0.5,0.5,0.5) | |
1192 | { | ||
1193 | } | ||
1194 | |||
1195 | 49 | ScaleTranslateMap(const Vec3d& scale, const Vec3d& translate): | |
1196 | MapBase(), | ||
1197 | mTranslation(translate), | ||
1198 | mScaleValues(scale), | ||
1199 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 49 times.
|
49 | mVoxelSize(std::abs(scale(0)), std::abs(scale(1)), std::abs(scale(2))) |
1200 | { | ||
1201 | 49 | const double determinant = scale[0]* scale[1] * scale[2]; | |
1202 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 49 times.
|
49 | if (std::abs(determinant) < 3.0 * math::Tolerance<double>::value()) { |
1203 | ✗ | OPENVDB_THROW(ArithmeticError, "Non-zero scale values required"); | |
1204 | } | ||
1205 | 49 | mScaleValuesInverse = 1.0 / mScaleValues; | |
1206 | 49 | mInvScaleSqr = mScaleValuesInverse * mScaleValuesInverse; | |
1207 | 49 | mInvTwiceScale = mScaleValuesInverse / 2; | |
1208 | 49 | } | |
1209 | |||
1210 | 2 | ScaleTranslateMap(const ScaleMap& scale, const TranslationMap& translate): | |
1211 | MapBase(), | ||
1212 | mTranslation(translate.getTranslation()), | ||
1213 | mScaleValues(scale.getScale()), | ||
1214 | mVoxelSize(std::abs(mScaleValues(0)), | ||
1215 | std::abs(mScaleValues(1)), | ||
1216 | std::abs(mScaleValues(2))), | ||
1217 | 2 | mScaleValuesInverse(1.0 / scale.getScale()) | |
1218 | { | ||
1219 | 2 | mInvScaleSqr = mScaleValuesInverse * mScaleValuesInverse; | |
1220 | 2 | mInvTwiceScale = mScaleValuesInverse / 2; | |
1221 | 2 | } | |
1222 | |||
1223 | 1 | ScaleTranslateMap(const ScaleTranslateMap& other): | |
1224 | MapBase(), | ||
1225 | mTranslation(other.mTranslation), | ||
1226 | mScaleValues(other.mScaleValues), | ||
1227 | mVoxelSize(other.mVoxelSize), | ||
1228 | mScaleValuesInverse(other.mScaleValuesInverse), | ||
1229 | mInvScaleSqr(other.mInvScaleSqr), | ||
1230 | ✗ | mInvTwiceScale(other.mInvTwiceScale) | |
1231 | {} | ||
1232 | |||
1233 |
1/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
37 | ~ScaleTranslateMap() override = default; |
1234 | |||
1235 | /// Return a MapBase::Ptr to a new ScaleTranslateMap | ||
1236 | 1 | static MapBase::Ptr create() { return MapBase::Ptr(new ScaleTranslateMap()); } | |
1237 | /// Return a MapBase::Ptr to a deep copy of this map | ||
1238 | ✗ | MapBase::Ptr copy() const override { return MapBase::Ptr(new ScaleTranslateMap(*this)); } | |
1239 | |||
1240 | 1 | MapBase::Ptr inverseMap() const override | |
1241 | { | ||
1242 | return MapBase::Ptr(new ScaleTranslateMap( | ||
1243 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
2 | mScaleValuesInverse, -mScaleValuesInverse * mTranslation)); |
1244 | } | ||
1245 | |||
1246 | 3 | static bool isRegistered() { return MapRegistry::isRegistered(ScaleTranslateMap::mapType()); } | |
1247 | |||
1248 | 338 | static void registerMap() | |
1249 | { | ||
1250 | 338 | MapRegistry::registerMap( | |
1251 | 338 | ScaleTranslateMap::mapType(), | |
1252 | ScaleTranslateMap::create); | ||
1253 | 338 | } | |
1254 | |||
1255 | 8 | Name type() const override { return mapType(); } | |
1256 |
6/119✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 335 times.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✓ Branch 19 taken 6 times.
✗ Branch 20 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 not taken.
✗ 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 not taken.
✗ 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.
✗ Branch 161 not taken.
✗ Branch 162 not taken.
✗ Branch 165 not taken.
✗ Branch 166 not taken.
✗ Branch 169 not taken.
✗ Branch 170 not taken.
✗ Branch 173 not taken.
✗ Branch 174 not taken.
✗ Branch 177 not taken.
✗ Branch 178 not taken.
✗ Branch 181 not taken.
✗ Branch 182 not taken.
✗ Branch 185 not taken.
✗ Branch 186 not taken.
✗ Branch 189 not taken.
✗ Branch 190 not taken.
✗ Branch 193 not taken.
✗ Branch 194 not taken.
✗ Branch 197 not taken.
✗ Branch 198 not taken.
✗ Branch 201 not taken.
✗ Branch 202 not taken.
✗ Branch 205 not taken.
✗ Branch 206 not taken.
✗ Branch 209 not taken.
✗ Branch 210 not taken.
✗ Branch 213 not taken.
✗ Branch 214 not taken.
✗ Branch 217 not taken.
✗ Branch 218 not taken.
✗ Branch 222 not taken.
✗ Branch 223 not taken.
|
348 | static Name mapType() { return Name("ScaleTranslateMap"); } |
1257 | |||
1258 | /// Return @c true (a ScaleTranslateMap is always linear). | ||
1259 | 8 | bool isLinear() const OPENVDB_MAP_FUNC_SPECIFIER { return true; } | |
1260 | |||
1261 | /// @brief Return @c true if the scale values have the same magnitude | ||
1262 | /// (eg. -1, 1, -1 would be a rotation). | ||
1263 | ✗ | bool hasUniformScale() const OPENVDB_MAP_FUNC_SPECIFIER | |
1264 | { | ||
1265 | bool value = isApproxEqual( | ||
1266 | std::abs(mScaleValues.x()), std::abs(mScaleValues.y()), double(5e-7)); | ||
1267 |
3/12✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
2 | value = value && isApproxEqual( |
1268 | std::abs(mScaleValues.x()), std::abs(mScaleValues.z()), double(5e-7)); | ||
1269 | ✗ | return value; | |
1270 | } | ||
1271 | |||
1272 | /// Return the image of @c under the map | ||
1273 | 9051559 | Vec3d applyMap(const Vec3d& in) const OPENVDB_MAP_FUNC_SPECIFIER | |
1274 | { | ||
1275 | return Vec3d( | ||
1276 |
0/60✗ 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 not taken.
✗ 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 not taken.
✗ Branch 32 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ Branch 67 not taken.
✗ Branch 68 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 76 not taken.
✗ Branch 77 not taken.
✗ Branch 79 not taken.
✗ Branch 80 not taken.
✗ Branch 82 not taken.
✗ Branch 83 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 88 not taken.
✗ Branch 89 not taken.
|
9051560 | in.x() * mScaleValues.x() + mTranslation.x(), |
1277 |
4/64✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ 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 not taken.
✗ Branch 32 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ Branch 67 not taken.
✗ Branch 68 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 76 not taken.
✗ Branch 77 not taken.
✗ Branch 79 not taken.
✗ Branch 80 not taken.
✗ Branch 82 not taken.
✗ Branch 83 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 88 not taken.
✗ Branch 89 not taken.
|
9051564 | in.y() * mScaleValues.y() + mTranslation.y(), |
1278 |
4/64✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ 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 not taken.
✗ Branch 32 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ Branch 67 not taken.
✗ Branch 68 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 76 not taken.
✗ Branch 77 not taken.
✗ Branch 79 not taken.
✗ Branch 80 not taken.
✗ Branch 82 not taken.
✗ Branch 83 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 88 not taken.
✗ Branch 89 not taken.
|
9051564 | in.z() * mScaleValues.z() + mTranslation.z()); |
1279 | } | ||
1280 | /// Return the pre-image of @c under the map | ||
1281 | 22 | Vec3d applyInverseMap(const Vec3d& in) const OPENVDB_MAP_FUNC_SPECIFIER | |
1282 | { | ||
1283 | return Vec3d( | ||
1284 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
24 | (in.x() - mTranslation.x() ) * mScaleValuesInverse.x(), |
1285 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
24 | (in.y() - mTranslation.y() ) * mScaleValuesInverse.y(), |
1286 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
24 | (in.z() - mTranslation.z() ) * mScaleValuesInverse.z()); |
1287 | } | ||
1288 | |||
1289 | /// Return the Jacobian of the map applied to @a in. | ||
1290 | ✗ | Vec3d applyJacobian(const Vec3d& in, const Vec3d&) const OPENVDB_MAP_FUNC_SPECIFIER { | |
1291 | ✗ | return applyJacobian(in); | |
1292 | } | ||
1293 | /// Return the Jacobian of the map applied to @a in. | ||
1294 | 2 | Vec3d applyJacobian(const Vec3d& in) const OPENVDB_MAP_FUNC_SPECIFIER { return in * mScaleValues; } | |
1295 | |||
1296 | /// @brief Return the Inverse Jacobian of the map applied to @a in | ||
1297 | /// (i.e. inverse map with out translation) | ||
1298 | ✗ | Vec3d applyInverseJacobian(const Vec3d& in, const Vec3d&) const OPENVDB_MAP_FUNC_SPECIFIER { | |
1299 | ✗ | return applyInverseJacobian(in); | |
1300 | } | ||
1301 | /// @brief Return the Inverse Jacobian of the map applied to @a in | ||
1302 | /// (i.e. inverse map with out translation) | ||
1303 | 2 | Vec3d applyInverseJacobian(const Vec3d& in) const OPENVDB_MAP_FUNC_SPECIFIER { | |
1304 | 2 | return in * mScaleValuesInverse; | |
1305 | } | ||
1306 | |||
1307 | /// @brief Return the Jacobian Transpose of the map applied to @a in. | ||
1308 | /// @details This tranforms range-space gradients to domain-space gradients | ||
1309 | ✗ | Vec3d applyJT(const Vec3d& in, const Vec3d&) const OPENVDB_MAP_FUNC_SPECIFIER { return applyJT(in); } | |
1310 | /// Return the Jacobian Transpose of the map applied to @a in. | ||
1311 | ✗ | Vec3d applyJT(const Vec3d& in) const OPENVDB_MAP_FUNC_SPECIFIER { return applyJacobian(in); } | |
1312 | |||
1313 | /// @brief Return the transpose of the inverse Jacobian of the map applied to @a in | ||
1314 | /// @details Ignores second argument | ||
1315 | ✗ | Vec3d applyIJT(const Vec3d& in, const Vec3d&) const OPENVDB_MAP_FUNC_SPECIFIER { | |
1316 | ✗ | return applyIJT(in); | |
1317 | } | ||
1318 | /// Return the transpose of the inverse Jacobian of the map applied to @c in | ||
1319 | ✗ | Vec3d applyIJT(const Vec3d& in) const OPENVDB_MAP_FUNC_SPECIFIER | |
1320 | { | ||
1321 | return Vec3d( | ||
1322 | in.x() * mScaleValuesInverse.x(), | ||
1323 | in.y() * mScaleValuesInverse.y(), | ||
1324 |
4/16✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
|
4 | in.z() * mScaleValuesInverse.z()); |
1325 | } | ||
1326 | /// Return the Jacobian Curvature: zero for a linear map | ||
1327 | ✗ | Mat3d applyIJC(const Mat3d& in) const OPENVDB_MAP_FUNC_SPECIFIER | |
1328 | { | ||
1329 | Mat3d tmp; | ||
1330 | ✗ | for (int i=0; i<3; i++){ | |
1331 | tmp.setRow(i, in.row(i)*mScaleValuesInverse(i)); | ||
1332 | } | ||
1333 | ✗ | for (int i=0; i<3; i++){ | |
1334 | tmp.setCol(i, tmp.col(i)*mScaleValuesInverse(i)); | ||
1335 | } | ||
1336 | ✗ | return tmp; | |
1337 | } | ||
1338 | ✗ | Mat3d applyIJC(const Mat3d& in, const Vec3d&, const Vec3d& ) const OPENVDB_MAP_FUNC_SPECIFIER { | |
1339 | ✗ | return applyIJC(in); | |
1340 | } | ||
1341 | |||
1342 | /// Return the product of the scale values, ignores argument | ||
1343 | ✗ | double determinant(const Vec3d&) const OPENVDB_MAP_FUNC_SPECIFIER { return determinant(); } | |
1344 | /// Return the product of the scale values | ||
1345 | ✗ | double determinant() const OPENVDB_MAP_FUNC_SPECIFIER { | |
1346 | ✗ | return mScaleValues.x() * mScaleValues.y() * mScaleValues.z(); | |
1347 | } | ||
1348 | /// Return the absolute values of the scale values | ||
1349 | 16 | Vec3d voxelSize() const OPENVDB_MAP_FUNC_SPECIFIER { return mVoxelSize;} | |
1350 | /// Return the absolute values of the scale values, ignores argument | ||
1351 | ✗ | Vec3d voxelSize(const Vec3d&) const OPENVDB_MAP_FUNC_SPECIFIER { return voxelSize();} | |
1352 | |||
1353 | /// Returns the scale values | ||
1354 | const Vec3d& getScale() const { return mScaleValues; } | ||
1355 | /// Returns the translation | ||
1356 | const Vec3d& getTranslation() const { return mTranslation; } | ||
1357 | |||
1358 | /// Return the square of the scale. Used to optimize some finite difference calculations | ||
1359 | const Vec3d& getInvScaleSqr() const {return mInvScaleSqr;} | ||
1360 | /// Return 1/(2 scale). Used to optimize some finite difference calculations | ||
1361 | const Vec3d& getInvTwiceScale() const {return mInvTwiceScale;} | ||
1362 | /// Return 1/(scale) | ||
1363 | const Vec3d& getInvScale() const {return mScaleValuesInverse; } | ||
1364 | |||
1365 | /// read serialization | ||
1366 | 1 | void read(std::istream& is) override | |
1367 | { | ||
1368 | mTranslation.read(is); | ||
1369 | mScaleValues.read(is); | ||
1370 | mVoxelSize.read(is); | ||
1371 | mScaleValuesInverse.read(is); | ||
1372 | mInvScaleSqr.read(is); | ||
1373 | mInvTwiceScale.read(is); | ||
1374 | 1 | } | |
1375 | /// write serialization | ||
1376 | 1 | void write(std::ostream& os) const override | |
1377 | { | ||
1378 | mTranslation.write(os); | ||
1379 | mScaleValues.write(os); | ||
1380 | mVoxelSize.write(os); | ||
1381 | mScaleValuesInverse.write(os); | ||
1382 | mInvScaleSqr.write(os); | ||
1383 | mInvTwiceScale.write(os); | ||
1384 | 1 | } | |
1385 | /// string serialization, useful for debuging | ||
1386 | ✗ | std::string str() const override | |
1387 | { | ||
1388 | ✗ | std::ostringstream buffer; | |
1389 | ✗ | buffer << " - translation: " << mTranslation << std::endl; | |
1390 | ✗ | buffer << " - scale: " << mScaleValues << std::endl; | |
1391 | ✗ | buffer << " - voxel dimensions: " << mVoxelSize << std::endl; | |
1392 | ✗ | return buffer.str(); | |
1393 | } | ||
1394 | |||
1395 | ✗ | bool isEqual(const MapBase& other) const override { return isEqualBase(*this, other); } | |
1396 | |||
1397 | 5 | bool operator==(const ScaleTranslateMap& other) const | |
1398 | { | ||
1399 | // ::eq() uses a tolerance | ||
1400 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | if (!mScaleValues.eq(other.mScaleValues)) { return false; } |
1401 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
|
5 | if (!mTranslation.eq(other.mTranslation)) { return false; } |
1402 | return true; | ||
1403 | } | ||
1404 | |||
1405 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | bool operator!=(const ScaleTranslateMap& other) const { return !(*this == other); } |
1406 | |||
1407 | /// Return AffineMap::Ptr to an AffineMap equivalent to *this | ||
1408 | 26 | AffineMap::Ptr getAffineMap() const override | |
1409 | { | ||
1410 |
2/4✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 26 times.
✗ Branch 6 not taken.
|
52 | AffineMap::Ptr affineMap(new AffineMap(math::scale<Mat4d>(mScaleValues))); |
1411 | 26 | affineMap->accumPostTranslation(mTranslation); | |
1412 | 26 | return affineMap; | |
1413 | } | ||
1414 | |||
1415 | //@{ | ||
1416 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
1417 | /// of prepending the appropraite operation. | ||
1418 | 3 | MapBase::Ptr preRotate(double radians, Axis axis) const override | |
1419 | { | ||
1420 | 3 | AffineMap::Ptr affineMap = getAffineMap(); | |
1421 | affineMap->accumPreRotation(axis, radians); | ||
1422 |
2/6✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
9 | return simplify(affineMap); |
1423 | } | ||
1424 | 1 | MapBase::Ptr preTranslate(const Vec3d& t) const override | |
1425 | { | ||
1426 | const Vec3d& s = mScaleValues; | ||
1427 | const Vec3d scaled_trans( t.x() * s.x(), | ||
1428 | t.y() * s.y(), | ||
1429 | 1 | t.z() * s.z() ); | |
1430 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
2 | return MapBase::Ptr( new ScaleTranslateMap(mScaleValues, mTranslation + scaled_trans)); |
1431 | } | ||
1432 | |||
1433 | MapBase::Ptr preScale(const Vec3d& v) const override; | ||
1434 | |||
1435 | 2 | MapBase::Ptr preShear(double shear, Axis axis0, Axis axis1) const override | |
1436 | { | ||
1437 | 2 | AffineMap::Ptr affineMap = getAffineMap(); | |
1438 | affineMap->accumPreShear(axis0, axis1, shear); | ||
1439 |
2/6✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
6 | return simplify(affineMap); |
1440 | } | ||
1441 | //@} | ||
1442 | |||
1443 | //@{ | ||
1444 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
1445 | /// of postfixing the appropraite operation. | ||
1446 | 3 | MapBase::Ptr postRotate(double radians, Axis axis) const override | |
1447 | { | ||
1448 | 3 | AffineMap::Ptr affineMap = getAffineMap(); | |
1449 | affineMap->accumPostRotation(axis, radians); | ||
1450 |
2/6✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
9 | return simplify(affineMap); |
1451 | } | ||
1452 | 1 | MapBase::Ptr postTranslate(const Vec3d& t) const override | |
1453 | { | ||
1454 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
2 | return MapBase::Ptr( new ScaleTranslateMap(mScaleValues, mTranslation + t)); |
1455 | } | ||
1456 | |||
1457 | MapBase::Ptr postScale(const Vec3d& v) const override; | ||
1458 | |||
1459 | 2 | MapBase::Ptr postShear(double shear, Axis axis0, Axis axis1) const override | |
1460 | { | ||
1461 | 2 | AffineMap::Ptr affineMap = getAffineMap(); | |
1462 | affineMap->accumPostShear(axis0, axis1, shear); | ||
1463 |
2/6✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
6 | return simplify(affineMap); |
1464 | } | ||
1465 | //@} | ||
1466 | |||
1467 | private: | ||
1468 | Vec3d mTranslation, mScaleValues, mVoxelSize, mScaleValuesInverse, | ||
1469 | mInvScaleSqr, mInvTwiceScale; | ||
1470 | }; // class ScaleTanslateMap | ||
1471 | |||
1472 | |||
1473 | inline MapBase::Ptr | ||
1474 | 5 | ScaleMap::postTranslate(const Vec3d& t) const | |
1475 | { | ||
1476 |
1/2✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
|
10 | return MapBase::Ptr(new ScaleTranslateMap(mScaleValues, t)); |
1477 | } | ||
1478 | |||
1479 | |||
1480 | inline MapBase::Ptr | ||
1481 | 2 | ScaleMap::preTranslate(const Vec3d& t) const | |
1482 | { | ||
1483 | |||
1484 | const Vec3d& s = mScaleValues; | ||
1485 | const Vec3d scaled_trans( t.x() * s.x(), | ||
1486 | t.y() * s.y(), | ||
1487 | 2 | t.z() * s.z() ); | |
1488 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
4 | return MapBase::Ptr(new ScaleTranslateMap(mScaleValues, scaled_trans)); |
1489 | } | ||
1490 | |||
1491 | |||
1492 | /// @brief A specialized Affine transform that uniformaly scales along the principal axis | ||
1493 | /// and then translates the result. | ||
1494 | /// @note This class is marked final with ABI=8 | ||
1495 | class OPENVDB_API UniformScaleTranslateMap OPENVDB_MAP_CLASS_SPECIFIER: public ScaleTranslateMap | ||
1496 | { | ||
1497 | public: | ||
1498 | using Ptr = SharedPtr<UniformScaleTranslateMap>; | ||
1499 | using ConstPtr = SharedPtr<const UniformScaleTranslateMap>; | ||
1500 | |||
1501 | 8 | UniformScaleTranslateMap():ScaleTranslateMap(Vec3d(1,1,1), Vec3d(0,0,0)) {} | |
1502 | 20 | UniformScaleTranslateMap(double scale, const Vec3d& translate): | |
1503 |
9/32✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2 times.
✓ Branch 11 taken 7 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✓ Branch 23 taken 1 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✓ Branch 27 taken 1 times.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
|
20 | ScaleTranslateMap(Vec3d(scale,scale,scale), translate) {} |
1504 | 2 | UniformScaleTranslateMap(const UniformScaleMap& scale, const TranslationMap& translate): | |
1505 |
4/8✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
|
2 | ScaleTranslateMap(scale.getScale(), translate.getTranslation()) {} |
1506 | |||
1507 | 1 | UniformScaleTranslateMap(const UniformScaleTranslateMap& other):ScaleTranslateMap(other) {} | |
1508 |
2/6✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
|
21 | ~UniformScaleTranslateMap() override = default; |
1509 | |||
1510 | /// Return a MapBase::Ptr to a new UniformScaleTranslateMap | ||
1511 | ✗ | static MapBase::Ptr create() { return MapBase::Ptr(new UniformScaleTranslateMap()); } | |
1512 | /// Return a MapBase::Ptr to a deep copy of this map | ||
1513 | 1 | MapBase::Ptr copy() const override { return MapBase::Ptr(new UniformScaleTranslateMap(*this)); } | |
1514 | |||
1515 | 1 | MapBase::Ptr inverseMap() const override | |
1516 | { | ||
1517 | const Vec3d& scaleInv = getInvScale(); | ||
1518 | const Vec3d& trans = getTranslation(); | ||
1519 | 2 | return MapBase::Ptr(new UniformScaleTranslateMap(scaleInv[0], -scaleInv[0] * trans)); | |
1520 | } | ||
1521 | |||
1522 | 1 | static bool isRegistered() | |
1523 | { | ||
1524 | 1 | return MapRegistry::isRegistered(UniformScaleTranslateMap::mapType()); | |
1525 | } | ||
1526 | |||
1527 | 337 | static void registerMap() | |
1528 | { | ||
1529 | 337 | MapRegistry::registerMap( | |
1530 | 337 | UniformScaleTranslateMap::mapType(), UniformScaleTranslateMap::create); | |
1531 | 337 | } | |
1532 | |||
1533 | 32 | Name type() const override { return mapType(); } | |
1534 |
5/144✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 333 times.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 13 taken 5 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 65 not taken.
✗ Branch 66 not taken.
✗ Branch 67 not taken.
✗ Branch 69 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 75 not taken.
✗ Branch 77 not taken.
✗ Branch 78 not taken.
✗ Branch 79 not taken.
✗ Branch 81 not taken.
✗ Branch 82 not taken.
✗ Branch 83 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 87 not taken.
✗ Branch 89 not taken.
✗ Branch 90 not taken.
✗ Branch 91 not taken.
✗ Branch 93 not taken.
✗ Branch 94 not taken.
✗ Branch 95 not taken.
✗ Branch 97 not taken.
✗ Branch 98 not taken.
✗ Branch 99 not taken.
✗ Branch 101 not taken.
✗ Branch 102 not taken.
✗ Branch 103 not taken.
✗ Branch 105 not taken.
✗ Branch 106 not taken.
✗ Branch 107 not taken.
✗ Branch 109 not taken.
✗ Branch 110 not taken.
✗ Branch 111 not taken.
✗ Branch 113 not taken.
✗ Branch 114 not taken.
✗ Branch 115 not taken.
✗ Branch 117 not taken.
✗ Branch 118 not taken.
✗ Branch 119 not taken.
✗ Branch 121 not taken.
✗ Branch 122 not taken.
✗ Branch 123 not taken.
✗ Branch 125 not taken.
✗ Branch 126 not taken.
✗ Branch 127 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.
✗ Branch 161 not taken.
✗ Branch 162 not taken.
✗ Branch 165 not taken.
✗ Branch 166 not taken.
✗ Branch 169 not taken.
✗ Branch 170 not taken.
✗ Branch 173 not taken.
✗ Branch 174 not taken.
✗ Branch 177 not taken.
✗ Branch 178 not taken.
✗ Branch 181 not taken.
✗ Branch 182 not taken.
✗ Branch 185 not taken.
✗ Branch 186 not taken.
✗ Branch 189 not taken.
✗ Branch 190 not taken.
✗ Branch 193 not taken.
✗ Branch 194 not taken.
✗ Branch 197 not taken.
✗ Branch 198 not taken.
✗ Branch 201 not taken.
✗ Branch 202 not taken.
✗ Branch 205 not taken.
✗ Branch 206 not taken.
✗ Branch 209 not taken.
✗ Branch 210 not taken.
✗ Branch 213 not taken.
✗ Branch 214 not taken.
✗ Branch 217 not taken.
✗ Branch 218 not taken.
✗ Branch 222 not taken.
✗ Branch 223 not taken.
|
360 | static Name mapType() { return Name("UniformScaleTranslateMap"); } |
1535 | |||
1536 | 3 | bool isEqual(const MapBase& other) const override { return isEqualBase(*this, other); } | |
1537 | |||
1538 | bool operator==(const UniformScaleTranslateMap& other) const | ||
1539 | { | ||
1540 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
|
3 | return ScaleTranslateMap::operator==(other); |
1541 | } | ||
1542 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | bool operator!=(const UniformScaleTranslateMap& other) const { return !(*this == other); } |
1543 | |||
1544 | /// @brief Return a MapBase::Ptr to a UniformScaleTranslateMap that is | ||
1545 | /// the result of prepending translation on this map. | ||
1546 | 1 | MapBase::Ptr preTranslate(const Vec3d& t) const override | |
1547 | { | ||
1548 | const double scale = this->getScale().x(); | ||
1549 | 1 | const Vec3d new_trans = this->getTranslation() + scale * t; | |
1550 | 2 | return MapBase::Ptr( new UniformScaleTranslateMap(scale, new_trans)); | |
1551 | } | ||
1552 | |||
1553 | /// @brief Return a MapBase::Ptr to a UniformScaleTranslateMap that is | ||
1554 | /// the result of postfixing translation on this map. | ||
1555 | 1 | MapBase::Ptr postTranslate(const Vec3d& t) const override | |
1556 | { | ||
1557 | const double scale = this->getScale().x(); | ||
1558 | 2 | return MapBase::Ptr( new UniformScaleTranslateMap(scale, this->getTranslation() + t)); | |
1559 | } | ||
1560 | }; // class UniformScaleTanslateMap | ||
1561 | |||
1562 | |||
1563 | inline MapBase::Ptr | ||
1564 | 1 | UniformScaleMap::postTranslate(const Vec3d& t) const | |
1565 | { | ||
1566 | const double scale = this->getScale().x(); | ||
1567 | 2 | return MapBase::Ptr(new UniformScaleTranslateMap(scale, t)); | |
1568 | } | ||
1569 | |||
1570 | |||
1571 | inline MapBase::Ptr | ||
1572 | 7 | UniformScaleMap::preTranslate(const Vec3d& t) const | |
1573 | { | ||
1574 | const double scale = this->getScale().x(); | ||
1575 | 14 | return MapBase::Ptr(new UniformScaleTranslateMap(scale, scale*t)); | |
1576 | } | ||
1577 | |||
1578 | |||
1579 | inline MapBase::Ptr | ||
1580 | ✗ | TranslationMap::preScale(const Vec3d& v) const | |
1581 | { | ||
1582 | ✗ | if (isApproxEqual(v[0],v[1]) && isApproxEqual(v[0],v[2])) { | |
1583 | ✗ | return MapBase::Ptr(new UniformScaleTranslateMap(v[0], mTranslation)); | |
1584 | } else { | ||
1585 | ✗ | return MapBase::Ptr(new ScaleTranslateMap(v, mTranslation)); | |
1586 | } | ||
1587 | } | ||
1588 | |||
1589 | |||
1590 | inline MapBase::Ptr | ||
1591 | ✗ | TranslationMap::postScale(const Vec3d& v) const | |
1592 | { | ||
1593 | ✗ | if (isApproxEqual(v[0],v[1]) && isApproxEqual(v[0],v[2])) { | |
1594 | ✗ | return MapBase::Ptr(new UniformScaleTranslateMap(v[0], v[0]*mTranslation)); | |
1595 | } else { | ||
1596 | const Vec3d trans(mTranslation.x()*v.x(), | ||
1597 | mTranslation.y()*v.y(), | ||
1598 | ✗ | mTranslation.z()*v.z()); | |
1599 | ✗ | return MapBase::Ptr(new ScaleTranslateMap(v, trans)); | |
1600 | } | ||
1601 | } | ||
1602 | |||
1603 | |||
1604 | inline MapBase::Ptr | ||
1605 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | ScaleTranslateMap::preScale(const Vec3d& v) const |
1606 | { | ||
1607 | const Vec3d new_scale( v * mScaleValues ); | ||
1608 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
3 | if (isApproxEqual(new_scale[0],new_scale[1]) && isApproxEqual(new_scale[0],new_scale[2])) { |
1609 | ✗ | return MapBase::Ptr( new UniformScaleTranslateMap(new_scale[0], mTranslation)); | |
1610 | } else { | ||
1611 |
1/2✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | return MapBase::Ptr( new ScaleTranslateMap(new_scale, mTranslation)); |
1612 | } | ||
1613 | } | ||
1614 | |||
1615 | |||
1616 | inline MapBase::Ptr | ||
1617 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | ScaleTranslateMap::postScale(const Vec3d& v) const |
1618 | { | ||
1619 | const Vec3d new_scale( v * mScaleValues ); | ||
1620 | const Vec3d new_trans( mTranslation.x()*v.x(), | ||
1621 | mTranslation.y()*v.y(), | ||
1622 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | mTranslation.z()*v.z() ); |
1623 | |||
1624 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
3 | if (isApproxEqual(new_scale[0],new_scale[1]) && isApproxEqual(new_scale[0],new_scale[2])) { |
1625 | ✗ | return MapBase::Ptr( new UniformScaleTranslateMap(new_scale[0], new_trans)); | |
1626 | } else { | ||
1627 |
1/2✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | return MapBase::Ptr( new ScaleTranslateMap(new_scale, new_trans)); |
1628 | } | ||
1629 | } | ||
1630 | |||
1631 | |||
1632 | //////////////////////////////////////// | ||
1633 | |||
1634 | |||
1635 | /// @brief A specialized linear transform that performs a unitary maping | ||
1636 | /// i.e. rotation and or reflection. | ||
1637 | /// @note This class is marked final with ABI=8 | ||
1638 | class OPENVDB_API UnitaryMap OPENVDB_MAP_CLASS_SPECIFIER: public MapBase | ||
1639 | { | ||
1640 | public: | ||
1641 | using Ptr = SharedPtr<UnitaryMap>; | ||
1642 | using ConstPtr = SharedPtr<const UnitaryMap>; | ||
1643 | |||
1644 | /// default constructor makes an Idenity. | ||
1645 | ✗ | UnitaryMap(): mAffineMap(Mat4d::identity()) | |
1646 | { | ||
1647 | } | ||
1648 | |||
1649 | 3 | UnitaryMap(const Vec3d& axis, double radians) | |
1650 | 3 | { | |
1651 | Mat3d matrix; | ||
1652 | matrix.setToRotation(axis, radians); | ||
1653 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | mAffineMap = AffineMap(matrix); |
1654 | 3 | } | |
1655 | |||
1656 | ✗ | UnitaryMap(Axis axis, double radians) | |
1657 | { | ||
1658 | Mat4d matrix; | ||
1659 | matrix.setToRotation(axis, radians); | ||
1660 | ✗ | mAffineMap = AffineMap(matrix); | |
1661 | } | ||
1662 | |||
1663 | 3 | UnitaryMap(const Mat3d& m) | |
1664 | 3 | { | |
1665 | // test that the mat3 is a rotation || reflection | ||
1666 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
|
3 | if (!isUnitary(m)) { |
1667 | ✗ | OPENVDB_THROW(ArithmeticError, "Matrix initializing unitary map was not unitary"); | |
1668 | } | ||
1669 | |||
1670 | 3 | Mat4d matrix(Mat4d::identity()); | |
1671 | matrix.setMat3(m); | ||
1672 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | mAffineMap = AffineMap(matrix); |
1673 | 3 | } | |
1674 | |||
1675 | 1 | UnitaryMap(const Mat4d& m) | |
1676 | 1 | { | |
1677 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (!isInvertible(m)) { |
1678 | ✗ | OPENVDB_THROW(ArithmeticError, | |
1679 | "4x4 Matrix initializing unitary map was not unitary: not invertible"); | ||
1680 | } | ||
1681 | |||
1682 | if (!isAffine(m)) { | ||
1683 | ✗ | OPENVDB_THROW(ArithmeticError, | |
1684 | "4x4 Matrix initializing unitary map was not unitary: not affine"); | ||
1685 | } | ||
1686 | |||
1687 | if (hasTranslation(m)) { | ||
1688 | ✗ | OPENVDB_THROW(ArithmeticError, | |
1689 | "4x4 Matrix initializing unitary map was not unitary: had translation"); | ||
1690 | } | ||
1691 | |||
1692 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | if (!isUnitary(m.getMat3())) { |
1693 | ✗ | OPENVDB_THROW(ArithmeticError, | |
1694 | "4x4 Matrix initializing unitary map was not unitary"); | ||
1695 | } | ||
1696 | |||
1697 | 1 | mAffineMap = AffineMap(m); | |
1698 | 1 | } | |
1699 | |||
1700 | 10 | UnitaryMap(const UnitaryMap& other): | |
1701 | MapBase(other), | ||
1702 | 4 | mAffineMap(other.mAffineMap) | |
1703 | { | ||
1704 | } | ||
1705 | |||
1706 | ✗ | UnitaryMap(const UnitaryMap& first, const UnitaryMap& second): | |
1707 | ✗ | mAffineMap(*(first.getAffineMap()), *(second.getAffineMap())) | |
1708 | { | ||
1709 | } | ||
1710 | |||
1711 |
1/4✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
4 | ~UnitaryMap() override = default; |
1712 | |||
1713 | /// Return a MapBase::Ptr to a new UnitaryMap | ||
1714 | ✗ | static MapBase::Ptr create() { return MapBase::Ptr(new UnitaryMap()); } | |
1715 | /// Returns a MapBase::Ptr to a deep copy of *this | ||
1716 | ✗ | MapBase::Ptr copy() const override { return MapBase::Ptr(new UnitaryMap(*this)); } | |
1717 | |||
1718 | 1 | MapBase::Ptr inverseMap() const override | |
1719 | { | ||
1720 |
1/2✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
|
2 | return MapBase::Ptr(new UnitaryMap(mAffineMap.getMat4().inverse())); |
1721 | } | ||
1722 | |||
1723 | 3 | static bool isRegistered() { return MapRegistry::isRegistered(UnitaryMap::mapType()); } | |
1724 | |||
1725 | 323 | static void registerMap() | |
1726 | { | ||
1727 | 323 | MapRegistry::registerMap( | |
1728 | 323 | UnitaryMap::mapType(), | |
1729 | UnitaryMap::create); | ||
1730 | 323 | } | |
1731 | |||
1732 | /// Return @c UnitaryMap | ||
1733 | 2 | Name type() const override { return mapType(); } | |
1734 | /// Return @c UnitaryMap | ||
1735 |
4/143✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 323 times.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 65 not taken.
✗ Branch 66 not taken.
✗ Branch 67 not taken.
✗ Branch 69 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 75 not taken.
✗ Branch 77 not taken.
✗ Branch 78 not taken.
✗ Branch 79 not taken.
✗ Branch 81 not taken.
✗ Branch 82 not taken.
✗ Branch 83 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 87 not taken.
✗ Branch 89 not taken.
✗ Branch 90 not taken.
✗ Branch 91 not taken.
✗ Branch 93 not taken.
✗ Branch 94 not taken.
✗ Branch 95 not taken.
✗ Branch 97 not taken.
✗ Branch 98 not taken.
✗ Branch 99 not taken.
✗ Branch 101 not taken.
✗ Branch 102 not taken.
✗ Branch 103 not taken.
✗ Branch 105 not taken.
✗ Branch 106 not taken.
✗ Branch 107 not taken.
✗ Branch 109 not taken.
✗ Branch 110 not taken.
✗ Branch 111 not taken.
✗ Branch 113 not taken.
✗ Branch 114 not taken.
✗ Branch 115 not taken.
✗ Branch 117 not taken.
✗ Branch 118 not taken.
✗ Branch 119 not taken.
✗ Branch 121 not taken.
✗ Branch 122 not taken.
✗ Branch 123 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.
✗ Branch 161 not taken.
✗ Branch 162 not taken.
✗ Branch 165 not taken.
✗ Branch 166 not taken.
✗ Branch 169 not taken.
✗ Branch 170 not taken.
✗ Branch 173 not taken.
✗ Branch 174 not taken.
✗ Branch 177 not taken.
✗ Branch 178 not taken.
✗ Branch 181 not taken.
✗ Branch 182 not taken.
✗ Branch 185 not taken.
✗ Branch 186 not taken.
✗ Branch 189 not taken.
✗ Branch 190 not taken.
✗ Branch 193 not taken.
✗ Branch 194 not taken.
✗ Branch 197 not taken.
✗ Branch 198 not taken.
✗ Branch 201 not taken.
✗ Branch 202 not taken.
✗ Branch 205 not taken.
✗ Branch 206 not taken.
✗ Branch 209 not taken.
✗ Branch 210 not taken.
✗ Branch 213 not taken.
✗ Branch 214 not taken.
✗ Branch 217 not taken.
✗ Branch 218 not taken.
✗ Branch 222 not taken.
✗ Branch 223 not taken.
|
328 | static Name mapType() { return Name("UnitaryMap"); } |
1736 | |||
1737 | /// Return @c true (a UnitaryMap is always linear). | ||
1738 | ✗ | bool isLinear() const override { return true; } | |
1739 | |||
1740 | /// Return @c false (by convention true) | ||
1741 | ✗ | bool hasUniformScale() const override { return true; } | |
1742 | |||
1743 | ✗ | bool isEqual(const MapBase& other) const override { return isEqualBase(*this, other); } | |
1744 | |||
1745 | bool operator==(const UnitaryMap& other) const | ||
1746 | { | ||
1747 | // compare underlying linear map. | ||
1748 |
2/6✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
2 | if (mAffineMap!=other.mAffineMap) return false; |
1749 | return true; | ||
1750 | } | ||
1751 | |||
1752 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | bool operator!=(const UnitaryMap& other) const { return !(*this == other); } |
1753 | /// Return the image of @c in under the map | ||
1754 | 1 | Vec3d applyMap(const Vec3d& in) const override { return mAffineMap.applyMap(in); } | |
1755 | /// Return the pre-image of @c in under the map | ||
1756 | ✗ | Vec3d applyInverseMap(const Vec3d& in) const override { return mAffineMap.applyInverseMap(in); } | |
1757 | |||
1758 | ✗ | Vec3d applyJacobian(const Vec3d& in, const Vec3d&) const override { return applyJacobian(in); } | |
1759 | /// Return the Jacobian of the map applied to @a in. | ||
1760 | ✗ | Vec3d applyJacobian(const Vec3d& in) const override { return mAffineMap.applyJacobian(in); } | |
1761 | |||
1762 | /// @brief Return the Inverse Jacobian of the map applied to @a in | ||
1763 | /// (i.e. inverse map with out translation) | ||
1764 | ✗ | Vec3d applyInverseJacobian(const Vec3d& in, const Vec3d&) const override { | |
1765 | ✗ | return applyInverseJacobian(in); | |
1766 | } | ||
1767 | /// @brief Return the Inverse Jacobian of the map applied to @a in | ||
1768 | /// (i.e. inverse map with out translation) | ||
1769 | ✗ | Vec3d applyInverseJacobian(const Vec3d& in) const override { | |
1770 | ✗ | return mAffineMap.applyInverseJacobian(in); | |
1771 | } | ||
1772 | |||
1773 | /// @brief Return the Jacobian Transpose of the map applied to @a in. | ||
1774 | /// @details This tranforms range-space gradients to domain-space gradients | ||
1775 | ✗ | Vec3d applyJT(const Vec3d& in, const Vec3d&) const override { return applyJT(in); } | |
1776 | /// Return the Jacobian Transpose of the map applied to @a in. | ||
1777 | ✗ | Vec3d applyJT(const Vec3d& in) const override { | |
1778 | ✗ | return applyInverseMap(in); // the transpose of the unitary map is its inverse | |
1779 | } | ||
1780 | |||
1781 | |||
1782 | /// @brief Return the transpose of the inverse Jacobian of the map applied to @a in | ||
1783 | /// @details Ignores second argument | ||
1784 | ✗ | Vec3d applyIJT(const Vec3d& in, const Vec3d& ) const override { return applyIJT(in);} | |
1785 | /// Return the transpose of the inverse Jacobian of the map applied to @c in | ||
1786 | ✗ | Vec3d applyIJT(const Vec3d& in) const override { return mAffineMap.applyIJT(in); } | |
1787 | /// Return the Jacobian Curvature: zero for a linear map | ||
1788 | ✗ | Mat3d applyIJC(const Mat3d& in) const override { return mAffineMap.applyIJC(in); } | |
1789 | ✗ | Mat3d applyIJC(const Mat3d& in, const Vec3d&, const Vec3d& ) const override { | |
1790 | ✗ | return applyIJC(in); | |
1791 | } | ||
1792 | |||
1793 | /// Return the determinant of the Jacobian, ignores argument | ||
1794 | ✗ | double determinant(const Vec3d&) const override { return determinant(); } | |
1795 | /// Return the determinant of the Jacobian | ||
1796 | ✗ | double determinant() const override { return mAffineMap.determinant(); } | |
1797 | |||
1798 | |||
1799 | /// @{ | ||
1800 | /// @brief Returns the lengths of the images of the segments | ||
1801 | /// (0,0,0) − (1,0,0), (0,0,0) − (0,1,0) and (0,0,0) − (0,0,1). | ||
1802 | ✗ | Vec3d voxelSize() const override { return mAffineMap.voxelSize();} | |
1803 | ✗ | Vec3d voxelSize(const Vec3d&) const override { return voxelSize();} | |
1804 | /// @} | ||
1805 | |||
1806 | /// read serialization | ||
1807 | ✗ | void read(std::istream& is) override | |
1808 | { | ||
1809 | ✗ | mAffineMap.read(is); | |
1810 | } | ||
1811 | |||
1812 | /// write serialization | ||
1813 | ✗ | void write(std::ostream& os) const override | |
1814 | { | ||
1815 | mAffineMap.write(os); | ||
1816 | } | ||
1817 | /// string serialization, useful for debuging | ||
1818 | ✗ | std::string str() const override | |
1819 | { | ||
1820 | ✗ | std::ostringstream buffer; | |
1821 | ✗ | buffer << mAffineMap.str(); | |
1822 | ✗ | return buffer.str(); | |
1823 | } | ||
1824 | /// Return AffineMap::Ptr to an AffineMap equivalent to *this | ||
1825 | 4 | AffineMap::Ptr getAffineMap() const override { | |
1826 | 4 | return AffineMap::Ptr(new AffineMap(mAffineMap)); | |
1827 | } | ||
1828 | |||
1829 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
1830 | /// of prepending the given rotation. | ||
1831 | ✗ | MapBase::Ptr preRotate(double radians, Axis axis) const override | |
1832 | { | ||
1833 | ✗ | UnitaryMap first(axis, radians); | |
1834 | ✗ | UnitaryMap::Ptr unitaryMap(new UnitaryMap(first, *this)); | |
1835 | ✗ | return StaticPtrCast<MapBase, UnitaryMap>(unitaryMap); | |
1836 | } | ||
1837 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
1838 | /// of prepending the given translation. | ||
1839 | ✗ | MapBase::Ptr preTranslate(const Vec3d& t) const override | |
1840 | { | ||
1841 | ✗ | AffineMap::Ptr affineMap = getAffineMap(); | |
1842 | affineMap->accumPreTranslation(t); | ||
1843 | ✗ | return simplify(affineMap); | |
1844 | } | ||
1845 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
1846 | /// of prepending the given scale. | ||
1847 | ✗ | MapBase::Ptr preScale(const Vec3d& v) const override | |
1848 | { | ||
1849 | ✗ | AffineMap::Ptr affineMap = getAffineMap(); | |
1850 | affineMap->accumPreScale(v); | ||
1851 | ✗ | return simplify(affineMap); | |
1852 | } | ||
1853 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
1854 | /// of prepending the given shear. | ||
1855 | ✗ | MapBase::Ptr preShear(double shear, Axis axis0, Axis axis1) const override | |
1856 | { | ||
1857 | ✗ | AffineMap::Ptr affineMap = getAffineMap(); | |
1858 | affineMap->accumPreShear(axis0, axis1, shear); | ||
1859 | ✗ | return simplify(affineMap); | |
1860 | } | ||
1861 | |||
1862 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
1863 | /// of appending the given rotation. | ||
1864 | ✗ | MapBase::Ptr postRotate(double radians, Axis axis) const override | |
1865 | { | ||
1866 | ✗ | UnitaryMap second(axis, radians); | |
1867 | ✗ | UnitaryMap::Ptr unitaryMap(new UnitaryMap(*this, second)); | |
1868 | ✗ | return StaticPtrCast<MapBase, UnitaryMap>(unitaryMap); | |
1869 | } | ||
1870 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
1871 | /// of appending the given translation. | ||
1872 | ✗ | MapBase::Ptr postTranslate(const Vec3d& t) const override | |
1873 | { | ||
1874 | ✗ | AffineMap::Ptr affineMap = getAffineMap(); | |
1875 | affineMap->accumPostTranslation(t); | ||
1876 | ✗ | return simplify(affineMap); | |
1877 | } | ||
1878 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
1879 | /// of appending the given scale. | ||
1880 | ✗ | MapBase::Ptr postScale(const Vec3d& v) const override | |
1881 | { | ||
1882 | ✗ | AffineMap::Ptr affineMap = getAffineMap(); | |
1883 | affineMap->accumPostScale(v); | ||
1884 | ✗ | return simplify(affineMap); | |
1885 | } | ||
1886 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
1887 | /// of appending the given shear. | ||
1888 | ✗ | MapBase::Ptr postShear(double shear, Axis axis0, Axis axis1) const override | |
1889 | { | ||
1890 | ✗ | AffineMap::Ptr affineMap = getAffineMap(); | |
1891 | affineMap->accumPostShear(axis0, axis1, shear); | ||
1892 | ✗ | return simplify(affineMap); | |
1893 | } | ||
1894 | |||
1895 | private: | ||
1896 | AffineMap mAffineMap; | ||
1897 | }; // class UnitaryMap | ||
1898 | |||
1899 | |||
1900 | //////////////////////////////////////// | ||
1901 | |||
1902 | |||
1903 | /// @brief This map is composed of three steps. | ||
1904 | /// First it will take a box of size (Lx X Ly X Lz) defined by a member data bounding box | ||
1905 | /// and map it into a frustum with near plane (1 X Ly/Lx) and prescribed depth | ||
1906 | /// Then this frustum is transformed by an internal second map: most often a uniform scale, | ||
1907 | /// but other effects can be achieved by accumulating translation, shear and rotation: these | ||
1908 | /// are all applied to the second map | ||
1909 | /// @note This class is marked final with ABI=8 | ||
1910 | class OPENVDB_API NonlinearFrustumMap OPENVDB_MAP_CLASS_SPECIFIER: public MapBase | ||
1911 | { | ||
1912 | public: | ||
1913 | using Ptr = SharedPtr<NonlinearFrustumMap>; | ||
1914 | using ConstPtr = SharedPtr<const NonlinearFrustumMap>; | ||
1915 | |||
1916 | ✗ | NonlinearFrustumMap(): | |
1917 | MapBase(), | ||
1918 | ✗ | mBBox(Vec3d(0), Vec3d(1)), | |
1919 | mTaper(1), | ||
1920 | ✗ | mDepth(1) | |
1921 | { | ||
1922 | ✗ | init(); | |
1923 | } | ||
1924 | |||
1925 | /// @brief Constructor that takes an index-space bounding box | ||
1926 | /// to be mapped into a frustum with a given @a depth and @a taper | ||
1927 | /// (defined as ratio of nearplane/farplane). | ||
1928 | 10 | NonlinearFrustumMap(const BBoxd& bb, double taper, double depth): | |
1929 | 10 | MapBase(),mBBox(bb), mTaper(taper), mDepth(depth) | |
1930 | { | ||
1931 | 10 | init(); | |
1932 | } | ||
1933 | |||
1934 | /// @brief Constructor that takes an index-space bounding box | ||
1935 | /// to be mapped into a frustum with a given @a depth and @a taper | ||
1936 | /// (defined as ratio of nearplane/farplane). | ||
1937 | /// @details This frustum is further modifed by the @a secondMap, | ||
1938 | /// intended to be a simple translation and rotation and uniform scale | ||
1939 | 34 | NonlinearFrustumMap(const BBoxd& bb, double taper, double depth, | |
1940 | 34 | const MapBase::Ptr& secondMap): | |
1941 | 34 | mBBox(bb), mTaper(taper), mDepth(depth) | |
1942 | { | ||
1943 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 34 times.
|
34 | if (!secondMap->isLinear() ) { |
1944 | ✗ | OPENVDB_THROW(ArithmeticError, | |
1945 | "The second map in the Frustum transfrom must be linear"); | ||
1946 | } | ||
1947 | 34 | mSecondMap = *( secondMap->getAffineMap() ); | |
1948 | 34 | init(); | |
1949 | 34 | } | |
1950 | |||
1951 | 21728 | NonlinearFrustumMap(const NonlinearFrustumMap& other): | |
1952 | MapBase(), | ||
1953 | mBBox(other.mBBox), | ||
1954 | 21728 | mTaper(other.mTaper), | |
1955 | 21728 | mDepth(other.mDepth), | |
1956 | 21728 | mSecondMap(other.mSecondMap), | |
1957 | 21728 | mHasSimpleAffine(other.mHasSimpleAffine) | |
1958 | { | ||
1959 | 21728 | init(); | |
1960 | 21728 | } | |
1961 | |||
1962 | /// @brief Constructor from a camera frustum | ||
1963 | /// | ||
1964 | /// @param position the tip of the frustum (i.e., the camera's position). | ||
1965 | /// @param direction a vector pointing from @a position toward the near plane. | ||
1966 | /// @param up a non-unit vector describing the direction and extent of | ||
1967 | /// the frustum's intersection on the near plane. Together, | ||
1968 | /// @a up must be orthogonal to @a direction. | ||
1969 | /// @param aspect the aspect ratio of the frustum intersection with near plane | ||
1970 | /// defined as width / height | ||
1971 | /// @param z_near,depth the distance from @a position along @a direction to the | ||
1972 | /// near and far planes of the frustum. | ||
1973 | /// @param x_count the number of voxels, aligned with @a left, | ||
1974 | /// across the face of the frustum | ||
1975 | /// @param z_count the number of voxels, aligned with @a direction, | ||
1976 | /// between the near and far planes | ||
1977 | 7 | NonlinearFrustumMap(const Vec3d& position, | |
1978 | const Vec3d& direction, | ||
1979 | const Vec3d& up, | ||
1980 | double aspect /* width / height */, | ||
1981 | double z_near, double depth, | ||
1982 | 7 | Coord::ValueType x_count, Coord::ValueType z_count) { | |
1983 | |||
1984 | /// @todo check that depth > 0 | ||
1985 | /// @todo check up.length > 0 | ||
1986 | /// @todo check that direction dot up = 0 | ||
1987 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | if (!(depth > 0)) { |
1988 | ✗ | OPENVDB_THROW(ArithmeticError, | |
1989 | "The frustum depth must be non-zero and positive"); | ||
1990 | } | ||
1991 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | if (!(up.length() > 0)) { |
1992 | ✗ | OPENVDB_THROW(ArithmeticError, | |
1993 | "The frustum height must be non-zero and positive"); | ||
1994 | } | ||
1995 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | if (!(aspect > 0)) { |
1996 | ✗ | OPENVDB_THROW(ArithmeticError, | |
1997 | "The frustum aspect ratio must be non-zero and positive"); | ||
1998 | } | ||
1999 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | if (!(isApproxEqual(up.dot(direction), 0.))) { |
2000 | ✗ | OPENVDB_THROW(ArithmeticError, | |
2001 | "The frustum up orientation must be perpendicular to into-frustum direction"); | ||
2002 | } | ||
2003 | |||
2004 | 7 | double near_plane_height = 2 * up.length(); | |
2005 | 7 | double near_plane_width = aspect * near_plane_height; | |
2006 | |||
2007 | 7 | Coord::ValueType y_count = static_cast<int>(Round(x_count / aspect)); | |
2008 | |||
2009 | 7 | mBBox = BBoxd(Vec3d(0,0,0), Vec3d(x_count, y_count, z_count)); | |
2010 | 7 | mDepth = depth / near_plane_width; // depth non-dimensionalized on width | |
2011 | 7 | double gamma = near_plane_width / z_near; | |
2012 | 7 | mTaper = 1./(mDepth*gamma + 1.); | |
2013 | |||
2014 | 7 | Vec3d direction_unit = direction; | |
2015 | 7 | direction_unit.normalize(); | |
2016 | |||
2017 | 7 | Mat4d r1(Mat4d::identity()); | |
2018 | 7 | r1.setToRotation(/*from*/Vec3d(0,0,1), /*to */direction_unit); | |
2019 | 7 | Mat4d r2(Mat4d::identity()); | |
2020 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
14 | Vec3d temp = r1.inverse().transform(up); |
2021 | 7 | r2.setToRotation(/*from*/Vec3d(0,1,0), /*to*/temp ); | |
2022 | Mat4d scale = math::scale<Mat4d>( | ||
2023 | 7 | Vec3d(near_plane_width, near_plane_width, near_plane_width)); | |
2024 | |||
2025 | // move the near plane to origin, rotate to align with axis, and scale down | ||
2026 | // T_inv * R1_inv * R2_inv * scale_inv | ||
2027 |
1/2✓ Branch 3 taken 7 times.
✗ Branch 4 not taken.
|
7 | Mat4d mat = scale * r2 * r1; |
2028 | 7 | mat.setTranslation(position + z_near*direction_unit); | |
2029 | |||
2030 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | mSecondMap = AffineMap(mat); |
2031 | |||
2032 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | init(); |
2033 | 7 | } | |
2034 | |||
2035 |
4/16✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
21767 | ~NonlinearFrustumMap() override = default; |
2036 | |||
2037 | /// Return a MapBase::Ptr to a new NonlinearFrustumMap | ||
2038 | ✗ | static MapBase::Ptr create() { return MapBase::Ptr(new NonlinearFrustumMap()); } | |
2039 | /// Return a MapBase::Ptr to a deep copy of this map | ||
2040 |
1/2✓ Branch 2 taken 21728 times.
✗ Branch 3 not taken.
|
43456 | MapBase::Ptr copy() const override { return MapBase::Ptr(new NonlinearFrustumMap(*this)); } |
2041 | |||
2042 | /// @brief Not implemented, since there is currently no map type that can | ||
2043 | /// represent the inverse of a frustum | ||
2044 | /// @throw NotImplementedError | ||
2045 | ✗ | MapBase::Ptr inverseMap() const override | |
2046 | { | ||
2047 | ✗ | OPENVDB_THROW(NotImplementedError, | |
2048 | "inverseMap() is not implemented for NonlinearFrustumMap"); | ||
2049 | } | ||
2050 | 3 | static bool isRegistered() { return MapRegistry::isRegistered(NonlinearFrustumMap::mapType()); } | |
2051 | |||
2052 | 332 | static void registerMap() | |
2053 | { | ||
2054 | 332 | MapRegistry::registerMap( | |
2055 | 332 | NonlinearFrustumMap::mapType(), | |
2056 | NonlinearFrustumMap::create); | ||
2057 | 332 | } | |
2058 | /// Return @c NonlinearFrustumMap | ||
2059 | 43516 | Name type() const override { return mapType(); } | |
2060 | /// Return @c NonlinearFrustumMap | ||
2061 |
2/116✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 332 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ 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 not taken.
✗ 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 not taken.
✗ 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.
✗ Branch 161 not taken.
✗ Branch 162 not taken.
✗ Branch 165 not taken.
✗ Branch 166 not taken.
✗ Branch 169 not taken.
✗ Branch 170 not taken.
✗ Branch 173 not taken.
✗ Branch 174 not taken.
✗ Branch 177 not taken.
✗ Branch 178 not taken.
✗ Branch 181 not taken.
✗ Branch 182 not taken.
✗ Branch 185 not taken.
✗ Branch 186 not taken.
✗ Branch 189 not taken.
✗ Branch 190 not taken.
✗ Branch 193 not taken.
✗ Branch 194 not taken.
✗ Branch 197 not taken.
✗ Branch 198 not taken.
✗ Branch 201 not taken.
✗ Branch 202 not taken.
✗ Branch 205 not taken.
✗ Branch 206 not taken.
✗ Branch 209 not taken.
✗ Branch 210 not taken.
✗ Branch 213 not taken.
✗ Branch 214 not taken.
✗ Branch 217 not taken.
✗ Branch 218 not taken.
✗ Branch 222 not taken.
✗ Branch 223 not taken.
|
22116 | static Name mapType() { return Name("NonlinearFrustumMap"); } |
2062 | |||
2063 | /// Return @c false (a NonlinearFrustumMap is never linear). | ||
2064 | 43433 | bool isLinear() const override { return false; } | |
2065 | |||
2066 | /// Return @c false (by convention false) | ||
2067 | ✗ | bool hasUniformScale() const override { return false; } | |
2068 | |||
2069 | /// Return @c true if the map is equivalent to an identity | ||
2070 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | bool isIdentity() const |
2071 | { | ||
2072 | // The frustum can only be consistent with a linear map if the taper value is 1 | ||
2073 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (!isApproxEqual(mTaper, double(1)) ) return false; |
2074 | |||
2075 | // There are various ways an identity can decomposed between the two parts of the | ||
2076 | // map. Best to just check that the principle vectors are stationary. | ||
2077 | const Vec3d e1(1,0,0); | ||
2078 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
|
3 | if (!applyMap(e1).eq(e1)) return false; |
2079 | |||
2080 | const Vec3d e2(0,1,0); | ||
2081 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | if (!applyMap(e2).eq(e2)) return false; |
2082 | |||
2083 | const Vec3d e3(0,0,1); | ||
2084 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
|
2 | if (!applyMap(e3).eq(e3)) return false; |
2085 | |||
2086 | return true; | ||
2087 | } | ||
2088 | |||
2089 | 8 | bool isEqual(const MapBase& other) const override { return isEqualBase(*this, other); } | |
2090 | |||
2091 | 3 | bool operator==(const NonlinearFrustumMap& other) const | |
2092 | { | ||
2093 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (mBBox!=other.mBBox) return false; |
2094 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (!isApproxEqual(mTaper, other.mTaper)) return false; |
2095 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (!isApproxEqual(mDepth, other.mDepth)) return false; |
2096 | |||
2097 | // Two linear transforms are equivalent iff they have the same translation | ||
2098 | // and have the same affects on orthongal spanning basis check translation | ||
2099 | Vec3d e(0,0,0); | ||
2100 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (!mSecondMap.applyMap(e).eq(other.mSecondMap.applyMap(e))) return false; |
2101 | /// check spanning vectors | ||
2102 | 3 | e(0) = 1; | |
2103 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (!mSecondMap.applyMap(e).eq(other.mSecondMap.applyMap(e))) return false; |
2104 | 3 | e(0) = 0; | |
2105 | 3 | e(1) = 1; | |
2106 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (!mSecondMap.applyMap(e).eq(other.mSecondMap.applyMap(e))) return false; |
2107 | 3 | e(1) = 0; | |
2108 | 3 | e(2) = 1; | |
2109 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (!mSecondMap.applyMap(e).eq(other.mSecondMap.applyMap(e))) return false; |
2110 | return true; | ||
2111 | } | ||
2112 | |||
2113 | bool operator!=(const NonlinearFrustumMap& other) const { return !(*this == other); } | ||
2114 | |||
2115 | /// Return the image of @c in under the map | ||
2116 | 2499599586 | Vec3d applyMap(const Vec3d& in) const override | |
2117 | { | ||
2118 | 2499599586 | return mSecondMap.applyMap(applyFrustumMap(in)); | |
2119 | } | ||
2120 | |||
2121 | /// Return the pre-image of @c in under the map | ||
2122 | 143874285 | Vec3d applyInverseMap(const Vec3d& in) const override | |
2123 | { | ||
2124 | 143874285 | return applyFrustumInverseMap(mSecondMap.applyInverseMap(in)); | |
2125 | } | ||
2126 | /// Return the Jacobian of the linear second map applied to @c in | ||
2127 | ✗ | Vec3d applyJacobian(const Vec3d& in) const override { return mSecondMap.applyJacobian(in); } | |
2128 | /// Return the Jacobian defined at @c isloc applied to @c in | ||
2129 | 1 | Vec3d applyJacobian(const Vec3d& in, const Vec3d& isloc) const override | |
2130 | { | ||
2131 | // Move the center of the x-face of the bbox | ||
2132 | // to the origin in index space. | ||
2133 | 1 | Vec3d centered(isloc); | |
2134 | 1 | centered = centered - mBBox.min(); | |
2135 | 1 | centered.x() -= mXo; | |
2136 | 1 | centered.y() -= mYo; | |
2137 | |||
2138 | // scale the z-direction on depth / K count | ||
2139 | 1 | const double zprime = centered.z()*mDepthOnLz; | |
2140 | |||
2141 | 1 | const double scale = (mGamma * zprime + 1.) / mLx; | |
2142 | 1 | const double scale2 = mGamma * mDepthOnLz / mLx; | |
2143 | |||
2144 | 1 | const Vec3d tmp(scale * in.x() + scale2 * centered.x()* in.z(), | |
2145 | 1 | scale * in.y() + scale2 * centered.y()* in.z(), | |
2146 | 1 | mDepthOnLz * in.z()); | |
2147 | |||
2148 | 1 | return mSecondMap.applyJacobian(tmp); | |
2149 | } | ||
2150 | |||
2151 | |||
2152 | /// @brief Return the Inverse Jacobian of the map applied to @a in | ||
2153 | /// (i.e. inverse map with out translation) | ||
2154 | ✗ | Vec3d applyInverseJacobian(const Vec3d& in) const override { | |
2155 | ✗ | return mSecondMap.applyInverseJacobian(in); | |
2156 | } | ||
2157 | /// Return the Inverse Jacobian defined at @c isloc of the map applied to @a in. | ||
2158 | 1 | Vec3d applyInverseJacobian(const Vec3d& in, const Vec3d& isloc) const override { | |
2159 | |||
2160 | // Move the center of the x-face of the bbox | ||
2161 | // to the origin in index space. | ||
2162 | 1 | Vec3d centered(isloc); | |
2163 | 1 | centered = centered - mBBox.min(); | |
2164 | 1 | centered.x() -= mXo; | |
2165 | 1 | centered.y() -= mYo; | |
2166 | |||
2167 | // scale the z-direction on depth / K count | ||
2168 | 1 | const double zprime = centered.z()*mDepthOnLz; | |
2169 | |||
2170 | 1 | const double scale = (mGamma * zprime + 1.) / mLx; | |
2171 | 1 | const double scale2 = mGamma * mDepthOnLz / mLx; | |
2172 | |||
2173 | |||
2174 | Vec3d out = mSecondMap.applyInverseJacobian(in); | ||
2175 | |||
2176 | 1 | out.x() = (out.x() - scale2 * centered.x() * out.z() / mDepthOnLz) / scale; | |
2177 | 1 | out.y() = (out.y() - scale2 * centered.y() * out.z() / mDepthOnLz) / scale; | |
2178 | 1 | out.z() = out.z() / mDepthOnLz; | |
2179 | |||
2180 | 1 | return out; | |
2181 | } | ||
2182 | |||
2183 | /// @brief Return the Jacobian Transpose of the map applied to vector @c in at @c indexloc. | ||
2184 | /// @details This tranforms range-space gradients to domain-space gradients. | ||
2185 | ✗ | Vec3d applyJT(const Vec3d& in, const Vec3d& isloc) const override { | |
2186 | ✗ | const Vec3d tmp = mSecondMap.applyJT(in); | |
2187 | // Move the center of the x-face of the bbox | ||
2188 | // to the origin in index space. | ||
2189 | ✗ | Vec3d centered(isloc); | |
2190 | ✗ | centered = centered - mBBox.min(); | |
2191 | ✗ | centered.x() -= mXo; | |
2192 | ✗ | centered.y() -= mYo; | |
2193 | |||
2194 | // scale the z-direction on depth / K count | ||
2195 | ✗ | const double zprime = centered.z()*mDepthOnLz; | |
2196 | |||
2197 | ✗ | const double scale = (mGamma * zprime + 1.) / mLx; | |
2198 | ✗ | const double scale2 = mGamma * mDepthOnLz / mLx; | |
2199 | |||
2200 | return Vec3d(scale * tmp.x(), | ||
2201 | scale * tmp.y(), | ||
2202 | ✗ | scale2 * centered.x()* tmp.x() + | |
2203 | ✗ | scale2 * centered.y()* tmp.y() + | |
2204 | ✗ | mDepthOnLz * tmp.z()); | |
2205 | } | ||
2206 | /// Return the Jacobian Transpose of the second map applied to @c in. | ||
2207 | ✗ | Vec3d applyJT(const Vec3d& in) const override { | |
2208 | ✗ | return mSecondMap.applyJT(in); | |
2209 | } | ||
2210 | |||
2211 | /// Return the transpose of the inverse Jacobian of the linear second map applied to @c in | ||
2212 | ✗ | Vec3d applyIJT(const Vec3d& in) const override { return mSecondMap.applyIJT(in); } | |
2213 | |||
2214 | // the Jacobian of the nonlinear part of the transform is a sparse matrix | ||
2215 | // Jacobian^(-T) = | ||
2216 | // | ||
2217 | // (Lx)( 1/s 0 0 ) | ||
2218 | // ( 0 1/s 0 ) | ||
2219 | // ( -(x-xo)g/(sLx) -(y-yo)g/(sLx) Lz/(Depth Lx) ) | ||
2220 | /// Return the transpose of the inverse Jacobain (at @c locW applied to @c in. | ||
2221 | /// @c ijk is the location in the pre-image space (e.g. index space) | ||
2222 | 2 | Vec3d applyIJT(const Vec3d& d1_is, const Vec3d& ijk) const override | |
2223 | { | ||
2224 | 2 | const Vec3d loc = applyFrustumMap(ijk); | |
2225 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | const double s = mGamma * loc.z() + 1.; |
2226 | |||
2227 | // verify that we aren't at the singularity | ||
2228 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (isApproxEqual(s, 0.)) { |
2229 | ✗ | OPENVDB_THROW(ArithmeticError, "Tried to evaluate the frustum transform" | |
2230 | " at the singular focal point (e.g. camera)"); | ||
2231 | } | ||
2232 | |||
2233 | 2 | const double sinv = 1.0/s; // 1/(z*gamma + 1) | |
2234 | 2 | const double pt0 = mLx * sinv; // Lx / (z*gamma +1) | |
2235 | 2 | const double pt1 = mGamma * pt0; // gamma * Lx / ( z*gamma +1) | |
2236 | 2 | const double pt2 = pt1 * sinv; // gamma * Lx / ( z*gamma +1)**2 | |
2237 | |||
2238 | const Mat3d& jacinv = mSecondMap.getConstJacobianInv(); | ||
2239 | |||
2240 | // compute \frac{\partial E_i}{\partial x_j} | ||
2241 | 2 | Mat3d gradE(Mat3d::zero()); | |
2242 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
|
8 | for (int j = 0; j < 3; ++j ) { |
2243 | 6 | gradE(0,j) = pt0 * jacinv(0,j) - pt2 * loc.x()*jacinv(2,j); | |
2244 | 6 | gradE(1,j) = pt0 * jacinv(1,j) - pt2 * loc.y()*jacinv(2,j); | |
2245 | 6 | gradE(2,j) = (1./mDepthOnLz) * jacinv(2,j); | |
2246 | } | ||
2247 | |||
2248 | Vec3d result; | ||
2249 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
|
8 | for (int i = 0; i < 3; ++i) { |
2250 | 6 | result(i) = d1_is(0) * gradE(0,i) + d1_is(1) * gradE(1,i) + d1_is(2) * gradE(2,i); | |
2251 | } | ||
2252 | |||
2253 | 2 | return result; | |
2254 | |||
2255 | } | ||
2256 | |||
2257 | /// Return the Jacobian Curvature for the linear second map | ||
2258 | ✗ | Mat3d applyIJC(const Mat3d& in) const override { return mSecondMap.applyIJC(in); } | |
2259 | /// Return the Jacobian Curvature: all the second derivatives in range space | ||
2260 | /// @param d2_is second derivative matrix computed in index space | ||
2261 | /// @param d1_is gradient computed in index space | ||
2262 | /// @param ijk the index space location where the result is computed | ||
2263 | 1 | Mat3d applyIJC(const Mat3d& d2_is, const Vec3d& d1_is, const Vec3d& ijk) const override | |
2264 | { | ||
2265 | 1 | const Vec3d loc = applyFrustumMap(ijk); | |
2266 | |||
2267 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | const double s = mGamma * loc.z() + 1.; |
2268 | |||
2269 | // verify that we aren't at the singularity | ||
2270 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (isApproxEqual(s, 0.)) { |
2271 | ✗ | OPENVDB_THROW(ArithmeticError, "Tried to evaluate the frustum transform" | |
2272 | " at the singular focal point (e.g. camera)"); | ||
2273 | } | ||
2274 | |||
2275 | // precompute | ||
2276 | 1 | const double sinv = 1.0/s; // 1/(z*gamma + 1) | |
2277 | 1 | const double pt0 = mLx * sinv; // Lx / (z*gamma +1) | |
2278 | 1 | const double pt1 = mGamma * pt0; // gamma * Lx / ( z*gamma +1) | |
2279 | 1 | const double pt2 = pt1 * sinv; // gamma * Lx / ( z*gamma +1)**2 | |
2280 | 1 | const double pt3 = pt2 * sinv; // gamma * Lx / ( z*gamma +1)**3 | |
2281 | |||
2282 | const Mat3d& jacinv = mSecondMap.getConstJacobianInv(); | ||
2283 | |||
2284 | // compute \frac{\partial^2 E_i}{\partial x_j \partial x_k} | ||
2285 | |||
2286 | 1 | Mat3d matE0(Mat3d::zero()); | |
2287 | 1 | Mat3d matE1(Mat3d::zero()); // matE2 = 0 | |
2288 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
|
4 | for(int j = 0; j < 3; j++) { |
2289 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 3 times.
|
12 | for (int k = 0; k < 3; k++) { |
2290 | |||
2291 | 9 | const double pt4 = 2. * jacinv(2,j) * jacinv(2,k) * pt3; | |
2292 | |||
2293 | 9 | matE0(j,k) = -(jacinv(0,j) * jacinv(2,k) + jacinv(2,j) * jacinv(0,k)) * pt2 + | |
2294 | 9 | pt4 * loc.x(); | |
2295 | |||
2296 | 9 | matE1(j,k) = -(jacinv(1,j) * jacinv(2,k) + jacinv(2,j) * jacinv(1,k)) * pt2 + | |
2297 | 9 | pt4 * loc.y(); | |
2298 | } | ||
2299 | } | ||
2300 | |||
2301 | // compute \frac{\partial E_i}{\partial x_j} | ||
2302 | 1 | Mat3d gradE(Mat3d::zero()); | |
2303 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
|
4 | for (int j = 0; j < 3; ++j ) { |
2304 | 3 | gradE(0,j) = pt0 * jacinv(0,j) - pt2 * loc.x()*jacinv(2,j); | |
2305 | 3 | gradE(1,j) = pt0 * jacinv(1,j) - pt2 * loc.y()*jacinv(2,j); | |
2306 | 3 | gradE(2,j) = (1./mDepthOnLz) * jacinv(2,j); | |
2307 | } | ||
2308 | |||
2309 | 1 | Mat3d result(Mat3d::zero()); | |
2310 | // compute \fac{\partial E_j}{\partial x_m} \fac{\partial E_i}{\partial x_n} | ||
2311 | // \frac{\partial^2 input}{\partial E_i \partial E_j} | ||
2312 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
|
4 | for (int m = 0; m < 3; ++m ) { |
2313 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 3 times.
|
12 | for ( int n = 0; n < 3; ++n) { |
2314 |
2/2✓ Branch 0 taken 27 times.
✓ Branch 1 taken 9 times.
|
36 | for (int i = 0; i < 3; ++i ) { |
2315 |
2/2✓ Branch 0 taken 81 times.
✓ Branch 1 taken 27 times.
|
108 | for (int j = 0; j < 3; ++j) { |
2316 | 81 | result(m, n) += gradE(j, m) * gradE(i, n) * d2_is(i, j); | |
2317 | } | ||
2318 | } | ||
2319 | } | ||
2320 | } | ||
2321 | |||
2322 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
|
4 | for (int m = 0; m < 3; ++m ) { |
2323 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 3 times.
|
12 | for ( int n = 0; n < 3; ++n) { |
2324 | 9 | result(m, n) += | |
2325 | 9 | matE0(m, n) * d1_is(0) + matE1(m, n) * d1_is(1);// + matE2(m, n) * d1_is(2); | |
2326 | } | ||
2327 | } | ||
2328 | |||
2329 | 1 | return result; | |
2330 | } | ||
2331 | |||
2332 | /// Return the determinant of the Jacobian of linear second map | ||
2333 | ✗ | double determinant() const override {return mSecondMap.determinant();} // no implementation | |
2334 | |||
2335 | /// Return the determinate of the Jacobian evaluated at @c loc | ||
2336 | /// @c loc is a location in the pre-image space (e.g., index space) | ||
2337 | ✗ | double determinant(const Vec3d& loc) const override | |
2338 | { | ||
2339 | ✗ | double s = mGamma * loc.z() + 1.0; | |
2340 | ✗ | double frustum_determinant = s * s * mDepthOnLzLxLx; | |
2341 | ✗ | return mSecondMap.determinant() * frustum_determinant; | |
2342 | } | ||
2343 | |||
2344 | /// Return the size of a voxel at the center of the near plane | ||
2345 | 21728 | Vec3d voxelSize() const override | |
2346 | { | ||
2347 | 21728 | const Vec3d loc( 0.5*(mBBox.min().x() + mBBox.max().x()), | |
2348 | 21728 | 0.5*(mBBox.min().y() + mBBox.max().y()), | |
2349 | 21728 | mBBox.min().z()); | |
2350 | |||
2351 | 21728 | return voxelSize(loc); | |
2352 | |||
2353 | } | ||
2354 | |||
2355 | /// @brief Returns the lengths of the images of the three segments | ||
2356 | /// from @a loc to @a loc + (1,0,0), from @a loc to @a loc + (0,1,0) | ||
2357 | /// and from @a loc to @a loc + (0,0,1) | ||
2358 | /// @param loc a location in the pre-image space (e.g., index space) | ||
2359 | 1645249 | Vec3d voxelSize(const Vec3d& loc) const override | |
2360 | { | ||
2361 | 1645249 | Vec3d out, pos = applyMap(loc); | |
2362 | 1645249 | out(0) = (applyMap(loc + Vec3d(1,0,0)) - pos).length(); | |
2363 | 1645249 | out(1) = (applyMap(loc + Vec3d(0,1,0)) - pos).length(); | |
2364 | 1645249 | out(2) = (applyMap(loc + Vec3d(0,0,1)) - pos).length(); | |
2365 | 1645249 | return out; | |
2366 | } | ||
2367 | |||
2368 | ✗ | AffineMap::Ptr getAffineMap() const override { return mSecondMap.getAffineMap(); } | |
2369 | |||
2370 | /// set the taper value, the ratio of nearplane width / far plane width | ||
2371 | void setTaper(double t) { mTaper = t; init();} | ||
2372 | /// Return the taper value. | ||
2373 | ✗ | double getTaper() const { return mTaper; } | |
2374 | /// set the frustum depth: distance between near and far plane = frustm depth * frustm x-width | ||
2375 | void setDepth(double d) { mDepth = d; init();} | ||
2376 | /// Return the unscaled frustm depth | ||
2377 |
1/3✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
1 | double getDepth() const { return mDepth; } |
2378 | // gamma a non-dimensional number: nearplane x-width / camera to near plane distance | ||
2379 | 1 | double getGamma() const { return mGamma; } | |
2380 | |||
2381 | /// Return the bounding box that defines the frustum in pre-image space | ||
2382 |
2/6✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
|
4 | const BBoxd& getBBox() const { return mBBox; } |
2383 | |||
2384 | /// Return MapBase::Ptr& to the second map | ||
2385 | const AffineMap& secondMap() const { return mSecondMap; } | ||
2386 | /// Return @c true if the the bounding box in index space that defines the region that | ||
2387 | /// is maped into the frustum is non-zero, otherwise @c false | ||
2388 | bool isValid() const { return !mBBox.empty();} | ||
2389 | |||
2390 | /// Return @c true if the second map is a uniform scale, Rotation and translation | ||
2391 |
3/6✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
|
3 | bool hasSimpleAffine() const { return mHasSimpleAffine; } |
2392 | |||
2393 | /// read serialization | ||
2394 | ✗ | void read(std::istream& is) override | |
2395 | { | ||
2396 | // for backward compatibility with earlier version | ||
2397 | ✗ | if (io::getFormatVersion(is) < OPENVDB_FILE_VERSION_FLOAT_FRUSTUM_BBOX ) { | |
2398 | ✗ | CoordBBox bb; | |
2399 | ✗ | bb.read(is); | |
2400 | ✗ | mBBox = BBoxd(bb.min().asVec3d(), bb.max().asVec3d()); | |
2401 | } else { | ||
2402 | ✗ | mBBox.read(is); | |
2403 | } | ||
2404 | |||
2405 | ✗ | is.read(reinterpret_cast<char*>(&mTaper), sizeof(double)); | |
2406 | ✗ | is.read(reinterpret_cast<char*>(&mDepth), sizeof(double)); | |
2407 | |||
2408 | // Read the second maps type. | ||
2409 | ✗ | Name type = readString(is); | |
2410 | |||
2411 | // Check if the map has been registered. | ||
2412 | ✗ | if(!MapRegistry::isRegistered(type)) { | |
2413 | ✗ | OPENVDB_THROW(KeyError, "Map " << type << " is not registered"); | |
2414 | } | ||
2415 | |||
2416 | // Create the second map of the type and then read it in. | ||
2417 | ✗ | MapBase::Ptr proxy = math::MapRegistry::createMap(type); | |
2418 | ✗ | proxy->read(is); | |
2419 | ✗ | mSecondMap = *(proxy->getAffineMap()); | |
2420 | ✗ | init(); | |
2421 | } | ||
2422 | |||
2423 | /// write serialization | ||
2424 | ✗ | void write(std::ostream& os) const override | |
2425 | { | ||
2426 | ✗ | mBBox.write(os); | |
2427 | ✗ | os.write(reinterpret_cast<const char*>(&mTaper), sizeof(double)); | |
2428 | ✗ | os.write(reinterpret_cast<const char*>(&mDepth), sizeof(double)); | |
2429 | |||
2430 | ✗ | writeString(os, mSecondMap.type()); | |
2431 | mSecondMap.write(os); | ||
2432 | } | ||
2433 | |||
2434 | /// string serialization, useful for debuging | ||
2435 | ✗ | std::string str() const override | |
2436 | { | ||
2437 | ✗ | std::ostringstream buffer; | |
2438 | ✗ | buffer << " - taper: " << mTaper << std::endl; | |
2439 | ✗ | buffer << " - depth: " << mDepth << std::endl; | |
2440 | ✗ | buffer << " SecondMap: "<< mSecondMap.type() << std::endl; | |
2441 | ✗ | buffer << mSecondMap.str() << std::endl; | |
2442 | ✗ | return buffer.str(); | |
2443 | } | ||
2444 | |||
2445 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
2446 | /// of prepending the given rotation to the linear part of this map | ||
2447 | 1 | MapBase::Ptr preRotate(double radians, Axis axis = X_AXIS) const override | |
2448 | { | ||
2449 | return MapBase::Ptr( | ||
2450 |
2/4✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
|
2 | new NonlinearFrustumMap(mBBox, mTaper, mDepth, mSecondMap.preRotate(radians, axis))); |
2451 | } | ||
2452 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
2453 | /// of prepending the given translation to the linear part of this map | ||
2454 | 2 | MapBase::Ptr preTranslate(const Vec3d& t) const override | |
2455 | { | ||
2456 | return MapBase::Ptr( | ||
2457 |
2/4✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
|
4 | new NonlinearFrustumMap(mBBox, mTaper, mDepth, mSecondMap.preTranslate(t))); |
2458 | } | ||
2459 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
2460 | /// of prepending the given scale to the linear part of this map | ||
2461 | 13 | MapBase::Ptr preScale(const Vec3d& s) const override | |
2462 | { | ||
2463 | return MapBase::Ptr( | ||
2464 |
2/4✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 13 times.
✗ Branch 6 not taken.
|
26 | new NonlinearFrustumMap(mBBox, mTaper, mDepth, mSecondMap.preScale(s))); |
2465 | } | ||
2466 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
2467 | /// of prepending the given shear to the linear part of this map | ||
2468 | 1 | MapBase::Ptr preShear(double shear, Axis axis0, Axis axis1) const override | |
2469 | { | ||
2470 | return MapBase::Ptr(new NonlinearFrustumMap( | ||
2471 |
2/4✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
|
2 | mBBox, mTaper, mDepth, mSecondMap.preShear(shear, axis0, axis1))); |
2472 | } | ||
2473 | |||
2474 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
2475 | /// of appending the given rotation to the linear part of this map. | ||
2476 | 3 | MapBase::Ptr postRotate(double radians, Axis axis = X_AXIS) const override | |
2477 | { | ||
2478 | return MapBase::Ptr( | ||
2479 |
2/4✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
|
6 | new NonlinearFrustumMap(mBBox, mTaper, mDepth, mSecondMap.postRotate(radians, axis))); |
2480 | } | ||
2481 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
2482 | /// of appending the given translation to the linear part of this map. | ||
2483 | 6 | MapBase::Ptr postTranslate(const Vec3d& t) const override | |
2484 | { | ||
2485 | return MapBase::Ptr( | ||
2486 |
2/4✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
|
12 | new NonlinearFrustumMap(mBBox, mTaper, mDepth, mSecondMap.postTranslate(t))); |
2487 | } | ||
2488 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
2489 | /// of appending the given scale to the linear part of this map. | ||
2490 | 1 | MapBase::Ptr postScale(const Vec3d& s) const override | |
2491 | { | ||
2492 | return MapBase::Ptr( | ||
2493 |
2/4✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
|
2 | new NonlinearFrustumMap(mBBox, mTaper, mDepth, mSecondMap.postScale(s))); |
2494 | } | ||
2495 | /// @brief Return a MapBase::Ptr to a new map that is the result | ||
2496 | /// of appending the given shear to the linear part of this map. | ||
2497 | 1 | MapBase::Ptr postShear(double shear, Axis axis0, Axis axis1) const override | |
2498 | { | ||
2499 | return MapBase::Ptr(new NonlinearFrustumMap( | ||
2500 |
2/4✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
|
2 | mBBox, mTaper, mDepth, mSecondMap.postShear(shear, axis0, axis1))); |
2501 | } | ||
2502 | |||
2503 | private: | ||
2504 |
1/2✓ Branch 0 taken 21779 times.
✗ Branch 1 not taken.
|
21779 | void init() |
2505 | { | ||
2506 | // set up as a frustum | ||
2507 |
1/2✓ Branch 0 taken 21779 times.
✗ Branch 1 not taken.
|
21779 | mLx = mBBox.extents().x(); |
2508 |
1/2✓ Branch 0 taken 21779 times.
✗ Branch 1 not taken.
|
21779 | mLy = mBBox.extents().y(); |
2509 |
1/2✓ Branch 0 taken 21779 times.
✗ Branch 1 not taken.
|
21779 | mLz = mBBox.extents().z(); |
2510 | |||
2511 |
3/6✓ Branch 0 taken 21779 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21779 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 21779 times.
|
21779 | if (isApproxEqual(mLx,0.) || isApproxEqual(mLy,0.) || isApproxEqual(mLz,0.) ) { |
2512 | ✗ | OPENVDB_THROW(ArithmeticError, "The index space bounding box" | |
2513 | " must have at least two index points in each direction."); | ||
2514 | } | ||
2515 | |||
2516 | 21779 | mXo = 0.5* mLx; | |
2517 | 21779 | mYo = 0.5* mLy; | |
2518 | |||
2519 | // mDepth is non-dimensionalized on near | ||
2520 | 21779 | mGamma = (1./mTaper - 1) / mDepth; | |
2521 | |||
2522 | 21779 | mDepthOnLz = mDepth/mLz; | |
2523 | 21779 | mDepthOnLzLxLx = mDepthOnLz/(mLx * mLx); | |
2524 | |||
2525 | /// test for shear and non-uniform scale | ||
2526 |
2/2✓ Branch 0 taken 19862 times.
✓ Branch 1 taken 1917 times.
|
21779 | mHasSimpleAffine = true; |
2527 | Vec3d tmp = mSecondMap.voxelSize(); | ||
2528 | |||
2529 | /// false if there is non-uniform scale | ||
2530 |
2/2✓ Branch 0 taken 19862 times.
✓ Branch 1 taken 1917 times.
|
21786 | if (!isApproxEqual(tmp(0), tmp(1))) { mHasSimpleAffine = false; return; } |
2531 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 1910 times.
|
1917 | if (!isApproxEqual(tmp(0), tmp(2))) { mHasSimpleAffine = false; return; } |
2532 | |||
2533 | 1910 | Vec3d trans = mSecondMap.applyMap(Vec3d(0,0,0)); | |
2534 | /// look for shear | ||
2535 | 1910 | Vec3d tmp1 = mSecondMap.applyMap(Vec3d(1,0,0)) - trans; | |
2536 | 1910 | Vec3d tmp2 = mSecondMap.applyMap(Vec3d(0,1,0)) - trans; | |
2537 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1910 times.
|
1910 | Vec3d tmp3 = mSecondMap.applyMap(Vec3d(0,0,1)) - trans; |
2538 | |||
2539 | /// false if there is shear | ||
2540 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1910 times.
|
1910 | if (!isApproxEqual(tmp1.dot(tmp2), 0., 1.e-7)) { mHasSimpleAffine = false; return; } |
2541 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1910 times.
|
1910 | if (!isApproxEqual(tmp2.dot(tmp3), 0., 1.e-7)) { mHasSimpleAffine = false; return; } |
2542 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1910 times.
|
1910 | if (!isApproxEqual(tmp3.dot(tmp1), 0., 1.e-7)) { mHasSimpleAffine = false; return; } |
2543 | } | ||
2544 | |||
2545 | 2499599589 | Vec3d applyFrustumMap(const Vec3d& in) const | |
2546 | { | ||
2547 | |||
2548 | // Move the center of the x-face of the bbox | ||
2549 | // to the origin in index space. | ||
2550 | 2499599589 | Vec3d out(in); | |
2551 | 2499599589 | out = out - mBBox.min(); | |
2552 | 2499599589 | out.x() -= mXo; | |
2553 | 2499599589 | out.y() -= mYo; | |
2554 | |||
2555 | // scale the z-direction on depth / K count | ||
2556 | 2499599589 | out.z() *= mDepthOnLz; | |
2557 | |||
2558 | 2499599589 | double scale = (mGamma * out.z() + 1.)/ mLx; | |
2559 | |||
2560 | // scale the x-y on the length I count and apply tapper | ||
2561 | 2499599589 | out.x() *= scale ; | |
2562 | 2499599589 | out.y() *= scale ; | |
2563 | |||
2564 | 2499599589 | return out; | |
2565 | } | ||
2566 | |||
2567 | 143874285 | Vec3d applyFrustumInverseMap(const Vec3d& in) const | |
2568 | { | ||
2569 | // invert taper and resize: scale = 1/( (z+1)/2 (mt-1) + 1) | ||
2570 | 143874285 | Vec3d out(in); | |
2571 | 143874285 | double invScale = mLx / (mGamma * out.z() + 1.); | |
2572 | 143874285 | out.x() *= invScale; | |
2573 | 143874285 | out.y() *= invScale; | |
2574 | |||
2575 | 143874285 | out.x() += mXo; | |
2576 | 143874285 | out.y() += mYo; | |
2577 | |||
2578 | 143874285 | out.z() /= mDepthOnLz; | |
2579 | |||
2580 | // move back | ||
2581 | 143874285 | out = out + mBBox.min(); | |
2582 | 143874285 | return out; | |
2583 | } | ||
2584 | |||
2585 | // bounding box in index space used in Frustum transforms. | ||
2586 | BBoxd mBBox; | ||
2587 | |||
2588 | // taper value used in constructing Frustums. | ||
2589 | double mTaper; | ||
2590 | double mDepth; | ||
2591 | |||
2592 | // defines the second map | ||
2593 | AffineMap mSecondMap; | ||
2594 | |||
2595 | // these are derived from the above. | ||
2596 | double mLx, mLy, mLz; | ||
2597 | double mXo, mYo, mGamma, mDepthOnLz, mDepthOnLzLxLx; | ||
2598 | |||
2599 | // true: if the mSecondMap is linear and has no shear, and has no non-uniform scale | ||
2600 | bool mHasSimpleAffine; | ||
2601 | }; // class NonlinearFrustumMap | ||
2602 | |||
2603 | |||
2604 | //////////////////////////////////////// | ||
2605 | |||
2606 | |||
2607 | /// @brief Creates the composition of two maps, each of which could be a composition. | ||
2608 | /// In the case that each component of the composition classified as linear an | ||
2609 | /// acceleration AffineMap is stored. | ||
2610 | template<typename FirstMapType, typename SecondMapType> | ||
2611 |
1/4✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
|
4 | class CompoundMap |
2612 | { | ||
2613 | public: | ||
2614 | using MyType = CompoundMap<FirstMapType, SecondMapType>; | ||
2615 | |||
2616 | using Ptr = SharedPtr<MyType>; | ||
2617 | using ConstPtr = SharedPtr<const MyType>; | ||
2618 | |||
2619 | |||
2620 | CompoundMap() { updateAffineMatrix(); } | ||
2621 | |||
2622 | 14 | CompoundMap(const FirstMapType& f, const SecondMapType& s): mFirstMap(f), mSecondMap(s) | |
2623 | { | ||
2624 | 10 | updateAffineMatrix(); | |
2625 | 10 | } | |
2626 | |||
2627 | 12 | CompoundMap(const MyType& other): | |
2628 | 4 | mFirstMap(other.mFirstMap), | |
2629 | mSecondMap(other.mSecondMap), | ||
2630 | 16 | mAffineMap(other.mAffineMap) | |
2631 | 12 | {} | |
2632 | |||
2633 | Name type() const { return mapType(); } | ||
2634 | static Name mapType() | ||
2635 | { | ||
2636 | return (FirstMapType::mapType() + Name(":") + SecondMapType::mapType()); | ||
2637 | } | ||
2638 | |||
2639 | bool operator==(const MyType& other) const | ||
2640 | { | ||
2641 | if (mFirstMap != other.mFirstMap) return false; | ||
2642 | if (mSecondMap != other.mSecondMap) return false; | ||
2643 | if (mAffineMap != other.mAffineMap) return false; | ||
2644 | return true; | ||
2645 | } | ||
2646 | |||
2647 | bool operator!=(const MyType& other) const { return !(*this == other); } | ||
2648 | |||
2649 | MyType& operator=(const MyType& other) | ||
2650 | { | ||
2651 | mFirstMap = other.mFirstMap; | ||
2652 | mSecondMap = other.mSecondMap; | ||
2653 | mAffineMap = other.mAffineMap; | ||
2654 | return *this; | ||
2655 | } | ||
2656 | |||
2657 | bool isIdentity() const | ||
2658 | { | ||
2659 | if (is_linear<MyType>::value) { | ||
2660 | return mAffineMap.isIdentity(); | ||
2661 | } else { | ||
2662 | return mFirstMap.isIdentity()&&mSecondMap.isIdentity(); | ||
2663 | } | ||
2664 | } | ||
2665 | |||
2666 | bool isDiagonal() const { | ||
2667 | if (is_linear<MyType>::value) { | ||
2668 | return mAffineMap.isDiagonal(); | ||
2669 | } else { | ||
2670 | return mFirstMap.isDiagonal()&&mSecondMap.isDiagonal(); | ||
2671 | } | ||
2672 | } | ||
2673 | |||
2674 | 8 | AffineMap::Ptr getAffineMap() const | |
2675 | { | ||
2676 | if (is_linear<MyType>::value) { | ||
2677 | 8 | AffineMap::Ptr affine(new AffineMap(mAffineMap)); | |
2678 | 8 | return affine; | |
2679 | } else { | ||
2680 | OPENVDB_THROW(ArithmeticError, | ||
2681 | "Constant affine matrix representation not possible for this nonlinear map"); | ||
2682 | } | ||
2683 | } | ||
2684 | |||
2685 | // direct decompotion | ||
2686 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | const FirstMapType& firstMap() const { return mFirstMap; } |
2687 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | const SecondMapType& secondMap() const {return mSecondMap; } |
2688 | |||
2689 | void setFirstMap(const FirstMapType& first) { mFirstMap = first; updateAffineMatrix(); } | ||
2690 | void setSecondMap(const SecondMapType& second) { mSecondMap = second; updateAffineMatrix(); } | ||
2691 | |||
2692 | void read(std::istream& is) | ||
2693 | { | ||
2694 | mAffineMap.read(is); | ||
2695 | mFirstMap.read(is); | ||
2696 | mSecondMap.read(is); | ||
2697 | } | ||
2698 | void write(std::ostream& os) const | ||
2699 | { | ||
2700 | mAffineMap.write(os); | ||
2701 | mFirstMap.write(os); | ||
2702 | mSecondMap.write(os); | ||
2703 | } | ||
2704 | |||
2705 | private: | ||
2706 | 10 | void updateAffineMatrix() | |
2707 | { | ||
2708 | if (is_linear<MyType>::value) { | ||
2709 | // both maps need to be linear, these methods are only defined for linear maps | ||
2710 | 10 | AffineMap::Ptr first = mFirstMap.getAffineMap(); | |
2711 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
10 | AffineMap::Ptr second= mSecondMap.getAffineMap(); |
2712 |
2/4✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
|
10 | mAffineMap = AffineMap(*first, *second); |
2713 | } | ||
2714 | 10 | } | |
2715 | |||
2716 | FirstMapType mFirstMap; | ||
2717 | SecondMapType mSecondMap; | ||
2718 | // used for acceleration | ||
2719 | AffineMap mAffineMap; | ||
2720 | }; // class CompoundMap | ||
2721 | |||
2722 | } // namespace math | ||
2723 | } // namespace OPENVDB_VERSION_NAME | ||
2724 | } // namespace openvdb | ||
2725 | |||
2726 | #endif // OPENVDB_MATH_MAPS_HAS_BEEN_INCLUDED | ||
2727 |