Mantid
Loading...
Searching...
No Matches
BoundingBox.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 +
7//---------------------------------------------------------
8// Includes
9//---------------------------------------------------------
13
14#include <cfloat>
15
16namespace Mantid::Geometry {
17using Kernel::V3D;
18
19//---------------------------------------------------------
20// Public member functions
21//---------------------------------------------------------
28bool BoundingBox::isPointInside(const V3D &point) const {
29 if (!this->isAxisAligned()) {
30 throw(Kernel::Exception::NotImplementedError("this function has not been modified properly"));
31 }
32
33 return point.X() <= xMax() + Kernel::Tolerance && point.X() >= xMin() - Kernel::Tolerance &&
34 point.Y() <= yMax() + Kernel::Tolerance && point.Y() >= yMin() - Kernel::Tolerance &&
35 point.Z() <= zMax() + Kernel::Tolerance && point.Z() >= zMin() - Kernel::Tolerance;
36}
37
44bool BoundingBox::doesLineIntersect(const Track &track) const {
45 return this->doesLineIntersect(track.startPoint(), track.direction());
46}
47
55bool BoundingBox::doesLineIntersect(const V3D &startPoint, const V3D &lineDir) const {
56 if (!this->isAxisAligned()) {
57 throw(Kernel::Exception::NotImplementedError("this function has not been modified properly"));
58 }
59 // Method - Loop through planes looking for ones that are visible and check
60 // intercept
61 // Assume that orig is outside of BoundingBox.
62 const double tol = Mantid::Kernel::Tolerance;
63 double lambda;
64 if (startPoint.X() > xMax()) {
65 if (lineDir.X() < -tol) {
66 lambda = (xMax() - startPoint.X()) / lineDir.X();
67 if (yMin() <= startPoint.Y() + lambda * lineDir.Y() && yMax() >= startPoint.Y() + lambda * lineDir.Y())
68 if (zMin() <= startPoint.Z() + lambda * lineDir.Z() && zMax() >= startPoint.Z() + lambda * lineDir.Z())
69 return true;
70 }
71 }
72 if (startPoint.X() < xMin()) {
73 if (lineDir.X() > tol) {
74 lambda = (xMin() - startPoint.X()) / lineDir.X();
75 if (yMin() <= startPoint.Y() + lambda * lineDir.Y() && yMax() >= startPoint.Y() + lambda * lineDir.Y())
76 if (zMin() <= startPoint.Z() + lambda * lineDir.Z() && zMax() >= startPoint.Z() + lambda * lineDir.Z())
77 return true;
78 }
79 }
80 if (startPoint.Y() > yMax()) {
81 if (lineDir.Y() < -tol) {
82 lambda = (yMax() - startPoint.Y()) / lineDir.Y();
83 if (xMin() <= startPoint.X() + lambda * lineDir.X() && xMax() >= startPoint.X() + lambda * lineDir.X())
84 if (zMin() <= startPoint.Z() + lambda * lineDir.Z() && zMax() >= startPoint.Z() + lambda * lineDir.Z())
85 return true;
86 }
87 }
88 if (startPoint.Y() < yMin()) {
89 if (lineDir.Y() > tol) {
90 lambda = (yMin() - startPoint.Y()) / lineDir.Y();
91 if (xMin() <= startPoint.X() + lambda * lineDir.X() && xMax() >= startPoint.X() + lambda * lineDir.X())
92 if (zMin() <= startPoint.Z() + lambda * lineDir.Z() && zMax() >= startPoint.Z() + lambda * lineDir.Z())
93 return true;
94 }
95 }
96 if (startPoint.Z() > zMax()) {
97 if (lineDir.Z() < -tol) {
98 lambda = (zMax() - startPoint.Z()) / lineDir.Z();
99 if (yMin() <= startPoint.Y() + lambda * lineDir.Y() && yMax() >= startPoint.Y() + lambda * lineDir.Y())
100 if (xMin() <= startPoint.X() + lambda * lineDir.X() && xMax() >= startPoint.X() + lambda * lineDir.X())
101 return true;
102 }
103 }
104 if (startPoint.Z() < zMin()) {
105 if (lineDir.Z() > tol) {
106 lambda = (zMin() - startPoint.Z()) / lineDir.Z();
107 if (yMin() <= startPoint.Y() + lambda * lineDir.Y() && yMax() >= startPoint.Y() + lambda * lineDir.Y())
108 if (xMin() <= startPoint.X() + lambda * lineDir.X() && xMax() >= startPoint.X() + lambda * lineDir.X())
109 return true;
110 }
111 }
112 return this->isPointInside(startPoint);
113}
114
122double BoundingBox::angularWidth(const Kernel::V3D &observer) const {
123 Kernel::V3D centre = centrePoint() - observer;
124 std::vector<Kernel::V3D> pts;
125 this->getFullBox(pts, observer);
126
127 std::vector<Kernel::V3D>::const_iterator ip;
128 double centre_norm_inv = 1.0 / centre.norm();
129 double thetaMax(-1.0);
130 for (ip = pts.begin(); ip != pts.end(); ++ip) {
131 double theta = acos(ip->scalar_prod(centre) * centre_norm_inv / ip->norm());
132 if (theta > thetaMax)
133 thetaMax = theta;
134 }
135 return thetaMax;
136}
137
146Kernel::V3D BoundingBox::generatePointInside(double r1, double r2, double r3) const {
147 return V3D(xMin() + r1 * (xMax() - xMin()), yMin() + r2 * (yMax() - yMin()), zMin() + r3 * (zMax() - zMin()));
148}
149
150void BoundingBox::getFullBox(std::vector<Kernel::V3D> &box, const Kernel::V3D &observer) const {
151 box.resize(8);
152 box[0] = Kernel::V3D(xMin(), yMin(), zMin()) - observer;
153 box[1] = Kernel::V3D(xMax(), yMin(), zMin()) - observer;
154 box[2] = Kernel::V3D(xMax(), yMax(), zMin()) - observer;
155 box[3] = Kernel::V3D(xMin(), yMax(), zMin()) - observer;
156 box[4] = Kernel::V3D(xMin(), yMax(), zMax()) - observer;
157 box[5] = Kernel::V3D(xMin(), yMin(), zMax()) - observer;
158 box[6] = Kernel::V3D(xMax(), yMin(), zMax()) - observer;
159 box[7] = Kernel::V3D(xMax(), yMax(), zMax()) - observer;
160}
161
162void BoundingBox::setBoxAlignment(const Kernel::V3D &R0, const std::vector<Kernel::V3D> &orts) {
163 this->coord_system.resize(4);
164 coord_system[0] = R0;
165 coord_system[1] = orts[0];
166 coord_system[2] = orts[1];
167 coord_system[3] = orts[2];
168 is_axis_aligned = false;
169}
170
172 this->m_null = true;
173 for (int i = 0; i < 3; i++) {
174 this->m_minPoint[i] = FLT_MAX;
175 this->m_maxPoint[i] = -FLT_MAX;
176 }
177}
178
179void BoundingBox::realign(std::vector<Kernel::V3D> const *const pCS) {
180 if (pCS) {
181 this->coord_system.resize(pCS->size());
182 for (unsigned int i = 0; i < pCS->size(); i++) {
183 this->coord_system[i] = pCS->operator[](i);
184 }
185 this->is_axis_aligned = false;
186 if (this->m_null)
187 return;
188 } else {
189 if (this->isAxisAligned())
190 return;
191 }
192
193 // expand the bounding box to full size and shift it to the coordinates with
194 // the
195 // centre cpecified;
196 std::vector<V3D> BBpoints;
197 this->getFullBox(BBpoints, this->coord_system[0]);
198
199 // identify min-max vrt the new coordinate system;
200 double xMin(FLT_MAX), yMin(FLT_MAX), zMin(FLT_MAX);
201 double xMax(-FLT_MAX), yMax(-FLT_MAX), zMax(-FLT_MAX);
202 for (unsigned int i = 0; i < 8; i++) {
203 double x = coord_system[1].scalar_prod(BBpoints[i]);
204 double y = coord_system[2].scalar_prod(BBpoints[i]);
205 double z = coord_system[3].scalar_prod(BBpoints[i]);
206 if (x < xMin)
207 xMin = x;
208 if (x > xMax)
209 xMax = x;
210 if (y < yMin)
211 yMin = y;
212 if (y > yMax)
213 yMax = y;
214 if (z < zMin)
215 zMin = z;
216 if (z > zMax)
217 zMax = z;
218 }
219 this->xMin() = xMin;
220 this->xMax() = xMax;
221 this->yMin() = yMin;
222 this->yMax() = yMax;
223 this->zMin() = zMin;
224 this->zMax() = zMax;
225}
226
231void BoundingBox::grow(const BoundingBox &other) {
232
233 // If the current box is empty then we definitely need to grow
234 if (m_null) {
235 m_minPoint = other.minPoint();
236 m_maxPoint = other.maxPoint();
237 } else {
238
239 // Simply checks if an of the points in the given box are outside this one
240 // and changes the coordinate appropriately
241 V3D otherPoint = other.minPoint();
242 for (size_t i = 0; i < 3; ++i) {
243 if (otherPoint[i] < m_minPoint[i]) {
244 m_minPoint[i] = otherPoint[i];
245 }
246 }
247 otherPoint = other.maxPoint();
248 for (size_t i = 0; i < 3; ++i) {
249 if (otherPoint[i] > m_maxPoint[i]) {
250 m_maxPoint[i] = otherPoint[i];
251 }
252 }
253 }
254 m_null &= other.isNull();
255}
256
257//--------------------------------------------------------------------------
258// Namespace functions
259//--------------------------------------------------------------------------
260
267std::ostream &operator<<(std::ostream &os, const BoundingBox &box) {
268 os << "X from " << box.xMin() << " to " << box.xMax() << "; Y from " << box.yMin() << " to " << box.yMax()
269 << "; Z from " << box.zMin() << " to " << box.zMax();
270 return os;
271}
272} // namespace Mantid::Geometry
const std::vector< double > * lambda
A simple structure that defines an axis-aligned cuboid shaped bounding box for a geometrical object.
Definition: BoundingBox.h:34
void setBoxAlignment(const Kernel::V3D &R0, const std::vector< Kernel::V3D > &orts)
change the BB alighnment, providing new coordinate system to alighn it to.
bool isPointInside(const Kernel::V3D &point) const
Is the given point within the bounding box?
Definition: BoundingBox.cpp:28
bool m_null
Flag marking if we've been initialized using the default constructor, with values or default values a...
Definition: BoundingBox.h:181
double angularWidth(const Kernel::V3D &observer) const
Calculate the angular half width from the given point.
void getFullBox(std::vector< Kernel::V3D > &box, const Kernel::V3D &observer) const
returns the expanded box consisting of all 8 box points, shifted into the coordinate system with the ...
double xMax() const
Return the maximum value of X.
Definition: BoundingBox.h:80
double zMin() const
Return the minimum value of Z.
Definition: BoundingBox.h:86
Kernel::V3D m_maxPoint
The maximum point of the axis-aligned box.
Definition: BoundingBox.h:178
Kernel::V3D generatePointInside(double r1, double r2, double r3) const
Generate a random point within the box.
double zMax() const
Return the maximum value of Z.
Definition: BoundingBox.h:88
double yMax() const
Return the maximum value of Y.
Definition: BoundingBox.h:84
bool isAxisAligned() const
Check if it is normal axis aligned bounding box or not.
Definition: BoundingBox.h:116
double xMin() const
Return the minimum value of X.
Definition: BoundingBox.h:78
void nullify()
set BB in to undefined state with min=FLT_MAX>max=-FLT_MAX
bool doesLineIntersect(const Track &track) const
Does a specified track intersect the bounding box.
Definition: BoundingBox.cpp:44
Kernel::V3D centrePoint() const
Returns the centre of the bounding box.
Definition: BoundingBox.h:94
double yMin() const
Return the minimum value of Y.
Definition: BoundingBox.h:82
std::vector< Kernel::V3D > coord_system
if the bounding box is not axis aligned, the vector below describes the coordinate system,...
Definition: BoundingBox.h:189
Kernel::V3D m_minPoint
The minimum point of the axis-aligned box.
Definition: BoundingBox.h:176
void grow(const BoundingBox &other)
Grow the bounding box so that it also encompasses the given box.
void realign(std::vector< Kernel::V3D > const *const pCS=nullptr)
reallign the BB according to new coordinate system, provided earlier or specified as parameter;
bool is_axis_aligned
the parameter which describe if the bounding box is axis aligned or not
Definition: BoundingBox.h:183
Defines a track as a start point and a direction.
Definition: Track.h:165
const Kernel::V3D & startPoint() const
Returns the starting point.
Definition: Track.h:191
const Kernel::V3D & direction() const
Returns the direction as a unit vector.
Definition: Track.h:193
Marks code as not implemented yet.
Definition: Exception.h:138
Class for 3D vectors.
Definition: V3D.h:34
constexpr double X() const noexcept
Get x.
Definition: V3D.h:232
constexpr double Y() const noexcept
Get y.
Definition: V3D.h:233
double norm() const noexcept
Definition: V3D.h:263
constexpr double Z() const noexcept
Get z.
Definition: V3D.h:234
MANTID_GEOMETRY_DLL std::ostream & operator<<(std::ostream &stream, const PointGroup &self)
Returns a streamed representation of the PointGroup object.
Definition: PointGroup.cpp:312
constexpr double Tolerance
Standard tolerance value.
Definition: Tolerance.h:12