Mantid
Loading...
Searching...
No Matches
PeaksOnSurface.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 +
10
11using namespace Mantid::Kernel;
12using VecDouble = std::vector<double>;
13
14namespace Mantid::Crystal {
15
16// Register the algorithm into the AlgorithmFactory
17DECLARE_ALGORITHM(PeaksOnSurface)
18
19//----------------------------------------------------------------------------------------------
22PeaksOnSurface::PeaksOnSurface() : m_extents(6) {}
23
24//----------------------------------------------------------------------------------------------
26const std::string PeaksOnSurface::name() const { return "PeaksOnSurface"; }
27
29int PeaksOnSurface::version() const { return 1; }
30
32const std::string PeaksOnSurface::category() const { return "Crystal\\Peaks"; }
33
34//----------------------------------------------------------------------------------------------
35
36//----------------------------------------------------------------------------------------------
40 this->initBaseProperties();
41
42 auto manditoryExtents = std::make_shared<Mantid::Kernel::MandatoryValidator<std::vector<double>>>();
43
44 declareProperty(std::make_unique<ArrayProperty<double>>("Vertex1", std::vector<double>(), manditoryExtents->clone()),
45 "A comma separated list of cartesian coordinates for the "
46 "lower left vertex of the surface. Values to be specified in "
47 "the CoordinateFrame choosen.");
48
49 declareProperty(std::make_unique<ArrayProperty<double>>("Vertex2", std::vector<double>(), manditoryExtents->clone()),
50 "A comma separated list of cartesian coordinates for the "
51 "upper left vertex of the surface. Values to be specified in "
52 "the CoordinateFrame choosen.");
53
54 declareProperty(std::make_unique<ArrayProperty<double>>("Vertex3", std::vector<double>(), manditoryExtents->clone()),
55 "A comma separated list of cartesian coordinates for the "
56 "upper right vertex of the surface. Values to be specified "
57 "in the CoordinateFrame choosen.");
58
60 std::make_unique<ArrayProperty<double>>("Vertex4", std::vector<double>(), std::move(manditoryExtents)),
61 "A comma separated list of cartesian coordinates for the "
62 "lower right vertex of the surface. Values to be specified "
63 "in the CoordinateFrame choosen.");
64}
65
67 /* Parallelepipid volume should be zero if all points are coplanar.
68 V = |a.(b x c)|
69 */
70
74
75 if (a.scalar_prod(b.cross_prod(c)) != 0) {
76 throw std::invalid_argument("Input vertexes are not coplanar.");
77 }
78
80
81 if (b.norm2() != d.norm2()) {
82 throw std::invalid_argument("Defined surface is not square sided.");
83 }
84}
85
86bool PeaksOnSurface::pointOutsideAnyExtents(const V3D & /*testPoint*/) const { return true; }
87
88bool lineIntersectsSphere(const V3D &line, const V3D &lineStart, const V3D &peakCenter, const double peakRadius) {
89 V3D peakToStart = peakCenter - lineStart;
90 const V3D unitLine = normalize(line);
91 double proj = peakToStart.scalar_prod(unitLine); // All we are doing here is
92 // projecting the peak to
93 // segment start vector onto
94 // the segment itself.
95
96 V3D closestPointOnSegment;
97 if (proj <= 0) // The projection is outside the segment. So use the start
98 // point of the segment.
99 {
100 closestPointOnSegment = lineStart; // Start of line
101 } else if (proj >= line.norm()) // The projection is greater than the segment
102 // length. So use the end point of the
103 // segment.
104 {
105 closestPointOnSegment = lineStart + line; // End of line.
106 } else // The projection falls somewhere between the start and end of the line
107 // segment.
108 {
109 V3D projectionVector = unitLine * proj;
110 closestPointOnSegment = projectionVector + lineStart;
111 }
112
113 return (peakCenter - closestPointOnSegment).norm() <= peakRadius;
114}
115
116bool PeaksOnSurface::pointInsideAllExtents(const V3D &testPoint, const V3D &peakCenter) const {
117 const double peakRadius = getPeakRadius();
118
119 /*
120 Either, the sphere interesects one of the line segments, which define the
121 bounding edges of the surface,
122 OR, the test point lies somewhere on the surface within the extents. We need
123 to check for both.
124
125 The sphere may not necessarily interesect one of the line segments in order to
126 be in contact with the surface, for example, if the peak center as
127 perpendicular to the
128 surface, and the radius such that it only just touched the surface. In this
129 case, no line segments would intersect the sphere.
130 */
131
132 return lineIntersectsSphere(m_line1, m_vertex1, peakCenter, peakRadius) ||
133 lineIntersectsSphere(m_line2, m_vertex2, peakCenter, peakRadius) ||
134 lineIntersectsSphere(m_line3, m_vertex3, peakCenter, peakRadius) ||
135 lineIntersectsSphere(m_line4, m_vertex4, peakCenter, peakRadius) ||
136 (testPoint[0] >= m_extents[0] && testPoint[0] <= m_extents[1] && testPoint[1] >= m_extents[2] &&
137 testPoint[1] <= m_extents[3] && testPoint[2] >= m_extents[4] && testPoint[2] <= m_extents[5]);
138}
139
140void PeaksOnSurface::checkTouchPoint(const V3D &touchPoint, const V3D &normal, const V3D &faceVertex) const {
141 if (normal.scalar_prod(touchPoint - faceVertex) != 0) {
142 throw std::runtime_error("Debugging. Calculation is wrong. touch point should always be on the "
143 "plane!"); // Remove this line later. Check that geometry is setup
144 // properly.
145 }
146}
147
152int PeaksOnSurface::numberOfFaces() const { return 1; }
153
159
162
163 // Face is constructed as follows.
164
165 // p2|---|p3
166 // | |
167 // p1|---|p4
168 //*
169
170 const int numberOfFaces = this->numberOfFaces();
172 faces[0] = {m_vertex1, m_vertex2, m_vertex3}; // These define a face normal
173 // to x at xmin.
174 return faces;
175}
176
178 if (vec.size() != 3) {
179 throw std::invalid_argument("All Vertex parameter arguments must have 3 entries.");
180 }
181 return V3D(vec[0], vec[1], vec[2]);
182}
183
184//----------------------------------------------------------------------------------------------
188 VecDouble vertex1 = this->getProperty("Vertex1");
189 VecDouble vertex2 = this->getProperty("Vertex2");
190 VecDouble vertex3 = this->getProperty("Vertex3");
191 VecDouble vertex4 = this->getProperty("Vertex4");
192
193 // Check vertexes, make a V3D and assign..
194 m_vertex1 = makeV3DFromVector(vertex1);
195 m_vertex2 = makeV3DFromVector(vertex2);
196 m_vertex3 = makeV3DFromVector(vertex3);
197 m_vertex4 = makeV3DFromVector(vertex4);
198
199 // Template method. Validate the extents inputs.
201
202 // Create line segments for boundary calculations.
207
208 // Determine minimum and maximum in x, y and z.
209 using std::max;
210 using std::min;
211 m_extents[0] = min(m_vertex1.X(), min(m_vertex2.X(), min(m_vertex3.X(), m_vertex4.X())));
212 m_extents[1] = max(m_vertex1.X(), max(m_vertex2.X(), max(m_vertex3.X(), m_vertex4.X())));
213 m_extents[2] = min(m_vertex1.Y(), min(m_vertex2.Y(), min(m_vertex3.Y(), m_vertex4.Y())));
214 m_extents[3] = max(m_vertex1.Y(), max(m_vertex2.Y(), max(m_vertex3.Y(), m_vertex4.Y())));
215 m_extents[4] = min(m_vertex1.Z(), min(m_vertex2.Z(), min(m_vertex3.Z(), m_vertex4.Z())));
216 m_extents[5] = max(m_vertex1.Z(), max(m_vertex2.Z(), max(m_vertex3.Z(), m_vertex4.Z())));
217
219}
220
221} // namespace Mantid::Crystal
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
size_t lineStart
Definition: LineProfile.cpp:86
std::vector< double > VecDouble
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
Definition: Algorithm.cpp:1913
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Definition: Algorithm.cpp:2076
void executePeaksIntersection(const bool checkPeakExtents=true)
Run the algorithm.
double getPeakRadius() const
Get the peak radius.
void initBaseProperties()
Initalize the common properties.
PeaksOnSurface : Check peak workspace interaction with a single surface.
Mantid::Kernel::V3D m_vertex1
void validateExtentsInput() const override
Validate the input extents.
int version() const override
Algorithm's version for identification.
std::vector< double > m_extents
Extents.
Mantid::Kernel::V3D m_vertex3
bool pointOutsideAnyExtents(const Mantid::Kernel::V3D &testPoint) const override
Check that a point is outside any of the extents.
Mantid::Kernel::V3D m_vertex2
const std::string category() const override
Algorithm's category for identification.
bool pointInsideAllExtents(const Mantid::Kernel::V3D &testPoint, const Mantid::Kernel::V3D &peakCenter) const override
Check that a point is inside ALL of the extents.
const std::string name() const override
Algorithm's name for identification.
void checkTouchPoint(const Mantid::Kernel::V3D &touchPoint, const Mantid::Kernel::V3D &normal, const Mantid::Kernel::V3D &faceVertex) const override
Verfifies that the normals have been set up correctly such that the touch point falls onto the plane.
VecVecV3D createFaces() const override
Create the faces associated with this shape.
Mantid::Kernel::V3D m_vertex4
int numberOfFaces() const override
Implementation of pure virtual method on PeaksIntersection.
void exec() override
Execute the algorithm.
void init() override
Initialize the algorithm's properties.
Support for a property that holds an array of values.
Definition: ArrayProperty.h:28
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
constexpr double X() const noexcept
Get x.
Definition: V3D.h:232
constexpr V3D cross_prod(const V3D &v) const noexcept
Cross product (this * argument)
Definition: V3D.h:278
constexpr double Y() const noexcept
Get y.
Definition: V3D.h:233
double norm() const noexcept
Definition: V3D.h:263
constexpr double norm2() const noexcept
Vector length squared.
Definition: V3D.h:265
constexpr double Z() const noexcept
Get z.
Definition: V3D.h:234
std::vector< VecV3D > VecVecV3D
V3D makeV3DFromVector(const VecDouble &vec)
bool MANTID_CRYSTAL_DLL lineIntersectsSphere(const Mantid::Kernel::V3D &line, const Mantid::Kernel::V3D &lineStart, const Mantid::Kernel::V3D &peakCenter, const double peakRadius)
Non-member helper function.
MANTID_KERNEL_DLL V3D normalize(V3D v)
Normalizes a V3D.
Definition: V3D.h:341