diff --git a/src/libslic3r/ClipperUtils.cpp b/src/libslic3r/ClipperUtils.cpp index b7d9a142a..cc91ce050 100644 --- a/src/libslic3r/ClipperUtils.cpp +++ b/src/libslic3r/ClipperUtils.cpp @@ -598,16 +598,18 @@ ClipperLib::PolyTree _clipper_do_pl(const ClipperLib::ClipType clipType, const P // read input ClipperLib::Paths input_subject = Slic3rMultiPoints_to_ClipperPaths(subject); ClipperLib::Paths input_clip = Slic3rMultiPoints_to_ClipperPaths(clip); + //scale to have some more precision to do some Y-bugfix + scaleClipperPolygons(input_subject); + scaleClipperPolygons(input_clip); //perform y safing : if a line is on the same Y, clipper may not pick the good point. - std::set bad_y; - for (ClipperLib::Paths* input : {&input_subject, &input_clip} ) + //note: if not enough, next time, add some of the X coordinate (modulo it so it's contained in the scaling part) + for (ClipperLib::Paths* input : { &input_subject, &input_clip }) for (ClipperLib::Path& path : *input) { coord_t lasty = 0; for (ClipperLib::IntPoint& pt : path) { if (lasty == pt.Y) { - pt.Y+=5; //min is 3 on a certain exemple. Using 5 to have some security - bad_y.insert(pt.Y); + pt.Y += 50;// well below CLIPPER_OFFSET_POWER_OF_2 } lasty = pt.Y; } @@ -629,19 +631,31 @@ ClipperLib::PolyTree _clipper_do_pl(const ClipperLib::ClipType clipType, const P clipper.Execute(clipType, retval, fillType, fillType); //restore good y - if (!bad_y.empty()) { - std::vector to_check; - to_check.push_back(&retval); - while (!to_check.empty()) { - ClipperLib::PolyNode* node = to_check.back(); - to_check.pop_back(); - for (ClipperLib::IntPoint& pt : node->Contour) { - if (bad_y.find(pt.Y) != bad_y.end()) { - pt.Y-=5; - } - } - to_check.insert(to_check.end(), node->Childs.begin(), node->Childs.end()); + std::vector to_check; + to_check.push_back(&retval); + while (!to_check.empty()) { + ClipperLib::PolyNode* node = to_check.back(); + to_check.pop_back(); + for (ClipperLib::IntPoint& pit : node->Contour) { + pit.X += CLIPPER_OFFSET_SCALE_ROUNDING_DELTA; + pit.Y += CLIPPER_OFFSET_SCALE_ROUNDING_DELTA; + pit.X >>= CLIPPER_OFFSET_POWER_OF_2; + pit.Y >>= CLIPPER_OFFSET_POWER_OF_2; } + //note: moving in Y may create 0-length segment, so it needs an extra post-processing step to remove these duplicate points. + for (size_t idx = 1; idx < node->Contour.size(); ++idx) { + ClipperLib::IntPoint& pit = node->Contour[idx]; + ClipperLib::IntPoint& previous = node->Contour[idx - 1]; + // unscaling remove too small differences. The equality is enough. + if (pit.X == previous.X && pit.Y == previous.Y) { + node->Contour.erase(node->Contour.begin() + idx); + --idx; + } + } + //be sure you don't save 1-point paths + if (node->Contour.size() == 1) + node->Contour.clear(); + to_check.insert(to_check.end(), node->Childs.begin(), node->Childs.end()); } return retval; diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp index 796fd9315..4409bd93e 100644 --- a/src/libslic3r/PerimeterGenerator.cpp +++ b/src/libslic3r/PerimeterGenerator.cpp @@ -135,12 +135,12 @@ void PerimeterGenerator::process() } } - if (overhangs_width_speed > 0) { + if (overhangs_width_speed > 0 && this->config->overhangs_width_speed.value < this->config->overhangs_width.value) { this->_lower_slices_bridge_speed_small = offset((simplified.empty() ? *this->lower_slices : simplified), (coordf_t)overhangs_width_speed_90 - (coordf_t)(ext_perimeter_width / 2)); this->_lower_slices_bridge_speed_big = offset((simplified.empty() ? *this->lower_slices : simplified), (coordf_t)overhangs_width_speed_110 - (coordf_t)(ext_perimeter_width / 2)); } if (overhangs_width_flow > 0) { - if (overhangs_width_speed_110 == overhangs_width_flow_90) + if (overhangs_width_speed_110 == overhangs_width_flow_90 && this->config->overhangs_width_speed.value < this->config->overhangs_width.value) this->_lower_slices_bridge_flow_small = this->_lower_slices_bridge_speed_big; else this->_lower_slices_bridge_flow_small = offset((simplified.empty() ? *this->lower_slices : simplified), (coordf_t)overhangs_width_flow_90 - (coordf_t)(ext_perimeter_width / 2)); @@ -1201,7 +1201,7 @@ ExtrusionPaths PerimeterGenerator::create_overhangs(const Polyline& loop_polygon Polylines big_flow; Polylines* previous = &ok_polylines; - if (this->config->overhangs_width_speed.value > 0) { + if (this->config->overhangs_width_speed.value > 0 && this->config->overhangs_width_speed.value < this->config->overhangs_width.value) { if (!this->_lower_slices_bridge_speed_small.empty()) { small_speed = diff_pl(*previous, this->_lower_slices_bridge_speed_small); if (!small_speed.empty()) {