Mantid
Loading...
Searching...
No Matches
MDImplicitFunction.h
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2011 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 +
7#pragma once
8
12#include <algorithm>
13#include <memory>
14#include <string>
15#include <vector>
16
17namespace Mantid {
18namespace Geometry {
19
45class MANTID_GEOMETRY_DLL MDImplicitFunction {
46public:
48 virtual ~MDImplicitFunction() = default;
49
50 void addPlane(const MDPlane &plane);
51
54 const MDPlane &getPlane(size_t index) const { return m_planes[index]; }
55
57 size_t getNumDims() const { return m_nd; }
58
60 size_t getNumPlanes() const { return m_planes.size(); }
61
63 virtual std::string getName() const {
64 throw std::runtime_error("Cannot call MDImplicitFunction does not implement getName()");
65 }
66
68 virtual std::string toXMLString() const {
69 throw std::runtime_error("Cannot call MDImplicitFunction does not implement toXMLString()");
70 }
71
72 //----------------------------------------------------------------------------------------------
76 enum eContact {
78 NOT_TOUCHING = 0,
80 TOUCHING = 1,
82 CONTAINED = 2
83 };
84
85 // ==================== Methods that are inline for performance
86 // ================================
87 //----------------------------------------------------------------------------------------------
95 virtual bool isPointContained(const coord_t *coords) {
96 const auto it = std::find_if(m_planes.begin(), m_planes.end(),
97 [coords](const MDPlane &plane) { return !plane.isPointBounded(coords); });
98 return it == m_planes.end();
99 }
100
101 //----------------------------------------------------------------------------------------------
109 virtual bool isPointContained(const Mantid::Kernel::VMD &coords) {
110 const auto it = std::find_if(m_planes.begin(), m_planes.end(),
111 [coords](const MDPlane &plane) { return !plane.isPointBounded(coords); });
112 return it == m_planes.end();
113 }
114
115 //----------------------------------------------------------------------------------------------
123 virtual bool isPointContained(const std::vector<coord_t> &coords) {
124 const auto it = std::find_if(m_planes.begin(), m_planes.end(),
125 [coords](const MDPlane &plane) { return !plane.isPointBounded(coords); });
126 return it == m_planes.end();
127 }
128
129 //----------------------------------------------------------------------------------------------
156 bool isBoxTouching(const std::vector<std::vector<coord_t>> &vertexes) {
157 // The first plane with NO points inside it means the box does NOT touch.
158 return std::all_of(m_planes.cbegin(), m_planes.cbegin() + m_numPlanes, [&vertexes](const MDPlane &plane) {
159 return std::any_of(vertexes.cbegin(), vertexes.cend(),
160 [&plane](const std::vector<coord_t> &vertex) { return plane.isPointBounded(vertex); });
161 });
162 }
163
164 //----------------------------------------------------------------------------------------------
175 bool isBoxTouching(const coord_t *vertexes, const size_t numPoints) {
176 // As the description states, the first plane with NO points inside it
177 // means the box does NOT touch. So iterate by planes
178 for (size_t i = 0; i < m_numPlanes; i++) {
179 size_t numBounded = 0;
180 for (size_t j = 0; j < numPoints; j++) {
181 if (m_planes[i].isPointBounded(vertexes + j * m_nd)) {
182 numBounded++;
183 // No need to evaluate any more points.
184 break;
185 }
186 }
187 // Not a single point is in this plane
188 if (numBounded == 0)
189 // That means the box CANNOT touch the implicit function
190 return false;
191 }
192 return true;
193 }
194
195 //----------------------------------------------------------------------------------------------
209 eContact boxContact(const coord_t *vertexes, const size_t numPoints) const {
210 // For speed, we can stop looking when we know the box CANNOT be fully
211 // contained.
212 bool lookForFullyContained = true;
213
214 // As the description states, the first plane with NO points inside it
215 // means the box does NOT touch. So iterate by planes
216 for (size_t i = 0; i < m_numPlanes; i++) {
217 size_t numBounded = 0;
218 for (size_t j = 0; j < numPoints; j++) {
219 if (m_planes[i].isPointBounded(vertexes + j * m_nd)) {
220 numBounded++;
221 // No need to evaluate any more points, unless we look for fully
222 // contained
223 if (!lookForFullyContained)
224 break;
225 } else
226 // One of the vertexes is not contained by one of the planes.
227 // This means that the box CANNOT be fully contained.
228 lookForFullyContained = false;
229 }
230 // Not a single point is in this plane
231 if (numBounded == 0)
232 // That means the box CANNOT touch the implicit function
233 return NOT_TOUCHING;
234 // If all points were within this plane, then there is still a chance that
235 // the box is fully contained
236 if (numBounded != numPoints)
237 lookForFullyContained = false;
238 }
239 // If nothing said that the box might not be fully contained, then it is
240 // fully contained!
241 if (lookForFullyContained)
242 return CONTAINED;
243 else
244 return TOUCHING;
245 }
246
247protected:
249 size_t m_nd;
250
252 std::vector<MDPlane> m_planes;
253
256};
257
258using MDImplicitFunction_sptr = std::shared_ptr<MDImplicitFunction>;
259
260} // namespace Geometry
261} // namespace Mantid
std::map< DeltaEMode::Type, std::string > index
An "ImplicitFunction" defining a hyper-cuboid-shaped region in N dimensions.
eContact boxContact(const coord_t *vertexes, const size_t numPoints) const
Determine how a box (consisting of a number of vertexes) is in contact with the implicit function.
eContact
Enum for describing the contact between a box and an implicit function.
virtual bool isPointContained(const std::vector< coord_t > &coords)
Is a point in MDimensions contained by this ImplicitFunction? If the point is bounded by ALL planes c...
virtual bool isPointContained(const Mantid::Kernel::VMD &coords)
Is a point in MDimensions contained by this ImplicitFunction? If the point is bounded by ALL planes c...
size_t m_numPlanes
Cached number of planes (for a sligh speed-up)
virtual std::string getName() const
virtual bool isPointContained(const coord_t *coords)
Is a point in MDimensions contained by this ImplicitFunction? If the point is bounded by ALL planes c...
bool isBoxTouching(const std::vector< std::vector< coord_t > > &vertexes)
Is there a chance that the box defined by these vertexes touches the implicit function volume?
std::vector< MDPlane > m_planes
Vector of all the planes applying for this implict function.
size_t m_nd
number of dimensions for which this object can be applied
virtual std::string toXMLString() const
const MDPlane & getPlane(size_t index) const
bool isBoxTouching(const coord_t *vertexes, const size_t numPoints)
Same as isBoxTouching(vector), except that it takes a bare array of coordinates.
A generalized description of a N-dimensional hyperplane.
Definition MDPlane.h:41
std::shared_ptr< MDImplicitFunction > MDImplicitFunction_sptr
Helper class which provides the Collimation Length for SANS instruments.
float coord_t
Typedef for the data type to use for coordinate axes in MD objects such as MDBox, MDEventWorkspace,...
Definition MDTypes.h:27