From 5e62a8524b9444b2b342746514cdfd044e67ab7a Mon Sep 17 00:00:00 2001 From: Saumya Jain Date: Fri, 19 Apr 2024 16:54:02 +0200 Subject: [PATCH 01/15] Add support z-seam type to inset order optimization The implementation of the order optimizer has been updated to account for the z-seam type for support. This includes adjustment of the start point calculation and Both 'InsetOrderOptimizer' and 'PathOrderOptimizer' classes have been modified to accommodate these changes. CURA-11227 --- include/InsetOrderOptimizer.h | 1 + include/PathOrderOptimizer.h | 55 +++++++++++++++++++++++++++++++-- include/settings/EnumSettings.h | 1 + src/FffGcodeWriter.cpp | 12 ++++++- src/InsetOrderOptimizer.cpp | 16 ++++++++++ src/settings/Settings.cpp | 2 ++ 6 files changed, 84 insertions(+), 3 deletions(-) diff --git a/include/InsetOrderOptimizer.h b/include/InsetOrderOptimizer.h index 7ff5300090..3a09d460f4 100644 --- a/include/InsetOrderOptimizer.h +++ b/include/InsetOrderOptimizer.h @@ -106,6 +106,7 @@ class InsetOrderOptimizer const ZSeamConfig& z_seam_config_; const std::vector& paths_; const LayerIndex layer_nr_; + std::vector mesh_paths_; std::vector> inset_polys_; // vector of vectors holding the inset polygons Polygons retraction_region_; // After printing an outer wall, move into this region so that retractions do not leave visible blobs. Calculated lazily if needed (see diff --git a/include/PathOrderOptimizer.h b/include/PathOrderOptimizer.h index df1cc07c7e..e049816620 100644 --- a/include/PathOrderOptimizer.h +++ b/include/PathOrderOptimizer.h @@ -59,6 +59,10 @@ namespace cura template class PathOrderOptimizer { +private: + std::vector mesh_paths_{}; + size_t min_size_support_zeam_ = 0; + public: using OrderablePath = PathOrdering; /*! @@ -118,6 +122,8 @@ class PathOrderOptimizer , reverse_direction_(reverse_direction) , _group_outer_walls(group_outer_walls) , order_requirements_(&order_requirements) + , mesh_paths_ {} + { } @@ -131,6 +137,12 @@ class PathOrderOptimizer paths_.emplace_back(polygon, is_closed); } + void addMeshPathsinfo(const std::vector& polylines, const size_t min_distance) + { + constexpr bool is_closed = true; + mesh_paths_ = polylines; + min_size_support_zeam_ = min_distance; + } /*! * Add a new polyline to be optimized. * \param polyline The polyline to optimize. @@ -199,7 +211,7 @@ class PathOrderOptimizer // For some Z seam types the start position can be pre-computed. // This is faster since we don't need to re-compute the start position at each step then. - precompute_start &= seam_config_.type_ == EZSeamType::RANDOM || seam_config_.type_ == EZSeamType::USER_SPECIFIED || seam_config_.type_ == EZSeamType::SHARPEST_CORNER; + precompute_start &= seam_config_.type_ == EZSeamType::SUPPORT || seam_config_.type_ == EZSeamType::RANDOM || seam_config_.type_ == EZSeamType::USER_SPECIFIED || seam_config_.type_ == EZSeamType::SHARPEST_CORNER; if (precompute_start) { for (auto& path : paths_) @@ -561,6 +573,24 @@ class PathOrderOptimizer return best_candidate->vertices_; } + bool isVertexCloseToPolygonPath(Point2LL point) + { + for( const auto& points : ranges::front(mesh_paths_)) + { + for (const auto& polygon_point : points) + { + double distance = std::sqrt(std::pow(static_cast(polygon_point.X - point.X), 2) + std::pow(static_cast(polygon_point.Y - point.Y), 2)); + + if (distance <= min_size_support_zeam_) + { + return true; + } + } + } + + return false; + } + OrderablePath* findClosestPath(Point2LL start_position, std::vector candidate_paths) { coord_t best_distance2 = std::numeric_limits::max(); @@ -604,6 +634,21 @@ class PathOrderOptimizer return best_candidate; } + + size_t pathIfzeamSupportIsCloseToModel(size_t best_pos, const OrderablePath& path) + { + if (!mesh_paths_.empty()) + { + Point2LL current_candidate = (*path.converted_)[best_pos]; + if (isVertexCloseToPolygonPath(current_candidate)) + { + best_pos = pathIfzeamSupportIsCloseToModel(best_pos+1, path); + } + } + return best_pos; + } + + /*! * Find the vertex which will be the starting point of printing a polygon or * polyline. @@ -674,7 +719,8 @@ class PathOrderOptimizer // angles > 0 are convex (right turning) double corner_shift; - if (seam_config_.type_ == EZSeamType::SHORTEST) + + if ((seam_config_.type_ == EZSeamType::SHORTEST) || (seam_config_.type_ == EZSeamType::SUPPORT)) { // the more a corner satisfies our criteria, the closer it appears to be // shift 10mm for a very acute corner @@ -740,6 +786,11 @@ class PathOrderOptimizer } } + if (seam_config_.type_ == EZSeamType::SUPPORT) + { + best_i = pathIfzeamSupportIsCloseToModel(best_i, path); + + } return best_i; } diff --git a/include/settings/EnumSettings.h b/include/settings/EnumSettings.h index 18bd091569..367b27d223 100644 --- a/include/settings/EnumSettings.h +++ b/include/settings/EnumSettings.h @@ -70,6 +70,7 @@ enum class EZSeamType SHORTEST, USER_SPECIFIED, SHARPEST_CORNER, + SUPPORT, /* The 'Skirt/brim' type behaves like shortest, except it doesn't try to do tie-breaking for similar locations to * the last attempt, as that gives a different result when the seams are next to each other instead of on top. diff --git a/src/FffGcodeWriter.cpp b/src/FffGcodeWriter.cpp index 040b7d8376..982c9dd7aa 100644 --- a/src/FffGcodeWriter.cpp +++ b/src/FffGcodeWriter.cpp @@ -33,6 +33,7 @@ #include "utils/Simplify.h" //Removing micro-segments created by offsetting. #include "utils/ThreadPool.h" #include "utils/linearAlg2D.h" +#include "utils/polygonUtils.h" #include "utils/math.h" #include "utils/orderOptimizer.h" @@ -3451,7 +3452,16 @@ bool FffGcodeWriter::processSupportInfill(const SliceDataStorage& storage, Layer const GCodePathConfig& config = configs[0]; constexpr bool retract_before_outer_wall = false; constexpr coord_t wipe_dist = 0; - const ZSeamConfig z_seam_config(EZSeamType::SHORTEST, gcode_layer.getLastPlannedPositionOrStartingPosition(), EZSeamCornerPrefType::Z_SEAM_CORNER_PREF_NONE, false); + ZSeamConfig z_seam_config; + Point2LL start_pos; + + start_pos = gcode_layer.getLastPlannedPositionOrStartingPosition(); + z_seam_config = ZSeamConfig(EZSeamType::SUPPORT, + start_pos, + EZSeamCornerPrefType::Z_SEAM_CORNER_PREF_NONE, + false); + + InsetOrderOptimizer wall_orderer( *this, storage, diff --git a/src/InsetOrderOptimizer.cpp b/src/InsetOrderOptimizer.cpp index 82d4199d01..7b732d31c0 100644 --- a/src/InsetOrderOptimizer.cpp +++ b/src/InsetOrderOptimizer.cpp @@ -70,6 +70,7 @@ InsetOrderOptimizer::InsetOrderOptimizer( , z_seam_config_(z_seam_config) , paths_(paths) , layer_nr_(gcode_layer.getLayerNr()) + , mesh_paths_{} { } @@ -112,6 +113,21 @@ bool InsetOrderOptimizer::addToLayer() order_optimizer.addPolyline(&line); } } + if (z_seam_config_.type_== EZSeamType::SUPPORT) + { + for (std::shared_ptr mesh_ptr : storage_.meshes) + { + auto& mesh = *mesh_ptr; + for (auto &part : mesh.layers[layer_nr_].parts) + { + mesh_paths_.push_back(part.print_outline.paths); + } + } + if (!mesh_paths_.empty()) + { + order_optimizer.addMeshPathsinfo(mesh_paths_,settings_.get("support_z_seam_min_distance")); + } + } order_optimizer.optimize(); diff --git a/src/settings/Settings.cpp b/src/settings/Settings.cpp index d946ec4496..9724281593 100644 --- a/src/settings/Settings.cpp +++ b/src/settings/Settings.cpp @@ -513,6 +513,8 @@ EZSeamType Settings::get(const std::string& key) const return EZSeamType::SHARPEST_CORNER; case "plugin"_sw: return EZSeamType::PLUGIN; + case "support"_sw: + return EZSeamType::SUPPORT; default: return EZSeamType::SHORTEST; } From 8c6d99eb821f6194cf17150b657cbe5c5ea8ad7f Mon Sep 17 00:00:00 2001 From: saumyaj3 Date: Fri, 19 Apr 2024 14:55:53 +0000 Subject: [PATCH 02/15] Applied clang-format. --- include/PathOrderOptimizer.h | 12 ++++++------ src/FffGcodeWriter.cpp | 7 ++----- src/InsetOrderOptimizer.cpp | 8 ++++---- 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/include/PathOrderOptimizer.h b/include/PathOrderOptimizer.h index e049816620..684128a5f9 100644 --- a/include/PathOrderOptimizer.h +++ b/include/PathOrderOptimizer.h @@ -122,7 +122,7 @@ class PathOrderOptimizer , reverse_direction_(reverse_direction) , _group_outer_walls(group_outer_walls) , order_requirements_(&order_requirements) - , mesh_paths_ {} + , mesh_paths_{} { } @@ -211,7 +211,8 @@ class PathOrderOptimizer // For some Z seam types the start position can be pre-computed. // This is faster since we don't need to re-compute the start position at each step then. - precompute_start &= seam_config_.type_ == EZSeamType::SUPPORT || seam_config_.type_ == EZSeamType::RANDOM || seam_config_.type_ == EZSeamType::USER_SPECIFIED || seam_config_.type_ == EZSeamType::SHARPEST_CORNER; + precompute_start &= seam_config_.type_ == EZSeamType::SUPPORT || seam_config_.type_ == EZSeamType::RANDOM || seam_config_.type_ == EZSeamType::USER_SPECIFIED + || seam_config_.type_ == EZSeamType::SHARPEST_CORNER; if (precompute_start) { for (auto& path : paths_) @@ -575,7 +576,7 @@ class PathOrderOptimizer bool isVertexCloseToPolygonPath(Point2LL point) { - for( const auto& points : ranges::front(mesh_paths_)) + for (const auto& points : ranges::front(mesh_paths_)) { for (const auto& polygon_point : points) { @@ -637,12 +638,12 @@ class PathOrderOptimizer size_t pathIfzeamSupportIsCloseToModel(size_t best_pos, const OrderablePath& path) { - if (!mesh_paths_.empty()) + if (! mesh_paths_.empty()) { Point2LL current_candidate = (*path.converted_)[best_pos]; if (isVertexCloseToPolygonPath(current_candidate)) { - best_pos = pathIfzeamSupportIsCloseToModel(best_pos+1, path); + best_pos = pathIfzeamSupportIsCloseToModel(best_pos + 1, path); } } return best_pos; @@ -789,7 +790,6 @@ class PathOrderOptimizer if (seam_config_.type_ == EZSeamType::SUPPORT) { best_i = pathIfzeamSupportIsCloseToModel(best_i, path); - } return best_i; } diff --git a/src/FffGcodeWriter.cpp b/src/FffGcodeWriter.cpp index 982c9dd7aa..da17d2c13c 100644 --- a/src/FffGcodeWriter.cpp +++ b/src/FffGcodeWriter.cpp @@ -33,9 +33,9 @@ #include "utils/Simplify.h" //Removing micro-segments created by offsetting. #include "utils/ThreadPool.h" #include "utils/linearAlg2D.h" -#include "utils/polygonUtils.h" #include "utils/math.h" #include "utils/orderOptimizer.h" +#include "utils/polygonUtils.h" namespace cura { @@ -3456,10 +3456,7 @@ bool FffGcodeWriter::processSupportInfill(const SliceDataStorage& storage, Layer Point2LL start_pos; start_pos = gcode_layer.getLastPlannedPositionOrStartingPosition(); - z_seam_config = ZSeamConfig(EZSeamType::SUPPORT, - start_pos, - EZSeamCornerPrefType::Z_SEAM_CORNER_PREF_NONE, - false); + z_seam_config = ZSeamConfig(EZSeamType::SUPPORT, start_pos, EZSeamCornerPrefType::Z_SEAM_CORNER_PREF_NONE, false); InsetOrderOptimizer wall_orderer( diff --git a/src/InsetOrderOptimizer.cpp b/src/InsetOrderOptimizer.cpp index 7b732d31c0..409900584d 100644 --- a/src/InsetOrderOptimizer.cpp +++ b/src/InsetOrderOptimizer.cpp @@ -113,19 +113,19 @@ bool InsetOrderOptimizer::addToLayer() order_optimizer.addPolyline(&line); } } - if (z_seam_config_.type_== EZSeamType::SUPPORT) + if (z_seam_config_.type_ == EZSeamType::SUPPORT) { for (std::shared_ptr mesh_ptr : storage_.meshes) { auto& mesh = *mesh_ptr; - for (auto &part : mesh.layers[layer_nr_].parts) + for (auto& part : mesh.layers[layer_nr_].parts) { mesh_paths_.push_back(part.print_outline.paths); } } - if (!mesh_paths_.empty()) + if (! mesh_paths_.empty()) { - order_optimizer.addMeshPathsinfo(mesh_paths_,settings_.get("support_z_seam_min_distance")); + order_optimizer.addMeshPathsinfo(mesh_paths_, settings_.get("support_z_seam_min_distance")); } } From 9d35904f20a05f20b2bf977681d7eda3f82b1b14 Mon Sep 17 00:00:00 2001 From: Saumya Jain Date: Tue, 23 Apr 2024 13:48:59 +0200 Subject: [PATCH 03/15] Update z-seam handling and improve path optimization This update tweaks handling of the z-seam by allowing it to shift away from the model based on specific settings. It also introduces better path optimization, by calculating the shortest distance from a point to a line segment, optimizing how the best position is retrieved if such support exists and dealing with edge cases where no optimal starting path is found. CURA-11227 --- include/PathOrderOptimizer.h | 61 ++++++++++++++++++++++++++++++------ src/FffGcodeWriter.cpp | 15 ++++++--- 2 files changed, 63 insertions(+), 13 deletions(-) diff --git a/include/PathOrderOptimizer.h b/include/PathOrderOptimizer.h index 684128a5f9..a8d6cec840 100644 --- a/include/PathOrderOptimizer.h +++ b/include/PathOrderOptimizer.h @@ -211,7 +211,7 @@ class PathOrderOptimizer // For some Z seam types the start position can be pre-computed. // This is faster since we don't need to re-compute the start position at each step then. - precompute_start &= seam_config_.type_ == EZSeamType::SUPPORT || seam_config_.type_ == EZSeamType::RANDOM || seam_config_.type_ == EZSeamType::USER_SPECIFIED + precompute_start &= seam_config_.type_ == EZSeamType::RANDOM || seam_config_.type_ == EZSeamType::USER_SPECIFIED || seam_config_.type_ == EZSeamType::SHARPEST_CORNER; if (precompute_start) { @@ -578,17 +578,46 @@ class PathOrderOptimizer { for (const auto& points : ranges::front(mesh_paths_)) { - for (const auto& polygon_point : points) + const int len = points.size(); + + for (int i = 0; i < len; ++i) { - double distance = std::sqrt(std::pow(static_cast(polygon_point.X - point.X), 2) + std::pow(static_cast(polygon_point.Y - point.Y), 2)); + const auto& polygon_point1 = points[i]; + const auto& polygon_point2 = points[(i + 1) % len]; // Ensures looping back to the first point to create the final segment + + // Definitions + double x = static_cast(point.X); + double y = static_cast(point.Y); + double x1 = static_cast(polygon_point1.X); + double y1 = static_cast(polygon_point1.Y); + double x2 = static_cast(polygon_point2.X); + double y2 = static_cast(polygon_point2.Y); + + // Calculate the shortest distance from the point to the line segment + double dx = x2 - x1; + double dy = y2 - y1; + + // Calculate the t parameter + double t = ((x - x1) * dx + (y - y1) * dy) / (dx * dx + dy * dy); + + // If t is outside bounds [0,1], point is closest to an endpoint of the segment + t = std::max(0.0, std::min(1.0, t)); + + // Compute the coordinates of the point on the line segment nearest to the external point + double nearestX = x1 + t * dx; + double nearestY = y1 + t * dy; + + // Calculate squared distance from external point to its nearest point on the line segment + double dx_nearest = x - nearestX; + double dy_nearest = y - nearestY; + double squared_distance = dx_nearest*dx_nearest + dy_nearest*dy_nearest; - if (distance <= min_size_support_zeam_) + if (squared_distance <= min_size_support_zeam_ * min_size_support_zeam_) { return true; } } } - return false; } @@ -638,14 +667,28 @@ class PathOrderOptimizer size_t pathIfzeamSupportIsCloseToModel(size_t best_pos, const OrderablePath& path) { - if (! mesh_paths_.empty()) + static size_t number_of_paths_analysed = 0; + size_t path_size = path.converted_->size(); + if (path_size > number_of_paths_analysed) { - Point2LL current_candidate = (*path.converted_)[best_pos]; - if (isVertexCloseToPolygonPath(current_candidate)) + if (! mesh_paths_.empty()) { - best_pos = pathIfzeamSupportIsCloseToModel(best_pos + 1, path); + Point2LL current_candidate = (path.converted_)->at(best_pos); + if (isVertexCloseToPolygonPath(current_candidate)) + { + size_t next_best_position = (path_size > best_pos + 1) ? best_pos + 1 : 0; + best_pos = pathIfzeamSupportIsCloseToModel(next_best_position, path); + number_of_paths_analysed +=1; + } } } + else + { + number_of_paths_analysed = 0; + spdlog::warn("no start path found for support z seam distance"); + // We can also calculate the best point to start at this point. + // This usually happens when the distance of support seam from model is bigger than the whole support wall points. + } return best_pos; } diff --git a/src/FffGcodeWriter.cpp b/src/FffGcodeWriter.cpp index da17d2c13c..b34b284c25 100644 --- a/src/FffGcodeWriter.cpp +++ b/src/FffGcodeWriter.cpp @@ -33,9 +33,9 @@ #include "utils/Simplify.h" //Removing micro-segments created by offsetting. #include "utils/ThreadPool.h" #include "utils/linearAlg2D.h" +#include "utils/polygonUtils.h" #include "utils/math.h" #include "utils/orderOptimizer.h" -#include "utils/polygonUtils.h" namespace cura { @@ -3452,11 +3452,18 @@ bool FffGcodeWriter::processSupportInfill(const SliceDataStorage& storage, Layer const GCodePathConfig& config = configs[0]; constexpr bool retract_before_outer_wall = false; constexpr coord_t wipe_dist = 0; + EZSeamType z_seam_type = EZSeamType::SHORTEST; ZSeamConfig z_seam_config; - Point2LL start_pos; + Point2LL start_pos = gcode_layer.getLastPlannedPositionOrStartingPosition(); + if (infill_extruder.settings_.get("support_z_seam_away_from_model")) + { + z_seam_type = EZSeamType::SUPPORT; + } - start_pos = gcode_layer.getLastPlannedPositionOrStartingPosition(); - z_seam_config = ZSeamConfig(EZSeamType::SUPPORT, start_pos, EZSeamCornerPrefType::Z_SEAM_CORNER_PREF_NONE, false); + z_seam_config = ZSeamConfig(z_seam_type, + start_pos, + EZSeamCornerPrefType::Z_SEAM_CORNER_PREF_NONE, + false); InsetOrderOptimizer wall_orderer( From 17d5828bb844ab2144c46866d3e82172efdf4c84 Mon Sep 17 00:00:00 2001 From: saumyaj3 Date: Tue, 23 Apr 2024 11:49:32 +0000 Subject: [PATCH 04/15] Applied clang-format. --- include/PathOrderOptimizer.h | 7 +++---- src/FffGcodeWriter.cpp | 7 ++----- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/include/PathOrderOptimizer.h b/include/PathOrderOptimizer.h index a8d6cec840..2163561cdb 100644 --- a/include/PathOrderOptimizer.h +++ b/include/PathOrderOptimizer.h @@ -211,8 +211,7 @@ class PathOrderOptimizer // For some Z seam types the start position can be pre-computed. // This is faster since we don't need to re-compute the start position at each step then. - precompute_start &= seam_config_.type_ == EZSeamType::RANDOM || seam_config_.type_ == EZSeamType::USER_SPECIFIED - || seam_config_.type_ == EZSeamType::SHARPEST_CORNER; + precompute_start &= seam_config_.type_ == EZSeamType::RANDOM || seam_config_.type_ == EZSeamType::USER_SPECIFIED || seam_config_.type_ == EZSeamType::SHARPEST_CORNER; if (precompute_start) { for (auto& path : paths_) @@ -610,7 +609,7 @@ class PathOrderOptimizer // Calculate squared distance from external point to its nearest point on the line segment double dx_nearest = x - nearestX; double dy_nearest = y - nearestY; - double squared_distance = dx_nearest*dx_nearest + dy_nearest*dy_nearest; + double squared_distance = dx_nearest * dx_nearest + dy_nearest * dy_nearest; if (squared_distance <= min_size_support_zeam_ * min_size_support_zeam_) { @@ -678,7 +677,7 @@ class PathOrderOptimizer { size_t next_best_position = (path_size > best_pos + 1) ? best_pos + 1 : 0; best_pos = pathIfzeamSupportIsCloseToModel(next_best_position, path); - number_of_paths_analysed +=1; + number_of_paths_analysed += 1; } } } diff --git a/src/FffGcodeWriter.cpp b/src/FffGcodeWriter.cpp index b34b284c25..e9e4bed92d 100644 --- a/src/FffGcodeWriter.cpp +++ b/src/FffGcodeWriter.cpp @@ -33,9 +33,9 @@ #include "utils/Simplify.h" //Removing micro-segments created by offsetting. #include "utils/ThreadPool.h" #include "utils/linearAlg2D.h" -#include "utils/polygonUtils.h" #include "utils/math.h" #include "utils/orderOptimizer.h" +#include "utils/polygonUtils.h" namespace cura { @@ -3460,10 +3460,7 @@ bool FffGcodeWriter::processSupportInfill(const SliceDataStorage& storage, Layer z_seam_type = EZSeamType::SUPPORT; } - z_seam_config = ZSeamConfig(z_seam_type, - start_pos, - EZSeamCornerPrefType::Z_SEAM_CORNER_PREF_NONE, - false); + z_seam_config = ZSeamConfig(z_seam_type, start_pos, EZSeamCornerPrefType::Z_SEAM_CORNER_PREF_NONE, false); InsetOrderOptimizer wall_orderer( From 4cdd1166eb5bf4afdf6915e0ece59d7f84b393eb Mon Sep 17 00:00:00 2001 From: Saumya Jain Date: Tue, 23 Apr 2024 14:01:04 +0200 Subject: [PATCH 05/15] Refactor PathOrderOptimizer logic and adjust warnings Refactored the logic of the PathOrderOptimizer function to ensure 'number_of_paths_analysed' is increased and reset only in the suitable scenarios. Also, corrected the case of a warning message related to the 'z seam distance'. CURA-11227 --- include/PathOrderOptimizer.h | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/include/PathOrderOptimizer.h b/include/PathOrderOptimizer.h index 2163561cdb..821df2c8da 100644 --- a/include/PathOrderOptimizer.h +++ b/include/PathOrderOptimizer.h @@ -677,17 +677,22 @@ class PathOrderOptimizer { size_t next_best_position = (path_size > best_pos + 1) ? best_pos + 1 : 0; best_pos = pathIfzeamSupportIsCloseToModel(next_best_position, path); - number_of_paths_analysed += 1; + } + else + { + number_of_paths_analysed = 0; + return best_pos; } } + number_of_paths_analysed +=1; } else { - number_of_paths_analysed = 0; - spdlog::warn("no start path found for support z seam distance"); + spdlog::warn("No start path found for support z seam distance"); // We can also calculate the best point to start at this point. // This usually happens when the distance of support seam from model is bigger than the whole support wall points. } + number_of_paths_analysed = 0; return best_pos; } From 765569c96e454a6f65f87497d262476ed98c510b Mon Sep 17 00:00:00 2001 From: saumyaj3 Date: Tue, 23 Apr 2024 12:01:36 +0000 Subject: [PATCH 06/15] Applied clang-format. --- include/PathOrderOptimizer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/PathOrderOptimizer.h b/include/PathOrderOptimizer.h index 821df2c8da..4f9bf9d173 100644 --- a/include/PathOrderOptimizer.h +++ b/include/PathOrderOptimizer.h @@ -684,7 +684,7 @@ class PathOrderOptimizer return best_pos; } } - number_of_paths_analysed +=1; + number_of_paths_analysed += 1; } else { From d89c4d6271beb35c494632bf3457ae2438f0b9ba Mon Sep 17 00:00:00 2001 From: Saumya Jain Date: Tue, 23 Apr 2024 14:56:57 +0200 Subject: [PATCH 07/15] Added documentation CURA-11227 --- include/PathOrderOptimizer.h | 49 ++++++++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/include/PathOrderOptimizer.h b/include/PathOrderOptimizer.h index 4f9bf9d173..f25e3a1a96 100644 --- a/include/PathOrderOptimizer.h +++ b/include/PathOrderOptimizer.h @@ -573,6 +573,21 @@ class PathOrderOptimizer return best_candidate->vertices_; } + /** + * @brief Checks if the given vertex is close to any polygon path defined by the front of the mesh_paths_. + * + * The function iteratively checks the shortest distance from the point to each line segment in the polygon. + * A line segment is defined by each pair of consecutive points in the polygon. + * If the shortest distance is less than or equal to min_size_support_zeam_, the function returns true. + * This implies that the vertex is considered "close" to the polygon path. + * The check is performed against all polygons in the front of the mesh_paths_. + * + * @param point Vertex of interest, provided as a 2D point in the LongLong (LL) coordinate space. + * @return Returns true if the vertex is close to any line segment in the polygon path, false otherwise. + * + * @note The closeness is judged based on the minimum Zeam support size. + * @note The distance check is performed on the squared distance to avoid costly square root operations. + */ bool isVertexCloseToPolygonPath(Point2LL point) { for (const auto& points : ranges::front(mesh_paths_)) @@ -663,10 +678,28 @@ class PathOrderOptimizer return best_candidate; } + /** + * @brief Analyze the positions in a path and determine the next optimal position based on a proximity criterion. + * + * This function iteratively examines positions along the given path, checking if the position is close to 3D model. + * Each position is specified by an index, starting with `best_pos`. If the position is close to the model according to + * `isVertexCloseToPolygonPath` function, the function recursively calls itself with the next position. This process is + * repeated until all positions have been checked or `number_of_paths_analysed` becomes equal to `path_size`. + * If `number_of_paths_analysed` becomes equal to `path_size`, it logs a warning and returns the current best position. + * + * @param best_pos The index of the initial position for analysis in the path. + * @param path An OrderablePath instance containing the path to be examined. + * @param number_of_paths_analysed Optionally, the initial index of paths analysed. Defaults to 0. + * @return The index of the next optimal position in the path sequence. May be the same as the input `best_pos`, + * or may be incremented to a different location based on the proximity criterion. + * + * @note This function uses recursion to evaluate each position in the path. + * @note The process stops prematurely if no start path is found for the support z seam distance. + * This typically happens when the distance of the support seam from the model is bigger than all the support wall points. + */ - size_t pathIfzeamSupportIsCloseToModel(size_t best_pos, const OrderablePath& path) + size_t pathIfzeamSupportIsCloseToModel(size_t best_pos, const OrderablePath& path, size_t number_of_paths_analysed) { - static size_t number_of_paths_analysed = 0; size_t path_size = path.converted_->size(); if (path_size > number_of_paths_analysed) { @@ -676,15 +709,10 @@ class PathOrderOptimizer if (isVertexCloseToPolygonPath(current_candidate)) { size_t next_best_position = (path_size > best_pos + 1) ? best_pos + 1 : 0; - best_pos = pathIfzeamSupportIsCloseToModel(next_best_position, path); - } - else - { - number_of_paths_analysed = 0; - return best_pos; + number_of_paths_analysed += 1; + best_pos = pathIfzeamSupportIsCloseToModel(next_best_position, path, number_of_paths_analysed); } } - number_of_paths_analysed += 1; } else { @@ -692,7 +720,6 @@ class PathOrderOptimizer // We can also calculate the best point to start at this point. // This usually happens when the distance of support seam from model is bigger than the whole support wall points. } - number_of_paths_analysed = 0; return best_pos; } @@ -836,7 +863,7 @@ class PathOrderOptimizer if (seam_config_.type_ == EZSeamType::SUPPORT) { - best_i = pathIfzeamSupportIsCloseToModel(best_i, path); + best_i = pathIfzeamSupportIsCloseToModel(best_i, path, 0); } return best_i; } From 70e33aa13c2d81b109b6bee8a4d898f4d1659724 Mon Sep 17 00:00:00 2001 From: Saumya Jain Date: Wed, 1 May 2024 11:31:01 +0200 Subject: [PATCH 08/15] Removed SUPPORT type z seam and added isInDisallowedArea func. The code changes revolve around the functionality of the InsetOrderOptimizer and related path optimizers. These changes allow for better handling of support meshes by allowing the optimizer to consider if a layer part is supported or not. Furthermore, the type of paths used in path optimization was switched from 'ClipperLib::Paths' to 'Polygons' providing better performance and cleaner code. Also, the conditions for EZSeamType::SUPPORT in the seam configuration were removed. CURA-11227 --- include/InsetOrderOptimizer.h | 4 +- include/PathOrderOptimizer.h | 76 ++++++++--------------------------- src/FffGcodeWriter.cpp | 12 +----- src/InsetOrderOptimizer.cpp | 6 +-- src/settings/Settings.cpp | 2 - 5 files changed, 23 insertions(+), 77 deletions(-) diff --git a/include/InsetOrderOptimizer.h b/include/InsetOrderOptimizer.h index 3a09d460f4..8d3d9f3afa 100644 --- a/include/InsetOrderOptimizer.h +++ b/include/InsetOrderOptimizer.h @@ -64,7 +64,7 @@ class InsetOrderOptimizer * class, so this optimize function needs no additional information. * \return Whether anything was added to the layer plan. */ - bool addToLayer(); + bool addToLayer(const bool is_support = false); /*! * Get the order constraints of the insets when printing walls per region / hole. @@ -106,7 +106,7 @@ class InsetOrderOptimizer const ZSeamConfig& z_seam_config_; const std::vector& paths_; const LayerIndex layer_nr_; - std::vector mesh_paths_; + std::vector mesh_paths_; std::vector> inset_polys_; // vector of vectors holding the inset polygons Polygons retraction_region_; // After printing an outer wall, move into this region so that retractions do not leave visible blobs. Calculated lazily if needed (see diff --git a/include/PathOrderOptimizer.h b/include/PathOrderOptimizer.h index f25e3a1a96..22a986c19f 100644 --- a/include/PathOrderOptimizer.h +++ b/include/PathOrderOptimizer.h @@ -60,7 +60,7 @@ template class PathOrderOptimizer { private: - std::vector mesh_paths_{}; + std::vector mesh_paths_{}; size_t min_size_support_zeam_ = 0; public: @@ -137,11 +137,15 @@ class PathOrderOptimizer paths_.emplace_back(polygon, is_closed); } - void addMeshPathsinfo(const std::vector& polylines, const size_t min_distance) + void addMeshPathsinfo(const std::vector& mesh_polygons, const size_t min_distance) { constexpr bool is_closed = true; - mesh_paths_ = polylines; min_size_support_zeam_ = min_distance; + //offset polygon with th min_size_support z seam + for (auto& polygons :mesh_polygons) + { + mesh_paths_.push_back(polygons.offset(min_size_support_zeam_, ClipperLib::jtRound)); + } } /*! * Add a new polyline to be optimized. @@ -573,63 +577,15 @@ class PathOrderOptimizer return best_candidate->vertices_; } - /** - * @brief Checks if the given vertex is close to any polygon path defined by the front of the mesh_paths_. - * - * The function iteratively checks the shortest distance from the point to each line segment in the polygon. - * A line segment is defined by each pair of consecutive points in the polygon. - * If the shortest distance is less than or equal to min_size_support_zeam_, the function returns true. - * This implies that the vertex is considered "close" to the polygon path. - * The check is performed against all polygons in the front of the mesh_paths_. - * - * @param point Vertex of interest, provided as a 2D point in the LongLong (LL) coordinate space. - * @return Returns true if the vertex is close to any line segment in the polygon path, false otherwise. - * - * @note The closeness is judged based on the minimum Zeam support size. - * @note The distance check is performed on the squared distance to avoid costly square root operations. - */ - bool isVertexCloseToPolygonPath(Point2LL point) + + bool isInDisallowedPaths(Point2LL point, std::vector& paths) { - for (const auto& points : ranges::front(mesh_paths_)) - { - const int len = points.size(); - for (int i = 0; i < len; ++i) + for (const auto& polygons : paths) + { + if (polygons.inside(point, true)) { - const auto& polygon_point1 = points[i]; - const auto& polygon_point2 = points[(i + 1) % len]; // Ensures looping back to the first point to create the final segment - - // Definitions - double x = static_cast(point.X); - double y = static_cast(point.Y); - double x1 = static_cast(polygon_point1.X); - double y1 = static_cast(polygon_point1.Y); - double x2 = static_cast(polygon_point2.X); - double y2 = static_cast(polygon_point2.Y); - - // Calculate the shortest distance from the point to the line segment - double dx = x2 - x1; - double dy = y2 - y1; - - // Calculate the t parameter - double t = ((x - x1) * dx + (y - y1) * dy) / (dx * dx + dy * dy); - - // If t is outside bounds [0,1], point is closest to an endpoint of the segment - t = std::max(0.0, std::min(1.0, t)); - - // Compute the coordinates of the point on the line segment nearest to the external point - double nearestX = x1 + t * dx; - double nearestY = y1 + t * dy; - - // Calculate squared distance from external point to its nearest point on the line segment - double dx_nearest = x - nearestX; - double dy_nearest = y - nearestY; - double squared_distance = dx_nearest * dx_nearest + dy_nearest * dy_nearest; - - if (squared_distance <= min_size_support_zeam_ * min_size_support_zeam_) - { - return true; - } + return true; } } return false; @@ -706,7 +662,7 @@ class PathOrderOptimizer if (! mesh_paths_.empty()) { Point2LL current_candidate = (path.converted_)->at(best_pos); - if (isVertexCloseToPolygonPath(current_candidate)) + if (isInDisallowedPaths(current_candidate, mesh_paths_)) { size_t next_best_position = (path_size > best_pos + 1) ? best_pos + 1 : 0; number_of_paths_analysed += 1; @@ -795,7 +751,7 @@ class PathOrderOptimizer double corner_shift; - if ((seam_config_.type_ == EZSeamType::SHORTEST) || (seam_config_.type_ == EZSeamType::SUPPORT)) + if (seam_config_.type_ == EZSeamType::SHORTEST) { // the more a corner satisfies our criteria, the closer it appears to be // shift 10mm for a very acute corner @@ -861,7 +817,7 @@ class PathOrderOptimizer } } - if (seam_config_.type_ == EZSeamType::SUPPORT) + if (min_size_support_zeam_ != 0) { best_i = pathIfzeamSupportIsCloseToModel(best_i, path, 0); } diff --git a/src/FffGcodeWriter.cpp b/src/FffGcodeWriter.cpp index c9a858d8e4..524ecbc8e4 100644 --- a/src/FffGcodeWriter.cpp +++ b/src/FffGcodeWriter.cpp @@ -3457,15 +3457,7 @@ bool FffGcodeWriter::processSupportInfill(const SliceDataStorage& storage, Layer const GCodePathConfig& config = configs[0]; constexpr bool retract_before_outer_wall = false; constexpr coord_t wipe_dist = 0; - EZSeamType z_seam_type = EZSeamType::SHORTEST; - ZSeamConfig z_seam_config; - Point2LL start_pos = gcode_layer.getLastPlannedPositionOrStartingPosition(); - if (infill_extruder.settings_.get("support_z_seam_away_from_model")) - { - z_seam_type = EZSeamType::SUPPORT; - } - - z_seam_config = ZSeamConfig(z_seam_type, start_pos, EZSeamCornerPrefType::Z_SEAM_CORNER_PREF_NONE, false); + ZSeamConfig z_seam_config = ZSeamConfig(EZSeamType::SHORTEST, gcode_layer.getLastPlannedPositionOrStartingPosition(), EZSeamCornerPrefType::Z_SEAM_CORNER_PREF_NONE, false); InsetOrderOptimizer wall_orderer( @@ -3487,7 +3479,7 @@ bool FffGcodeWriter::processSupportInfill(const SliceDataStorage& storage, Layer extruder_nr, z_seam_config, wall_toolpaths); - added_something |= wall_orderer.addToLayer(); + added_something |= wall_orderer.addToLayer(true); } if ((default_support_line_distance <= 0 && support_structure != ESupportStructure::TREE) || part.infill_area_per_combine_per_density_.empty()) diff --git a/src/InsetOrderOptimizer.cpp b/src/InsetOrderOptimizer.cpp index 409900584d..94edd2bcd8 100644 --- a/src/InsetOrderOptimizer.cpp +++ b/src/InsetOrderOptimizer.cpp @@ -74,7 +74,7 @@ InsetOrderOptimizer::InsetOrderOptimizer( { } -bool InsetOrderOptimizer::addToLayer() +bool InsetOrderOptimizer::addToLayer(const bool is_support) { // Settings & configs: const auto pack_by_inset = ! settings_.get("optimize_wall_printing_order"); @@ -113,14 +113,14 @@ bool InsetOrderOptimizer::addToLayer() order_optimizer.addPolyline(&line); } } - if (z_seam_config_.type_ == EZSeamType::SUPPORT) + if (is_support && settings_.get("support_z_seam_away_from_model")) { for (std::shared_ptr mesh_ptr : storage_.meshes) { auto& mesh = *mesh_ptr; for (auto& part : mesh.layers[layer_nr_].parts) { - mesh_paths_.push_back(part.print_outline.paths); + mesh_paths_.push_back(part.print_outline); } } if (! mesh_paths_.empty()) diff --git a/src/settings/Settings.cpp b/src/settings/Settings.cpp index 9724281593..d946ec4496 100644 --- a/src/settings/Settings.cpp +++ b/src/settings/Settings.cpp @@ -513,8 +513,6 @@ EZSeamType Settings::get(const std::string& key) const return EZSeamType::SHARPEST_CORNER; case "plugin"_sw: return EZSeamType::PLUGIN; - case "support"_sw: - return EZSeamType::SUPPORT; default: return EZSeamType::SHORTEST; } From 744f417ad0e37a363a3a93c92e0451c3df5fcf6f Mon Sep 17 00:00:00 2001 From: saumyaj3 Date: Wed, 1 May 2024 09:31:36 +0000 Subject: [PATCH 09/15] Applied clang-format. --- include/PathOrderOptimizer.h | 7 +++---- src/FffGcodeWriter.cpp | 3 ++- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/PathOrderOptimizer.h b/include/PathOrderOptimizer.h index 22a986c19f..07acabedf1 100644 --- a/include/PathOrderOptimizer.h +++ b/include/PathOrderOptimizer.h @@ -141,8 +141,8 @@ class PathOrderOptimizer { constexpr bool is_closed = true; min_size_support_zeam_ = min_distance; - //offset polygon with th min_size_support z seam - for (auto& polygons :mesh_polygons) + // offset polygon with th min_size_support z seam + for (auto& polygons : mesh_polygons) { mesh_paths_.push_back(polygons.offset(min_size_support_zeam_, ClipperLib::jtRound)); } @@ -580,7 +580,6 @@ class PathOrderOptimizer bool isInDisallowedPaths(Point2LL point, std::vector& paths) { - for (const auto& polygons : paths) { if (polygons.inside(point, true)) @@ -817,7 +816,7 @@ class PathOrderOptimizer } } - if (min_size_support_zeam_ != 0) + if (min_size_support_zeam_ != 0) { best_i = pathIfzeamSupportIsCloseToModel(best_i, path, 0); } diff --git a/src/FffGcodeWriter.cpp b/src/FffGcodeWriter.cpp index 524ecbc8e4..bf3c03dc96 100644 --- a/src/FffGcodeWriter.cpp +++ b/src/FffGcodeWriter.cpp @@ -3457,7 +3457,8 @@ bool FffGcodeWriter::processSupportInfill(const SliceDataStorage& storage, Layer const GCodePathConfig& config = configs[0]; constexpr bool retract_before_outer_wall = false; constexpr coord_t wipe_dist = 0; - ZSeamConfig z_seam_config = ZSeamConfig(EZSeamType::SHORTEST, gcode_layer.getLastPlannedPositionOrStartingPosition(), EZSeamCornerPrefType::Z_SEAM_CORNER_PREF_NONE, false); + ZSeamConfig z_seam_config + = ZSeamConfig(EZSeamType::SHORTEST, gcode_layer.getLastPlannedPositionOrStartingPosition(), EZSeamCornerPrefType::Z_SEAM_CORNER_PREF_NONE, false); InsetOrderOptimizer wall_orderer( From 8537117012f0800af85112921d774b680da6b1e2 Mon Sep 17 00:00:00 2001 From: Saumya Jain Date: Wed, 1 May 2024 11:39:28 +0200 Subject: [PATCH 10/15] remove z-seam support from enaum class as well CURA-11227 --- include/settings/EnumSettings.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/settings/EnumSettings.h b/include/settings/EnumSettings.h index 367b27d223..18bd091569 100644 --- a/include/settings/EnumSettings.h +++ b/include/settings/EnumSettings.h @@ -70,7 +70,6 @@ enum class EZSeamType SHORTEST, USER_SPECIFIED, SHARPEST_CORNER, - SUPPORT, /* The 'Skirt/brim' type behaves like shortest, except it doesn't try to do tie-breaking for similar locations to * the last attempt, as that gives a different result when the seams are next to each other instead of on top. From 9fc42e113f30b88543b344c1eff300fe2ec97b06 Mon Sep 17 00:00:00 2001 From: Saumya Jain Date: Thu, 2 May 2024 14:20:25 +0200 Subject: [PATCH 11/15] added disallowed area in PathOptimiser. Instead of specific case of support away from model, now it is given from Insetoptimiser as disallowed area. this can also be used for other features in future. CURA-11227 --- include/InsetOrderOptimizer.h | 2 +- include/PathOrderOptimizer.h | 43 ++++++++--------------------------- src/InsetOrderOptimizer.cpp | 5 ++-- 3 files changed, 13 insertions(+), 37 deletions(-) diff --git a/include/InsetOrderOptimizer.h b/include/InsetOrderOptimizer.h index 8d3d9f3afa..90097205ec 100644 --- a/include/InsetOrderOptimizer.h +++ b/include/InsetOrderOptimizer.h @@ -106,7 +106,7 @@ class InsetOrderOptimizer const ZSeamConfig& z_seam_config_; const std::vector& paths_; const LayerIndex layer_nr_; - std::vector mesh_paths_; + Polygons mesh_paths_; std::vector> inset_polys_; // vector of vectors holding the inset polygons Polygons retraction_region_; // After printing an outer wall, move into this region so that retractions do not leave visible blobs. Calculated lazily if needed (see diff --git a/include/PathOrderOptimizer.h b/include/PathOrderOptimizer.h index 07acabedf1..1ff01a13ee 100644 --- a/include/PathOrderOptimizer.h +++ b/include/PathOrderOptimizer.h @@ -59,12 +59,10 @@ namespace cura template class PathOrderOptimizer { -private: - std::vector mesh_paths_{}; - size_t min_size_support_zeam_ = 0; - public: using OrderablePath = PathOrdering; + /* Areas defined here are not allowed to have the start the prints */ + Polygons disallowed_area {}; /*! * After optimizing, this contains the paths that need to be printed in the * correct order. @@ -122,7 +120,7 @@ class PathOrderOptimizer , reverse_direction_(reverse_direction) , _group_outer_walls(group_outer_walls) , order_requirements_(&order_requirements) - , mesh_paths_{} + , disallowed_area{} { } @@ -137,16 +135,6 @@ class PathOrderOptimizer paths_.emplace_back(polygon, is_closed); } - void addMeshPathsinfo(const std::vector& mesh_polygons, const size_t min_distance) - { - constexpr bool is_closed = true; - min_size_support_zeam_ = min_distance; - // offset polygon with th min_size_support z seam - for (auto& polygons : mesh_polygons) - { - mesh_paths_.push_back(polygons.offset(min_size_support_zeam_, ClipperLib::jtRound)); - } - } /*! * Add a new polyline to be optimized. * \param polyline The polyline to optimize. @@ -577,19 +565,6 @@ class PathOrderOptimizer return best_candidate->vertices_; } - - bool isInDisallowedPaths(Point2LL point, std::vector& paths) - { - for (const auto& polygons : paths) - { - if (polygons.inside(point, true)) - { - return true; - } - } - return false; - } - OrderablePath* findClosestPath(Point2LL start_position, std::vector candidate_paths) { coord_t best_distance2 = std::numeric_limits::max(); @@ -653,19 +628,19 @@ class PathOrderOptimizer * This typically happens when the distance of the support seam from the model is bigger than all the support wall points. */ - size_t pathIfzeamSupportIsCloseToModel(size_t best_pos, const OrderablePath& path, size_t number_of_paths_analysed) + size_t pathIfZseamIsInDisallowedArea(size_t best_pos, const OrderablePath& path, size_t number_of_paths_analysed) { size_t path_size = path.converted_->size(); if (path_size > number_of_paths_analysed) { - if (! mesh_paths_.empty()) + if (! disallowed_area.empty()) { Point2LL current_candidate = (path.converted_)->at(best_pos); - if (isInDisallowedPaths(current_candidate, mesh_paths_)) + if (disallowed_area.inside(current_candidate, true)) { size_t next_best_position = (path_size > best_pos + 1) ? best_pos + 1 : 0; number_of_paths_analysed += 1; - best_pos = pathIfzeamSupportIsCloseToModel(next_best_position, path, number_of_paths_analysed); + best_pos = pathIfZseamIsInDisallowedArea(next_best_position, path, number_of_paths_analysed); } } } @@ -816,9 +791,9 @@ class PathOrderOptimizer } } - if (min_size_support_zeam_ != 0) + if (!disallowed_area.empty()) { - best_i = pathIfzeamSupportIsCloseToModel(best_i, path, 0); + best_i = pathIfZseamIsInDisallowedArea(best_i, path, 0); } return best_i; } diff --git a/src/InsetOrderOptimizer.cpp b/src/InsetOrderOptimizer.cpp index 94edd2bcd8..7e3eeb0ce0 100644 --- a/src/InsetOrderOptimizer.cpp +++ b/src/InsetOrderOptimizer.cpp @@ -120,12 +120,13 @@ bool InsetOrderOptimizer::addToLayer(const bool is_support) auto& mesh = *mesh_ptr; for (auto& part : mesh.layers[layer_nr_].parts) { - mesh_paths_.push_back(part.print_outline); + mesh_paths_.add(part.print_outline); } } if (! mesh_paths_.empty()) { - order_optimizer.addMeshPathsinfo(mesh_paths_, settings_.get("support_z_seam_min_distance")); + coord_t min_distance = settings_.get("support_z_seam_min_distance"); + order_optimizer.disallowed_area = mesh_paths_.offset(min_distance, ClipperLib::jtRound); } } From 6777aa0dd89d4689ff911561901201a3a627eab3 Mon Sep 17 00:00:00 2001 From: saumyaj3 Date: Thu, 2 May 2024 12:21:04 +0000 Subject: [PATCH 12/15] Applied clang-format. --- include/PathOrderOptimizer.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/PathOrderOptimizer.h b/include/PathOrderOptimizer.h index 1ff01a13ee..c8a8b05421 100644 --- a/include/PathOrderOptimizer.h +++ b/include/PathOrderOptimizer.h @@ -62,7 +62,7 @@ class PathOrderOptimizer public: using OrderablePath = PathOrdering; /* Areas defined here are not allowed to have the start the prints */ - Polygons disallowed_area {}; + Polygons disallowed_area{}; /*! * After optimizing, this contains the paths that need to be printed in the * correct order. @@ -791,7 +791,7 @@ class PathOrderOptimizer } } - if (!disallowed_area.empty()) + if (! disallowed_area.empty()) { best_i = pathIfZseamIsInDisallowedArea(best_i, path, 0); } From 7229363746bcdb311fa023a3e92df8a9613ff751 Mon Sep 17 00:00:00 2001 From: Saumya Jain Date: Thu, 2 May 2024 17:15:37 +0200 Subject: [PATCH 13/15] Refactor "support away from model" to generic "disallowed areas" The specific "support away from model" case has been refactored to a more generic "disallowed areas" in the Insetoptimizer. This adjustment enhances flexibility and allows for potential future utilization in other features. Related to CURA-11227. --- include/InsetOrderOptimizer.h | 7 ++++--- include/PathOrderOptimizer.h | 7 ++++--- src/FffGcodeWriter.cpp | 23 ++++++++++++++++++++--- src/InsetOrderOptimizer.cpp | 25 +++++-------------------- 4 files changed, 33 insertions(+), 29 deletions(-) diff --git a/include/InsetOrderOptimizer.h b/include/InsetOrderOptimizer.h index 90097205ec..47cd832fcb 100644 --- a/include/InsetOrderOptimizer.h +++ b/include/InsetOrderOptimizer.h @@ -55,7 +55,8 @@ class InsetOrderOptimizer const size_t wall_0_extruder_nr, const size_t wall_x_extruder_nr, const ZSeamConfig& z_seam_config, - const std::vector& paths); + const std::vector& paths, + const Polygons& disallowed_areas = {}); /*! * Adds the insets to the given layer plan. @@ -64,7 +65,7 @@ class InsetOrderOptimizer * class, so this optimize function needs no additional information. * \return Whether anything was added to the layer plan. */ - bool addToLayer(const bool is_support = false); + bool addToLayer(); /*! * Get the order constraints of the insets when printing walls per region / hole. @@ -106,7 +107,7 @@ class InsetOrderOptimizer const ZSeamConfig& z_seam_config_; const std::vector& paths_; const LayerIndex layer_nr_; - Polygons mesh_paths_; + Polygons disallowed_areas_; std::vector> inset_polys_; // vector of vectors holding the inset polygons Polygons retraction_region_; // After printing an outer wall, move into this region so that retractions do not leave visible blobs. Calculated lazily if needed (see diff --git a/include/PathOrderOptimizer.h b/include/PathOrderOptimizer.h index c8a8b05421..31eb58efb3 100644 --- a/include/PathOrderOptimizer.h +++ b/include/PathOrderOptimizer.h @@ -62,7 +62,7 @@ class PathOrderOptimizer public: using OrderablePath = PathOrdering; /* Areas defined here are not allowed to have the start the prints */ - Polygons disallowed_area{}; + Polygons disallowed_area; /*! * After optimizing, this contains the paths that need to be printed in the * correct order. @@ -112,7 +112,8 @@ class PathOrderOptimizer const Polygons* combing_boundary = nullptr, const bool reverse_direction = false, const std::unordered_multimap& order_requirements = no_order_requirements_, - const bool group_outer_walls = false) + const bool group_outer_walls = false, + const Polygons& disallowed_areas = {}) : start_point_(start_point) , seam_config_(seam_config) , combing_boundary_((combing_boundary != nullptr && ! combing_boundary->empty()) ? combing_boundary : nullptr) @@ -120,7 +121,7 @@ class PathOrderOptimizer , reverse_direction_(reverse_direction) , _group_outer_walls(group_outer_walls) , order_requirements_(&order_requirements) - , disallowed_area{} + , disallowed_area{disallowed_areas} { } diff --git a/src/FffGcodeWriter.cpp b/src/FffGcodeWriter.cpp index bf3c03dc96..2c1aac5858 100644 --- a/src/FffGcodeWriter.cpp +++ b/src/FffGcodeWriter.cpp @@ -3459,7 +3459,23 @@ bool FffGcodeWriter::processSupportInfill(const SliceDataStorage& storage, Layer constexpr coord_t wipe_dist = 0; ZSeamConfig z_seam_config = ZSeamConfig(EZSeamType::SHORTEST, gcode_layer.getLastPlannedPositionOrStartingPosition(), EZSeamCornerPrefType::Z_SEAM_CORNER_PREF_NONE, false); - + Polygons disallowed_area {}; + if (infill_extruder.settings_.get("support_z_seam_away_from_model")) + { + for (std::shared_ptr mesh_ptr : storage.meshes) + { + auto& mesh = *mesh_ptr; + for (auto& part : mesh.layers[gcode_layer.getLayerNr()].parts) + { + disallowed_area.add(part.print_outline); + } + } + if (! disallowed_area.empty()) + { + coord_t min_distance = infill_extruder.settings_.get("support_z_seam_min_distance"); + disallowed_area = disallowed_area.offset(min_distance, ClipperLib::jtRound); + } + } InsetOrderOptimizer wall_orderer( *this, @@ -3479,8 +3495,9 @@ bool FffGcodeWriter::processSupportInfill(const SliceDataStorage& storage, Layer extruder_nr, extruder_nr, z_seam_config, - wall_toolpaths); - added_something |= wall_orderer.addToLayer(true); + wall_toolpaths, + disallowed_area); + added_something |= wall_orderer.addToLayer(); } if ((default_support_line_distance <= 0 && support_structure != ESupportStructure::TREE) || part.infill_area_per_combine_per_density_.empty()) diff --git a/src/InsetOrderOptimizer.cpp b/src/InsetOrderOptimizer.cpp index 7e3eeb0ce0..57cfd32201 100644 --- a/src/InsetOrderOptimizer.cpp +++ b/src/InsetOrderOptimizer.cpp @@ -50,7 +50,8 @@ InsetOrderOptimizer::InsetOrderOptimizer( const size_t wall_0_extruder_nr, const size_t wall_x_extruder_nr, const ZSeamConfig& z_seam_config, - const std::vector& paths) + const std::vector& paths, + const Polygons& disallowed_areas) : gcode_writer_(gcode_writer) , storage_(storage) , gcode_layer_(gcode_layer) @@ -70,11 +71,11 @@ InsetOrderOptimizer::InsetOrderOptimizer( , z_seam_config_(z_seam_config) , paths_(paths) , layer_nr_(gcode_layer.getLayerNr()) - , mesh_paths_{} + , disallowed_areas_{disallowed_areas} { } -bool InsetOrderOptimizer::addToLayer(const bool is_support) +bool InsetOrderOptimizer::addToLayer() { // Settings & configs: const auto pack_by_inset = ! settings_.get("optimize_wall_printing_order"); @@ -100,7 +101,7 @@ bool InsetOrderOptimizer::addToLayer(const bool is_support) // When we alternate walls, also alternate the direction at which the first wall starts in. // On even layers we start with normal direction, on odd layers with inverted direction. PathOrderOptimizer - order_optimizer(gcode_layer_.getLastPlannedPositionOrStartingPosition(), z_seam_config_, detect_loops, combing_boundary, reverse, order, group_outer_walls); + order_optimizer(gcode_layer_.getLastPlannedPositionOrStartingPosition(), z_seam_config_, detect_loops, combing_boundary, reverse, order, group_outer_walls, disallowed_areas_); for (const auto& line : walls_to_be_added) { @@ -113,22 +114,6 @@ bool InsetOrderOptimizer::addToLayer(const bool is_support) order_optimizer.addPolyline(&line); } } - if (is_support && settings_.get("support_z_seam_away_from_model")) - { - for (std::shared_ptr mesh_ptr : storage_.meshes) - { - auto& mesh = *mesh_ptr; - for (auto& part : mesh.layers[layer_nr_].parts) - { - mesh_paths_.add(part.print_outline); - } - } - if (! mesh_paths_.empty()) - { - coord_t min_distance = settings_.get("support_z_seam_min_distance"); - order_optimizer.disallowed_area = mesh_paths_.offset(min_distance, ClipperLib::jtRound); - } - } order_optimizer.optimize(); From c3d155d30c2e6355c0f418f9da2eac509fdf1a08 Mon Sep 17 00:00:00 2001 From: saumyaj3 Date: Thu, 2 May 2024 15:16:14 +0000 Subject: [PATCH 14/15] Applied clang-format. --- include/PathOrderOptimizer.h | 2 +- src/FffGcodeWriter.cpp | 2 +- src/InsetOrderOptimizer.cpp | 13 ++++++++++--- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/include/PathOrderOptimizer.h b/include/PathOrderOptimizer.h index 31eb58efb3..a709e22a2d 100644 --- a/include/PathOrderOptimizer.h +++ b/include/PathOrderOptimizer.h @@ -121,7 +121,7 @@ class PathOrderOptimizer , reverse_direction_(reverse_direction) , _group_outer_walls(group_outer_walls) , order_requirements_(&order_requirements) - , disallowed_area{disallowed_areas} + , disallowed_area{ disallowed_areas } { } diff --git a/src/FffGcodeWriter.cpp b/src/FffGcodeWriter.cpp index 2c1aac5858..9063efa2f1 100644 --- a/src/FffGcodeWriter.cpp +++ b/src/FffGcodeWriter.cpp @@ -3459,7 +3459,7 @@ bool FffGcodeWriter::processSupportInfill(const SliceDataStorage& storage, Layer constexpr coord_t wipe_dist = 0; ZSeamConfig z_seam_config = ZSeamConfig(EZSeamType::SHORTEST, gcode_layer.getLastPlannedPositionOrStartingPosition(), EZSeamCornerPrefType::Z_SEAM_CORNER_PREF_NONE, false); - Polygons disallowed_area {}; + Polygons disallowed_area{}; if (infill_extruder.settings_.get("support_z_seam_away_from_model")) { for (std::shared_ptr mesh_ptr : storage.meshes) diff --git a/src/InsetOrderOptimizer.cpp b/src/InsetOrderOptimizer.cpp index 57cfd32201..81febedcfa 100644 --- a/src/InsetOrderOptimizer.cpp +++ b/src/InsetOrderOptimizer.cpp @@ -71,7 +71,7 @@ InsetOrderOptimizer::InsetOrderOptimizer( , z_seam_config_(z_seam_config) , paths_(paths) , layer_nr_(gcode_layer.getLayerNr()) - , disallowed_areas_{disallowed_areas} + , disallowed_areas_{ disallowed_areas } { } @@ -100,8 +100,15 @@ bool InsetOrderOptimizer::addToLayer() const auto group_outer_walls = settings_.get("group_outer_walls"); // When we alternate walls, also alternate the direction at which the first wall starts in. // On even layers we start with normal direction, on odd layers with inverted direction. - PathOrderOptimizer - order_optimizer(gcode_layer_.getLastPlannedPositionOrStartingPosition(), z_seam_config_, detect_loops, combing_boundary, reverse, order, group_outer_walls, disallowed_areas_); + PathOrderOptimizer order_optimizer( + gcode_layer_.getLastPlannedPositionOrStartingPosition(), + z_seam_config_, + detect_loops, + combing_boundary, + reverse, + order, + group_outer_walls, + disallowed_areas_); for (const auto& line : walls_to_be_added) { From 962a5a40bb5790117a784f8bbed3f7769ccef5e7 Mon Sep 17 00:00:00 2001 From: Saumya Jain Date: Fri, 3 May 2024 12:44:31 +0200 Subject: [PATCH 15/15] Refactor variable name to 'disallowed_areas_for_seams' Renamed the variable 'disallowed_area' to 'disallowed_areas_for_seams' in different files for more accurate representation. CURA-11227 --- include/InsetOrderOptimizer.h | 4 ++-- include/PathOrderOptimizer.h | 12 ++++++------ src/FffGcodeWriter.cpp | 10 +++++----- src/InsetOrderOptimizer.cpp | 6 +++--- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/include/InsetOrderOptimizer.h b/include/InsetOrderOptimizer.h index 47cd832fcb..f23aae04bb 100644 --- a/include/InsetOrderOptimizer.h +++ b/include/InsetOrderOptimizer.h @@ -56,7 +56,7 @@ class InsetOrderOptimizer const size_t wall_x_extruder_nr, const ZSeamConfig& z_seam_config, const std::vector& paths, - const Polygons& disallowed_areas = {}); + const Polygons& disallowed_areas_for_seams = {}); /*! * Adds the insets to the given layer plan. @@ -107,7 +107,7 @@ class InsetOrderOptimizer const ZSeamConfig& z_seam_config_; const std::vector& paths_; const LayerIndex layer_nr_; - Polygons disallowed_areas_; + Polygons disallowed_areas_for_seams_; std::vector> inset_polys_; // vector of vectors holding the inset polygons Polygons retraction_region_; // After printing an outer wall, move into this region so that retractions do not leave visible blobs. Calculated lazily if needed (see diff --git a/include/PathOrderOptimizer.h b/include/PathOrderOptimizer.h index a709e22a2d..1a8c174cc7 100644 --- a/include/PathOrderOptimizer.h +++ b/include/PathOrderOptimizer.h @@ -62,7 +62,7 @@ class PathOrderOptimizer public: using OrderablePath = PathOrdering; /* Areas defined here are not allowed to have the start the prints */ - Polygons disallowed_area; + Polygons disallowed_area_for_seams; /*! * After optimizing, this contains the paths that need to be printed in the * correct order. @@ -113,7 +113,7 @@ class PathOrderOptimizer const bool reverse_direction = false, const std::unordered_multimap& order_requirements = no_order_requirements_, const bool group_outer_walls = false, - const Polygons& disallowed_areas = {}) + const Polygons& disallowed_areas_for_seams = {}) : start_point_(start_point) , seam_config_(seam_config) , combing_boundary_((combing_boundary != nullptr && ! combing_boundary->empty()) ? combing_boundary : nullptr) @@ -121,7 +121,7 @@ class PathOrderOptimizer , reverse_direction_(reverse_direction) , _group_outer_walls(group_outer_walls) , order_requirements_(&order_requirements) - , disallowed_area{ disallowed_areas } + , disallowed_area_for_seams{ disallowed_areas_for_seams } { } @@ -634,10 +634,10 @@ class PathOrderOptimizer size_t path_size = path.converted_->size(); if (path_size > number_of_paths_analysed) { - if (! disallowed_area.empty()) + if (! disallowed_area_for_seams.empty()) { Point2LL current_candidate = (path.converted_)->at(best_pos); - if (disallowed_area.inside(current_candidate, true)) + if (disallowed_area_for_seams.inside(current_candidate, true)) { size_t next_best_position = (path_size > best_pos + 1) ? best_pos + 1 : 0; number_of_paths_analysed += 1; @@ -792,7 +792,7 @@ class PathOrderOptimizer } } - if (! disallowed_area.empty()) + if (! disallowed_area_for_seams.empty()) { best_i = pathIfZseamIsInDisallowedArea(best_i, path, 0); } diff --git a/src/FffGcodeWriter.cpp b/src/FffGcodeWriter.cpp index 9063efa2f1..bbfdaf47eb 100644 --- a/src/FffGcodeWriter.cpp +++ b/src/FffGcodeWriter.cpp @@ -3459,7 +3459,7 @@ bool FffGcodeWriter::processSupportInfill(const SliceDataStorage& storage, Layer constexpr coord_t wipe_dist = 0; ZSeamConfig z_seam_config = ZSeamConfig(EZSeamType::SHORTEST, gcode_layer.getLastPlannedPositionOrStartingPosition(), EZSeamCornerPrefType::Z_SEAM_CORNER_PREF_NONE, false); - Polygons disallowed_area{}; + Polygons disallowed_area_for_seams{}; if (infill_extruder.settings_.get("support_z_seam_away_from_model")) { for (std::shared_ptr mesh_ptr : storage.meshes) @@ -3467,13 +3467,13 @@ bool FffGcodeWriter::processSupportInfill(const SliceDataStorage& storage, Layer auto& mesh = *mesh_ptr; for (auto& part : mesh.layers[gcode_layer.getLayerNr()].parts) { - disallowed_area.add(part.print_outline); + disallowed_area_for_seams.add(part.print_outline); } } - if (! disallowed_area.empty()) + if (! disallowed_area_for_seams.empty()) { coord_t min_distance = infill_extruder.settings_.get("support_z_seam_min_distance"); - disallowed_area = disallowed_area.offset(min_distance, ClipperLib::jtRound); + disallowed_area_for_seams = disallowed_area_for_seams.offset(min_distance, ClipperLib::jtRound); } } @@ -3496,7 +3496,7 @@ bool FffGcodeWriter::processSupportInfill(const SliceDataStorage& storage, Layer extruder_nr, z_seam_config, wall_toolpaths, - disallowed_area); + disallowed_area_for_seams); added_something |= wall_orderer.addToLayer(); } diff --git a/src/InsetOrderOptimizer.cpp b/src/InsetOrderOptimizer.cpp index 81febedcfa..03ad5434cb 100644 --- a/src/InsetOrderOptimizer.cpp +++ b/src/InsetOrderOptimizer.cpp @@ -51,7 +51,7 @@ InsetOrderOptimizer::InsetOrderOptimizer( const size_t wall_x_extruder_nr, const ZSeamConfig& z_seam_config, const std::vector& paths, - const Polygons& disallowed_areas) + const Polygons& disallowed_areas_for_seams) : gcode_writer_(gcode_writer) , storage_(storage) , gcode_layer_(gcode_layer) @@ -71,7 +71,7 @@ InsetOrderOptimizer::InsetOrderOptimizer( , z_seam_config_(z_seam_config) , paths_(paths) , layer_nr_(gcode_layer.getLayerNr()) - , disallowed_areas_{ disallowed_areas } + , disallowed_areas_for_seams_{ disallowed_areas_for_seams } { } @@ -108,7 +108,7 @@ bool InsetOrderOptimizer::addToLayer() reverse, order, group_outer_walls, - disallowed_areas_); + disallowed_areas_for_seams_); for (const auto& line : walls_to_be_added) {