Skip to content
This repository has been archived by the owner on Jun 15, 2023. It is now read-only.

Commit

Permalink
Merge branch 'master' of https://github.com/ultimaker/curaengine
Browse files Browse the repository at this point in the history
  • Loading branch information
GitHub committed Aug 14, 2021
2 parents 9527c1c + a412313 commit 99a5245
Show file tree
Hide file tree
Showing 13 changed files with 74 additions and 24 deletions.
4 changes: 2 additions & 2 deletions src/FffGcodeWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1828,7 +1828,6 @@ bool FffGcodeWriter::partitionInfillBySkinAbove(Polygons& infill_below_skin, Pol
}

// need to take skin/infill overlap that was added in SkinInfillAreaComputation::generateInfill() into account
const coord_t infill_skin_overlap = mesh.settings.get<coord_t>((part.insets.size() > 1) ? "wall_line_width_x" : "wall_line_width_0") / 2;
const Polygons infill_below_skin_overlap = infill_below_skin.offset(-tiny_infill_offset);

return ! infill_below_skin_overlap.empty() && ! infill_not_below_skin.empty();
Expand Down Expand Up @@ -2061,6 +2060,7 @@ bool FffGcodeWriter::processInsets(const SliceDataStorage& storage, LayerPlan& g
gcode_layer.setIsInside(true); // going to print stuff inside print object
ZSeamConfig z_seam_config(mesh.settings.get<EZSeamType>("z_seam_type"), mesh.getZSeamHint(), mesh.settings.get<EZSeamCornerPrefType>("z_seam_corner"));
Polygons outer_wall = part.insets[0];

if (!compensate_overlap_0)
{
WallOverlapComputation* wall_overlap_computation(nullptr);
Expand Down Expand Up @@ -2513,7 +2513,7 @@ void FffGcodeWriter::processSkinPrintFeature(const SliceDataStorage& storage, La

if(monotonic)
{
const AngleRadians monotonic_direction = AngleRadians(skin_angle + 90);
const AngleRadians monotonic_direction = AngleRadians(skin_angle);
constexpr Ratio flow = 1.0_r;
const coord_t max_adjacent_distance = config.getLineWidth() * 1.1; //Lines are considered adjacent if they are 1 line width apart, with 10% extra play. The monotonic order is enforced if they are adjacent.
if(pattern == EFillMethod::GRID || pattern == EFillMethod::LINES || pattern == EFillMethod::TRIANGLES || pattern == EFillMethod::CUBIC || pattern == EFillMethod::TETRAHEDRAL || pattern == EFillMethod::QUARTER_CUBIC || pattern == EFillMethod::CUBICSUBDIV)
Expand Down
2 changes: 1 addition & 1 deletion src/InsetOrderOptimizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ void InsetOrderOptimizer::processHoleInsets()
const unsigned outer_poly_idx = order_optimizer.polyOrder[outer_poly_order_idx];
unsigned outer_poly_start_idx = gcode_layer.locateFirstSupportedVertex(hole_outer_wall[0], order_optimizer.polyStart[outer_poly_idx]);

// detect special case where where the z-seam is located on the sharpest corner and there is only 1 hole and
// detect special case where the z-seam is located on the sharpest corner and there is only 1 hole and
// the gap between the walls is just a few line widths
if (z_seam_config.type == EZSeamType::SHARPEST_CORNER && inset_polys[0].size() == 2 && PolygonUtils::polygonOutlinesAdjacent(*inset_polys[0][1], *inset_polys[0][0], max_gap * 4))
{
Expand Down
18 changes: 15 additions & 3 deletions src/LayerPlan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,8 @@ GCodePath& LayerPlan::addTravel(const Point p, const bool force_retract)
// Multiply by 2 because if two lines start and end points places very close then will be applied combing with retractions. (Ex: for brim)
const coord_t max_distance_ignored = extruder->settings.get<coord_t>("machine_nozzle_tip_outer_diameter") / 2 * 2;

combed = comb->calc(*extruder, *last_planned_position, p, combPaths, was_inside, is_inside, max_distance_ignored);
bool unretract_before_last_travel_move = false; // Decided when calculating the combing
combed = comb->calc(*extruder, *last_planned_position, p, combPaths, was_inside, is_inside, max_distance_ignored, unretract_before_last_travel_move); //Here is the magic happening
if (combed)
{
bool retract = path->retract || (combPaths.size() > 1 && retraction_enable);
Expand Down Expand Up @@ -443,7 +444,7 @@ GCodePath& LayerPlan::addTravel(const Point p, const bool force_retract)
Point last_point((last_planned_position) ? *last_planned_position : Point(0, 0));
for (CombPath& combPath : combPaths)
{ // add all comb paths (don't do anything special for paths which are moving through air)
if (combPath.size() == 0)
if (combPath.empty())
{
continue;
}
Expand All @@ -461,6 +462,11 @@ GCodePath& LayerPlan::addTravel(const Point p, const bool force_retract)
path->retract = retract || (retract_threshold > 0 && distance > retract_threshold && retraction_enable);
// don't perform a z-hop
}
// Whether to unretract before the last travel move of the travel path, which comes before the wall to be printed.
// This should be true when traveling towards an outer wall to make sure that the unretraction will happen before the
// last travel move BEFORE going to that wall. This way, the nozzle doesn't sit still on top of the outer wall's
// path while it is unretracting, avoiding possible blips.
path->unretract_before_last_travel_move = path->retract && unretract_before_last_travel_move;
}
}

Expand Down Expand Up @@ -1704,10 +1710,16 @@ void LayerPlan::writeGCode(GCodeExport& gcode)
// Prevent the final travel(s) from resetting to the 'previous' layer height.
gcode.setZ(final_travel_z);
}
for(unsigned int point_idx = 0; point_idx < path.points.size(); point_idx++)
for(unsigned int point_idx = 0; point_idx < path.points.size() - 1; point_idx++)
{
gcode.writeTravel(path.points[point_idx], speed);
}
if (path.unretract_before_last_travel_move)
{
// We need to unretract before the last travel move of the path if the next path is an outer wall.
gcode.writeUnretractionAndPrime();
}
gcode.writeTravel(path.points.back(), speed);
continue;
}

Expand Down
4 changes: 2 additions & 2 deletions src/LayerPlan.h
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,7 @@ class LayerPlan : public NoCopy
* no combing and no retraction. This travel move needs to be fixed
* afterwards.
* \param p The point to travel to.
* \param force_comb_retract Whether to force a retraction to occur.
* \param force_retract Whether to force a retraction to occur.
*/
GCodePath& addTravel(const Point p, const bool force_retract = false);

Expand Down Expand Up @@ -666,7 +666,7 @@ class LayerPlan : public NoCopy
*
* \param extruder_plan_idx The index of the current extruder plan
* \param path_idx The index of the current retracted path
* \return Whether the path should be an extgruder switch retracted path
* \return Whether the path should be an extruder switch retracted path
*/
bool makeRetractSwitchRetract(unsigned int extruder_plan_idx, unsigned int path_idx);

Expand Down
2 changes: 1 addition & 1 deletion src/LayerPlanBuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ void LayerPlanBuffer::addConnectingTravelMove(LayerPlan* prev_layer, const Layer
const Settings& extruder_settings = Application::getInstance().current_slice->scene.extruders[prev_layer->extruder_plans.back().extruder_nr].settings;
prev_layer->setIsInside(new_layer_destination_state->second);
const bool force_retract = extruder_settings.get<bool>("retract_at_layer_change") ||
(mesh_group_settings.get<bool>("travel_retract_before_outer_wall") && (mesh_group_settings.get<bool>("outer_inset_first") || mesh_group_settings.get<size_t>("wall_line_count") == 1)); //Moving towards an outer wall.
(mesh_group_settings.get<bool>("travel_retract_before_outer_wall") && (mesh_group_settings.get<bool>("outer_inset_first") || mesh_group_settings.get<size_t>("wall_line_count") == 1)); //Moving towards an outer wall.
prev_layer->final_travel_z = newest_layer->z;
GCodePath &path = prev_layer->addTravel(first_location_new_layer, force_retract);
if (force_retract && !path.retract)
Expand Down
11 changes: 6 additions & 5 deletions src/PathOrderMonotonic.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ class PathOrderMonotonic : public PathOrder<PathType>
using PathOrder<PathType>::coincident_point_distance;

PathOrderMonotonic(const AngleRadians monotonic_direction, const coord_t max_adjacent_distance, const Point start_point)
: monotonic_vector(std::cos(monotonic_direction) * monotonic_vector_resolution, std::sin(monotonic_direction) * monotonic_vector_resolution)
//The monotonic vector needs to rotate clockwise instead of counter-clockwise, the same as how the infill patterns are generated.
: monotonic_vector(-std::cos(monotonic_direction) * monotonic_vector_resolution, std::sin(monotonic_direction) * monotonic_vector_resolution)
, max_adjacent_distance(max_adjacent_distance)
{
this->start_point = start_point;
Expand Down Expand Up @@ -161,14 +162,14 @@ class PathOrderMonotonic : public PathOrder<PathType>
}
else //Not a string of polylines, but simply adjacent line segments.
{
if(connected_lines.find(*polyline_it) == connected_lines.end()) //Nothing connects to this line yet.
{
starting_lines.insert(*polyline_it); //This is a starting point then.
}
const std::vector<Path*> overlapping_lines = getOverlappingLines(polyline_it, perpendicular, polylines);
if(overlapping_lines.size() == 1) //If we're not a string of polylines, but adjacent to only one other polyline, create a sequence of polylines.
{
connections[*polyline_it] = overlapping_lines[0];
if(connected_lines.find(*polyline_it) == connected_lines.end()) //Nothing connects to this line yet.
{
starting_lines.insert(*polyline_it); //This is a starting point then.
}
if(connected_lines.find(overlapping_lines[0]) != connected_lines.end()) //This line was already connected to.
{
starting_lines.insert(overlapping_lines[0]); //Multiple lines connect to it, so we must be able to start there.
Expand Down
2 changes: 1 addition & 1 deletion src/TopSurface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ bool TopSurface::ironing(const SliceMeshStorage& mesh, const GCodePathConfig& li
else
{
const coord_t max_adjacent_distance = line_spacing * 1.1; //Lines are considered adjacent - meaning they need to be printed in monotonic order - if spaced 1 line apart, with 10% extra play.
layer.addLinesMonotonic(ironing_lines, line_config, SpaceFillType::PolyLines, AngleRadians(direction + 90.0), max_adjacent_distance);
layer.addLinesMonotonic(ironing_lines, line_config, SpaceFillType::PolyLines, AngleRadians(direction), max_adjacent_distance);
}
added = true;
}
Expand Down
18 changes: 14 additions & 4 deletions src/pathPlanning/Comb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,13 @@ Comb::~Comb()
}
}

bool Comb::calc(const ExtruderTrain& train, Point startPoint, Point endPoint, CombPaths& combPaths, bool _startInside, bool _endInside, coord_t max_comb_distance_ignored)
bool Comb::calc(const ExtruderTrain& train, Point startPoint, Point endPoint, CombPaths& combPaths, bool _startInside, bool _endInside, coord_t max_comb_distance_ignored, bool &unretract_before_last_travel_move)
{
if (shorterThen(endPoint - startPoint, max_comb_distance_ignored))
{
return true;
}

const Point travel_end_point_before_combing = endPoint;
//Move start and end point inside the optimal comb boundary
unsigned int start_inside_poly = NO_INDEX;
const bool startInside = moveInside(boundary_inside_optimal, _startInside, inside_loc_to_line_optimal, startPoint, start_inside_poly);
Expand All @@ -106,7 +106,11 @@ bool Comb::calc(const ExtruderTrain& train, Point startPoint, Point endPoint, Co
{
PolygonsPart part = partsView_inside_optimal.assemblePart(start_part_idx);
combPaths.emplace_back();
return LinePolygonsCrossings::comb(part, *inside_loc_to_line_optimal, startPoint, endPoint, combPaths.back(), -offset_dist_to_get_from_on_the_polygon_to_outside, max_comb_distance_ignored, fail_on_unavoidable_obstacles);
const bool combing_succeeded = LinePolygonsCrossings::comb(part, *inside_loc_to_line_optimal, startPoint, endPoint, combPaths.back(), -offset_dist_to_get_from_on_the_polygon_to_outside, max_comb_distance_ignored, fail_on_unavoidable_obstacles);
// If the endpoint of the travel path changes with combing, then it means that we are moving to an outer wall
// and we should unretract before the last travel move when travelling to that outer wall
unretract_before_last_travel_move = combing_succeeded && endPoint != travel_end_point_before_combing;
return combing_succeeded;
}

//Move start and end point inside the minimum comb boundary
Expand All @@ -132,6 +136,9 @@ bool Comb::calc(const ExtruderTrain& train, Point startPoint, Point endPoint, Co

comb_result = LinePolygonsCrossings::comb(part, *inside_loc_to_line_minimum, startPoint, endPoint, result_path, -offset_dist_to_get_from_on_the_polygon_to_outside, max_comb_distance_ignored, fail_on_unavoidable_obstacles);
Comb::moveCombPathInside(boundary_inside_minimum, boundary_inside_optimal, result_path, combPaths.back()); // add altered result_path to combPaths.back()
// If the endpoint of the travel path changes with combing, then it means that we are moving to an outer wall
// and we should unretract before the last travel move when travelling to that outer wall
unretract_before_last_travel_move = comb_result && endPoint != travel_end_point_before_combing;
return comb_result;
}

Expand Down Expand Up @@ -198,7 +205,7 @@ bool Comb::calc(const ExtruderTrain& train, Point startPoint, Point endPoint, Co
}
}

// throught air from boundary to boundary
// through air from boundary to boundary
if (travel_avoid_other_parts && !skip_avoid_other_parts_path)
{
combPaths.emplace_back();
Expand Down Expand Up @@ -251,6 +258,9 @@ bool Comb::calc(const ExtruderTrain& train, Point startPoint, Point endPoint, Co
combPaths.emplace_back();

bool combing_succeeded = LinePolygonsCrossings::comb(end_crossing.dest_part, *inside_loc_to_line_optimal, end_crossing.in_or_mid, endPoint, combPaths.back(), -offset_dist_to_get_from_on_the_polygon_to_outside, max_comb_distance_ignored, fail_on_unavoidable_obstacles);
// If the endpoint of the travel path changes with combing, then it means that we are moving to an outer wall
// and we should unretract before the last travel move when travelling to that outer wall
unretract_before_last_travel_move = combing_succeeded && endPoint != travel_end_point_before_combing;
if (!combing_succeeded)
{ // Couldn't comb between end point and computed crossing to the end part! Happens for very thin parts when the offset_to_get_off_boundary moves points to outside the polygon
return false;
Expand Down
6 changes: 5 additions & 1 deletion src/pathPlanning/Comb.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,9 +195,13 @@ class Comb
* \p startPoint (?) and \p endPoint.
* \param startInside Whether we want to start inside the comb boundary.
* \param endInside Whether we want to end up inside the comb boundary.
* \param unretract_before_last_travel_move Whether we should unretract before the last travel move when travelling
* because of combing. If the endpoint of a travel path changes with combing, then it means that an outer wall is
* involved, which means that we should then unretract before the last travel move to that wall to avoid any blips
* being introduced due to the unretraction.
* \return Whether combing has succeeded; otherwise a retraction is needed.
*/
bool calc(const ExtruderTrain& train, Point startPoint, Point endPoint, CombPaths& combPaths, bool startInside, bool endInside, coord_t max_comb_distance_ignored);
bool calc(const ExtruderTrain& train, Point startPoint, Point endPoint, CombPaths& combPaths, bool startInside, bool endInside, coord_t max_comb_distance_ignored, bool &unretract_before_last_travel_move);
};

}//namespace cura
Expand Down
1 change: 1 addition & 0 deletions src/pathPlanning/GCodePath.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ space_fill_type(space_fill_type),
flow(flow),
speed_factor(speed_factor),
retract(false),
unretract_before_last_travel_move(false),
perform_z_hop(false),
perform_prime(false),
skip_agressive_merge_hint(false),
Expand Down
1 change: 1 addition & 0 deletions src/pathPlanning/GCodePath.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class GCodePath
Ratio flow; //!< A type-independent flow configuration (used for wall overlap compensation)
Ratio speed_factor; //!< A speed factor that is multiplied with the travel speed. This factor can be used to change the travel speed.
bool retract; //!< Whether the path is a move path preceded by a retraction move; whether the path is a retracted move path.
bool unretract_before_last_travel_move; //!< Whether the last move of the path should be preceded by an unretraction. Used to unretract in the last travel move before an outer wall
bool perform_z_hop; //!< Whether to perform a z_hop in this path, which is assumed to be a travel path.
bool perform_prime; //!< Whether this path is preceded by a prime (blob)
bool skip_agressive_merge_hint; //!< Wheter this path needs to skip merging if any travel paths are in between the extrusions.
Expand Down
13 changes: 10 additions & 3 deletions src/settings/types/Angle.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,10 @@ class AngleDegrees
{
return std::fmod(std::fmod(value + other.value, 360) + 360, 360);
}
AngleDegrees operator +(const int& other) const
template<class T>
AngleDegrees operator +(const T& other) const
{
return operator+(AngleDegrees(other));
return operator+(AngleDegrees(static_cast<double>(other)));
}
AngleDegrees& operator +=(const AngleDegrees& other)
{
Expand All @@ -66,6 +67,11 @@ class AngleDegrees
{
return std::fmod(std::fmod(value - other.value, 360) + 360, 360);
}
template<class T>
AngleDegrees operator -(const T& other) const
{
return operator-(AngleDegrees(static_cast<double>(other)));
}
AngleDegrees& operator -=(const AngleDegrees& other)
{
value = std::fmod(std::fmod(value - other.value, 360) + 360, 360);
Expand All @@ -86,8 +92,9 @@ class AngleDegrees
* This is a facade. It behaves like a double, but this is using clock
* arithmetic which guarantees that the value is always between 0 and 2 * pi.
*/
struct AngleRadians
class AngleRadians
{
public:
/*
* \brief Default constructor setting the angle to 0.
*/
Expand Down
16 changes: 15 additions & 1 deletion tests/LayerPlanTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -536,4 +536,18 @@ TEST_P(AddTravelTest, RetractIfCombingImpossible)
}
}

}
/*!
* Tests to verify that when there is no retraction, then there should also be no unretraction before the last travel
* move in the path.
*/
TEST_P(AddTravelTest, NoUnretractBeforeLastTravelMoveIfNoPriorRetraction)
{
const GCodePath result = run(GetParam());

if(!result.retract)
{
EXPECT_FALSE(result.unretract_before_last_travel_move) << "If no retraction has been issued, then there should also be no unretraction before the last travel move.";
}
}

}

0 comments on commit 99a5245

Please sign in to comment.