diff --git a/src/libslic3r/ExtrusionEntity.hpp b/src/libslic3r/ExtrusionEntity.hpp index 279c1a0cf..aea71da0f 100644 --- a/src/libslic3r/ExtrusionEntity.hpp +++ b/src/libslic3r/ExtrusionEntity.hpp @@ -88,6 +88,8 @@ enum ExtrusionLoopRole : uint16_t { elrHole = 1 << 3, // 8 //it's a modifier that indicate that the loop should be printed as vase elrVase = 1 << 4, //16 + //it's a modifier that indicate that the loop does not contains an inner loop, used for random seam + elrFirstLoop = 1 << 5, //32 }; diff --git a/src/libslic3r/GCode/SeamPlacer.cpp b/src/libslic3r/GCode/SeamPlacer.cpp index 99158ee08..4ddf59a00 100644 --- a/src/libslic3r/GCode/SeamPlacer.cpp +++ b/src/libslic3r/GCode/SeamPlacer.cpp @@ -206,6 +206,8 @@ void SeamPlacer::init(const Print& print) explgs = Slic3r::offset_ex(explgs, scale_(max_nozzle_dmr)); for (ExPolygons& explgs : m_blockers) explgs = Slic3r::offset_ex(explgs, scale_(max_nozzle_dmr)); + + this->external_perimeters_first = print.default_region_config().external_perimeters_first; } @@ -439,22 +441,30 @@ Point SeamPlacer::get_seam(const Layer *layer, SeamPosition seam_position, return polygon.points[idx_min]; } else { // spRandom - if ( (loop.loop_role() & elrInternal) != 0 && loop.role() != erExternalPerimeter) { + if ( (loop.loop_role() & ExtrusionLoopRole::elrInternal) != 0 && loop.role() != erExternalPerimeter) { // This loop does not contain any other loop. Set a random position. // The other loops will get a seam close to the random point chosen // on the innermost contour. - //FIXME This works correctly for inner contours first only. last_pos = this->get_random_seam(layer_idx, polygon); - } - if (loop.role() == erExternalPerimeter && is_custom_seam_on_layer(layer_idx)) { - // There is a possibility that the loop will be influenced by custom - // seam enforcer/blocker. In this case do not inherit the seam - // from internal loops (which may conflict with the custom selection - // and generate another random one. - bool saw_custom = false; - Point candidate = this->get_random_seam(layer_idx, polygon, &saw_custom); - if (saw_custom) - last_pos = candidate; + } else if (loop.role() == erExternalPerimeter) { + if (is_custom_seam_on_layer(layer_idx)) { + // There is a possibility that the loop will be influenced by custom + // seam enforcer/blocker. In this case do not inherit the seam + // from internal loops (which may conflict with the custom selection + // and generate another random one. + bool saw_custom = false; + Point candidate = this->get_random_seam(layer_idx, polygon, &saw_custom); + if (saw_custom) + last_pos = candidate; + } else if (external_perimeters_first || (loop.loop_role() & ExtrusionLoopRole::elrFirstLoop) != 0) { + // this is if external_perimeters_first + // this is if only space for one externalperimeter. + //in these case, there isn't a seam from the inner loops, so we had to creat our on + last_pos = this->get_random_seam(layer_idx, polygon); + } + } else if (loop.role() == erThinWall) { + //thin wall loop is like an external perimeter, but without anything near it. + last_pos = this->get_random_seam(layer_idx, polygon); } return last_pos; } diff --git a/src/libslic3r/GCode/SeamPlacer.hpp b/src/libslic3r/GCode/SeamPlacer.hpp index d72079f2e..4d99dcee9 100644 --- a/src/libslic3r/GCode/SeamPlacer.hpp +++ b/src/libslic3r/GCode/SeamPlacer.hpp @@ -51,6 +51,9 @@ private: //std::map m_last_seam_position; SeamHistory m_seam_history; + + // if it's expected, we need to randomized at the external periemter. + bool external_perimeters_first; // Get indices of points inside enforcers and blockers. void get_enforcers_and_blockers(size_t layer_id, diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp index 394bbe281..eae335e51 100644 --- a/src/libslic3r/PerimeterGenerator.cpp +++ b/src/libslic3r/PerimeterGenerator.cpp @@ -1103,6 +1103,9 @@ ExtrusionEntityCollection PerimeterGenerator::_traverse_loops( if (!loop.is_contour) { loop_role = (ExtrusionLoopRole)(loop_role | ExtrusionLoopRole::elrHole); } + if (loop.children.empty()) { + loop_role = ExtrusionLoopRole(loop_role | ExtrusionLoopRole::elrFirstLoop); + } if (this->config->external_perimeters_vase.value && this->config->external_perimeters_first.value && is_external) { if ((loop.is_contour && this->config->external_perimeters_nothole.value) || (!loop.is_contour && this->config->external_perimeters_hole.value)) { loop_role = (ExtrusionLoopRole)(loop_role | ExtrusionLoopRole::elrVase);