Skip to content

Commit

Permalink
Support-infill can has fractional layers + refactor spike-code for ro…
Browse files Browse the repository at this point in the history
…ofs.

- Move code outside of the gcode-writer. For example, z-offset is now calulated in the settings themselves.
- Other than support roofs, support infill now also is fractional layer 'aware'.

this is the 'main' commit for CURA-10407 -- splitting this into different commits would've been a bit more hassle than it's worth, as several of the changes are closely related
  • Loading branch information
rburema committed Oct 13, 2023
1 parent ab538dc commit 8c3740d
Show file tree
Hide file tree
Showing 8 changed files with 134 additions and 122 deletions.
4 changes: 3 additions & 1 deletion include/FffGcodeWriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -634,10 +634,12 @@ class FffGcodeWriter : public NoCopy
* layer.
*
* \param[in] storage Where the slice data is stored.
* \param[in] support_roof_outlines which polygons to generate roofs for -- originally split-up because of fractional (layer-height) layers
* \param[in] current_roof_config config to be used -- most importantly, support has slightly different configs for fractional (layer-height) layers
* \param gcodeLayer The initial planning of the g-code of the layer.
* \return Whether any support skin was added to the layer plan.
*/
bool addSupportRoofsToGCode(const SliceDataStorage& storage, LayerPlan& gcodeLayer) const;
bool addSupportRoofsToGCode(const SliceDataStorage& storage, const Polygons& support_roof_outlines, const GCodePathConfig& current_roof_config, LayerPlan& gcode_layer) const;

/*!
* Add the support bottoms to the layer plan \p gcodeLayer of the current
Expand Down
3 changes: 2 additions & 1 deletion include/SupportInfillPart.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,9 @@ class SupportInfillPart
std::vector<VariableWidthLines> wall_toolpaths; //!< Any walls go here, not in the areas, where they could be combined vertically (don't combine walls). Binned by inset_idx.

coord_t custom_line_distance;
bool use_fractional_config;

SupportInfillPart(const PolygonsPart& outline, coord_t support_line_width, int inset_count_to_generate = 0, coord_t custom_line_distance = 0 );
SupportInfillPart(const PolygonsPart& outline, coord_t support_line_width, bool use_fractional_config, int inset_count_to_generate = 0, coord_t custom_line_distance = 0 );

const Polygons& getInfillArea() const;
};
Expand Down
2 changes: 2 additions & 0 deletions include/settings/PathConfigStorage.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ class PathConfigStorage
std::vector<GCodePathConfig> prime_tower_config_per_extruder; //!< Configuration for the prime tower per extruder.

std::vector<GCodePathConfig> support_infill_config; //!< The config used to print the normal support, rather than the support interface
std::vector<GCodePathConfig> support_fractional_infill_config; //!< The config used to print the normal support on fractional layer-height parts.
GCodePathConfig support_roof_config; //!< The config used to print the dense roofs of support.
GCodePathConfig support_fractional_roof_config; //!< The config used to print the dense roofs of support on fractional layer-height parts.
GCodePathConfig support_bottom_config; //!< The config to use to print the dense bottoms of support

std::vector<MeshPathConfigs> mesh_configs; //!< For each meash the config for all its feature types
Expand Down
5 changes: 3 additions & 2 deletions include/sliceDataStorage.h
Original file line number Diff line number Diff line change
Expand Up @@ -212,8 +212,9 @@ 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 not exactly a multiple of the layer height,
// the first part of support just underneath the model needs to be printed at a fracional layer height.
// NOTE: This is _all_ of the support_roof, and as such, overlaps with support_fractional_roof!
Polygons support_fractional_roof; //!< If the support distance is not exactly a multiple of the layer height,
// 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
188 changes: 87 additions & 101 deletions src/FffGcodeWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3064,7 +3064,8 @@ bool FffGcodeWriter::addSupportToGCode(const SliceDataStorage& storage, LayerPla
}
if (extruder_nr == support_roof_extruder_nr)
{
support_added |= addSupportRoofsToGCode(storage, gcode_layer);
support_added |= addSupportRoofsToGCode(storage, support_layer.support_roof.difference(support_layer.support_fractional_roof), gcode_layer.configs_storage.support_roof_config, gcode_layer);
support_added |= addSupportRoofsToGCode(storage, support_layer.support_fractional_roof, gcode_layer.configs_storage.support_fractional_roof_config, gcode_layer);
}
if (extruder_nr == support_bottom_extruder_nr)
{
Expand Down Expand Up @@ -3160,6 +3161,7 @@ bool FffGcodeWriter::processSupportInfill(const SliceDataStorage& storage, Layer
for (const PathOrdering<const SupportInfillPart*>& path : island_order_optimizer.paths)
{
const SupportInfillPart& part = *path.vertices;
const auto& configs = part.use_fractional_config ? gcode_layer.configs_storage.support_fractional_infill_config : gcode_layer.configs_storage.support_infill_config;

// always process the wall overlap if walls are generated
const int current_support_infill_overlap = (part.inset_count_to_generate > 0) ? default_support_infill_overlap : 0;
Expand All @@ -3169,7 +3171,7 @@ bool FffGcodeWriter::processSupportInfill(const SliceDataStorage& storage, Layer

if (! wall_toolpaths.empty())
{
const GCodePathConfig& config = gcode_layer.configs_storage.support_infill_config[0];
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);
Expand Down Expand Up @@ -3223,7 +3225,7 @@ bool FffGcodeWriter::processSupportInfill(const SliceDataStorage& storage, Layer
{
support_line_distance_here /= 2;
}
const Polygons& area = part.infill_area_per_combine_per_density[density_idx][combine_idx];
const Polygons& area = Simplify(infill_extruder.settings).polygon(part.infill_area_per_combine_per_density[density_idx][combine_idx]);

constexpr size_t wall_count = 0; // Walls are generated somewhere else, so their layers aren't vertically combined.
const coord_t small_area_width = 0;
Expand All @@ -3239,7 +3241,7 @@ bool FffGcodeWriter::processSupportInfill(const SliceDataStorage& storage, Layer
current_support_infill_overlap - (density_idx == max_density_idx ? 0 : wall_line_count * support_line_width),
infill_multiplier,
support_infill_angle,
gcode_layer.z,
gcode_layer.z + configs[combine_idx].z_offset,
support_shift,
max_resolution,
max_deviation,
Expand Down Expand Up @@ -3303,7 +3305,7 @@ bool FffGcodeWriter::processSupportInfill(const SliceDataStorage& storage, Layer

gcode_layer.addPolygonsByOptimizer(
support_polygons,
gcode_layer.configs_storage.support_infill_config[combine_idx],
configs[combine_idx],
z_seam_config,
wall_0_wipe_dist,
spiralize,
Expand All @@ -3324,7 +3326,7 @@ bool FffGcodeWriter::processSupportInfill(const SliceDataStorage& storage, Layer

gcode_layer.addLinesByOptimizer(
support_lines,
gcode_layer.configs_storage.support_infill_config[combine_idx],
configs[combine_idx],
(support_pattern == EFillMethod::ZIG_ZAG) ? SpaceFillType::PolyLines : SpaceFillType::Lines,
enable_travel_optimization,
wipe_dist,
Expand All @@ -3340,7 +3342,7 @@ bool FffGcodeWriter::processSupportInfill(const SliceDataStorage& storage, Layer
// If not, the pattern may still generate gap filling (if it's connected infill or zigzag). We still want to print those.
if (wall_line_count == 0 || ! wall_toolpaths_here.empty())
{
const GCodePathConfig& config = gcode_layer.configs_storage.support_infill_config[0];
const GCodePathConfig& config = configs[0];
constexpr bool retract_before_outer_wall = false;
constexpr coord_t wipe_dist = 0;
constexpr coord_t simplify_curvature = 0;
Expand Down Expand Up @@ -3375,7 +3377,7 @@ bool FffGcodeWriter::processSupportInfill(const SliceDataStorage& storage, Layer
}


bool FffGcodeWriter::addSupportRoofsToGCode(const SliceDataStorage& storage, LayerPlan& gcode_layer) const
bool FffGcodeWriter::addSupportRoofsToGCode(const SliceDataStorage& storage, const Polygons& support_roof_outlines, const GCodePathConfig& current_roof_config, LayerPlan& gcode_layer) const
{
const SupportLayer& support_layer = storage.support.supportLayers[std::max(LayerIndex{ 0 }, gcode_layer.getLayerNr())];

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

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;

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)
Polygons infill_outline = support_roof_outlines;
Polygons wall;
// make sure there is a wall if this is on the first layer
if (gcode_layer.getLayerNr() == 0)
{
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);
}

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()))
{
current_roof_config.z_offset = -leftover_support_distance;
current_roof_config.flow *= Ratio(layer_height - leftover_support_distance, layer_height);

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);
wall = support_layer.support_roof.offset(-support_roof_line_width / 2);
infill_outline = wall.offset(-support_roof_line_width / 2);
}
infill_outline = Simplify(roof_extruder.settings).polygon(infill_outline);

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, current_roof_config, (pattern == EFillMethod::ZIG_ZAG) ? SpaceFillType::PolyLines : SpaceFillType::Lines);
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()))
{
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, 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);

current_roof_config.z_offset = -leftover_support_distance;
current_roof_config.flow *= Ratio(layer_height - leftover_support_distance, layer_height);
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();
}
return generated_something;
gcode_layer.addLinesByOptimizer(roof_lines, current_roof_config, (pattern == EFillMethod::ZIG_ZAG) ? SpaceFillType::PolyLines : SpaceFillType::Lines);
return true;
}

bool FffGcodeWriter::addSupportBottomsToGCode(const SliceDataStorage& storage, LayerPlan& gcode_layer) const
Expand Down
3 changes: 2 additions & 1 deletion src/SupportInfillPart.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@
using namespace cura;


SupportInfillPart::SupportInfillPart(const PolygonsPart& outline, coord_t support_line_width, int inset_count_to_generate, coord_t custom_line_distance)
SupportInfillPart::SupportInfillPart(const PolygonsPart& outline, coord_t support_line_width, bool use_fractional_config, int inset_count_to_generate, coord_t custom_line_distance)
: outline(outline)
, outline_boundary_box(outline)
, support_line_width(support_line_width)
, inset_count_to_generate(inset_count_to_generate)
, custom_line_distance(custom_line_distance)
, use_fractional_config(use_fractional_config)
{
infill_area_per_combine_per_density.clear();
}
15 changes: 15 additions & 0 deletions src/settings/PathConfigStorage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,21 @@ PathConfigStorage::PathConfigStorage(const SliceDataStorage& storage, const Laye
{
handleInitialLayerSpeedup(storage, layer_nr, initial_speedup_layer_count);
}

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;

support_fractional_infill_config = support_infill_config; // copy
for (auto& config : support_fractional_infill_config)
{
config.z_offset = -leftover_support_distance;
config.flow *= Ratio(layer_height - leftover_support_distance, layer_height);
}

support_fractional_roof_config = support_roof_config; // copy
support_fractional_roof_config.z_offset = -leftover_support_distance;
support_fractional_roof_config.flow *= Ratio(layer_height - leftover_support_distance, layer_height);
}

void MeshPathConfigs::smoothAllSpeeds(const SpeedDerivatives& first_layer_config, const LayerIndex layer_nr, const LayerIndex max_speed_layer)
Expand Down
Loading

0 comments on commit 8c3740d

Please sign in to comment.