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

Apply scarf seam and speed gradient in surface mode #2158

Merged
merged 7 commits into from
Oct 31, 2024
Merged
Show file tree
Hide file tree
Changes from 5 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
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ set(engine_SRCS # Except main.cpp.
src/Mold.cpp
src/multiVolumes.cpp
src/path_ordering.cpp
src/PathAdapter.cpp
src/Preheat.cpp
src/PrimeTower/PrimeTower.cpp
src/PrimeTower/PrimeTowerNormal.cpp
Expand Down
88 changes: 70 additions & 18 deletions include/LayerPlan.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ class Comb;
class SliceDataStorage;
class LayerPlanBuffer;

template<typename PathType>
class PathAdapter;

/*!
* The LayerPlan class stores multiple moves that are planned.
*
Expand Down Expand Up @@ -398,11 +401,15 @@ class LayerPlan : public NoCopy
const Polygon& polygon,
int startIdx,
const bool reverse,
const Settings& settings,
const GCodePathConfig& config,
coord_t wall_0_wipe_dist = 0,
bool spiralize = false,
const Ratio& flow_ratio = 1.0_r,
bool always_retract = false);
bool always_retract = false,
bool scarf_seam = false,
wawanbreton marked this conversation as resolved.
Show resolved Hide resolved
bool smooth_speed = false,
bool is_candidate_small_feature = false);
wawanbreton marked this conversation as resolved.
Show resolved Hide resolved

/*!
* Add polygons to the gcode with optimized order.
Expand Down Expand Up @@ -435,13 +442,16 @@ class LayerPlan : public NoCopy
void addPolygonsByOptimizer(
const Shape& polygons,
const GCodePathConfig& config,
const Settings& settings,
const ZSeamConfig& z_seam_config = ZSeamConfig(),
coord_t wall_0_wipe_dist = 0,
bool spiralize = false,
const Ratio flow_ratio = 1.0_r,
bool always_retract = false,
bool reverse_order = false,
const std::optional<Point2LL> start_near_location = std::optional<Point2LL>());
const std::optional<Point2LL> start_near_location = std::optional<Point2LL>(),
bool scarf_seam = false,
bool smooth_acceleration = false);

/*!
* Add a single line that is part of a wall to the gcode.
Expand Down Expand Up @@ -836,18 +846,15 @@ class LayerPlan : public NoCopy

/*!
* \brief Add a wall to the gcode with optimized order, but split into pieces in order to facilitate the scarf seam and/or speed gradient.
* \tparam PathType The type of path to be processed, either ExtrusionLine or some subclass of Polyline
* \param wall The full wall to be added
* \param wall_length The pre-calculated full wall length
* \param start_idx The index of the point where to start printing the wall
* \param direction The direction along which to print the wall, which should be 1 or -1
* \param max_index The last index to be used when iterating over the wall segments
* \param settings The settings which should apply to this wall added to the layer plan
* \param default_config The config with which to print the wall lines that are not spanning a bridge or are exposed to air
* \param roofing_config The config with which to print the wall lines that are exposed to air
* \param bridge_config The config with which to print the wall lines that are spanning a bridge
* \param flow_ratio The ratio with which to multiply the extrusion amount
* \param line_width_ratio The line width ratio to be applied
* \param non_bridge_line_volume A pseudo-volume that is derived from the print speed and flow of the non-bridge lines that have preceded this lin
* \param nominal_line_width The nominal line width for the wall
* \param min_bridge_line_len The minimum line width to allow an extrusion move to be processed as a bridge move
* \param always_retract Whether to force a retraction when moving to the start of the polygon (used for outer walls)
* \param is_small_feature Indicates whether the wall is so small that it should be processed differently
Expand All @@ -864,26 +871,26 @@ class LayerPlan : public NoCopy
* \param end_speed_ratio The ratio of the top speed to be applied when finishing a segment
* \param decelerate_length The pre-calculated length of the deceleration phase
* \param is_scarf_closure Indicates whether this function is called to make the scarf closure (overlap over the first scarf pass) or the normal first pass of the wall
* \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
*/
template<class PathType>
void addSplitWall(
const ExtrusionLine& wall,
const PathAdapter<PathType>& wall,
const coord_t wall_length,
size_t start_idx,
const int direction,
const size_t start_idx,
const size_t max_index,
const Settings& settings,
const int direction,
const GCodePathConfig& default_config,
const GCodePathConfig& roofing_config,
const GCodePathConfig& bridge_config,
const double flow_ratio,
const Ratio line_width_ratio,
double& non_bridge_line_volume,
const coord_t min_bridge_line_len,
const bool always_retract,
const bool is_small_feature,
Ratio small_feature_speed_factor,
const coord_t max_area_deviation,
const auto max_resolution,
const double flow_ratio,
const coord_t nominal_line_width,
const coord_t min_bridge_line_len,
const auto scarf_seam_length,
const auto scarf_seam_start_ratio,
const auto scarf_split_distance,
Expand All @@ -893,7 +900,52 @@ class LayerPlan : public NoCopy
const coord_t accelerate_length,
const Ratio end_speed_ratio,
const coord_t decelerate_length,
const bool is_scarf_closure);
const bool is_scarf_closure,
const bool compute_distance_to_bridge_start,
const std::function<void(
wawanbreton marked this conversation as resolved.
Show resolved Hide resolved
const Point3LL& start,
const Point3LL& end,
const Ratio& speed_factor,
const Ratio& flow_ratio,
const Ratio& line_width_ratio,
const coord_t distance_to_bridge_start)>& func_add_segment);

/*!
* \brief Add a wall to the gcode with optimized order, possibly adding a scarf seam / speed gradient according to settings
* \tparam PathType The type of path to be processed, either ExtrusionLine or some subclass of Polyline
* \param wall The full wall to be added
* \param start_idx The index of the point where to start printing the wall
* \param settings The settings which should apply to this wall added to the layer plan
* \param default_config The config with which to print the wall lines that are not spanning a bridge or are exposed to air
* \param flow_ratio The ratio with which to multiply the extrusion amount
* \param always_retract Whether to force a retraction when moving to the start of the polygon (used for outer walls)
* \param is_closed Indicates whether the path is closed (or open)
* \param is_reversed Indicates if the path is to be processed backwards
* \param is_candidate_small_feature Indicates whether the path should be tested for being treated as a smell feature
* \param scarf_seam Indicates whether we may set a scraf seam to the path
* \param smooth_speed Indicates whether we may set a speed gradient to the path
* \param func_add_segment The function to be called to actually add an extrusion segment with the given parameters
*/
template<class PathType>
void addWallWithScarfSeam(
const PathAdapter<PathType>& wall,
size_t start_idx,
const Settings& settings,
const GCodePathConfig& default_config,
const double flow_ratio,
bool always_retract,
const bool is_closed,
const bool is_reversed,
const bool is_candidate_small_feature,
const bool scarf_seam,
const bool smooth_speed,
const std::function<void(
wawanbreton marked this conversation as resolved.
Show resolved Hide resolved
const Point3LL& start,
const Point3LL& end,
const Ratio& speed_factor,
const Ratio& flow_ratio,
const Ratio& line_width_ratio,
const coord_t distance_to_bridge_start)>& func_add_segment);

/*!
* \brief Helper function to calculate the distance from the start of the current wall line to the first bridge segment
Expand Down
63 changes: 63 additions & 0 deletions include/PathAdapter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright (c) 2024 Ultimaker B.V.
// CuraEngine is released under the terms of the AGPLv3 or higher.

#ifndef PATH_ADAPTER_H
#define PATH_ADAPTER_H

#include <stddef.h>

#include "geometry/Point2LL.h"
#include "utils/Coord_t.h"

namespace cura
{

/* Adapter class to allow extrusion-related functions to work with either an ExtrusionLine or a Polygon */
template<typename PathType>
class PathAdapter
{
public:
/*!
* \brief Base constructor
* \param path The actual stored path
* \param fixed_line_width The fixed line width in case the stored path doesn't handle information about a variable
* line width. Can be omitted otherwise.
*/
PathAdapter(const PathType& path, coord_t fixed_line_width = 0)
: path_(path)
, fixed_line_width_(fixed_line_width)
{
}

bool empty() const
{
return path_.empty();
}

size_t size() const
{
return path_.size();
}

coord_t length() const
{
return path_.length();
}

const Point2LL& pointAt(size_t index) const;

coord_t lineWidthAt(size_t index) const;

const PathType& getPath() const
{
return path_;
}

private:
const PathType& path_;
const coord_t fixed_line_width_;
};

} // namespace cura

#endif // PATH_ADAPTER_H
46 changes: 35 additions & 11 deletions src/FffGcodeWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -735,6 +735,7 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage)
gcode_layer.addPolygonsByOptimizer(
raft_polygons,
gcode_layer.configs_storage_.raft_base_config,
mesh_group_settings,
ZSeamConfig(),
wipe_dist,
spiralize,
Expand Down Expand Up @@ -895,6 +896,7 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage)
gcode_layer.addPolygonsByOptimizer(
raft_polygons,
gcode_layer.configs_storage_.raft_interface_config,
mesh_group_settings,
ZSeamConfig(),
wipe_dist,
spiralize,
Expand Down Expand Up @@ -1073,6 +1075,7 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage)
gcode_layer.addPolygonsByOptimizer(
raft_polygons,
gcode_layer.configs_storage_.raft_surface_config,
mesh_group_settings,
ZSeamConfig(),
wipe_dist,
spiralize,
Expand Down Expand Up @@ -1477,13 +1480,14 @@ void FffGcodeWriter::processSkirtBrim(const SliceDataStorage& storage, LayerPlan
void FffGcodeWriter::processOozeShield(const SliceDataStorage& storage, LayerPlan& gcode_layer) const
{
LayerIndex layer_nr = std::max(LayerIndex{ 0 }, gcode_layer.getLayerNr());
if (layer_nr == 0 && Application::getInstance().current_slice_->scene.current_mesh_group->settings.get<EPlatformAdhesion>("adhesion_type") == EPlatformAdhesion::BRIM)
const Settings& mesh_group_settings = Application::getInstance().current_slice_->scene.current_mesh_group->settings;
if (layer_nr == 0 && mesh_group_settings.get<EPlatformAdhesion>("adhesion_type") == EPlatformAdhesion::BRIM)
{
return; // ooze shield already generated by brim
}
if (storage.ooze_shield.size() > 0 && layer_nr < storage.ooze_shield.size())
{
gcode_layer.addPolygonsByOptimizer(storage.ooze_shield[layer_nr], gcode_layer.configs_storage_.skirt_brim_config_per_extruder[0]);
gcode_layer.addPolygonsByOptimizer(storage.ooze_shield[layer_nr], gcode_layer.configs_storage_.skirt_brim_config_per_extruder[0], mesh_group_settings);
}
}

Expand Down Expand Up @@ -1516,7 +1520,7 @@ void FffGcodeWriter::processDraftShield(const SliceDataStorage& storage, LayerPl
}
}

gcode_layer.addPolygonsByOptimizer(storage.draft_protection_shield, gcode_layer.configs_storage_.skirt_brim_config_per_extruder[0]);
gcode_layer.addPolygonsByOptimizer(storage.draft_protection_shield, gcode_layer.configs_storage_.skirt_brim_config_per_extruder[0], mesh_group_settings);
}

void FffGcodeWriter::calculateExtruderOrderPerLayer(const SliceDataStorage& storage)
Expand Down Expand Up @@ -1723,7 +1727,26 @@ void FffGcodeWriter::addMeshLayerToGCode_meshSurfaceMode(const SliceMeshStorage&
mesh.settings.get<EZSeamCornerPrefType>("z_seam_corner"),
mesh.settings.get<coord_t>("wall_line_width_0") * 2);
const bool spiralize = Application::getInstance().current_slice_->scene.current_mesh_group->settings.get<bool>("magic_spiralize");
gcode_layer.addPolygonsByOptimizer(polygons, mesh_config.inset0_config, z_seam_config, mesh.settings.get<coord_t>("wall_0_wipe_dist"), spiralize);
constexpr Ratio flow_ratio = 1.0;
constexpr bool always_retract = false;
constexpr bool reverse_order = false;
const std::optional<Point2LL> start_near_location = std::nullopt;
constexpr bool scarf_seam = true;
constexpr bool smooth_speed = true;

gcode_layer.addPolygonsByOptimizer(
polygons,
mesh_config.inset0_config,
mesh.settings,
z_seam_config,
mesh.settings.get<coord_t>("wall_0_wipe_dist"),
spiralize,
flow_ratio,
always_retract,
reverse_order,
start_near_location,
scarf_seam,
smooth_speed);

addMeshOpenPolyLinesToGCode(mesh, mesh_config, gcode_layer);
}
Expand Down Expand Up @@ -1966,7 +1989,7 @@ bool FffGcodeWriter::processMultiLayerInfill(
{
constexpr bool force_comb_retract = false;
gcode_layer.addTravel(infill_polygons[0][0], force_comb_retract);
gcode_layer.addPolygonsByOptimizer(infill_polygons, mesh_config.infill_config[combine_idx]);
gcode_layer.addPolygonsByOptimizer(infill_polygons, mesh_config.infill_config[combine_idx], mesh.settings);
}

if (! infill_lines.empty())
Expand Down Expand Up @@ -2723,7 +2746,7 @@ bool FffGcodeWriter::processSingleLayerInfill(
constexpr bool force_comb_retract = false;
// start the infill polygons at the nearest vertex to the current location
gcode_layer.addTravel(PolygonUtils::findNearestVert(gcode_layer.getLastPlannedPositionOrStartingPosition(), infill_polygons).p(), force_comb_retract);
gcode_layer.addPolygonsByOptimizer(infill_polygons, mesh_config.infill_config[0], ZSeamConfig(), 0, false, 1.0_r, false, false, near_start_location);
gcode_layer.addPolygonsByOptimizer(infill_polygons, mesh_config.infill_config[0], mesh.settings, ZSeamConfig(), 0, false, 1.0_r, false, false, near_start_location);
}
const bool enable_travel_optimization = mesh.settings.get<bool>("infill_enable_travel_optimization");
if (pattern == EFillMethod::GRID || pattern == EFillMethod::LINES || pattern == EFillMethod::TRIANGLES || pattern == EFillMethod::CUBIC
Expand Down Expand Up @@ -2965,7 +2988,7 @@ bool FffGcodeWriter::processInsets(
gcode_layer.addTravel(spiral_inset[spiral_start_vertex]);
}
int wall_0_wipe_dist(0);
gcode_layer.addPolygonsByOptimizer(part.spiral_wall, mesh_config.inset0_config, ZSeamConfig(), wall_0_wipe_dist);
gcode_layer.addPolygonsByOptimizer(part.spiral_wall, mesh_config.inset0_config, mesh.settings, ZSeamConfig(), wall_0_wipe_dist);
}
}
// for non-spiralized layers, determine the shape of the unsupported areas below this part
Expand Down Expand Up @@ -3596,7 +3619,7 @@ void FffGcodeWriter::processSkinPrintFeature(
{
constexpr bool force_comb_retract = false;
gcode_layer.addTravel(skin_polygons[0][0], force_comb_retract);
gcode_layer.addPolygonsByOptimizer(skin_polygons, config);
gcode_layer.addPolygonsByOptimizer(skin_polygons, config, mesh.settings);
}

if (monotonic)
Expand Down Expand Up @@ -4001,6 +4024,7 @@ bool FffGcodeWriter::processSupportInfill(const SliceDataStorage& storage, Layer
gcode_layer.addPolygonsByOptimizer(
support_polygons,
configs[combine_idx],
mesh_group_settings,
z_seam_config,
wall_0_wipe_dist,
spiralize,
Expand Down Expand Up @@ -4167,13 +4191,13 @@ bool FffGcodeWriter::addSupportRoofsToGCode(const SliceDataStorage& storage, con
gcode_layer.setIsInside(false); // going to print stuff outside print object, i.e. support
if (gcode_layer.getLayerNr() == 0)
{
gcode_layer.addPolygonsByOptimizer(wall, current_roof_config);
gcode_layer.addPolygonsByOptimizer(wall, current_roof_config, roof_extruder.settings_);
}
if (! roof_polygons.empty())
{
constexpr bool force_comb_retract = false;
gcode_layer.addTravel(roof_polygons[0][0], force_comb_retract);
gcode_layer.addPolygonsByOptimizer(roof_polygons, current_roof_config);
gcode_layer.addPolygonsByOptimizer(roof_polygons, current_roof_config, roof_extruder.settings_);
}
if (! roof_paths.empty())
{
Expand Down Expand Up @@ -4287,7 +4311,7 @@ bool FffGcodeWriter::addSupportBottomsToGCode(const SliceDataStorage& storage, L
{
constexpr bool force_comb_retract = false;
gcode_layer.addTravel(bottom_polygons[0][0], force_comb_retract);
gcode_layer.addPolygonsByOptimizer(bottom_polygons, gcode_layer.configs_storage_.support_bottom_config);
gcode_layer.addPolygonsByOptimizer(bottom_polygons, gcode_layer.configs_storage_.support_bottom_config, bottom_extruder.settings_);
}
if (! bottom_paths.empty())
{
Expand Down
Loading
Loading