Mantid
Loading...
Searching...
No Matches
MDPlane.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#include "MantidKernel/VMD.h"
11#include <gsl/gsl_linalg.h>
12#include <stdexcept>
13
14using namespace Mantid::Kernel;
15
16namespace Mantid::Geometry {
17
18//----------------------------------------------------------------------------------------------
25MDPlane::MDPlane(const std::vector<coord_t> &normal, const std::vector<coord_t> &point) {
26 m_nd = normal.size();
27 if ((m_nd < 1) || (m_nd > 100))
28 throw std::invalid_argument("MDPlane::ctor(): Invalid number of dimensions in the normal vector !");
29 if (point.size() != normal.size())
30 throw std::invalid_argument("MDPlane::ctor(): Inconsistent number of "
31 "dimensions in the normal/point vectors!");
32 construct(normal, point);
33}
34
35//----------------------------------------------------------------------------------------------
43 m_nd = normal.getNumDims();
44 if ((m_nd < 1) || (m_nd > 100))
45 throw std::invalid_argument("MDPlane::ctor(): Invalid number of dimensions in the normal vector !");
46 if (point.getNumDims() != normal.getNumDims())
47 throw std::invalid_argument("MDPlane::ctor(): Inconsistent number of "
48 "dimensions in the normal/point vectors!");
49 construct(normal, point);
50}
51
52//----------------------------------------------------------------------------------------------
60MDPlane::MDPlane(const size_t nd, const float *normal, const float *point) : m_nd(nd) {
61 if ((m_nd < 1) || (m_nd > 100))
62 throw std::invalid_argument("MDPlane::ctor(): Invalid number of dimensions in the workspace!");
63 construct(normal, point);
64}
65
66//----------------------------------------------------------------------------------------------
74MDPlane::MDPlane(const size_t nd, const double *normal, const double *point) : m_nd(nd) {
75 if ((m_nd < 1) || (m_nd > 100))
76 throw std::invalid_argument("MDPlane::ctor(): Invalid number of dimensions in the workspace!");
77 construct(normal, point);
78}
79
80//----------------------------------------------------------------------------------------------
89MDPlane::MDPlane(const std::vector<Mantid::Kernel::VMD> &vectors, const Mantid::Kernel::VMD &origin,
90 const Mantid::Kernel::VMD &insidePoint) {
91 // Get the normal vector by the determinant method
92 VMD normal = VMD::getNormalVector(vectors);
93
94 // The dimensionality of the plane
95 m_nd = normal.getNumDims();
96
97 // Whew. We have a normal, and a point on the plane. We can construct
98 construct(normal, origin);
99
100 // Did we get the wrong sign of the normal?
101 if (!this->isPointBounded(insidePoint)) {
102 // Flip the normal over
103 delete[] this->m_normal;
104 for (size_t d = 0; d < normal.getNumDims(); d++)
105 normal[d] = -1.0f * normal[d];
106 // And re-construct
107 construct(normal, origin);
108 }
109}
110
111// //----------------------------------------------------------------------------------------------
112// MDPlane::MDPlane(const std::vector<Mantid::Kernel::VMD> & points, const VMD
113// & insidePoint)
114// {
115// if (points.size() <= 0)
116// throw std::invalid_argument("MDPlane::ctor(): Must give at least 1
117// point");
118// VMD origin = points[0];
119// m_nd = origin.getNumDims();
120// if (insidePoint.getNumDims() != m_nd)
121// throw std::invalid_argument("MDPlane::ctor(): The insidePoint parameter
122// must match the dimensions of the other points!");
123// if (m_nd < 1)
124// throw std::invalid_argument("MDPlane::ctor(): Must have at least 1
125// dimension!");
126// if (points.size() != m_nd)
127// throw std::invalid_argument("MDPlane::ctor(): Must have as many points
128// as there are dimensions!");
129// for (size_t i=0; i < points.size(); i++)
130// if (points[i].getNumDims() != m_nd)
131// throw std::invalid_argument("MDPlane::ctor(): Inconsistent number of
132// dimensions in the points given!");
133//
134// // Special case for 1D (no need to use the linear equation system)
135// if (m_nd == 1)
136// {
137// VMD origin = points[0];
138// VMD normal(1);
139// normal[0] = (insidePoint[0] > origin[0]) ? +1.0 : -1.0;
140// construct(normal, origin);
141// return;
142// }
143//
144// // Make the A and B matrices as described above
145// double * a_data = new double[(m_nd-1) * (m_nd-1)];;
146// double * b_data = new double[(m_nd-1)];
147// for (size_t row=0; row<(m_nd-1); row++)
148// {
149// // Offset the point
150// VMD point = points[row+1] - origin;
151// // Put the 1th+ coords
152// for (size_t col=0; col<(m_nd-1); col++)
153// a_data[row*(m_nd-1) + col] = point[col+1];
154// // The row in B = - the 0th coordinate of the offset point.
155// b_data[row] = -point[0];
156// }
157// // To avoid aborting
158// gsl_set_error_handler_off();
159//
160// int ret = 0;
161//
162// gsl_matrix_view m = gsl_matrix_view_array (a_data, m_nd-1, m_nd-1);
163// gsl_vector_view b = gsl_vector_view_array (b_data, m_nd-1);
164// gsl_vector *x = gsl_vector_alloc (m_nd-1);
165//
166// // Use GSL to solve the linear algebra problem
172//
173// gsl_matrix * V = gsl_matrix_alloc(m_nd-1, m_nd-1);
174// gsl_vector * S = gsl_vector_alloc(m_nd-1);
175// gsl_vector * work = gsl_vector_alloc(m_nd-1);
176// ret = gsl_linalg_SV_decomp(&m.matrix, V, S, work);
177// if (ret == 0)
178// ret = gsl_linalg_SV_solve(&m.matrix, V, S, &b.vector, x);
179//
180// if (ret != 0)
181// {
182// std::string pointsStr;
183// for (size_t i=0; i < points.size(); i++)
184// pointsStr += points[i].toString(",") + ((i != points.size()-1) ? "; "
185// : "");
186// // Something failed
187// throw std::runtime_error("MDPlane::ctor(): unable to solve the system of
188// equations.\n"
189// "The points given likely do not form a plane (some may be
190// collinear), meaning the plane cannot be constructed.\n"
191// "Points were: " + pointsStr);
192// }
193//
194// // The normal vector
195// VMD normal(m_nd);
196//
197// // Recall that we fixed a1 to 1.0
198// normal[0] = 1.0;
199// for (size_t d=0; d<(m_nd-1); d++)
200// normal[d+1] = x->data[d];
201//
202// gsl_vector_free (x);
203// gsl_vector_free (S);
204// gsl_matrix_free (V);
205// delete [] a_data;
206// delete [] b_data;
207//
208// // Whew. We have a normal, and a point on the plane. We can construct
209// construct(normal, origin);
210//
211// // Did we get the wrong normal?
212// if (!this->isPointBounded(insidePoint))
213// {
214// // Flip the normal over
215// delete [] this->m_normal;
216// for (size_t d=0; d<normal.getNumDims(); d++)
217// normal[d] = -1.0 * normal[d];
218// // And re-construct
219// construct(normal, origin);
220// }
221// }
222
223//----------------------------------------------------------------------------------------------
228MDPlane::MDPlane(const MDPlane &other) : m_nd(other.m_nd), m_inequality(other.m_inequality) {
229 m_normal = new coord_t[m_nd];
230 for (size_t d = 0; d < m_nd; d++)
231 m_normal[d] = other.m_normal[d];
232}
233
234//----------------------------------------------------------------------------------------------
240 if (this != &other) // protect against invalid self-assignment
241 {
242 m_nd = other.m_nd;
243 m_inequality = other.m_inequality;
244 // Replace the array
245 delete[] m_normal;
246 m_normal = new coord_t[m_nd];
247 for (size_t d = 0; d < m_nd; d++)
248 m_normal[d] = other.m_normal[d];
249 }
250 return *this;
251}
252
253//----------------------------------------------------------------------------------------------
257
258} // namespace Mantid::Geometry
A generalized description of a N-dimensional hyperplane.
Definition: MDPlane.h:41
MDPlane(const Mantid::Kernel::VMD &normal, const Mantid::Kernel::VMD &point)
Constructor with normal and point.
Definition: MDPlane.cpp:42
coord_t m_inequality
Right-hand side of the linear equation. aka b in : a1*x1 + a2*x2 + ... < b.
Definition: MDPlane.h:189
void construct(IterableType normal, IterableType point)
Templated method for constructing the MDPlane.
Definition: MDPlane.h:170
size_t m_nd
Number of dimensions in the MDEventWorkspace.
Definition: MDPlane.h:181
bool isPointBounded(const coord_t *coords) const
Is a point in MDimensions bounded by this hyperplane, that is, is (a1*x1 + a2*x2 + ....
Definition: MDPlane.h:71
coord_t * m_normal
Coefficients to multiply each coordinate, sized m_nd.
Definition: MDPlane.h:186
MDPlane & operator=(const MDPlane &other)
Assignment operator.
Definition: MDPlane.cpp:239
size_t getNumDims() const
Definition: VMD.cpp:236
static VMDBase getNormalVector(const std::vector< VMDBase > &vectors)
Given N-1 vectors defining a N-1 dimensional hyperplane in N dimensions, returns a vector that is nor...
Definition: VMD.cpp:494
float coord_t
Typedef for the data type to use for coordinate axes in MD objects such as MDBox, MDEventWorkspace,...
Definition: MDTypes.h:27