Mantid
Loading...
Searching...
No Matches
RandomPoint.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2019 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 <boost/math/special_functions/pow.hpp>
11
13
23Kernel::V3D localPointInCylinder(const Kernel::V3D &basis, const Kernel::V3D &alongAxis, double polarAngle,
24 double radialLength) {
25 // Use basis to get a second perpendicular vector to define basis2
26 Kernel::V3D basis2;
27 if (basis.X() == 0) {
28 basis2.setX(1.);
29 } else if (basis.Y() == 0) {
30 basis2.setY(1.);
31 } else if (basis.Z() == 0) {
32 basis2.setZ(1.);
33 } else {
34 basis2.setX(-basis.Y());
35 basis2.setY(basis.X());
36 basis2.normalize();
37 }
38 const Kernel::V3D basis3{basis.cross_prod(basis2)};
39 const Kernel::V3D localPoint{((basis2 * std::cos(polarAngle) + basis3 * std::sin(polarAngle)) * radialLength) +
40 alongAxis};
41 return localPoint;
42}
43
51 const auto geometry = shapeInfo.cuboidGeometry();
52 const double r1{rng.nextValue()};
53 const double r2{rng.nextValue()};
54 const double r3{rng.nextValue()};
55 const Kernel::V3D basis1{geometry.leftFrontTop - geometry.leftFrontBottom};
56 const Kernel::V3D basis2{geometry.leftBackBottom - geometry.leftFrontBottom};
57 const Kernel::V3D basis3{geometry.rightFrontBottom - geometry.leftFrontBottom};
58 return geometry.leftFrontBottom + (basis1 * r1 + basis2 * r2 + basis3 * r3);
59}
60
68 const auto geometry = shapeInfo.cylinderGeometry();
69 const double r1{rng.nextValue()};
70 const double r2{rng.nextValue()};
71 const double r3{rng.nextValue()};
72 const double polar{2. * M_PI * r1};
73 // The sqrt is needed for a uniform distribution of points.
74 const double r{geometry.radius * std::sqrt(r2)};
75 const double z{geometry.height * r3};
76 const Kernel::V3D alongAxis{geometry.axis * z};
77 auto localPoint = localPointInCylinder(geometry.axis, alongAxis, polar, r);
78 return localPoint + geometry.centreOfBottomBase;
79}
80
88 const auto geometry = shapeInfo.hollowCylinderGeometry();
89 const double r1{rng.nextValue()};
90 const double r2{rng.nextValue()};
91 const double r3{rng.nextValue()};
92 const double polar{2. * M_PI * r1};
93 // We need a random number between the inner radius and outer radius, but also
94 // need the square root for a uniform distribution of points
95 const double c1 = geometry.innerRadius * geometry.innerRadius;
96 const double c2 = geometry.radius * geometry.radius;
97 const double r{std::sqrt(c1 + (c2 - c1) * r2)};
98 const double z{geometry.height * r3};
99 const Kernel::V3D alongAxis{geometry.axis * z};
100 auto localPoint = localPointInCylinder(geometry.axis, alongAxis, polar, r);
101 return localPoint + geometry.centreOfBottomBase;
102}
103
111 const auto geometry = shapeInfo.sphereGeometry();
112 const double r1{rng.nextValue()};
113 const double r2{rng.nextValue()};
114 const double r3{rng.nextValue()};
115 const double azimuthal{2. * M_PI * r1};
116 // The acos is needed for a uniform distribution of points.
117 const double polar{std::acos(2. * r2 - 1.)};
118 const double r{r3 * geometry.radius};
119 const double x{r * std::cos(azimuthal) * std::sin(polar)};
120 const double y{r * std::sin(azimuthal) * std::sin(polar)};
121 const double z{r * std::cos(polar)};
122 return geometry.centre + Kernel::V3D{x, y, z};
123}
124
132boost::optional<Kernel::V3D> inGenericShape(const IObject &object, Kernel::PseudoRandomNumberGenerator &rng,
133 size_t maxAttempts) {
134 return bounded(object, rng, object.getBoundingBox(), maxAttempts);
135}
136
145boost::optional<Kernel::V3D> bounded(const IObject &object, Kernel::PseudoRandomNumberGenerator &rng,
146 const BoundingBox &box, size_t maxAttempts) {
147 boost::optional<Kernel::V3D> point{boost::none};
148 if (box.isNull()) {
149 throw std::invalid_argument("Invalid bounding box. Cannot generate random point.");
150 }
151 for (size_t attempts{0}; attempts < maxAttempts; ++attempts) {
152 const double r1 = rng.nextValue();
153 const double r2 = rng.nextValue();
154 const double r3 = rng.nextValue();
155 auto pt = box.generatePointInside(r1, r2, r3);
156 if (object.isValid(pt)) {
157 point = pt;
158 break;
159 }
160 };
161 return point;
162}
163} // namespace Mantid::Geometry::RandomPoint
A simple structure that defines an axis-aligned cuboid shaped bounding box for a geometrical object.
Definition: BoundingBox.h:34
Kernel::V3D generatePointInside(double r1, double r2, double r3) const
Generate a random point within the box.
bool isNull() const
Is this a default constructed box?
Definition: BoundingBox.h:104
IObject : Interface for geometry objects.
Definition: IObject.h:41
SphereGeometry sphereGeometry() const
Definition: ShapeInfo.cpp:48
CylinderGeometry cylinderGeometry() const
Definition: ShapeInfo.cpp:53
CuboidGeometry cuboidGeometry() const
Definition: ShapeInfo.cpp:38
HollowCylinderGeometry hollowCylinderGeometry() const
Definition: ShapeInfo.cpp:58
Defines a 1D pseudo-random number generator, i.e.
virtual double nextValue()=0
Return the next double in the sequence.
Class for 3D vectors.
Definition: V3D.h:34
constexpr double X() const noexcept
Get x.
Definition: V3D.h:232
double normalize()
Make a normalized vector (return norm value)
Definition: V3D.cpp:130
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
void setZ(const double zz) noexcept
Set is z position.
Definition: V3D.h:230
void setX(const double xx) noexcept
Set is x position.
Definition: V3D.h:218
void setY(const double yy) noexcept
Set is y position.
Definition: V3D.h:224
constexpr double Z() const noexcept
Get z.
Definition: V3D.h:234
MANTID_GEOMETRY_DLL Kernel::V3D inCylinder(const detail::ShapeInfo &shapeInfo, Kernel::PseudoRandomNumberGenerator &rng)
Return a random point in cylinder.
Definition: RandomPoint.cpp:67
MANTID_GEOMETRY_DLL Kernel::V3D inCuboid(const detail::ShapeInfo &shapeInfo, Kernel::PseudoRandomNumberGenerator &rng)
Return a random point in a cuboid shape.
Definition: RandomPoint.cpp:50
MANTID_GEOMETRY_DLL Kernel::V3D inSphere(const detail::ShapeInfo &shapeInfo, Kernel::PseudoRandomNumberGenerator &rng)
Return a random point in sphere.
MANTID_GEOMETRY_DLL Kernel::V3D inHollowCylinder(const detail::ShapeInfo &shapeInfo, Kernel::PseudoRandomNumberGenerator &rng)
Return a random point in a hollow cylinder.
Definition: RandomPoint.cpp:87
MANTID_GEOMETRY_DLL Kernel::V3D localPointInCylinder(const Kernel::V3D &basis, const Kernel::V3D &alongAxis, double polarAngle, double radialLength)
Return a local point in a cylinder shape.
Definition: RandomPoint.cpp:23
MANTID_GEOMETRY_DLL boost::optional< Kernel::V3D > inGenericShape(const IObject &object, Kernel::PseudoRandomNumberGenerator &rng, size_t maxAttempts)
Return a random point in a generic shape.
boost::optional< Kernel::V3D > bounded(const detail::ShapeInfo &shapeInfo, Kernel::PseudoRandomNumberGenerator &rng, const BoundingBox &box, size_t maxAttempts)
Return a random point in a known shape restricted by a bounding box.
Definition: RandomPoint.h:62