From eced18ebf65f95b94d86554836639d8c9bd1b7d3 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Mon, 17 Jun 2024 10:09:47 +0200 Subject: [PATCH] Use the most explicit geometric types in PrimeTower --- include/PrimeTower/PrimeTower.h | 7 +-- include/geometry/ClosedPolyline.h | 9 ++-- include/utils/polygonUtils.h | 30 ++++++++----- src/PrimeTower/PrimeTower.cpp | 24 +++++------ src/PrimeTower/PrimeTowerInterleaved.cpp | 4 +- src/sliceDataStorage.cpp | 5 +-- src/utils/polygonUtils.cpp | 55 ++++++++++-------------- 7 files changed, 68 insertions(+), 66 deletions(-) diff --git a/include/PrimeTower/PrimeTower.h b/include/PrimeTower/PrimeTower.h index b294c03ee0..0c8343d48e 100644 --- a/include/PrimeTower/PrimeTower.h +++ b/include/PrimeTower/PrimeTower.h @@ -8,6 +8,7 @@ #include #include "ExtruderUse.h" +#include "geometry/ClosedLinesSet.h" #include "geometry/Polygon.h" #include "settings/EnumSettings.h" #include "settings/types/LayerIndex.h" @@ -38,7 +39,7 @@ class PrimeTower struct ExtruderToolPaths { size_t extruder_nr; - Shape toolpaths; + ClosedLinesSet toolpaths; coord_t outer_radius; coord_t inner_radius; }; @@ -179,7 +180,7 @@ class PrimeTower * \param outer_radius The radius of the starting outer circle * \return A tuple containing the newly generated toolpaths, and the inner radius of the newly generated annulus */ - std::tuple generatePrimeToolpaths(const size_t extruder_nr, const coord_t outer_radius); + std::tuple generatePrimeToolpaths(const size_t extruder_nr, const coord_t outer_radius); /*! * \brief Generate support toolpaths using the wheel pattern applied on an annulus @@ -188,7 +189,7 @@ class PrimeTower * \param inner_radius The annulis inner radius * \return */ - Shape generateSupportToolpaths(const size_t extruder_nr, const coord_t outer_radius, const coord_t inner_radius); + ClosedLinesSet generateSupportToolpaths(const size_t extruder_nr, const coord_t outer_radius, const coord_t inner_radius); /*! * \brief Calculates whether an extruder requires priming at a specific layer diff --git a/include/geometry/ClosedPolyline.h b/include/geometry/ClosedPolyline.h index 8f4bc3e753..979ed6f29c 100644 --- a/include/geometry/ClosedPolyline.h +++ b/include/geometry/ClosedPolyline.h @@ -32,14 +32,17 @@ class ClosedPolyline : public Polyline bool explicitely_closed_{ false }; public: + /*! + * \brief Builds an empty closed polyline + * \warning By default, the line is tagged as non explicitely closed. We need this default + * constructor in various places, but be careful that the interpretation of the points + * added later will depend on this. + */ ClosedPolyline() = default; /*! * \brief Builds an empty closed polyline * \param explicitely_closed Indicates whether the line will be explicitely closed - * \warning By default, the line is tagged as explicitely closed. We need this default - * constructor in various places, but be careful that the interpretation of the points - * added later will depend on this. */ explicit ClosedPolyline(const bool explicitely_closed) : explicitely_closed_{ explicitely_closed } diff --git a/include/utils/polygonUtils.h b/include/utils/polygonUtils.h index 2048580eeb..43d96a5c5d 100644 --- a/include/utils/polygonUtils.h +++ b/include/utils/polygonUtils.h @@ -13,6 +13,7 @@ #include "PolygonsPointIndex.h" #include "SparseLineGrid.h" #include "SparsePointGridInclusive.h" +#include "geometry/ClosedLinesSet.h" #include "geometry/Polygon.h" namespace cura @@ -599,15 +600,24 @@ class PolygonUtils static double relativeHammingDistance(const Shape& poly_a, const Shape& poly_b); /*! - * Create an approximation of a circle. + * Creates a regular polygon that is supposed to approximate a disc. + * + * \param mid The center of the disc. + * \param radius The radius of the disc. + * \param steps The numbers of segments (definition) of the generated disc. + * \return A new Polygon containing the disc. + */ + static Polygon makeDisc(const Point2LL& mid, const coord_t radius, const size_t steps); + + /*! + * Creates a closed polyline that is supposed to approximate a circle. * - * This creates a regular polygon that is supposed to approximate a circle. * \param mid The center of the circle. * \param radius The radius of the circle. * \param steps The numbers of segments (definition) of the generated circle. * \return A new Polygon containing the circle. */ - static Polygon makeCircle(const Point2LL& mid, const coord_t radius, const size_t steps); + static ClosedPolyline makeCircle(const Point2LL& mid, const coord_t radius, const size_t steps); /*! * Create a point of a circle. @@ -620,17 +630,16 @@ class PolygonUtils static Point2LL makeCirclePoint(const Point2LL& mid, const coord_t radius, const AngleRadians& angle); /*! - * Create a "wheel" shape. + * This creates a polyline which represents the shape of a wheel, which is kind of a "circular zigzag" pattern. * - * This creates a polygon which represents the shape of a wheel. * \param mid The center of the circle. * \param inner_radius The radius of the wheel inner circle. * \param outer_radius The radius of the wheel outer circle. * \param semi_nb_spokes The semi number of spokes in the wheel. There will actually be N*2 spokes. - * \param arc_angle_resolution The number of segment on each arc. - * \return A new Polygon containing the circle. + * \param arc_angle_resolution The number of segments on each arc. + * \return A new Polyline containing the circle. */ - static Polygon makeWheel(const Point2LL& mid, const coord_t inner_radius, const coord_t outer_radius, const size_t semi_nb_spokes, const size_t arc_angle_resolution); + static ClosedPolyline makeWheel(const Point2LL& mid, const coord_t inner_radius, const coord_t outer_radius, const size_t semi_nb_spokes, const size_t arc_angle_resolution); /*! * Connect all polygons to their holes using zero widths hole channels, so that the polygons and their outlines are connected together @@ -641,7 +650,6 @@ class PolygonUtils static Shape unionManySmall(const Shape& polygon); - /*! * Intersects a polygon with an AABB. * \param src The polygon that has to be intersected with an AABB @@ -660,7 +668,7 @@ class PolygonUtils * \param circle_definition The definition (number of segments) of the generated circles * \return The generated outset circles, and the outer radius or the shape */ - static std::tuple + static std::tuple generateCirculatOutset(const Point2LL& center, const coord_t inner_radius, const coord_t outer_radius, const coord_t line_width, const size_t circle_definition); /*! @@ -672,7 +680,7 @@ class PolygonUtils * \param circle_definition The definition (number of segments) of the generated circles * \return The generated inset circles */ - static Shape generateCircularInset(const Point2LL& center, const coord_t outer_radius, const coord_t line_width, const size_t circle_definition); + static ClosedLinesSet generateCircularInset(const Point2LL& center, const coord_t outer_radius, const coord_t line_width, const size_t circle_definition); private: /*! diff --git a/src/PrimeTower/PrimeTower.cpp b/src/PrimeTower/PrimeTower.cpp index 89da6babdc..accfeaf374 100644 --- a/src/PrimeTower/PrimeTower.cpp +++ b/src/PrimeTower/PrimeTower.cpp @@ -40,7 +40,7 @@ PrimeTower::PrimeTower() const double base_curve_magnitude = mesh_group_settings.get("prime_tower_base_curve_magnitude"); middle_ = Point2LL(x - tower_radius, y + tower_radius); - outer_poly_ = { PolygonUtils::makeCircle(middle_, tower_radius, circle_definition_), tower_radius }; + outer_poly_ = { PolygonUtils::makeDisc(middle_, tower_radius, circle_definition_), tower_radius }; post_wipe_point_ = Point2LL(x - tower_radius, y + tower_radius); // Generate the base outline @@ -53,7 +53,7 @@ PrimeTower::PrimeTower() const double brim_radius_factor = std::pow((1.0 - static_cast(z) / static_cast(base_height)), base_curve_magnitude); const coord_t extra_radius = std::llrint(static_cast(base_extra_radius) * brim_radius_factor); const coord_t total_radius = tower_radius + extra_radius; - base_occupied_outline_.emplace_back(PolygonUtils::makeCircle(middle_, total_radius, circle_definition_), total_radius); + base_occupied_outline_.emplace_back(PolygonUtils::makeDisc(middle_, total_radius, circle_definition_), total_radius); } } } @@ -83,11 +83,11 @@ void PrimeTower::generateBase() const size_t extruder_nr = first_extruder_toolpaths.extruder_nr; const coord_t line_width = scene.extruders[extruder_nr].settings_.get("prime_tower_line_width"); - std::tuple outset + std::tuple outset = PolygonUtils::generateCirculatOutset(middle_, first_extruder_toolpaths.outer_radius, base_ouline_at_this_layer.outer_radius, line_width, circle_definition_); first_extruder_toolpaths.toolpaths.push_back(std::get<0>(outset)); - base_extrusion_outline_.push_back(PolygonUtils::makeCircle(middle_, std::get<1>(outset), circle_definition_)); + base_extrusion_outline_.push_back(PolygonUtils::makeDisc(middle_, std::get<1>(outset), circle_definition_)); } } } @@ -105,13 +105,13 @@ void PrimeTower::generateFirtLayerInset() const Scene& scene = Application::getInstance().current_slice_->scene; const size_t extruder_nr = last_extruder_toolpaths.extruder_nr; const coord_t line_width = scene.extruders[extruder_nr].settings_.get("prime_tower_line_width"); - Shape pattern = PolygonUtils::generateCircularInset(middle_, last_extruder_toolpaths.inner_radius, line_width, circle_definition_); + ClosedLinesSet pattern = PolygonUtils::generateCircularInset(middle_, last_extruder_toolpaths.inner_radius, line_width, circle_definition_); last_extruder_toolpaths.toolpaths.push_back(pattern); } } } -std::tuple PrimeTower::generatePrimeToolpaths(const size_t extruder_nr, const coord_t outer_radius) +std::tuple PrimeTower::generatePrimeToolpaths(const size_t extruder_nr, const coord_t outer_radius) { const Scene& scene = Application::getInstance().current_slice_->scene; const Settings& mesh_group_settings = scene.current_mesh_group->settings; @@ -123,10 +123,10 @@ std::tuple PrimeTower::generatePrimeToolpaths(const size_t extru double current_volume = 0; coord_t current_outer_radius = outer_radius - semi_line_width; - Shape toolpaths; + ClosedLinesSet toolpaths; while (current_volume < required_volume && current_outer_radius >= semi_line_width) { - Polygon circle = PolygonUtils::makeCircle(middle_, current_outer_radius, circle_definition_); + ClosedPolyline circle = PolygonUtils::makeCircle(middle_, current_outer_radius, circle_definition_); toolpaths.push_back(circle); current_volume += static_cast(circle.length() * line_width * layer_height) * flow; current_outer_radius -= line_width; @@ -135,7 +135,7 @@ std::tuple PrimeTower::generatePrimeToolpaths(const size_t extru return { toolpaths, current_outer_radius + semi_line_width }; } -Shape PrimeTower::generateSupportToolpaths(const size_t extruder_nr, const coord_t outer_radius, const coord_t inner_radius) +ClosedLinesSet PrimeTower::generateSupportToolpaths(const size_t extruder_nr, const coord_t outer_radius, const coord_t inner_radius) { const Scene& scene = Application::getInstance().current_slice_->scene; const double max_bridging_distance = static_cast(scene.extruders[extruder_nr].settings_.get("prime_tower_max_bridging_distance")); @@ -143,7 +143,7 @@ Shape PrimeTower::generateSupportToolpaths(const size_t extruder_nr, const coord const coord_t radius_delta = outer_radius - inner_radius; const coord_t semi_line_width = line_width / 2; - Shape toolpaths; + ClosedLinesSet toolpaths; // Split annuli according to max bridging distance const coord_t nb_annuli = static_cast(std::ceil(static_cast(radius_delta) / max_bridging_distance)); @@ -205,7 +205,7 @@ void PrimeTower::addToGcode( return; } - const Shape* toolpaths = nullptr; + const ClosedLinesSet* toolpaths = nullptr; auto iterator_layer = toolpaths_.find(layer_nr); if (iterator_layer != toolpaths_.end()) { @@ -228,7 +228,7 @@ void PrimeTower::addToGcode( gotoStartLocation(gcode_layer, new_extruder_nr); const GCodePathConfig& config = gcode_layer.configs_storage_.prime_tower_config_per_extruder[new_extruder_nr]; - gcode_layer.addPolygonsByOptimizer(*toolpaths, config); + gcode_layer.addLinesByOptimizer(*toolpaths, config, SpaceFillType::PolyLines); } gcode_layer.setPrimeTowerIsPlanned(new_extruder_nr); diff --git a/src/PrimeTower/PrimeTowerInterleaved.cpp b/src/PrimeTower/PrimeTowerInterleaved.cpp index 3742c37151..5973cca4b0 100644 --- a/src/PrimeTower/PrimeTowerInterleaved.cpp +++ b/src/PrimeTower/PrimeTowerInterleaved.cpp @@ -78,11 +78,11 @@ std::map> PrimeTowerInter { if (toolpaths_at_layer.empty()) { - toolpaths_at_layer.emplace_back(last_extruder_support, Shape(), outer_radius, support_radius); + toolpaths_at_layer.emplace_back(last_extruder_support, ClosedLinesSet(), outer_radius, support_radius); } ExtruderToolPaths& last_extruder_toolpaths = toolpaths_at_layer.back(); - Shape support_toolpaths = generateSupportToolpaths(last_extruder_toolpaths.extruder_nr, outer_radius, support_radius); + ClosedLinesSet support_toolpaths = generateSupportToolpaths(last_extruder_toolpaths.extruder_nr, outer_radius, support_radius); last_extruder_toolpaths.toolpaths.push_back(support_toolpaths); last_extruder_toolpaths.inner_radius = support_radius; } diff --git a/src/sliceDataStorage.cpp b/src/sliceDataStorage.cpp index a419f75680..e5ba129b7f 100644 --- a/src/sliceDataStorage.cpp +++ b/src/sliceDataStorage.cpp @@ -638,9 +638,8 @@ Shape SliceDataStorage::getMachineBorder(int checking_extruder_nr) const } Point2LL translation(extruder_settings.get("machine_nozzle_offset_x"), extruder_settings.get("machine_nozzle_offset_y")); prime_pos -= translation; - Shape prime_polygons; - prime_polygons.emplace_back(PolygonUtils::makeCircle(prime_pos, prime_clearance, 64)); - disallowed_areas = disallowed_areas.unionPolygons(prime_polygons); + Polygon prime_polygon = PolygonUtils::makeDisc(prime_pos, prime_clearance, 64); + disallowed_areas = disallowed_areas.unionPolygons(prime_polygon); } Shape disallowed_all_extruders; diff --git a/src/utils/polygonUtils.cpp b/src/utils/polygonUtils.cpp index b7aad13923..5ca80ac87c 100644 --- a/src/utils/polygonUtils.cpp +++ b/src/utils/polygonUtils.cpp @@ -1303,16 +1303,21 @@ double PolygonUtils::relativeHammingDistance(const Shape& poly_a, const Shape& p return hamming_distance / total_area; } -Polygon PolygonUtils::makeCircle(const Point2LL& mid, const coord_t radius, const size_t steps) +Polygon PolygonUtils::makeDisc(const Point2LL& mid, const coord_t radius, const size_t steps) { - Polygon circle; + Polygon disc; const AngleRadians step_angle = (std::numbers::pi * 2) / static_cast(steps); for (size_t step = 0; step < steps; ++step) { const AngleRadians angle = static_cast(step) * step_angle; - circle.emplace_back(makeCirclePoint(mid, radius, angle)); + disc.push_back(makeCirclePoint(mid, radius, angle)); } - return circle; + return disc; +} + +ClosedPolyline PolygonUtils::makeCircle(const Point2LL& mid, const coord_t radius, const size_t steps) +{ + return makeDisc(mid, radius, steps); } Point2LL PolygonUtils::makeCirclePoint(const Point2LL& mid, const coord_t radius, const AngleRadians& angle) @@ -1320,43 +1325,29 @@ Point2LL PolygonUtils::makeCirclePoint(const Point2LL& mid, const coord_t radius return mid + Point2LL(std::llrint(static_cast(radius) * cos(angle)), std::llrint(static_cast(radius) * sin(angle))); } -Polygon PolygonUtils::makeWheel(const Point2LL& mid, const coord_t inner_radius, const coord_t outer_radius, const size_t semi_nb_spokes, const size_t arc_angle_resolution) +ClosedPolyline PolygonUtils::makeWheel(const Point2LL& mid, const coord_t inner_radius, const coord_t outer_radius, const size_t semi_nb_spokes, const size_t arc_angle_resolution) { - Polygon wheel; - - std::vector> target_radii; - target_radii.push_back({ inner_radius, outer_radius }); - target_radii.push_back({ outer_radius, inner_radius }); + ClosedPolyline wheel; const size_t nb_spokes = semi_nb_spokes * 2; - const float angle_step = TAU / nb_spokes; - const float arc_step = angle_step / arc_angle_resolution; - float angle = 0.0; + const double spoke_angle_step = TAU / static_cast(nb_spokes); + const double arc_angle_step = spoke_angle_step / static_cast(arc_angle_resolution); + for (size_t spoke = 0; spoke < nb_spokes; ++spoke) { - const std::pair& radii = target_radii.at(spoke % 2); + const double spoke_angle = static_cast(spoke) * spoke_angle_step; + const coord_t radius = spoke % 2 == 0 ? inner_radius : outer_radius; - angle = spoke * angle_step; - float cos_angle = cos(angle); - float sin_angle = sin(angle); - wheel.emplace_back(mid + Point2LL(radii.first * cos_angle, radii.first * sin_angle)); - - for (size_t arc_part = 0; arc_part < arc_angle_resolution; ++arc_part) + for (size_t arc_part = 0; arc_part <= arc_angle_resolution; ++arc_part) { - wheel.emplace_back(mid + Point2LL(radii.second * cos_angle, radii.second * sin_angle)); - if (arc_part < arc_angle_resolution - 1) - { - angle += arc_step; - cos_angle = cos(angle); - sin_angle = sin(angle); - } + const double angle = spoke_angle + static_cast(arc_part) * arc_angle_step; + wheel.push_back(makeCirclePoint(mid, radius, angle)); } } return wheel; } - Shape PolygonUtils::connect(const Shape& input) { Shape ret; @@ -1539,10 +1530,10 @@ Shape PolygonUtils::clipPolygonWithAABB(const Shape& src, const AABB& aabb) return out; } -std::tuple +std::tuple PolygonUtils::generateCirculatOutset(const Point2LL& center, const coord_t inner_radius, const coord_t outer_radius, coord_t line_width, const size_t circle_definition) { - Shape outset; + ClosedLinesSet outset; const coord_t semi_line_width = line_width / 2; coord_t radius = inner_radius + semi_line_width; @@ -1555,9 +1546,9 @@ std::tuple return { outset, radius - semi_line_width }; } -Shape PolygonUtils::generateCircularInset(const Point2LL& center, const coord_t outer_radius, const coord_t line_width, const size_t circle_definition) +ClosedLinesSet PolygonUtils::generateCircularInset(const Point2LL& center, const coord_t outer_radius, const coord_t line_width, const size_t circle_definition) { - Shape inset; + ClosedLinesSet inset; const coord_t semi_line_width = line_width / 2; coord_t radius = outer_radius - semi_line_width;