 ROOT   Reference Guide
Searching...
No Matches
Rotation3D.h
Go to the documentation of this file.
1// @(#)root/mathcore:$Id$
2// Authors: W. Brown, M. Fischler, L. Moneta 2005
3
4 /**********************************************************************
5 * *
6 * Copyright (c) 2005 , LCG ROOT FNAL MathLib Team *
7 * *
8 * *
9 **********************************************************************/
10
11// Header file for class Rotation in 3 dimensions, represented by 3x3 matrix
12//
13// Created by: Mark Fischler Thurs June 9 2005
14//
15// Last update: $Id$
16//
17#ifndef ROOT_Math_GenVector_Rotation3D
18#define ROOT_Math_GenVector_Rotation3D 1
19
20
28
36
37
38#include <algorithm>
39#include <cassert>
40#include <iostream>
41
42
43namespace ROOT {
44namespace Math {
45
46
47//__________________________________________________________________________________________
48 /**
49 Rotation class with the (3D) rotation represented by
50 a 3x3 orthogonal matrix.
51 This is the optimal representation for application to vectors.
53 classes which have conversion operators to Rotation3D.
54
55 All Rotations types (not only Rotation3D) can be applied to all 3D Vector classes
56 (like ROOT::Math::DisplacementVector3D and ROOT::Math::PositionVector3D)
57 and also to the 4D Vectors (ROOT::Math::LorentzVector classes), acting on the 3D components.
58 A rotation operation is applied by using the operator() or the operator *.
59 With the operator * is possible also to combine rotations.
60 Note that the operator is NOT commutative, the order how the rotations are applied is relevant.
61
62 @ingroup GenVector
63 */
64
66
67public:
68
69 typedef double Scalar;
70
72 kXX = 0, kXY = 1, kXZ = 2
73 , kYX = 3, kYY = 4, kYZ = 5
74 , kZX = 6, kZY = 7, kZZ = 8
75 };
76
77 // ========== Constructors and Assignment =====================
78
79 /**
80 Default constructor (identity rotation)
81 */
82 Rotation3D();
83
84 /**
85 Construct given a pair of pointers or iterators defining the
86 beginning and end of an array of nine Scalars
87 */
88 template<class IT>
89 Rotation3D(IT begin, IT end) { SetComponents(begin,end); }
90
91 /**
92 copy constructor
93 */
94 Rotation3D ( Rotation3D const & r ) {
95 *this = r;
96 }
97
98 /**
99 Construct from an AxisAngle
100 */
101 explicit Rotation3D( AxisAngle const & a ) { gv_detail::convert(a, *this); }
102
103 /**
104 Construct from EulerAngles
105 */
106 explicit Rotation3D( EulerAngles const & e ) { gv_detail::convert(e, *this); }
107
108 /**
109 Construct from RotationZYX
110 */
111 explicit Rotation3D( RotationZYX const & e ) { gv_detail::convert(e, *this); }
112
113 /**
114 Construct from a Quaternion
115 */
116 explicit Rotation3D( Quaternion const & q ) { gv_detail::convert(q, *this); }
117
118 /**
119 Construct from an axial rotation
120 */
121 explicit Rotation3D( RotationZ const & r ) { gv_detail::convert(r, *this); }
122 explicit Rotation3D( RotationY const & r ) { gv_detail::convert(r, *this); }
123 explicit Rotation3D( RotationX const & r ) { gv_detail::convert(r, *this); }
124
125 /**
126 Construct from a linear algebra matrix of size at least 3x3,
127 which must support operator()(i,j) to obtain elements (0,0) thru (2,2).
128 Precondition: The matrix is assumed to be orthonormal. No checking
130 */
131 template<class ForeignMatrix>
132 explicit Rotation3D(const ForeignMatrix & m) { SetComponents(m); }
133
134 /**
135 Construct from three orthonormal vectors (which must have methods
136 x(), y() and z()) which will be used as the columns of the rotation
137 matrix. The orthonormality will be checked, and values adjusted
138 so that the result will always be a good rotation matrix.
139 */
140 template<class ForeignVector>
141 Rotation3D(const ForeignVector& v1,
142 const ForeignVector& v2,
143 const ForeignVector& v3 ) { SetComponents(v1, v2, v3); }
144
145 // compiler generated destruuctor is ok
146
147 /**
148 Raw constructor from nine Scalar components (without any checking)
149 */
151 Scalar yx, Scalar yy, Scalar yz,
152 Scalar zx, Scalar zy, Scalar zz)
153 {
154 SetComponents (xx, xy, xz, yx, yy, yz, zx, zy, zz);
155 }
156
157 // need to implement assignment operator to avoid using the templated one
158
159 /**
160 Assignment operator
161 */
162 Rotation3D &
163 operator=( Rotation3D const & rhs ) {
164 SetComponents( rhs.fM, rhs.fM, rhs.fM,
165 rhs.fM, rhs.fM, rhs.fM,
166 rhs.fM, rhs.fM, rhs.fM );
167 return *this;
168 }
169
170 /**
171 Assign from an AxisAngle
172 */
173 Rotation3D &
174 operator=( AxisAngle const & a ) { return operator=(Rotation3D(a)); }
175
176 /**
177 Assign from EulerAngles
178 */
179 Rotation3D &
180 operator=( EulerAngles const & e ) { return operator=(Rotation3D(e)); }
181
182 /**
183 Assign from RotationZYX
184 */
185 Rotation3D &
186 operator=( RotationZYX const & r ) { return operator=(Rotation3D(r)); }
187
188 /**
189 Assign from a Quaternion
190 */
191 Rotation3D &
192 operator=( Quaternion const & q ) {return operator=(Rotation3D(q)); }
193
194 /**
195 Assign from an axial rotation
196 */
197 Rotation3D &
198 operator=( RotationZ const & r ) { return operator=(Rotation3D(r)); }
199 Rotation3D &
200 operator=( RotationY const & r ) { return operator=(Rotation3D(r)); }
201 Rotation3D &
202 operator=( RotationX const & r ) { return operator=(Rotation3D(r)); }
203
204 /**
205 Assign from an orthonormal linear algebra matrix of size 3x3,
206 which must support operator()(i,j) to obtain elements (0,0) thru (2,2).
207 */
208 template<class ForeignMatrix>
209 Rotation3D &
210 operator=(const ForeignMatrix & m) {
211 SetComponents( m(0,0), m(0,1), m(0,2),
212 m(1,0), m(1,1), m(1,2),
213 m(2,0), m(2,1), m(2,2) );
214 return *this;
215 }
216
217 /**
218 Re-adjust components to eliminate small deviations from perfect
219 orthonormality.
220 */
221 void Rectify();
222
223 // ======== Components ==============
224
225 /**
226 Set components from three orthonormal vectors (which must have methods
227 x(), y() and z()) which will be used as the columns of the rotation
228 matrix. The orthonormality will be checked, and values adjusted
229 so that the result will always be a good rotation matrix.
230 */
231 template<class ForeignVector>
232 void
233 SetComponents (const ForeignVector& v1,
234 const ForeignVector& v2,
235 const ForeignVector& v3 ) {
236 fM[kXX]=v1.x(); fM[kXY]=v2.x(); fM[kXZ]=v3.x();
237 fM[kYX]=v1.y(); fM[kYY]=v2.y(); fM[kYZ]=v3.y();
238 fM[kZX]=v1.z(); fM[kZY]=v2.z(); fM[kZZ]=v3.z();
239 Rectify();
240 }
241
242 /**
243 Get components into three vectors which will be the (orthonormal)
244 columns of the rotation matrix. (The vector class must have a
245 constructor from 3 Scalars.)
246 */
247 template<class ForeignVector>
248 void
249 GetComponents ( ForeignVector& v1,
250 ForeignVector& v2,
251 ForeignVector& v3 ) const {
252 v1 = ForeignVector ( fM[kXX], fM[kYX], fM[kZX] );
253 v2 = ForeignVector ( fM[kXY], fM[kYY], fM[kZY] );
254 v3 = ForeignVector ( fM[kXZ], fM[kYZ], fM[kZZ] );
255 }
256
257 /**
258 Set the 9 matrix components given an iterator to the start of
259 the desired data, and another to the end (9 past start).
260 */
261 template<class IT>
262 void SetComponents(IT begin, IT end) {
263 for (int i = 0; i <9; ++i) {
264 fM[i] = *begin;
265 ++begin;
266 }
267 (void)end;
268 assert (end==begin);
269 }
270
271 /**
272 Get the 9 matrix components into data specified by an iterator begin
273 and another to the end of the desired data (9 past start).
274 */
275 template<class IT>
276 void GetComponents(IT begin, IT end) const {
277 for (int i = 0; i <9; ++i) {
278 *begin = fM[i];
279 ++begin;
280 }
281 (void)end;
282 assert (end==begin);
283 }
284
285 /**
286 Get the 9 matrix components into data specified by an iterator begin
287 */
288 template<class IT>
289 void GetComponents(IT begin) const {
290 std::copy ( fM, fM+9, begin );
291 }
292
293 /**
294 Set components from a linear algebra matrix of size at least 3x3,
295 which must support operator()(i,j) to obtain elements (0,0) thru (2,2).
296 Precondition: The matrix is assumed to be orthonormal. NO checking
298 */
299 template<class ForeignMatrix>
300 void
301 SetRotationMatrix (const ForeignMatrix & m) {
302 fM[kXX]=m(0,0); fM[kXY]=m(0,1); fM[kXZ]=m(0,2);
303 fM[kYX]=m(1,0); fM[kYY]=m(1,1); fM[kYZ]=m(1,2);
304 fM[kZX]=m(2,0); fM[kZY]=m(2,1); fM[kZZ]=m(2,2);
305 }
306
307 /**
308 Get components into a linear algebra matrix of size at least 3x3,
310 (0,0) thru (2,2).
311 */
312 template<class ForeignMatrix>
313 void
314 GetRotationMatrix (ForeignMatrix & m) const {
315 m(0,0)=fM[kXX]; m(0,1)=fM[kXY]; m(0,2)=fM[kXZ];
316 m(1,0)=fM[kYX]; m(1,1)=fM[kYY]; m(1,2)=fM[kYZ];
317 m(2,0)=fM[kZX]; m(2,1)=fM[kZY]; m(2,2)=fM[kZZ];
318 }
319
320 /**
321 Set the components from nine scalars -- UNCHECKED for orthonormaility
322 */
323 void
325 Scalar yx, Scalar yy, Scalar yz,
326 Scalar zx, Scalar zy, Scalar zz) {
327 fM[kXX]=xx; fM[kXY]=xy; fM[kXZ]=xz;
328 fM[kYX]=yx; fM[kYY]=yy; fM[kYZ]=yz;
329 fM[kZX]=zx; fM[kZY]=zy; fM[kZZ]=zz;
330 }
331
332 /**
333 Get the nine components into nine scalars
334 */
335 void
337 Scalar &yx, Scalar &yy, Scalar &yz,
338 Scalar &zx, Scalar &zy, Scalar &zz) const {
339 xx=fM[kXX]; xy=fM[kXY]; xz=fM[kXZ];
340 yx=fM[kYX]; yy=fM[kYY]; yz=fM[kYZ];
341 zx=fM[kZX]; zy=fM[kZY]; zz=fM[kZZ];
342 }
343
344 // =========== operations ==============
345
346
347 /**
348 Rotation operation on a displacement vector in any coordinate system
349 */
350 template <class CoordSystem, class U>
354 xyz.SetXYZ( fM[kXX] * v.X() + fM[kXY] * v.Y() + fM[kXZ] * v.Z() ,
355 fM[kYX] * v.X() + fM[kYY] * v.Y() + fM[kYZ] * v.Z() ,
356 fM[kZX] * v.X() + fM[kZY] * v.Y() + fM[kZZ] * v.Z() );
358 }
359
360 /**
361 Rotation operation on a position vector in any coordinate system
362 */
363 template <class CoordSystem, class U>
368 return PositionVector3D<CoordSystem,U> ( rxyz );
369 }
370
371 /**
372 Rotation operation on a Lorentz vector in any spatial coordinate system
373 */
374 template <class CoordSystem>
378 xyz = operator()(xyz);
379 LorentzVector< PxPyPzE4D<double> > xyzt (xyz.X(), xyz.Y(), xyz.Z(), v.E());
380 return LorentzVector<CoordSystem> ( xyzt );
381 }
382
383 /**
384 Rotation operation on an arbitrary vector v.
385 Preconditions: v must implement methods x(), y(), and z()
386 and the arbitrary vector type must have a constructor taking (x,y,z)
387 */
388 template <class ForeignVector>
389 ForeignVector
390 operator() (const ForeignVector & v) const {
393 return ForeignVector ( rxyz.X(), rxyz.Y(), rxyz.Z() );
394 }
395
396 /**
397 Overload operator * for rotation on a vector
398 */
399 template <class AVector>
400 inline
401 AVector operator* (const AVector & v) const
402 {
403 return operator()(v);
404 }
405
406 /**
407 Invert a rotation in place
408 */
409 void Invert();
410
411 /**
412 Return inverse of a rotation
413 */
414 Rotation3D Inverse() const { Rotation3D t(*this); t.Invert(); return t; }
415
416 // ========= Multi-Rotation Operations ===============
417
418 /**
419 Multiply (combine) two rotations
420 */
422 return Rotation3D
423 ( fM[kXX]*r.fM[kXX] + fM[kXY]*r.fM[kYX] + fM[kXZ]*r.fM[kZX]
424 , fM[kXX]*r.fM[kXY] + fM[kXY]*r.fM[kYY] + fM[kXZ]*r.fM[kZY]
425 , fM[kXX]*r.fM[kXZ] + fM[kXY]*r.fM[kYZ] + fM[kXZ]*r.fM[kZZ]
426
427 , fM[kYX]*r.fM[kXX] + fM[kYY]*r.fM[kYX] + fM[kYZ]*r.fM[kZX]
428 , fM[kYX]*r.fM[kXY] + fM[kYY]*r.fM[kYY] + fM[kYZ]*r.fM[kZY]
429 , fM[kYX]*r.fM[kXZ] + fM[kYY]*r.fM[kYZ] + fM[kYZ]*r.fM[kZZ]
430
431 , fM[kZX]*r.fM[kXX] + fM[kZY]*r.fM[kYX] + fM[kZZ]*r.fM[kZX]
432 , fM[kZX]*r.fM[kXY] + fM[kZY]*r.fM[kYY] + fM[kZZ]*r.fM[kZY]
433 , fM[kZX]*r.fM[kXZ] + fM[kZY]*r.fM[kYZ] + fM[kZZ]*r.fM[kZZ] );
434
435 }
436
437
438 /**
439 Multiplication with arbitrary rotations
440 */
441 // note: cannot have a template method since it is ambigous with the operator * on vectors
442
443 Rotation3D operator * (const AxisAngle & a) const;
444 Rotation3D operator * (const EulerAngles & e) const;
445 Rotation3D operator * (const Quaternion & q) const;
446 Rotation3D operator * (const RotationZYX & r) const;
447 Rotation3D operator * (const RotationX & rx) const;
448 Rotation3D operator * (const RotationY & ry) const;
449 Rotation3D operator * (const RotationZ & rz) const;
450
451 /**
452 Post-Multiply (on right) by another rotation : T = T*R
453 */
454 template <class R>
455 Rotation3D & operator *= (const R & r) { return *this = (*this)*r; }
456
457 /**
458 Equality/inequality operators
459 */
460 bool operator == (const Rotation3D & rhs) const {
461 if( fM != rhs.fM ) return false;
462 if( fM != rhs.fM ) return false;
463 if( fM != rhs.fM ) return false;
464 if( fM != rhs.fM ) return false;
465 if( fM != rhs.fM ) return false;
466 if( fM != rhs.fM ) return false;
467 if( fM != rhs.fM ) return false;
468 if( fM != rhs.fM ) return false;
469 if( fM != rhs.fM ) return false;
470 return true;
471 }
472 bool operator != (const Rotation3D & rhs) const {
473 return ! operator==(rhs);
474 }
475
476private:
477
478 Scalar fM; // 9 elements (3x3 matrix) representing the rotation
479
480}; // Rotation3D
481
482// ============ Class Rotation3D ends here ============
483
484/**
485 Distance between two rotations
486 */
487template <class R>
488inline
489typename Rotation3D::Scalar
490Distance ( const Rotation3D& r1, const R & r2) {return gv_detail::dist(r1,r2);}
491
492/**
493 Multiplication of an axial rotation by a Rotation3D
494 */
495Rotation3D operator* (RotationX const & r1, Rotation3D const & r2);
496Rotation3D operator* (RotationY const & r1, Rotation3D const & r2);
497Rotation3D operator* (RotationZ const & r1, Rotation3D const & r2);
498
499/**
500 Multiplication of an axial rotation by another axial Rotation
501 */
502Rotation3D operator* (RotationX const & r1, RotationY const & r2);
503Rotation3D operator* (RotationX const & r1, RotationZ const & r2);
504
505Rotation3D operator* (RotationY const & r1, RotationX const & r2);
506Rotation3D operator* (RotationY const & r1, RotationZ const & r2);
507
508Rotation3D operator* (RotationZ const & r1, RotationX const & r2);
509Rotation3D operator* (RotationZ const & r1, RotationY const & r2);
510
511/**
512 Stream Output and Input
513 */
514 // TODO - I/O should be put in the manipulator form
515
516std::ostream & operator<< (std::ostream & os, const Rotation3D & r);
517
518} // namespace Math
519} // namespace ROOT
520
521#endif // ROOT_Math_GenVector_Rotation3D
ROOT::R::TRInterface & r
Definition Object.C:4
#define a(i)
Definition RSha256.hxx:99
#define e(i)
Definition RSha256.hxx:103
XPoint xy[kMAXMK]
Definition TGX11.cxx:123
float * q
typedef void((*Func_t)())
AxisAngle class describing rotation represented with direction axis (3D Vector) and an angle of rotat...
Definition AxisAngle.h:41
Class describing a generic displacement vector in 3 dimensions.
Scalar X() const
Cartesian X, converting if necessary from internal coordinate system.
Scalar Y() const
Cartesian Y, converting if necessary from internal coordinate system.
DisplacementVector3D< CoordSystem, Tag > & SetXYZ(Scalar a, Scalar b, Scalar c)
set the values of the vector from the cartesian components (x,y,z) (if the vector is held in polar or...
Scalar Z() const
Cartesian Z, converting if necessary from internal coordinate system.
EulerAngles class describing rotation as three angles (Euler Angles).
Definition EulerAngles.h:43
Class describing a generic LorentzVector in the 4D space-time, using the specified coordinate system ...
Class describing a generic position vector (point) in 3 dimensions.
Rotation class with the (3D) rotation represented by a unit quaternion (u, i, j, k).
Definition Quaternion.h:47
Rotation class with the (3D) rotation represented by a 3x3 orthogonal matrix.
Definition Rotation3D.h:65
Rotation3D(AxisAngle const &a)
Construct from an AxisAngle.
Definition Rotation3D.h:101
Rotation3D(RotationZ const &r)
Construct from an axial rotation.
Definition Rotation3D.h:121
void SetComponents(IT begin, IT end)
Set the 9 matrix components given an iterator to the start of the desired data, and another to the en...
Definition Rotation3D.h:262
Rotation3D & operator=(Quaternion const &q)
Assign from a Quaternion.
Definition Rotation3D.h:192
void GetComponents(IT begin) const
Get the 9 matrix components into data specified by an iterator begin.
Definition Rotation3D.h:289
Rotation3D(IT begin, IT end)
Construct given a pair of pointers or iterators defining the beginning and end of an array of nine Sc...
Definition Rotation3D.h:89
Rotation3D(RotationX const &r)
Definition Rotation3D.h:123
void SetComponents(Scalar xx, Scalar xy, Scalar xz, Scalar yx, Scalar yy, Scalar yz, Scalar zx, Scalar zy, Scalar zz)
Set the components from nine scalars – UNCHECKED for orthonormaility.
Definition Rotation3D.h:324
void Rectify()
Re-adjust components to eliminate small deviations from perfect orthonormality.
Rotation3D & operator=(AxisAngle const &a)
Assign from an AxisAngle.
Definition Rotation3D.h:174
void Invert()
Invert a rotation in place.
void SetRotationMatrix(const ForeignMatrix &m)
Set components from a linear algebra matrix of size at least 3x3, which must support operator()(i,...
Definition Rotation3D.h:301
Rotation3D & operator=(Rotation3D const &rhs)
Assignment operator.
Definition Rotation3D.h:163
Rotation3D(RotationY const &r)
Definition Rotation3D.h:122
DisplacementVector3D< CoordSystem, U > operator()(const DisplacementVector3D< CoordSystem, U > &v) const
Rotation operation on a displacement vector in any coordinate system.
Definition Rotation3D.h:352
void GetComponents(ForeignVector &v1, ForeignVector &v2, ForeignVector &v3) const
Get components into three vectors which will be the (orthonormal) columns of the rotation matrix.
Definition Rotation3D.h:249
bool operator!=(const Rotation3D &rhs) const
Definition Rotation3D.h:472
Rotation3D & operator=(RotationZ const &r)
Assign from an axial rotation.
Definition Rotation3D.h:198
Rotation3D Inverse() const
Return inverse of a rotation.
Definition Rotation3D.h:414
Rotation3D & operator=(RotationZYX const &r)
Assign from RotationZYX.
Definition Rotation3D.h:186
Rotation3D(RotationZYX const &e)
Construct from RotationZYX.
Definition Rotation3D.h:111
AVector operator*(const AVector &v) const
Overload operator * for rotation on a vector.
Definition Rotation3D.h:401
Rotation3D(Rotation3D const &r)
copy constructor
Definition Rotation3D.h:94
Rotation3D(Quaternion const &q)
Construct from a Quaternion.
Definition Rotation3D.h:116
void SetComponents(const ForeignVector &v1, const ForeignVector &v2, const ForeignVector &v3)
Set components from three orthonormal vectors (which must have methods x(), y() and z()) which will b...
Definition Rotation3D.h:233
Rotation3D(EulerAngles const &e)
Construct from EulerAngles.
Definition Rotation3D.h:106
void GetComponents(IT begin, IT end) const
Get the 9 matrix components into data specified by an iterator begin and another to the end of the de...
Definition Rotation3D.h:276
Rotation3D(const ForeignVector &v1, const ForeignVector &v2, const ForeignVector &v3)
Construct from three orthonormal vectors (which must have methods x(), y() and z()) which will be use...
Definition Rotation3D.h:141
Rotation3D & operator=(RotationY const &r)
Definition Rotation3D.h:200
Rotation3D()
Default constructor (identity rotation)
void GetRotationMatrix(ForeignMatrix &m) const
Get components into a linear algebra matrix of size at least 3x3, which must support operator()(i,...
Definition Rotation3D.h:314
void GetComponents(Scalar &xx, Scalar &xy, Scalar &xz, Scalar &yx, Scalar &yy, Scalar &yz, Scalar &zx, Scalar &zy, Scalar &zz) const
Get the nine components into nine scalars.
Definition Rotation3D.h:336
Rotation3D(const ForeignMatrix &m)
Construct from a linear algebra matrix of size at least 3x3, which must support operator()(i,...
Definition Rotation3D.h:132
Rotation3D & operator*=(const R &r)
Post-Multiply (on right) by another rotation : T = T*R.
Definition Rotation3D.h:455
Rotation3D(Scalar xx, Scalar xy, Scalar xz, Scalar yx, Scalar yy, Scalar yz, Scalar zx, Scalar zy, Scalar zz)
Raw constructor from nine Scalar components (without any checking)
Definition Rotation3D.h:150
Rotation3D & operator=(EulerAngles const &e)
Assign from EulerAngles.
Definition Rotation3D.h:180
Rotation3D & operator=(const ForeignMatrix &m)
Assign from an orthonormal linear algebra matrix of size 3x3, which must support operator()(i,...
Definition Rotation3D.h:210
Rotation3D & operator=(RotationX const &r)
Definition Rotation3D.h:202
bool operator==(const Rotation3D &rhs) const
Equality/inequality operators.
Definition Rotation3D.h:460
Rotation class representing a 3D rotation about the X axis by the angle of rotation.
Definition RotationX.h:43
Rotation class representing a 3D rotation about the Y axis by the angle of rotation.
Definition RotationY.h:43
Rotation class with the (3D) rotation represented by angles describing first a rotation of an angle p...
Definition RotationZYX.h:61
Rotation class representing a 3D rotation about the Z axis by the angle of rotation.
Definition RotationZ.h:43
Namespace for new Math classes and functions.
double dist(Rotation3D const &r1, Rotation3D const &r2)
void convert(R1 const &, R2 const)
AxisAngle operator*(RotationX const &r1, AxisAngle const &r2)
Multiplication of an axial rotation by an AxisAngle.
AxisAngle::Scalar Distance(const AxisAngle &r1, const R &r2)
Distance between two rotations.
Definition AxisAngle.h:320
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
auto * m
Definition textangle.C:8