From 2d9c399d96cbe92f64b28faa79f9d369d2c8f4fe Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Mon, 13 Jan 2014 00:45:19 +0100 Subject: [PATCH] Bugfix: incomplete slicing when a horizontal surface was tangent to the slicing plane and it shared an edge with an adjacent volume. #1672 Conflicts: xs/src/TriangleMesh.cpp --- xs/src/TriangleMesh.cpp | 32 +++++++++++++++++++++++--------- xs/src/TriangleMesh.hpp | 2 +- xs/t/01_trianglemesh.t | 6 ++++-- 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/xs/src/TriangleMesh.cpp b/xs/src/TriangleMesh.cpp index 9eae734c8..bf29f72e6 100644 --- a/xs/src/TriangleMesh.cpp +++ b/xs/src/TriangleMesh.cpp @@ -253,16 +253,11 @@ TriangleMesh::slice(const std::vector &z) printf("z: min = %.2f, max = %.2f\n", min_z, max_z); #endif - if (min_z == max_z) { - #ifdef SLIC3R_DEBUG - printf("Facet is horizontal; ignoring\n"); - #endif - continue; - } - + // find layer extents std::vector::const_iterator min_layer, max_layer; min_layer = std::lower_bound(z.begin(), z.end(), min_z); // first layer whose slice_z is >= min_z max_layer = std::upper_bound(z.begin() + (min_layer - z.begin()), z.end(), max_z) - 1; // last layer whose slice_z is <= max_z + /* If no layer is <= max_z, then max_layer == -1 */ #ifdef SLIC3R_DEBUG printf("layers: min = %d, max = %d\n", (int)(min_layer - z.begin()), (int)(max_layer - z.begin())); #endif @@ -298,7 +293,9 @@ TriangleMesh::slice(const std::vector &z) /* We assume that this method is never being called for horizontal facets, so no other edge is going to be on this layer. */ IntersectionLine line; - if (facet->vertex[0].z < slice_z || facet->vertex[1].z < slice_z || facet->vertex[2].z < slice_z) { + if (min_z == max_z) { + line.edge_type = feHorizontal; + } else if (facet->vertex[0].z < slice_z || facet->vertex[1].z < slice_z || facet->vertex[2].z < slice_z) { line.edge_type = feTop; std::swap(a, b); std::swap(a_id, b_id); @@ -314,7 +311,10 @@ TriangleMesh::slice(const std::vector &z) lines[layer_idx].push_back(line); found_horizontal_edge = true; - break; + + // if this is a top or bottom edge, we can stop looping through edges + // because we won't find anything interesting + if (line.edge_type != feHorizontal) break; } else if (a->z == slice_z) { IntersectionPoint point; point.x = a->x; @@ -375,6 +375,13 @@ TriangleMesh::slice(const std::vector &z) printf("Layer %d:\n", layer_idx); #endif + /* + SVG svg("lines.svg"); + for (IntersectionLines::iterator line = it->begin(); line != it->end(); ++line) + svg.AddLine(*line); + svg.Close(); + */ + // remove tangent edges for (IntersectionLines::iterator line = it->begin(); line != it->end(); ++line) { if (line->skip || line->edge_type == feNone) continue; @@ -398,6 +405,13 @@ TriangleMesh::slice(const std::vector &z) line->skip = true; break; } + } else if (line->a_id == line2->b_id && line->b_id == line2->a_id) { + /* if this edge joins two horizontal facets, remove both of them */ + if (line->edge_type == feHorizontal && line2->edge_type == feHorizontal) { + line->skip = true; + line2->skip = true; + break; + } } } } diff --git a/xs/src/TriangleMesh.hpp b/xs/src/TriangleMesh.hpp index d341fa098..e96b17412 100644 --- a/xs/src/TriangleMesh.hpp +++ b/xs/src/TriangleMesh.hpp @@ -40,7 +40,7 @@ class TriangleMesh #endif }; -enum FacetEdgeType { feNone, feTop, feBottom }; +enum FacetEdgeType { feNone, feTop, feBottom, feHorizontal }; class IntersectionPoint : public Point { diff --git a/xs/t/01_trianglemesh.t b/xs/t/01_trianglemesh.t index c80d603fa..4a88cff25 100644 --- a/xs/t/01_trianglemesh.t +++ b/xs/t/01_trianglemesh.t @@ -4,7 +4,8 @@ use strict; use warnings; use Slic3r::XS; -use Test::More tests => 52; +use List::Util qw(sum); +use Test::More tests => 53; is Slic3r::TriangleMesh::hello_world(), 'Hello world!', 'hello world'; @@ -96,6 +97,7 @@ my $cube = { ); $m->repair; my $slices = $m->slice([ 5, 10 ]); - is $slices->[0][0]->area, $slices->[1][0]->area, 'slicing a tangent plane includes its area'; + is sum(map $_->area, @{$slices->[0]}), sum(map $_->area, @{$slices->[1]}), + 'slicing a tangent plane includes its area'; } __END__