Skip to content

Commit

Permalink
Basically working parameterizable prime tower with base
Browse files Browse the repository at this point in the history
  • Loading branch information
wawanbreton committed Oct 10, 2023
1 parent 3dccc63 commit 5f3a1f4
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 116 deletions.
7 changes: 5 additions & 2 deletions include/PrimeTower.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,14 @@ class PrimeTower
const unsigned int number_of_prime_tower_start_locations = 21; //!< The required size of \ref PrimeTower::wipe_locations

std::vector<ExtrusionMoves> pattern_per_extruder; //!< For each extruder the pattern to print on all layers of the prime tower.
std::vector<ExtrusionMoves> pattern_extra_brim_per_layer; //!< For each layer with an extra brim, the pattern to be added
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

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,7 +102,9 @@ class PrimeTower
void subtractFromSupport(SliceDataStorage& storage);

private:
ExtrusionMoves generatePaths_extraBrim(const Polygons &outer_poly, coord_t extra_radius, coord_t line_width, bool add_inset);
ExtrusionMoves generatePaths_base(const Polygons &outer_poly, coord_t extra_radius, coord_t line_width);

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

/*!
* \see WipeTower::generatePaths
Expand Down
9 changes: 0 additions & 9 deletions include/SkirtBrim.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,15 +118,6 @@ class SkirtBrim
*/
std::vector<Offset> generateBrimOffsetPlan(std::vector<Polygons>& starting_outlines);

/*!
* In case that the models have skirt 'adhesion', but the prime tower has a brim, the covered areas are different.
*
* Since the output of this function will need to be handled differently than the rest of the adhesion lines, have a separate function.
* Specifically, for skirt an additional 'approximate convex hull' is applied to the initial 'covered area', which is detrimental to brim.
* \return An ordered list of offsets of the prime-tower to perform in the order in which they are to be performed.
*/
std::vector<Offset> generatePrimeTowerBrimForSkirtAdhesionOffsetPlan();

/*!
* Generate the primary skirt/brim of the one skirt_brim_extruder or of all extruders simultaneously.
*
Expand Down
14 changes: 0 additions & 14 deletions src/FffGcodeWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,6 @@ void FffGcodeWriter::writeGCode(SliceDataStorage& storage, TimeKeeper& time_keep

run_multiple_producers_ordered_consumer(
process_layer_starting_layer_nr,
//-Raft::getTotalExtraLayers(),
// total_layers + Raft::getFillerLayerCount() - 1,
total_layers,
[&storage, total_layers, this](int layer_nr)
{
Expand Down Expand Up @@ -687,8 +685,6 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage)
raftLines.clear();
}

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

layer_plan_buffer.handle(gcode_layer, gcode);
last_planned_position = gcode_layer.getLastPlannedPositionOrStartingPosition();
}
Expand Down Expand Up @@ -735,11 +731,6 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage)
std::vector<Polygons> raft_outline_paths;
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.
if (storage.primeRaftOutline.area() > 0)
{
raft_outline_paths.emplace_back(storage.primeRaftOutline.offset(-small_offset));
raft_outline_paths.back() = Simplify(interface_settings).polygon(raft_outline_paths.back()); // Remove those micron-movements.
}
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.
const coord_t infill_outline_width = gcode_layer.configs_storage.raft_interface_config.getLineWidth();
Expand Down Expand Up @@ -841,11 +832,6 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage)
std::vector<Polygons> raft_outline_paths;
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.
if (storage.primeRaftOutline.area() > 0)
{
raft_outline_paths.emplace_back(storage.primeRaftOutline.offset(-small_offset));
raft_outline_paths.back() = Simplify(interface_settings).polygon(raft_outline_paths.back()); // Remove those micron-movements.
}
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.
const coord_t infill_outline_width = gcode_layer.configs_storage.raft_interface_config.getLineWidth();
Expand Down
109 changes: 72 additions & 37 deletions src/PrimeTower.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,18 @@ void PrimeTower::generateGroundpoly()
middle = Point(x - tower_size / 2, y + tower_size / 2);

post_wipe_point = Point(x - tower_size / 2, y + tower_size / 2);

const bool base_enabled = mesh_group_settings.get<bool>("prime_tower_brim_enable");
const coord_t base_extra_radius = mesh_group_settings.get<coord_t>("prime_tower_base_size");
const coord_t base_height = mesh_group_settings.get<coord_t>("prime_tower_base_height");
if (base_enabled && base_extra_radius > 0 && base_height > 0)
{
footprint = outer_poly.offset(base_extra_radius);
}
else
{
footprint = outer_poly;
}
}

void PrimeTower::generatePaths(const SliceDataStorage& storage)
Expand All @@ -110,24 +122,14 @@ void PrimeTower::generatePaths(const SliceDataStorage& storage)
}
}

PrimeTower::ExtrusionMoves PrimeTower::generatePaths_extraBrim(const Polygons& outer_poly, coord_t extra_radius, coord_t line_width, bool add_inset)
PrimeTower::ExtrusionMoves PrimeTower::generatePaths_base(const Polygons& outer_poly, coord_t extra_radius, coord_t line_width)
{
const Scene& scene = Application::getInstance().current_slice->scene;
const Settings& mesh_group_settings = scene.current_mesh_group->settings;
const coord_t tower_size = mesh_group_settings.get<coord_t>("prime_tower_size");

ExtrusionMoves pattern;

if (add_inset)
{
Polygons inset = outer_poly.offset(-line_width / 2);
while (! inset.empty())
{
pattern.polygons.add(inset);
inset = inset.offset(-line_width);
}
}

int circles = 0;
Polygons outset = outer_poly.offset(line_width / 2);
while (outset.max() - outset.min() < (tower_size + extra_radius * 2))
Expand All @@ -140,15 +142,34 @@ PrimeTower::ExtrusionMoves PrimeTower::generatePaths_extraBrim(const Polygons& o
return pattern;
}

void PrimeTower::generatePaths_denseInfill()
PrimeTower::ExtrusionMoves PrimeTower::generatePaths_inset(const Polygons& outer_poly, coord_t line_width, coord_t initial_inset)
{
constexpr coord_t brim_extra_radius = 20000;
constexpr coord_t brim_extra_height = 20000;
const Scene& scene = Application::getInstance().current_slice->scene;
const Settings& mesh_group_settings = scene.current_mesh_group->settings;

ExtrusionMoves pattern;

Polygons inset = outer_poly.offset(-(initial_inset + line_width / 2));
while (! inset.empty())
{
pattern.polygons.add(inset);
inset = inset.offset(-line_width);
}

return pattern;
}

void PrimeTower::generatePaths_denseInfill()
{
const Scene& scene = Application::getInstance().current_slice->scene;
const Settings& mesh_group_settings = scene.current_mesh_group->settings;
const coord_t layer_height = mesh_group_settings.get<coord_t>("layer_height");
const bool base_enabled = mesh_group_settings.get<bool>("prime_tower_brim_enable");
const coord_t base_extra_radius = scene.settings.get<coord_t>("prime_tower_base_size");
const coord_t base_height = scene.settings.get<coord_t>("prime_tower_base_height");
const int magnitude = scene.settings.get<int>("prime_tower_base_curve_magnitude");
pattern_per_extruder.resize(extruder_count);
pattern_extra_brim_per_layer.resize(extruder_count);

coord_t cumulative_inset = 0; // Each tower shape is going to be printed inside the other. This is the inset we're doing for each extruder.
for (size_t extruder_nr : extruder_order)
Expand All @@ -173,23 +194,33 @@ void PrimeTower::generatePaths_denseInfill()
}
}

// Only the most inside extruder needs to fill the inside of the prime tower
if (extruder_nr == extruder_order.front())
// The most outside extruder is used for the base
if (base_enabled && extruder_nr == extruder_order.front())
{
// Generate the pattern for the first layer.
const coord_t line_width_layer0 = scene.extruders[extruder_nr].settings.get<coord_t>("raft_base_line_width");
ExtrusionMoves pattern_layer0 = generatePaths_extraBrim(outer_poly, brim_extra_radius, line_width_layer0, true);
pattern_extra_brim_per_layer.push_back(pattern_layer0);

for (coord_t z = layer_height; z < brim_extra_height; z += layer_height)
for (coord_t z = 0; z < base_height; z += layer_height)
{
double brim_radius_factor = std::pow((1.0 - static_cast<double>(z) / brim_extra_height), 4);
coord_t extra_radius = brim_extra_radius * brim_radius_factor;
ExtrusionMoves pattern = generatePaths_extraBrim(outer_poly, extra_radius, line_width, false);
pattern_extra_brim_per_layer.push_back(pattern);
double brim_radius_factor = std::pow((1.0 - static_cast<double>(z) / base_height), magnitude);
coord_t extra_radius = base_extra_radius * brim_radius_factor;
ExtrusionMoves pattern = generatePaths_base(outer_poly, extra_radius, line_width);
if (pattern.polygons.empty() && pattern.lines.empty())
{
break;
}
pattern_extra_brim_per_layer[extruder_nr].push_back(pattern);
}
}

cumulative_inset += wall_nr * line_width;

// Only the most inside extruder needs to fill the inside of the prime tower
if (extruder_nr == extruder_order.back())
{
ExtrusionMoves pattern = generatePaths_inset(outer_poly, line_width, cumulative_inset);
if (! pattern.polygons.empty() || ! pattern.lines.empty())
{
pattern_extra_brim_per_layer[extruder_nr].push_back(pattern);
}
}
}
}

Expand All @@ -215,7 +246,7 @@ void PrimeTower::addToGcode(const SliceDataStorage& storage, LayerPlan& gcode_la
}

const LayerIndex layer_nr = gcode_layer.getLayerNr();
if (/*layer_nr < 0 ||*/ layer_nr > storage.max_print_height_second_to_last_extruder + 1)
if (layer_nr > storage.max_print_height_second_to_last_extruder + 1)
{
return;
}
Expand Down Expand Up @@ -252,26 +283,30 @@ void PrimeTower::addToGcode(const SliceDataStorage& storage, LayerPlan& gcode_la

void PrimeTower::addToGcode_denseInfill(LayerPlan& gcode_layer, const size_t extruder_nr) const
{
LayerIndex absolute_layer_number = gcode_layer.getLayerNr() + Raft::getTotalExtraLayers();
assert(absolute_layer_number >= 0);
const Settings& mesh_group_settings = Application::getInstance().current_slice->scene.current_mesh_group->settings;
const ExtruderTrain& base_train = mesh_group_settings.get<ExtruderTrain&>("raft_base_extruder_nr");
const bool adhesion_raft = base_train.settings.get<EPlatformAdhesion>("adhesion_type") == EPlatformAdhesion::RAFT;
LayerIndex absolute_layer_number = gcode_layer.getLayerNr();
if (adhesion_raft)
{
absolute_layer_number += Raft::getTotalExtraLayers();
}

if (absolute_layer_number > 0)
if (! adhesion_raft || absolute_layer_number > 0)
{
// Actual prime pattern
const GCodePathConfig& config = gcode_layer.configs_storage.prime_tower_config_per_extruder[extruder_nr];

const ExtrusionMoves& pattern = pattern_per_extruder[extruder_nr];
gcode_layer.addPolygonsByOptimizer(pattern.polygons, config);
gcode_layer.addLinesByOptimizer(pattern.lines, config, SpaceFillType::Lines);
}

if (absolute_layer_number < pattern_extra_brim_per_layer.size() && extruder_nr == extruder_order.front())
const std::vector<ExtrusionMoves>& pattern_extra_brim = pattern_extra_brim_per_layer[extruder_nr];
if (absolute_layer_number < pattern_extra_brim.size())
{
// Specific case for first layer => very high adhesion
const GCodePathConfig& config
= absolute_layer_number == 0 ? gcode_layer.configs_storage.raft_base_config : gcode_layer.configs_storage.prime_tower_config_per_extruder[extruder_nr];

const ExtrusionMoves& pattern = pattern_extra_brim_per_layer[absolute_layer_number];
// Extra rings for stronger base
const GCodePathConfig& config = gcode_layer.configs_storage.prime_tower_config_per_extruder[extruder_nr];
const ExtrusionMoves& pattern = pattern_extra_brim[absolute_layer_number];
gcode_layer.addPolygonsByOptimizer(pattern.polygons, config);
gcode_layer.addLinesByOptimizer(pattern.lines, config, SpaceFillType::Lines);
}
Expand Down
49 changes: 4 additions & 45 deletions src/SkirtBrim.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,39 +110,15 @@ std::vector<SkirtBrim::Offset> SkirtBrim::generateBrimOffsetPlan(std::vector<Pol
return all_brim_offsets;
}

std::vector<SkirtBrim::Offset> SkirtBrim::generatePrimeTowerBrimForSkirtAdhesionOffsetPlan()
{
std::vector<Offset> prime_brim_offsets;

const Settings& global_settings = Application::getInstance().current_slice->scene.current_mesh_group->settings;
const bool prime_tower_brim_enable = global_settings.get<bool>("prime_tower_brim_enable");
if (adhesion_type == EPlatformAdhesion::SKIRT && prime_tower_brim_enable && storage.primeTower.enabled)
{
const int extruder_nr = storage.primeTower.extruder_order[0];
const ExtruderTrain& extruder = extruders[extruder_nr];
int line_count = extruder.settings.get<int>("brim_line_count");
coord_t gap = extruder.settings.get<coord_t>("brim_gap");
for (int line_idx = 0; line_idx < line_count; line_idx++)
{
const bool is_last = line_idx == line_count - 1;
coord_t offset = gap + line_widths[extruder_nr] / 2 + line_widths[extruder_nr] * line_idx;
prime_brim_offsets.emplace_back(&storage.primeTower.outer_poly, external_polys_only[extruder_nr], offset, offset, line_idx, extruder_nr, is_last);
}
}

std::sort(prime_brim_offsets.begin(), prime_brim_offsets.end(), OffsetSorter);
return prime_brim_offsets;
}

void SkirtBrim::generate()
{
std::vector<Polygons> starting_outlines(extruder_count);
std::vector<Offset> all_brim_offsets = generateBrimOffsetPlan(starting_outlines);
std::vector<Offset> prime_brim_offsets_for_skirt = generatePrimeTowerBrimForSkirtAdhesionOffsetPlan();

constexpr LayerIndex layer_nr = 0;
constexpr bool include_support = true;
Polygons covered_area = storage.getLayerOutlines(layer_nr, include_support, /*include_prime_tower*/ true, /*external_polys_only*/ false);
const bool include_prime_tower = adhesion_type == EPlatformAdhesion::SKIRT;
Polygons covered_area = storage.getLayerOutlines(layer_nr, include_support, include_prime_tower, /*external_polys_only*/ false);

std::vector<Polygons> allowed_areas_per_extruder(extruder_count);
for (int extruder_nr = 0; extruder_nr < extruder_count; extruder_nr++)
Expand All @@ -161,14 +137,6 @@ void SkirtBrim::generate()
}
}

// Note that the brim generated here for the prime-tower is _only_ when the rest if the model uses skirt.
// If everything uses brim to begin with, _including_ the prime-tower, it's not generated here, but along the rest.
if (! prime_brim_offsets_for_skirt.empty())
{
// Note that his ignores the returned lengths: Less 'correct' in a sense, will be predictable for the user.
generatePrimaryBrim(prime_brim_offsets_for_skirt, covered_area, allowed_areas_per_extruder);
}

// Apply 'approximate convex hull' if the adhesion is skirt _after_ any skirt but also prime-tower-brim adhesion.
// Otherwise, the now expanded convex hull covered areas will mess with that brim. Fortunately this does not mess
// with the other area calculation above, since they are either itself a simple/convex shape or relevant for brim.
Expand Down Expand Up @@ -406,12 +374,7 @@ Polygons SkirtBrim::getFirstLayerOutline(const int extruder_nr /* = -1 */)

if (skirt_around_prime_tower_brim)
{
const int prime_tower_brim_extruder_nr = storage.primeTower.extruder_order[0];
const ExtruderTrain& prime_tower_brim_extruder = extruders[prime_tower_brim_extruder_nr];
int line_count = prime_tower_brim_extruder.settings.get<int>("brim_line_count");
coord_t tower_gap = prime_tower_brim_extruder.settings.get<coord_t>("brim_gap");
coord_t brim_width = tower_gap + line_count * line_widths[prime_tower_brim_extruder_nr];
first_layer_outline = first_layer_outline.unionPolygons(storage.primeTower.outer_poly.offset(brim_width));
first_layer_outline = first_layer_outline.unionPolygons(storage.primeTower.footprint);
}

Polygons shields;
Expand All @@ -435,7 +398,7 @@ Polygons SkirtBrim::getFirstLayerOutline(const int extruder_nr /* = -1 */)
else
{ // add brim underneath support by removing support where there's brim around the model
constexpr bool include_support = false; // Include manually below.
constexpr bool include_prime_tower = false; // Include manually below.
constexpr bool include_prime_tower = false; // Not included.
constexpr bool external_outlines_only = false; // Remove manually below.
first_layer_outline = storage.getLayerOutlines(layer_nr, include_support, include_prime_tower, external_outlines_only, extruder_nr);
first_layer_outline = first_layer_outline.unionPolygons(); // To guard against overlapping outlines, which would produce holes according to the even-odd rule.
Expand Down Expand Up @@ -480,10 +443,6 @@ Polygons SkirtBrim::getFirstLayerOutline(const int extruder_nr /* = -1 */)
first_layer_outline.add(support_layer.support_bottom);
first_layer_outline.add(support_layer.support_roof);
}
if (storage.primeTower.enabled && global_settings.get<bool>("prime_tower_brim_enable") && (extruder_nr == -1 || int(storage.primeTower.extruder_order[0]) == extruder_nr))
{
first_layer_outline.add(storage.primeTower.outer_poly); // don't remove parts of the prime tower, but make a brim for it
}
}
constexpr coord_t join_distance = 20;
first_layer_outline = first_layer_outline.offset(join_distance).offset(-join_distance); // merge adjacent models into single polygon
Expand Down
Loading

0 comments on commit 5f3a1f4

Please sign in to comment.