16#include "MantidNexus/NexusFile.h"
25 : m_boundingBox(), m_id(
"MeshObject"), m_triangles(
std::move(faces)), m_vertices(
std::move(vertices)),
26 m_material(material) {
33 : m_boundingBox(), m_id(
"MeshObject"), m_triangles(
std::move(faces)), m_vertices(
std::move(vertices)),
34 m_material(material) {
43 m_handler = std::make_shared<GeometryHandler>(*
this);
80 std::vector<Kernel::V3D> intersectionPoints;
81 std::vector<TrackDirection> entryExitFlags;
85 if (intersectionPoints.empty()) {
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())
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;
124 for (
const auto &direction : directions) {
125 std::vector<Kernel::V3D> intersectionPoints;
126 std::vector<TrackDirection> entryExitFlags;
130 if (intersectionPoints.empty()) {
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())
149 int originalCount = UT.
count();
155 std::vector<Kernel::V3D> intersectionPoints;
156 std::vector<TrackDirection> entryExit;
159 if (intersectionPoints.empty())
163 for (
size_t i = 0; i < intersectionPoints.size(); ++i) {
164 UT.
addPoint(entryExit[i], intersectionPoints[i], *
this);
168 return UT.
count() - originalCount;
180 for (
size_t i = 0;
getTriangle(i, vertex1, vertex2, vertex3); ++i) {
186 std::ostringstream os;
187 os <<
"Unable to find intersection with object with track starting at " << track.
startPoint() <<
" in direction "
189 throw std::runtime_error(os.str());
200 std::vector<Kernel::V3D> &intersectionPoints,
201 std::vector<TrackDirection> &entryExitFlags)
const {
205 for (
size_t i = 0;
getTriangle(i, vertex1, vertex2, vertex3); ++i) {
208 entryExitFlags.emplace_back(entryExit);
225 if (triangleExists) {
230 return triangleExists;
245 const int flagA =
isValid(testA);
246 const int flagB =
isValid(testB);
247 if (!(flagA ^ flagB))
249 return (flagA) ? -1 : 1;
265 double &zmin)
const {
275 double solidAngleSum(0), solidAngleNegativeSum(0);
277 for (
size_t i = 0; this->
getTriangle(i, vertex1, vertex2, vertex3); ++i) {
282 solidAngleNegativeSum += sa;
292 return 0.5 * (solidAngleSum - solidAngleNegativeSum);
303 std::vector<Kernel::V3D> scaledVertices;
306 [&scaleFactor](
const auto &vertex) { return scaleFactor * vertex; });
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());
327 double volumeTimesSix(0.0);
330 for (
size_t i = 0;
getTriangle(i, vertex1, vertex2, vertex3); ++i) {
337 return volumeTimesSix / 6.0;
379 const size_t maxAttempts)
const {
382 throw std::runtime_error(
"Object::generatePointInObject() - Invalid "
383 "bounding box. Cannot generate new point.");
400 const size_t maxAttempts)
const {
423 point = tr.
cbegin()->entryPoint;
479 [&rotationMatrix](
auto &vertex) { vertex.rotate(rotationMatrix); });
488 [&translationVector](
const auto &vertex) { return vertex + translationVector; });
497 [&scaleFactor](
const auto &vertex) { return vertex * scaleFactor; });
507 throw "Transformation matrix must be 4 x 4";
513 std::vector<double> vertexin(4);
514 vertexin[0] = vertex.X();
515 vertexin[1] = vertex.Y();
516 vertexin[2] = vertex.Z();
518 std::vector<double> vertexout(4);
520 Kernel::V3D newvertex(vertexout[0], vertexout[1], vertexout[2]);
560 throw std::runtime_error(
"MeshObject::shapeInfo() is not implemented");
567 double &innerRadius,
double &radius,
double &
height)
const {
578 file->makeGroup(
group,
"NXoff_geometry",
true);
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);
587 file->writeData(
"faces", faceIndices);
593 file->openGroup(
group,
"NXoff_geometry");
595 std::vector<double> flatVertices;
596 file->readData(
"vertices", flatVertices);
598 std::vector<uint32_t> windingOrder;
599 file->readData(
"winding_order", windingOrder);
601 std::vector<uint32_t> faceIndices;
602 file->readData(
"faces", faceIndices);
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]);
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;
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));
629 return std::make_shared<MeshObject>(std::move(triangles), std::move(vertices),
material);
std::map< DeltaEMode::Type, std::string > index
A simple structure that defines an axis-aligned cuboid shaped bounding box for a geometrical object.
bool isPointInside(const Kernel::V3D &point) const
Is the given point within the bounding box?
double xMax() const
Return the maximum value of X.
bool isNonNull() const
Is the box considered valid. Convenience for !isNull()
double zMin() const
Return the minimum value of Z.
double zMax() const
Return the maximum value of Z.
double yMax() const
Return the maximum value of Y.
double xMin() const
Return the minimum value of X.
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.
double yMin() const
Return the minimum value of Y.
Kernel::Material m_material
material composition
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
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.
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.
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.
double solidAngle(const SolidAngleParams ¶ms) 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.
const Kernel::V3D & startPoint() const
Returns the starting point.
void addPoint(const TrackDirection direction, const Kernel::V3D &endPoint, const IObject &obj, const ComponentID compID=nullptr)
Adds a point of intersection to the track.
void buildLink()
Construct links between added points.
int count() const
Returns the number of links.
const Kernel::V3D & direction() const
Returns the direction as a unit vector.
LType::const_iterator cbegin() const
Returns an interator to the start of the set of links (const version)
A material is defined as being composed of a given element, defined as a PhysicalConstants::NeutronAt...
void multiplyPoint(const std::vector< T > &in, std::vector< T > &out) const
Multiply M*Vec.
size_t numRows() const
Return the number of rows in the matrix.
size_t numCols() const
Return the number of columns in the matrix.
Defines a 1D pseudo-random number generator, i.e.
double distance(const V3D &v) const noexcept
Calculates the distance between two vectors.
std::size_t size() const noexcept
Number of components in V3D.
constexpr double scalar_prod(const V3D &v) const noexcept
Calculates the cross product.
constexpr V3D cross_prod(const V3D &v) const noexcept
Cross product (this * argument)
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.
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.