Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
DisplacementVector2D.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 MathLib Team and *
7  * FNAL LCG ROOT MathLib Team *
8  * *
9  * *
10  **********************************************************************/
11 
12 // Header source file for class DisplacementVector2D
13 //
14 // Created by: Lorenzo Moneta at Mon Apr 16 2007
15 //
16 
17 #ifndef ROOT_Math_GenVector_DisplacementVector2D
18 #define ROOT_Math_GenVector_DisplacementVector2D 1
19 
21 
23 
25 
27 
29 
30 //#include "Math/GenVector/Expression2D.h"
31 
32 
33 
34 
35 namespace ROOT {
36 
37  namespace Math {
38 
39 
40 
41 //__________________________________________________________________________________________
42  /**
43  Class describing a generic displacement vector in 2 dimensions.
44  This class is templated on the type of Coordinate system.
45  One example is the XYVector which is a vector based on
46  double precision x,y data members by using the
47  ROOT::Math::Cartesian2D<double> Coordinate system.
48  The class is having also an extra template parameter, the coordinate system tag,
49  to be able to identify (tag) vector described in different reference coordinate system,
50  like global or local coordinate systems.
51 
52  @ingroup GenVector
53  */
54 
55  template <class CoordSystem, class Tag = DefaultCoordinateSystemTag >
56  class DisplacementVector2D {
57 
58  public:
59 
60  typedef typename CoordSystem::Scalar Scalar;
61  typedef CoordSystem CoordinateType;
62  typedef Tag CoordinateSystemTag;
63 
64  // ------ ctors ------
65 
66  /**
67  Default constructor. Construct an empty object with zero values
68  */
69  DisplacementVector2D ( ) : fCoordinates() { }
70 
71 
72  /**
73  Construct from three values of type <em>Scalar</em>.
74  In the case of a XYVector the values are x,y
75  In the case of a polar vector they are r, phi
76  */
77  DisplacementVector2D(Scalar a, Scalar b) :
78  fCoordinates ( a , b ) { }
79 
80  /**
81  Construct from a displacement vector expressed in different
82  coordinates, or using a different Scalar type, but with same coordinate system tag
83  */
84  template <class OtherCoords>
85  explicit DisplacementVector2D( const DisplacementVector2D<OtherCoords, Tag> & v) :
86  fCoordinates ( v.Coordinates() ) { }
87 
88 
89  /**
90  Construct from a position vector expressed in different coordinates
91  but with the same coordinate system tag
92  */
93  template <class OtherCoords>
94  explicit DisplacementVector2D( const PositionVector2D<OtherCoords,Tag> & p) :
95  fCoordinates ( p.Coordinates() ) { }
96 
97 
98  /**
99  Construct from a foreign 2D vector type, for example, Hep2Vector
100  Precondition: v must implement methods x() and y()
101  */
102  template <class ForeignVector>
103  explicit DisplacementVector2D( const ForeignVector & v) :
104  fCoordinates ( Cartesian2D<Scalar>( v.x(), v.y() ) ) { }
105 
106 
107 
108  // compiler-generated copy ctor and dtor are fine.
109 
110  // ------ assignment ------
111 
112  /**
113  Assignment operator from a displacement vector of arbitrary type
114  */
115  template <class OtherCoords>
116  DisplacementVector2D & operator=
117  ( const DisplacementVector2D<OtherCoords, Tag> & v) {
118  fCoordinates = v.Coordinates();
119  return *this;
120  }
121 
122  /**
123  Assignment operator from a position vector
124  (not necessarily efficient unless one or the other is Cartesian)
125  */
126  template <class OtherCoords>
127  DisplacementVector2D & operator=
128  ( const PositionVector2D<OtherCoords,Tag> & rhs) {
129  SetXY(rhs.x(), rhs.y() );
130  return *this;
131  }
132 
133 
134  /**
135  Assignment from a foreign 2D vector type, for example, Hep2Vector
136  Precondition: v must implement methods x() and y()
137  */
138  template <class ForeignVector>
139  DisplacementVector2D & operator= ( const ForeignVector & v) {
140  SetXY( v.x(), v.y() );
141  return *this;
142  }
143 
144 
145  // ------ Set, Get, and access coordinate data ------
146 
147  /**
148  Retrieve a copy of the coordinates object
149  */
150  CoordSystem Coordinates() const {
151  return fCoordinates;
152  }
153 
154  /**
155  Set internal data based on 2 Scalar numbers.
156  These are for example (x,y) for a cartesian vector or (r,phi) for a polar vector
157  */
158  DisplacementVector2D<CoordSystem, Tag>& SetCoordinates( Scalar a, Scalar b) {
159  fCoordinates.SetCoordinates(a, b);
160  return *this;
161  }
162 
163 
164  /**
165  get internal data into 2 Scalar numbers.
166  These are for example (x,y) for a cartesian vector or (r,phi) for a polar vector
167  */
168  void GetCoordinates( Scalar& a, Scalar& b) const
169  { fCoordinates.GetCoordinates(a, b); }
170 
171 
172  /**
173  set the values of the vector from the cartesian components (x,y)
174  (if the vector is held in polar coordinates,
175  then (x, y) are converted to that form)
176  */
177  DisplacementVector2D<CoordSystem, Tag>& SetXY (Scalar a, Scalar b) {
178  fCoordinates.SetXY(a,b);
179  return *this;
180  }
181 
182  // ------------------- Equality -----------------
183 
184  /**
185  Exact equality
186  */
187  bool operator==(const DisplacementVector2D & rhs) const {
188  return fCoordinates==rhs.fCoordinates;
189  }
190  bool operator!= (const DisplacementVector2D & rhs) const {
191  return !(operator==(rhs));
192  }
193 
194  // ------ Individual element access, in various coordinate systems ------
195 
196  /**
197  Cartesian X, converting if necessary from internal coordinate system.
198  */
199  Scalar X() const { return fCoordinates.X(); }
200 
201  /**
202  Cartesian Y, converting if necessary from internal coordinate system.
203  */
204  Scalar Y() const { return fCoordinates.Y(); }
205 
206 
207  /**
208  Polar R, converting if necessary from internal coordinate system.
209  */
210  Scalar R() const { return fCoordinates.R(); }
211 
212 
213  /**
214  Polar phi, converting if necessary from internal coordinate system.
215  */
216  Scalar Phi() const { return fCoordinates.Phi(); }
217 
218 
219  // ----- Other fundamental properties -----
220 
221  /**
222  Magnitute squared ( r^2 in spherical coordinate)
223  */
224  Scalar Mag2() const { return fCoordinates.Mag2();}
225 
226 
227  /**
228  return unit vector parallel to this
229  */
230  DisplacementVector2D Unit() const {
231  Scalar tot = R();
232  return tot == 0 ? *this : DisplacementVector2D(*this) / tot;
233  }
234 
235  // ------ Setting individual elements present in coordinate system ------
236 
237  /**
238  Change X - Cartesian2D coordinates only
239  */
240  DisplacementVector2D<CoordSystem, Tag>& SetX (Scalar a) {
241  fCoordinates.SetX(a);
242  return *this;
243  }
244 
245  /**
246  Change Y - Cartesian2D coordinates only
247  */
248  DisplacementVector2D<CoordSystem, Tag>& SetY (Scalar a) {
249  fCoordinates.SetY(a);
250  return *this;
251  }
252 
253 
254  /**
255  Change R - Polar2D coordinates only
256  */
257  DisplacementVector2D<CoordSystem, Tag>& SetR (Scalar a) {
258  fCoordinates.SetR(a);
259  return *this;
260  }
261 
262 
263  /**
264  Change Phi - Polar2D coordinates
265  */
266  DisplacementVector2D<CoordSystem, Tag>& SetPhi (Scalar ang) {
267  fCoordinates.SetPhi(ang);
268  return *this;
269  }
270 
271 
272 
273  // ------ Operations combining two vectors ------
274  // -- need to have the specialized version in order to avoid
275 
276  /**
277  Return the scalar (dot) product of two displacement vectors.
278  It is possible to perform the product for any type of vector coordinates,
279  but they must have the same coordinate system tag
280  */
281  template< class OtherCoords >
282  Scalar Dot( const DisplacementVector2D<OtherCoords,Tag> & v) const {
283  return X()*v.X() + Y()*v.Y();
284  }
285  /**
286  Return the scalar (dot) product of two vectors.
287  It is possible to perform the product for any classes
288  implementing x() and y() member functions
289  */
290  template< class OtherVector >
291  Scalar Dot( const OtherVector & v) const {
292  return X()*v.x() + Y()*v.y();
293  }
294 
295 
296 
297  /**
298  Self Addition with a displacement vector.
299  */
300  template <class OtherCoords>
301  DisplacementVector2D & operator+=
302  (const DisplacementVector2D<OtherCoords,Tag> & v) {
303  SetXY( X() + v.X(), Y() + v.Y() );
304  return *this;
305  }
306 
307  /**
308  Self Difference with a displacement vector.
309  */
310  template <class OtherCoords>
311  DisplacementVector2D & operator-=
312  (const DisplacementVector2D<OtherCoords,Tag> & v) {
313  SetXY( x() - v.x(), y() - v.y() );
314  return *this;
315  }
316 
317 
318  /**
319  multiply this vector by a scalar quantity
320  */
321  DisplacementVector2D & operator*= (Scalar a) {
322  fCoordinates.Scale(a);
323  return *this;
324  }
325 
326  /**
327  divide this vector by a scalar quantity
328  */
329  DisplacementVector2D & operator/= (Scalar a) {
330  fCoordinates.Scale(1/a);
331  return *this;
332  }
333 
334  // -- The following methods (v*a and v/a) could instead be free functions.
335  // -- They were moved into the class to solve a problem on AIX.
336 
337  /**
338  Multiply a vector by a real number
339  */
340  DisplacementVector2D operator * ( Scalar a ) const {
341  DisplacementVector2D tmp(*this);
342  tmp *= a;
343  return tmp;
344  }
345 
346  /**
347  Negative of the vector
348  */
349  DisplacementVector2D operator - ( ) const {
350  return operator*( Scalar(-1) );
351  }
352 
353  /**
354  Positive of the vector, return itself
355  */
356  DisplacementVector2D operator + ( ) const {return *this;}
357 
358  /**
359  Division of a vector with a real number
360  */
361  DisplacementVector2D operator/ (Scalar a) const {
362  DisplacementVector2D tmp(*this);
363  tmp /= a;
364  return tmp;
365  }
366 
367  /**
368  Rotate by an angle
369  */
370  void Rotate( Scalar angle) {
371  return fCoordinates.Rotate(angle);
372  }
373 
374 
375  // Methods providing Limited backward name compatibility with CLHEP
376 
377  Scalar x() const { return fCoordinates.X(); }
378  Scalar y() const { return fCoordinates.Y(); }
379  Scalar r() const { return fCoordinates.R(); }
380  Scalar phi() const { return fCoordinates.Phi(); }
381  Scalar mag2() const { return fCoordinates.Mag2(); }
382  DisplacementVector2D unit() const {return Unit();}
383 
384 
385  private:
386 
387  CoordSystem fCoordinates; // internal coordinate system
388 
389 
390  // the following methods should not compile
391 
392  // this should not compile (if from a vector or points with different tag
393  template <class OtherCoords, class OtherTag>
394  explicit DisplacementVector2D( const DisplacementVector2D<OtherCoords, OtherTag> & ) {}
395 
396  template <class OtherCoords, class OtherTag>
397  explicit DisplacementVector2D( const PositionVector2D<OtherCoords, OtherTag> & ) {}
398 
399  template <class OtherCoords, class OtherTag>
400  DisplacementVector2D & operator=( const DisplacementVector2D<OtherCoords, OtherTag> & );
401 
402 
403  template <class OtherCoords, class OtherTag>
404  DisplacementVector2D & operator=( const PositionVector2D<OtherCoords, OtherTag> & );
405 
406  template <class OtherCoords, class OtherTag>
407  DisplacementVector2D & operator+=(const DisplacementVector2D<OtherCoords, OtherTag> & );
408 
409  template <class OtherCoords, class OtherTag>
410  DisplacementVector2D & operator-=(const DisplacementVector2D<OtherCoords, OtherTag> & );
411 
412  template<class OtherCoords, class OtherTag >
413  Scalar Dot( const DisplacementVector2D<OtherCoords, OtherTag> & ) const;
414 
415  template<class OtherCoords, class OtherTag >
416  DisplacementVector2D Cross( const DisplacementVector2D<OtherCoords, OtherTag> & ) const;
417 
418 
419  };
420 
421 // ---------- DisplacementVector2D class template ends here ------------
422 // ---------------------------------------------------------------------
423 
424 
425  /**
426  Addition of DisplacementVector2D vectors.
427  The (coordinate system) type of the returned vector is defined to
428  be identical to that of the first vector, which is passed by value
429  */
430  template <class CoordSystem1, class CoordSystem2, class U>
431  inline
432  DisplacementVector2D<CoordSystem1,U>
433  operator+( DisplacementVector2D<CoordSystem1,U> v1,
434  const DisplacementVector2D<CoordSystem2,U> & v2) {
435  return v1 += v2;
436  }
437 
438  /**
439  Difference between two DisplacementVector2D vectors.
440  The (coordinate system) type of the returned vector is defined to
441  be identical to that of the first vector.
442  */
443  template <class CoordSystem1, class CoordSystem2, class U>
444  inline
445  DisplacementVector2D<CoordSystem1,U>
446  operator-( DisplacementVector2D<CoordSystem1,U> v1,
447  DisplacementVector2D<CoordSystem2,U> const & v2) {
448  return v1 -= v2;
449  }
450 
451 
452 
453 
454 
455  /**
456  Multiplication of a displacement vector by real number a*v
457  */
458  template <class CoordSystem, class U>
459  inline
460  DisplacementVector2D<CoordSystem,U>
461  operator * ( typename DisplacementVector2D<CoordSystem,U>::Scalar a,
462  DisplacementVector2D<CoordSystem,U> v) {
463  return v *= a;
464  // Note - passing v by value and using operator *= may save one
465  // copy relative to passing v by const ref and creating a temporary.
466  }
467 
468 
469  // v1*v2 notation for Cross product of two vectors is omitted,
470  // since it is always confusing as to whether dot product is meant.
471 
472 
473 
474  // ------------- I/O to/from streams -------------
475 
476  template< class char_t, class traits_t, class T, class U >
477  inline
478  std::basic_ostream<char_t,traits_t> &
479  operator << ( std::basic_ostream<char_t,traits_t> & os
480  , DisplacementVector2D<T,U> const & v
481  )
482  {
483  if( !os ) return os;
484 
485  typename T::Scalar a, b;
486  v.GetCoordinates(a, b);
487 
488  if( detail::get_manip( os, detail::bitforbit ) ) {
489  detail::set_manip( os, detail::bitforbit, '\00' );
490  typedef GenVector_detail::BitReproducible BR;
491  BR::Output(os, a);
492  BR::Output(os, b);
493  }
494  else {
495  os << detail::get_manip( os, detail::open ) << a
496  << detail::get_manip( os, detail::sep ) << b
497  << detail::get_manip( os, detail::close );
498  }
499 
500  return os;
501 
502  } // op<< <>()
503 
504 
505  template< class char_t, class traits_t, class T, class U >
506  inline
507  std::basic_istream<char_t,traits_t> &
508  operator >> ( std::basic_istream<char_t,traits_t> & is
509  , DisplacementVector2D<T,U> & v
510  )
511  {
512  if( !is ) return is;
513 
514  typename T::Scalar a, b;
515 
516  if( detail::get_manip( is, detail::bitforbit ) ) {
517  detail::set_manip( is, detail::bitforbit, '\00' );
518  typedef GenVector_detail::BitReproducible BR;
519  BR::Input(is, a);
520  BR::Input(is, b);
521  }
522  else {
523  detail::require_delim( is, detail::open ); is >> a;
524  detail::require_delim( is, detail::sep ); is >> b;
525  detail::require_delim( is, detail::close );
526  }
527 
528  if( is )
529  v.SetCoordinates(a, b);
530  return is;
531 
532  } // op>> <>()
533 
534 
535 
536  } // namespace Math
537 
538 } // namespace ROOT
539 
540 
541 #endif /* ROOT_Math_GenVector_DisplacementVector2D */
542