Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-12 10:08:50

0001 // @(#)root/mathcore:$Id$
0002 // Authors: W. Brown, M. Fischler, L. Moneta    2005
0003 
0004  /**********************************************************************
0005   *                                                                    *
0006   * Copyright (c) 2005 , LCG ROOT MathLib Team and                     *
0007   *                      FNAL LCG ROOT MathLib Team                    *
0008   *                                                                    *
0009   *                                                                    *
0010   **********************************************************************/
0011 
0012 // Header source file for class DisplacementVector2D
0013 //
0014 // Created by: Lorenzo Moneta  at Mon Apr 16 2007
0015 //
0016 
0017 #ifndef ROOT_Math_GenVector_DisplacementVector2D
0018 #define ROOT_Math_GenVector_DisplacementVector2D  1
0019 
0020 #include "Math/GenVector/Cartesian2D.h"
0021 
0022 #include "Math/GenVector/PositionVector2Dfwd.h"
0023 
0024 #include "Math/GenVector/GenVectorIO.h"
0025 
0026 #include "Math/GenVector/BitReproducible.h"
0027 
0028 #include "Math/GenVector/CoordinateSystemTags.h"
0029 
0030 //#include "Math/GenVector/Expression2D.h"
0031 
0032 
0033 
0034 
0035 namespace ROOT {
0036 
0037   namespace Math {
0038 
0039 
0040 
0041 //__________________________________________________________________________________________
0042      /**
0043         Class describing a generic displacement vector in 2 dimensions.
0044         This class is templated on the type of Coordinate system.
0045         One example is the XYVector which is a vector based on
0046         double precision x,y  data members by using the
0047         ROOT::Math::Cartesian2D<double> Coordinate system.
0048         The class is having also an extra template parameter, the coordinate system tag,
0049         to be able to identify (tag) vector described in different reference coordinate system,
0050         like global or local coordinate systems.
0051 
0052         @ingroup GenVector
0053 
0054         @see GenVector
0055      */
0056 
0057      template <class CoordSystem, class Tag = DefaultCoordinateSystemTag >
0058      class DisplacementVector2D {
0059 
0060      public:
0061 
0062         typedef typename CoordSystem::Scalar Scalar;
0063         typedef CoordSystem CoordinateType;
0064         typedef Tag  CoordinateSystemTag;
0065 
0066         // ------ ctors ------
0067 
0068         /**
0069            Default constructor. Construct an empty object with zero values
0070         */
0071         constexpr DisplacementVector2D ( ) :   fCoordinates()  { }
0072 
0073 
0074         /**
0075            Construct from three values of type <em>Scalar</em>.
0076            In the case of a XYVector the values are x,y
0077            In the case of  a polar vector they are r, phi
0078         */
0079         constexpr DisplacementVector2D(Scalar a, Scalar b) :
0080            fCoordinates ( a , b )  { }
0081 
0082         /**
0083            Construct from a displacement vector expressed in different
0084            coordinates, or using a different Scalar type, but with same coordinate system tag
0085         */
0086         template <class OtherCoords>
0087         explicit constexpr DisplacementVector2D( const DisplacementVector2D<OtherCoords, Tag> & v) :
0088            fCoordinates ( v.Coordinates() ) { }
0089 
0090 
0091         /**
0092            Construct from a position vector expressed in different coordinates
0093            but with the same coordinate system tag
0094         */
0095         template <class OtherCoords>
0096         explicit constexpr DisplacementVector2D( const PositionVector2D<OtherCoords,Tag> & p) :
0097            fCoordinates ( p.Coordinates() ) { }
0098 
0099 
0100         /**
0101            Construct from a foreign 2D vector type, for example, Hep2Vector
0102            Precondition: v must implement methods x() and  y()
0103         */
0104         template <class ForeignVector>
0105         explicit constexpr DisplacementVector2D( const ForeignVector & v) :
0106            fCoordinates ( Cartesian2D<Scalar>( v.x(), v.y() ) ) { }
0107 
0108 
0109 
0110         // compiler-generated copy ctor and dtor are fine.
0111 
0112         // ------ assignment ------
0113 
0114         /**
0115            Assignment operator from a displacement vector of arbitrary type
0116         */
0117         template <class OtherCoords>
0118         DisplacementVector2D & operator=
0119         ( const DisplacementVector2D<OtherCoords, Tag> & v) {
0120            fCoordinates = v.Coordinates();
0121            return *this;
0122         }
0123 
0124         /**
0125            Assignment operator from a position vector
0126            (not necessarily efficient unless one or the other is Cartesian)
0127         */
0128         template <class OtherCoords>
0129         DisplacementVector2D & operator=
0130         ( const PositionVector2D<OtherCoords,Tag> & rhs) {
0131            SetXY(rhs.x(), rhs.y() );
0132            return *this;
0133         }
0134 
0135 
0136         /**
0137            Assignment from a foreign 2D vector type, for example, Hep2Vector
0138            Precondition: v must implement methods x() and  y()
0139         */
0140         template <class ForeignVector>
0141         DisplacementVector2D & operator= ( const ForeignVector & v) {
0142            SetXY( v.x(),  v.y()  );
0143            return *this;
0144         }
0145 
0146 
0147         // ------ Set, Get, and access coordinate data ------
0148 
0149         /**
0150            Retrieve a copy of the coordinates object
0151         */
0152         CoordSystem Coordinates() const {
0153            return fCoordinates;
0154         }
0155 
0156         /**
0157            Set internal data based on 2 Scalar numbers.
0158            These are for example (x,y) for a cartesian vector or (r,phi) for a polar vector
0159        */
0160         DisplacementVector2D<CoordSystem, Tag>& SetCoordinates( Scalar a, Scalar b) {
0161            fCoordinates.SetCoordinates(a, b);
0162            return *this;
0163         }
0164 
0165 
0166         /**
0167            get internal data into 2 Scalar numbers.
0168            These are for example (x,y) for a cartesian vector or (r,phi) for a polar vector
0169            \note Alternatively, you may use structured bindings: `auto const [a, b] = v`.
0170         */
0171         void GetCoordinates( Scalar& a, Scalar& b) const
0172         { fCoordinates.GetCoordinates(a, b);  }
0173 
0174 
0175         /**
0176            set the values of the vector from the cartesian components (x,y)
0177            (if the vector is held in polar coordinates,
0178            then (x, y) are converted to that form)
0179         */
0180         DisplacementVector2D<CoordSystem, Tag>& SetXY (Scalar a, Scalar b) {
0181            fCoordinates.SetXY(a,b);
0182            return *this;
0183         }
0184 
0185         // ------------------- Equality -----------------
0186 
0187         /**
0188            Exact equality
0189         */
0190         bool operator==(const DisplacementVector2D & rhs) const {
0191            return fCoordinates==rhs.fCoordinates;
0192         }
0193         bool operator!= (const DisplacementVector2D & rhs) const {
0194            return !(operator==(rhs));
0195         }
0196 
0197         // ------ Individual element access, in various coordinate systems ------
0198 
0199         /**
0200           Dimension
0201         */
0202         unsigned int Dimension() const { return fDimension; };
0203 
0204         /**
0205            Cartesian X, converting if necessary from internal coordinate system.
0206         */
0207         Scalar X() const { return fCoordinates.X(); }
0208 
0209         /**
0210            Cartesian Y, converting if necessary from internal coordinate system.
0211         */
0212         Scalar Y() const { return fCoordinates.Y(); }
0213 
0214 
0215         /**
0216            Polar R, converting if necessary from internal coordinate system.
0217         */
0218         Scalar R() const { return fCoordinates.R(); }
0219 
0220 
0221         /**
0222            Polar phi, converting if necessary from internal coordinate system.
0223         */
0224         Scalar Phi() const { return fCoordinates.Phi(); }
0225 
0226 
0227         // ----- Other fundamental properties -----
0228 
0229         /**
0230            Magnitute squared ( r^2 in spherical coordinate)
0231         */
0232         Scalar Mag2() const { return fCoordinates.Mag2();}
0233 
0234 
0235         /**
0236            return unit vector parallel to this
0237         */
0238         DisplacementVector2D  Unit() const {
0239            Scalar tot = R();
0240            return tot == 0 ? *this : DisplacementVector2D(*this) / tot;
0241         }
0242 
0243         // ------ Setting individual elements present in coordinate system ------
0244 
0245         /**
0246            Change X - Cartesian2D coordinates only
0247         */
0248         DisplacementVector2D<CoordSystem, Tag>& SetX (Scalar a) {
0249            fCoordinates.SetX(a);
0250            return *this;
0251         }
0252 
0253         /**
0254            Change Y - Cartesian2D coordinates only
0255         */
0256         DisplacementVector2D<CoordSystem, Tag>& SetY (Scalar a) {
0257            fCoordinates.SetY(a);
0258            return *this;
0259         }
0260 
0261 
0262         /**
0263            Change R - Polar2D coordinates only
0264         */
0265         DisplacementVector2D<CoordSystem, Tag>& SetR (Scalar a) {
0266            fCoordinates.SetR(a);
0267            return *this;
0268         }
0269 
0270 
0271         /**
0272            Change Phi - Polar2D  coordinates
0273         */
0274         DisplacementVector2D<CoordSystem, Tag>& SetPhi (Scalar ang) {
0275            fCoordinates.SetPhi(ang);
0276            return *this;
0277         }
0278 
0279 
0280 
0281         // ------ Operations combining two vectors ------
0282         // -- need to have the specialized version in order to avoid
0283 
0284         /**
0285            Return the scalar (dot) product of two displacement vectors.
0286            It is possible to perform the product for any type of vector coordinates,
0287            but they must have the same coordinate system tag
0288         */
0289         template< class OtherCoords >
0290         Scalar Dot( const  DisplacementVector2D<OtherCoords,Tag>  & v) const {
0291            return X()*v.X() + Y()*v.Y();
0292         }
0293         /**
0294            Return the scalar (dot) product of two vectors.
0295            It is possible to perform the product for any classes
0296            implementing x() and  y()  member functions
0297         */
0298         template< class OtherVector >
0299         Scalar Dot( const  OtherVector & v) const {
0300            return X()*v.x() + Y()*v.y();
0301         }
0302 
0303 
0304 
0305         /**
0306            Self Addition with a displacement vector.
0307         */
0308         template <class OtherCoords>
0309         DisplacementVector2D & operator+=
0310         (const  DisplacementVector2D<OtherCoords,Tag> & v) {
0311            SetXY(  X() + v.X(), Y() + v.Y() );
0312            return *this;
0313         }
0314 
0315         /**
0316            Self Difference with a displacement vector.
0317         */
0318         template <class OtherCoords>
0319         DisplacementVector2D & operator-=
0320         (const  DisplacementVector2D<OtherCoords,Tag> & v) {
0321            SetXY(  x() - v.x(), y() - v.y() );
0322            return *this;
0323         }
0324 
0325 
0326         /**
0327            multiply this vector by a scalar quantity
0328         */
0329         DisplacementVector2D & operator*= (Scalar a) {
0330            fCoordinates.Scale(a);
0331            return *this;
0332         }
0333 
0334         /**
0335            divide this vector by a scalar quantity
0336         */
0337         DisplacementVector2D & operator/= (Scalar a) {
0338            fCoordinates.Scale(1/a);
0339            return *this;
0340         }
0341 
0342         // -- The following methods (v*a and v/a) could instead be free functions.
0343         // -- They were moved into the class to solve a problem on AIX.
0344 
0345         /**
0346            Multiply a vector by a real number
0347         */
0348         DisplacementVector2D operator * ( Scalar a ) const {
0349            DisplacementVector2D tmp(*this);
0350            tmp *= a;
0351            return tmp;
0352         }
0353 
0354         /**
0355            Negative of the vector
0356         */
0357         DisplacementVector2D operator - ( ) const {
0358            return operator*( Scalar(-1) );
0359         }
0360 
0361         /**
0362            Positive of the vector, return itself
0363         */
0364         DisplacementVector2D operator + ( ) const {return *this;}
0365 
0366         /**
0367            Division of a vector with a real number
0368         */
0369         DisplacementVector2D operator/ (Scalar a) const {
0370            DisplacementVector2D tmp(*this);
0371            tmp /= a;
0372            return tmp;
0373         }
0374 
0375         /**
0376            Rotate by an angle
0377          */
0378         void Rotate( Scalar angle) {
0379            return fCoordinates.Rotate(angle);
0380         }
0381 
0382 
0383         // Methods providing  Limited backward name compatibility with CLHEP
0384 
0385         Scalar x()     const { return fCoordinates.X();     }
0386         Scalar y()     const { return fCoordinates.Y();     }
0387         Scalar r()     const { return fCoordinates.R();     }
0388         Scalar phi()   const { return fCoordinates.Phi();   }
0389         Scalar mag2()  const { return fCoordinates.Mag2();  }
0390         DisplacementVector2D unit() const {return Unit();}
0391 
0392 
0393      private:
0394 
0395         CoordSystem fCoordinates;    // internal coordinate system
0396         static constexpr unsigned int fDimension = CoordinateType::Dimension;
0397 
0398         // the following methods should not compile
0399 
0400         // this should not compile (if from a vector or points with different tag
0401         template <class OtherCoords, class OtherTag>
0402         explicit constexpr DisplacementVector2D( const DisplacementVector2D<OtherCoords, OtherTag> & ) {}
0403 
0404         template <class OtherCoords, class OtherTag>
0405         explicit constexpr DisplacementVector2D( const PositionVector2D<OtherCoords, OtherTag> & ) {}
0406 
0407         template <class OtherCoords, class OtherTag>
0408         DisplacementVector2D & operator=( const DisplacementVector2D<OtherCoords, OtherTag> & );
0409 
0410 
0411         template <class OtherCoords, class OtherTag>
0412         DisplacementVector2D & operator=( const PositionVector2D<OtherCoords, OtherTag> & );
0413 
0414         template <class OtherCoords, class OtherTag>
0415         DisplacementVector2D & operator+=(const  DisplacementVector2D<OtherCoords, OtherTag> & );
0416 
0417         template <class OtherCoords, class OtherTag>
0418         DisplacementVector2D & operator-=(const  DisplacementVector2D<OtherCoords, OtherTag> & );
0419 
0420         template<class OtherCoords, class OtherTag >
0421         Scalar Dot( const  DisplacementVector2D<OtherCoords, OtherTag> &  ) const;
0422 
0423         template<class OtherCoords, class OtherTag >
0424         DisplacementVector2D Cross( const  DisplacementVector2D<OtherCoords, OtherTag> &  ) const;
0425 
0426 
0427      };
0428 
0429 // ---------- DisplacementVector2D class template ends here ------------
0430 // ---------------------------------------------------------------------
0431 
0432 
0433      /**
0434         Addition of DisplacementVector2D vectors.
0435         The (coordinate system) type of the returned vector is defined to
0436         be identical to that of the first vector, which is passed by value
0437      */
0438      template <class CoordSystem1, class CoordSystem2, class U>
0439      inline
0440      DisplacementVector2D<CoordSystem1,U>
0441      operator+(       DisplacementVector2D<CoordSystem1,U> v1,
0442                       const DisplacementVector2D<CoordSystem2,U>  & v2) {
0443         return v1 += v2;
0444      }
0445 
0446      /**
0447         Difference between two DisplacementVector2D vectors.
0448         The (coordinate system) type of the returned vector is defined to
0449         be identical to that of the first vector.
0450      */
0451      template <class CoordSystem1, class CoordSystem2, class U>
0452      inline
0453      DisplacementVector2D<CoordSystem1,U>
0454      operator-( DisplacementVector2D<CoordSystem1,U> v1,
0455                 DisplacementVector2D<CoordSystem2,U> const & v2) {
0456         return v1 -= v2;
0457      }
0458 
0459 
0460 
0461 
0462 
0463      /**
0464         Multiplication of a displacement vector by real number  a*v
0465      */
0466      template <class CoordSystem, class U>
0467      inline
0468      DisplacementVector2D<CoordSystem,U>
0469      operator * ( typename DisplacementVector2D<CoordSystem,U>::Scalar a,
0470                   DisplacementVector2D<CoordSystem,U> v) {
0471         return v *= a;
0472         // Note - passing v by value and using operator *= may save one
0473         // copy relative to passing v by const ref and creating a temporary.
0474      }
0475 
0476 
0477      // v1*v2 notation for Cross product of two vectors is omitted,
0478      // since it is always confusing as to whether dot product is meant.
0479 
0480 
0481 
0482      // ------------- I/O to/from streams -------------
0483 
0484      template< class char_t, class traits_t, class T, class U >
0485      inline
0486      std::basic_ostream<char_t,traits_t> &
0487      operator << ( std::basic_ostream<char_t,traits_t> & os
0488                    , DisplacementVector2D<T,U> const & v
0489         )
0490      {
0491         if( !os )  return os;
0492 
0493         typename T::Scalar a, b;
0494         v.GetCoordinates(a, b);
0495 
0496         if( detail::get_manip( os, detail::bitforbit ) )  {
0497            detail::set_manip( os, detail::bitforbit, '\00' );
0498            typedef GenVector_detail::BitReproducible BR;
0499            BR::Output(os, a);
0500            BR::Output(os, b);
0501         }
0502         else  {
0503            os << detail::get_manip( os, detail::open  ) << a
0504               << detail::get_manip( os, detail::sep   ) << b
0505               << detail::get_manip( os, detail::close );
0506         }
0507 
0508         return os;
0509 
0510      }  // op<< <>()
0511 
0512 
0513      template< class char_t, class traits_t, class T, class U >
0514      inline
0515      std::basic_istream<char_t,traits_t> &
0516      operator >> ( std::basic_istream<char_t,traits_t> & is
0517                    , DisplacementVector2D<T,U> & v
0518         )
0519      {
0520         if( !is )  return is;
0521 
0522         typename T::Scalar a, b;
0523 
0524         if( detail::get_manip( is, detail::bitforbit ) )  {
0525            detail::set_manip( is, detail::bitforbit, '\00' );
0526            typedef GenVector_detail::BitReproducible BR;
0527            BR::Input(is, a);
0528            BR::Input(is, b);
0529         }
0530         else  {
0531            detail::require_delim( is, detail::open  );  is >> a;
0532            detail::require_delim( is, detail::sep   );  is >> b;
0533            detail::require_delim( is, detail::close );
0534         }
0535 
0536         if( is )
0537            v.SetCoordinates(a, b);
0538         return is;
0539 
0540      }  // op>> <>()
0541 
0542      // Structured bindings
0543      template <std::size_t I, class CoordSystem, class Tag>
0544      typename CoordSystem::Scalar get(DisplacementVector2D<CoordSystem, Tag> const& p)
0545      {
0546         static_assert(I < 2);
0547         if constexpr (I == 0) {
0548            return p.x();
0549         } else {
0550            return p.y();
0551         }
0552      }
0553 
0554   }  // namespace Math
0555 
0556 }  // namespace ROOT
0557 
0558 // Structured bindings
0559 #include <tuple>
0560 namespace std {
0561    template <class CoordSystem, class Tag>
0562    struct tuple_size<ROOT::Math::DisplacementVector2D<CoordSystem, Tag>> : integral_constant<size_t, 2> {};
0563    template <size_t I, class CoordSystem, class Tag>
0564    struct tuple_element<I, ROOT::Math::DisplacementVector2D<CoordSystem, Tag>> {
0565       static_assert(I < 2);
0566       using type = typename CoordSystem::Scalar;
0567    };
0568 }
0569 
0570 #endif /* ROOT_Math_GenVector_DisplacementVector2D  */