From c1179fc2c7f9048a315a38d390e55d2052b1213d Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik <bubnikv@gmail.com> Date: Tue, 13 Apr 2021 13:28:21 +0200 Subject: [PATCH] Marked the unsafe ClipperUtils offset functions with CLIPPERUTILS_UNSAFE_OFFSET Replaced some of the unsafe offset functions with safe variants. Please test the 1) print bed from STL function 2) concentric infill --- src/libslic3r/BridgeDetector.cpp | 2 +- src/libslic3r/ClipperUtils.hpp | 13 +++++++++++++ src/libslic3r/ExPolygon.hpp | 22 ++++++++++++++++++++++ src/libslic3r/Fill/FillConcentric.cpp | 8 ++++---- src/libslic3r/Fill/FillLine.cpp | 2 +- src/libslic3r/LayerRegion.cpp | 2 +- src/libslic3r/Polygon.hpp | 4 +++- src/libslic3r/TriangleMesh.cpp | 18 ++++++++++-------- 8 files changed, 55 insertions(+), 16 deletions(-) diff --git a/src/libslic3r/BridgeDetector.cpp b/src/libslic3r/BridgeDetector.cpp index ff33e81d5..671ebbdaa 100644 --- a/src/libslic3r/BridgeDetector.cpp +++ b/src/libslic3r/BridgeDetector.cpp @@ -40,7 +40,7 @@ void BridgeDetector::initialize() this->angle = -1.; // Outset our bridge by an arbitrary amout; we'll use this outer margin for detecting anchors. - Polygons grown = offset(to_polygons(this->expolygons), float(this->spacing)); + Polygons grown = offset(this->expolygons, float(this->spacing)); // Detect possible anchoring edges of this bridging region. // Detect what edges lie on lower slices by turning bridge contour and holes diff --git a/src/libslic3r/ClipperUtils.hpp b/src/libslic3r/ClipperUtils.hpp index c1b887583..6668a9ae9 100644 --- a/src/libslic3r/ClipperUtils.hpp +++ b/src/libslic3r/ClipperUtils.hpp @@ -12,6 +12,8 @@ using ClipperLib::jtMiter; using ClipperLib::jtRound; using ClipperLib::jtSquare; +#define CLIPPERUTILS_UNSAFE_OFFSET + // #define CLIPPERUTILS_OFFSET_SCALE #ifdef CLIPPERUTILS_OFFSET_SCALE @@ -51,8 +53,11 @@ ClipperLib::Paths _offset(ClipperLib::Path &&input, ClipperLib::EndType endType, ClipperLib::Paths _offset(ClipperLib::Paths &&input, ClipperLib::EndType endType, const float delta, ClipperLib::JoinType joinType, double miterLimit); inline Slic3r::Polygons offset(const Slic3r::Polygon &polygon, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3) { return ClipperPaths_to_Slic3rPolygons(_offset(Slic3rMultiPoint_to_ClipperPath(polygon), ClipperLib::etClosedPolygon, delta, joinType, miterLimit)); } + +#ifdef CLIPPERUTILS_UNSAFE_OFFSET inline Slic3r::Polygons offset(const Slic3r::Polygons &polygons, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3) { return ClipperPaths_to_Slic3rPolygons(_offset(Slic3rMultiPoints_to_ClipperPaths(polygons), ClipperLib::etClosedPolygon, delta, joinType, miterLimit)); } +#endif // CLIPPERUTILS_UNSAFE_OFFSET // offset Polylines inline Slic3r::Polygons offset(const Slic3r::Polyline &polyline, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtSquare, double miterLimit = 3) @@ -69,13 +74,18 @@ inline Slic3r::Polygons offset(const Slic3r::ExPolygons &expolygons, const float { return ClipperPaths_to_Slic3rPolygons(_offset(expolygons, delta, joinType, miterLimit)); } inline Slic3r::ExPolygons offset_ex(const Slic3r::Polygon &polygon, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3) { return ClipperPaths_to_Slic3rExPolygons(_offset(Slic3rMultiPoint_to_ClipperPath(polygon), ClipperLib::etClosedPolygon, delta, joinType, miterLimit)); } + +#ifdef CLIPPERUTILS_UNSAFE_OFFSET inline Slic3r::ExPolygons offset_ex(const Slic3r::Polygons &polygons, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3) { return ClipperPaths_to_Slic3rExPolygons(_offset(Slic3rMultiPoints_to_ClipperPaths(polygons), ClipperLib::etClosedPolygon, delta, joinType, miterLimit)); } +#endif // CLIPPERUTILS_UNSAFE_OFFSET + inline Slic3r::ExPolygons offset_ex(const Slic3r::ExPolygon &expolygon, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3) { return ClipperPaths_to_Slic3rExPolygons(_offset(expolygon, delta, joinType, miterLimit)); } inline Slic3r::ExPolygons offset_ex(const Slic3r::ExPolygons &expolygons, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3) { return ClipperPaths_to_Slic3rExPolygons(_offset(expolygons, delta, joinType, miterLimit)); } +#ifdef CLIPPERUTILS_UNSAFE_OFFSET ClipperLib::Paths _offset2(const Slic3r::Polygons &polygons, const float delta1, const float delta2, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3); @@ -85,6 +95,8 @@ Slic3r::Polygons offset2(const Slic3r::Polygons &polygons, const float delta1, Slic3r::ExPolygons offset2_ex(const Slic3r::Polygons &polygons, const float delta1, const float delta2, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3); +#endif // CLIPPERUTILS_UNSAFE_OFFSET + Slic3r::ExPolygons offset2_ex(const Slic3r::ExPolygons &expolygons, const float delta1, const float delta2, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3); @@ -323,6 +335,7 @@ void safety_offset(ClipperLib::Paths* paths); Polygons top_level_islands(const Slic3r::Polygons &polygons); +ClipperLib::Path mittered_offset_path_scaled(const Points &contour, const std::vector<float> &deltas, double miter_limit); Polygons variable_offset_inner(const ExPolygon &expoly, const std::vector<std::vector<float>> &deltas, double miter_limit = 2.); Polygons variable_offset_outer(const ExPolygon &expoly, const std::vector<std::vector<float>> &deltas, double miter_limit = 2.); ExPolygons variable_offset_outer_ex(const ExPolygon &expoly, const std::vector<std::vector<float>> &deltas, double miter_limit = 2.); diff --git a/src/libslic3r/ExPolygon.hpp b/src/libslic3r/ExPolygon.hpp index 46b3a3a1b..73770bb18 100644 --- a/src/libslic3r/ExPolygon.hpp +++ b/src/libslic3r/ExPolygon.hpp @@ -217,6 +217,28 @@ inline Polygons to_polygons(const ExPolygons &src) return polygons; } +inline ConstPolygonPtrs to_polygon_ptrs(const ExPolygon &src) +{ + ConstPolygonPtrs polygons; + polygons.reserve(src.holes.size() + 1); + polygons.emplace_back(&src.contour); + for (const Polygon &hole : src.holes) + polygons.emplace_back(&hole); + return polygons; +} + +inline ConstPolygonPtrs to_polygon_ptrs(const ExPolygons &src) +{ + ConstPolygonPtrs polygons; + polygons.reserve(number_polygons(src)); + for (const ExPolygon &expoly : src) { + polygons.emplace_back(&expoly.contour); + for (const Polygon &hole : expoly.holes) + polygons.emplace_back(&hole); + } + return polygons; +} + inline Polygons to_polygons(ExPolygon &&src) { Polygons polygons; diff --git a/src/libslic3r/Fill/FillConcentric.cpp b/src/libslic3r/Fill/FillConcentric.cpp index 1b96c43a4..785c93be3 100644 --- a/src/libslic3r/Fill/FillConcentric.cpp +++ b/src/libslic3r/Fill/FillConcentric.cpp @@ -24,11 +24,11 @@ void FillConcentric::_fill_surface_single( this->spacing = unscale<double>(distance); } - Polygons loops = to_polygons(std::move(expolygon)); - Polygons last = loops; + Polygons loops = to_polygons(expolygon); + ExPolygons last { std::move(expolygon) }; while (! last.empty()) { - last = offset2(last, -(distance + min_spacing/2), +min_spacing/2); - append(loops, last); + last = offset2_ex(last, -(distance + min_spacing/2), +min_spacing/2); + append(loops, to_polygons(last)); } // generate paths from the outermost to the innermost, to avoid diff --git a/src/libslic3r/Fill/FillLine.cpp b/src/libslic3r/Fill/FillLine.cpp index 6a0a19efd..f6431a333 100644 --- a/src/libslic3r/Fill/FillLine.cpp +++ b/src/libslic3r/Fill/FillLine.cpp @@ -58,7 +58,7 @@ void FillLine::_fill_surface_single( pts.push_back(it->a); pts.push_back(it->b); } - Polylines polylines = intersection_pl(polylines_src, offset(to_polygons(expolygon), scale_(0.02)), false); + Polylines polylines = intersection_pl(polylines_src, offset(expolygon, scale_(0.02)), false); // FIXME Vojtech: This is only performed for horizontal lines, not for the vertical lines! const float INFILL_OVERLAP_OVER_SPACING = 0.3f; diff --git a/src/libslic3r/LayerRegion.cpp b/src/libslic3r/LayerRegion.cpp index f6c0c9c7a..059d94e25 100644 --- a/src/libslic3r/LayerRegion.cpp +++ b/src/libslic3r/LayerRegion.cpp @@ -216,7 +216,7 @@ void LayerRegion::process_external_surfaces(const Layer *lower_layer, const Poly break; } // Grown by 3mm. - Polygons polys = offset(to_polygons(bridges[i].expolygon), margin, EXTERNAL_SURFACES_OFFSET_PARAMETERS); + Polygons polys = offset(bridges[i].expolygon, margin, EXTERNAL_SURFACES_OFFSET_PARAMETERS); if (idx_island == -1) { BOOST_LOG_TRIVIAL(trace) << "Bridge did not fall into the source region!"; } else { diff --git a/src/libslic3r/Polygon.hpp b/src/libslic3r/Polygon.hpp index aa72b4244..dd2d68d46 100644 --- a/src/libslic3r/Polygon.hpp +++ b/src/libslic3r/Polygon.hpp @@ -11,7 +11,9 @@ namespace Slic3r { class Polygon; -typedef std::vector<Polygon> Polygons; +using Polygons = std::vector<Polygon>; +using PolygonPtrs = std::vector<Polygon*>; +using ConstPolygonPtrs = std::vector<const Polygon*>; class Polygon : public MultiPoint { diff --git a/src/libslic3r/TriangleMesh.cpp b/src/libslic3r/TriangleMesh.cpp index d5a349087..f8fa1ca17 100644 --- a/src/libslic3r/TriangleMesh.cpp +++ b/src/libslic3r/TriangleMesh.cpp @@ -511,20 +511,22 @@ void TriangleMesh::merge(const TriangleMesh &mesh) //FIXME This could be extremely slow! Use it for tiny meshes only! ExPolygons TriangleMesh::horizontal_projection() const { - Polygons pp; - pp.reserve(this->stl.stats.number_of_facets); + ClipperLib::Paths paths; + Polygon p; + p.points.assign(3, Point()); + auto delta = scaled<float>(0.01); + std::vector<float> deltas { delta, delta, delta }; + paths.reserve(this->stl.stats.number_of_facets); for (const stl_facet &facet : this->stl.facet_start) { - Polygon p; - p.points.resize(3); p.points[0] = Point::new_scale(facet.vertex[0](0), facet.vertex[0](1)); p.points[1] = Point::new_scale(facet.vertex[1](0), facet.vertex[1](1)); p.points[2] = Point::new_scale(facet.vertex[2](0), facet.vertex[2](1)); - p.make_counter_clockwise(); // do this after scaling, as winding order might change while doing that - pp.emplace_back(p); + p.make_counter_clockwise(); + paths.emplace_back(mittered_offset_path_scaled(p.points, deltas, 3.)); } // the offset factor was tuned using groovemount.stl - return union_ex(offset(pp, scale_(0.01)), true); + return ClipperPaths_to_Slic3rExPolygons(paths); } // 2D convex hull of a 3D mesh projected into the Z=0 plane. @@ -1797,7 +1799,7 @@ void TriangleMeshSlicer::make_expolygons(const Polygons &loops, const float clos // append to the supplied collection if (safety_offset > 0) - expolygons_append(*slices, offset2_ex(union_(loops, false), +safety_offset, -safety_offset)); + expolygons_append(*slices, offset2_ex(union_ex(loops, false), +safety_offset, -safety_offset)); else expolygons_append(*slices, union_ex(loops, false)); }