diff --git a/include/geometry/LinesSet.h b/include/geometry/LinesSet.h index 08f498a17f..212af90228 100644 --- a/include/geometry/LinesSet.h +++ b/include/geometry/LinesSet.h @@ -37,11 +37,14 @@ class LinesSet public: // Required for some std calls as a container - typedef LineType value_type; + using value_type = LineType; + using iterator = typename std::vector::iterator; + using const_iterator = typename std::vector::const_iterator; -public: /*! \brief Builds an empty set */ - LinesSet() = default; + LinesSet() noexcept = default; + + virtual ~LinesSet() = default; /*! \brief Creates a copy of the given lines set */ LinesSet(const LinesSet& other) = default; @@ -66,8 +69,16 @@ class LinesSet * \warning This constructor is actually only defined for a LinesSet containing OpenPolyline * objects, because closed ones require an additional argument */ - template::value>::type> - LinesSet(ClipperLib::Paths&& paths); + template + requires std::is_same_v + LinesSet(ClipperLib::Paths&& paths) + { + reserve(paths.size()); + for (ClipperLib::Path& path : paths) + { + lines_.emplace_back(std::move(path)); + } + } const std::vector& getLines() const { @@ -84,22 +95,22 @@ class LinesSet lines_ = lines; } - std::vector::const_iterator begin() const + const_iterator begin() const { return lines_.begin(); } - std::vector::iterator begin() + iterator begin() { return lines_.begin(); } - std::vector::const_iterator end() const + const_iterator end() const { return lines_.end(); } - std::vector::iterator end() + iterator end() { return lines_.end(); } @@ -126,15 +137,15 @@ class LinesSet /*! * \brief Pushes the given line at the end of the set - * \param checkNonEmpty Indicates whether we should check for the line to be non-empty before adding it + * \param check_non_empty Indicates whether we should check for the line to be non-empty before adding it */ - void push_back(const LineType& line, CheckNonEmptyParam checkNonEmpty = CheckNonEmptyParam::EvenIfEmpty); + void push_back(const LineType& line, CheckNonEmptyParam check_non_empty = CheckNonEmptyParam::EvenIfEmpty); /*! * \brief Pushes the given line at the end of the set and takes ownership of the inner data - * \param checkNonEmpty Indicates whether we should check for the line to be non-empty before adding it + * \param check_non_empty Indicates whether we should check for the line to be non-empty before adding it */ - void push_back(LineType&& line, CheckNonEmptyParam checkNonEmpty = CheckNonEmptyParam::EvenIfEmpty); + void push_back(LineType&& line, CheckNonEmptyParam check_non_empty = CheckNonEmptyParam::EvenIfEmpty); /*! \brief Pushes an entier set at the end and takes ownership of the inner data */ template @@ -151,12 +162,12 @@ class LinesSet lines_.pop_back(); } - size_t size() const + [[nodiscard]] size_t size() const { return lines_.size(); } - bool empty() const + [[nodiscard]] bool empty() const { return lines_.empty(); } @@ -176,13 +187,12 @@ class LinesSet lines_.clear(); } - template - void emplace_back(Args&&... args) + void emplace_back(auto&&... args) { - lines_.emplace_back(args...); + lines_.emplace_back(std::forward(args)...); } - std::vector::iterator erase(std::vector::const_iterator first, std::vector::const_iterator last) + iterator erase(const_iterator first, const_iterator last) { return lines_.erase(first, last); } @@ -193,7 +203,7 @@ class LinesSet return *this; } - LinesSet& operator=(LinesSet&& other) + LinesSet& operator=(LinesSet&& other) noexcept { lines_ = std::move(other.lines_); return *this; diff --git a/include/geometry/Shape.h b/include/geometry/Shape.h index 5e9e1d21d3..46091d49a3 100644 --- a/include/geometry/Shape.h +++ b/include/geometry/Shape.h @@ -30,7 +30,6 @@ class Shape : public LinesSet // Clipper expects and returns implicitely closed polygons static constexpr bool clipper_explicitely_closed_ = false; -public: /*! \brief Constructor of an empty shape */ Shape() = default; @@ -49,38 +48,38 @@ class Shape : public LinesSet */ explicit Shape(ClipperLib::Paths&& paths, bool explicitely_closed = clipper_explicitely_closed_); - Shape& operator=(const Shape& other); + Shape& operator=(const Shape& other) = default; + + Shape& operator=(Shape&& other) noexcept = default; - Shape& operator=(Shape&& other); + ~Shape() override = default; void emplace_back(ClipperLib::Paths&& paths, bool explicitely_closed = clipper_explicitely_closed_); void emplace_back(ClipperLib::Path&& path, bool explicitely_closed = clipper_explicitely_closed_); - template - void emplace_back(Args&&... args) + void emplace_back(auto&&... args) { - LinesSet::emplace_back(args...); + LinesSet::emplace_back(std::forward(args)...); } + [[nodiscard]] Shape difference(const Shape& other) const; - Shape difference(const Shape& other) const; - - Shape unionPolygons(const Shape& other, ClipperLib::PolyFillType fill_type = ClipperLib::pftNonZero) const; + [[nodiscard]] Shape unionPolygons(const Shape& other, ClipperLib::PolyFillType fill_type = ClipperLib::pftNonZero) const; /*! * Union all polygons with each other (When polygons.add(polygon) has been called for overlapping polygons) */ - Shape unionPolygons() const; + [[nodiscard]] Shape unionPolygons() const; - Shape intersection(const Shape& other) const; + [[nodiscard]] Shape intersection(const Shape& other) const; /*! * @brief Overridden definition of LinesSet::offset() * @note The behavior of this method is exactly the same, but it just exists because it allows * for a performance optimization */ - Shape offset(coord_t distance, ClipperLib::JoinType join_type = ClipperLib::jtMiter, double miter_limit = 1.2) const; + [[nodiscard]] Shape offset(coord_t distance, ClipperLib::JoinType join_type = ClipperLib::jtMiter, double miter_limit = 1.2) const; /*! * Intersect polylines with the area covered by the shape. @@ -96,9 +95,9 @@ class Shape : public LinesSet template OpenLinesSet intersection(const LinesSet& polylines, bool restitch = true, const coord_t max_stitch_distance = 10_mu) const; - Shape xorPolygons(const Shape& other, ClipperLib::PolyFillType pft = ClipperLib::pftEvenOdd) const; + [[nodiscard]] Shape xorPolygons(const Shape& other, ClipperLib::PolyFillType pft = ClipperLib::pftEvenOdd) const; - Shape execute(ClipperLib::PolyFillType pft = ClipperLib::pftEvenOdd) const; + [[nodiscard]] Shape execute(ClipperLib::PolyFillType pft = ClipperLib::pftEvenOdd) const; /*! * Check if we are inside the polygon. @@ -112,7 +111,7 @@ class Shape : public LinesSet * \param border_result What to return when the point is exactly on the border * \return Whether the point \p p is inside this polygon (or \p border_result when it is on the border) */ - bool inside(const Point2LL& p, bool border_result = false) const; + [[nodiscard]] bool inside(const Point2LL& p, bool border_result = false) const; /*! * Find the polygon inside which point \p p resides. @@ -127,7 +126,7 @@ class Shape : public LinesSet * \param border_result Whether a point exactly on a polygon counts as inside * \return The index of the polygon inside which the point \p p resides */ - size_t findInside(const Point2LL& p, bool border_result = false) const; + [[nodiscard]] size_t findInside(const Point2LL& p, bool border_result = false) const; /*! * \brief Approximates the convex hull of the polygons. @@ -135,7 +134,7 @@ class Shape : public LinesSet * \return the convex hull (approximately) * */ - Shape approxConvexHull(int extra_outset = 0) const; + [[nodiscard]] Shape approxConvexHull(int extra_outset = 0) const; /*! \brief Make each of the polygons convex */ void makeConvex(); @@ -145,7 +144,7 @@ class Shape : public LinesSet * * \return The area in square micron */ - double area() const; + [[nodiscard]] double area() const; /*! * Smooth out small perpendicular segments @@ -158,7 +157,7 @@ class Shape : public LinesSet * \param remove_length The length of the largest segment removed * \return The smoothed polygon */ - Shape smooth(int remove_length) const; + [[nodiscard]] Shape smooth(int remove_length) const; /*! * Smooth out sharp inner corners, by taking a shortcut which bypasses the corner @@ -167,9 +166,9 @@ class Shape : public LinesSet * \param shortcut_length The desired length of the shortcut line segment introduced (shorter shortcuts may be unavoidable) * \return The resulting polygons */ - Shape smooth_outward(const AngleDegrees angle, int shortcut_length) const; + [[nodiscard]] Shape smoothOutward(const AngleDegrees angle, int shortcut_length) const; - Shape smooth2(int remove_length, int min_area) const; //!< removes points connected to small lines + [[nodiscard]] Shape smooth2(int remove_length, int min_area) const; //!< removes points connected to small lines void removeColinearEdges(const AngleRadians max_deviation_angle = AngleRadians(0.0005)); @@ -178,20 +177,20 @@ class Shape : public LinesSet * Exclude holes and parts within holes. * \return the resulting polygons. */ - Shape getOutsidePolygons() const; + [[nodiscard]] Shape getOutsidePolygons() const; /*! * Split up the polygons into groups according to the even-odd rule. * Each SingleShape in the result has an outline as first polygon, whereas the rest are holes. */ - std::vector splitIntoParts(bool unionAll = false) const; + [[nodiscard]] std::vector splitIntoParts(bool union_all = false) const; /*! * Sort the polygons into bins where each bin has polygons which are contained within one of the polygons in the previous bin. * * \warning When polygons are crossing each other the result is undefined. */ - std::vector sortByNesting() const; + [[nodiscard]] std::vector sortByNesting() const; /*! * Split up the polygons into groups according to the even-odd rule. @@ -199,7 +198,7 @@ class Shape : public LinesSet * * \warning Note that this function reorders the polygons! */ - PartsView splitIntoPartsView(bool unionAll = false); + PartsView splitIntoPartsView(bool union_all = false); /*! * Removes polygons with area smaller than \p min_area_size (note that min_area_size is in mm^2, not in micron^2). @@ -212,9 +211,9 @@ class Shape : public LinesSet * Removes the same polygons from this set (and also empty polygons). * Shape are considered the same if all points lie within [same_distance] of their counterparts. */ - Shape removePolygon(const Shape& to_be_removed, int same_distance = 0) const; + [[nodiscard]] Shape removePolygon(const Shape& to_be_removed, int same_distance = 0) const; - Shape processEvenOdd(ClipperLib::PolyFillType poly_fill_type = ClipperLib::PolyFillType::pftEvenOdd) const; + [[nodiscard]] Shape processEvenOdd(ClipperLib::PolyFillType poly_fill_type = ClipperLib::PolyFillType::pftEvenOdd) const; /*! * Ensure the polygon is manifold, by removing small areas where the polygon touches itself. @@ -231,7 +230,7 @@ class Shape : public LinesSet void applyMatrix(const Point3Matrix& matrix); - Shape offsetMulti(const std::vector& offset_dists) const; + [[nodiscard]] Shape offsetMulti(const std::vector& offset_dists) const; /*! * @brief Remove self-intersections from the polygons @@ -242,7 +241,7 @@ class Shape : public LinesSet * * @return Polygons - the cleaned polygons */ - Shape removeNearSelfIntersections() const; + [[nodiscard]] Shape removeNearSelfIntersections() const; /*! * \brief Simplify the polygon lines using ClipperLib::SimplifyPolygons @@ -271,10 +270,10 @@ class Shape : public LinesSet * \param remove_holes Whether to remove empty holes or everything but the empty holes * \param ret Where to store polygons which are not empty holes */ - void removeEmptyHoles_processPolyTreeNode(const ClipperLib::PolyNode& node, const bool remove_holes, Shape& ret) const; - void splitIntoParts_processPolyTreeNode(ClipperLib::PolyNode* node, std::vector& ret) const; - void sortByNesting_processPolyTreeNode(ClipperLib::PolyNode* node, const size_t nesting_idx, std::vector& ret) const; - void splitIntoPartsView_processPolyTreeNode(PartsView& partsView, Shape& reordered, ClipperLib::PolyNode* node) const; + void removeEmptyHolesProcessPolyTreeNode(const ClipperLib::PolyNode& node, const bool remove_holes, Shape& ret) const; + void splitIntoPartsProcessPolyTreeNode(ClipperLib::PolyNode* node, std::vector& ret) const; + void sortByNestingProcessPolyTreeNode(ClipperLib::PolyNode* node, const size_t nesting_idx, std::vector& ret) const; + void splitIntoPartsViewProcessPolyTreeNode(PartsView& parts_view, Shape& reordered, ClipperLib::PolyNode* node) const; }; } // namespace cura diff --git a/include/geometry/SingleShape.h b/include/geometry/SingleShape.h index a1a185c1df..f57309fdcc 100644 --- a/include/geometry/SingleShape.h +++ b/include/geometry/SingleShape.h @@ -21,6 +21,10 @@ class Polygon; class SingleShape : public Shape { public: + SingleShape() = default; + + explicit SingleShape(Shape&& shape) : Shape{ shape } {}; + Polygon& outerPolygon(); const Polygon& outerPolygon() const; diff --git a/include/settings/EnumSettings.h b/include/settings/EnumSettings.h index 18bd091569..bc6ea72cee 100644 --- a/include/settings/EnumSettings.h +++ b/include/settings/EnumSettings.h @@ -275,7 +275,7 @@ enum class BrimLocation /*! * Convenience binary operator to allow testing brim location easily, like (actual_location & BrimLocation::OUTSIDE) */ -static int operator&(BrimLocation location1, BrimLocation location2) +[[maybe_unused]] static int operator&(BrimLocation location1, BrimLocation location2) { return static_cast(location1) & static_cast(location2); } diff --git a/src/FffGcodeWriter.cpp b/src/FffGcodeWriter.cpp index e798b15a8b..ab8338d2c2 100644 --- a/src/FffGcodeWriter.cpp +++ b/src/FffGcodeWriter.cpp @@ -998,7 +998,7 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage) raft_outline_path = raft_outline_path.difference(storage.primeTower.getOuterPoly(layer_nr)); } - for (const Shape raft_island : raft_outline_path.splitIntoParts()) + for (const Shape& raft_island : raft_outline_path.splitIntoParts()) { Infill infill_comp( EFillMethod::ZIG_ZAG, @@ -2689,7 +2689,7 @@ bool FffGcodeWriter::processInsets( gcode_layer.setOverhangMask(overhang_region); } - const auto roofing_mask = [&]() -> Shape + const auto roofing_mask_fn = [&]() -> Shape { const size_t roofing_layer_count = std::min(mesh.settings.get("roofing_layer_count"), mesh.settings.get("top_layers")); @@ -2711,7 +2711,7 @@ bool FffGcodeWriter::processInsets( return roofing_mask; }(); - gcode_layer.setRoofingMask(roofing_mask); + gcode_layer.setRoofingMask(roofing_mask_fn); } else { diff --git a/src/WallsComputation.cpp b/src/WallsComputation.cpp index 4f02bedc91..752d1cf0c9 100644 --- a/src/WallsComputation.cpp +++ b/src/WallsComputation.cpp @@ -85,7 +85,7 @@ void WallsComputation::generateWalls(SliceLayerPart* part, SectionType section_t part->inner_area = wall_tool_paths.getInnerContour(); } - part->outline = SingleShape({ Simplify(settings_).polygon(part->outline) }); + part->outline = SingleShape{ Simplify(settings_).polygon(part->outline) }; part->print_outline = part->outline; } diff --git a/src/geometry/LinesSet.cpp b/src/geometry/LinesSet.cpp index c1fa4f8172..3f116b41eb 100644 --- a/src/geometry/LinesSet.cpp +++ b/src/geometry/LinesSet.cpp @@ -14,32 +14,21 @@ namespace cura { -template<> -template<> -LinesSet::LinesSet(ClipperLib::Paths&& paths) -{ - reserve(paths.size()); - for (ClipperLib::Path& path : paths) - { - lines_.emplace_back(std::move(path)); - } -} - template -void LinesSet::push_back(const LineType& line, CheckNonEmptyParam checkNonEmpty) +void LinesSet::push_back(const LineType& line, CheckNonEmptyParam check_non_empty) { - if (checkNonEmpty == CheckNonEmptyParam::EvenIfEmpty || ! line.empty()) + if (check_non_empty == CheckNonEmptyParam::EvenIfEmpty || ! line.empty()) { lines_.push_back(line); } } template -void LinesSet::push_back(LineType&& line, CheckNonEmptyParam checkNonEmpty) +void LinesSet::push_back(LineType&& line, CheckNonEmptyParam check_non_empty) { - if (checkNonEmpty == CheckNonEmptyParam::EvenIfEmpty || ! line.empty()) + if (check_non_empty == CheckNonEmptyParam::EvenIfEmpty || ! line.empty()) { - lines_.push_back(line); + lines_.push_back(std::move(line)); } } @@ -60,7 +49,7 @@ size_t LinesSet::pointCount() const return std::accumulate( lines_.begin(), lines_.end(), - size_t(0), + 0ULL, [](size_t total, const LineType& line) { return total + line.size(); @@ -117,7 +106,7 @@ coord_t LinesSet::length() const return std::accumulate( lines_.begin(), lines_.end(), - 0, + 0LL, [](coord_t total, const LineType& line) { return total += line.length(); @@ -147,9 +136,9 @@ Shape LinesSet::offset(coord_t distance, ClipperLib::JoinType jo { if (empty()) { - return Shape(); + return {}; } - else if (distance == 0) + if (distance == 0) { Shape result; for (const ClosedPolyline& line : getLines()) @@ -158,15 +147,12 @@ Shape LinesSet::offset(coord_t distance, ClipperLib::JoinType jo } return result; } - else - { - ClipperLib::Paths ret; - ClipperLib::ClipperOffset clipper(miter_limit, 10.0); - addPaths(clipper, join_type, ClipperLib::etClosedLine); - clipper.MiterLimit = miter_limit; - clipper.Execute(ret, static_cast(distance)); - return Shape(std::move(ret)); - } + ClipperLib::Paths ret; + ClipperLib::ClipperOffset clipper(miter_limit, 10.0); + addPaths(clipper, join_type, ClipperLib::etClosedLine); + clipper.MiterLimit = miter_limit; + clipper.Execute(ret, static_cast(distance)); + return Shape { std::move(ret) }; } template<> @@ -174,21 +160,18 @@ Shape LinesSet::offset(coord_t distance, ClipperLib::JoinType join_type { if (empty()) { - return Shape(); - } - else if (distance == 0) - { - return Shape(getLines()); + return {}; } - else + if (distance == 0) { - ClipperLib::Paths ret; - ClipperLib::ClipperOffset clipper(miter_limit, 10.0); - Shape(getLines()).unionPolygons().addPaths(clipper, join_type, ClipperLib::etClosedPolygon); - clipper.MiterLimit = miter_limit; - clipper.Execute(ret, static_cast(distance)); - return Shape(std::move(ret)); + return { getLines() }; } + ClipperLib::Paths ret; + ClipperLib::ClipperOffset clipper(miter_limit, 10.0); + Shape(getLines()).unionPolygons().addPaths(clipper, join_type, ClipperLib::etClosedPolygon); + clipper.MiterLimit = miter_limit; + clipper.Execute(ret, static_cast(distance)); + return Shape{ std::move(ret) }; } template<> @@ -196,32 +179,17 @@ Shape OpenLinesSet::offset(coord_t distance, ClipperLib::JoinType join_type, dou { if (empty() || distance == 0) { - return Shape(); + return {}; } - else - { - Shape result; - ClipperLib::ClipperOffset clipper(miter_limit, 10.0); - ClipperLib::EndType end_type; - if (join_type == ClipperLib::jtMiter) - { - end_type = ClipperLib::etOpenSquare; - } - else - { - end_type = ClipperLib::etOpenRound; - } - - addPaths(clipper, join_type, end_type); - - clipper.MiterLimit = miter_limit; - ClipperLib::Paths result_paths; - clipper.Execute(result_paths, static_cast(distance)); - result = Shape(std::move(result_paths)); + ClipperLib::ClipperOffset clipper(miter_limit, 10.0); + const ClipperLib::EndType end_type{ join_type == ClipperLib::jtMiter ? ClipperLib::etOpenSquare : ClipperLib::etOpenRound }; + addPaths(clipper, join_type, end_type); + clipper.MiterLimit = miter_limit; + ClipperLib::Paths result_paths; + clipper.Execute(result_paths, static_cast(distance)); - return result; - } + return Shape{ std::move(result_paths) }; } template @@ -233,7 +201,7 @@ void LinesSet::removeDegenerateVerts() const bool for_polyline = (dynamic_cast(&poly) != nullptr); ClipperLib::Path result; - auto isDegenerate = [](const Point2LL& last, const Point2LL& now, const Point2LL& next) + auto is_degenerate = [](const Point2LL& last, const Point2LL& now, const Point2LL& next) { Point2LL last_line = now - last; Point2LL next_line = next - now; @@ -248,7 +216,7 @@ void LinesSet::removeDegenerateVerts() result.push_back(poly[i]); // Add everything before the start vertex. } - bool isChanged = false; + bool is_changed = false; for (size_t idx = start_vertex; idx < end_vertex; idx++) { const Point2LL& last = (result.size() == 0) ? poly.back() : result.back(); @@ -257,11 +225,11 @@ void LinesSet::removeDegenerateVerts() break; } const Point2LL& next = (idx + 1 >= poly.size()) ? result[0] : poly[idx + 1]; - if (isDegenerate(last, poly[idx], next)) + if (is_degenerate(last, poly[idx], next)) { // lines are in the opposite direction // don't add vert to the result - isChanged = true; - while (result.size() > 1 && isDegenerate(result[result.size() - 2], result.back(), next)) + is_changed = true; + while (result.size() > 1 && is_degenerate(result[result.size() - 2], result.back(), next)) { result.pop_back(); } @@ -277,7 +245,7 @@ void LinesSet::removeDegenerateVerts() result.push_back(poly[i]); // Add everything after the end vertex. } - if (isChanged) + if (is_changed) { if (for_polyline || result.size() > 2) { @@ -293,7 +261,7 @@ void LinesSet::removeDegenerateVerts() } template -void LinesSet::addPaths(ClipperLib::Clipper& clipper, ClipperLib::PolyType PolyTyp) const +void LinesSet::addPaths(ClipperLib::Clipper& clipper, ClipperLib::PolyType poly_typ) const { for (const LineType& line : getLines()) { @@ -301,21 +269,21 @@ void LinesSet::addPaths(ClipperLib::Clipper& clipper, ClipperLib::Poly // true for actual filled polygons. Closed polylines are to be treated as lines here. if constexpr (std::is_same::value) { - clipper.AddPath(line.getPoints(), PolyTyp, true); + clipper.AddPath(line.getPoints(), poly_typ, true); } else { - clipper.AddPath(line.getPoints(), PolyTyp, false); + clipper.AddPath(line.getPoints(), poly_typ, false); } } } template -void LinesSet::addPaths(ClipperLib::ClipperOffset& clipper, ClipperLib::JoinType jointType, ClipperLib::EndType endType) const +void LinesSet::addPaths(ClipperLib::ClipperOffset& clipper, ClipperLib::JoinType joint_type, ClipperLib::EndType endType) const { for (const LineType& line : getLines()) { - clipper.AddPath(line.getPoints(), jointType, endType); + clipper.AddPath(line.getPoints(), joint_type, endType); } } diff --git a/src/geometry/Shape.cpp b/src/geometry/Shape.cpp index 270047cbdc..54440b2b80 100644 --- a/src/geometry/Shape.cpp +++ b/src/geometry/Shape.cpp @@ -3,6 +3,8 @@ #include "geometry/Shape.h" +#include +#include #include #include #include @@ -59,18 +61,6 @@ void Shape::emplace_back(ClipperLib::Path&& path, bool explicitely_closed) static_cast*>(this)->emplace_back(std::move(path), explicitely_closed); } -Shape& Shape::operator=(const Shape& other) -{ - LinesSet::operator=(other); - return *this; -} - -Shape& Shape::operator=(Shape&& other) -{ - LinesSet::operator=(std::move(other)); - return *this; -} - Shape Shape::approxConvexHull(int extra_outset) const { constexpr int overshoot = MM2INT(100); // 10cm (hard-coded value). @@ -141,53 +131,47 @@ void Shape::makeConvex() std::reverse(points.begin(), points.end()); make_sorted_poly_convex(points); - setLines({ std::move(convexified) }); + setLines({ convexified }); } Shape Shape::difference(const Shape& other) const { if (empty()) { - return Shape(); - } - else if (other.empty()) - { - return Shape(*this); + return {}; } - else + if (other.empty()) { - ClipperLib::Paths ret; - ClipperLib::Clipper clipper(clipper_init); - addPaths(clipper, ClipperLib::ptSubject); - other.addPaths(clipper, ClipperLib::ptClip); - clipper.Execute(ClipperLib::ctDifference, ret); - return Shape(std::move(ret)); + return *this; } + ClipperLib::Paths ret; + ClipperLib::Clipper clipper(clipper_init); + addPaths(clipper, ClipperLib::ptSubject); + other.addPaths(clipper, ClipperLib::ptClip); + clipper.Execute(ClipperLib::ctDifference, ret); + return Shape(std::move(ret)); } Shape Shape::unionPolygons(const Shape& other, ClipperLib::PolyFillType fill_type) const { if (empty() && other.empty()) { - return Shape(); + return {}; } - else if (empty() && other.size() <= 1) + if (empty() && other.size() <= 1) { return other; } - else if (other.empty() && size() <= 1) + if (other.empty() && size() <= 1) { return *this; } - else - { - ClipperLib::Paths ret; - ClipperLib::Clipper clipper(clipper_init); - addPaths(clipper, ClipperLib::ptSubject); - other.addPaths(clipper, ClipperLib::ptSubject); - clipper.Execute(ClipperLib::ctUnion, ret, fill_type, fill_type); - return Shape(std::move(ret)); - } + ClipperLib::Paths ret; + ClipperLib::Clipper clipper(clipper_init); + addPaths(clipper, ClipperLib::ptSubject); + other.addPaths(clipper, ClipperLib::ptSubject); + clipper.Execute(ClipperLib::ctUnion, ret, fill_type, fill_type); + return Shape{ std::move(ret) }; } Shape Shape::unionPolygons() const @@ -199,38 +183,33 @@ Shape Shape::intersection(const Shape& other) const { if (empty() || other.empty()) { - return Shape(); - } - else - { - ClipperLib::Paths ret; - ClipperLib::Clipper clipper(clipper_init); - addPaths(clipper, ClipperLib::ptSubject); - other.addPaths(clipper, ClipperLib::ptClip); - clipper.Execute(ClipperLib::ctIntersection, ret); - return Shape(std::move(ret)); + return {}; } + ClipperLib::Paths ret; + ClipperLib::Clipper clipper(clipper_init); + addPaths(clipper, ClipperLib::ptSubject); + other.addPaths(clipper, ClipperLib::ptClip); + clipper.Execute(ClipperLib::ctIntersection, ret); + return Shape{ std::move(ret) }; } Shape Shape::offset(coord_t distance, ClipperLib::JoinType join_type, double miter_limit) const { if (empty()) { - return Shape(); + return {}; } - else if (distance == 0) + if (distance == 0) { return *this; } - else - { - ClipperLib::Paths ret; - ClipperLib::ClipperOffset clipper(miter_limit, 10.0); - unionPolygons().addPaths(clipper, join_type, ClipperLib::etClosedPolygon); - clipper.MiterLimit = miter_limit; - clipper.Execute(ret, static_cast(distance)); - return Shape(std::move(ret)); - } + + ClipperLib::Paths ret; + ClipperLib::ClipperOffset clipper(miter_limit, 10.0); + unionPolygons().addPaths(clipper, join_type, ClipperLib::etClosedPolygon); + clipper.MiterLimit = miter_limit; + clipper.Execute(ret, static_cast(distance)); + return Shape{ std::move(ret) }; } bool Shape::inside(const Point2LL& p, bool border_result) const @@ -250,9 +229,9 @@ bool Shape::inside(const Point2LL& p, bool border_result) const size_t Shape::findInside(const Point2LL& p, bool border_result) const { - if (size() < 1) + if (empty()) { - return false; + return 0; } // NOTE: Keep these vectors fixed-size, they replace an (non-standard, sized at runtime) arrays. @@ -278,10 +257,7 @@ size_t Shape::findInside(const Point2LL& p, bool border_result) const { x = p0.X + (p1.X - p0.X) * (p.Y - p0.Y) / (p1.Y - p0.Y); } - if (x < min_x[poly_idx]) - { - min_x[poly_idx] = x; - } + min_x[poly_idx] = std::min(x, min_x[poly_idx]); } else if (border_result && comp == 0) { @@ -318,7 +294,7 @@ OpenLinesSet Shape::intersection(const LinesSet& polylines, bool resti { if (empty() || polylines.empty()) { - return OpenLinesSet(); + return {}; } OpenLinesSet split_polylines = polylines.splitIntoSegments(); @@ -365,19 +341,16 @@ Shape Shape::xorPolygons(const Shape& other, ClipperLib::PolyFillType pft) const { return other; } - else if (other.empty()) + if (other.empty()) { return *this; } - else - { - ClipperLib::Paths ret; - ClipperLib::Clipper clipper(clipper_init); - addPaths(clipper, ClipperLib::ptSubject); - other.addPaths(clipper, ClipperLib::ptClip); - clipper.Execute(ClipperLib::ctXor, ret, pft); - return Shape(std::move(ret)); - } + ClipperLib::Paths ret; + ClipperLib::Clipper clipper(clipper_init); + addPaths(clipper, ClipperLib::ptSubject); + other.addPaths(clipper, ClipperLib::ptClip); + clipper.Execute(ClipperLib::ctXor, ret, pft); + return Shape{ std::move(ret) }; } Shape Shape::execute(ClipperLib::PolyFillType pft) const @@ -386,7 +359,7 @@ Shape Shape::execute(ClipperLib::PolyFillType pft) const ClipperLib::Clipper clipper(clipper_init); addPaths(clipper, ClipperLib::ptSubject); clipper.Execute(ClipperLib::ctXor, ret, pft); - return Shape(std::move(ret)); + return Shape{ std::move(ret) }; } Shape Shape::offsetMulti(const std::vector& offset_dists) const @@ -441,9 +414,9 @@ Shape Shape::getOutsidePolygons() const { if (empty()) { - return Shape(); + return {}; } - else if (size() == 1) + if (size() == 1) { return *this; } @@ -462,7 +435,7 @@ Shape Shape::getOutsidePolygons() const return ret; } -void Shape::removeEmptyHoles_processPolyTreeNode(const ClipperLib::PolyNode& node, const bool remove_holes, Shape& ret) const +void Shape::removeEmptyHolesProcessPolyTreeNode(const ClipperLib::PolyNode& node, const bool remove_holes, Shape& ret) const { for (size_t outer_poly_idx = 0; outer_poly_idx < static_cast(node.ChildCount()); outer_poly_idx++) { @@ -477,7 +450,7 @@ void Shape::removeEmptyHoles_processPolyTreeNode(const ClipperLib::PolyNode& nod if ((hole_node.ChildCount() > 0) == remove_holes) { ret.emplace_back(std::move(hole_node.Contour)); - removeEmptyHoles_processPolyTreeNode(hole_node, remove_holes, ret); + removeEmptyHolesProcessPolyTreeNode(hole_node, remove_holes, ret); } } } @@ -516,15 +489,9 @@ void Shape::removeSmallAreas(const double min_area_size, const bool remove_holes std::swap(*new_end, *it); continue; } - else - { // Don't self-swap the last Path - break; - } - } - else - { - small_holes.push_back(&(*it)); + break; } + small_holes.push_back(&(*it)); } it++; // Skipped on removal such that the polygon just swaped in is checked next } @@ -554,34 +521,37 @@ Shape Shape::removePolygon(const Shape& to_be_removed, int same_distance) const { const Polygon& poly_keep = (*this)[poly_keep_idx]; bool should_be_removed = false; - if (poly_keep.size() > 0) - // for (int hole_poly_idx = 0; hole_poly_idx < to_be_removed.size(); hole_poly_idx++) + if (! poly_keep.empty()) + { for (const Polygon& poly_rem : to_be_removed) { - // PolygonRef poly_rem = to_be_removed[hole_poly_idx]; - if (poly_rem.size() != poly_keep.size() || poly_rem.size() == 0) + if (poly_rem.size() != poly_keep.size() || poly_rem.empty()) + { continue; + } // find closest point, supposing this point aligns the two shapes in the best way size_t closest_point_idx = 0; - coord_t smallestDist2 = -1; + coord_t smallest_dist2 = -1; for (size_t point_rem_idx = 0; point_rem_idx < poly_rem.size(); point_rem_idx++) { coord_t dist2 = vSize2(poly_rem[point_rem_idx] - poly_keep[0]); - if (dist2 < smallestDist2 || smallestDist2 < 0) + if (dist2 < smallest_dist2 || smallest_dist2 < 0) { - smallestDist2 = dist2; + smallest_dist2 = dist2; closest_point_idx = point_rem_idx; } } bool poly_rem_is_poly_keep = true; // compare the two polygons on all points - if (smallestDist2 > same_distance * same_distance) + if (smallest_dist2 > static_cast(same_distance * same_distance)) + { continue; + } for (size_t point_idx = 0; point_idx < poly_rem.size(); point_idx++) { coord_t dist2 = vSize2(poly_rem[(closest_point_idx + point_idx) % poly_rem.size()] - poly_keep[point_idx]); - if (dist2 > same_distance * same_distance) + if (dist2 > static_cast(same_distance * same_distance)) { poly_rem_is_poly_keep = false; break; @@ -593,8 +563,11 @@ Shape Shape::removePolygon(const Shape& to_be_removed, int same_distance) const break; } } + } if (! should_be_removed) + { result.push_back(poly_keep); + } } return result; } @@ -605,10 +578,10 @@ Shape Shape::processEvenOdd(ClipperLib::PolyFillType poly_fill_type) const ClipperLib::Clipper clipper(clipper_init); addPaths(clipper, ClipperLib::ptSubject); clipper.Execute(ClipperLib::ctUnion, ret, poly_fill_type); - return Shape(std::move(ret)); + return Shape{ std::move(ret) }; } -Shape Shape::smooth_outward(const AngleDegrees max_angle, int shortcut_length) const +Shape Shape::smoothOutward(const AngleDegrees max_angle, int shortcut_length) const { Shape ret; for (const Polygon& poly : (*this)) @@ -660,7 +633,7 @@ Shape Shape::smooth2(int remove_length, int min_area) const Shape ret; for (const Polygon& poly : (*this)) { - if (poly.size() == 0) + if (poly.empty()) { continue; } @@ -708,22 +681,26 @@ double Shape::area() const }); } -std::vector Shape::splitIntoParts(bool unionAll) const +std::vector Shape::splitIntoParts(bool union_all) const { std::vector ret; ClipperLib::Clipper clipper(clipper_init); - ClipperLib::PolyTree resultPolyTree; + ClipperLib::PolyTree result_poly_tree; addPaths(clipper, ClipperLib::ptSubject); - if (unionAll) - clipper.Execute(ClipperLib::ctUnion, resultPolyTree, ClipperLib::pftNonZero, ClipperLib::pftNonZero); + if (union_all) + { + clipper.Execute(ClipperLib::ctUnion, result_poly_tree, ClipperLib::pftNonZero, ClipperLib::pftNonZero); + } else - clipper.Execute(ClipperLib::ctUnion, resultPolyTree); + { + clipper.Execute(ClipperLib::ctUnion, result_poly_tree); + } - splitIntoParts_processPolyTreeNode(&resultPolyTree, ret); + splitIntoPartsProcessPolyTreeNode(&result_poly_tree, ret); return ret; } -void Shape::splitIntoParts_processPolyTreeNode(ClipperLib::PolyNode* node, std::vector& ret) const +void Shape::splitIntoPartsProcessPolyTreeNode(ClipperLib::PolyNode* node, std::vector& ret) const { for (size_t n = 0; n < static_cast(node->ChildCount()); n++) { @@ -733,7 +710,7 @@ void Shape::splitIntoParts_processPolyTreeNode(ClipperLib::PolyNode* node, std:: for (size_t i = 0; i < static_cast(child->ChildCount()); i++) { part.emplace_back(std::move(child->Childs[i]->Contour)); - splitIntoParts_processPolyTreeNode(child->Childs[i], ret); + splitIntoPartsProcessPolyTreeNode(child->Childs[i], ret); } ret.push_back(std::move(part)); } @@ -743,15 +720,15 @@ std::vector Shape::sortByNesting() const { std::vector ret; ClipperLib::Clipper clipper(clipper_init); - ClipperLib::PolyTree resultPolyTree; + ClipperLib::PolyTree result_poly_tree; addPaths(clipper, ClipperLib::ptSubject); - clipper.Execute(ClipperLib::ctUnion, resultPolyTree); + clipper.Execute(ClipperLib::ctUnion, result_poly_tree); - sortByNesting_processPolyTreeNode(&resultPolyTree, 0, ret); + sortByNestingProcessPolyTreeNode(&result_poly_tree, 0, ret); return ret; } -void Shape::sortByNesting_processPolyTreeNode(ClipperLib::PolyNode* node, const size_t nesting_idx, std::vector& ret) const +void Shape::sortByNestingProcessPolyTreeNode(ClipperLib::PolyNode* node, const size_t nesting_idx, std::vector& ret) const { for (size_t n = 0; n < static_cast(node->ChildCount()); n++) { @@ -761,29 +738,33 @@ void Shape::sortByNesting_processPolyTreeNode(ClipperLib::PolyNode* node, const ret.resize(nesting_idx + 1); } ret[nesting_idx].emplace_back(std::move(child->Contour)); - sortByNesting_processPolyTreeNode(child, nesting_idx + 1, ret); + sortByNestingProcessPolyTreeNode(child, nesting_idx + 1, ret); } } -PartsView Shape::splitIntoPartsView(bool unionAll) +PartsView Shape::splitIntoPartsView(bool union_all) { Shape reordered; - PartsView partsView(*this); + PartsView parts_view(*this); ClipperLib::Clipper clipper(clipper_init); - ClipperLib::PolyTree resultPolyTree; + ClipperLib::PolyTree result_poly_tree; addPaths(clipper, ClipperLib::ptSubject); - if (unionAll) - clipper.Execute(ClipperLib::ctUnion, resultPolyTree, ClipperLib::pftNonZero, ClipperLib::pftNonZero); + if (union_all) + { + clipper.Execute(ClipperLib::ctUnion, result_poly_tree, ClipperLib::pftNonZero, ClipperLib::pftNonZero); + } else - clipper.Execute(ClipperLib::ctUnion, resultPolyTree); + { + clipper.Execute(ClipperLib::ctUnion, result_poly_tree); + } - splitIntoPartsView_processPolyTreeNode(partsView, reordered, &resultPolyTree); + splitIntoPartsViewProcessPolyTreeNode(parts_view, reordered, &result_poly_tree); (*this) = std::move(reordered); - return partsView; + return parts_view; } -void Shape::splitIntoPartsView_processPolyTreeNode(PartsView& partsView, Shape& reordered, ClipperLib::PolyNode* node) const +void Shape::splitIntoPartsViewProcessPolyTreeNode(PartsView& partsView, Shape& reordered, ClipperLib::PolyNode* node) const { for (size_t n = 0; n < static_cast(node->ChildCount()); n++) { @@ -796,7 +777,7 @@ void Shape::splitIntoPartsView_processPolyTreeNode(PartsView& partsView, Shape& { partsView[pos].push_back(reordered.size()); reordered.emplace_back(std::move(child->Childs[i]->Contour)); - splitIntoPartsView_processPolyTreeNode(partsView, reordered, child->Childs[i]); + splitIntoPartsViewProcessPolyTreeNode(partsView, reordered, child->Childs[i]); } } } diff --git a/src/infill.cpp b/src/infill.cpp index 705489ee18..a2d931d262 100644 --- a/src/infill.cpp +++ b/src/infill.cpp @@ -136,7 +136,7 @@ void Infill::generate( small_infill.push_back(small_infill_part); } } - inner_contour_.unionPolygons(); + inner_contour_ = inner_contour_.unionPolygons(); // Fill narrow area with walls. const size_t narrow_wall_count = small_area_width_ / infill_line_width_ + 1; diff --git a/src/sliceDataStorage.cpp b/src/sliceDataStorage.cpp index d346d6df35..2447ce356f 100644 --- a/src/sliceDataStorage.cpp +++ b/src/sliceDataStorage.cpp @@ -658,7 +658,7 @@ Shape SliceDataStorage::getMachineBorder(int checking_extruder_nr) const disallowed_all_extruders = disallowed_all_extruders.unionPolygons(extruder_border); } } - disallowed_all_extruders.processEvenOdd(ClipperLib::pftNonZero); // prevent overlapping disallowed areas from XORing + disallowed_all_extruders = disallowed_all_extruders.processEvenOdd(ClipperLib::pftNonZero); // prevent overlapping disallowed areas from XORing Shape border_all_extruders = border; // each extruders border areas must be limited to the global border, which is the union of all extruders borders if (mesh_group_settings.has("nozzle_offsetting_for_disallowed_areas") && mesh_group_settings.get("nozzle_offsetting_for_disallowed_areas"))