File indexing completed on 2025-01-18 10:10:11
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #ifndef ROOT_Math_GenVector_Plane3D
0018 #define ROOT_Math_GenVector_Plane3D 1
0019
0020 #include <type_traits>
0021
0022 #include "Math/GenVector/DisplacementVector3D.h"
0023 #include "Math/GenVector/PositionVector3D.h"
0024
0025
0026
0027 namespace ROOT {
0028
0029 namespace Math {
0030
0031 namespace Impl {
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052 template <typename T = double>
0053 class Plane3D {
0054
0055 public:
0056
0057
0058 typedef T Scalar;
0059
0060 typedef DisplacementVector3D<Cartesian3D<T>, DefaultCoordinateSystemTag> Vector;
0061 typedef PositionVector3D<Cartesian3D<T>, DefaultCoordinateSystemTag> Point;
0062
0063
0064
0065
0066 Plane3D() : fA(0), fB(0), fC(1), fD(0) {}
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076 Plane3D(const Scalar &a, const Scalar &b, const Scalar &c, const Scalar &d) : fA(a), fB(b), fC(c), fD(d)
0077 {
0078
0079 Normalize();
0080 }
0081
0082
0083
0084
0085
0086
0087 Plane3D(const Vector &n, const Point &p) { BuildFromVecAndPoint(n, p); }
0088
0089
0090
0091
0092
0093
0094
0095 template <class T1, class T2, class U>
0096 Plane3D(const DisplacementVector3D<T1, U> &n, const PositionVector3D<T2, U> &p)
0097 {
0098 BuildFromVecAndPoint(Vector(n), Point(p));
0099 }
0100
0101
0102
0103
0104
0105
0106
0107 Plane3D(const Point &p1, const Point &p2, const Point &p3) { BuildFrom3Points(p1, p2, p3); }
0108
0109
0110
0111
0112
0113
0114
0115 template <class T1, class T2, class T3, class U>
0116 Plane3D(const PositionVector3D<T1, U> &p1, const PositionVector3D<T2, U> &p2, const PositionVector3D<T3, U> &p3)
0117 {
0118 BuildFrom3Points(Point(p1.X(), p1.Y(), p1.Z()), Point(p2.X(), p2.Y(), p2.Z()), Point(p3.X(), p3.Y(), p3.Z()));
0119 }
0120
0121
0122 Plane3D(const Plane3D &) = default;
0123
0124
0125
0126
0127
0128
0129 Plane3D &operator=(const Plane3D &) = default;
0130
0131
0132
0133
0134
0135 Scalar A() const { return fA; }
0136
0137
0138
0139
0140
0141 Scalar B() const { return fB; }
0142
0143
0144
0145
0146
0147 Scalar C() const { return fC; }
0148
0149
0150
0151
0152
0153 Scalar D() const { return fD; }
0154
0155
0156
0157
0158 Vector Normal() const { return Vector(fA, fB, fC); }
0159
0160
0161
0162
0163
0164 Scalar HesseDistance() const { return fD; }
0165
0166
0167
0168
0169
0170
0171
0172 Scalar Distance(const Point &p) const { return fA * p.X() + fB * p.Y() + fC * p.Z() + fD; }
0173
0174
0175
0176
0177
0178 template <class T1, class U>
0179 Scalar Distance(const PositionVector3D<T1, U> &p) const
0180 {
0181 return Distance(Point(p.X(), p.Y(), p.Z()));
0182 }
0183
0184
0185
0186
0187
0188 Point ProjectOntoPlane(const Point &p) const
0189 {
0190 const Scalar d = Distance(p);
0191 return XYZPoint(p.X() - fA * d, p.Y() - fB * d, p.Z() - fC * d);
0192 }
0193
0194
0195
0196
0197
0198 template <class T1, class U>
0199 PositionVector3D<T1, U> ProjectOntoPlane(const PositionVector3D<T1, U> &p) const
0200 {
0201 const Point pxyz = ProjectOntoPlane(Point(p.X(), p.Y(), p.Z()));
0202 return PositionVector3D<T, U>(pxyz.X(), pxyz.Y(), pxyz.Z());
0203 }
0204
0205
0206
0207
0208
0209
0210 bool operator==(const Plane3D &rhs) const { return (fA == rhs.fA && fB == rhs.fB && fC == rhs.fC && fD == rhs.fD); }
0211 bool operator!=(const Plane3D &rhs) const { return !(operator==(rhs)); }
0212
0213 protected:
0214
0215
0216
0217 template <typename SCALAR = T, typename std::enable_if<std::is_arithmetic<SCALAR>::value>::type * = nullptr>
0218 void Normalize()
0219 {
0220
0221 using std::sqrt;
0222 const SCALAR s = sqrt(fA * fA + fB * fB + fC * fC);
0223
0224 if (s == SCALAR(0)) {
0225 fD = SCALAR(0);
0226 } else {
0227 const SCALAR w = Scalar(1) / s;
0228 fA *= w;
0229 fB *= w;
0230 fC *= w;
0231 fD *= w;
0232 }
0233 }
0234
0235
0236
0237
0238 template <typename SCALAR = T, typename std::enable_if<!std::is_arithmetic<SCALAR>::value>::type * = nullptr>
0239 void Normalize()
0240 {
0241
0242 using std::sqrt;
0243 SCALAR s = sqrt(fA * fA + fB * fB + fC * fC);
0244
0245 const auto m = (s == SCALAR(0));
0246
0247 s(m) = SCALAR(1);
0248 fD(m) = SCALAR(0);
0249 const SCALAR w = SCALAR(1) / s;
0250 fA *= w;
0251 fB *= w;
0252 fC *= w;
0253 fD *= w;
0254 }
0255
0256 private:
0257
0258 void BuildFromVecAndPoint(const Vector &n, const Point &p)
0259 {
0260
0261 fA = n.X();
0262 fB = n.Y();
0263 fC = n.Z();
0264 fD = -n.Dot(p);
0265 Normalize();
0266 }
0267
0268
0269 void BuildFrom3Points(const Point &p1, const Point &p2, const Point &p3)
0270 {
0271
0272
0273 const Vector n = (p2 - p1).Cross(p3 - p1);
0274 fA = n.X();
0275 fB = n.Y();
0276 fC = n.Z();
0277 fD = -n.Dot(p1);
0278 Normalize();
0279 }
0280
0281
0282
0283
0284 Scalar fA;
0285 Scalar fB;
0286 Scalar fC;
0287 Scalar fD;
0288
0289 };
0290
0291
0292
0293
0294
0295 template <typename T>
0296 std::ostream &operator<<(std::ostream &os, const Plane3D<T> &p)
0297 {
0298 os << "\n"
0299 << p.Normal().X() << " " << p.Normal().Y() << " " << p.Normal().Z() << " " << p.HesseDistance() << "\n";
0300 return os;
0301 }
0302
0303 }
0304
0305
0306 typedef Impl::Plane3D<double> Plane3D;
0307 typedef Impl::Plane3D<float> Plane3DF;
0308
0309 }
0310
0311 }
0312
0313
0314 #endif