Skip to content

Commit

Permalink
CURA-12265 the wiping movement goes in the wrong direction (#2170)
Browse files Browse the repository at this point in the history
  • Loading branch information
HellAholic authored Nov 11, 2024
2 parents 44bb1b7 + f94839a commit f32cb0f
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 72 deletions.
18 changes: 16 additions & 2 deletions include/LayerPlan.h
Original file line number Diff line number Diff line change
Expand Up @@ -881,9 +881,10 @@ class LayerPlan : public NoCopy
* \param compute_distance_to_bridge_start Whether we should compute the distance to start of bridge. This is
* possible only if PathType is ExtrusionLine and will be ignored otherwise.
* \param func_add_segment The function to be called to actually add an extrusion segment with the given parameters
* \return The index of the last traversed point, and the final position with the scarf seam
*/
template<class PathType>
void addSplitWall(
std::tuple<size_t, Point2LL> addSplitWall(
const PathAdapter<PathType>& wall,
const coord_t wall_length,
const size_t start_idx,
Expand Down Expand Up @@ -926,9 +927,10 @@ class LayerPlan : public NoCopy
* \param scarf_seam Indicates whether we may use a scarf seam for the path
* \param smooth_speed Indicates whether we may use a speed gradient for the path
* \param func_add_segment The function to be called to actually add an extrusion segment with the given parameters
* \return The index of the last traversed point, and the final position with the scarf seam
*/
template<class PathType>
void addWallWithScarfSeam(
std::tuple<size_t, Point2LL> addWallWithScarfSeam(
const PathAdapter<PathType>& wall,
size_t start_idx,
const Settings& settings,
Expand All @@ -942,6 +944,18 @@ class LayerPlan : public NoCopy
const bool smooth_speed,
const AddExtrusionSegmentFunction& func_add_segment);

/*!
* \brief Add a wipe travel after the given path has been extruded
* \tparam PathType The type of path to be processed, either ExtrusionLine or some subclass of Polyline
* \param path The path that has just been extruded
* \param wipe_distance The length of the wipe move to be added
* \param backwards Indicates if the path has been processed backwards
* \param start_index The index of the point where o start printing the path
* \param last_path_position The actual last position of the extruder, which may be slightly forwards on the last printed segment
*/
template<class PathType>
void addWipeTravel(const PathAdapter<PathType>& path, const coord_t wipe_distance, const bool backwards, const size_t start_index, const Point2LL& last_path_position);

/*!
* Pre-calculates the coasting to be applied on the paths
*
Expand Down
146 changes: 76 additions & 70 deletions src/LayerPlan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,45 @@ void LayerPlan::addExtrusionMove(
last_planned_position_ = p.toPoint2LL();
}

template<class PathType>
void LayerPlan::addWipeTravel(const PathAdapter<PathType>& path, const coord_t wipe_distance, const bool backwards, const size_t start_index, const Point2LL& last_path_position)
{
if (path.size() >= 2 && wipe_distance > 0)
{
const int direction = backwards ? -1 : 1;
Point2LL p0 = last_path_position;
int distance_traversed = 0;
size_t index = start_index;
while (distance_traversed < wipe_distance)
{
index = static_cast<size_t>((index + direction + path.size()) % path.size());
if (index == start_index && distance_traversed == 0)
{
// Wall has a total circumference of 0. This loop would never end.
break;
}

const Point2LL& p1 = path.pointAt(index);
const int p0p1_dist = vSize(p1 - p0);
if (distance_traversed + p0p1_dist >= wipe_distance)
{
Point2LL vector = p1 - p0;
Point2LL half_way = p0 + normal(vector, wipe_distance - distance_traversed);
addTravel_simple(half_way);
}
else
{
addTravel_simple(p1);
}

distance_traversed += p0p1_dist;
p0 = p1;
}

forceNewPathStart();
}
}

void LayerPlan::addPolygon(
const Polygon& polygon,
int start_idx,
Expand All @@ -572,12 +611,13 @@ void LayerPlan::addPolygon(
{
constexpr bool is_closed = true;
constexpr bool is_candidate_small_feature = false;
const PathAdapter path_adapter(polygon, config.getLineWidth());

Point2LL p0 = polygon[start_idx];
addTravel(p0, always_retract, config.z_offset);

addWallWithScarfSeam(
PathAdapter(polygon, config.getLineWidth()),
const std::tuple<size_t, Point2LL> add_wall_result = addWallWithScarfSeam(
path_adapter,
start_idx,
settings,
config,
Expand Down Expand Up @@ -605,31 +645,7 @@ void LayerPlan::addPolygon(

if (polygon.size() > 2)
{
if (wall_0_wipe_dist > 0)
{ // apply outer wall wipe
p0 = polygon[start_idx];
const int direction = backwards ? -1 : 1;
int distance_traversed = 0;
for (size_t point_idx = 1;; point_idx++)
{
Point2LL p1 = polygon[(start_idx + point_idx * direction + polygon.size()) % polygon.size()];
int p0p1_dist = vSize(p1 - p0);
if (distance_traversed + p0p1_dist >= wall_0_wipe_dist)
{
Point2LL vector = p1 - p0;
Point2LL half_way = p0 + normal(vector, wall_0_wipe_dist - distance_traversed);
addTravel_simple(half_way);
break;
}
else
{
addTravel_simple(p1);
distance_traversed += p0p1_dist;
}
p0 = p1;
}
forceNewPathStart();
}
addWipeTravel(path_adapter, wall_0_wipe_dist, backwards, get<0>(add_wall_result), get<1>(add_wall_result));
}
else
{
Expand Down Expand Up @@ -1042,7 +1058,7 @@ void LayerPlan::addWall(
}

template<class PathType>
void LayerPlan::addSplitWall(
std::tuple<size_t, Point2LL> LayerPlan::addSplitWall(
const PathAdapter<PathType>& wall,
const coord_t wall_length,
const size_t start_idx,
Expand Down Expand Up @@ -1086,10 +1102,14 @@ void LayerPlan::addSplitWall(
double accelerate_factor_origin = 0.0; // Interpolation factor at the current point for the acceleration
double decelerate_factor_origin = 0.0; // Interpolation factor at the current point for the deceleration
const coord_t start_decelerate_position = wall_length - decelerate_length;
Point3LL split_destination = p0;
size_t previous_point_index = start_idx;
bool keep_processing = true;

for (size_t point_idx = 1; point_idx < max_index; point_idx++)
for (size_t point_idx = 1; point_idx < max_index && keep_processing; point_idx++)
{
const size_t actual_point_index = (wall.size() + start_idx + point_idx * direction) % wall.size();
previous_point_index = (wall.size() + start_idx + (point_idx - 1) * direction) % wall.size();
const Point2LL& p1 = wall.pointAt(actual_point_index);
const coord_t w1 = wall.lineWidthAt(actual_point_index);
coord_t segment_processed_distance = 0;
Expand Down Expand Up @@ -1140,7 +1160,7 @@ void LayerPlan::addSplitWall(
const size_t pieces = std::max(size_t(1), std::min(pieces_limit_deviation, pieces_limit_resolution)); // Resolution overrides deviation, if resolution is a constraint.
const coord_t piece_length = round_divide(line_length, pieces);

for (size_t piece = 0; piece < pieces; ++piece)
for (size_t piece = 0; piece < pieces && keep_processing; ++piece)
{
const double average_progress = (double(piece) + 0.5) / pieces; // How far along this line to sample the line width in the middle of this piece.
// Round the line_width value to overcome floating point rounding issues, otherwise we may end up with slightly different values
Expand All @@ -1158,7 +1178,7 @@ void LayerPlan::addSplitWall(
coord_t piece_remaining_distance = piece_length;

// Cut piece into smaller parts for scarf seam and acceleration/deceleration
while (piece_remaining_distance > 0 && (! is_scarf_closure || wall_processed_distance < scarf_seam_length))
while (piece_remaining_distance > 0 && keep_processing)
{
// Make a list of all the possible incoming positions where we would eventually want to stop next
// The positions are expressed in distance from wall start along the wall segments
Expand Down Expand Up @@ -1196,7 +1216,7 @@ void LayerPlan::addSplitWall(
const coord_t destination_position = *std::min_element(split_positions.begin(), split_positions.end());
const coord_t length_to_process = destination_position - wall_processed_distance;
const double destination_factor = static_cast<double>(segment_processed_distance + length_to_process) / line_length;
Point3LL split_destination = cura::lerp(p0, p1, destination_factor);
split_destination = cura::lerp(p0, p1, destination_factor);

double scarf_segment_flow_ratio = 1.0;
double scarf_factor_destination = 1.0; // Out of range, scarf is done => 1.0
Expand Down Expand Up @@ -1269,13 +1289,20 @@ void LayerPlan::addSplitWall(
scarf_factor_origin = scarf_factor_destination;
accelerate_factor_origin = accelerate_factor_destination;
decelerate_factor_origin = decelerate_factor_destination;

if (is_scarf_closure)
{
keep_processing = wall_processed_distance < scarf_seam_length;
}
}
}
}

p0 = p1;
w0 = w1;
}

return { previous_point_index, split_destination.toPoint2LL() };
}

std::vector<LayerPlan::PathCoasting>
Expand Down Expand Up @@ -1463,7 +1490,7 @@ coord_t LayerPlan::computeDistanceToBridgeStart(const ExtrusionLine& wall, const
}

template<class PathType>
void LayerPlan::addWallWithScarfSeam(
std::tuple<size_t, Point2LL> LayerPlan::addWallWithScarfSeam(
const PathAdapter<PathType>& wall,
size_t start_idx,
const Settings& settings,
Expand All @@ -1479,10 +1506,10 @@ void LayerPlan::addWallWithScarfSeam(
{
if (wall.empty())
{
return;
return { start_idx, Point2LL() };
}

const bool actual_scarf_seam = scarf_seam && is_closed;
const bool actual_scarf_seam = scarf_seam && is_closed && layer_nr_ > 0;

const coord_t min_bridge_line_len = settings.get<coord_t>("bridge_wall_min_length");

Expand All @@ -1499,7 +1526,7 @@ void LayerPlan::addWallWithScarfSeam(
const int direction = is_reversed ? -1 : 1;
const size_t max_index = is_closed ? wall.size() + 1 : wall.size();

const auto scarf_seam_length = std::min(wall_length, actual_scarf_seam ? settings.get<coord_t>("scarf_joint_seam_length") : 0);
const coord_t scarf_seam_length = std::min(wall_length, actual_scarf_seam ? settings.get<coord_t>("scarf_joint_seam_length") : 0);
const auto scarf_seam_start_ratio = actual_scarf_seam ? settings.get<Ratio>("scarf_joint_seam_start_height_ratio") : 1.0_r;
const auto scarf_split_distance = settings.get<coord_t>("scarf_split_distance");
const coord_t scarf_max_z_offset = static_cast<coord_t>(-(1.0 - scarf_seam_start_ratio) * static_cast<double>(layer_thickness_));
Expand All @@ -1516,11 +1543,11 @@ void LayerPlan::addWallWithScarfSeam(
const Velocity end_speed = top_speed * end_speed_ratio; // mm/s
const coord_t decelerate_length = (smooth_speed && end_speed_ratio < 1.0) ? MM2INT((square(top_speed) - square(end_speed)) / (2.0 * deceleration)) : 0; // µm

auto addSplitWallPass = [&](bool is_scarf_closure)
auto addSplitWallPass = [&](bool is_scarf_closure) -> std::tuple<size_t, Point2LL>
{
constexpr bool compute_distance_to_bridge_start = true;

addSplitWall(
return addSplitWall(
PathAdapter(wall),
wall_length,
start_idx,
Expand All @@ -1535,7 +1562,7 @@ void LayerPlan::addWallWithScarfSeam(
flow_ratio,
nominal_line_width,
min_bridge_line_len,
layer_nr_ > 0 ? scarf_seam_length : 0,
scarf_seam_length,
scarf_seam_start_ratio,
scarf_split_distance,
scarf_max_z_offset,
Expand All @@ -1550,13 +1577,15 @@ void LayerPlan::addWallWithScarfSeam(
};

// First pass to add the wall with the scarf beginning and acceleration
addSplitWallPass(false);
std::tuple<size_t, Point2LL> result = addSplitWallPass(false);

if (scarf_seam_length > 0)
{
// Second pass to add the scarf closure
addSplitWallPass(true);
result = addSplitWallPass(true);
}

return result;
}

void LayerPlan::addWall(
Expand All @@ -1582,9 +1611,10 @@ void LayerPlan::addWall(

double non_bridge_line_volume = max_non_bridge_line_volume; // assume extruder is fully pressurised before first non-bridge line is output
const coord_t min_bridge_line_len = settings.get<coord_t>("bridge_wall_min_length");
const PathAdapter path_adapter(wall);

addWallWithScarfSeam(
PathAdapter(wall),
const std::tuple<size_t, Point2LL> add_wall_result = addWallWithScarfSeam(
path_adapter,
start_idx,
settings,
default_config,
Expand Down Expand Up @@ -1626,33 +1656,9 @@ void LayerPlan::addWall(
computeDistanceToBridgeStart(wall, (start_idx + wall.size() - 1) % wall.size(), min_bridge_line_len);
}

if (wall_0_wipe_dist > 0 && ! is_linked_path)
{ // apply outer wall wipe
ExtrusionJunction p0 = wall[start_idx];
coord_t distance_traversed = 0;
for (unsigned int point_idx = 1;; point_idx++)
{
if (point_idx > wall.size() && distance_traversed == 0) // Wall has a total circumference of 0. This loop would never end.
{
break; // No wipe if the wall has no circumference.
}
ExtrusionJunction p1 = wall[(start_idx + point_idx) % wall.size()];
coord_t p0p1_dist = vSize(p1 - p0);
if (distance_traversed + p0p1_dist >= wall_0_wipe_dist)
{
Point2LL vector = p1.p_ - p0.p_;
Point2LL half_way = p0.p_ + normal(vector, wall_0_wipe_dist - distance_traversed);
addTravel_simple(half_way);
break;
}
else
{
addTravel_simple(p1.p_);
distance_traversed += p0p1_dist;
}
p0 = p1;
}
forceNewPathStart();
if (! is_linked_path)
{
addWipeTravel(path_adapter, wall_0_wipe_dist, is_reversed, get<0>(add_wall_result), get<1>(add_wall_result));
}
}
else
Expand Down

0 comments on commit f32cb0f

Please sign in to comment.