From dc2789a0e81030f6ac33127556f311c2dcf6e533 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Thu, 9 Jun 2022 10:12:30 +0200 Subject: [PATCH 1/4] Added computation of bridging perimeters for Arachne. --- src/libslic3r/Arachne/utils/ExtrusionLine.cpp | 17 +++ src/libslic3r/Arachne/utils/ExtrusionLine.hpp | 31 +++++ src/libslic3r/PerimeterGenerator.cpp | 121 +++++++++++++++--- 3 files changed, 148 insertions(+), 21 deletions(-) diff --git a/src/libslic3r/Arachne/utils/ExtrusionLine.cpp b/src/libslic3r/Arachne/utils/ExtrusionLine.cpp index bfec48075..0b9c9a7b1 100644 --- a/src/libslic3r/Arachne/utils/ExtrusionLine.cpp +++ b/src/libslic3r/Arachne/utils/ExtrusionLine.cpp @@ -5,6 +5,7 @@ #include "ExtrusionLine.hpp" #include "linearAlg2D.hpp" +#include "../../PerimeterGenerator.hpp" namespace Slic3r::Arachne { @@ -231,4 +232,20 @@ int64_t ExtrusionLine::calculateExtrusionAreaDeviationError(ExtrusionJunction A, } } +} // namespace Slic3r::Arachne + +namespace Slic3r { +void extrusion_paths_append(ExtrusionPaths &dst, const ClipperLib_Z::Paths &extrusion_paths, const ExtrusionRole role, const Flow &flow) +{ + for (const ClipperLib_Z::Path &extrusion_path : extrusion_paths) { + ThickPolyline thick_polyline = Arachne::to_thick_polyline(extrusion_path); + Slic3r::append(dst, thick_polyline_to_extrusion_paths(thick_polyline, role, flow, scaled(0.05), 0)); + } } + +void extrusion_paths_append(ExtrusionPaths &dst, const Arachne::ExtrusionLine &extrusion, const ExtrusionRole role, const Flow &flow) +{ + ThickPolyline thick_polyline = Arachne::to_thick_polyline(extrusion); + Slic3r::append(dst, thick_polyline_to_extrusion_paths(thick_polyline, role, flow, scaled(0.05), 0)); +} +} // namespace Slic3r \ No newline at end of file diff --git a/src/libslic3r/Arachne/utils/ExtrusionLine.hpp b/src/libslic3r/Arachne/utils/ExtrusionLine.hpp index 07d8d41a2..a7189cebd 100644 --- a/src/libslic3r/Arachne/utils/ExtrusionLine.hpp +++ b/src/libslic3r/Arachne/utils/ExtrusionLine.hpp @@ -9,6 +9,9 @@ #include "../../Polyline.hpp" #include "../../Polygon.hpp" #include "../../BoundingBox.hpp" +#include "../../ExtrusionEntity.hpp" +#include "../../Flow.hpp" +#include "../../../clipper/clipper_z.hpp" namespace Slic3r { class ThickPolyline; @@ -208,6 +211,26 @@ static inline Slic3r::ThickPolyline to_thick_polyline(const Arachne::ExtrusionLi return out; } +static inline Slic3r::ThickPolyline to_thick_polyline(const ClipperLib_Z::Path &path) +{ + assert(path.size() >= 2); + Slic3r::ThickPolyline out; + out.points.emplace_back(path.front().x(), path.front().y()); + out.width.emplace_back(path.front().z()); + out.points.emplace_back(path[1].x(), path[1].y()); + out.width.emplace_back(path[1].z()); + + auto it_prev = path.begin() + 1; + for (auto it = path.begin() + 2; it != path.end(); ++it) { + out.points.emplace_back(it->x(), it->y()); + out.width.emplace_back(it_prev->z()); + out.width.emplace_back(it->z()); + it_prev = it; + } + + return out; +} + static inline Polygon to_polygon(const ExtrusionLine &line) { Polygon out; @@ -269,4 +292,12 @@ static std::vector to_points(const std::vector &e using VariableWidthLines = std::vector; // #include @@ -277,6 +280,101 @@ static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perime return out; } +static ClipperLib_Z::Paths clip_extrusion(const ClipperLib_Z::Path &subject, const ClipperLib_Z::Paths &clip, ClipperLib_Z::ClipType clipType) +{ + ClipperLib_Z::Clipper clipper; + clipper.ZFillFunction([](const ClipperLib_Z::IntPoint &e1bot, const ClipperLib_Z::IntPoint &e1top, const ClipperLib_Z::IntPoint &e2bot, + const ClipperLib_Z::IntPoint &e2top, ClipperLib_Z::IntPoint &pt) { + ClipperLib_Z::IntPoint start = e1bot; + ClipperLib_Z::IntPoint end = e1top; + + if (start.z() <= 0 && end.z() <= 0) { + start = e2bot; + end = e2top; + } + + assert(start.z() > 0 && end.z() > 0); + + // Interpolate extrusion line width. + double length_sqr = (end - start).cast().squaredNorm(); + double dist_sqr = (pt - start).cast().squaredNorm(); + double t = std::sqrt(dist_sqr / length_sqr); + + pt.z() = start.z() + coord_t((end.z() - start.z()) * t); + }); + + clipper.AddPath(subject, ClipperLib_Z::ptSubject, false); + clipper.AddPaths(clip, ClipperLib_Z::ptClip, true); + + ClipperLib_Z::PolyTree clipped_polytree; + ClipperLib_Z::Paths clipped_paths; + clipper.Execute(clipType, clipped_polytree, ClipperLib_Z::pftNonZero, ClipperLib_Z::pftNonZero); + ClipperLib_Z::PolyTreeToPaths(clipped_polytree, clipped_paths); + + return clipped_paths; +} + +static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator &perimeter_generator, const std::vector &extrusions) +{ + ExtrusionEntityCollection extrusion_coll; + for (const Arachne::ExtrusionLine *extrusion : extrusions) { + if (extrusion->empty()) + continue; + + const bool is_external = extrusion->inset_idx == 0; + ExtrusionRole role = is_external ? erExternalPerimeter : erPerimeter; + + ExtrusionPaths paths; + // detect overhanging/bridging perimeters + if (perimeter_generator.config->overhangs && perimeter_generator.layer_id > perimeter_generator.object_config->raft_layers + && ! ((perimeter_generator.object_config->support_material || perimeter_generator.object_config->support_material_enforce_layers > 0) && + perimeter_generator.object_config->support_material_contact_distance.value == 0)) { + + ClipperLib_Z::Path extrusion_path; + extrusion_path.reserve(extrusion->size()); + for (const Arachne::ExtrusionJunction &ej : extrusion->junctions) + extrusion_path.emplace_back(ej.p.x(), ej.p.y(), ej.w); + + ClipperLib_Z::Paths lower_slices_paths; + lower_slices_paths.reserve(perimeter_generator.lower_slices_polygons().size()); + for (const Polygon &poly : perimeter_generator.lower_slices_polygons()) { + lower_slices_paths.emplace_back(); + ClipperLib_Z::Path &out = lower_slices_paths.back(); + out.reserve(poly.points.size()); + for (const Point &pt : poly.points) + out.emplace_back(pt.x(), pt.y(), 0); + } + + // get non-overhang paths by intersecting this loop with the grown lower slices + extrusion_paths_append(paths, clip_extrusion(extrusion_path, lower_slices_paths, ClipperLib_Z::ctIntersection), role, + is_external ? perimeter_generator.ext_perimeter_flow : perimeter_generator.perimeter_flow); + + // get overhang paths by checking what parts of this loop fall + // outside the grown lower slices (thus where the distance between + // the loop centerline and original lower slices is >= half nozzle diameter + extrusion_paths_append(paths, clip_extrusion(extrusion_path, lower_slices_paths, ClipperLib_Z::ctDifference), erOverhangPerimeter, + perimeter_generator.overhang_flow); + + // Reapply the nearest point search for starting point. + // We allow polyline reversal because Clipper may have randomly reversed polylines during clipping. + chain_and_reorder_extrusion_paths(paths, &paths.front().first_point()); + } else { + extrusion_paths_append(paths, *extrusion, role, is_external ? perimeter_generator.ext_perimeter_flow : perimeter_generator.perimeter_flow); + } + + // Append paths to collection. + if (!paths.empty()) { + if (extrusion->is_closed) + extrusion_coll.entities.emplace_back(new ExtrusionLoop(std::move(paths))); + else + for (ExtrusionPath &path : paths) + extrusion_coll.entities.emplace_back(new ExtrusionPath(std::move(path))); + } + } + + return extrusion_coll; +} + // Thanks, Cura developers, for implementing an algorithm for generating perimeters with variable width (Arachne) that is based on the paper // "A framework for adaptive width control of dense contour-parallel toolpaths in fused deposition modeling" void PerimeterGenerator::process_arachne() @@ -406,27 +504,8 @@ void PerimeterGenerator::process_arachne() } } - for (const Arachne::ExtrusionLine *extrusion : ordered_extrusions) { - if (extrusion->empty()) - continue; - - ExtrusionEntityCollection entities_coll; - - ThickPolyline thick_polyline = Arachne::to_thick_polyline(*extrusion); - bool ext_perimeter = extrusion->inset_idx == 0; - ExtrusionPaths paths = thick_polyline_to_extrusion_paths(thick_polyline, ext_perimeter ? erExternalPerimeter : erPerimeter, - ext_perimeter ? this->ext_perimeter_flow : this->perimeter_flow, scaled(0.05), 0); - // Append paths to collection. - if (!paths.empty()) { - if (paths.front().first_point() == paths.back().last_point()) - entities_coll.entities.emplace_back(new ExtrusionLoop(std::move(paths))); - else - for (ExtrusionPath &path : paths) - entities_coll.entities.emplace_back(new ExtrusionPath(std::move(path))); - } - - this->loops->append(entities_coll); - } + if (ExtrusionEntityCollection extrusion_coll = traverse_extrusions(*this, ordered_extrusions); !extrusion_coll.empty()) + this->loops->append(extrusion_coll); ExPolygons infill_contour = union_ex(wallToolPaths.getInnerContour()); // create one more offset to be used as boundary for fill From 357dbb46869c0ef145606cdf46f2231f62156048 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Thu, 9 Jun 2022 10:15:54 +0200 Subject: [PATCH 2/4] Fixed the flow of bridging perimeters for Arachne. --- src/libslic3r/PerimeterGenerator.cpp | 2 +- src/libslic3r/PerimeterGenerator.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp index 0706c60e2..8ea70daed 100644 --- a/src/libslic3r/PerimeterGenerator.cpp +++ b/src/libslic3r/PerimeterGenerator.cpp @@ -67,7 +67,7 @@ ExtrusionPaths thick_polyline_to_extrusion_paths(const ThickPolyline &thick_poly path.polyline.append(line.b); // Convert from spacing to extrusion width based on the extrusion model // of a square extrusion ended with semi circles. - Flow new_flow = flow.with_width(unscale(w) + flow.height() * float(1. - 0.25 * PI)); + Flow new_flow = (role == erOverhangPerimeter && flow.bridge()) ? flow : flow.with_width(unscale(w) + flow.height() * float(1. - 0.25 * PI)); #ifdef SLIC3R_DEBUG printf(" filling %f gap\n", flow.width); #endif diff --git a/src/libslic3r/PerimeterGenerator.hpp b/src/libslic3r/PerimeterGenerator.hpp index d38f6b8fa..2e478e107 100644 --- a/src/libslic3r/PerimeterGenerator.hpp +++ b/src/libslic3r/PerimeterGenerator.hpp @@ -72,7 +72,7 @@ private: Polygons m_lower_slices_polygons; }; -ExtrusionPaths thick_polyline_to_extrusion_paths(const ThickPolyline &thick_polyline, ExtrusionRole role, const Flow &flow, const float tolerance, const float merge_tolerance); +ExtrusionPaths thick_polyline_to_extrusion_paths(const ThickPolyline &thick_polyline, ExtrusionRole role, const Flow &flow, float tolerance, float merge_tolerance); } From 3d9b13a5e3d761433147d4e6bc00a7280f72aae2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Mon, 6 Jun 2022 14:06:54 +0200 Subject: [PATCH 3/4] Added fuzzy skin for Arachne. --- src/libslic3r/Arachne/WallToolPaths.cpp | 2 +- src/libslic3r/Arachne/WallToolPaths.hpp | 2 +- src/libslic3r/PerimeterGenerator.cpp | 102 ++++++++++++++++++++++-- 3 files changed, 97 insertions(+), 9 deletions(-) diff --git a/src/libslic3r/Arachne/WallToolPaths.cpp b/src/libslic3r/Arachne/WallToolPaths.cpp index 104c780f5..803d6d2c1 100644 --- a/src/libslic3r/Arachne/WallToolPaths.cpp +++ b/src/libslic3r/Arachne/WallToolPaths.cpp @@ -761,7 +761,7 @@ bool WallToolPaths::removeEmptyToolPaths(std::vector &toolpa * * \param outer_to_inner Whether the wall polygons with a lower inset_idx should go before those with a higher one. */ -std::unordered_set, boost::hash>> WallToolPaths::getRegionOrder(const std::vector &input, const bool outer_to_inner) +std::unordered_set, boost::hash>> WallToolPaths::getRegionOrder(const std::vector &input, const bool outer_to_inner) { std::unordered_set, boost::hash>> order_requirements; diff --git a/src/libslic3r/Arachne/WallToolPaths.hpp b/src/libslic3r/Arachne/WallToolPaths.hpp index 698f84115..9be1159b3 100644 --- a/src/libslic3r/Arachne/WallToolPaths.hpp +++ b/src/libslic3r/Arachne/WallToolPaths.hpp @@ -81,7 +81,7 @@ public: * * \param outer_to_inner Whether the wall polygons with a lower inset_idx should go before those with a higher one. */ - static std::unordered_set, boost::hash>> getRegionOrder(const std::vector &input, bool outer_to_inner); + static std::unordered_set, boost::hash>> getRegionOrder(const std::vector &input, bool outer_to_inner); protected: /*! diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp index 8ea70daed..a0ea876fc 100644 --- a/src/libslic3r/PerimeterGenerator.cpp +++ b/src/libslic3r/PerimeterGenerator.cpp @@ -172,6 +172,43 @@ static void fuzzy_polygon(Polygon &poly, double fuzzy_skin_thickness, double fuz poly.points = std::move(out); } +// Thanks Cura developers for this function. +static void fuzzy_extrusion_line(Arachne::ExtrusionLine &ext_lines, double fuzzy_skin_thickness, double fuzzy_skin_point_dist) +{ + const double min_dist_between_points = fuzzy_skin_point_dist * 3. / 4.; // hardcoded: the point distance may vary between 3/4 and 5/4 the supplied value + const double range_random_point_dist = fuzzy_skin_point_dist / 2.; + double dist_left_over = double(rand()) * (min_dist_between_points / 2) / double(RAND_MAX); // the distance to be traversed on the line before making the first new point + + auto * p0 = &ext_lines.junctions.back(); + std::vector out; + out.reserve(ext_lines.size()); + for (auto &p1 : ext_lines) + { // 'a' is the (next) new point between p0 and p1 + Vec2d p0p1 = (p1.p - p0->p).cast(); + double p0p1_size = p0p1.norm(); + // so that p0p1_size - dist_last_point evaulates to dist_left_over - p0p1_size + double dist_last_point = dist_left_over + p0p1_size * 2.; + for (double p0pa_dist = dist_left_over; p0pa_dist < p0p1_size; + p0pa_dist += min_dist_between_points + double(rand()) * range_random_point_dist / double(RAND_MAX)) + { + double r = double(rand()) * (fuzzy_skin_thickness * 2.) / double(RAND_MAX) - fuzzy_skin_thickness; + out.emplace_back(p0->p + (p0p1 * (p0pa_dist / p0p1_size) + perp(p0p1).cast().normalized() * r).cast(), p1.w, p1.perimeter_index); + dist_last_point = p0pa_dist; + } + dist_left_over = p0p1_size - dist_last_point; + p0 = &p1; + } + while (out.size() < 3) { + size_t point_idx = ext_lines.size() - 2; + out.emplace_back(ext_lines[point_idx].p, ext_lines[point_idx].w, ext_lines[point_idx].perimeter_index); + if (point_idx == 0) + break; + -- point_idx; + } + if (out.size() >= 3) + ext_lines.junctions = std::move(out); +} + using PerimeterGeneratorLoops = std::vector; static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perimeter_generator, const PerimeterGeneratorLoops &loops, ThickPolylines &thin_walls) @@ -314,16 +351,27 @@ static ClipperLib_Z::Paths clip_extrusion(const ClipperLib_Z::Path &subject, con return clipped_paths; } -static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator &perimeter_generator, const std::vector &extrusions) +struct PerimeterGeneratorArachneExtrusion +{ + Arachne::ExtrusionLine *extrusion = nullptr; + // Should this extrusion be fuzzyfied on path generation? + bool fuzzify = false; +}; + +static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator &perimeter_generator, std::vector &pg_extrusions) { ExtrusionEntityCollection extrusion_coll; - for (const Arachne::ExtrusionLine *extrusion : extrusions) { + for (PerimeterGeneratorArachneExtrusion &pg_extrusion : pg_extrusions) { + Arachne::ExtrusionLine *extrusion = pg_extrusion.extrusion; if (extrusion->empty()) continue; const bool is_external = extrusion->inset_idx == 0; ExtrusionRole role = is_external ? erExternalPerimeter : erPerimeter; + if (pg_extrusion.fuzzify) + fuzzy_extrusion_line(*extrusion, scaled(perimeter_generator.config->fuzzy_skin_thickness.value), scaled(perimeter_generator.config->fuzzy_skin_point_dist.value)); + ExtrusionPaths paths; // detect overhanging/bridging perimeters if (perimeter_generator.config->overhangs && perimeter_generator.layer_id > perimeter_generator.object_config->raft_layers @@ -425,11 +473,11 @@ void PerimeterGenerator::process_arachne() direction = 1; } - std::vector all_extrusions; + std::vector all_extrusions; for (int perimeter_idx = start_perimeter; perimeter_idx != end_perimeter; perimeter_idx += direction) { if (perimeters[perimeter_idx].empty()) continue; - for (const Arachne::ExtrusionLine &wall : perimeters[perimeter_idx]) + for (Arachne::ExtrusionLine &wall : perimeters[perimeter_idx]) all_extrusions.emplace_back(&wall); } @@ -447,9 +495,9 @@ void PerimeterGenerator::process_arachne() blocking[map_extrusion_to_idx.find(before)->second].emplace_back(after_it->second); } - std::vector processed(all_extrusions.size(), false); // Indicate that the extrusion was already processed. + std::vector processed(all_extrusions.size(), false); // Indicate that the extrusion was already processed. Point current_position = all_extrusions.empty() ? Point::Zero() : all_extrusions.front()->junctions.front().p; // Some starting position. - std::vector ordered_extrusions; // To store our result in. At the end we'll std::swap. + std::vector ordered_extrusions; // To store our result in. At the end we'll std::swap. ordered_extrusions.reserve(all_extrusions.size()); while (ordered_extrusions.size() < all_extrusions.size()) { @@ -491,7 +539,7 @@ void PerimeterGenerator::process_arachne() } auto &best_path = all_extrusions[best_candidate]; - ordered_extrusions.push_back(best_path); + ordered_extrusions.push_back({best_path, false}); processed[best_candidate] = true; for (size_t unlocked_idx : blocking[best_candidate]) blocked[unlocked_idx]--; @@ -504,6 +552,46 @@ void PerimeterGenerator::process_arachne() } } + if (this->layer_id > 0 && this->config->fuzzy_skin != FuzzySkinType::None) { + std::vector closed_loop_extrusions; + for (PerimeterGeneratorArachneExtrusion &extrusion : ordered_extrusions) + if (extrusion.extrusion->inset_idx == 0) { + if (extrusion.extrusion->is_closed && this->config->fuzzy_skin == FuzzySkinType::External) { + closed_loop_extrusions.emplace_back(&extrusion); + } else { + extrusion.fuzzify = true; + } + } + + if (this->config->fuzzy_skin == FuzzySkinType::External) { + ClipperLib_Z::Paths loops_paths; + loops_paths.reserve(closed_loop_extrusions.size()); + for (const auto &cl_extrusion : closed_loop_extrusions) { + assert(cl_extrusion->extrusion->junctions.front() == cl_extrusion->extrusion->junctions.back()); + size_t loop_idx = &cl_extrusion - &closed_loop_extrusions.front(); + ClipperLib_Z::Path loop_path; + loop_path.reserve(cl_extrusion->extrusion->junctions.size() - 1); + for (auto junction_it = cl_extrusion->extrusion->junctions.begin(); junction_it != std::prev(cl_extrusion->extrusion->junctions.end()); ++junction_it) + loop_path.emplace_back(junction_it->p.x(), junction_it->p.y(), loop_idx); + loops_paths.emplace_back(loop_path); + } + + ClipperLib_Z::Clipper clipper; + clipper.AddPaths(loops_paths, ClipperLib_Z::ptSubject, true); + ClipperLib_Z::PolyTree loops_polytree; + clipper.Execute(ClipperLib_Z::ctUnion, loops_polytree, ClipperLib_Z::pftEvenOdd, ClipperLib_Z::pftEvenOdd); + + for (const ClipperLib_Z::PolyNode *child_node : loops_polytree.Childs) { + // The whole contour must have the same index. + coord_t polygon_idx = child_node->Contour.front().z(); + bool has_same_idx = std::all_of(child_node->Contour.begin(), child_node->Contour.end(), + [&polygon_idx](const ClipperLib_Z::IntPoint &point) -> bool { return polygon_idx == point.z(); }); + if (has_same_idx) + closed_loop_extrusions[polygon_idx]->fuzzify = true; + } + } + } + if (ExtrusionEntityCollection extrusion_coll = traverse_extrusions(*this, ordered_extrusions); !extrusion_coll.empty()) this->loops->append(extrusion_coll); From ce038fd7f07d01782863f0f53f9d7737d84e7677 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Thu, 9 Jun 2022 10:53:43 +0200 Subject: [PATCH 4/4] Reenabled some of the previously disabled tests after the computation of bridging perimeters was added. One test was disabled for Arachne because Arachne is causing issues with seam alignment. --- t/perimeters.t | 4 ---- tests/fff_print/test_print.cpp | 5 +---- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/t/perimeters.t b/t/perimeters.t index b55f9527d..a5262f0b8 100644 --- a/t/perimeters.t +++ b/t/perimeters.t @@ -257,8 +257,6 @@ use Slic3r::Test; $config->set('bridge_fan_speed', [ 100 ]); $config->set('bridge_flow_ratio', 33); # arbitrary value $config->set('overhangs', 1); - # FIXME Lukas H.: For now, this unit test is disabled for Arachne because of an issue with detecting overhang when Arachne is enabled. - $config->set('perimeter_generator', 'classic'); my $print = Slic3r::Test::init_print('overhang', config => $config); my %layer_speeds = (); # print Z => [ speeds ] my $fan_speed = 0; @@ -397,8 +395,6 @@ use Slic3r::Test; $config->set('overhangs', 1); $config->set('cooling', [ 0 ]); # to prevent speeds from being altered $config->set('first_layer_speed', '100%'); # to prevent speeds from being altered - # FIXME Lukas H.: For now, this unit test is disabled for Arachne because of an issue with detecting overhang when Arachne is enabled. - $config->set('perimeter_generator', 'classic'); my $test = sub { my ($print) = @_; diff --git a/tests/fff_print/test_print.cpp b/tests/fff_print/test_print.cpp index eac8c98a1..a139e4c2b 100644 --- a/tests/fff_print/test_print.cpp +++ b/tests/fff_print/test_print.cpp @@ -20,10 +20,7 @@ SCENARIO("PrintObject: Perimeter generation", "[PrintObject]") { } THEN("Every layer in region 0 has 1 island of perimeters") { for (const Layer *layer : object.layers()) - if (object.config().perimeter_generator == PerimeterGeneratorType::Arachne) - REQUIRE(layer->regions().front()->perimeters.entities.size() == 3); - else - REQUIRE(layer->regions().front()->perimeters.entities.size() == 1); + REQUIRE(layer->regions().front()->perimeters.entities.size() == 1); } THEN("Every layer in region 0 has 3 paths in its perimeters list.") { for (const Layer *layer : object.layers())