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-10407] Introduce fractional layer-height support gaps #1955

Merged
merged 60 commits into from
Oct 27, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
b621644
Proof-of-concept 'true' support z-offset: half-layer heights.
rburema Sep 21, 2023
a07fb92
Proof-of-concept: fractional support z-distance.
rburema Sep 21, 2023
7bdbe9a
Applied clang-format.
rburema Sep 21, 2023
16d1a84
Fix crash in proof-of-concept code.
rburema Sep 22, 2023
3820d3b
Proof-of-concept. Attempt to fix newly introduced small extrusions.
rburema Sep 22, 2023
94d6007
Applied clang-format.
rburema Sep 22, 2023
7b6453c
Merge branch '5.5' into CURA-11041_fracional_support_gap
casperlamboo Sep 25, 2023
09a2ce9
Merge branch 'CURA-11084_fix_missing_prime' into CURA-11041_fracional…
rburema Sep 26, 2023
b996cd0
Proof-of-concept. Fix partial-layer-height difference for (support) l…
rburema Sep 26, 2023
185a221
Applied clang-format.
rburema Sep 26, 2023
de2c993
Fix comment to be technically correct.
rburema Oct 11, 2023
ad1aa19
Reverted the changes done in CURA-9521
saumyaj3 Oct 3, 2023
88e0f4c
Support brim printed only at layer 0
saumyaj3 Sep 25, 2023
54e4592
Applied clang-format.
saumyaj3 Sep 25, 2023
7a3aa04
Comment fix
saumyaj3 Sep 25, 2023
ff858f3
Comment fix
saumyaj3 Sep 29, 2023
0b18634
Use correct path config
casperlamboo Oct 3, 2023
09bbf91
Change seam position scoring to make it more consistent
wawanbreton Oct 5, 2023
69ff2c9
Better version of the corner angle computation (to be optimized)
wawanbreton Oct 5, 2023
8228272
Applied clang-format.
wawanbreton Oct 5, 2023
9311a7f
Clean and optimized new corner angle computation algorithm
wawanbreton Oct 6, 2023
55c4327
Applied clang-format.
wawanbreton Oct 6, 2023
57a0dae
Removed debug output
wawanbreton Oct 9, 2023
26ea92b
Fixed some edge-cases with new angle calculation
wawanbreton Oct 9, 2023
31399b1
Remove unused variable
casperlamboo Oct 5, 2023
e44da00
Use different config for roofing inner/outer walls
casperlamboo Oct 5, 2023
5a815f6
Applied clang-format.
casperlamboo Oct 5, 2023
0a91c65
the length of brim is correctly calculated in case of no adhesion
saumyaj3 Oct 5, 2023
3f81191
Applied clang-format.
saumyaj3 Oct 5, 2023
edfd1ce
comment for adding if statement
saumyaj3 Oct 6, 2023
1be4124
Applied clang-format.
saumyaj3 Oct 6, 2023
77028a9
Minor optimization
wawanbreton Oct 9, 2023
784ecfc
Applied code suggestion by @casperlamboo
wawanbreton Oct 9, 2023
948f860
Applied clang-format.
wawanbreton Oct 9, 2023
a96e603
pin gRPC defs to 0.1.0-beta.1
jellespijker Oct 10, 2023
6c20ccd
set version to 5.5.0-beta.2
jellespijker Oct 10, 2023
9ab698b
set version to 5.6.0-alpha
jellespijker Oct 10, 2023
81883c0
loosen deps version
jellespijker Oct 10, 2023
ab538dc
Small refactor.
rburema Oct 13, 2023
8c3740d
Support-infill can has fractional layers + refactor spike-code for ro…
rburema Oct 13, 2023
830c56a
Fractional(-support)-layers: Prevent nozzle from impacting build-plate.
rburema Oct 13, 2023
06a0157
Applied clang-format.
rburema Oct 13, 2023
4682128
Fix unit-test.
rburema Oct 13, 2023
3bea298
Introduce fractional roof-top layer-heigths in tree-support.
rburema Oct 17, 2023
ab39a77
Applied clang-format.
rburema Oct 17, 2023
e1e90a4
Print lower fractional layer heights before full ones, pt 1.
rburema Oct 17, 2023
f61991b
Remove debug code and typos.
rburema Oct 17, 2023
774cc0f
Fix flip-around of boolean. Refactor in prep for consolidation.
rburema Oct 17, 2023
7c02094
Consolidate duplicated code into 'fillInfillParts'.
rburema Oct 17, 2023
bd1b634
Print lower fractional layer heights before full ones, pt 2.
rburema Oct 17, 2023
42b3a71
Applied clang-format.
rburema Oct 17, 2023
1fed8a7
Merge branch 'main' into CURA-11041_fracional_support_gap
rburema Oct 18, 2023
e78f42c
Fix slice in fractional support
casperlamboo Oct 24, 2023
131cae1
Applied clang-format.
casperlamboo Oct 24, 2023
1609f0e
Fix possible crash
wawanbreton Oct 25, 2023
01a5b35
Merge remote-tracking branch 'origin/main' into CURA-11041_fracional_…
rburema Oct 25, 2023
98fc849
(From code review.) Small refactors and add documentation.
rburema Oct 25, 2023
78fcc88
Correct for support-gap equal to exact layer-height multiple.
rburema Oct 25, 2023
54edc02
Applied clang-format.
rburema Oct 25, 2023
4a09451
Really correct support z-gap for all heights now hopefully.
rburema Oct 26, 2023
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 include/GCodePathConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ namespace cura
*/
struct GCodePathConfig
{
coord_t z_offset{};
PrintFeatureType type{}; //!< name of the feature type
coord_t line_width{}; //!< width of the line extruded
coord_t layer_thickness{}; //!< current layer height in micron
Expand Down
19 changes: 10 additions & 9 deletions include/LayerPlan.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,11 @@ class LayerPlan : public NoCopy
*/
GCodePath* getLatestPathWithConfig(
const GCodePathConfig& config,
SpaceFillType space_fill_type,
const coord_t z_offset,
const SpaceFillType space_fill_type,
const Ratio flow = 1.0_r,
const Ratio width_factor = 1.0_r,
bool spiralize = false,
const bool spiralize = false,
const Ratio speed_factor = 1.0_r);

public:
Expand Down Expand Up @@ -281,7 +282,7 @@ class LayerPlan : public NoCopy
* \param p The point to travel to.
* \param force_retract Whether to force a retraction to occur.
*/
GCodePath& addTravel(const Point p, const bool force_retract = false);
GCodePath& addTravel(const Point p, const bool force_retract = false, const coord_t z_offset = 0);

/*!
* Add a travel path to a certain point and retract if needed.
Expand All @@ -291,7 +292,7 @@ class LayerPlan : public NoCopy
* \param p The point to travel to
* \param path (optional) The travel path to which to add the point \p p
*/
GCodePath& addTravel_simple(Point p, GCodePath* path = nullptr);
GCodePath& addTravel_simple(const Point p, GCodePath* path = nullptr);
rburema marked this conversation as resolved.
Show resolved Hide resolved

/*!
* Plan a prime blob at the current location.
Expand All @@ -317,14 +318,14 @@ class LayerPlan : public NoCopy
* \param fan_speed Fan speed override for this path.
*/
void addExtrusionMove(
Point p,
const Point p,
const GCodePathConfig& config,
SpaceFillType space_fill_type,
const SpaceFillType space_fill_type,
const Ratio& flow = 1.0_r,
const Ratio width_factor = 1.0_r,
bool spiralize = false,
Ratio speed_factor = 1.0_r,
double fan_speed = GCodePathConfig::FAN_SPEED_DEFAULT);
const bool spiralize = false,
const Ratio speed_factor = 1.0_r,
const double fan_speed = GCodePathConfig::FAN_SPEED_DEFAULT);

/*!
* Add polygon to the gcode starting at vertex \p startIdx
Expand Down
1 change: 1 addition & 0 deletions include/pathPlanning/GCodePath.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ namespace cura
*/
struct GCodePath
{
coord_t z_offset{};
rburema marked this conversation as resolved.
Show resolved Hide resolved
GCodePathConfig config{}; //!< The configuration settings of the path.
std::shared_ptr<const SliceMeshStorage> mesh; //!< Which mesh this path belongs to, if any. If it's not part of any mesh, the mesh should be nullptr;
SpaceFillType space_fill_type{}; //!< The type of space filling of which this path is a part
Expand Down
2 changes: 2 additions & 0 deletions include/sliceDataStorage.h
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,8 @@ class SupportLayer
std::vector<SupportInfillPart> support_infill_parts; //!< a list of support infill parts
Polygons support_bottom; //!< Piece of support below the support and above the model. This must not overlap with any of the support_infill_parts or support_roof.
Polygons support_roof; //!< Piece of support above the support and below the model. This must not overlap with any of the support_infill_parts or support_bottom.
Polygons support_fractional_roof_top; //!< If the support distance is less than a multiple of the layer height,
rburema marked this conversation as resolved.
Show resolved Hide resolved
// the first part of support just underneath the model needs to be printed at a fracional layer height.
Polygons support_mesh_drop_down; //!< Areas from support meshes which should be supported by more support
Polygons support_mesh; //!< Areas from support meshes which should NOT be supported by more support
Polygons anti_overhang; //!< Areas where no overhang should be detected.
Expand Down
176 changes: 95 additions & 81 deletions src/FffGcodeWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2287,7 +2287,7 @@ bool FffGcodeWriter::processInsets(
if (mesh_group_settings.get<bool>("support_enable"))
{
const coord_t z_distance_top = mesh.settings.get<coord_t>("support_top_distance");
const size_t z_distance_top_layers = round_up_divide(z_distance_top, layer_height) + 1;
const size_t z_distance_top_layers = round_up_divide(z_distance_top, layer_height); // Previously '... +1', but now there is an extra fractional layer on top.
const int support_layer_nr = gcode_layer.getLayerNr() - z_distance_top_layers;

if (support_layer_nr > 0)
Expand Down Expand Up @@ -2596,7 +2596,7 @@ void FffGcodeWriter::processTopBottom(
{
const coord_t layer_height = mesh_config.inset0_config.getLayerThickness();
const coord_t z_distance_top = mesh.settings.get<coord_t>("support_top_distance");
const size_t z_distance_top_layers = round_up_divide(z_distance_top, layer_height) + 1;
const size_t z_distance_top_layers = round_up_divide(z_distance_top, layer_height); // Previously '... +1', but now there is an extra fractional layer on top.
support_layer_nr = layer_nr - z_distance_top_layers;
}

Expand Down Expand Up @@ -3327,89 +3327,103 @@ bool FffGcodeWriter::addSupportRoofsToGCode(const SliceDataStorage& storage, Lay
support_roof_line_distance *= roof_extruder.settings.get<Ratio>("initial_layer_line_width_factor");
}

Polygons infill_outline = support_layer.support_roof;
Polygons wall;
// make sure there is a wall if this is on the first layer
if (gcode_layer.getLayerNr() == 0)
{
wall = support_layer.support_roof.offset(-support_roof_line_width / 2);
infill_outline = wall.offset(-support_roof_line_width / 2);
}
const auto layer_height = Application::getInstance().current_slice->scene.current_mesh_group->settings.get<coord_t>("layer_height");
const auto support_top_distance = Application::getInstance().current_slice->scene.current_mesh_group->settings.get<coord_t>("support_top_distance");
const coord_t leftover_support_distance = support_top_distance % layer_height;

Infill roof_computation(
pattern,
zig_zaggify_infill,
connect_polygons,
infill_outline,
gcode_layer.configs_storage.support_roof_config.getLineWidth(),
support_roof_line_distance,
support_roof_overlap,
infill_multiplier,
fill_angle,
gcode_layer.z,
extra_infill_shift,
max_resolution,
max_deviation,
wall_line_count,
small_area_width,
infill_origin,
skip_stitching,
fill_gaps,
connected_zigzags,
use_endpieces,
skip_some_zags,
zag_skip_count,
pocket_size);
Polygons roof_polygons;
std::vector<VariableWidthLines> roof_paths;
Polygons roof_lines;
roof_computation.generate(roof_paths, roof_polygons, roof_lines, roof_extruder.settings, gcode_layer.getLayerNr(), SectionType::SUPPORT);
if ((gcode_layer.getLayerNr() == 0 && wall.empty()) || (gcode_layer.getLayerNr() > 0 && roof_paths.empty() && roof_polygons.empty() && roof_lines.empty()))
{
return false; // We didn't create any support roof.
}
gcode_layer.setIsInside(false); // going to print stuff outside print object, i.e. support
if (gcode_layer.getLayerNr() == 0)
{
gcode_layer.addPolygonsByOptimizer(wall, gcode_layer.configs_storage.support_roof_config);
}
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, gcode_layer.configs_storage.support_roof_config);
}
if (! roof_paths.empty())
std::vector<Polygons> infill_outlines = { Simplify(roof_extruder.settings).polygon(support_layer.support_roof.difference(support_layer.support_fractional_roof_top)),
Simplify(roof_extruder.settings).polygon(support_layer.support_fractional_roof_top) };
auto current_roof_config = gcode_layer.configs_storage.support_roof_config; // copy!
bool generated_something = false;
for (auto& infill_outline : infill_outlines)
{
const GCodePathConfig& config = gcode_layer.configs_storage.support_roof_config;
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);
Polygons wall;
// make sure there is a wall if this is on the first layer
if (gcode_layer.getLayerNr() == 0)
{
wall = support_layer.support_roof.offset(-support_roof_line_width / 2);
infill_outline = wall.offset(-support_roof_line_width / 2);
}

InsetOrderOptimizer wall_orderer(
*this,
storage,
gcode_layer,
roof_extruder.settings,
roof_extruder_nr,
config,
config,
config,
config,
retract_before_outer_wall,
wipe_dist,
wipe_dist,
roof_extruder_nr,
roof_extruder_nr,
z_seam_config,
roof_paths);
wall_orderer.addToLayer();
Infill roof_computation(
pattern,
zig_zaggify_infill,
connect_polygons,
infill_outline,
current_roof_config.getLineWidth(),
support_roof_line_distance,
support_roof_overlap,
infill_multiplier,
fill_angle,
gcode_layer.z + current_roof_config.z_offset,
extra_infill_shift,
max_resolution,
max_deviation,
wall_line_count,
small_area_width,
infill_origin,
skip_stitching,
fill_gaps,
connected_zigzags,
use_endpieces,
skip_some_zags,
zag_skip_count,
pocket_size);
Polygons roof_polygons;
std::vector<VariableWidthLines> roof_paths;
Polygons roof_lines;
roof_computation.generate(roof_paths, roof_polygons, roof_lines, roof_extruder.settings, gcode_layer.getLayerNr(), SectionType::SUPPORT);
if ((gcode_layer.getLayerNr() == 0 && wall.empty()) || (gcode_layer.getLayerNr() > 0 && roof_paths.empty() && roof_polygons.empty() && roof_lines.empty()))
{
continue; // We didn't create any support roof.
}
generated_something = true; // We _did_ create at least some support roof.
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);
}
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);
}
if (! roof_paths.empty())
{
const GCodePathConfig& config = current_roof_config;
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);

InsetOrderOptimizer wall_orderer(
*this,
storage,
gcode_layer,
roof_extruder.settings,
roof_extruder_nr,
config,
config,
config,
config,
retract_before_outer_wall,
wipe_dist,
wipe_dist,
roof_extruder_nr,
roof_extruder_nr,
z_seam_config,
roof_paths);
wall_orderer.addToLayer();
}
gcode_layer.addLinesByOptimizer(
roof_lines,
gcode_layer.configs_storage.support_roof_config,
(pattern == EFillMethod::ZIG_ZAG) ? SpaceFillType::PolyLines : SpaceFillType::Lines);

current_roof_config.z_offset = -leftover_support_distance;
current_roof_config.flow *= Ratio(layer_height - leftover_support_distance, layer_height);
}
gcode_layer.addLinesByOptimizer(
roof_lines,
gcode_layer.configs_storage.support_roof_config,
(pattern == EFillMethod::ZIG_ZAG) ? SpaceFillType::PolyLines : SpaceFillType::Lines);
return true;
return generated_something;
}

bool FffGcodeWriter::addSupportBottomsToGCode(const SliceDataStorage& storage, LayerPlan& gcode_layer) const
Expand Down
42 changes: 25 additions & 17 deletions src/LayerPlan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,22 @@ constexpr int MINIMUM_SQUARED_LINE_LENGTH = MINIMUM_LINE_LENGTH * MINIMUM_LINE_L

GCodePath* LayerPlan::getLatestPathWithConfig(
const GCodePathConfig& config,
SpaceFillType space_fill_type,
const coord_t z_offset,
const SpaceFillType space_fill_type,
const Ratio flow,
const Ratio width_factor,
bool spiralize,
const bool spiralize,
const Ratio speed_factor)
{
std::vector<GCodePath>& paths = extruder_plans.back().paths;
if (paths.size() > 0 && paths.back().config == config && ! paths.back().done && paths.back().flow == flow && paths.back().width_factor == width_factor
&& paths.back().speed_factor == speed_factor && paths.back().mesh == current_mesh) // spiralize can only change when a travel path is in between
&& paths.back().speed_factor == speed_factor && paths.back().z_offset == z_offset
&& paths.back().mesh == current_mesh) // spiralize can only change when a travel path is in between
{
return &paths.back();
}
paths.emplace_back(GCodePath{ .config = config,
paths.emplace_back(GCodePath{ .z_offset = z_offset,
.config = config,
.mesh = current_mesh,
.space_fill_type = space_fill_type,
.flow = flow,
Expand Down Expand Up @@ -326,14 +329,14 @@ std::optional<std::pair<Point, bool>> LayerPlan::getFirstTravelDestinationState(
return ret;
}

GCodePath& LayerPlan::addTravel(const Point p, const bool force_retract)
GCodePath& LayerPlan::addTravel(const Point p, const bool force_retract, const coord_t z_offset)
{
const GCodePathConfig& travel_config = configs_storage.travel_config_per_extruder[getExtruder()];

const RetractionConfig& retraction_config
= current_mesh ? current_mesh->retraction_wipe_config.retraction_config : storage.retraction_wipe_config_per_extruder[getExtruder()].retraction_config;

GCodePath* path = getLatestPathWithConfig(travel_config, SpaceFillType::None);
GCodePath* path = getLatestPathWithConfig(travel_config, z_offset, SpaceFillType::None);

bool combed = false;

Expand Down Expand Up @@ -478,7 +481,7 @@ GCodePath& LayerPlan::addTravel(const Point p, const bool force_retract)
return ret;
}

GCodePath& LayerPlan::addTravel_simple(Point p, GCodePath* path)
GCodePath& LayerPlan::addTravel_simple(const Point p, GCodePath* path)
{
bool is_first_travel_of_layer = ! static_cast<bool>(last_planned_position);
if (is_first_travel_of_layer)
Expand All @@ -488,7 +491,7 @@ GCodePath& LayerPlan::addTravel_simple(Point p, GCodePath* path)
}
if (path == nullptr)
{
path = getLatestPathWithConfig(configs_storage.travel_config_per_extruder[getExtruder()], SpaceFillType::None);
path = getLatestPathWithConfig(configs_storage.travel_config_per_extruder[getExtruder()], 0, SpaceFillType::None);
rburema marked this conversation as resolved.
Show resolved Hide resolved
}
path->points.push_back(p);
last_planned_position = p;
Expand All @@ -506,16 +509,16 @@ void LayerPlan::planPrime(const float& prime_blob_wipe_length)
}

void LayerPlan::addExtrusionMove(
Point p,
const Point p,
const GCodePathConfig& config,
SpaceFillType space_fill_type,
const SpaceFillType space_fill_type,
const Ratio& flow,
const Ratio width_factor,
bool spiralize,
Ratio speed_factor,
double fan_speed)
const bool spiralize,
const Ratio speed_factor,
const double fan_speed)
{
GCodePath* path = getLatestPathWithConfig(config, space_fill_type, flow, width_factor, spiralize, speed_factor);
GCodePath* path = getLatestPathWithConfig(config, config.z_offset, space_fill_type, flow, width_factor, spiralize, speed_factor);
path->points.push_back(p);
path->setFanSpeed(fan_speed);
if (! static_cast<bool>(first_extrusion_acc_jerk))
Expand All @@ -537,7 +540,7 @@ void LayerPlan::addPolygon(
{
constexpr Ratio width_ratio = 1.0_r; // Not printed with variable line width.
Point p0 = polygon[start_idx];
addTravel(p0, always_retract);
addTravel(p0, always_retract, config.z_offset);
const int direction = backwards ? -1 : 1;
for (size_t point_idx = 1; point_idx < polygon.size(); point_idx++)
{
Expand Down Expand Up @@ -1250,7 +1253,7 @@ void LayerPlan::addLinesInGivenOrder(
}
else
{
addTravel(start);
addTravel(start, false, config.z_offset);
}

Point p0 = start;
Expand Down Expand Up @@ -1947,7 +1950,12 @@ void LayerPlan::writeGCode(GCodeExport& gcode)
gcode.writeRetraction(retraction_config->retraction_config);
}

if (! path.retract && path.config.isTravelPath() && path.points.size() == 1 && path.points[0] == gcode.getPositionXY() && z == gcode.getPositionZ())
if (z > 0)
{
gcode.setZ(z + path.z_offset);
}

if (! path.retract && path.config.isTravelPath() && path.points.size() == 1 && path.points[0] == gcode.getPositionXY() && (z + path.z_offset) == gcode.getPositionZ())
{
// ignore travel moves to the current location to avoid needless change of acceleration/jerk
continue;
Expand Down
Loading