Bugfix: tangent horizontal mesh surfaces were not included in slices under rare circumstances, generating almost invalid polygons that confused Clipper and caused skipped layers. Includes regression test

This commit is contained in:
Alessandro Ranellucci 2015-01-28 13:00:38 +01:00
parent 8a5a0b6726
commit b1f1893481
4 changed files with 83 additions and 21 deletions

View file

@ -181,6 +181,7 @@ TriangleMesh::WriteOBJFile(char* output_file) {
void TriangleMesh::scale(float factor)
{
stl_scale(&(this->stl), factor);
stl_invalidate_shared_vertices(&this->stl);
}
void TriangleMesh::scale(const Pointf3 &versor)
@ -190,41 +191,49 @@ void TriangleMesh::scale(const Pointf3 &versor)
fversor[1] = versor.y;
fversor[2] = versor.z;
stl_scale_versor(&this->stl, fversor);
stl_invalidate_shared_vertices(&this->stl);
}
void TriangleMesh::translate(float x, float y, float z)
{
stl_translate_relative(&(this->stl), x, y, z);
stl_invalidate_shared_vertices(&this->stl);
}
void TriangleMesh::rotate_x(float angle)
{
stl_rotate_x(&(this->stl), angle);
stl_invalidate_shared_vertices(&this->stl);
}
void TriangleMesh::rotate_y(float angle)
{
stl_rotate_y(&(this->stl), angle);
stl_invalidate_shared_vertices(&this->stl);
}
void TriangleMesh::rotate_z(float angle)
{
stl_rotate_z(&(this->stl), angle);
stl_invalidate_shared_vertices(&this->stl);
}
void TriangleMesh::flip_x()
{
stl_mirror_yz(&this->stl);
stl_invalidate_shared_vertices(&this->stl);
}
void TriangleMesh::flip_y()
{
stl_mirror_xz(&this->stl);
stl_invalidate_shared_vertices(&this->stl);
}
void TriangleMesh::flip_z()
{
stl_mirror_xy(&this->stl);
stl_invalidate_shared_vertices(&this->stl);
}
void TriangleMesh::align_to_origin()
@ -507,7 +516,7 @@ TriangleMeshSlicer::slice(const std::vector<float> &z, std::vector<ExPolygons>*
for (std::vector<Polygons>::const_iterator loops = layers_p.begin(); loops != layers_p.end(); ++loops) {
#ifdef SLIC3R_DEBUG
size_t layer_id = loops - layers_p.begin();
printf("Layer %zu (slice_z = %.2f): ", layer_id, z[layer_id]);
printf("Layer %zu (slice_z = %.2f):\n", layer_id, z[layer_id]);
#endif
this->make_expolygons(*loops, &(*layers)[ loops - layers_p.begin() ]);
@ -542,15 +551,19 @@ TriangleMeshSlicer::slice_facet(float slice_z, const stl_facet &facet, const int
if (a->z == b->z && a->z == slice_z) {
// edge is horizontal and belongs to the current layer
/* We assume that this method is never being called for horizontal
facets, so no other edge is going to be on this layer. */
stl_vertex* v0 = &this->v_scaled_shared[ this->mesh->stl.v_indices[facet_idx].vertex[0] ];
stl_vertex* v1 = &this->v_scaled_shared[ this->mesh->stl.v_indices[facet_idx].vertex[1] ];
stl_vertex* v2 = &this->v_scaled_shared[ this->mesh->stl.v_indices[facet_idx].vertex[2] ];
stl_vertex &v0 = this->v_scaled_shared[ this->mesh->stl.v_indices[facet_idx].vertex[0] ];
stl_vertex &v1 = this->v_scaled_shared[ this->mesh->stl.v_indices[facet_idx].vertex[1] ];
stl_vertex &v2 = this->v_scaled_shared[ this->mesh->stl.v_indices[facet_idx].vertex[2] ];
IntersectionLine line;
if (min_z == max_z) {
line.edge_type = feHorizontal;
} else if (v0->z < slice_z || v1->z < slice_z || v2->z < slice_z) {
if (this->mesh->stl.facet_start[facet_idx].normal.z < 0) {
/* if normal points downwards this is a bottom horizontal facet so we reverse
its point order */
std::swap(a, b);
std::swap(a_id, b_id);
}
} else if (v0.z < slice_z || v1.z < slice_z || v2.z < slice_z) {
line.edge_type = feTop;
std::swap(a, b);
std::swap(a_id, b_id);
@ -624,12 +637,9 @@ TriangleMeshSlicer::slice_facet(float slice_z, const stl_facet &facet, const int
void
TriangleMeshSlicer::make_loops(std::vector<IntersectionLine> &lines, Polygons* loops)
{
/*
SVG svg("lines.svg");
for (IntersectionLines::iterator line = lines.begin(); line != lines.end(); ++line) {
svg.AddLine(*line);
}
svg.draw(lines);
svg.Close();
*/
@ -837,9 +847,9 @@ TriangleMeshSlicer::make_expolygons(const Polygons &loops, ExPolygons* slices)
of the loops, since the Orientation() function provided by Clipper
would do the same, thus repeating the calculation */
Polygons::const_iterator loop = loops.begin() + *loop_idx;
if (area[*loop_idx] >= 0) {
if (area[*loop_idx] > +EPSILON) {
p_slices.push_back(*loop);
} else {
} else if (area[*loop_idx] < -EPSILON) {
diff(p_slices, *loop, &p_slices);
}
}