Implemented some of the tests and additional object code to pass tests.

Using [!mayfail] to indicate that test may fail (so as to not crash build).
This commit is contained in:
Joseph Lenox 2018-07-09 22:40:18 -05:00 committed by Joseph Lenox
parent 83af35b7c4
commit 21946dc1a1
3 changed files with 111 additions and 33 deletions

View File

@ -10,43 +10,41 @@ SCENARIO( "TriangleMesh: Basic mesh statistics") {
const Pointf3s vertices { Pointf3(20,20,0), Pointf3(20,0,0), Pointf3(0,0,0), Pointf3(0,20,0), Pointf3(20,20,20), Pointf3(0,20,20), Pointf3(0,0,20), Pointf3(20,0,20) }; const Pointf3s vertices { Pointf3(20,20,0), Pointf3(20,0,0), Pointf3(0,0,0), Pointf3(0,20,0), Pointf3(20,20,20), Pointf3(0,20,20), Pointf3(0,0,20), Pointf3(20,0,20) };
const Point3s facets { Point3(0,1,2), Point3(0,2,3), Point3(4,5,6), Point3(4,6,7), Point3(0,4,7), Point3(0,7,1), Point3(1,7,6), Point3(1,6,2), Point3(2,6,5), Point3(2,5,3), Point3(4,0,3), Point3(4,3,5) }; const Point3s facets { Point3(0,1,2), Point3(0,2,3), Point3(4,5,6), Point3(4,6,7), Point3(0,4,7), Point3(0,7,1), Point3(1,7,6), Point3(1,6,2), Point3(2,6,5), Point3(2,5,3), Point3(4,0,3), Point3(4,3,5) };
auto* cube {new TriangleMesh(vertices, facets)}; auto cube {TriangleMesh(vertices, facets)};
cube->repair(); cube.repair();
THEN( "Volume is appropriate for 20mm square cube.") { THEN( "Volume is appropriate for 20mm square cube.") {
REQUIRE(abs(cube->volume() - 20.0*20.0*20.0) < 1e-2); REQUIRE(abs(cube.volume() - 20.0*20.0*20.0) < 1e-2);
} }
THEN( "Vertices array matches input.") { THEN( "Vertices array matches input.") {
for (auto i = 0U; i < cube->vertices().size(); i++) { for (auto i = 0U; i < cube.vertices().size(); i++) {
REQUIRE(cube->vertices().at(i) == vertices.at(i)); REQUIRE(cube.vertices().at(i) == vertices.at(i));
} }
for (auto i = 0U; i < vertices.size(); i++) { for (auto i = 0U; i < vertices.size(); i++) {
REQUIRE(vertices.at(i) == cube->vertices().at(i)); REQUIRE(vertices.at(i) == cube.vertices().at(i));
} }
} }
THEN( "Vertex count matches vertex array size.") { THEN( "Vertex count matches vertex array size.") {
REQUIRE(cube->facets_count() == facets.size()); REQUIRE(cube.facets_count() == facets.size());
} }
THEN( "Facet array matches input.") { THEN( "Facet array matches input.") {
for (auto i = 0U; i < cube->facets().size(); i++) { for (auto i = 0U; i < cube.facets().size(); i++) {
REQUIRE(cube->facets().at(i) == facets.at(i)); REQUIRE(cube.facets().at(i) == facets.at(i));
} }
for (auto i = 0U; i < facets.size(); i++) { for (auto i = 0U; i < facets.size(); i++) {
REQUIRE(facets.at(i) == cube->facets().at(i)); REQUIRE(facets.at(i) == cube.facets().at(i));
} }
} }
THEN( "Facet count matches facet array size.") { THEN( "Facet count matches facet array size.") {
REQUIRE(cube->facets_count() == facets.size()); REQUIRE(cube.facets_count() == facets.size());
} }
THEN( "Number of normals is equal to the number of facets.") { THEN( "Number of normals is equal to the number of facets.") {
REQUIRE(cube->normals().size() == facets.size()); REQUIRE(cube.normals().size() == facets.size());
} }
delete cube;
} }
} }
@ -54,43 +52,48 @@ SCENARIO( "TriangleMesh: Transformation functions affect mesh as expected.") {
GIVEN( "A 20mm cube with one corner on the origin") { GIVEN( "A 20mm cube with one corner on the origin") {
const Pointf3s vertices { Pointf3(20,20,0), Pointf3(20,0,0), Pointf3(0,0,0), Pointf3(0,20,0), Pointf3(20,20,20), Pointf3(0,20,20), Pointf3(0,0,20), Pointf3(20,0,20) }; const Pointf3s vertices { Pointf3(20,20,0), Pointf3(20,0,0), Pointf3(0,0,0), Pointf3(0,20,0), Pointf3(20,20,20), Pointf3(0,20,20), Pointf3(0,0,20), Pointf3(20,0,20) };
const std::vector<Point3> facets { Point3(0,1,2), Point3(0,2,3), Point3(4,5,6), Point3(4,6,7), Point3(0,4,7), Point3(0,7,1), Point3(1,7,6), Point3(1,6,2), Point3(2,6,5), Point3(2,5,3), Point3(4,0,3), Point3(4,3,5) }; const std::vector<Point3> facets { Point3(0,1,2), Point3(0,2,3), Point3(4,5,6), Point3(4,6,7), Point3(0,4,7), Point3(0,7,1), Point3(1,7,6), Point3(1,6,2), Point3(2,6,5), Point3(2,5,3), Point3(4,0,3), Point3(4,3,5) };
auto* cube {new TriangleMesh(vertices, facets)}; auto cube {TriangleMesh(vertices, facets)};
cube->repair(); cube.repair();
WHEN( "The cube is scaled 200\%") {
WHEN( "The cube is scaled 200\% uniformly") {
cube.scale(2.0);
THEN( "The volume is equivalent to 40x40x40 (all dimensions increased by 200\%") { THEN( "The volume is equivalent to 40x40x40 (all dimensions increased by 200\%") {
REQUIRE(false); // TODO REQUIRE(abs(cube.volume() - 40.0*40.0*40.0) < 1e-2);
} }
} }
WHEN( "The cube is scaled 200\% in the X direction") { WHEN( "The resulting cube is scaled 200\% in the X direction") {
cube.scale(Vectorf3(2.0, 1, 1));
THEN( "The volume is doubled.") { THEN( "The volume is doubled.") {
REQUIRE(false); // TODO REQUIRE(abs(cube.volume() - 2*20.0*20.0*20.0) < 1e-2);
} }
THEN( "The X coordinate size is 200\%.") { THEN( "The X coordinate size is 200\%.") {
REQUIRE(false); // TODO REQUIRE(cube.vertices().at(0).x == 40.0);
} }
} }
WHEN( "The cube is scaled 50\% in the X direction") {
THEN( "The volume is doubled.") { WHEN( "The cube is scaled 25\% in the X direction") {
REQUIRE(false); // TODO cube.scale(Vectorf3(0.25, 1, 1));
THEN( "The volume is 25\% of the previous volume.") {
REQUIRE(abs(cube.volume() - 0.25*20.0*20.0*20.0) < 1e-2);
} }
THEN( "The X coordinate size is 50\%.") { THEN( "The X coordinate size is 25\% from previous.") {
REQUIRE(false); // TODO REQUIRE(cube.vertices().at(0).x == 5.0);
} }
} }
WHEN( "The scaled cube is rotated 45 degrees.") { WHEN( "The scaled cube is rotated 45 degrees.") {
THEN( "The X component of the size is sqrt(2)*40") { cube.rotate(45.0, Slic3r::Point(20,20));
REQUIRE(false); // TODO THEN( "The X component of the size is sqrt(2)*20") {
REQUIRE(abs(cube.size().x - sqrt(2.0)*20) < 1e-2);
} }
} }
} }
} }
SCENARIO( "TriangleMesh: split function functionality.") { SCENARIO( "TriangleMesh: split functionality.", "[!mayfail]") {
REQUIRE(false); // TODO REQUIRE(false); // TODO
} }
SCENARIO( "make_xxx functions produce meshes.") { SCENARIO( "make_xxx functions produce meshes.", "[!mayfail]") {
REQUIRE(false); // TODO REQUIRE(false); // TODO
} }

View File

@ -1,5 +1,6 @@
#include "TriangleMesh.hpp" #include "TriangleMesh.hpp"
#include "ClipperUtils.hpp" #include "ClipperUtils.hpp"
#include "Log.hpp"
#include "Geometry.hpp" #include "Geometry.hpp"
#include <cmath> #include <cmath>
#include <deque> #include <deque>
@ -93,6 +94,59 @@ TriangleMesh::TriangleMesh(const TriangleMesh &other)
} }
} }
Pointf3s TriangleMesh::vertices()
{
Pointf3s tmp {};
if (this->repaired) {
if (this->stl.v_shared == nullptr)
stl_generate_shared_vertices(&stl); // build the list of vertices
for (auto i = 0; i < this->stl.stats.shared_vertices; i++) {
const auto& v {this->stl.v_shared[i]};
tmp.emplace_back(Pointf3(v.x, v.y, v.z));
}
} else {
Slic3r::Log::warn("TriangleMesh", "vertices() requires repair()");
}
return std::move(tmp);
}
Point3s TriangleMesh::facets()
{
Point3s tmp {};
if (this->repaired) {
if (this->stl.v_shared == nullptr)
stl_generate_shared_vertices(&stl); // build the list of vertices
for (auto i = 0; i < stl.stats.number_of_facets; i++) {
const auto& v {stl.v_indices[i]};
tmp.emplace_back(Point3(v.vertex[0], v.vertex[1], v.vertex[2]));
}
} else {
Slic3r::Log::warn("TriangleMesh", "facets() requires repair()");
}
return std::move(tmp);
}
Pointf3s TriangleMesh::normals() const
{
Pointf3s tmp {};
if (this->repaired) {
for (auto i = 0; i < stl.stats.number_of_facets; i++) {
const auto& n {stl.facet_start[i].normal};
tmp.emplace_back(Pointf3(n.x, n.y, n.z));
}
} else {
Slic3r::Log::warn("TriangleMesh", "normals() requires repair()");
}
return std::move(tmp);
}
Pointf3 TriangleMesh::size() const
{
const auto& sz {stl.stats.size};
return std::move(Pointf3(sz.x, sz.y, sz.z));
}
TriangleMesh& TriangleMesh::operator= (TriangleMesh other) TriangleMesh& TriangleMesh::operator= (TriangleMesh other)
{ {
this->swap(other); this->swap(other);
@ -356,9 +410,13 @@ void TriangleMesh::center_around_origin()
void TriangleMesh::rotate(double angle, Point* center) void TriangleMesh::rotate(double angle, Point* center)
{ {
this->translate(-center->x, -center->y, 0); this->rotate(angle, *center);
}
void TriangleMesh::rotate(double angle, const Point& center)
{
this->translate(-center.x, -center.y, 0);
stl_rotate_z(&(this->stl), (float)angle); stl_rotate_z(&(this->stl), (float)angle);
this->translate(+center->x, +center->y, 0); this->translate(+center.x, +center.y, 0);
} }
TriangleMeshPtrs TriangleMeshPtrs
@ -1393,6 +1451,7 @@ TriangleMeshSlicer<A>::cut(float z, TriangleMesh* upper, TriangleMesh* lower) co
stl_get_size(&(lower->stl)); stl_get_size(&(lower->stl));
} }
template <Axis A> template <Axis A>
TriangleMeshSlicer<A>::TriangleMeshSlicer(TriangleMesh* _mesh) : mesh(_mesh), v_scaled_shared(NULL) TriangleMeshSlicer<A>::TriangleMeshSlicer(TriangleMesh* _mesh) : mesh(_mesh), v_scaled_shared(NULL)
{ {

View File

@ -47,7 +47,11 @@ class TriangleMesh
void mirror_z(); void mirror_z();
void align_to_origin(); void align_to_origin();
void center_around_origin(); void center_around_origin();
/// Rotate angle around a specified point.
void rotate(double angle, const Point& center);
void rotate(double angle, Point* center); void rotate(double angle, Point* center);
TriangleMeshPtrs split() const; TriangleMeshPtrs split() const;
TriangleMeshPtrs cut_by_grid(const Pointf &grid) const; TriangleMeshPtrs cut_by_grid(const Pointf &grid) const;
void merge(const TriangleMesh &mesh); void merge(const TriangleMesh &mesh);
@ -60,6 +64,18 @@ class TriangleMesh
void extrude_tin(float offset); void extrude_tin(float offset);
void require_shared_vertices(); void require_shared_vertices();
void reverse_normals(); void reverse_normals();
/// Return a copy of the vertex array defining this mesh.
Pointf3s vertices();
/// Return a copy of the facet array defining this mesh.
Point3s facets();
/// Return a copy of the normals array defining this mesh.
Pointf3s normals() const;
/// Return the size of the mesh in coordinates.
Pointf3 size() const;
/// Generate a mesh representing a cube with dimensions (x, y, z), with one corner at (0,0,0). /// Generate a mesh representing a cube with dimensions (x, y, z), with one corner at (0,0,0).
static TriangleMesh make_cube(double x, double y, double z); static TriangleMesh make_cube(double x, double y, double z);