Skip to content
Snippets Groups Projects
Commit 0771ef92 authored by Karl Palmen's avatar Karl Palmen
Browse files

Move shape reading functions into anonymous namespace re #12828


This required reordering of these functions

Also hopefully final stage or renaming

Signed-off-by: default avatarKarl Palmen <karl.palmen@stfc.ac.uk>
parent 46bad3cd
No related branches found
No related tags found
No related merge requests found
......@@ -63,19 +63,6 @@ private:
// Implement abstract Algorithm methods
void init() override;
void exec() override;
std::unique_ptr<Geometry::MeshObject> readSTLSolid(std::ifstream &file,
std::string &name);
std::unique_ptr<Geometry::MeshObject> readSTLMeshObject(std::ifstream &file);
bool readSTLTriangle(std::ifstream &file, Kernel::V3D &v1, Kernel::V3D &v2,
Kernel::V3D &v3);
bool readSTLVertex(std::ifstream &file, Kernel::V3D &v);
bool readSTLLine(std::ifstream &file, std::string const &linetype);
uint16_t addSTLVertex(Kernel::V3D &vertex,
std::vector<Kernel::V3D> &vertices);
bool areEqualVertices(Kernel::V3D const &v1, Kernel::V3D const &v2) const {
Kernel::V3D diff = v1 - v2;
return diff.norm() < 1e-9;
}
};
} // end namespace DataHandling
......
......@@ -18,12 +18,139 @@
namespace Mantid {
namespace DataHandling {
// Register the algorithm into the algorithm factory
DECLARE_ALGORITHM(LoadSampleShape)
using namespace Kernel;
using namespace API;
using namespace Geometry;
// Register the algorithm into the algorithm factory
DECLARE_ALGORITHM(LoadSampleShape)
using namespace Kernel;
using namespace API;
using namespace Geometry;
namespace {
bool areEqualVertices(Kernel::V3D const &v1, Kernel::V3D const &v2) {
Kernel::V3D diff = v1 - v2;
return diff.norm() < 1e-9;
}
// Read, check and ignore line in STL file. Return true if line is read
bool readSTLLine(std::ifstream &file, std::string const &type) {
std::string line;
if (getline(file, line)) {
boost::trim(line);
if (line.size() < type.size() || line.substr(0, type.size()) != type) {
// Before throwing, check for endsolid statment
std::string type2 = "endsolid";
if (line.size() < type2.size() || line.substr(0, type2.size()) != type2) {
throw std::runtime_error("Expected STL line begining with " + type +
" or " + type2);
}
else {
return false; // ends reading at endsolid
}
}
return true; // expected line read, then ignored
}
else {
return false; // end of file
}
}
/* Reads vertex from STL file and returns true if vertex is found */
bool readSTLVertex(std::ifstream &file, V3D &vertex) {
std::string line;
if (getline(file, line)) {
boost::trim(line);
std::vector<std::string> tokens;
boost::split(tokens, line, boost::is_any_of(" "), boost::token_compress_on);
if (tokens.size() == 4 && tokens[0] == "vertex") {
vertex.setX(boost::lexical_cast<double>(tokens[1]));
vertex.setY(boost::lexical_cast<double>(tokens[2]));
vertex.setZ(boost::lexical_cast<double>(tokens[3]));
return true;
}
else {
throw std::runtime_error("Error on reading STL vertex");
}
}
return false;
}
/* Reads triangle for STL file and returns true if triangle is found */
bool readSTLTriangle(std::ifstream &file, V3D &v1, V3D &v2,
V3D &v3) {
if (readSTLLine(file, "facet") && readSTLLine(file, "outer loop")) {
bool ok = (readSTLVertex(file, v1) && readSTLVertex(file, v2) &&
readSTLVertex(file, v3));
if (!ok) {
throw std::runtime_error("Error on reading STL triangle");
}
}
else {
return false; // End of file
}
return readSTLLine(file, "endloop") && readSTLLine(file, "endfacet");
}
// Adds vertex to list if distinct and returns index to vertex added or equal
uint16_t addSTLVertex(V3D &vertex, std::vector<V3D> &vertices) {
for (uint16_t i = 0; i < vertices.size(); ++i) {
if (areEqualVertices(vertex, vertices[i])) {
return i;
}
}
vertices.push_back(vertex);
uint16_t index = static_cast<uint16_t>(vertices.size() - 1);
if (index != vertices.size() - 1) {
throw std::runtime_error("Too many vertices in solid");
}
return index;
}
std::unique_ptr<MeshObject> readSTLMeshObject(std::ifstream &file) {
std::vector<uint16_t> triangleIndices;
std::vector<V3D> vertices;
V3D t1, t2, t3;
while (readSTLTriangle(file, t1, t2, t3)) {
// Add triangle if all 3 vertices are distinct
if (!areEqualVertices(t1, t2) && !areEqualVertices(t1, t3) &&
!areEqualVertices(t2, t3)) {
triangleIndices.push_back(addSTLVertex(t1, vertices));
triangleIndices.push_back(addSTLVertex(t2, vertices));
triangleIndices.push_back(addSTLVertex(t3, vertices));
}
}
// Use efficient constructor of MeshObject
std::unique_ptr<MeshObject> retVal = std::unique_ptr<MeshObject>(
new MeshObject(std::move(triangleIndices), std::move(vertices),
Mantid::Kernel::Material()));
return retVal;
}
std::unique_ptr<Geometry::MeshObject> readSTLSolid(std::ifstream &file, std::string &name) {
// Read Solid name
// We expect line after trimming to be "solid "+name.
std::string line;
if (getline(file, line)) {
boost::trim(line);
if (line.size() < 5 || line.substr(0, 5) != "solid") {
throw std::runtime_error("Expected start of solid");
}
else {
name = line.substr(6, std::string::npos);
}
// Read Solid shape
return readSTLMeshObject(file);
}
return nullptr;
}
} // end anonymous namespace
void LoadSampleShape::init() {
auto wsValidator = boost::make_shared<API::InstrumentValidator>();
......@@ -99,118 +226,6 @@ void LoadSampleShape::exec() {
setProperty("OutputWorkspace", outputWS);
}
std::unique_ptr<Geometry::MeshObject>
LoadSampleShape::readSTLSolid(std::ifstream &file, std::string &name) {
// Read Solid name
// We expect line after trimming to be "solid "+name.
std::string line;
if (getline(file, line)) {
boost::trim(line);
if (line.size() < 5 || line.substr(0, 5) != "solid") {
throw std::runtime_error("Expected start of solid");
} else {
name = line.substr(6, std::string::npos);
}
// Read Solid shape
return readSTLMeshObject(file);
}
return nullptr;
}
std::unique_ptr<MeshObject>
LoadSampleShape::readSTLMeshObject(std::ifstream &file) {
std::vector<uint16_t> triangleIndices;
std::vector<V3D> vertices;
V3D t1, t2, t3;
while (readSTLTriangle(file, t1, t2, t3)) {
// Add triangle if all 3 vertices are distinct
if (!areEqualVertices(t1, t2) && !areEqualVertices(t1, t3) &&
!areEqualVertices(t2, t3)) {
triangleIndices.push_back(addSTLVertex(t1, vertices));
triangleIndices.push_back(addSTLVertex(t2, vertices));
triangleIndices.push_back(addSTLVertex(t3, vertices));
}
}
// Use efficient constructor of MeshObject
std::unique_ptr<MeshObject> retVal = std::unique_ptr<MeshObject>(
new MeshObject(std::move(triangleIndices), std::move(vertices),
Mantid::Kernel::Material()));
return retVal;
}
/* Reads triangle for STL file and returns true if triangle is found */
bool LoadSampleShape::readSTLTriangle(std::ifstream &file, V3D &v1, V3D &v2,
V3D &v3) {
if (readSTLLine(file, "facet") && readSTLLine(file, "outer loop")) {
bool ok = (readSTLVertex(file, v1) && readSTLVertex(file, v2) &&
readSTLVertex(file, v3));
if (!ok) {
throw std::runtime_error("Error on reading STL triangle");
}
} else {
return false; // End of file
}
return readSTLLine(file, "endloop") && readSTLLine(file, "endfacet");
}
/* Reads vertex from STL file and returns true if vertex is found */
bool LoadSampleShape::readSTLVertex(std::ifstream &file, V3D &vertex) {
std::string line;
if (getline(file, line)) {
boost::trim(line);
std::vector<std::string> tokens;
boost::split(tokens, line, boost::is_any_of(" "), boost::token_compress_on);
if (tokens.size() == 4 && tokens[0] == "vertex") {
vertex.setX(boost::lexical_cast<double>(tokens[1]));
vertex.setY(boost::lexical_cast<double>(tokens[2]));
vertex.setZ(boost::lexical_cast<double>(tokens[3]));
return true;
} else {
throw std::runtime_error("Error on reading STL vertex");
}
}
return false;
}
// Read, check and ignore line in STL file. Return true if line is read
bool LoadSampleShape::readSTLLine(std::ifstream &file,
std::string const &type) {
std::string line;
if (getline(file, line)) {
boost::trim(line);
if (line.size() < type.size() || line.substr(0, type.size()) != type) {
// Before throwing, check for endsolid statment
std::string type2 = "endsolid";
if (line.size() < type2.size() || line.substr(0, type2.size()) != type2) {
throw std::runtime_error("Expected STL line begining with " + type +
" or " + type2);
} else {
return false; // ends reading at endsolid
}
}
return true; // expected line read, then ignored
} else {
return false; // end of file
}
}
// Adds vertex to list if distinct and returns index to vertex added or equal
uint16_t LoadSampleShape::addSTLVertex(V3D &vertex,
std::vector<V3D> &vertices) {
for (uint16_t i = 0; i < vertices.size(); ++i) {
if (areEqualVertices(vertex, vertices[i])) {
return i;
}
}
vertices.push_back(vertex);
uint16_t index = static_cast<uint16_t>(vertices.size() - 1);
if (index != vertices.size() - 1) {
throw std::runtime_error("Too many vertices in solid");
}
return index;
}
} // end DataHandling namespace
} // end MantidNamespace
......@@ -24,7 +24,7 @@ public:
}
static void destroySuite(LoadSampleShapeTest *suite) { delete suite; }
void testName() { TS_ASSERT_EQUALS(loadShape.name(), "LoadShape"); }
void testName() { TS_ASSERT_EQUALS(loadShape.name(), "LoadSampleShape"); }
void testVersion() { TS_ASSERT_EQUALS(loadShape.version(), 1); }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment