// @(#)root/geom:$Id$
// Author: Andrei Gheata   28/04/04

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#ifndef ROOT_TGeoHelix
#define ROOT_TGeoHelix

#include "TObject.h"

class TGeoHMatrix;

class TGeoHelix : public TObject {
private:
   Double_t fC;                   // curvature in XY plane
   Double_t fS;                   // Z step of the helix / 2*PI
   Double_t fStep;                // current step
   Double_t fPhi;                 // phi angle
   Double_t fPointInit[3];        // initial point
   Double_t fDirInit[3];          // normalized initial direction
   Double_t fPoint[3];            // point after a step
   Double_t fDir[3];              // direction after a step
   Double_t fB[3];                // normalized direction for magnetic field
   Int_t fQ;                      // right/left-handed (+/- 1) - "charge"
   TGeoHMatrix *fMatrix{nullptr}; // transformation of local helix frame to MARS

   TGeoHelix(const TGeoHelix &) = delete;
   TGeoHelix &operator=(const TGeoHelix &) = delete;

public:
   enum EGeoHelixTypes { kHelixNeedUpdate = BIT(16), kHelixStraight = BIT(17), kHelixCircle = BIT(18) };
   // constructors
   TGeoHelix();
   TGeoHelix(Double_t curvature, Double_t step, Int_t charge = 1);
   // destructor
   ~TGeoHelix() override;

   void InitPoint(Double_t x0, Double_t y0, Double_t z0);
   void InitPoint(Double_t *point);
   void InitDirection(Double_t dirx, Double_t diry, Double_t dirz, Bool_t is_normalized = kTRUE);
   void InitDirection(Double_t *dir, Bool_t is_normalized = kTRUE);

   Double_t ComputeSafeStep(Double_t epsil = 1E-6) const;
   const Double_t *GetCurrentPoint() const { return fPoint; }
   const Double_t *GetCurrentDirection() const { return fDir; }
   Double_t GetXYcurvature() const { return fC; }
   Double_t GetStep() const { return fStep; }
   Double_t GetTotalCurvature() const;
   Bool_t IsRightHanded() const
   {
      return (fQ > 0) ? kFALSE : kTRUE;
   } // a positive charge in B field makes a left-handed helix

   void ResetStep();
   Double_t StepToPlane(Double_t *point, Double_t *norm);
   //   Double_t       *StepToPlane(Double_t a, Double_t b, Double_t c);

   void SetCharge(Int_t charge);
   void SetXYcurvature(Double_t curvature);
   void SetField(Double_t bx, Double_t by, Double_t bz, Bool_t is_normalized = kTRUE);
   void SetHelixStep(Double_t hstep);

   void Step(Double_t step);

   void UpdateHelix();

   ClassDefOverride(TGeoHelix, 1) // helix class
};

#endif
