-
Notifications
You must be signed in to change notification settings - Fork 122
/
PeaksInRegion.cpp
177 lines (146 loc) · 6.67 KB
/
PeaksInRegion.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
#include "MantidCrystal/PeaksInRegion.h"
#include "MantidKernel/ArrayProperty.h"
#include "MantidKernel/MandatoryValidator.h"
#include "MantidKernel/EnabledWhenProperty.h"
using namespace Mantid::Kernel;
using namespace Mantid::API;
namespace Mantid {
namespace Crystal {
// Register the algorithm into the AlgorithmFactory
DECLARE_ALGORITHM(PeaksInRegion)
//----------------------------------------------------------------------------------------------
/// Algorithm's name for identification. @see Algorithm::name
const std::string PeaksInRegion::name() const { return "PeaksInRegion"; }
/// Algorithm's version for identification. @see Algorithm::version
int PeaksInRegion::version() const { return 1; }
/// Algorithm's category for identification. @see Algorithm::category
const std::string PeaksInRegion::category() const { return "Crystal\\Peaks"; }
//----------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------
/** Initialize the algorithm's properties.
*/
void PeaksInRegion::init() {
declareProperty(
make_unique<PropertyWithValue<bool>>("CheckPeakExtents", false),
"Include any peak in the region that has a shape extent "
"extending into that region.");
this->initBaseProperties();
auto mandatoryExtents = boost::make_shared<
Mantid::Kernel::MandatoryValidator<std::vector<double>>>();
std::vector<double> extents(2, 0);
extents[0] = -50;
extents[1] = +50;
declareProperty(
Kernel::make_unique<ArrayProperty<double>>("Extents", extents,
mandatoryExtents),
"A comma separated list of min, max for each dimension,\n"
"specifying the extents of each dimension. Optional, default +-50 in "
"each dimension.");
setPropertySettings("PeakRadius", make_unique<EnabledWhenProperty>(
"CheckPeakExtents", IS_NOT_DEFAULT));
}
void PeaksInRegion::validateExtentsInput() const {
const size_t numberOfFaces = this->numberOfFaces();
std::stringstream outbuff;
if (m_extents.size() != numberOfFaces) {
throw std::invalid_argument(
"Six commma separated entries for the extents expected");
}
if (m_extents[0] > m_extents[1]) {
outbuff << "xmin > xmax " << m_extents[0] << " > " << m_extents[1];
throw std::invalid_argument(outbuff.str());
}
if (m_extents[2] > m_extents[3]) {
outbuff << "ymin > ymax " << m_extents[2] << " > " << m_extents[3];
throw std::invalid_argument(outbuff.str());
}
if (m_extents[4] > m_extents[5]) {
outbuff << "zmin > zmax " << m_extents[2] << " > " << m_extents[3];
throw std::invalid_argument(outbuff.str());
}
}
bool PeaksInRegion::pointOutsideAnyExtents(const V3D &testPoint) const {
return testPoint[0] < m_extents[0] || testPoint[0] > m_extents[1] ||
testPoint[1] < m_extents[2] || testPoint[1] > m_extents[3] ||
testPoint[2] < m_extents[4] || testPoint[2] > m_extents[5];
}
bool PeaksInRegion::pointInsideAllExtents(const V3D &testPoint,
const Mantid::Kernel::V3D &) const {
return testPoint[0] >= m_extents[0] && testPoint[0] <= m_extents[1] &&
testPoint[1] >= m_extents[2] && testPoint[1] <= m_extents[3] &&
testPoint[2] >= m_extents[4] && testPoint[2] <= m_extents[5];
}
void PeaksInRegion::checkTouchPoint(const V3D &touchPoint, const V3D &normal,
const V3D &faceVertex) const {
if (normal.scalar_prod(touchPoint - faceVertex) != 0) {
throw std::runtime_error(
"Debugging. Calculation is wrong. touch point should always be on the "
"plane!"); // Remove this line later. Check that geometry is setup
// properly.
}
}
/**
Implementation of pure virtual method on PeaksIntersection.
@return Number of faces that the box has (6 - always)
*/
int PeaksInRegion::numberOfFaces() const { return 6; }
/**
Create the faces associated with this shape.
@return newly created faces
*/
VecVecV3D PeaksInRegion::createFaces() const {
const int minXIndex = 0;
const int maxXIndex = 1;
const int minYIndex = 2;
const int maxYIndex = 3;
const int minZIndex = 4;
const int maxZIndex = 5;
// Clockwise ordering of points around the extents box
/*
on front face. Positive z extends into plane.
p2|---|p3
| |
p1|---|p4
*/
V3D point1(m_extents[minXIndex], m_extents[minYIndex], m_extents[minZIndex]);
V3D point2(m_extents[minXIndex], m_extents[maxYIndex], m_extents[minZIndex]);
V3D point3(m_extents[maxXIndex], m_extents[maxYIndex], m_extents[minZIndex]);
V3D point4(m_extents[maxXIndex], m_extents[minYIndex], m_extents[minZIndex]);
V3D point5(m_extents[minXIndex], m_extents[minYIndex], m_extents[maxZIndex]);
V3D point6(m_extents[minXIndex], m_extents[maxYIndex], m_extents[maxZIndex]);
V3D point7(m_extents[maxXIndex], m_extents[maxYIndex], m_extents[maxZIndex]);
V3D point8(m_extents[maxXIndex], m_extents[minYIndex], m_extents[maxZIndex]);
const int numberOfFaces = this->numberOfFaces();
VecVecV3D faces(numberOfFaces);
int faceIndex = 0;
faces[faceIndex++] = {point1, point5, point6}; // These define a
// face normal to x
// at xmin.
faces[faceIndex++] = {point4, point7, point8}; // These define a
// face normal to x
// at xmax.
faces[faceIndex++] = {point1, point4, point8}; // These define a
// face normal to y
// at ymin.
faces[faceIndex++] = {point2, point3, point7}; // These define a
// face normal to y
// at ymax.
faces[faceIndex++] = {point1, point2, point3}; // These define a
// face normal to z
// at zmin.
faces[faceIndex++] = {point5, point6, point7}; // These define a
// face normal to z
// at zmax.
return faces;
}
//----------------------------------------------------------------------------------------------
/** Execute the algorithm.
*/
void PeaksInRegion::exec() {
m_extents = this->getProperty("Extents");
const bool checkPeakExtents = this->getProperty("CheckPeakExtents");
validateExtentsInput();
executePeaksIntersection(checkPeakExtents);
}
} // namespace Crystal
} // namespace Mantid