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 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)};
cube->repair();
auto cube {TriangleMesh(vertices, facets)};
cube.repair();
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.") {
for (auto i = 0U; i < cube->vertices().size(); i++) {
REQUIRE(cube->vertices().at(i) == vertices.at(i));
for (auto i = 0U; i < cube.vertices().size(); i++) {
REQUIRE(cube.vertices().at(i) == vertices.at(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.") {
REQUIRE(cube->facets_count() == facets.size());
REQUIRE(cube.facets_count() == facets.size());
}
THEN( "Facet array matches input.") {
for (auto i = 0U; i < cube->facets().size(); i++) {
REQUIRE(cube->facets().at(i) == facets.at(i));
for (auto i = 0U; i < cube.facets().size(); i++) {
REQUIRE(cube.facets().at(i) == facets.at(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.") {
REQUIRE(cube->facets_count() == facets.size());
REQUIRE(cube.facets_count() == facets.size());
}
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") {
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) };
auto* cube {new TriangleMesh(vertices, facets)};
cube->repair();
WHEN( "The cube is scaled 200\%") {
auto cube {TriangleMesh(vertices, facets)};
cube.repair();
WHEN( "The cube is scaled 200\% uniformly") {
cube.scale(2.0);
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.") {
REQUIRE(false); // TODO
REQUIRE(abs(cube.volume() - 2*20.0*20.0*20.0) < 1e-2);
}
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.") {
REQUIRE(false); // TODO
WHEN( "The cube is scaled 25\% in the X direction") {
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\%.") {
REQUIRE(false); // TODO
THEN( "The X coordinate size is 25\% from previous.") {
REQUIRE(cube.vertices().at(0).x == 5.0);
}
}
WHEN( "The scaled cube is rotated 45 degrees.") {
THEN( "The X component of the size is sqrt(2)*40") {
REQUIRE(false); // TODO
cube.rotate(45.0, Slic3r::Point(20,20));
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
}
SCENARIO( "make_xxx functions produce meshes.") {
SCENARIO( "make_xxx functions produce meshes.", "[!mayfail]") {
REQUIRE(false); // TODO
}

View File

@ -1,5 +1,6 @@
#include "TriangleMesh.hpp"
#include "ClipperUtils.hpp"
#include "Log.hpp"
#include "Geometry.hpp"
#include <cmath>
#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)
{
this->swap(other);
@ -356,9 +410,13 @@ void TriangleMesh::center_around_origin()
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);
this->translate(+center->x, +center->y, 0);
this->translate(+center.x, +center.y, 0);
}
TriangleMeshPtrs
@ -1393,6 +1451,7 @@ TriangleMeshSlicer<A>::cut(float z, TriangleMesh* upper, TriangleMesh* lower) co
stl_get_size(&(lower->stl));
}
template <Axis A>
TriangleMeshSlicer<A>::TriangleMeshSlicer(TriangleMesh* _mesh) : mesh(_mesh), v_scaled_shared(NULL)
{

View File

@ -47,7 +47,11 @@ class TriangleMesh
void mirror_z();
void align_to_origin();
void center_around_origin();
/// Rotate angle around a specified point.
void rotate(double angle, const Point& center);
void rotate(double angle, Point* center);
TriangleMeshPtrs split() const;
TriangleMeshPtrs cut_by_grid(const Pointf &grid) const;
void merge(const TriangleMesh &mesh);
@ -60,6 +64,18 @@ class TriangleMesh
void extrude_tin(float offset);
void require_shared_vertices();
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).
static TriangleMesh make_cube(double x, double y, double z);