diff --git a/src/libslic3r/Config.hpp b/src/libslic3r/Config.hpp index a087dd854..bfd307de3 100644 --- a/src/libslic3r/Config.hpp +++ b/src/libslic3r/Config.hpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include "libslic3r.h" #include "clonable_ptr.hpp" @@ -1989,6 +1990,7 @@ public: struct SetDeserializeItem { SetDeserializeItem(const char *opt_key, const char *opt_value, bool append = false) : opt_key(opt_key), opt_value(opt_value), append(append) {} SetDeserializeItem(const std::string &opt_key, const std::string &opt_value, bool append = false) : opt_key(opt_key), opt_value(opt_value), append(append) {} + SetDeserializeItem(const std::string &opt_key, const std::string_view opt_value, bool append = false) : opt_key(opt_key), opt_value(opt_value), append(append) {} SetDeserializeItem(const char *opt_key, const bool value, bool append = false) : opt_key(opt_key), opt_value(value ? "1" : "0"), append(append) {} SetDeserializeItem(const std::string &opt_key, const bool value, bool append = false) : opt_key(opt_key), opt_value(value ? "1" : "0"), append(append) {} SetDeserializeItem(const char *opt_key, const int value, bool append = false) : opt_key(opt_key), opt_value(std::to_string(value)), append(append) {} diff --git a/src/libslic3r/ExtrusionEntity.hpp b/src/libslic3r/ExtrusionEntity.hpp index 5e6a51d20..2e9e46789 100644 --- a/src/libslic3r/ExtrusionEntity.hpp +++ b/src/libslic3r/ExtrusionEntity.hpp @@ -324,10 +324,10 @@ inline void extrusion_paths_append(ExtrusionPaths &dst, Polylines &&polylines, E polylines.clear(); } -inline void extrusion_entities_append_paths(ExtrusionEntitiesPtr &dst, Polylines &polylines, ExtrusionRole role, double mm3_per_mm, float width, float height) +inline void extrusion_entities_append_paths(ExtrusionEntitiesPtr &dst, const Polylines &polylines, ExtrusionRole role, double mm3_per_mm, float width, float height) { dst.reserve(dst.size() + polylines.size()); - for (Polyline &polyline : polylines) + for (const Polyline &polyline : polylines) if (polyline.is_valid()) { ExtrusionPath *extrusion_path = new ExtrusionPath(role, mm3_per_mm, width, height); dst.push_back(extrusion_path); diff --git a/src/libslic3r/GCodeReader.hpp b/src/libslic3r/GCodeReader.hpp index 0ab268139..40a099229 100644 --- a/src/libslic3r/GCodeReader.hpp +++ b/src/libslic3r/GCodeReader.hpp @@ -35,6 +35,8 @@ public: float new_Z(const GCodeReader &reader) const { return this->has(Z) ? this->z() : reader.z(); } float new_E(const GCodeReader &reader) const { return this->has(E) ? this->e() : reader.e(); } float new_F(const GCodeReader &reader) const { return this->has(F) ? this->f() : reader.f(); } + Point new_XY_scaled(const GCodeReader &reader) const + { return Point::new_scale(this->new_X(reader), this->new_Y(reader)); } float dist_X(const GCodeReader &reader) const { return this->has(X) ? (this->x() - reader.x()) : 0; } float dist_Y(const GCodeReader &reader) const { return this->has(Y) ? (this->y() - reader.y()) : 0; } float dist_Z(const GCodeReader &reader) const { return this->has(Z) ? (this->z() - reader.z()) : 0; } @@ -134,6 +136,8 @@ public: float e() const { return m_position[E]; } float& f() { return m_position[F]; } float f() const { return m_position[F]; } + Point xy_scaled() const { return Point::new_scale(this->x(), this->y()); } + // Returns 0 for gcfNoExtrusion. char extrusion_axis() const { return m_extrusion_axis; } diff --git a/t/fill.t b/t/fill.t deleted file mode 100644 index 88cc35801..000000000 --- a/t/fill.t +++ /dev/null @@ -1,318 +0,0 @@ -use Test::More; -use strict; -use warnings; - -#plan tests => 43; -# Test of a 100% coverage is off. -plan tests => 19; - -BEGIN { - use FindBin; - use lib "$FindBin::Bin/../lib"; - use local::lib "$FindBin::Bin/../local-lib"; -} - -use List::Util qw(first sum); -use Slic3r; -use Slic3r::Geometry qw(X Y scale unscale convex_hull); -use Slic3r::Geometry::Clipper qw(union diff diff_ex offset offset2_ex); -use Slic3r::Surface qw(:types); -use Slic3r::Test; - -sub scale_points (@) { map [scale $_->[X], scale $_->[Y]], @_ } - -{ - my $expolygon = Slic3r::ExPolygon->new([ scale_points [0,0], [50,0], [50,50], [0,50] ]); - my $filler = Slic3r::Filler->new_from_type('rectilinear'); - $filler->set_bounding_box($expolygon->bounding_box); - $filler->set_angle(0); - my $surface = Slic3r::Surface->new( - surface_type => S_TYPE_TOP, - expolygon => $expolygon, - ); - my $flow = Slic3r::Flow->new( - width => 0.69, - height => 0.4, - nozzle_diameter => 0.50, - ); - $filler->set_spacing($flow->spacing); - foreach my $angle (0, 45) { - $surface->expolygon->rotate(Slic3r::Geometry::deg2rad($angle), [0,0]); - my $paths = $filler->fill_surface($surface, layer_height => 0.4, density => 0.4); - is scalar @$paths, 1, 'one continuous path'; - } -} - -SKIP: -{ - skip "The FillRectilinear2 does not fill the surface completely", 1; - - my $test = sub { - my ($expolygon, $flow_spacing, $angle, $density) = @_; - - my $filler = Slic3r::Filler->new_from_type('rectilinear'); - $filler->set_bounding_box($expolygon->bounding_box); - $filler->set_angle($angle // 0); - # Adjust line spacing to fill the region. - $filler->set_dont_adjust(0); - $filler->set_link_max_length(scale(1.2*$flow_spacing)); - my $surface = Slic3r::Surface->new( - surface_type => S_TYPE_BOTTOM, - expolygon => $expolygon, - ); - my $flow = Slic3r::Flow->new( - width => $flow_spacing, - height => 0.4, - nozzle_diameter => $flow_spacing, - ); - $filler->set_spacing($flow->spacing); - my $paths = $filler->fill_surface( - $surface, - layer_height => $flow->height, - density => $density // 1, - ); - - # check whether any part was left uncovered - my @grown_paths = map @{Slic3r::Polyline->new(@$_)->grow(scale $filler->spacing/2)}, @$paths; - my $uncovered = diff_ex([ @$expolygon ], [ @grown_paths ], 1); - - # ignore very small dots - my $uncovered_filtered = [ grep $_->area > (scale $flow_spacing)**2, @$uncovered ]; - - is scalar(@$uncovered_filtered), 0, 'solid surface is fully filled'; - - if (0 && @$uncovered_filtered) { - require "Slic3r/SVG.pm"; - Slic3r::SVG::output("uncovered.svg", - no_arrows => 1, - expolygons => [ $expolygon ], - blue_expolygons => [ @$uncovered ], - red_expolygons => [ @$uncovered_filtered ], - polylines => [ @$paths ], - ); - exit; - } - }; - - my $expolygon = Slic3r::ExPolygon->new([ - [6883102, 9598327.01296997], - [6883102, 20327272.01297], - [3116896, 20327272.01297], - [3116896, 9598327.01296997], - ]); - $test->($expolygon, 0.55); - - for (1..20) { - $expolygon->scale(1.05); - $test->($expolygon, 0.55); - } - - $expolygon = Slic3r::ExPolygon->new( - [[59515297,5422499],[59531249,5578697],[59695801,6123186],[59965713,6630228],[60328214,7070685],[60773285,7434379],[61274561,7702115],[61819378,7866770],[62390306,7924789],[62958700,7866744],[63503012,7702244],[64007365,7434357],[64449960,7070398],[64809327,6634999],[65082143,6123325],[65245005,5584454],[65266967,5422499],[66267307,5422499],[66269190,8310081],[66275379,17810072],[66277259,20697500],[65267237,20697500],[65245004,20533538],[65082082,19994444],[64811462,19488579],[64450624,19048208],[64012101,18686514],[63503122,18415781],[62959151,18251378],[62453416,18198442],[62390147,18197355],[62200087,18200576],[61813519,18252990],[61274433,18415918],[60768598,18686517],[60327567,19047892],[59963609,19493297],[59695865,19994587],[59531222,20539379],[59515153,20697500],[58502480,20697500],[58502480,5422499]] - ); - $test->($expolygon, 0.524341649025257); - - $expolygon = Slic3r::ExPolygon->new([ scale_points [0,0], [98,0], [98,10], [0,10] ]); - $test->($expolygon, 0.5, 45, 0.99); # non-solid infill -} - -{ - my $collection = Slic3r::Polyline::Collection->new( - Slic3r::Polyline->new([0,15], [0,18], [0,20]), - Slic3r::Polyline->new([0,10], [0,8], [0,5]), - ); - is_deeply - [ map $_->[Y], map @$_, @{$collection->chained_path_from(Slic3r::Point->new(0,30), 0)} ], - [20, 18, 15, 10, 8, 5], - 'chained path'; -} - -{ - my $collection = Slic3r::Polyline::Collection->new( - Slic3r::Polyline->new([4,0], [10,0], [15,0]), - Slic3r::Polyline->new([10,5], [15,5], [20,5]), - ); - is_deeply - [ map $_->[X], map @$_, @{$collection->chained_path_from(Slic3r::Point->new(30,0), 0)} ], - [reverse 4, 10, 15, 10, 15, 20], - 'chained path'; -} - -{ - my $collection = Slic3r::ExtrusionPath::Collection->new( - map Slic3r::ExtrusionPath->new(polyline => $_, role => 0, mm3_per_mm => 1), - Slic3r::Polyline->new([0,15], [0,18], [0,20]), - Slic3r::Polyline->new([0,10], [0,8], [0,5]), - ); - is_deeply - [ map $_->[Y], map @{$_->polyline}, @{$collection->chained_path_from(Slic3r::Point->new(0,30), 0)} ], - [20, 18, 15, 10, 8, 5], - 'chained path'; -} - -{ - my $collection = Slic3r::ExtrusionPath::Collection->new( - map Slic3r::ExtrusionPath->new(polyline => $_, role => 0, mm3_per_mm => 1), - Slic3r::Polyline->new([15,0], [10,0], [4,0]), - Slic3r::Polyline->new([10,5], [15,5], [20,5]), - ); - is_deeply - [ map $_->[X], map @{$_->polyline}, @{$collection->chained_path_from(Slic3r::Point->new(30,0), 0)} ], - [reverse 4, 10, 15, 10, 15, 20], - 'chained path'; -} - -for my $pattern (qw(rectilinear honeycomb hilbertcurve concentric)) { - my $config = Slic3r::Config::new_from_defaults; - $config->set('nozzle_diameter', [0.4,0.4,0.4,0.4]); - $config->set('fill_pattern', $pattern); - $config->set('top_fill_pattern', $pattern); - $config->set('bottom_fill_pattern', $pattern); - $config->set('perimeters', 1); - $config->set('skirts', 0); - $config->set('fill_density', 20); - $config->set('layer_height', 0.05); - $config->set('perimeter_extruder', 1); - $config->set('infill_extruder', 2); - my $print = Slic3r::Test::init_print('20mm_cube', config => $config, scale => 2); - ok my $gcode = Slic3r::Test::gcode($print), "successful $pattern infill generation"; - my $tool = undef; - my @perimeter_points = my @infill_points = (); - Slic3r::GCode::Reader->new->parse($gcode, sub { - my ($self, $cmd, $args, $info) = @_; - - if ($cmd =~ /^T(\d+)/) { - $tool = $1; - } elsif ($cmd eq 'G1' && $info->{extruding} && $info->{dist_XY} > 0) { - if ($tool == $config->perimeter_extruder-1) { - push @perimeter_points, Slic3r::Point->new_scale($args->{X}, $args->{Y}); - } elsif ($tool == $config->infill_extruder-1) { - push @infill_points, Slic3r::Point->new_scale($args->{X}, $args->{Y}); - } - } - }); - my $convex_hull = convex_hull(\@perimeter_points); - ok !(defined first { !$convex_hull->contains_point($_) } @infill_points), "infill does not exceed perimeters ($pattern)"; -} - -{ - my $config = Slic3r::Config::new_from_defaults; - $config->set('nozzle_diameter', [0.4,0.4,0.4,0.4]); - $config->set('infill_only_where_needed', 1); - $config->set('bottom_solid_layers', 0); - $config->set('infill_extruder', 2); - $config->set('infill_extrusion_width', 0.5); - $config->set('wipe_into_infill', 0); - $config->set('fill_density', 40); - $config->set('cooling', [ 0 ]); # for preventing speeds from being altered - $config->set('first_layer_speed', '100%'); # for preventing speeds from being altered - - my $test = sub { - my $print = Slic3r::Test::init_print('pyramid', config => $config); - - my $tool = undef; - my @infill_extrusions = (); # array of polylines - Slic3r::GCode::Reader->new->parse(Slic3r::Test::gcode($print), sub { - my ($self, $cmd, $args, $info) = @_; - - if ($cmd =~ /^T(\d+)/) { - $tool = $1; - } elsif ($cmd eq 'G1' && $info->{extruding} && $info->{dist_XY} > 0) { - if ($tool == $config->infill_extruder-1) { - push @infill_extrusions, Slic3r::Line->new_scale( - [ $self->X, $self->Y ], - [ $info->{new_X}, $info->{new_Y} ], - ); - } - } - }); - return 0 if !@infill_extrusions; # prevent calling convex_hull() with no points - - my $convex_hull = convex_hull([ map $_->pp, map @$_, @infill_extrusions ]); - return unscale unscale sum(map $_->area, @{offset([$convex_hull], scale(+$config->infill_extrusion_width/2))}); - }; - - my $tolerance = 5; # mm^2 - - $config->set('solid_infill_below_area', 0); - ok $test->() < $tolerance, - 'no infill is generated when using infill_only_where_needed on a pyramid'; - - $config->set('solid_infill_below_area', 70); - ok abs($test->() - $config->solid_infill_below_area) < $tolerance, - 'infill is only generated under the forced solid shells'; -} - -{ - my $config = Slic3r::Config::new_from_defaults; - $config->set('skirts', 0); - $config->set('perimeters', 1); - $config->set('fill_density', 0); - $config->set('top_solid_layers', 0); - $config->set('bottom_solid_layers', 0); - $config->set('solid_infill_below_area', 20000000); - $config->set('solid_infill_every_layers', 2); - $config->set('perimeter_speed', 99); - $config->set('external_perimeter_speed', 99); - $config->set('cooling', [ 0 ]); - $config->set('first_layer_speed', '100%'); - - my $print = Slic3r::Test::init_print('20mm_cube', config => $config); - my %layers_with_extrusion = (); - Slic3r::GCode::Reader->new->parse(Slic3r::Test::gcode($print), sub { - my ($self, $cmd, $args, $info) = @_; - - if ($cmd eq 'G1' && $info->{dist_XY} > 0 && $info->{extruding}) { - if (($args->{F} // $self->F) != $config->perimeter_speed*60) { - $layers_with_extrusion{$self->Z} = ($args->{F} // $self->F); - } - } - }); - - ok !%layers_with_extrusion, - "solid_infill_below_area and solid_infill_every_layers are ignored when fill_density is 0"; -} - -{ - my $config = Slic3r::Config::new_from_defaults; - $config->set('skirts', 0); - $config->set('perimeters', 3); - $config->set('fill_density', 0); - $config->set('layer_height', 0.2); - $config->set('first_layer_height', 0.2); - $config->set('nozzle_diameter', [0.35,0.35,0.35,0.35]); - $config->set('infill_extruder', 2); - $config->set('solid_infill_extruder', 2); - $config->set('infill_extrusion_width', 0.52); - $config->set('solid_infill_extrusion_width', 0.52); - $config->set('first_layer_extrusion_width', 0); - - my $print = Slic3r::Test::init_print('A', config => $config); - my %infill = (); # Z => [ Line, Line ... ] - my $tool = undef; - Slic3r::GCode::Reader->new->parse(Slic3r::Test::gcode($print), sub { - my ($self, $cmd, $args, $info) = @_; - - if ($cmd =~ /^T(\d+)/) { - $tool = $1; - } elsif ($cmd eq 'G1' && $info->{extruding} && $info->{dist_XY} > 0) { - if ($tool == $config->infill_extruder-1) { - my $z = 1 * $self->Z; - $infill{$z} ||= []; - push @{$infill{$z}}, Slic3r::Line->new_scale( - [ $self->X, $self->Y ], - [ $info->{new_X}, $info->{new_Y} ], - ); - } - } - }); - my $grow_d = scale($config->infill_extrusion_width)/2; - my $layer0_infill = union([ map @{$_->grow($grow_d)}, @{ $infill{0.2} } ]); - my $layer1_infill = union([ map @{$_->grow($grow_d)}, @{ $infill{0.4} } ]); - my $diff = diff($layer0_infill, $layer1_infill); - $diff = offset2_ex($diff, -$grow_d, +$grow_d); - $diff = [ grep { $_->area > 2*(($grow_d*2)**2) } @$diff ]; - is scalar(@$diff), 0, 'no missing parts in solid shell when fill_density is 0'; -} - -__END__ diff --git a/tests/fff_print/test_data.cpp b/tests/fff_print/test_data.cpp index f7077007d..6be45d238 100644 --- a/tests/fff_print/test_data.cpp +++ b/tests/fff_print/test_data.cpp @@ -187,6 +187,19 @@ TriangleMesh mesh(TestMesh m) return mesh; } +TriangleMesh mesh(TestMesh min, Vec3d translate, Vec3d scale) +{ + TriangleMesh m = mesh(min); + m.translate(translate.cast()); + m.scale(scale.cast()); + return m; +} + +TriangleMesh mesh(TestMesh m, Vec3d translate, double scale) +{ + return mesh(m, translate, Vec3d(scale, scale, scale)); +} + static bool verbose_gcode() { const char *v = std::getenv("SLIC3R_TESTS_GCODE"); diff --git a/tests/fff_print/test_extrusion_entity.cpp b/tests/fff_print/test_extrusion_entity.cpp index 9bef52a5c..7e0ca822f 100644 --- a/tests/fff_print/test_extrusion_entity.cpp +++ b/tests/fff_print/test_extrusion_entity.cpp @@ -5,6 +5,7 @@ #include "libslic3r/ExtrusionEntityCollection.hpp" #include "libslic3r/ExtrusionEntity.hpp" #include "libslic3r/Point.hpp" +#include "libslic3r/ShortestPath.hpp" #include "libslic3r/libslic3r.h" #include "test_data.hpp" @@ -83,3 +84,60 @@ SCENARIO("ExtrusionEntityCollection: Polygon flattening", "[ExtrusionEntity]") { } } } + +TEST_CASE("ExtrusionEntityCollection: Chained path", "[ExtrusionEntity]") { + struct Test { + Polylines unchained; + Polylines chained; + Point initial_point; + }; + std::vector tests { + { + { + { {0,15}, {0,18}, {0,20} }, + { {0,10}, {0,8}, {0,5} } + }, + { + { {0,20}, {0,18}, {0,15} }, + { {0,10}, {0,8}, {0,5} } + }, + { 0,30 } + }, + { + { + { {4,0}, {10,0}, {15,0} }, + { {10,5}, {15,5}, {20,5} } + }, + { + { {20,5}, {15,5}, {10,5} }, + { {15,0}, {10,0}, {4,0} } + }, + { 30,0 } + }, + { + { + { {15,0}, {10,0}, {4,0} }, + { {10,5}, {15,5}, {20,5} } + }, + { + { {20,5}, {15,5}, {10,5} }, + { {15,0}, {10,0}, {4,0} } + }, + { 30,0 } + }, + }; + for (const Test &test : tests) { + Polylines chained = chain_polylines(test.unchained, &test.initial_point); + REQUIRE(chained == test.chained); + ExtrusionEntityCollection unchained_extrusions; + extrusion_entities_append_paths(unchained_extrusions.entities, test.unchained, + erInternalInfill, 0., 0.4f, 0.3f); + ExtrusionEntityCollection chained_extrusions = unchained_extrusions.chained_path_from(test.initial_point); + REQUIRE(chained_extrusions.entities.size() == test.chained.size()); + for (size_t i = 0; i < chained_extrusions.entities.size(); ++ i) { + const Points &p1 = test.chained[i].points; + const Points &p2 = dynamic_cast(chained_extrusions.entities[i])->polyline.points; + REQUIRE(p1 == p2); + } + } +} \ No newline at end of file diff --git a/tests/fff_print/test_fill.cpp b/tests/fff_print/test_fill.cpp index 8e311282e..9f30bf8be 100644 --- a/tests/fff_print/test_fill.cpp +++ b/tests/fff_print/test_fill.cpp @@ -7,6 +7,7 @@ #include "libslic3r/Fill/Fill.hpp" #include "libslic3r/Flow.hpp" #include "libslic3r/Geometry.hpp" +#include "libslic3r/Geometry/ConvexHull.hpp" #include "libslic3r/Print.hpp" #include "libslic3r/SVG.hpp" #include "libslic3r/libslic3r.h" @@ -14,6 +15,7 @@ #include "test_data.hpp" using namespace Slic3r; +using namespace std::literals; bool test_if_solid_surface_filled(const ExPolygon& expolygon, double flow_spacing, double angle = 0, double density = 1.0); @@ -43,7 +45,7 @@ TEST_CASE("Fill: Pattern Path Length", "[Fill]") { SECTION("Square") { Slic3r::Points test_set; test_set.reserve(4); - std::vector points {Vec2d(0,0), Vec2d(100,0), Vec2d(100,100), Vec2d(0,100)}; + std::vector points { {0,0}, {100,0}, {100,100}, {0,100} }; for (size_t i = 0; i < 4; ++i) { std::transform(points.cbegin()+i, points.cend(), std::back_inserter(test_set), [] (const Vec2d& a) -> Point { return Point::new_scale(a.x(), a.y()); } ); std::transform(points.cbegin(), points.cbegin()+i, std::back_inserter(test_set), [] (const Vec2d& a) -> Point { return Point::new_scale(a.x(), a.y()); } ); @@ -118,24 +120,26 @@ TEST_CASE("Fill: Pattern Path Length", "[Fill]") { REQUIRE(std::abs(paths[0].length() - static_cast(scale_(3*100 + 2*50))) - SCALED_EPSILON > 0); // path has expected length } - SECTION("Rotated Square") { - Slic3r::Points square { Point::new_scale(0,0), Point::new_scale(50,0), Point::new_scale(50,50), Point::new_scale(0,50)}; - Slic3r::ExPolygon expolygon(square); + SECTION("Rotated Square produces one continuous path") { + Slic3r::ExPolygon expolygon(Polygon::new_scale({ {0, 0}, {50, 0}, {50, 50}, {0, 50} })); std::unique_ptr filler(Slic3r::Fill::new_from_type("rectilinear")); - filler->bounding_box = get_extents(expolygon.contour); + filler->bounding_box = get_extents(expolygon); filler->angle = 0; Surface surface(stTop, expolygon); - auto flow = Slic3r::Flow(0.69f, 0.4f, 0.50f); + // width, height, nozzle_dmr + auto flow = Slic3r::Flow(0.69f, 0.4f, 0.5f); FillParams fill_params; - fill_params.density = 1.0; - filler->spacing = flow.spacing(); - - for (auto angle : { 0.0, 45.0}) { - surface.expolygon.rotate(angle, Point(0,0)); - Polylines paths = filler->fill_surface(&surface, fill_params); - REQUIRE(paths.size() == 1); + for (auto density : { 0.4, 1.0 }) { + fill_params.density = density; + filler->spacing = flow.spacing(); + for (auto angle : { 0.0, 45.0}) { + surface.expolygon.rotate(angle, Point(0,0)); + Polylines paths = filler->fill_surface(&surface, fill_params); + // one continuous path + REQUIRE(paths.size() == 1); + } } } @@ -190,202 +194,226 @@ TEST_CASE("Fill: Pattern Path Length", "[Fill]") { } } +SCENARIO("Infill does not exceed perimeters", "[Fill]") +{ + auto test = [](const std::string_view pattern) { + DynamicPrintConfig config = Slic3r::DynamicPrintConfig::full_print_config(); + config.set_deserialize_strict({ + { "nozzle_diameter", "0.4, 0.4, 0.4, 0.4" }, + { "fill_pattern", pattern }, + { "top_fill_pattern", pattern }, + { "bottom_fill_pattern", pattern }, + { "perimeters", 1 }, + { "skirts", 0 }, + { "fill_density", 0.2 }, + { "layer_height", 0.05 }, + { "perimeter_extruder", 1 }, + { "infill_extruder", 2 } + }); + + WHEN("40mm cube sliced") { + std::string gcode = Slic3r::Test::slice({ mesh(Slic3r::Test::TestMesh::cube_20x20x20, Vec3d::Zero(), 2.0) }, config); + THEN("gcode not empty") { + REQUIRE(! gcode.empty()); + } + THEN("infill does not exceed perimeters") { + GCodeReader parser; + const int perimeter_extruder = config.opt_int("perimeter_extruder"); + const int infill_extruder = config.opt_int("infill_extruder"); + int tool = -1; + Points perimeter_points; + Points infill_points; + parser.parse_buffer(gcode, [&tool, &perimeter_points, &infill_points, perimeter_extruder, infill_extruder] + (Slic3r::GCodeReader &self, const Slic3r::GCodeReader::GCodeLine &line) + { + // if the command is a T command, set the the current tool + if (boost::starts_with(line.cmd(), "T")) { + tool = atoi(line.cmd().data() + 1) + 1; + } else if (line.cmd() == "G1" && line.extruding(self) && line.dist_XY(self) > 0) { + if (tool == perimeter_extruder) + perimeter_points.emplace_back(line.new_XY_scaled(self)); + else if (tool == infill_extruder) + infill_points.emplace_back(line.new_XY_scaled(self)); + } + }); + auto convex_hull = Geometry::convex_hull(perimeter_points); + int num_inside = std::count_if(infill_points.begin(), infill_points.end(), [&convex_hull](const Point &pt){ return convex_hull.contains(pt); }); + REQUIRE(num_inside == infill_points.size()); + } + } + }; + + GIVEN("Rectilinear") { test("rectilinear"sv); } + GIVEN("Honeycomb") { test("honeycomb"sv); } + GIVEN("HilbertCurve") { test("hilbertcurve"sv); } + GIVEN("Concentric") { test("concentric"sv); } +} + +SCENARIO("Infill only where needed", "[Fill]") +{ + DynamicPrintConfig config = Slic3r::DynamicPrintConfig::full_print_config(); + config.set_deserialize_strict({ + { "nozzle_diameter", "0.4, 0.4, 0.4, 0.4" }, + { "infill_only_where_needed", true }, + { "bottom_solid_layers", 0 }, + { "infill_extruder", 2 }, + { "infill_extrusion_width", 0.5 }, + { "wipe_into_infill", false }, + { "fill_density", 0.4 }, + // for preventing speeds from being altered + { "cooling", "0, 0, 0, 0" }, + // for preventing speeds from being altered + { "first_layer_speed", "100%" } + }); + + auto test = [&config]() -> double { + std::string gcode = Slic3r::Test::slice({ Slic3r::Test::TestMesh::pyramid }, config); + THEN("gcode not empty") { + REQUIRE(! gcode.empty()); + } + + GCodeReader parser; + int tool = -1; + const int infill_extruder = config.opt_int("infill_extruder"); + Points infill_points; + parser.parse_buffer(gcode, [&tool, &infill_points, infill_extruder](Slic3r::GCodeReader &self, const Slic3r::GCodeReader::GCodeLine &line) + { + // if the command is a T command, set the the current tool + if (boost::starts_with(line.cmd(), "T")) { + tool = atoi(line.cmd().data() + 1) + 1; + } else if (line.cmd() == "G1" && line.extruding(self) && line.dist_XY(self) > 0) { + if (tool == infill_extruder) { + infill_points.emplace_back(self.xy_scaled()); + infill_points.emplace_back(line.new_XY_scaled(self)); + } + } + }); + // prevent calling convex_hull() with no points + THEN("infill not empty") { + REQUIRE(! infill_points.empty()); + } + + auto opt_width = config.opt("infill_extrusion_width"); + REQUIRE(! opt_width->percent); + Polygons convex_hull = expand(Geometry::convex_hull(infill_points), scaled(opt_width->value / 2)); + return SCALING_FACTOR * SCALING_FACTOR * std::accumulate(convex_hull.begin(), convex_hull.end(), 0., [](double acc, const Polygon &poly){ return acc + poly.area(); }); + }; + + double tolerance = 5; // mm^2 + + GIVEN("solid_infill_below_area == 0") { + config.opt_float("solid_infill_below_area") = 0; + WHEN("pyramid is sliced ") { + auto area = test(); + THEN("no infill is generated when using infill_only_where_needed on a pyramid") { + REQUIRE(area < tolerance); + } + } + } + GIVEN("solid_infill_below_area == 70") { + config.opt_float("solid_infill_below_area") = 70; + WHEN("pyramid is sliced ") { + auto area = test(); + THEN("infill is only generated under the forced solid shells") { + REQUIRE(std::abs(area - 70) < tolerance); + } + } + } +} + +SCENARIO("Infill density zero", "[Fill]") +{ + WHEN("20mm cube is sliced") { + DynamicPrintConfig config = Slic3r::DynamicPrintConfig::full_print_config(); + config.set_deserialize_strict({ + { "skirts", 0 }, + { "perimeters", 1 }, + { "fill_density", 0 }, + { "top_solid_layers", 0 }, + { "bottom_solid_layers", 0 }, + { "solid_infill_below_area", 20000000 }, + { "solid_infill_every_layers", 2 }, + { "perimeter_speed", 99 }, + { "external_perimeter_speed", 99 }, + { "cooling", "0" }, + { "first_layer_speed", "100%" } + }); + + std::string gcode = Slic3r::Test::slice({ Slic3r::Test::TestMesh::cube_20x20x20 }, config); + THEN("gcode not empty") { + REQUIRE(! gcode.empty()); + } + + THEN("solid_infill_below_area and solid_infill_every_layers are ignored when fill_density is 0") { + GCodeReader parser; + const double perimeter_speed = config.opt_float("perimeter_speed"); + std::map layers_with_extrusion; + parser.parse_buffer(gcode, [&layers_with_extrusion, perimeter_speed](Slic3r::GCodeReader &self, const Slic3r::GCodeReader::GCodeLine &line) { + if (line.cmd() == "G1" && line.extruding(self) && line.dist_XY(self) > 0) { + double f = line.new_F(self); + if (std::abs(f - perimeter_speed * 60.) > 0.01) + // It is a perimeter. + layers_with_extrusion[self.z()] = f; + } + }); + REQUIRE(layers_with_extrusion.empty()); + } + } + + WHEN("A is sliced") { + DynamicPrintConfig config = Slic3r::DynamicPrintConfig::full_print_config(); + config.set_deserialize_strict({ + { "skirts", 0 }, + { "perimeters", 3 }, + { "fill_density", 0 }, + { "layer_height", 0.2 }, + { "first_layer_height", 0.2 }, + { "nozzle_diameter", "0.35,0.35,0.35,0.35" }, + { "infill_extruder", 2 }, + { "solid_infill_extruder", 2 }, + { "infill_extrusion_width", 0.52 }, + { "solid_infill_extrusion_width", 0.52 }, + { "first_layer_extrusion_width", 0 } + }); + + std::string gcode = Slic3r::Test::slice({ Slic3r::Test::TestMesh::A }, config); + THEN("gcode not empty") { + REQUIRE(! gcode.empty()); + } + + THEN("no missing parts in solid shell when fill_density is 0") { + GCodeReader parser; + int tool = -1; + const int infill_extruder = config.opt_int("infill_extruder"); + std::map infill; + parser.parse_buffer(gcode, [&tool, &infill, infill_extruder](Slic3r::GCodeReader &self, const Slic3r::GCodeReader::GCodeLine &line) { + if (boost::starts_with(line.cmd(), "T")) { + tool = atoi(line.cmd().data() + 1) + 1; + } else if (line.cmd() == "G1" && line.extruding(self) && line.dist_XY(self) > 0) { + if (tool == infill_extruder) + infill[scaled(self.z())].emplace_back(self.xy_scaled(), line.new_XY_scaled(self)); + } + }); + auto opt_width = config.opt("infill_extrusion_width"); + REQUIRE(! opt_width->percent); + auto grow_d = scaled(opt_width->value / 2); + auto inflate_lines = [grow_d](const Lines &lines) { + Polygons out; + for (const Line &line : lines) + append(out, offset(Polyline{ line.a, line.b }, grow_d, Slic3r::ClipperLib::jtSquare, 3.)); + return union_(out); + }; + Polygons layer0_infill = inflate_lines(infill[scaled(0.2)]); + Polygons layer1_infill = inflate_lines(infill[scaled(0.4)]); + ExPolygons poly = opening_ex(diff_ex(layer0_infill, layer1_infill), grow_d); + const double threshold = 2. * sqr(grow_d * 2.); + int missing_parts = std::count_if(poly.begin(), poly.end(), [threshold](const ExPolygon &poly){ return poly.area() > threshold; }); + REQUIRE(missing_parts == 0); + } + } +} + /* -{ - my $collection = Slic3r::Polyline::Collection->new( - Slic3r::Polyline->new([0,15], [0,18], [0,20]), - Slic3r::Polyline->new([0,10], [0,8], [0,5]), - ); - is_deeply - [ map $_->[Y], map @$_, @{$collection->chained_path_from(Slic3r::Point->new(0,30), 0)} ], - [20, 18, 15, 10, 8, 5], - 'chained path'; -} - -{ - my $collection = Slic3r::Polyline::Collection->new( - Slic3r::Polyline->new([4,0], [10,0], [15,0]), - Slic3r::Polyline->new([10,5], [15,5], [20,5]), - ); - is_deeply - [ map $_->[X], map @$_, @{$collection->chained_path_from(Slic3r::Point->new(30,0), 0)} ], - [reverse 4, 10, 15, 10, 15, 20], - 'chained path'; -} - -{ - my $collection = Slic3r::ExtrusionPath::Collection->new( - map Slic3r::ExtrusionPath->new(polyline => $_, role => 0, mm3_per_mm => 1), - Slic3r::Polyline->new([0,15], [0,18], [0,20]), - Slic3r::Polyline->new([0,10], [0,8], [0,5]), - ); - is_deeply - [ map $_->[Y], map @{$_->polyline}, @{$collection->chained_path_from(Slic3r::Point->new(0,30), 0)} ], - [20, 18, 15, 10, 8, 5], - 'chained path'; -} - -{ - my $collection = Slic3r::ExtrusionPath::Collection->new( - map Slic3r::ExtrusionPath->new(polyline => $_, role => 0, mm3_per_mm => 1), - Slic3r::Polyline->new([15,0], [10,0], [4,0]), - Slic3r::Polyline->new([10,5], [15,5], [20,5]), - ); - is_deeply - [ map $_->[X], map @{$_->polyline}, @{$collection->chained_path_from(Slic3r::Point->new(30,0), 0)} ], - [reverse 4, 10, 15, 10, 15, 20], - 'chained path'; -} - -for my $pattern (qw(rectilinear honeycomb hilbertcurve concentric)) { - my $config = Slic3r::Config->new_from_defaults; - $config->set('fill_pattern', $pattern); - $config->set('external_fill_pattern', $pattern); - $config->set('perimeters', 1); - $config->set('skirts', 0); - $config->set('fill_density', 20); - $config->set('layer_height', 0.05); - $config->set('perimeter_extruder', 1); - $config->set('infill_extruder', 2); - my $print = Slic3r::Test::init_print('20mm_cube', config => $config, scale => 2); - ok my $gcode = Slic3r::Test::gcode($print), "successful $pattern infill generation"; - my $tool = undef; - my @perimeter_points = my @infill_points = (); - Slic3r::GCode::Reader->new->parse($gcode, sub { - my ($self, $cmd, $args, $info) = @_; - - if ($cmd =~ /^T(\d+)/) { - $tool = $1; - } elsif ($cmd eq 'G1' && $info->{extruding} && $info->{dist_XY} > 0) { - if ($tool == $config->perimeter_extruder-1) { - push @perimeter_points, Slic3r::Point->new_scale($args->{X}, $args->{Y}); - } elsif ($tool == $config->infill_extruder-1) { - push @infill_points, Slic3r::Point->new_scale($args->{X}, $args->{Y}); - } - } - }); - my $convex_hull = convex_hull(\@perimeter_points); - ok !(defined first { !$convex_hull->contains_point($_) } @infill_points), "infill does not exceed perimeters ($pattern)"; -} - -{ - my $config = Slic3r::Config->new_from_defaults; - $config->set('infill_only_where_needed', 1); - $config->set('bottom_solid_layers', 0); - $config->set('infill_extruder', 2); - $config->set('infill_extrusion_width', 0.5); - $config->set('fill_density', 40); - $config->set('cooling', 0); # for preventing speeds from being altered - $config->set('first_layer_speed', '100%'); # for preventing speeds from being altered - - my $test = sub { - my $print = Slic3r::Test::init_print('pyramid', config => $config); - - my $tool = undef; - my @infill_extrusions = (); # array of polylines - Slic3r::GCode::Reader->new->parse(Slic3r::Test::gcode($print), sub { - my ($self, $cmd, $args, $info) = @_; - - if ($cmd =~ /^T(\d+)/) { - $tool = $1; - } elsif ($cmd eq 'G1' && $info->{extruding} && $info->{dist_XY} > 0) { - if ($tool == $config->infill_extruder-1) { - push @infill_extrusions, Slic3r::Line->new_scale( - [ $self->X, $self->Y ], - [ $info->{new_X}, $info->{new_Y} ], - ); - } - } - }); - return 0 if !@infill_extrusions; # prevent calling convex_hull() with no points - - my $convex_hull = convex_hull([ map $_->pp, map @$_, @infill_extrusions ]); - return unscale unscale sum(map $_->area, @{offset([$convex_hull], scale(+$config->infill_extrusion_width/2))}); - }; - - my $tolerance = 5; # mm^2 - - $config->set('solid_infill_below_area', 0); - ok $test->() < $tolerance, - 'no infill is generated when using infill_only_where_needed on a pyramid'; - - $config->set('solid_infill_below_area', 70); - ok abs($test->() - $config->solid_infill_below_area) < $tolerance, - 'infill is only generated under the forced solid shells'; -} - -{ - my $config = Slic3r::Config->new_from_defaults; - $config->set('skirts', 0); - $config->set('perimeters', 1); - $config->set('fill_density', 0); - $config->set('top_solid_layers', 0); - $config->set('bottom_solid_layers', 0); - $config->set('solid_infill_below_area', 20000000); - $config->set('solid_infill_every_layers', 2); - $config->set('perimeter_speed', 99); - $config->set('external_perimeter_speed', 99); - $config->set('cooling', 0); - $config->set('first_layer_speed', '100%'); - - my $print = Slic3r::Test::init_print('20mm_cube', config => $config); - my %layers_with_extrusion = (); - Slic3r::GCode::Reader->new->parse(Slic3r::Test::gcode($print), sub { - my ($self, $cmd, $args, $info) = @_; - - if ($cmd eq 'G1' && $info->{dist_XY} > 0 && $info->{extruding}) { - if (($args->{F} // $self->F) != $config->perimeter_speed*60) { - $layers_with_extrusion{$self->Z} = ($args->{F} // $self->F); - } - } - }); - - ok !%layers_with_extrusion, - "solid_infill_below_area and solid_infill_every_layers are ignored when fill_density is 0"; -} - -{ - my $config = Slic3r::Config->new_from_defaults; - $config->set('skirts', 0); - $config->set('perimeters', 3); - $config->set('fill_density', 0); - $config->set('layer_height', 0.2); - $config->set('first_layer_height', 0.2); - $config->set('nozzle_diameter', [0.35]); - $config->set('infill_extruder', 2); - $config->set('solid_infill_extruder', 2); - $config->set('infill_extrusion_width', 0.52); - $config->set('solid_infill_extrusion_width', 0.52); - $config->set('first_layer_extrusion_width', 0); - - my $print = Slic3r::Test::init_print('A', config => $config); - my %infill = (); # Z => [ Line, Line ... ] - my $tool = undef; - Slic3r::GCode::Reader->new->parse(Slic3r::Test::gcode($print), sub { - my ($self, $cmd, $args, $info) = @_; - - if ($cmd =~ /^T(\d+)/) { - $tool = $1; - } elsif ($cmd eq 'G1' && $info->{extruding} && $info->{dist_XY} > 0) { - if ($tool == $config->infill_extruder-1) { - my $z = 1 * $self->Z; - $infill{$z} ||= []; - push @{$infill{$z}}, Slic3r::Line->new_scale( - [ $self->X, $self->Y ], - [ $info->{new_X}, $info->{new_Y} ], - ); - } - } - }); - my $grow_d = scale($config->infill_extrusion_width)/2; - my $layer0_infill = union([ map @{$_->grow($grow_d)}, @{ $infill{0.2} } ]); - my $layer1_infill = union([ map @{$_->grow($grow_d)}, @{ $infill{0.4} } ]); - my $diff = diff($layer0_infill, $layer1_infill); - $diff = offset2_ex($diff, -$grow_d, +$grow_d); - $diff = [ grep { $_->area > 2*(($grow_d*2)**2) } @$diff ]; - is scalar(@$diff), 0, 'no missing parts in solid shell when fill_density is 0'; -} - { # GH: #2697 my $config = Slic3r::Config->new_from_defaults; @@ -427,6 +455,78 @@ for my $pattern (qw(rectilinear honeycomb hilbertcurve concentric)) { my @holes = map @{$_->holes}, @$covered; ok sum(map unscale unscale $_->area*-1, @holes) < 1, 'no gaps between top solid infill and perimeters'; } + +{ + skip "The FillRectilinear2 does not fill the surface completely", 1; + + my $test = sub { + my ($expolygon, $flow_spacing, $angle, $density) = @_; + + my $filler = Slic3r::Filler->new_from_type('rectilinear'); + $filler->set_bounding_box($expolygon->bounding_box); + $filler->set_angle($angle // 0); + # Adjust line spacing to fill the region. + $filler->set_dont_adjust(0); + $filler->set_link_max_length(scale(1.2*$flow_spacing)); + my $surface = Slic3r::Surface->new( + surface_type => S_TYPE_BOTTOM, + expolygon => $expolygon, + ); + my $flow = Slic3r::Flow->new( + width => $flow_spacing, + height => 0.4, + nozzle_diameter => $flow_spacing, + ); + $filler->set_spacing($flow->spacing); + my $paths = $filler->fill_surface( + $surface, + layer_height => $flow->height, + density => $density // 1, + ); + + # check whether any part was left uncovered + my @grown_paths = map @{Slic3r::Polyline->new(@$_)->grow(scale $filler->spacing/2)}, @$paths; + my $uncovered = diff_ex([ @$expolygon ], [ @grown_paths ], 1); + + # ignore very small dots + my $uncovered_filtered = [ grep $_->area > (scale $flow_spacing)**2, @$uncovered ]; + + is scalar(@$uncovered_filtered), 0, 'solid surface is fully filled'; + + if (0 && @$uncovered_filtered) { + require "Slic3r/SVG.pm"; + Slic3r::SVG::output("uncovered.svg", + no_arrows => 1, + expolygons => [ $expolygon ], + blue_expolygons => [ @$uncovered ], + red_expolygons => [ @$uncovered_filtered ], + polylines => [ @$paths ], + ); + exit; + } + }; + + my $expolygon = Slic3r::ExPolygon->new([ + [6883102, 9598327.01296997], + [6883102, 20327272.01297], + [3116896, 20327272.01297], + [3116896, 9598327.01296997], + ]); + $test->($expolygon, 0.55); + + for (1..20) { + $expolygon->scale(1.05); + $test->($expolygon, 0.55); + } + + $expolygon = Slic3r::ExPolygon->new( + [[59515297,5422499],[59531249,5578697],[59695801,6123186],[59965713,6630228],[60328214,7070685],[60773285,7434379],[61274561,7702115],[61819378,7866770],[62390306,7924789],[62958700,7866744],[63503012,7702244],[64007365,7434357],[64449960,7070398],[64809327,6634999],[65082143,6123325],[65245005,5584454],[65266967,5422499],[66267307,5422499],[66269190,8310081],[66275379,17810072],[66277259,20697500],[65267237,20697500],[65245004,20533538],[65082082,19994444],[64811462,19488579],[64450624,19048208],[64012101,18686514],[63503122,18415781],[62959151,18251378],[62453416,18198442],[62390147,18197355],[62200087,18200576],[61813519,18252990],[61274433,18415918],[60768598,18686517],[60327567,19047892],[59963609,19493297],[59695865,19994587],[59531222,20539379],[59515153,20697500],[58502480,20697500],[58502480,5422499]] + ); + $test->($expolygon, 0.524341649025257); + + $expolygon = Slic3r::ExPolygon->new([ scale_points [0,0], [98,0], [98,10], [0,10] ]); + $test->($expolygon, 0.5, 45, 0.99); # non-solid infill +} */ bool test_if_solid_surface_filled(const ExPolygon& expolygon, double flow_spacing, double angle, double density) diff --git a/xs/CMakeLists.txt b/xs/CMakeLists.txt index 06fc98322..022ba2c01 100644 --- a/xs/CMakeLists.txt +++ b/xs/CMakeLists.txt @@ -53,11 +53,8 @@ set(XS_XSP_FILES ${XSP_DIR}/ExtrusionLoop.xsp ${XSP_DIR}/ExtrusionMultiPath.xsp ${XSP_DIR}/ExtrusionPath.xsp - ${XSP_DIR}/ExtrusionSimulator.xsp - ${XSP_DIR}/Filler.xsp ${XSP_DIR}/Flow.xsp ${XSP_DIR}/GCode.xsp - # ${XSP_DIR}/GCodeSender.xsp ${XSP_DIR}/Geometry.xsp ${XSP_DIR}/Layer.xsp ${XSP_DIR}/Line.xsp diff --git a/xs/lib/Slic3r/XS.pm b/xs/lib/Slic3r/XS.pm index 6d3bf35cf..83bc0ee70 100644 --- a/xs/lib/Slic3r/XS.pm +++ b/xs/lib/Slic3r/XS.pm @@ -133,23 +133,6 @@ sub clone { ); } -package Slic3r::ExtrusionSimulator; - -sub new { - my ($class, %args) = @_; - return $class->_new(); -} - -package Slic3r::Filler; - -sub fill_surface { - my ($self, $surface, %args) = @_; - $self->set_density($args{density}) if defined($args{density}); - $self->set_dont_adjust($args{dont_adjust}) if defined($args{dont_adjust}); - $self->set_complete($args{complete}) if defined($args{complete}); - return $self->_fill_surface($surface); -} - package Slic3r::Flow; sub new { @@ -255,19 +238,12 @@ for my $class (qw( Slic3r::ExtrusionMultiPath Slic3r::ExtrusionPath Slic3r::ExtrusionPath::Collection - Slic3r::ExtrusionSimulator - Slic3r::Filler Slic3r::Flow Slic3r::GCode Slic3r::GCode::PlaceholderParser Slic3r::Geometry::BoundingBox Slic3r::Geometry::BoundingBoxf Slic3r::Geometry::BoundingBoxf3 - Slic3r::GUI::_3DScene::GLShader - Slic3r::GUI::_3DScene::GLVolume - Slic3r::GUI::Preset - Slic3r::GUI::PresetCollection - Slic3r::GUI::Tab Slic3r::Layer Slic3r::Layer::Region Slic3r::Layer::Support diff --git a/xs/main.xs.in b/xs/main.xs.in index c10f432d8..d8db108be 100644 --- a/xs/main.xs.in +++ b/xs/main.xs.in @@ -2,7 +2,6 @@ #include #include #include -// #include #ifdef __cplusplus /* extern "C" { */ diff --git a/xs/src/perlglue.cpp b/xs/src/perlglue.cpp index 20288243e..2d996120d 100644 --- a/xs/src/perlglue.cpp +++ b/xs/src/perlglue.cpp @@ -9,8 +9,6 @@ REGISTER_CLASS(ExtrusionMultiPath, "ExtrusionMultiPath"); REGISTER_CLASS(ExtrusionPath, "ExtrusionPath"); REGISTER_CLASS(ExtrusionLoop, "ExtrusionLoop"); REGISTER_CLASS(ExtrusionEntityCollection, "ExtrusionPath::Collection"); -REGISTER_CLASS(ExtrusionSimulator, "ExtrusionSimulator"); -REGISTER_CLASS(Filler, "Filler"); REGISTER_CLASS(Flow, "Flow"); REGISTER_CLASS(CoolingBuffer, "GCode::CoolingBuffer"); REGISTER_CLASS(GCode, "GCode"); diff --git a/xs/xsp/ExtrusionSimulator.xsp b/xs/xsp/ExtrusionSimulator.xsp deleted file mode 100644 index 9395913b4..000000000 --- a/xs/xsp/ExtrusionSimulator.xsp +++ /dev/null @@ -1,50 +0,0 @@ -%module{Slic3r::XS}; - -%{ -#include -#include "libslic3r/ExtrusionSimulator.hpp" -%} - -%name{Slic3r::ExtrusionSimulator} class ExtrusionSimulator { - ~ExtrusionSimulator(); - %name{_new} ExtrusionSimulator(); - - Clone clone() - %code{% RETVAL = THIS; %}; - - void set_image_size(Point *image_size) - %code{% THIS->set_image_size(*image_size); %}; - void set_viewport(BoundingBox *viewport) - %code{% THIS->set_viewport(*viewport); %}; - void set_bounding_box(BoundingBox *bbox) - %code{% THIS->set_bounding_box(*bbox); %}; - - void reset_accumulator(); - void extrude_to_accumulator(ExtrusionPath *path, Point *shift, ExtrusionSimulationType simulationType) - %code{% THIS->extrude_to_accumulator(*path, *shift, simulationType); %}; - void evaluate_accumulator(ExtrusionSimulationType simulationType); - void* image_ptr() - %code{% RETVAL = const_cast(const_cast(THIS)->image_ptr()); %}; - -%{ - -%} -}; - -%package{Slic3r::ExtrusionSimulator}; -%{ - -IV -_constant() - ALIAS: - EXTRSIM_SIMPLE = ExtrusionSimulationSimple - EXTRSIM_DONT_SPREAD = ExtrusionSimulationDontSpread - EXTRSIM_SPREAD_NFULL = ExtrisopmSimulationSpreadNotOverfilled - EXTRSIM_SPREAD_FULL = ExtrusionSimulationSpreadFull - EXTRSIM_SPREAD_EXCESS = ExtrusionSimulationSpreadExcess - PROTOTYPE: - CODE: - RETVAL = ix; - OUTPUT: RETVAL - -%} diff --git a/xs/xsp/Filler.xsp b/xs/xsp/Filler.xsp deleted file mode 100644 index 2ea2b34d5..000000000 --- a/xs/xsp/Filler.xsp +++ /dev/null @@ -1,65 +0,0 @@ -%module{Slic3r::XS}; - -%{ -#include -#include "libslic3r/Fill/Fill.hpp" -#include "libslic3r/ExtrusionEntity.hpp" -#include "libslic3r/ExtrusionEntityCollection.hpp" -%} - -%name{Slic3r::Filler} class Filler { - ~Filler(); - - void set_bounding_box(BoundingBox *bbox) - %code{% THIS->fill->set_bounding_box(*bbox); %}; - void set_spacing(coordf_t spacing) - %code{% THIS->fill->spacing = spacing; %}; - coordf_t spacing() - %code{% RETVAL = THIS->fill->spacing; %}; - void set_layer_id(size_t layer_id) - %code{% THIS->fill->layer_id = layer_id; %}; - void set_z(coordf_t z) - %code{% THIS->fill->z = z; %}; - void set_angle(float angle) - %code{% THIS->fill->angle = angle; %}; - void set_link_max_length(coordf_t len) - %code{% THIS->fill->link_max_length = len; %}; - void set_loop_clipping(coordf_t clipping) - %code{% THIS->fill->loop_clipping = clipping; %}; - - bool use_bridge_flow() - %code{% RETVAL = THIS->fill->use_bridge_flow(); %}; - bool no_sort() - %code{% RETVAL = THIS->fill->no_sort(); %}; - - void set_density(float density) - %code{% THIS->params.density = density; %}; - void set_dont_adjust(bool dont_adjust) - %code{% THIS->params.dont_adjust = dont_adjust; %}; - - PolylineCollection* _fill_surface(Surface *surface) - %code{% - PolylineCollection *pc = NULL; - if (THIS->fill != NULL) { - pc = new PolylineCollection(); - pc->polylines = THIS->fill->fill_surface(surface, THIS->params); - } - RETVAL = pc; - %}; - -%{ - -Filler* -new_from_type(CLASS, type) - char* CLASS; - std::string type; - CODE: - Filler *filler = new Filler(); - filler->fill = Fill::new_from_type(type); - RETVAL = filler; - OUTPUT: - RETVAL - -%} - -}; diff --git a/xs/xsp/GCodeSender.xsp b/xs/xsp/GCodeSender.xsp deleted file mode 100644 index f99244a1f..000000000 --- a/xs/xsp/GCodeSender.xsp +++ /dev/null @@ -1,24 +0,0 @@ -%module{Slic3r::XS}; - -%{ -#include -#include "libslic3r/GCodeSender.hpp" -%} - -%name{Slic3r::GCode::Sender} class GCodeSender { - GCodeSender(); - ~GCodeSender(); - - bool connect(std::string port, unsigned int baud_rate); - void disconnect(); - bool is_connected(); - bool wait_connected(unsigned int timeout = 3); - int queue_size(); - void send(std::string s, bool priority = false); - void pause_queue(); - void resume_queue(); - void purge_queue(bool priority = false); - std::vector purge_log(); - std::string getT(); - std::string getB(); -}; diff --git a/xs/xsp/my.map b/xs/xsp/my.map index ca26750dc..a660041bc 100644 --- a/xs/xsp/my.map +++ b/xs/xsp/my.map @@ -118,14 +118,6 @@ ExtrusionLoop* O_OBJECT_SLIC3R Ref O_OBJECT_SLIC3R_T Clone O_OBJECT_SLIC3R_T -ExtrusionSimulator* O_OBJECT_SLIC3R -Ref O_OBJECT_SLIC3R_T -Clone O_OBJECT_SLIC3R_T - -Filler* O_OBJECT_SLIC3R -Ref O_OBJECT_SLIC3R_T -Clone O_OBJECT_SLIC3R_T - Flow* O_OBJECT_SLIC3R Ref O_OBJECT_SLIC3R_T Clone O_OBJECT_SLIC3R_T diff --git a/xs/xsp/typemap.xspt b/xs/xsp/typemap.xspt index f9e61c6a0..cc7109445 100644 --- a/xs/xsp/typemap.xspt +++ b/xs/xsp/typemap.xspt @@ -58,9 +58,6 @@ %typemap{ExPolygonCollection*}; %typemap{Ref}{simple}; %typemap{Clone}{simple}; -%typemap{Filler*}; -%typemap{Ref}{simple}; -%typemap{Clone}{simple}; %typemap{Flow*}; %typemap{Ref}{simple}; %typemap{Clone}{simple}; @@ -88,9 +85,6 @@ %typemap{ExtrusionLoop*}; %typemap{Ref}{simple}; %typemap{Clone}{simple}; -%typemap{ExtrusionSimulator*}; -%typemap{Ref}{simple}; -%typemap{Clone}{simple}; %typemap{TriangleMesh*}; %typemap{Ref}{simple}; %typemap{Clone}{simple};