Skip to content

Commit

Permalink
Cura 11227 zseam support (#2067)
Browse files Browse the repository at this point in the history
  • Loading branch information
HellAholic authored May 3, 2024
2 parents fb484b8 + 962a5a4 commit fc4266a
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 7 deletions.
4 changes: 3 additions & 1 deletion include/InsetOrderOptimizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<VariableWidthLines>& paths);
const std::vector<VariableWidthLines>& paths,
const Polygons& disallowed_areas_for_seams = {});

/*!
* Adds the insets to the given layer plan.
Expand Down Expand Up @@ -106,6 +107,7 @@ class InsetOrderOptimizer
const ZSeamConfig& z_seam_config_;
const std::vector<VariableWidthLines>& paths_;
const LayerIndex layer_nr_;
Polygons disallowed_areas_for_seams_;

std::vector<std::vector<ConstPolygonPointer>> 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
Expand Down
58 changes: 57 additions & 1 deletion include/PathOrderOptimizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ class PathOrderOptimizer
{
public:
using OrderablePath = PathOrdering<Path>;
/* Areas defined here are not allowed to have the start the prints */
Polygons disallowed_area_for_seams;
/*!
* After optimizing, this contains the paths that need to be printed in the
* correct order.
Expand Down Expand Up @@ -110,14 +112,17 @@ class PathOrderOptimizer
const Polygons* combing_boundary = nullptr,
const bool reverse_direction = false,
const std::unordered_multimap<Path, Path>& order_requirements = no_order_requirements_,
const bool group_outer_walls = false)
const bool group_outer_walls = false,
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)
, detect_loops_(detect_loops)
, reverse_direction_(reverse_direction)
, _group_outer_walls(group_outer_walls)
, order_requirements_(&order_requirements)
, disallowed_area_for_seams{ disallowed_areas_for_seams }

{
}

Expand Down Expand Up @@ -604,6 +609,52 @@ 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 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 (! disallowed_area_for_seams.empty())
{
Point2LL current_candidate = (path.converted_)->at(best_pos);
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;
best_pos = pathIfZseamIsInDisallowedArea(next_best_position, path, number_of_paths_analysed);
}
}
}
else
{
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;
}


/*!
* Find the vertex which will be the starting point of printing a polygon or
* polyline.
Expand Down Expand Up @@ -674,6 +725,7 @@ class PathOrderOptimizer
// angles > 0 are convex (right turning)

double corner_shift;

if (seam_config_.type_ == EZSeamType::SHORTEST)
{
// the more a corner satisfies our criteria, the closer it appears to be
Expand Down Expand Up @@ -740,6 +792,10 @@ class PathOrderOptimizer
}
}

if (! disallowed_area_for_seams.empty())
{
best_i = pathIfZseamIsInDisallowedArea(best_i, path, 0);
}
return best_i;
}

Expand Down
25 changes: 23 additions & 2 deletions src/FffGcodeWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "utils/linearAlg2D.h"
#include "utils/math.h"
#include "utils/orderOptimizer.h"
#include "utils/polygonUtils.h"

namespace cura
{
Expand Down Expand Up @@ -3456,7 +3457,26 @@ 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
= ZSeamConfig(EZSeamType::SHORTEST, gcode_layer.getLastPlannedPositionOrStartingPosition(), EZSeamCornerPrefType::Z_SEAM_CORNER_PREF_NONE, false);
Polygons disallowed_area_for_seams{};
if (infill_extruder.settings_.get<bool>("support_z_seam_away_from_model"))
{
for (std::shared_ptr<SliceMeshStorage> mesh_ptr : storage.meshes)
{
auto& mesh = *mesh_ptr;
for (auto& part : mesh.layers[gcode_layer.getLayerNr()].parts)
{
disallowed_area_for_seams.add(part.print_outline);
}
}
if (! disallowed_area_for_seams.empty())
{
coord_t min_distance = infill_extruder.settings_.get<coord_t>("support_z_seam_min_distance");
disallowed_area_for_seams = disallowed_area_for_seams.offset(min_distance, ClipperLib::jtRound);
}
}

InsetOrderOptimizer wall_orderer(
*this,
storage,
Expand All @@ -3475,7 +3495,8 @@ bool FffGcodeWriter::processSupportInfill(const SliceDataStorage& storage, Layer
extruder_nr,
extruder_nr,
z_seam_config,
wall_toolpaths);
wall_toolpaths,
disallowed_area_for_seams);
added_something |= wall_orderer.addToLayer();
}

Expand Down
15 changes: 12 additions & 3 deletions src/InsetOrderOptimizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<VariableWidthLines>& paths)
const std::vector<VariableWidthLines>& paths,
const Polygons& disallowed_areas_for_seams)
: gcode_writer_(gcode_writer)
, storage_(storage)
, gcode_layer_(gcode_layer)
Expand All @@ -70,6 +71,7 @@ InsetOrderOptimizer::InsetOrderOptimizer(
, z_seam_config_(z_seam_config)
, paths_(paths)
, layer_nr_(gcode_layer.getLayerNr())
, disallowed_areas_for_seams_{ disallowed_areas_for_seams }
{
}

Expand Down Expand Up @@ -98,8 +100,15 @@ bool InsetOrderOptimizer::addToLayer()
const auto group_outer_walls = settings_.get<bool>("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<const ExtrusionLine*>
order_optimizer(gcode_layer_.getLastPlannedPositionOrStartingPosition(), z_seam_config_, detect_loops, combing_boundary, reverse, order, group_outer_walls);
PathOrderOptimizer<const ExtrusionLine*> order_optimizer(
gcode_layer_.getLastPlannedPositionOrStartingPosition(),
z_seam_config_,
detect_loops,
combing_boundary,
reverse,
order,
group_outer_walls,
disallowed_areas_for_seams_);

for (const auto& line : walls_to_be_added)
{
Expand Down

0 comments on commit fc4266a

Please sign in to comment.