| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "na64util/transformations.hh" | ||
| 2 | |||
| 3 | #include <unordered_map> | ||
| 4 | #include <cassert> | ||
| 5 | |||
| 6 | namespace na64dp { | ||
| 7 | namespace util { | ||
| 8 | |||
| 9 | const na64sw_RotationOrder gStdRotationOrder | ||
| 10 | = na64sw_Rotation_zyx; // TODO: macro | ||
| 11 | |||
| 12 | template<> Matrix3T<float> | ||
| 13 | 6 | rotation_matrix<float>( na64sw_RotationOrder order, const float * angles ) { | |
| 14 | Matrix3T<float> m; | ||
| 15 | 6 | int rc = na64sw_rotation_matrix_f(order, angles, m.m); | |
| 16 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if(rc) { |
| 17 | ✗ | NA64DP_RUNTIME_ERROR("Couldn't create (float) rotation matrix for" | |
| 18 | " given axes order."); | ||
| 19 | } | ||
| 20 | 6 | return m; | |
| 21 | } | ||
| 22 | |||
| 23 | template<> Matrix3T<double> | ||
| 24 | ✗ | rotation_matrix<double>( na64sw_RotationOrder order, const double * angles ) { | |
| 25 | Matrix3T<double> m; | ||
| 26 | ✗ | int rc = na64sw_rotation_matrix_d(order, angles, m.m); | |
| 27 | ✗ | if(rc) { | |
| 28 | ✗ | NA64DP_RUNTIME_ERROR("Couldn't create (double float) rotation matrix for" | |
| 29 | " given axes order."); | ||
| 30 | } | ||
| 31 | ✗ | return m; | |
| 32 | } | ||
| 33 | |||
| 34 | // | ||
| 35 | // Transformation object implementation | ||
| 36 | |||
| 37 | void | ||
| 38 | 6 | Transformation::_recache_affine_transforms() const { | |
| 39 | 6 | _rotation = util::rotation_matrix(_rotationOrder, _angles); | |
| 40 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 6 times.
|
24 | for(int i = 0; i < 3; ++i) { |
| 41 | 18 | _shearAndScale.cm[i][0] = _u[i]; | |
| 42 | 18 | _shearAndScale.cm[i][1] = _v[i]; | |
| 43 | 18 | _shearAndScale.cm[i][2] = _w[i]; | |
| 44 | } | ||
| 45 | 6 | _affineMatrix = _rotation*_shearAndScale; | |
| 46 | 6 | _cachesValid = true; | |
| 47 | 6 | } | |
| 48 | |||
| 49 | 11 | Transformation::Transformation() | |
| 50 | 11 | : _cachesValid(false) | |
| 51 | 11 | , _rotationOrder(gStdRotationOrder) | |
| 52 | 11 | , _invertOffset(false) | |
| 53 | 11 | , _offset{{0, 0, 0}} | |
| 54 | 11 | , _u{{1, 0, 0}}, _v{{0, 1, 0}}, _w{{0, 0, 1}} | |
| 55 | 11 | , _angles{0, 0, 0} | |
| 56 | 11 | {} | |
| 57 | |||
| 58 | ✗ | Transformation::Transformation(const Transformation & other) | |
| 59 | ✗ | : _cachesValid(false) | |
| 60 | ✗ | , _rotationOrder(other._rotationOrder) | |
| 61 | ✗ | , _invertOffset(other._invertOffset) | |
| 62 | ✗ | , _offset(other._offset) | |
| 63 | ✗ | , _u(other._u), _v(other._v), _w(other._w) | |
| 64 | ✗ | , _angles{other._angles[0], other._angles[1], other._angles[2]} | |
| 65 | ✗ | {} | |
| 66 | |||
| 67 | 1 | Transformation::Transformation( const Vec3 & offset_ | |
| 68 | , const Vec3 & u_, const Vec3 & v_, const Vec3 & w_ | ||
| 69 | , Float_t alpha, Float_t beta, Float_t gamma | ||
| 70 | , na64sw_RotationOrder rotationOrder | ||
| 71 | , bool invertOffset | ||
| 72 | 1 | ) : _cachesValid(false) | |
| 73 | 1 | , _rotationOrder(rotationOrder) | |
| 74 | 1 | , _invertOffset(invertOffset) | |
| 75 | 1 | , _offset(offset_) | |
| 76 | 1 | , _u(u_), _v(v_), _w(w_) | |
| 77 | 1 | , _angles{alpha, beta, gamma} | |
| 78 | 1 | {} | |
| 79 | |||
| 80 | Float_t | ||
| 81 | 9 | Transformation::angle( int i ) const { | |
| 82 |
2/4✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
|
9 | if( i < 0 || i > 2 ) { |
| 83 | ✗ | NA64DP_RUNTIME_ERROR("%d is out of range for transformation angle.", i); | |
| 84 | } | ||
| 85 | 9 | return _angles[i]; | |
| 86 | } | ||
| 87 | |||
| 88 | void | ||
| 89 | 10 | Transformation::angle( int i, Float_t value ) { | |
| 90 |
2/4✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
|
10 | if( i < 0 || i > 2 ) { |
| 91 | ✗ | NA64DP_RUNTIME_ERROR("%d is out of range for transformation angle.", i); | |
| 92 | } | ||
| 93 | 10 | _invalidate_caches(); | |
| 94 | 10 | _angles[i] = value; | |
| 95 | 10 | } | |
| 96 | |||
| 97 | |||
| 98 | const Matrix3 & | ||
| 99 | ✗ | Transformation::rotation_matrix() const { | |
| 100 | ✗ | if(!_cachesValid) _recache_affine_transforms(); | |
| 101 | ✗ | return _rotation; | |
| 102 | } | ||
| 103 | |||
| 104 | const Matrix3 & | ||
| 105 | ✗ | Transformation::basis() const { | |
| 106 | ✗ | if(!_cachesValid) _recache_affine_transforms(); | |
| 107 | ✗ | return _shearAndScale; | |
| 108 | } | ||
| 109 | |||
| 110 | const Matrix3 & | ||
| 111 | 15 | Transformation::affine_matrix() const { | |
| 112 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 9 times.
|
15 | if(!_cachesValid) _recache_affine_transforms(); |
| 113 | 15 | return _affineMatrix; | |
| 114 | } | ||
| 115 | |||
| 116 | |||
| 117 | #if 0 | ||
| 118 | void | ||
| 119 | apply_std_rotation( Vec3 & r | ||
| 120 | , const Float_t rot[3] | ||
| 121 | ) { | ||
| 122 | #if 1 | ||
| 123 | const Float_t s1 = sin(rot[2]), c1 = cos(rot[2]) | ||
| 124 | , s2 = sin(rot[1]), c2 = cos(rot[1]) | ||
| 125 | , s3 = sin(rot[0]), c3 = cos(rot[0]) | ||
| 126 | ; | ||
| 127 | Matrix3 m = {{ {c1*c2, c1*s2*s3 - c3*s1, s1*s3 + c1*c3*s2} | ||
| 128 | , {c2*s1, c1*c3 + s1*s2*s3, c3*s1*s2 - c1*s3} | ||
| 129 | , { -s2, c2*s3, c2*c3} | ||
| 130 | }}; | ||
| 131 | r = m*r; | ||
| 132 | #else | ||
| 133 | //#if defined(ROOT_FOUND) && ROOT_FOUND | ||
| 134 | //r.RotateZ( M_PI * rot[2] / 180 ); | ||
| 135 | //r.RotateY( M_PI * rot[1] / 180 ); | ||
| 136 | //r.RotateX( M_PI * rot[0] / 180 ); | ||
| 137 | //#endif | ||
| 138 | #endif | ||
| 139 | } | ||
| 140 | #endif | ||
| 141 | |||
| 142 | #if 0 | ||
| 143 | void | ||
| 144 | cardinal_vectors( const float center[3] | ||
| 145 | , const float size[3] | ||
| 146 | , const float rot[3] | ||
| 147 | , Vec3 & o | ||
| 148 | , Vec3 & u, Vec3 & v, Vec3 & w | ||
| 149 | ) { | ||
| 150 | o.r[0] = center[0]; o.r[1] = center[1]; o.r[2] = center[2]; | ||
| 151 | u.r[0] = size[0]; u.r[1] = 0.; u.r[2] = 0.; | ||
| 152 | v.r[0] = 0.; v.r[1] = size[1]; v.r[2] = 0.; | ||
| 153 | w.r[0] = 0.; w.r[1] = 0.; w.r[2] = size[2]; | ||
| 154 | |||
| 155 | apply_std_rotation(u, rot); | ||
| 156 | apply_std_rotation(v, rot); | ||
| 157 | apply_std_rotation(w, rot); | ||
| 158 | } | ||
| 159 | #endif | ||
| 160 | |||
| 161 | static std::unordered_map< std::string, std::unordered_map<std::string, float> > | ||
| 162 | _gUnitsByQuantity; | ||
| 163 | |||
| 164 | 1 | static bool _init_units_conversion_table() { | |
| 165 | #define DEFINE_UNITS_ENTRY( name, value, quantity ) \ | ||
| 166 | { auto qIR = _gUnitsByQuantity.emplace(quantity, decltype(_gUnitsByQuantity)::mapped_type()); \ | ||
| 167 | qIR.first->second.emplace( # name, Units:: name ); } | ||
| 168 |
24/24✓ Branch 2 taken 1 times.
✓ Branch 7 taken 1 times.
✓ Branch 11 taken 1 times.
✓ Branch 16 taken 1 times.
✓ Branch 20 taken 1 times.
✓ Branch 25 taken 1 times.
✓ Branch 29 taken 1 times.
✓ Branch 34 taken 1 times.
✓ Branch 38 taken 1 times.
✓ Branch 43 taken 1 times.
✓ Branch 47 taken 1 times.
✓ Branch 52 taken 1 times.
✓ Branch 56 taken 1 times.
✓ Branch 61 taken 1 times.
✓ Branch 65 taken 1 times.
✓ Branch 70 taken 1 times.
✓ Branch 74 taken 1 times.
✓ Branch 79 taken 1 times.
✓ Branch 83 taken 1 times.
✓ Branch 88 taken 1 times.
✓ Branch 92 taken 1 times.
✓ Branch 97 taken 1 times.
✓ Branch 101 taken 1 times.
✓ Branch 106 taken 1 times.
|
1 | NA64SW_FOR_EVERY_UNITS(DEFINE_UNITS_ENTRY) |
| 169 | #undef DEFINE_UNITS_ENTRY | ||
| 170 | 1 | return true; | |
| 171 | } | ||
| 172 | |||
| 173 | static bool _unitConverionTableInitialized | ||
| 174 | = _init_units_conversion_table(); | ||
| 175 | |||
| 176 | float | ||
| 177 | 2 | Units::get_units_conversion_factor( const std::string & strUnitsFrom | |
| 178 | , const std::string & strUnitsToOrQuantity | ||
| 179 | ) { | ||
| 180 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | assert(_unitConverionTableInitialized); |
| 181 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
|
2 | if( strUnitsToOrQuantity.empty() ) { |
| 182 | // look over all the available quantities | ||
| 183 | ✗ | for( const auto & units : _gUnitsByQuantity ) { | |
| 184 | ✗ | auto it = units.second.find(strUnitsFrom); | |
| 185 | ✗ | if( units.second.end() != it ) return 1 / it->second; | |
| 186 | } | ||
| 187 | ✗ | throw errors::UnknownUnit(strUnitsFrom); | |
| 188 | } | ||
| 189 |
1/1✓ Branch 1 taken 2 times.
|
2 | auto qIt = _gUnitsByQuantity.find(strUnitsToOrQuantity); |
| 190 |
2/2✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
|
2 | if(_gUnitsByQuantity.end() != qIt) { |
| 191 | // second argument is quantity => look for the units | ||
| 192 |
1/1✓ Branch 2 taken 1 times.
|
1 | auto it = qIt->second.find(strUnitsFrom); |
| 193 |
1/2✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
|
1 | if(qIt->second.end() != it) return it->second; |
| 194 | ✗ | throw errors::UnknownUnit(strUnitsFrom, strUnitsToOrQuantity); | |
| 195 | } | ||
| 196 | // then both arguments are probably the units => find factors and return | ||
| 197 | // ratio, assuring both are of the same quantity | ||
| 198 |
1/2✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
|
4 | for( const auto & units : _gUnitsByQuantity ) { |
| 199 |
1/1✓ Branch 1 taken 4 times.
|
4 | auto it1 = units.second.find(strUnitsFrom) |
| 200 |
1/1✓ Branch 1 taken 4 times.
|
4 | , it2 = units.second.find(strUnitsToOrQuantity) |
| 201 | ; | ||
| 202 |
2/2✓ Branch 1 taken 3 times.
✓ Branch 2 taken 1 times.
|
4 | if( it1 == it2 ) { |
| 203 |
1/2✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | if(it1 == units.second.end()) continue; |
| 204 | 1 | return 1; | |
| 205 | } | ||
| 206 |
3/6✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
|
1 | if( it1 == units.second.end() || it2 == units.second.end() ) |
| 207 | ✗ | throw errors::QuantityMismatch(strUnitsFrom, strUnitsToOrQuantity); | |
| 208 | 1 | return it1->second / it2->second; | |
| 209 | } | ||
| 210 | ✗ | throw errors::UnknownUnit(strUnitsFrom, strUnitsToOrQuantity); | |
| 211 | } | ||
| 212 | |||
| 213 | |||
| 214 | } // namespace ::na64dp::util | ||
| 215 | } // namespace na64dp | ||
| 216 | |||
| 217 |