Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
Plane3D.h
Go to the documentation of this file.
1 // @(#)root/mathcore:$Id$
2 // Authors: L. Moneta 12/2005
3 
4 /**********************************************************************
5  * *
6  * Copyright (c) 2005 , LCG ROOT MathLib Team *
7  * *
8  * *
9  **********************************************************************/
10 
11 // Header file for class LorentzVector
12 //
13 // Created by: moneta at Fri Dec 02 2005
14 //
15 // Last update: $Id$
16 //
17 #ifndef ROOT_Math_GenVector_Plane3D
18 #define ROOT_Math_GenVector_Plane3D 1
19 
20 #include <type_traits>
21 
24 
25 
26 
27 namespace ROOT {
28 
29 namespace Math {
30 
31 namespace Impl {
32 
33 //_______________________________________________________________________________
34 /**
35  Class describing a geometrical plane in 3 dimensions.
36  A Plane3D is a 2 dimensional surface spanned by two linearly independent vectors.
37  The plane is described by the equation
38  \f$ a*x + b*y + c*z + d = 0 \f$ where (a,b,c) are the components of the
39  normal vector to the plane \f$ n = (a,b,c) \f$ and \f$ d = - n \dot x \f$, where x is any point
40  belonging to plane.
41  More information on the mathematics describing a plane in 3D is available on
42  <A HREF=http://mathworld.wolfram.com/Plane.html>MathWord</A>.
43  The Plane3D class contains the 4 scalar values in T which represent the
44  four coefficients, fA, fB, fC, fD. fA, fB, fC are the normal components normalized to 1,
45  i.e. fA**2 + fB**2 + fC**2 = 1
46 
47  @ingroup GenVector
48 */
49 
50 template <typename T = double>
51 class Plane3D {
52 
53 public:
54  // ------ ctors ------
55 
56  typedef T Scalar;
57 
58  typedef DisplacementVector3D<Cartesian3D<T>, DefaultCoordinateSystemTag> Vector;
59  typedef PositionVector3D<Cartesian3D<T>, DefaultCoordinateSystemTag> Point;
60 
61  /**
62  default constructor create plane z = 0
63  */
64  Plane3D() : fA(0), fB(0), fC(1), fD(0) {}
65 
66  /**
67  generic constructors from the four scalar values describing the plane
68  according to the equation ax + by + cz + d = 0
69  \param a scalar value
70  \param b scalar value
71  \param c scalar value
72  \param d sxcalar value
73  */
74  Plane3D(const Scalar &a, const Scalar &b, const Scalar &c, const Scalar &d) : fA(a), fB(b), fC(c), fD(d)
75  {
76  // renormalize a,b,c to unit
77  Normalize();
78  }
79 
80  /**
81  constructor a Plane3D from a normal vector and a point coplanar to the plane
82  \param n normal expressed as a ROOT::Math::DisplacementVector3D<Cartesian3D<T> >
83  \param p point expressed as a ROOT::Math::PositionVector3D<Cartesian3D<T> >
84  */
85  Plane3D(const Vector &n, const Point &p) { BuildFromVecAndPoint(n, p); }
86 
87  /**
88  Construct from a generic DisplacementVector3D (normal vector) and PositionVector3D (point coplanar to
89  the plane)
90  \param n normal expressed as a generic ROOT::Math::DisplacementVector3D
91  \param p point expressed as a generic ROOT::Math::PositionVector3D
92  */
93  template <class T1, class T2, class U>
94  Plane3D(const DisplacementVector3D<T1, U> &n, const PositionVector3D<T2, U> &p)
95  {
96  BuildFromVecAndPoint(Vector(n), Point(p));
97  }
98 
99  /**
100  constructor from three Cartesian point belonging to the plane
101  \param p1 point1 expressed as a generic ROOT::Math::PositionVector3D
102  \param p2 point2 expressed as a generic ROOT::Math::PositionVector3D
103  \param p3 point3 expressed as a generic ROOT::Math::PositionVector3D
104  */
105  Plane3D(const Point &p1, const Point &p2, const Point &p3) { BuildFrom3Points(p1, p2, p3); }
106 
107  /**
108  constructor from three generic point belonging to the plane
109  \param p1 point1 expressed as ROOT::Math::DisplacementVector3D<Cartesian3D<T> >
110  \param p2 point2 expressed as ROOT::Math::DisplacementVector3D<Cartesian3D<T> >
111  \param p3 point3 expressed as ROOT::Math::DisplacementVector3D<Cartesian3D<T> >
112  */
113  template <class T1, class T2, class T3, class U>
114  Plane3D(const PositionVector3D<T1, U> &p1, const PositionVector3D<T2, U> &p2, const PositionVector3D<T3, U> &p3)
115  {
116  BuildFrom3Points(Point(p1.X(), p1.Y(), p1.Z()), Point(p2.X(), p2.Y(), p2.Z()), Point(p3.X(), p3.Y(), p3.Z()));
117  }
118 
119  // compiler-generated copy ctor and dtor are fine.
120  Plane3D(const Plane3D &) = default;
121 
122  // ------ assignment ------
123 
124  /**
125  Assignment operator from other Plane3D class
126  */
127  Plane3D &operator=(const Plane3D &) = default;
128 
129  /**
130  Return the a coefficient of the plane equation \f$ a*x + b*y + c*z + d = 0 \f$. It is also the
131  x-component of the vector perpendicular to the plane.
132  */
133  Scalar A() const { return fA; }
134 
135  /**
136  Return the b coefficient of the plane equation \f$ a*x + b*y + c*z + d = 0 \f$. It is also the
137  y-component of the vector perpendicular to the plane
138  */
139  Scalar B() const { return fB; }
140 
141  /**
142  Return the c coefficient of the plane equation \f$ a*x + b*y + c*z + d = 0 \f$. It is also the
143  z-component of the vector perpendicular to the plane
144  */
145  Scalar C() const { return fC; }
146 
147  /**
148  Return the d coefficient of the plane equation \f$ a*x + b*y + c*z + d = 0 \f$. It is also
149  the distance from the origin (HesseDistance)
150  */
151  Scalar D() const { return fD; }
152 
153  /**
154  Return normal vector to the plane as Cartesian DisplacementVector
155  */
156  Vector Normal() const { return Vector(fA, fB, fC); }
157 
158  /**
159  Return the Hesse Distance (distance from the origin) of the plane or
160  the d coefficient expressed in normalize form
161  */
162  Scalar HesseDistance() const { return fD; }
163 
164  /**
165  Return the signed distance to a Point.
166  The distance is signed positive if the Point is in the same side of the
167  normal vector to the plane.
168  \param p Point expressed in Cartesian Coordinates
169  */
170  Scalar Distance(const Point &p) const { return fA * p.X() + fB * p.Y() + fC * p.Z() + fD; }
171 
172  /**
173  Return the distance to a Point described with generic coordinates
174  \param p Point expressed as generic ROOT::Math::PositionVector3D
175  */
176  template <class T1, class U>
177  Scalar Distance(const PositionVector3D<T1, U> &p) const
178  {
179  return Distance(Point(p.X(), p.Y(), p.Z()));
180  }
181 
182  /**
183  Return the projection of a Cartesian point to a plane
184  \param p Point expressed as PositionVector3D<Cartesian3D<T> >
185  */
186  Point ProjectOntoPlane(const Point &p) const
187  {
188  const Scalar d = Distance(p);
189  return XYZPoint(p.X() - fA * d, p.Y() - fB * d, p.Z() - fC * d);
190  }
191 
192  /**
193  Return the projection of a point to a plane
194  \param p Point expressed as generic ROOT::Math::PositionVector3D
195  */
196  template <class T1, class U>
197  PositionVector3D<T1, U> ProjectOntoPlane(const PositionVector3D<T1, U> &p) const
198  {
199  const Point pxyz = ProjectOntoPlane(Point(p.X(), p.Y(), p.Z()));
200  return PositionVector3D<T, U>(pxyz.X(), pxyz.Y(), pxyz.Z());
201  }
202 
203  // ------------------- Equality -----------------
204 
205  /**
206  Exact equality
207  */
208  bool operator==(const Plane3D &rhs) const { return (fA == rhs.fA && fB == rhs.fB && fC == rhs.fC && fD == rhs.fD); }
209  bool operator!=(const Plane3D &rhs) const { return !(operator==(rhs)); }
210 
211 protected:
212  /**
213  Normalize the normal (a,b,c) plane components
214  */
215  template <typename SCALAR = T, typename std::enable_if<std::is_arithmetic<SCALAR>::value>::type * = nullptr>
216  void Normalize()
217  {
218  // normalize the plane
219  const SCALAR s = sqrt(fA * fA + fB * fB + fC * fC);
220  // what to do if s = 0 ?
221  if (s == SCALAR(0)) {
222  fD = SCALAR(0);
223  } else {
224  const SCALAR w = Scalar(1) / s;
225  fA *= w;
226  fB *= w;
227  fC *= w;
228  fD *= w;
229  }
230  }
231 
232  /**
233  Normalize the normal (a,b,c) plane components
234  */
235  template <typename SCALAR = T, typename std::enable_if<!std::is_arithmetic<SCALAR>::value>::type * = nullptr>
236  void Normalize()
237  {
238  // normalize the plane
239  SCALAR s = sqrt(fA * fA + fB * fB + fC * fC);
240  // what to do if s = 0 ?
241  const auto m = (s == SCALAR(0));
242  // set zero entries to 1 in the vector to avoid /0 later on
243  s(m) = SCALAR(1);
244  fD(m) = SCALAR(0);
245  const SCALAR w = SCALAR(1) / s;
246  fA *= w;
247  fB *= w;
248  fC *= w;
249  fD *= w;
250  }
251 
252 private:
253  // internal method to construct class from a vector and a point
254  void BuildFromVecAndPoint(const Vector &n, const Point &p)
255  {
256  // build from a normal vector and a point
257  fA = n.X();
258  fB = n.Y();
259  fC = n.Z();
260  fD = -n.Dot(p);
261  Normalize();
262  }
263 
264  // internal method to construct class from 3 points
265  void BuildFrom3Points(const Point &p1, const Point &p2, const Point &p3)
266  {
267  // plane from thre points
268  // normal is (x3-x1) cross (x2 -x1)
269  const Vector n = (p2 - p1).Cross(p3 - p1);
270  fA = n.X();
271  fB = n.Y();
272  fC = n.Z();
273  fD = -n.Dot(p1);
274  Normalize();
275  }
276 
277  // plane data members the four scalar which satisfies fA*x + fB*y + fC*z + fD = 0
278  // for every point (x,y,z) belonging to the plane.
279  // fA**2 + fB**2 + fC** =1 plane is stored in normalized form
280  Scalar fA;
281  Scalar fB;
282  Scalar fC;
283  Scalar fD;
284 
285  }; // Plane3D<>
286 
287  /**
288  Stream Output and Input
289  */
290  // TODO - I/O should be put in the manipulator form
291  template <typename T>
292  std::ostream &operator<<(std::ostream &os, const Plane3D<T> &p)
293  {
294  os << "\n"
295  << p.Normal().X() << " " << p.Normal().Y() << " " << p.Normal().Z() << " " << p.HesseDistance() << "\n";
296  return os;
297  }
298 
299  } // end namespace Impl
300 
301  // typedefs for double and float versions
302  typedef Impl::Plane3D<double> Plane3D;
303  typedef Impl::Plane3D<float> Plane3DF;
304 
305 } // end namespace Math
306 
307 } // end namespace ROOT
308 
309 
310 #endif
311 
312 
313 
314