Mantid
Loading...
Searching...
No Matches
MeshObject.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 +
16#include "MantidNexus/NexusFile.h"
17
18#include <algorithm>
19#include <memory>
20#include <utility>
21
22namespace Mantid::Geometry {
23
24MeshObject::MeshObject(std::vector<uint32_t> faces, std::vector<Kernel::V3D> vertices, const Kernel::Material &material)
25 : m_boundingBox(), m_id("MeshObject"), m_triangles(std::move(faces)), m_vertices(std::move(vertices)),
26 m_material(material) {
27
28 initialize();
29}
30
31MeshObject::MeshObject(std::vector<uint32_t> &&faces, std::vector<Kernel::V3D> &&vertices,
32 const Kernel::Material &&material)
33 : m_boundingBox(), m_id("MeshObject"), m_triangles(std::move(faces)), m_vertices(std::move(vertices)),
34 m_material(material) {
35
36 initialize();
37}
38
39// Do things that need to be done in constructor
41
43 m_handler = std::make_shared<GeometryHandler>(*this);
44}
45
50
55
62 // May enclose volume if there are at
63 // at least 4 triangles and 4 vertices (Tetrahedron)
64 return (numberOfTriangles() >= 4 && numberOfVertices() >= 4);
65}
66
72bool MeshObject::isValid(const Kernel::V3D &point) const {
73
75 if (!bb.isPointInside(point)) {
76 return false;
77 }
78
79 Kernel::V3D direction(0.0, 0.0, 1.0); // direction to look for intersections
80 std::vector<Kernel::V3D> intersectionPoints;
81 std::vector<TrackDirection> entryExitFlags;
82
83 getIntersections(point, direction, intersectionPoints, entryExitFlags);
84
85 if (intersectionPoints.empty()) {
86 return false;
87 }
88
89 // True if point is on surface
90 const auto it = std::find_if(
91 intersectionPoints.cbegin(), intersectionPoints.cend(),
92 [this, &point](const auto &intersectionPoint) { return point.distance(intersectionPoint) < M_TOLERANCE; });
93 if (it != intersectionPoints.cend())
94 return true;
95
96 // Look for nearest point then check its entry-exit flag
97 double nearestPointDistance = point.distance(intersectionPoints[0]);
98 size_t nearestPointIndex = 0;
99 for (size_t i = 1; i < intersectionPoints.size(); ++i) {
100 if (point.distance(intersectionPoints[i]) < nearestPointDistance) {
101 nearestPointDistance = point.distance(intersectionPoints[i]);
102 nearestPointIndex = i;
103 }
104 }
105 return (entryExitFlags[nearestPointIndex] == TrackDirection::LEAVING);
106}
107
113bool MeshObject::isOnSide(const Kernel::V3D &point) const {
114
116 if (!bb.isPointInside(point)) {
117 return false;
118 }
119
120 const std::vector<Kernel::V3D> directions = {Kernel::V3D{0, 0, 1}, Kernel::V3D{0, 1, 0},
121 Kernel::V3D{1, 0, 0}}; // directions to look for intersections
122 // We have to look in several directions in case a point is on a face
123 // or edge parallel to the first direction or also the second direction.
124 for (const auto &direction : directions) {
125 std::vector<Kernel::V3D> intersectionPoints;
126 std::vector<TrackDirection> entryExitFlags;
127
128 getIntersections(point, direction, intersectionPoints, entryExitFlags);
129
130 if (intersectionPoints.empty()) {
131 return false;
132 }
133
134 const auto it = std::find_if(
135 intersectionPoints.cbegin(), intersectionPoints.cend(),
136 [this, &point](const auto &intersectionPoint) { return point.distance(intersectionPoint) < M_TOLERANCE; });
137 if (it != intersectionPoints.cend())
138 return true;
139 }
140 return false;
141}
142
149 int originalCount = UT.count(); // Number of intersections original track
151 if (!bb.doesLineIntersect(UT)) {
152 return 0;
153 }
154
155 std::vector<Kernel::V3D> intersectionPoints;
156 std::vector<TrackDirection> entryExit;
157
158 getIntersections(UT.startPoint(), UT.direction(), intersectionPoints, entryExit);
159 if (intersectionPoints.empty())
160 return 0; // Quit if no intersections found
161
162 // For a 3D mesh, a ray may intersect several segments
163 for (size_t i = 0; i < intersectionPoints.size(); ++i) {
164 UT.addPoint(entryExit[i], intersectionPoints[i], *this);
165 }
166 UT.buildLink();
167
168 return UT.count() - originalCount;
169}
170
177double MeshObject::distance(const Track &track) const {
178 Kernel::V3D vertex1, vertex2, vertex3, intersection;
179 TrackDirection unused;
180 for (size_t i = 0; getTriangle(i, vertex1, vertex2, vertex3); ++i) {
181 if (MeshObjectCommon::rayIntersectsTriangle(track.startPoint(), track.direction(), vertex1, vertex2, vertex3,
182 intersection, unused)) {
183 return track.startPoint().distance(intersection);
184 }
185 }
186 std::ostringstream os;
187 os << "Unable to find intersection with object with track starting at " << track.startPoint() << " in direction "
188 << track.direction() << "\n";
189 throw std::runtime_error(os.str());
190}
191
199void MeshObject::getIntersections(const Kernel::V3D &start, const Kernel::V3D &direction,
200 std::vector<Kernel::V3D> &intersectionPoints,
201 std::vector<TrackDirection> &entryExitFlags) const {
202
203 Kernel::V3D vertex1, vertex2, vertex3, intersection;
204 TrackDirection entryExit;
205 for (size_t i = 0; getTriangle(i, vertex1, vertex2, vertex3); ++i) {
206 if (MeshObjectCommon::rayIntersectsTriangle(start, direction, vertex1, vertex2, vertex3, intersection, entryExit)) {
207 intersectionPoints.emplace_back(intersection);
208 entryExitFlags.emplace_back(entryExit);
209 }
210 }
211 // still need to deal with edge cases
212}
213
214/*
215 * Get a triangle - useful for iterating over triangles
216 * @param index :: Index of triangle in MeshObject
217 * @param v1 :: First vertex of triangle
218 * @param v2 :: Second vertex of triangle
219 * @param v3 :: Third vertex of triangle
220 * @returns true if the specified triangle exists
221 */
222bool MeshObject::getTriangle(const size_t index, Kernel::V3D &vertex1, Kernel::V3D &vertex2,
223 Kernel::V3D &vertex3) const {
224 bool triangleExists = index < m_triangles.size() / 3;
225 if (triangleExists) {
226 vertex1 = m_vertices[m_triangles[3 * index]];
227 vertex2 = m_vertices[m_triangles[3 * index + 1]];
228 vertex3 = m_vertices[m_triangles[3 * index + 2]];
229 }
230 return triangleExists;
231}
232
241int MeshObject::calcValidType(const Kernel::V3D &point, const Kernel::V3D &uVec) const {
242 const Kernel::V3D shift(uVec * Kernel::Tolerance * 25.0);
243 const Kernel::V3D testA(point - shift);
244 const Kernel::V3D testB(point + shift);
245 const int flagA = isValid(testA);
246 const int flagB = isValid(testB);
247 if (!(flagA ^ flagB))
248 return 0;
249 return (flagA) ? -1 : 1;
250}
251
264void MeshObject::getBoundingBox(double &xmax, double &ymax, double &zmax, double &xmin, double &ymin,
265 double &zmin) const {
266 return MeshObjectCommon::getBoundingBox(m_vertices, m_boundingBox, xmax, ymax, zmax, xmin, ymin, zmin);
267}
268
274double MeshObject::solidAngle(const SolidAngleParams &params) const {
275 double solidAngleSum(0), solidAngleNegativeSum(0);
276 Kernel::V3D vertex1, vertex2, vertex3;
277 for (size_t i = 0; this->getTriangle(i, vertex1, vertex2, vertex3); ++i) {
278 double sa = MeshObjectCommon::getTriangleSolidAngle(vertex1, vertex2, vertex3, params.observer());
279 if (sa > 0.0) {
280 solidAngleSum += sa;
281 } else {
282 solidAngleNegativeSum += sa;
283 }
284 }
285 /*
286 Same implementation as CSGObject. Assumes a convex closed mesh with
287 solidAngleSum == -solidAngleNegativeSum
288
289 Average is used to bypass issues with winding order. Surface normal
290 affects magnitude of solid angle. See CSGObject.
291 */
292 return 0.5 * (solidAngleSum - solidAngleNegativeSum);
293}
294
302double MeshObject::solidAngle(const SolidAngleParams &params, const Kernel::V3D &scaleFactor) const {
303 std::vector<Kernel::V3D> scaledVertices;
304 scaledVertices.reserve(m_vertices.size());
305 std::transform(m_vertices.cbegin(), m_vertices.cend(), std::back_inserter(scaledVertices),
306 [&scaleFactor](const auto &vertex) { return scaleFactor * vertex; });
307 MeshObject meshScaled(m_triangles, scaledVertices, m_material);
308 return meshScaled.solidAngle(params);
309}
310
315double MeshObject::volume() const {
316 // Select centre of bounding box as centre point.
317 // For each triangle calculate the signed volume of
318 // the tetrahedron formed by the triangle and the
319 // centre point. Then add to total.
320
322 double cX = 0.5 * (bb.xMax() + bb.xMin());
323 double cY = 0.5 * (bb.yMax() + bb.yMin());
324 double cZ = 0.5 * (bb.zMax() + bb.zMin());
325 Kernel::V3D centre(cX, cY, cZ);
326
327 double volumeTimesSix(0.0);
328
329 Kernel::V3D vertex1, vertex2, vertex3;
330 for (size_t i = 0; getTriangle(i, vertex1, vertex2, vertex3); ++i) {
331 Kernel::V3D a = vertex1 - centre;
332 Kernel::V3D b = vertex2 - centre;
333 Kernel::V3D c = vertex3 - centre;
334 volumeTimesSix += a.scalar_prod(b.cross_prod(c));
335 }
336
337 return volumeTimesSix / 6.0;
338}
339
347
354
355 Kernel::V3D testPt(0, 0, 0);
356 // Try centre of bounding box as initial guess, if we have one.
357 const BoundingBox &boundingBox = getBoundingBox();
358 if (boundingBox.isNonNull()) {
359 testPt = boundingBox.centrePoint();
360 if (searchForObject(testPt)) {
361 point = testPt;
362 return 1;
363 }
364 }
365
366 return 0;
367}
368
379 const size_t maxAttempts) const {
380 const auto &bbox = getBoundingBox();
381 if (bbox.isNull()) {
382 throw std::runtime_error("Object::generatePointInObject() - Invalid "
383 "bounding box. Cannot generate new point.");
384 }
385 return generatePointInObject(rng, bbox, maxAttempts);
386}
387
399 const BoundingBox &activeRegion,
400 const size_t maxAttempts) const {
401
402 const auto point = RandomPoint::bounded(*this, rng, activeRegion, maxAttempts);
403
404 return point;
405}
406
413 //
414 // Method - check if point in object, if not search directions along
415 // principle axes using interceptSurface
416 //
417 if (isValid(point))
418 return true;
419 for (const auto &dir : {Kernel::V3D(1., 0., 0.), Kernel::V3D(-1., 0., 0.), Kernel::V3D(0., 1., 0.),
420 Kernel::V3D(0., -1., 0.), Kernel::V3D(0., 0., 1.), Kernel::V3D(0., 0., -1.)}) {
421 Geometry::Track tr(point, dir);
422 if (this->interceptSurface(tr) > 0) {
423 point = tr.cbegin()->entryPoint;
424 return true;
425 }
426 }
427 return false;
428}
429
435void MeshObject::setGeometryHandler(const std::shared_ptr<GeometryHandler> &h) {
436 if (h == nullptr)
437 return;
438 m_handler = h;
439}
440
445void MeshObject::draw() const {
446 if (m_handler == nullptr)
447 return;
448 // Render the Object
449 m_handler->render();
450}
451
458 if (m_handler == nullptr)
459 return;
460 // Render the Object
461 m_handler->initialize();
462}
463
467std::shared_ptr<GeometryHandler> MeshObject::getGeometryHandler() const {
468 // Check if the geometry handler is upto dated with the cache, if not then
469 // cache it now.
470 return m_handler;
471}
472
477void MeshObject::rotate(const Kernel::Matrix<double> &rotationMatrix) {
478 std::for_each(m_vertices.begin(), m_vertices.end(),
479 [&rotationMatrix](auto &vertex) { vertex.rotate(rotationMatrix); });
480}
481
486void MeshObject::translate(const Kernel::V3D &translationVector) {
487 std::transform(m_vertices.cbegin(), m_vertices.cend(), m_vertices.begin(),
488 [&translationVector](const auto &vertex) { return vertex + translationVector; });
489}
490
495void MeshObject::scale(const double scaleFactor) {
496 std::transform(m_vertices.cbegin(), m_vertices.cend(), m_vertices.begin(),
497 [&scaleFactor](const auto &vertex) { return vertex * scaleFactor; });
498}
499
506 if ((matrix.numCols() != 4) || (matrix.numRows() != 4)) {
507 throw "Transformation matrix must be 4 x 4";
508 }
509
510 // create homogenous coordinates for the input vector with 4th element
511 // equal to 1 (position)
512 for (Kernel::V3D &vertex : m_vertices) {
513 std::vector<double> vertexin(4);
514 vertexin[0] = vertex.X();
515 vertexin[1] = vertex.Y();
516 vertexin[2] = vertex.Z();
517 vertexin[3] = 1;
518 std::vector<double> vertexout(4);
519 matrix.multiplyPoint(vertexin, vertexout);
520 Kernel::V3D newvertex(vertexout[0], vertexout[1], vertexout[2]);
521 vertex = newvertex;
522 }
523}
524
529 return; // Hopefully nothing necessary here
530}
531
535size_t MeshObject::numberOfTriangles() const { return m_triangles.size() / 3; }
536
540const std::vector<uint32_t> &MeshObject::getTriangles() const { return m_triangles; }
541
545size_t MeshObject::numberOfVertices() const { return m_vertices.size(); }
546
551
555const std::vector<Kernel::V3D> &MeshObject::getV3Ds() const { return m_vertices; }
556
558
560 throw std::runtime_error("MeshObject::shapeInfo() is not implemented");
561}
562
566void MeshObject::GetObjectGeom(detail::ShapeInfo::GeometryShape &type, std::vector<Kernel::V3D> &vectors,
567 double &innerRadius, double &radius, double &height) const {
568 // In practice, this outputs type = -1,
569 // to indicate not a "standard" object (cuboid/cone/cyl/sphere).
570 // Retained for possible future use.
572 if (m_handler == nullptr)
573 return;
574 m_handler->GetObjectGeom(type, vectors, innerRadius, radius, height);
575}
576
577void MeshObject::saveNexus(Nexus::File *file, const std::string &group) const {
578 file->makeGroup(group, "NXoff_geometry", true);
579 file->writeData("vertices", getVertices());
580 file->writeData("winding_order", getTriangles());
581
582 const size_t nTriangles = numberOfTriangles();
583 std::vector<uint32_t> faceIndices(nTriangles);
584 for (size_t i = 0; i < nTriangles; ++i) {
585 faceIndices[i] = static_cast<uint32_t>(i * 3);
586 }
587 file->writeData("faces", faceIndices);
588 file->closeGroup();
589}
590
591std::shared_ptr<MeshObject> MeshObject::loadNexus(Nexus::File *file, const std::string &group,
592 const Kernel::Material &material) {
593 file->openGroup(group, "NXoff_geometry");
594
595 std::vector<double> flatVertices;
596 file->readData("vertices", flatVertices);
597
598 std::vector<uint32_t> windingOrder;
599 file->readData("winding_order", windingOrder);
600
601 std::vector<uint32_t> faceIndices;
602 file->readData("faces", faceIndices);
603
604 file->closeGroup();
605
606 // Convert flat vertex array to V3D
607 const size_t nVerts = flatVertices.size() / 3;
608 std::vector<Kernel::V3D> vertices;
609 vertices.reserve(nVerts);
610 for (size_t i = 0; i < nVerts; ++i) {
611 vertices.emplace_back(flatVertices[3 * i], flatVertices[3 * i + 1], flatVertices[3 * i + 2]);
612 }
613
614 // Convert OFF face indices + winding order to triangle indices
615 std::vector<uint32_t> triangles;
616 triangles.reserve(windingOrder.size());
617 for (size_t f = 0; f < faceIndices.size(); ++f) {
618 const uint32_t start = faceIndices[f];
619 const uint32_t end = (f + 1 < faceIndices.size()) ? faceIndices[f + 1] : static_cast<uint32_t>(windingOrder.size());
620 const uint32_t nVertsInFace = end - start;
621 // We assume that any polygon face is convex and that we can use a fan triangulation
622 for (uint32_t v = 1; v + 1 < nVertsInFace; ++v) {
623 triangles.push_back(windingOrder.at(start));
624 triangles.push_back(windingOrder.at(start + v));
625 triangles.push_back(windingOrder.at(start + v + 1));
626 }
627 }
628
629 return std::make_shared<MeshObject>(std::move(triangles), std::move(vertices), material);
630}
631
632} // namespace Mantid::Geometry
double height
Definition GetAllEi.cpp:155
std::map< DeltaEMode::Type, std::string > index
A simple structure that defines an axis-aligned cuboid shaped bounding box for a geometrical object.
Definition BoundingBox.h:33
bool isPointInside(const Kernel::V3D &point) const
Is the given point within the bounding box?
double xMax() const
Return the maximum value of X.
Definition BoundingBox.h:79
bool isNonNull() const
Is the box considered valid. Convenience for !isNull()
double zMin() const
Return the minimum value of Z.
Definition BoundingBox.h:85
double zMax() const
Return the maximum value of Z.
Definition BoundingBox.h:87
double yMax() const
Return the maximum value of Y.
Definition BoundingBox.h:83
double xMin() const
Return the minimum value of X.
Definition BoundingBox.h:77
bool doesLineIntersect(const Track &track) const
Does a specified track intersect the bounding box.
Kernel::V3D centrePoint() const
Returns the centre of the bounding box.
Definition BoundingBox.h:93
double yMin() const
Return the minimum value of Y.
Definition BoundingBox.h:81
Triangular Mesh Object.
Definition MeshObject.h:53
Kernel::Material m_material
material composition
Definition MeshObject.h:187
std::optional< Kernel::V3D > generatePointInObject(Kernel::PseudoRandomNumberGenerator &rng, const size_t) const override
Select a random point within the object.
void translate(const Kernel::V3D &)
Translate the mesh according to the supplied x, y, z vector.
int getPointInObject(Kernel::V3D &point) const override
Try to find a point that lies within (or on) the object.
size_t numberOfTriangles() const
Output functions for rendering, may also be used internally.
int interceptSurface(Geometry::Track &) const override
Given a track, fill the track with valid section.
const detail::ShapeInfo & shapeInfo() const override
std::vector< double > getVertices() const
get vertices
detail::ShapeInfo::GeometryShape shape() const override
std::vector< Kernel::V3D > m_vertices
Definition MeshObject.h:185
bool hasValidShape() const override
Return whether this object has a valid shape.
bool isValid(const Kernel::V3D &) const override
Check if a point is inside.
void setMaterial(const Kernel::Material &material) override
void draw() const override
Draws the Object using geometry handler, If the handler is not set then this function does nothing.
MeshObject(std::vector< uint32_t > faces, std::vector< Kernel::V3D > vertices, const Kernel::Material &material)
Constructor.
const BoundingBox & getBoundingBox() const override
Return cached value of axis-aligned bounding box.
void getIntersections(const Kernel::V3D &start, const Kernel::V3D &direction, std::vector< Kernel::V3D > &intersectionPoints, std::vector< Mantid::Geometry::TrackDirection > &entryExitFlags) const
Get intersections.
const std::vector< Kernel::V3D > & getV3Ds() const
get vertices in V3D form
double volume() const override
Calculates the volume of this object.
void saveNexus(Nexus::File *file, const std::string &group) const
Save mesh to an NXoff_geometry group in a NeXus file.
std::vector< uint32_t > m_triangles
Contents Triangles are specified by indices into a list of vertices.
Definition MeshObject.h:184
void scale(const double scaleFactor)
Scale the mesh according to the supplied scale factor.
bool searchForObject(Kernel::V3D &point) const
Search object for valid point.
void initDraw() const override
Initializes/prepares the object to be rendered, this will generate geometry for object,...
size_t numberOfVertices() const
Read access to mesh object for rendering.
void updateGeometryHandler()
Updates the geometry handler if needed.
static std::shared_ptr< MeshObject > loadNexus(Nexus::File *file, const std::string &group, const Kernel::Material &material)
Load mesh from an NXoff_geometry group in a NeXus file.
const Kernel::Material & material() const override
std::shared_ptr< GeometryHandler > m_handler
Geometry Handle for rendering.
Definition MeshObject.h:169
std::shared_ptr< GeometryHandler > getGeometryHandler() const override
Returns the geometry handler.
void multiply(const Kernel::Matrix< double > &)
Transform the mesh (scale, translate, rotate) according to the supplied transformation matrix.
bool getTriangle(const size_t index, Kernel::V3D &v1, Kernel::V3D &v2, Kernel::V3D &v3) const
Get triangle.
void rotate(const Kernel::Matrix< double > &)
Rotate the mesh according to the supplied rotation matrix.
const std::vector< uint32_t > & getTriangles() const
get faces
int calcValidType(const Kernel::V3D &Pt, const Kernel::V3D &uVec) const
Calculate if a point PT is a valid point on the track.
BoundingBox m_boundingBox
Cache for object's bounding box.
Definition MeshObject.h:163
double solidAngle(const SolidAngleParams &params) const override
Find solid angle of object wrt the observer.
bool isOnSide(const Kernel::V3D &) const override
Determines wither point is on the surface.
void GetObjectGeom(detail::ShapeInfo::GeometryShape &type, std::vector< Kernel::V3D > &vectors, double &innerRadius, double &radius, double &height) const override
get info on standard shapes (none for Mesh Object)
void setGeometryHandler(const std::shared_ptr< GeometryHandler > &h)
Set Geometry Handler.
double distance(const Track &track) const override
Compute the distance to the first point of intersection with the surface.
const Kernel::V3D & observer() const
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
void addPoint(const TrackDirection direction, const Kernel::V3D &endPoint, const IObject &obj, const ComponentID compID=nullptr)
Adds a point of intersection to the track.
Definition Track.cpp:124
void buildLink()
Construct links between added points.
Definition Track.cpp:184
int count() const
Returns the number of links.
Definition Track.h:219
const Kernel::V3D & direction() const
Returns the direction as a unit vector.
Definition Track.h:193
LType::const_iterator cbegin() const
Returns an interator to the start of the set of links (const version)
Definition Track.h:206
A material is defined as being composed of a given element, defined as a PhysicalConstants::NeutronAt...
Definition Material.h:50
Numerical Matrix class.
Definition Matrix.h:42
void multiplyPoint(const std::vector< T > &in, std::vector< T > &out) const
Multiply M*Vec.
Definition Matrix.cpp:375
size_t numRows() const
Return the number of rows in the matrix.
Definition Matrix.h:144
size_t numCols() const
Return the number of columns in the matrix.
Definition Matrix.h:147
Defines a 1D pseudo-random number generator, i.e.
Class for 3D vectors.
Definition V3D.h:34
double distance(const V3D &v) const noexcept
Calculates the distance between two vectors.
Definition V3D.h:293
std::size_t size() const noexcept
Number of components in V3D.
Definition V3D.h:49
constexpr double scalar_prod(const V3D &v) const noexcept
Calculates the cross product.
Definition V3D.h:280
constexpr V3D cross_prod(const V3D &v) const noexcept
Cross product (this * argument)
Definition V3D.h:284
MANTID_GEOMETRY_DLL bool rayIntersectsTriangle(const Kernel::V3D &start, const Kernel::V3D &direction, const Kernel::V3D &v1, const Kernel::V3D &v2, const Kernel::V3D &v3, Kernel::V3D &intersection, TrackDirection &entryExit)
Get intersection points and their in out directions on the given ray.
MANTID_GEOMETRY_DLL void checkVertexLimit(size_t nVertices)
MANTID_GEOMETRY_DLL std::vector< double > getVertices(const std::vector< Kernel::V3D > &vertices)
getVertices converts vector Kernel::V3D to vector doubles.
MANTID_GEOMETRY_DLL double getTriangleSolidAngle(const Kernel::V3D &a, const Kernel::V3D &b, const Kernel::V3D &c, const Kernel::V3D &observer)
Find the solid angle of a triangle defined by vectors a,b,c from point "observer".
MANTID_GEOMETRY_DLL const BoundingBox & getBoundingBox(const std::vector< Kernel::V3D > &vertices, BoundingBox &cacheBB)
Takes input vertices and calculates bounding box.
std::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
bool MANTID_GEOMETRY_DLL intersection(const ConvexPolygon &P, const ConvexPolygon &Q, ConvexPolygon &out)
Compute the instersection of two convex polygons.
constexpr double Tolerance
Standard tolerance value.
Definition Tolerance.h:12
STL namespace.