diff --git a/t/bridges.t b/t/bridges.t index 95db67daf..677115b84 100644 --- a/t/bridges.t +++ b/t/bridges.t @@ -1,4 +1,4 @@ -use Test::More tests => 18; +use Test::More tests => 20; use strict; use warnings; @@ -99,6 +99,24 @@ use Slic3r::Test; 'correct bridge angle for rectangle'; } +{ + # GH #3929: This test case checks that narrow gaps in lower slices don't prevent correct + # direction detection. + my $bridge = Slic3r::ExPolygon->new( + Slic3r::Polygon->new([10099996,45867519],[3762370,45867519],[3762370,2132479],[10099996,2132479]), + ); + my $lower = [ + Slic3r::ExPolygon->new( + Slic3r::Polygon->new([13534103,210089],[13629884,235753],[14249999,401901],[14269611,421510],[14272931,424830],[14287518,439411],[14484206,636101],[15348099,1500000],[15360812,1547449],[15365467,1564815],[15388623,1651235],[15391897,1663454],[15393088,1667906],[15399044,1690134],[15457593,1908648],[15750000,2999999],[15750000,45000000],[15742825,45026783],[15741540,45031580],[15735900,45052628],[15663980,45321047],[15348099,46500000],[15151410,46696691],[14287518,47560587],[14267907,47580196],[14264587,47583515],[14249999,47598100],[14211041,47608539],[14204785,47610215],[14176024,47617916],[14105602,47636784],[14097768,47638884],[14048000,47652220],[13871472,47699515],[12750000,48000000],[10446106,48000000],[10446124,47990347],[10446124,9652],[10446106,0],[12750000,0]), + Slic3r::Polygon->new([10251886,5013],[10251886,47994988],[10251907,48000000],[10100006,48000000],[10100006,0],[10251907,0]), + Slic3r::Polygon->new([3762360,17017],[3762360,47982984],[3762397,48000000],[1249999,48000000],[536029,47808700],[456599,47787419],[73471,47684764],[0,47665076],[0,23124327],[119299,22907322],[159278,22834601],[196290,22690451],[239412,22522516],[303787,22271780],[639274,20965103],[639274,19034896],[616959,18947983],[607651,18911729],[559146,18722807],[494769,18472073],[159278,17165397],[38931,16946491],[0,16875676],[0,334922],[128529,300484],[1250000,0],[3762397,0]), + ), + ]; + + ok check_angle($lower, $bridge, 0, undef, $bridge->area, 500000), + 'correct bridge angle when lower slices have narrow gap'; +} + sub check_angle { my ($lower, $bridge, $expected, $tolerance, $expected_coverage, $extrusion_width) = @_; @@ -121,9 +139,9 @@ sub check_angle { # our epsilon is equal to the steps used by the bridge detection algorithm ###use XXX; YYY [ rad2deg($result), $expected ]; # returned value must be non-negative, check for that too - my $delta=rad2deg($result) - $expected; - $delta-=180 if $delta>=180 - epsilon; - return defined $result && $result>=0 && abs($delta) < $tolerance; + my $delta = rad2deg($result) - $expected; + $delta -= 180 if $delta >= 180 - epsilon; + return defined $result && $result >= 0 && abs($delta) < $tolerance; } { diff --git a/xs/src/libslic3r/BridgeDetector.cpp b/xs/src/libslic3r/BridgeDetector.cpp index 33c239d6f..255b78a2a 100644 --- a/xs/src/libslic3r/BridgeDetector.cpp +++ b/xs/src/libslic3r/BridgeDetector.cpp @@ -7,13 +7,23 @@ namespace Slic3r { BridgeDetector::BridgeDetector(const ExPolygon &_expolygon, const ExPolygonCollection &_lower_slices, coord_t _extrusion_width) - : expolygon(_expolygon), lower_slices(_lower_slices), extrusion_width(_extrusion_width), + : expolygon(_expolygon), extrusion_width(_extrusion_width), resolution(PI/36.0), angle(-1) { /* outset our bridge by an arbitrary amout; we'll use this outer margin for detecting anchors */ Polygons grown = offset(this->expolygon, this->extrusion_width); + // remove narrow gaps from lower slices + // (this is only needed as long as we use clipped test lines for angle detection + // and we check their endpoints: when endpoint fall in the gap we'd get false + // negatives) + this->lower_slices.expolygons = offset2_ex( + _lower_slices, + +this->extrusion_width/2, + -this->extrusion_width/2 + ); + // detect what edges lie on lower slices by turning bridge contour and holes // into polylines and then clipping them with each lower slice's contour this->_edges = intersection_pl(grown, this->lower_slices.contours()); @@ -34,6 +44,10 @@ BridgeDetector::BridgeDetector(const ExPolygon &_expolygon, const ExPolygonColle svg.draw(this->_anchors, "yellow"); svg.draw(this->_edges, "black", scale_(0.2)); svg.Close(); + + std::cout << "expolygon: " << this->expolygon.dump_perl() << std::endl; + for (const ExPolygon &e : this->lower_slices.expolygons) + std::cout << "lower: " << e.dump_perl() << std::endl; } #endif } @@ -133,6 +147,13 @@ BridgeDetector::detect_angle() )); } if (candidate.coverage > 0) have_coverage = true; + + #if 0 + std::cout << "angle = " << Slic3r::Geometry::rad2deg(candidate.angle) + << "; coverage = " << candidate.coverage + << "; max_length = " << candidate.max_length + << std::endl; + #endif } // if no direction produced coverage, then there's no bridge direction @@ -159,12 +180,16 @@ BridgeDetector::detect_angle() return true; } +Polygons +BridgeDetector::coverage() const +{ + if (this->angle == -1) return Polygons(); + return this->coverage(this->angle); +} + Polygons BridgeDetector::coverage(double angle) const { - if (angle == -1) angle = this->angle; - if (angle == -1) return Polygons(); - // Clone our expolygon and rotate it so that we work with vertical lines. ExPolygon expolygon = this->expolygon; expolygon.rotate(PI/2.0 - angle, Point(0,0)); diff --git a/xs/src/libslic3r/BridgeDetector.hpp b/xs/src/libslic3r/BridgeDetector.hpp index 84f9f3848..9abe1162a 100644 --- a/xs/src/libslic3r/BridgeDetector.hpp +++ b/xs/src/libslic3r/BridgeDetector.hpp @@ -23,7 +23,8 @@ public: BridgeDetector(const ExPolygon &_expolygon, const ExPolygonCollection &_lower_slices, coord_t _extrusion_width); bool detect_angle(); - Polygons coverage(double angle = -1) const; + Polygons coverage() const; + Polygons coverage(double angle) const; Polylines unsupported_edges(double angle = -1) const; private: diff --git a/xs/src/libslic3r/Fill/Fill.cpp b/xs/src/libslic3r/Fill/Fill.cpp index 39c9107b9..c07851fb1 100644 --- a/xs/src/libslic3r/Fill/Fill.cpp +++ b/xs/src/libslic3r/Fill/Fill.cpp @@ -1,10 +1,9 @@ -#define DEBUG -#undef NDEBUG #include #include #include #include "../ClipperUtils.hpp" +#include "../Geometry.hpp" #include "../Surface.hpp" #include "../PrintConfig.hpp" @@ -96,10 +95,8 @@ Fill::_infill_direction(const Surface &surface) const if (surface.bridge_angle >= 0) { // use bridge angle - //FIXME Vojtech: Add a debugf? - // Slic3r::debugf "Filling bridge with angle %d\n", rad2deg($surface->bridge_angle); #ifdef SLIC3R_DEBUG - printf("Filling bridge with angle %f\n", surface.bridge_angle); + printf("Filling bridge with angle %f\n", Slic3r::Geometry::rad2deg(surface.bridge_angle)); #endif out_angle = surface.bridge_angle; } else if (this->layer_id != size_t(-1)) {