Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cura 11227 zseam support #2067

Merged
merged 16 commits into from
May 3, 2024
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 = {});

/*!
* 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_;

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;
/*!
* 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 = {})
: 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{ disallowed_areas }

{
}

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.empty())
{
Point2LL current_candidate = (path.converted_)->at(best_pos);
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 = 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.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{};
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.add(part.print_outline);
}
}
if (! disallowed_area.empty())
{
coord_t min_distance = infill_extruder.settings_.get<coord_t>("support_z_seam_min_distance");
disallowed_area = disallowed_area.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);
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)
: 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_{ disallowed_areas }
{
}

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 (const auto& line : walls_to_be_added)
{
Expand Down