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 <memory>
21
22#include <Poco/Path.h>
23
24namespace Mantid::DataHandling {
25// Register the algorithm into the algorithm factory
26DECLARE_ALGORITHM(SaveSampleEnvironmentAndShape)
27
28using namespace Kernel;
29using namespace API;
30using namespace Geometry;
31
33 auto wsValidator = std::make_shared<InstrumentValidator>();
34
35 // input workspace
36 declareProperty(std::make_unique<WorkspaceProperty<>>("InputWorkspace", "", Direction::Input, wsValidator),
37 "The name of the workspace containing the environment to save ");
38
39 // Environment file
40 const std::vector<std::string> extensions{".stl", ".3mf"};
41 declareProperty(std::make_unique<FileProperty>("Filename", "", FileProperty::Save, extensions),
42 "The path name of the file to save");
43
44 // scale to use for stl
45 declareProperty("Scale", "m", "The scale of the stl: m, cm, or mm");
46}
47
49 const MeshObject &sampleShape, const std::vector<const Geometry::MeshObject *> &environmentPieces) {
50
51 if (environmentPieces.size() > 0) {
52
53 // get the sample vertices and triangles and add them into the vector
54 addMeshToVector(sampleShape);
55
56 // keep track of the current number of vertices added
57 size_t offset = sampleShape.numberOfVertices();
58
59 // go through the environment, adding the triangles and vertices to the
60 // vector
61 for (size_t i = 0; i < environmentPieces.size(); ++i) {
62 offset = addMeshToVector(*environmentPieces[i], offset);
63 }
64 } else {
65 // get the sample vertices and triangles and add them into the vector
66 addMeshToVector(sampleShape);
67 }
68}
69
71 MatrixWorkspace_const_sptr inputWS = getProperty("InputWorkspace");
72 // track the total number of triangles and vertices
73 size_t numTriangles = 0;
74 size_t numVertices = 0;
75
76 // Get the shape of the sample
77 auto &sampleShape = toMeshObject(inputWS->sample().getShape());
78 if (!sampleShape.hasValidShape()) {
79 throw std::invalid_argument("Sample Shape is not complete");
80 }
81 numVertices += sampleShape.numberOfVertices();
82 numTriangles += (sampleShape.numberOfTriangles() * 3);
83
84 // Setup vector to store the pieces of the environment
85 std::vector<const MeshObject *> environmentPieces;
86
87 if (inputWS->sample().hasEnvironment()) {
88 // get the environment
89 auto environment = inputWS->sample().getEnvironment();
90
91 auto numElements = environment.nelements();
92 environmentPieces.reserve(numElements);
93
94 // get the shape the container of the environment and add it to the vector
95 bool environmentValid = true;
96 environmentPieces.emplace_back(&toMeshObject(environment.getContainer().getShape()));
97 environmentValid = environmentValid && environmentPieces[0]->hasValidShape();
98 numVertices += environmentPieces[0]->numberOfVertices();
99 numTriangles += (environmentPieces[0]->numberOfTriangles() * 3);
100
101 // get the shapes of the components and add them to the vector
102 for (size_t i = 1; i < numElements; ++i) { // start at 1 because element 0 is container
103 const MeshObject *temp = &toMeshObject(environment.getComponent(i));
104 numVertices += temp->numberOfVertices();
105 numTriangles += (temp->numberOfTriangles() * 3);
106 environmentValid = environmentValid && temp->hasValidShape();
107 environmentPieces.emplace_back(temp);
108 }
109 if (!environmentValid) {
110 throw std::invalid_argument("Environment Shape is not complete");
111 }
112 }
113 // get the scale to use
114 auto scale = getPropertyValue("Scale");
115 auto scaleType = getScaleTypeFromStr(scale);
116
117 // Save out the shape
118 auto filename = getPropertyValue("Filename");
119 std::string fileExt = Poco::Path(filename).getExtension();
120 std::transform(fileExt.begin(), fileExt.end(), fileExt.begin(), toupper);
121
122 if (fileExt == "STL") {
123 // setup vectors to store all triangles and vertices
124 m_vertices.reserve(numVertices);
125 m_triangle.reserve(numTriangles);
126 mergeSampleEnvironmentIntoSingleMesh(sampleShape, environmentPieces);
127 SaveStl writer = SaveStl(filename, m_triangle, m_vertices, scaleType);
128 writer.writeStl();
129 } else {
130#ifdef ENABLE_LIB3MF
131 Mantid3MFFileIO Mesh3MF;
132 Mesh3MF.writeMeshObjects(environmentPieces, MeshObject_const_sptr(&sampleShape), 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:576
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
Definition: Algorithm.cpp:1913
std::string getPropertyValue(const std::string &name) const override
Get the value of a property as a string.
Definition: Algorithm.cpp:2026
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Definition: Algorithm.cpp:2076
@ Save
to specify a file to write to, the file may or may not exist
Definition: FileProperty.h:49
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 saveFile(std::string filename)
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:79
IObject : Interface for geometry objects.
Definition: IObject.h:41
Triangular Mesh Object.
Definition: MeshObject.h:50
size_t numberOfTriangles() const
Output functions for rendering, may also be used internally.
Definition: MeshObject.cpp:534
bool hasValidShape() const override
Return whether this object has a valid shape.
Definition: MeshObject.cpp:60
std::vector< uint32_t > getTriangles() const
get faces
Definition: MeshObject.cpp:539
const std::vector< Kernel::V3D > & getV3Ds() const
get vertices in V3D form
Definition: MeshObject.cpp:554
size_t numberOfVertices() const
Read access to mesh object for rendering.
Definition: MeshObject.cpp:544
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