// @(#)root/mathcore:$Id$
// Authors: L. Moneta    12/2005

/**********************************************************************
 *                                                                    *
 * Copyright (c) 2005 , LCG ROOT MathLib Team                         *
 *                                                                    *
 *                                                                    *
 **********************************************************************/

// Header file for class LorentzVector
//
// Created by:    moneta   at Fri Dec 02   2005
//
// Last update: $Id$
//
#ifndef ROOT_Math_GenVector_Plane3D
#define ROOT_Math_GenVector_Plane3D  1

#include "Math/GenVector/DisplacementVector3D.h"
#include "Math/GenVector/PositionVector3D.h"



namespace ROOT {

namespace Math {



//_______________________________________________________________________________
   /**
      Class describing a geometrical plane in 3 dimensions.
      A Plane3D is a 2 dimensional surface spanned by two linearly independent vectors.
      The plane is described by the equation
      \f$ a*x + b*y + c*z + d = 0 \f$ where (a,b,c) are the components of the
      normal vector to the plane \f$ n = (a,b,c)  \f$ and \f$ d = - n \dot x \f$, where x is any point
      belonging to plane.
      More information on the mathematics describing a plane in 3D is available on
      <A HREF=http://mathworld.wolfram.com/Plane.html>MathWord</A>.
      The Plane3D class contains the 4 scalar values in double which represent the
      four coefficients, fA, fB, fC, fD. fA, fB, fC are the normal components normalized to 1,
      i.e. fA**2 + fB**2 + fC**2 = 1

      @ingroup GenVector
   */
   class Plane3D {

   public:

      // ------ ctors ------

      typedef double Scalar;

      typedef  DisplacementVector3D<Cartesian3D<double>, DefaultCoordinateSystemTag > Vector;
      typedef  PositionVector3D<Cartesian3D<double>, DefaultCoordinateSystemTag >     Point;



      /**
         default constructor create plane z = 0
      */
      Plane3D ( ) : fA(0), fB(0), fC(1.), fD(0) { }

      /**
       generic constructors from the four scalar values describing the plane
       according to the equation ax + by + cz + d = 0
         \param a scalar value
         \param b scalar value
         \param c scalar value
         \param d sxcalar value
      */
      Plane3D(const Scalar & a, const Scalar & b, const Scalar & c, const Scalar & d);

      /**
       constructor a Plane3D from a normal vector and a point coplanar to the plane
       \param n normal expressed as a ROOT::Math::DisplacementVector3D<Cartesian3D<double> >
       \param p point  expressed as a  ROOT::Math::PositionVector3D<Cartesian3D<double> >
      */
      Plane3D(const Vector & n, const Point & p )
      {
         BuildFromVecAndPoint( n, p );
      }


      /**
       Construct from a generic DisplacementVector3D (normal vector) and PositionVector3D (point coplanar to
       the plane)
       \param n normal expressed as a generic ROOT::Math::DisplacementVector3D
       \param p point  expressed as a generic ROOT::Math::PositionVector3D
      */
      template<class T1, class T2, class U>
      Plane3D( const  DisplacementVector3D<T1,U> & n, const  PositionVector3D<T2,U> & p)
      {
         BuildFromVecAndPoint( Vector(n), Point(p) );
      }

      /**
       constructor from three Cartesian point belonging to the plane
       \param p1 point1  expressed as a generic ROOT::Math::PositionVector3D
       \param p2 point2  expressed as a generic ROOT::Math::PositionVector3D
       \param p3 point3  expressed as a generic ROOT::Math::PositionVector3D
      */
      Plane3D(const Point & p1, const Point & p2, const Point & p3  ) {
         BuildFrom3Points(p1,p2,p3);
      }

      /**
       constructor from three generic point belonging to the plane
       \param p1 point1 expressed as  ROOT::Math::DisplacementVector3D<Cartesian3D<double> >
       \param p2 point2 expressed as  ROOT::Math::DisplacementVector3D<Cartesian3D<double> >
       \param p3 point3 expressed as  ROOT::Math::DisplacementVector3D<Cartesian3D<double> >
      */
      template <class T1, class T2, class T3, class U>
      Plane3D(const  PositionVector3D<T1,U> & p1, const  PositionVector3D<T2,U> & p2, const  PositionVector3D<T3,U> & p3  )
      {
         BuildFrom3Points( Point(p1.X(), p1.Y(), p1.Z()),
                           Point(p2.X(), p2.Y(), p2.Z()),
                           Point(p3.X(), p3.Y(), p3.Z()) );
      }



      // compiler-generated copy ctor and dtor are fine.

      // ------ assignment ------

      /**
         Assignment operator from other Plane3D class
      */
      Plane3D & operator= ( const Plane3D & plane) {
         fA = plane.fA;
         fB = plane.fB;
         fC = plane.fC;
         fD = plane.fD;
         return *this;
      }

      /**
         Return the a coefficient of the plane equation \f$ a*x + b*y + c*z + d = 0 \f$. It is also the
         x-component of the vector perpendicular to the plane.
      */
      Scalar A() { return fA; }

      /**
         Return the b coefficient of the plane equation \f$ a*x + b*y + c*z + d = 0 \f$. It is also the
         y-component of the vector perpendicular to the plane
      */
      Scalar B() { return fB; }

      /**
         Return the c coefficient of the plane equation \f$ a*x + b*y + c*z + d = 0 \f$. It is also the
         z-component of the vector perpendicular to the plane
      */
      Scalar C() { return fC; }

      /**
         Return the d coefficient of the plane equation \f$ a*x + b*y + c*z + d = 0 \f$. It is also
         the distance from the origin (HesseDistance)
      */
      Scalar D() { return fD; }

      /**
         Return normal vector to the plane as Cartesian DisplacementVector
      */
      Vector Normal() const {
         return Vector(fA, fB, fC);
      }

      /**
       Return the Hesse Distance (distance from the origin) of the plane or
       the d coefficient expressed in normalize form
      */
      Scalar HesseDistance() const {
         return fD;
      }


      /**
       Return the signed distance to a Point.
       The distance is signed positive if the Point is in the same side of the
       normal vector to the plane.
       \param p Point expressed in Cartesian Coordinates
       */
      Scalar Distance(const Point & p) const;

      /**
       Return the distance to a Point described with generic coordinates
       \param p Point expressed as generic ROOT::Math::PositionVector3D
       */
      template <class T, class U>
      Scalar Distance(const PositionVector3D<T,U> & p) const {
         return Distance( Point(p.X(), p.Y(), p.Z() ) );
      }

      /**
       Return the projection of a Cartesian point to a plane
       \param p Point expressed as PositionVector3D<Cartesian3D<double> >
       */
      Point ProjectOntoPlane(const Point & p) const;

      /**
       Return the projection of a point to a plane
       \param p Point expressed as generic ROOT::Math::PositionVector3D
       */
      template <class T, class U>
      PositionVector3D<T,U> ProjectOntoPlane(const PositionVector3D<T,U> & p) const {
         Point pxyz = ProjectOntoPlane(Point(p.X(), p.Y(), p.Z() ) );
         PositionVector3D<T,U> p2;
         p2.SetXYZ( pxyz.X(), pxyz.Y(), pxyz.Z() );
         return p2;
      }



      // ------------------- Equality -----------------

      /**
         Exact equality
      */
      bool operator==(const Plane3D & rhs) const {
         return  fA  == rhs.fA &&  fB == rhs.fB  &&  fC == rhs.fC && fD == rhs.fD;
      }
      bool operator!= (const Plane3D & rhs) const {
         return !(operator==(rhs));
      }

   protected:

      /**
         Normalize the normal (a,b,c) plane components
      */
      void Normalize();


   private:

      // internal method to construct class from a vector and a point
      void BuildFromVecAndPoint(const Vector & n, const Point & p);
      // internal method to construct class from 3 points
      void BuildFrom3Points(const Point & p1, const Point & p2, const Point & p3);

      // plane data members the four scalar which  satisfies fA*x + fB*y + fC*z + fD = 0
      // for every point (x,y,z) belonging to the plane.
      // fA**2 + fB**2 + fC** =1 plane is stored in normalized form
      Scalar  fA;
      Scalar  fB;
      Scalar  fC;
      Scalar  fD;


   };  // Plane3D<>

   /**
      Stream Output and Input
   */
   // TODO - I/O should be put in the manipulator form

   std::ostream & operator<< (std::ostream & os, const Plane3D & p);


} // end namespace Math

} // end namespace ROOT


#endif




 Plane3D.h:1
 Plane3D.h:2
 Plane3D.h:3
 Plane3D.h:4
 Plane3D.h:5
 Plane3D.h:6
 Plane3D.h:7
 Plane3D.h:8
 Plane3D.h:9
 Plane3D.h:10
 Plane3D.h:11
 Plane3D.h:12
 Plane3D.h:13
 Plane3D.h:14
 Plane3D.h:15
 Plane3D.h:16
 Plane3D.h:17
 Plane3D.h:18
 Plane3D.h:19
 Plane3D.h:20
 Plane3D.h:21
 Plane3D.h:22
 Plane3D.h:23
 Plane3D.h:24
 Plane3D.h:25
 Plane3D.h:26
 Plane3D.h:27
 Plane3D.h:28
 Plane3D.h:29
 Plane3D.h:30
 Plane3D.h:31
 Plane3D.h:32
 Plane3D.h:33
 Plane3D.h:34
 Plane3D.h:35
 Plane3D.h:36
 Plane3D.h:37
 Plane3D.h:38
 Plane3D.h:39
 Plane3D.h:40
 Plane3D.h:41
 Plane3D.h:42
 Plane3D.h:43
 Plane3D.h:44
 Plane3D.h:45
 Plane3D.h:46
 Plane3D.h:47
 Plane3D.h:48
 Plane3D.h:49
 Plane3D.h:50
 Plane3D.h:51
 Plane3D.h:52
 Plane3D.h:53
 Plane3D.h:54
 Plane3D.h:55
 Plane3D.h:56
 Plane3D.h:57
 Plane3D.h:58
 Plane3D.h:59
 Plane3D.h:60
 Plane3D.h:61
 Plane3D.h:62
 Plane3D.h:63
 Plane3D.h:64
 Plane3D.h:65
 Plane3D.h:66
 Plane3D.h:67
 Plane3D.h:68
 Plane3D.h:69
 Plane3D.h:70
 Plane3D.h:71
 Plane3D.h:72
 Plane3D.h:73
 Plane3D.h:74
 Plane3D.h:75
 Plane3D.h:76
 Plane3D.h:77
 Plane3D.h:78
 Plane3D.h:79
 Plane3D.h:80
 Plane3D.h:81
 Plane3D.h:82
 Plane3D.h:83
 Plane3D.h:84
 Plane3D.h:85
 Plane3D.h:86
 Plane3D.h:87
 Plane3D.h:88
 Plane3D.h:89
 Plane3D.h:90
 Plane3D.h:91
 Plane3D.h:92
 Plane3D.h:93
 Plane3D.h:94
 Plane3D.h:95
 Plane3D.h:96
 Plane3D.h:97
 Plane3D.h:98
 Plane3D.h:99
 Plane3D.h:100
 Plane3D.h:101
 Plane3D.h:102
 Plane3D.h:103
 Plane3D.h:104
 Plane3D.h:105
 Plane3D.h:106
 Plane3D.h:107
 Plane3D.h:108
 Plane3D.h:109
 Plane3D.h:110
 Plane3D.h:111
 Plane3D.h:112
 Plane3D.h:113
 Plane3D.h:114
 Plane3D.h:115
 Plane3D.h:116
 Plane3D.h:117
 Plane3D.h:118
 Plane3D.h:119
 Plane3D.h:120
 Plane3D.h:121
 Plane3D.h:122
 Plane3D.h:123
 Plane3D.h:124
 Plane3D.h:125
 Plane3D.h:126
 Plane3D.h:127
 Plane3D.h:128
 Plane3D.h:129
 Plane3D.h:130
 Plane3D.h:131
 Plane3D.h:132
 Plane3D.h:133
 Plane3D.h:134
 Plane3D.h:135
 Plane3D.h:136
 Plane3D.h:137
 Plane3D.h:138
 Plane3D.h:139
 Plane3D.h:140
 Plane3D.h:141
 Plane3D.h:142
 Plane3D.h:143
 Plane3D.h:144
 Plane3D.h:145
 Plane3D.h:146
 Plane3D.h:147
 Plane3D.h:148
 Plane3D.h:149
 Plane3D.h:150
 Plane3D.h:151
 Plane3D.h:152
 Plane3D.h:153
 Plane3D.h:154
 Plane3D.h:155
 Plane3D.h:156
 Plane3D.h:157
 Plane3D.h:158
 Plane3D.h:159
 Plane3D.h:160
 Plane3D.h:161
 Plane3D.h:162
 Plane3D.h:163
 Plane3D.h:164
 Plane3D.h:165
 Plane3D.h:166
 Plane3D.h:167
 Plane3D.h:168
 Plane3D.h:169
 Plane3D.h:170
 Plane3D.h:171
 Plane3D.h:172
 Plane3D.h:173
 Plane3D.h:174
 Plane3D.h:175
 Plane3D.h:176
 Plane3D.h:177
 Plane3D.h:178
 Plane3D.h:179
 Plane3D.h:180
 Plane3D.h:181
 Plane3D.h:182
 Plane3D.h:183
 Plane3D.h:184
 Plane3D.h:185
 Plane3D.h:186
 Plane3D.h:187
 Plane3D.h:188
 Plane3D.h:189
 Plane3D.h:190
 Plane3D.h:191
 Plane3D.h:192
 Plane3D.h:193
 Plane3D.h:194
 Plane3D.h:195
 Plane3D.h:196
 Plane3D.h:197
 Plane3D.h:198
 Plane3D.h:199
 Plane3D.h:200
 Plane3D.h:201
 Plane3D.h:202
 Plane3D.h:203
 Plane3D.h:204
 Plane3D.h:205
 Plane3D.h:206
 Plane3D.h:207
 Plane3D.h:208
 Plane3D.h:209
 Plane3D.h:210
 Plane3D.h:211
 Plane3D.h:212
 Plane3D.h:213
 Plane3D.h:214
 Plane3D.h:215
 Plane3D.h:216
 Plane3D.h:217
 Plane3D.h:218
 Plane3D.h:219
 Plane3D.h:220
 Plane3D.h:221
 Plane3D.h:222
 Plane3D.h:223
 Plane3D.h:224
 Plane3D.h:225
 Plane3D.h:226
 Plane3D.h:227
 Plane3D.h:228
 Plane3D.h:229
 Plane3D.h:230
 Plane3D.h:231
 Plane3D.h:232
 Plane3D.h:233
 Plane3D.h:234
 Plane3D.h:235
 Plane3D.h:236
 Plane3D.h:237
 Plane3D.h:238
 Plane3D.h:239
 Plane3D.h:240
 Plane3D.h:241
 Plane3D.h:242
 Plane3D.h:243
 Plane3D.h:244
 Plane3D.h:245
 Plane3D.h:246
 Plane3D.h:247
 Plane3D.h:248
 Plane3D.h:249
 Plane3D.h:250
 Plane3D.h:251
 Plane3D.h:252
 Plane3D.h:253
 Plane3D.h:254
 Plane3D.h:255
 Plane3D.h:256
 Plane3D.h:257
 Plane3D.h:258
 Plane3D.h:259
 Plane3D.h:260
 Plane3D.h:261
 Plane3D.h:262
 Plane3D.h:263
 Plane3D.h:264
 Plane3D.h:265
 Plane3D.h:266
 Plane3D.h:267
 Plane3D.h:268
 Plane3D.h:269
 Plane3D.h:270
 Plane3D.h:271