Mantid
Loading...
Searching...
No Matches
Line.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
13#include "MantidKernel/Logger.h"
16#include <boost/optional.hpp>
17
18namespace {
19Mantid::Kernel::Logger logger("Line");
20}
21namespace Mantid::Geometry {
22
24using Kernel::V3D;
25
27 : m_origin(), m_direction()
31{}
32
34 : m_origin(O), m_direction(normalize(D))
38{}
39
45{
46 return new Line(*this);
47}
48
55{
56 return m_origin + m_direction * lambda;
57}
58
59double Line::distance(const Kernel::V3D &A) const
65{
66 const double lambda = m_direction.scalar_prod(A - m_origin);
67 Kernel::V3D L = getPoint(lambda);
68 L -= A;
69 return L.norm();
70}
71
72int Line::isValid(const Kernel::V3D &A) const
80{
81 return (distance(A) > Tolerance) ? 0 : 1;
82}
83
90{
91 m_origin.rotate(MA);
94}
95
101{
102 m_origin += Pt;
103}
104
105int Line::lambdaPair(const int ix, const std::pair<std::complex<double>, std::complex<double>> &SQ, PType &PntOut) const
120{
121 // check results
122 if (ix < 1)
123 return 0;
124
125 boost::optional<Kernel::V3D> Ans1;
126 if (SQ.first.imag() == 0.0 && SQ.first.real() >= 0.0) // +ve roots only
127 {
128 const double lambda = SQ.first.real();
129 Ans1 = getPoint(lambda);
130 PntOut.emplace_back(*Ans1);
131 if (ix < 2) // only one unique root.
132 return 1;
133 }
134 if (SQ.second.imag() == 0.0 && SQ.second.real() >= 0.0) // +ve roots only
135 {
136 const double lambda = SQ.second.real();
137 const Kernel::V3D Ans2 = getPoint(lambda);
138 if (!Ans1) {
139 // first point wasn't good.
140 PntOut.emplace_back(Ans2);
141 return 1;
142 } else if (Ans1->distance(Ans2) < Tolerance) {
143 // If points too close return only 1 item.
144 return 1;
145 }
146 PntOut.emplace_back(Ans2);
147 return 2;
148 }
149 return 0; // both points imaginary
150}
151
152int Line::intersect(PType &VecOut, const Quadratic &Sur) const
161{
162 const std::vector<double> &BN = Sur.copyBaseEqn();
163 const double a(m_origin[0]), b(m_origin[1]), c(m_origin[2]);
164 const double d(m_direction[0]), e(m_direction[1]), f(m_direction[2]);
165 double Coef[3];
166 Coef[0] = BN[0] * d * d + BN[1] * e * e + BN[2] * f * f + BN[3] * d * e + BN[4] * d * f + BN[5] * e * f;
167 Coef[1] = 2 * BN[0] * a * d + 2 * BN[1] * b * e + 2 * BN[2] * c * f + BN[3] * (a * e + b * d) +
168 BN[4] * (a * f + c * d) + BN[5] * (b * f + c * e) + BN[6] * d + BN[7] * e + BN[8] * f;
169 Coef[2] = BN[0] * a * a + BN[1] * b * b + BN[2] * c * c + BN[3] * a * b + BN[4] * a * c + BN[5] * b * c + BN[6] * a +
170 BN[7] * b + BN[8] * c + BN[9];
171
172 std::pair<std::complex<double>, std::complex<double>> SQ;
173 const int ix = solveQuadratic(Coef, SQ);
174 return lambdaPair(ix, SQ, VecOut);
175}
176
177int Line::intersect(PType &PntOut, const Plane &Pln) const
187{
188
189 const double OdotN = m_origin.scalar_prod(Pln.getNormal());
190 const double DdotN = m_direction.scalar_prod(Pln.getNormal());
191 if (fabs(DdotN) < Tolerance) // Plane and line parallel
192 return 0;
193 const double u = (Pln.getDistance() - OdotN) / DdotN;
194 if (u <= 0)
195 return 0;
196 PntOut.emplace_back(getPoint(u));
197 return 1;
198}
199
200int Line::intersect(PType &PntOut, const Cylinder &cylinder) const
210{
211 const Kernel::V3D center = m_origin - cylinder.getCentre();
212 const Kernel::V3D cylinder_axis = cylinder.getNormal();
213 const double radius = cylinder.getRadius();
214 const double vDn = cylinder_axis.scalar_prod(m_direction);
215 const double vDA = cylinder_axis.scalar_prod(center);
216
217 // this is param[0] * x^2 + param[1] * x + param[0]
218 // NOTE: Check the documentation page (concept::GeometryofShape) to learn the
219 // detailed derivation of the following formula.
220 double quadratic_params[3];
221 quadratic_params[0] = 1.0 - (vDn * vDn);
222 quadratic_params[1] = 2.0 * (center.scalar_prod(m_direction) - vDA * vDn);
223 // norm is the distance from the origin to the center of the cylinder
224 quadratic_params[2] = center.norm2() - (radius * radius + vDA * vDA);
225
226 // output parameter
227 std::pair<std::complex<double>, std::complex<double>> roots;
228 // solve the equation of intersection
229 const int num_solutions = solveQuadratic(quadratic_params, roots);
230 // This takes the centre displacement into account:
231 return lambdaPair(num_solutions, roots, PntOut);
232}
233
234int Line::intersect(PType &PntOut, const Sphere &Sph) const
244{
245 // Nasty stripping of useful stuff from sphere
246 const Kernel::V3D Ax = m_origin - Sph.getCentre();
247 const double R = Sph.getRadius();
248 // First solve the equation of intersection
249 double C[3];
250 C[0] = 1;
251 C[1] = 2.0 * Ax.scalar_prod(m_direction);
252 C[2] = Ax.scalar_prod(Ax) - R * R;
253 std::pair<std::complex<double>, std::complex<double>> SQ;
254 const int ix = solveQuadratic(C, SQ);
255 return lambdaPair(ix, SQ, PntOut);
256}
257
258// SETING
259
260int Line::setLine(const Kernel::V3D &O, const Kernel::V3D &D)
268{
269 if (D.nullVector())
270 return 0;
271 m_origin = O;
273 return 1;
274}
275
276void Line::print() const
280{
281 logger.debug() << "Line == " << m_origin << " :: " << m_direction << '\n';
282}
283
284} // namespace Mantid::Geometry
const std::vector< double > * lambda
#define fabs(x)
Definition: Matrix.cpp:22
double radius
Definition: Rasterize.cpp:31
Holds a cylinder as a vector form.
Definition: Cylinder.h:32
Impliments a line.
Definition: Line.h:43
Kernel::V3D m_origin
Orign point (on plane)
Definition: Line.h:70
Kernel::V3D getPoint(const double lambda) const
gets the point O+lam*N
Definition: Line.cpp:49
Kernel::V3D m_direction
Direction of outer surface (Unit Vector)
Definition: Line.h:71
double distance(const Kernel::V3D &) const
distance from line
Definition: Line.cpp:59
int setLine(const Kernel::V3D &, const Kernel::V3D &)
input Origin + direction
Definition: Line.cpp:260
boost::container::small_vector< Kernel::V3D, 5 > PType
Definition: Line.h:45
int intersect(PType &, const Quadratic &) const
For the line that intersects the surfaces add the point(s) to the VecOut, return number of points add...
Definition: Line.cpp:152
int lambdaPair(const int ix, const std::pair< std::complex< double >, std::complex< double > > &SQ, PType &PntOut) const
Helper function to decide which roots to take.
Definition: Line.cpp:105
void print() const
Print statement for debugging.
Definition: Line.cpp:276
Line * clone() const
Virtual copy constructor (not currently used)
Definition: Line.cpp:40
int isValid(const Kernel::V3D &) const
Is the point on the line.
Definition: Line.cpp:72
Line()
Constructor.
Definition: Line.cpp:26
void rotate(const Kernel::Matrix< double > &)
Applies the rotation matrix to the object.
Definition: Line.cpp:84
void displace(const Kernel::V3D &)
Apply a displacement Pt.
Definition: Line.cpp:96
Holds a simple Plane.
Definition: Plane.h:35
Holds a basic quadratic surface.
Definition: Quadratic.h:29
Holds a Sphere as vector form.
Definition: Sphere.h:29
The Logger class is in charge of the publishing messages from the framework through various channels.
Definition: Logger.h:52
Numerical Matrix class.
Definition: Matrix.h:42
Class for 3D vectors.
Definition: V3D.h:34
constexpr double scalar_prod(const V3D &v) const noexcept
Calculates the cross product.
Definition: V3D.h:274
double normalize()
Make a normalized vector (return norm value)
Definition: V3D.cpp:130
void rotate(const Matrix< double > &) noexcept
Rotate a point by a matrix.
Definition: V3D.cpp:217
constexpr double norm2() const noexcept
Vector length squared.
Definition: V3D.h:265
bool nullVector(const double tolerance=1e-3) const noexcept
Determine if the point is null.
Definition: V3D.cpp:241
constexpr double Tolerance
Standard tolerance value.
Definition: Tolerance.h:12
MANTID_KERNEL_DLL V3D normalize(V3D v)
Normalizes a V3D.
Definition: V3D.h:341
MANTID_GEOMETRY_DLL int solveQuadratic(InputIter, std::pair< std::complex< double >, std::complex< double > > &)
Solve a Quadratic equation.
Definition: mathSupport.cpp:23