Mantid
Loading...
Searching...
No Matches
SaveSampleEnvironmentAndShape.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 +
11#include "MantidAPI/Sample.h"
12#ifdef ENABLE_LIB3MF
14#endif
19
20#include <filesystem>
21#include <memory>
22
23namespace Mantid::DataHandling {
24// Register the algorithm into the algorithm factory
25DECLARE_ALGORITHM(SaveSampleEnvironmentAndShape)
26
27using namespace Kernel;
28using namespace API;
29using namespace Geometry;
30
32 auto wsValidator = std::make_shared<InstrumentValidator>();
33
34 // input workspace
35 declareProperty(std::make_unique<WorkspaceProperty<>>("InputWorkspace", "", Direction::Input, wsValidator),
36 "The name of the workspace containing the environment to save ");
37
38 // Environment file
39 const std::vector<std::string> extensions{".stl", ".3mf"};
40 declareProperty(std::make_unique<FileProperty>("Filename", "", FileProperty::Save, extensions),
41 "The path name of the file to save");
42
43 // scale to use for stl
44 declareProperty("Scale", "m", "The scale of the stl: m, cm, or mm");
45}
46
48 const MeshObject &sampleShape, const std::vector<const Geometry::MeshObject *> &environmentPieces) {
49
50 if (environmentPieces.size() > 0) {
51
52 // get the sample vertices and triangles and add them into the vector
53 addMeshToVector(sampleShape);
54
55 // keep track of the current number of vertices added
56 size_t offset = sampleShape.numberOfVertices();
57
58 // go through the environment, adding the triangles and vertices to the
59 // vector
60 for (size_t i = 0; i < environmentPieces.size(); ++i) {
61 offset = addMeshToVector(*environmentPieces[i], offset);
62 }
63 } else {
64 // get the sample vertices and triangles and add them into the vector
65 addMeshToVector(sampleShape);
66 }
67}
68
70 MatrixWorkspace_const_sptr inputWS = getProperty("InputWorkspace");
71 // track the total number of triangles and vertices
72 size_t numTriangles = 0;
73 size_t numVertices = 0;
74
75 // Get the shape of the sample
76 const auto &sampleShape = toMeshObject(inputWS->sample().getShape());
77 if (!sampleShape.hasValidShape()) {
78 throw std::invalid_argument("Sample Shape is not complete");
79 }
80 numVertices += sampleShape.numberOfVertices();
81 numTriangles += (sampleShape.numberOfTriangles() * 3);
82
83 // Setup vector to store the pieces of the environment
84 std::vector<const MeshObject *> environmentPieces;
85
86 if (inputWS->sample().hasEnvironment()) {
87 // get the environment
88 auto environment = inputWS->sample().getEnvironment();
89
90 auto numElements = environment.nelements();
91 environmentPieces.reserve(numElements);
92
93 // get the shape the container of the environment and add it to the vector
94 bool environmentValid = true;
95 environmentPieces.emplace_back(&toMeshObject(environment.getContainer().getShape()));
96 environmentValid = environmentValid && environmentPieces[0]->hasValidShape();
97 numVertices += environmentPieces[0]->numberOfVertices();
98 numTriangles += (environmentPieces[0]->numberOfTriangles() * 3);
99
100 // get the shapes of the components and add them to the vector
101 for (size_t i = 1; i < numElements; ++i) { // start at 1 because element 0 is container
102 const MeshObject *temp = &toMeshObject(environment.getComponent(i));
103 numVertices += temp->numberOfVertices();
104 numTriangles += (temp->numberOfTriangles() * 3);
105 environmentValid = environmentValid && temp->hasValidShape();
106 environmentPieces.emplace_back(temp);
107 }
108 if (!environmentValid) {
109 throw std::invalid_argument("Environment Shape is not complete");
110 }
111 }
112 // get the scale to use
113 auto scale = getPropertyValue("Scale");
114 auto scaleType = getScaleTypeFromStr(scale);
115
116 // Save out the shape
117 auto filename = getPropertyValue("Filename");
118 std::string fileExt = std::filesystem::path(filename).extension().string().substr(1); // remove the '.'
119 std::transform(fileExt.begin(), fileExt.end(), fileExt.begin(), toupper);
120
121 if (fileExt == "STL") {
122 // setup vectors to store all triangles and vertices
123 m_vertices.reserve(numVertices);
124 m_triangle.reserve(numTriangles);
125 mergeSampleEnvironmentIntoSingleMesh(sampleShape, environmentPieces);
126 SaveStl writer = SaveStl(filename, m_triangle, m_vertices, scaleType);
127 writer.writeStl();
128 } else {
129#ifdef ENABLE_LIB3MF
130 Mantid3MFFileIO Mesh3MF;
131 auto samplePtr = MeshObject_const_sptr(&sampleShape);
132 Mesh3MF.writeMeshObjects(environmentPieces, samplePtr, scaleType);
133 Mesh3MF.saveFile(filename);
134#else
135 throw std::runtime_error("3MF format not supported on this platform");
136#endif
137 }
138}
139
147 auto vertices = mesh.getV3Ds();
148 auto triangles = mesh.getTriangles();
149 m_vertices.insert(std::end(m_vertices), std::begin(vertices), std::end(vertices));
150 m_triangle.insert(std::end(m_triangle), std::begin(triangles), std::end(triangles));
151}
152
164 auto vertices = mesh.getV3Ds();
165 auto triangles = mesh.getTriangles();
166
167 // increase the triangles by the offset, so they refer to the new index of
168 // the vertices
169 std::transform(std::begin(triangles), std::end(triangles), std::begin(triangles),
170 [&offset](const uint32_t &val) { return val + uint32_t(offset); });
171 m_vertices.insert(std::end(m_vertices), std::begin(vertices), std::end(vertices));
172 m_triangle.insert(std::end(m_triangle), std::begin(triangles), std::end(triangles));
173
174 // add the newly added vertices to the offset
175 return offset += vertices.size();
176}
177
185
186 try {
187 return dynamic_cast<const Geometry::MeshObject &>(object);
188 } catch (const std::bad_cast &) {
189 // if bad_cast is thrown the sample or environment is not a mesh_object, and
190 // therefore cannot be saved as an STL
191 throw std::invalid_argument("Attempted to Save out non mesh based Sample or Environment");
192 }
193}
194} // namespace Mantid::DataHandling
#define DECLARE_ALGORITHM(classname)
Definition Algorithm.h:538
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
std::string getPropertyValue(const std::string &name) const override
Get the value of a property as a string.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
@ Save
to specify a file to write to, the file may or may not exist
A property class for workspaces.
Class to load and save .3mf files .3mf format is a 3D manufacturing format for storing mesh descripti...
void writeMeshObjects(std::vector< const Geometry::MeshObject * > meshObjects, MeshObject_const_sptr &sample, DataHandling::ScaleUnits scale)
void init() override
Virtual method - must be overridden by concrete algorithm.
void addMeshToVector(const Mantid::Geometry::MeshObject &mesh)
Function to add the triangles and vertices of a mesh object into a vector to allow combining with mul...
void mergeSampleEnvironmentIntoSingleMesh(const Mantid::Geometry::MeshObject &sample, const std::vector< const Geometry::MeshObject * > &environmentPieces)
void exec() override
Virtual method - must be overridden by concrete algorithm.
Class to contain functionality for writing out STL files for SaveShapeAndEnvironment.
Definition SaveStl.h:30
void writeStl()
Function to write out the full mesh to an stl binary file.
Definition SaveStl.cpp:78
IObject : Interface for geometry objects.
Definition IObject.h:42
Triangular Mesh Object.
Definition MeshObject.h:50
size_t numberOfTriangles() const
Output functions for rendering, may also be used internally.
bool hasValidShape() const override
Return whether this object has a valid shape.
const std::vector< Kernel::V3D > & getV3Ds() const
get vertices in V3D form
size_t numberOfVertices() const
Read access to mesh object for rendering.
const std::vector< uint32_t > & getTriangles() const
get faces
std::shared_ptr< const MatrixWorkspace > MatrixWorkspace_const_sptr
shared pointer to the matrix workspace base class (const version)
const Mantid::Geometry::MeshObject & toMeshObject(const Mantid::Geometry::IObject &object)
Function to convert an IObject to a mesh, and throw if this can't be done.
std::shared_ptr< const Geometry::MeshObject > MeshObject_const_sptr
Typdef for a shared pointer to a const object.
ScaleUnits getScaleTypeFromStr(const std::string &scaleProperty)
Definition MeshFileIO.h:73
@ Input
An input workspace.
Definition Property.h:53