diff options
author | supermerill <merill@free.fr> | 2021-11-02 22:06:17 +0300 |
---|---|---|
committer | supermerill <merill@free.fr> | 2021-11-06 15:49:22 +0300 |
commit | 8cc345ad27d163b83985789d5d130bc8f2acd541 (patch) | |
tree | 17d94fc35979d6cfc212bc2ed99ab578da285b06 /src | |
parent | 1822af78543c90e89fd39c6fadf47c352262952c (diff) |
Fix for clipper fix 37838be
It can create 0-length segments. These have to be pruned.
supermerill/SuperSlicer#1641
supermerill/SuperSlicer#1781
Diffstat (limited to 'src')
-rw-r--r-- | src/libslic3r/ClipperUtils.cpp | 44 | ||||
-rw-r--r-- | src/libslic3r/PerimeterGenerator.cpp | 6 |
2 files changed, 32 insertions, 18 deletions
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<coord_t> 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<ClipperLib::PolyNode*> 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; - } + std::vector<ClipperLib::PolyNode*> 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; } - to_check.insert(to_check.end(), node->Childs.begin(), node->Childs.end()); } + //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()) { |