Skip to content

Commit

Permalink
Properly handle overlapping brims/rafts
Browse files Browse the repository at this point in the history
  • Loading branch information
wawanbreton committed Oct 12, 2023
1 parent 90f8a8f commit 2dada4c
Show file tree
Hide file tree
Showing 9 changed files with 196 additions and 196 deletions.
21 changes: 17 additions & 4 deletions include/PrimeTower.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#ifndef PRIME_TOWER_H
#define PRIME_TOWER_H

#include "settings/types/LayerIndex.h"
#include "utils/polygon.h" // Polygons
#include "utils/polygonUtils.h"

Expand Down Expand Up @@ -42,12 +43,20 @@ class PrimeTower
std::vector<ExtrusionMoves> pattern_per_extruder; //!< For each extruder the pattern to print on all layers of the prime tower.
std::vector<std::vector<ExtrusionMoves>> pattern_extra_brim_per_layer; //!< For each layer of each extruder with an extra brim, the pattern to be added

Polygons outer_poly; //!< The outline of the outermost prime tower.

struct BasePolygon
{
Polygons polygons;
size_t extra_rings;
};

std::vector<Polygons> outer_poly_base; //!< The outline of the prime tower for layers having a base

public:
bool enabled; //!< Whether the prime tower is enabled.
bool would_have_actual_tower; //!< Whether there is an actual tower.
bool multiple_extruders_on_first_layer; //!< Whether multiple extruders are allowed on the first layer of the prime tower (e.g. when a raft is there)
Polygons outer_poly; //!< The outline of the outermost prime tower.
Polygons footprint; //!< The outline of the prime tower on layer 0

/*
* In which order, from outside to inside, will we be printing the prime
Expand Down Expand Up @@ -101,10 +110,14 @@ class PrimeTower
*/
void subtractFromSupport(SliceDataStorage& storage);

const Polygons &getOuterPoly(const LayerIndex &layer_nr) const;

const Polygons &getGroundPoly() const;

private:
ExtrusionMoves generatePaths_base(const Polygons& outer_poly, coord_t extra_radius, coord_t line_width);
static ExtrusionMoves generatePaths_base(const Polygons &inset, size_t rings, coord_t line_width);

ExtrusionMoves generatePaths_inset(const Polygons& outer_poly, coord_t line_width, coord_t initial_inset);
static ExtrusionMoves generatePaths_inset(const Polygons& outer_poly, coord_t line_width, coord_t initial_inset);

/*!
* \see WipeTower::generatePaths
Expand Down
2 changes: 0 additions & 2 deletions include/sliceDataStorage.h
Original file line number Diff line number Diff line change
Expand Up @@ -333,8 +333,6 @@ class SliceDataStorage : public NoCopy
std::vector<SkirtBrimLine> skirt_brim[MAX_EXTRUDERS]; //!< Skirt/brim polygons per extruder, ordered from inner to outer polygons.
Polygons support_brim; //!< brim lines for support, going from the edge of the support inward. \note Not ordered by inset.
Polygons raftOutline; // Storage for the outline of the raft. Will be filled with lines when the GCode is generated.
Polygons primeRaftOutline; // ... the raft underneath the prime-tower will have to be printed first, if there is one. (When the raft has top layers with a different extruder
// for example.)

int max_print_height_second_to_last_extruder; //!< Used in multi-extrusion: the layer number beyond which all models are printed with the same extruder
std::vector<int> max_print_height_per_extruder; //!< For each extruder the highest layer number at which it is used.
Expand Down
252 changes: 126 additions & 126 deletions src/FffGcodeWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -621,69 +621,65 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage)
const coord_t max_resolution = base_settings.get<coord_t>("meshfix_maximum_resolution");
const coord_t max_deviation = base_settings.get<coord_t>("meshfix_maximum_deviation");

std::vector<Polygons> raft_outline_paths;
if (storage.primeRaftOutline.area() > 0)
Polygons raft_outline_path = storage.raftOutline;
if (storage.primeTower.enabled)
{
raft_outline_paths.emplace_back(storage.primeRaftOutline);
raft_outline_path = raft_outline_path.unionPolygons(storage.primeTower.getOuterPoly(layer_nr));
}
raft_outline_paths.emplace_back(storage.raftOutline);

for (const Polygons& raft_outline_path : raft_outline_paths)
Infill infill_comp(
EFillMethod::LINES,
zig_zaggify_infill,
connect_polygons,
raft_outline_path,
gcode_layer.configs_storage.raft_base_config.getLineWidth(),
line_spacing,
fill_overlap,
infill_multiplier,
fill_angle,
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);
std::vector<VariableWidthLines> raft_paths;
infill_comp.generate(raft_paths, raft_polygons, raftLines, base_settings, layer_nr, SectionType::ADHESION);
if (! raft_paths.empty())
{
Infill infill_comp(
EFillMethod::LINES,
zig_zaggify_infill,
connect_polygons,
raft_outline_path,
gcode_layer.configs_storage.raft_base_config.getLineWidth(),
line_spacing,
fill_overlap,
infill_multiplier,
fill_angle,
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);
std::vector<VariableWidthLines> raft_paths;
infill_comp.generate(raft_paths, raft_polygons, raftLines, base_settings, layer_nr, SectionType::ADHESION);
if (! raft_paths.empty())
{
const GCodePathConfig& config = gcode_layer.configs_storage.raft_base_config;
const ZSeamConfig z_seam_config(EZSeamType::SHORTEST, gcode_layer.getLastPlannedPositionOrStartingPosition(), EZSeamCornerPrefType::Z_SEAM_CORNER_PREF_NONE, false);
InsetOrderOptimizer wall_orderer(
*this,
storage,
gcode_layer,
base_settings,
base_extruder_nr,
config,
config,
config,
config,
retract_before_outer_wall,
wipe_dist,
wipe_dist,
base_extruder_nr,
base_extruder_nr,
z_seam_config,
raft_paths);
wall_orderer.addToLayer();
}
gcode_layer.addLinesByOptimizer(raftLines, gcode_layer.configs_storage.raft_base_config, SpaceFillType::Lines);

raft_polygons.clear();
raftLines.clear();
const GCodePathConfig& config = gcode_layer.configs_storage.raft_base_config;
const ZSeamConfig z_seam_config(EZSeamType::SHORTEST, gcode_layer.getLastPlannedPositionOrStartingPosition(), EZSeamCornerPrefType::Z_SEAM_CORNER_PREF_NONE, false);
InsetOrderOptimizer wall_orderer(
*this,
storage,
gcode_layer,
base_settings,
base_extruder_nr,
config,
config,
config,
config,
retract_before_outer_wall,
wipe_dist,
wipe_dist,
base_extruder_nr,
base_extruder_nr,
z_seam_config,
raft_paths);
wall_orderer.addToLayer();
}
gcode_layer.addLinesByOptimizer(raftLines, gcode_layer.configs_storage.raft_base_config, SpaceFillType::Lines);

raft_polygons.clear();
raftLines.clear();

layer_plan_buffer.handle(gcode_layer, gcode);
last_planned_position = gcode_layer.getLastPlannedPositionOrStartingPosition();
Expand Down Expand Up @@ -728,11 +724,11 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage)

Application::getInstance().communication->sendLayerComplete(layer_nr, z, interface_layer_height);

std::vector<Polygons> raft_outline_paths;
Polygons raft_outline_path;
const coord_t small_offset = gcode_layer.configs_storage.raft_interface_config.getLineWidth()
/ 2; // Do this manually because of micron-movement created in corners when insetting a polygon that was offset with round joint type.
raft_outline_paths.emplace_back(storage.raftOutline.offset(-small_offset));
raft_outline_paths.back() = Simplify(interface_settings).polygon(raft_outline_paths.back()); // Remove those micron-movements.
raft_outline_path = storage.raftOutline.offset(-small_offset);
raft_outline_path = Simplify(interface_settings).polygon(raft_outline_path); // Remove those micron-movements.
const coord_t infill_outline_width = gcode_layer.configs_storage.raft_interface_config.getLineWidth();
Polygons raft_lines;
AngleDegrees fill_angle = (num_surface_layers + num_interface_layers - raft_interface_layer) % 2 ? 45 : 135; // 90 degrees rotated from the first top layer.
Expand All @@ -749,40 +745,42 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage)
constexpr int zag_skip_count = 0;
constexpr coord_t pocket_size = 0;

for (const Polygons& raft_outline_path : raft_outline_paths)
if (storage.primeTower.enabled)
{
Infill infill_comp(
EFillMethod::ZIG_ZAG,
zig_zaggify_infill,
connect_polygons,
raft_outline_path,
infill_outline_width,
interface_line_spacing,
fill_overlap,
infill_multiplier,
fill_angle,
z,
extra_infill_shift,
interface_max_resolution,
interface_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);
std::vector<VariableWidthLines> raft_paths; // Should remain empty, since we have no walls.
infill_comp.generate(raft_paths, raft_polygons, raft_lines, interface_settings, layer_nr, SectionType::ADHESION);
gcode_layer.addLinesByOptimizer(raft_lines, gcode_layer.configs_storage.raft_interface_config, SpaceFillType::Lines, false, 0, 1.0, last_planned_position);

raft_polygons.clear();
raft_lines.clear();
raft_outline_path = raft_outline_path.difference(storage.primeTower.getOuterPoly(layer_nr));
}

Infill infill_comp(
EFillMethod::ZIG_ZAG,
zig_zaggify_infill,
connect_polygons,
raft_outline_path,
infill_outline_width,
interface_line_spacing,
fill_overlap,
infill_multiplier,
fill_angle,
z,
extra_infill_shift,
interface_max_resolution,
interface_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);
std::vector<VariableWidthLines> raft_paths; // Should remain empty, since we have no walls.
infill_comp.generate(raft_paths, raft_polygons, raft_lines, interface_settings, layer_nr, SectionType::ADHESION);
gcode_layer.addLinesByOptimizer(raft_lines, gcode_layer.configs_storage.raft_interface_config, SpaceFillType::Lines, false, 0, 1.0, last_planned_position);

raft_polygons.clear();
raft_lines.clear();

setExtruder_addPrime(storage, gcode_layer, storage.primeTower.extruder_order.front());

layer_plan_buffer.handle(gcode_layer, gcode);
Expand Down Expand Up @@ -829,11 +827,11 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage)

Application::getInstance().communication->sendLayerComplete(layer_nr, z, surface_layer_height);

std::vector<Polygons> raft_outline_paths;
Polygons raft_outline_path;
const coord_t small_offset = gcode_layer.configs_storage.raft_interface_config.getLineWidth()
/ 2; // Do this manually because of micron-movement created in corners when insetting a polygon that was offset with round joint type.
raft_outline_paths.emplace_back(storage.raftOutline.offset(-small_offset));
raft_outline_paths.back() = Simplify(interface_settings).polygon(raft_outline_paths.back()); // Remove those micron-movements.
raft_outline_path = storage.raftOutline.offset(-small_offset);
raft_outline_path = Simplify(interface_settings).polygon(raft_outline_path); // Remove those micron-movements.
const coord_t infill_outline_width = gcode_layer.configs_storage.raft_interface_config.getLineWidth();
Polygons raft_lines;
AngleDegrees fill_angle
Expand All @@ -851,40 +849,42 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage)
constexpr size_t zag_skip_count = 0;
constexpr coord_t pocket_size = 0;

for (const Polygons& raft_outline_path : raft_outline_paths)
if (storage.primeTower.enabled)
{
Infill infill_comp(
EFillMethod::ZIG_ZAG,
zig_zaggify_infill,
connect_polygons,
raft_outline_path,
infill_outline_width,
surface_line_spacing,
fill_overlap,
infill_multiplier,
fill_angle,
z,
extra_infill_shift,
surface_max_resolution,
surface_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);
std::vector<VariableWidthLines> raft_paths; // Should remain empty, since we have no walls.
infill_comp.generate(raft_paths, raft_polygons, raft_lines, surface_settings, layer_nr, SectionType::ADHESION);
gcode_layer.addLinesByOptimizer(raft_lines, gcode_layer.configs_storage.raft_surface_config, SpaceFillType::Lines, false, 0, 1.0, last_planned_position);

raft_polygons.clear();
raft_lines.clear();
raft_outline_path = raft_outline_path.difference(storage.primeTower.getOuterPoly(layer_nr));
}

Infill infill_comp(
EFillMethod::ZIG_ZAG,
zig_zaggify_infill,
connect_polygons,
raft_outline_path,
infill_outline_width,
surface_line_spacing,
fill_overlap,
infill_multiplier,
fill_angle,
z,
extra_infill_shift,
surface_max_resolution,
surface_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);
std::vector<VariableWidthLines> raft_paths; // Should remain empty, since we have no walls.
infill_comp.generate(raft_paths, raft_polygons, raft_lines, surface_settings, layer_nr, SectionType::ADHESION);
gcode_layer.addLinesByOptimizer(raft_lines, gcode_layer.configs_storage.raft_surface_config, SpaceFillType::Lines, false, 0, 1.0, last_planned_position);

raft_polygons.clear();
raft_lines.clear();

setExtruder_addPrime(storage, gcode_layer, storage.primeTower.extruder_order.front());

layer_plan_buffer.handle(gcode_layer, gcode);
Expand Down
4 changes: 2 additions & 2 deletions src/FffPolygonGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -985,7 +985,7 @@ void FffPolygonGenerator::processOozeShield(SliceDataStorage& storage)
}
for (LayerIndex layer_nr = 0; layer_nr <= storage.max_print_height_second_to_last_extruder; layer_nr++)
{
storage.oozeShield[layer_nr] = storage.oozeShield[layer_nr].difference(storage.primeTower.outer_poly.offset(max_line_width / 2));
storage.oozeShield[layer_nr] = storage.oozeShield[layer_nr].difference(storage.primeTower.getOuterPoly(layer_nr).offset(max_line_width / 2));
}
}
}
Expand Down Expand Up @@ -1035,7 +1035,7 @@ void FffPolygonGenerator::processDraftShield(SliceDataStorage& storage)
max_line_width = std::max(max_line_width, extruders[extruder_nr].settings.get<coord_t>("skirt_brim_line_width"));
}
}
storage.draft_protection_shield = storage.draft_protection_shield.difference(storage.primeTower.outer_poly.offset(max_line_width / 2));
storage.draft_protection_shield = storage.draft_protection_shield.difference(storage.primeTower.getGroundPoly().offset(max_line_width / 2));
}
}

Expand Down
Loading

0 comments on commit 2dada4c

Please sign in to comment.