mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-07-30 03:52:01 +08:00
Refactor process layer single object
This commit is contained in:
parent
a321a97f36
commit
dca7318896
@ -2341,7 +2341,6 @@ std::vector<GCode::ExtrusionOrder::ExtruderExtrusions> GCodeGenerator::get_sorte
|
|||||||
} else if (auto path = dynamic_cast<const ExtrusionPath *>(extrusion_entity)) {
|
} else if (auto path = dynamic_cast<const ExtrusionPath *>(extrusion_entity)) {
|
||||||
result = GCode::SmoothPath{GCode::SmoothPathElement{path->attributes(), smooth_path_caches.layer_local().resolve_or_fit(*path, extrusion_reference.flipped(), m_scaled_resolution)}};
|
result = GCode::SmoothPath{GCode::SmoothPathElement{path->attributes(), smooth_path_caches.layer_local().resolve_or_fit(*path, extrusion_reference.flipped(), m_scaled_resolution)}};
|
||||||
}
|
}
|
||||||
|
|
||||||
using GCode::SmoothPathElement;
|
using GCode::SmoothPathElement;
|
||||||
for (auto it{result.rbegin()}; it != result.rend(); ++it) {
|
for (auto it{result.rbegin()}; it != result.rend(); ++it) {
|
||||||
if (!it->path.empty()) {
|
if (!it->path.empty()) {
|
||||||
@ -2379,6 +2378,7 @@ std::vector<GCode::ExtrusionOrder::ExtruderExtrusions> GCodeGenerator::get_sorte
|
|||||||
return extrusions;
|
return extrusions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// In sequential mode, process_layer is called once per each object and its copy,
|
// In sequential mode, process_layer is called once per each object and its copy,
|
||||||
// therefore layers will contain a single entry and single_object_instance_idx will point to the copy of the object.
|
// therefore layers will contain a single entry and single_object_instance_idx will point to the copy of the object.
|
||||||
// In non-sequential mode, process_layer is called per each print_z height with all object and support layers accumulated.
|
// In non-sequential mode, process_layer is called per each print_z height with all object and support layers accumulated.
|
||||||
@ -2454,7 +2454,7 @@ LayerResult GCodeGenerator::process_layer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
using GCode::ExtrusionOrder::ExtruderExtrusions;
|
using GCode::ExtrusionOrder::ExtruderExtrusions;
|
||||||
std::vector<ExtruderExtrusions> extrusions{
|
const std::vector<ExtruderExtrusions> extrusions{
|
||||||
this->get_sorted_extrusions(print, layers, layer_tools, instances_to_print, smooth_path_caches, first_layer)};
|
this->get_sorted_extrusions(print, layers, layer_tools, instances_to_print, smooth_path_caches, first_layer)};
|
||||||
|
|
||||||
std::string gcode;
|
std::string gcode;
|
||||||
@ -2586,7 +2586,7 @@ LayerResult GCodeGenerator::process_layer(
|
|||||||
gcode += this->extrude_skirt(smooth_path,
|
gcode += this->extrude_skirt(smooth_path,
|
||||||
// Override of skirt extrusion parameters. extrude_skirt() will fill in the extrusion width.
|
// Override of skirt extrusion parameters. extrude_skirt() will fill in the extrusion width.
|
||||||
ExtrusionFlow{ mm3_per_mm, 0., layer_skirt_flow.height() },
|
ExtrusionFlow{ mm3_per_mm, 0., layer_skirt_flow.height() },
|
||||||
smooth_path_caches.global(), "skirt"sv, m_config.support_material_speed.value);
|
"skirt"sv, m_config.support_material_speed.value);
|
||||||
}
|
}
|
||||||
m_avoid_crossing_perimeters.use_external_mp(false);
|
m_avoid_crossing_perimeters.use_external_mp(false);
|
||||||
// Allow a straight travel move to the first object point if this is the first layer (but don't in next layers).
|
// Allow a straight travel move to the first object point if this is the first layer (but don't in next layers).
|
||||||
@ -2604,7 +2604,9 @@ LayerResult GCodeGenerator::process_layer(
|
|||||||
this->set_origin(0., 0.);
|
this->set_origin(0., 0.);
|
||||||
m_avoid_crossing_perimeters.use_external_mp();
|
m_avoid_crossing_perimeters.use_external_mp();
|
||||||
|
|
||||||
gcode += this->extrude_brim(extruder_extrusions.brim, "brim", m_config.support_material_speed.value);
|
for (const GCode::ExtrusionOrder::BrimPath &brim_path : extruder_extrusions.brim) {
|
||||||
|
gcode += this->extrude_smooth_path(brim_path.path, brim_path.is_loop, "brim", m_config.support_material_speed.value);
|
||||||
|
}
|
||||||
m_avoid_crossing_perimeters.use_external_mp(false);
|
m_avoid_crossing_perimeters.use_external_mp(false);
|
||||||
// Allow a straight travel move to the first object point.
|
// Allow a straight travel move to the first object point.
|
||||||
m_avoid_crossing_perimeters.disable_once();
|
m_avoid_crossing_perimeters.disable_once();
|
||||||
@ -2616,10 +2618,14 @@ LayerResult GCodeGenerator::process_layer(
|
|||||||
size_t gcode_size_old = gcode.size();
|
size_t gcode_size_old = gcode.size();
|
||||||
for (std::size_t i{0}; i < instances_to_print.size(); ++i) {
|
for (std::size_t i{0}; i < instances_to_print.size(); ++i) {
|
||||||
const InstanceToPrint &instance{instances_to_print[i]};
|
const InstanceToPrint &instance{instances_to_print[i]};
|
||||||
|
const std::vector<SliceExtrusions> overriden_extrusions{extruder_extrusions.overriden_extrusions[i]};
|
||||||
this->process_layer_single_object(
|
if (is_empty(overriden_extrusions)) {
|
||||||
gcode, instance, layers[instance.object_layer_to_print_id],
|
continue;
|
||||||
smooth_path_caches.layer_local(), {}, extruder_extrusions.overriden_extrusions[i]
|
}
|
||||||
|
this->initialize_layer(instance, layers[instance.object_layer_to_print_id]);
|
||||||
|
gcode += this->extrude_slices(
|
||||||
|
instance, layers[instance.object_layer_to_print_id],
|
||||||
|
overriden_extrusions
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (gcode_size_old < gcode.size()) {
|
if (gcode_size_old < gcode.size()) {
|
||||||
@ -2630,16 +2636,29 @@ LayerResult GCodeGenerator::process_layer(
|
|||||||
// Extrude normal extrusions.
|
// Extrude normal extrusions.
|
||||||
for (std::size_t i{0}; i < instances_to_print.size(); ++i) {
|
for (std::size_t i{0}; i < instances_to_print.size(); ++i) {
|
||||||
const InstanceToPrint &instance{instances_to_print[i]};
|
const InstanceToPrint &instance{instances_to_print[i]};
|
||||||
|
using GCode::ExtrusionOrder::SupportPath;
|
||||||
|
const std::vector<SupportPath> &support_extrusions{extruder_extrusions.normal_extrusions[i].support_extrusions};
|
||||||
|
const ObjectLayerToPrint &layer_to_print{layers[instance.object_layer_to_print_id]};
|
||||||
|
const std::vector<SliceExtrusions> &slices_extrusions{extruder_extrusions.normal_extrusions[i].slices_extrusions};
|
||||||
|
|
||||||
this->process_layer_single_object(
|
if (support_extrusions.empty() && is_empty(slices_extrusions)) {
|
||||||
gcode, instance, layers[instance.object_layer_to_print_id],
|
continue;
|
||||||
smooth_path_caches.layer_local(), extruder_extrusions.normal_extrusions[i].support_extrusions,
|
}
|
||||||
extruder_extrusions.normal_extrusions[i].slices_extrusions
|
|
||||||
|
this->initialize_layer(instance, layers[instance.object_layer_to_print_id]);
|
||||||
|
|
||||||
|
if (!support_extrusions.empty()) {
|
||||||
|
m_layer = layer_to_print.support_layer;
|
||||||
|
m_object_layer_over_raft = false;
|
||||||
|
gcode += this->extrude_support(support_extrusions);
|
||||||
|
}
|
||||||
|
|
||||||
|
gcode += this->extrude_slices(
|
||||||
|
instance, layer_to_print, slices_extrusions
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// During layer change the starting position of next layer is now known.
|
// During layer change the starting position of next layer is now known.
|
||||||
// The solution is thus to emplace a temporary tag to the gcode, cache the postion and
|
// The solution is thus to emplace a temporary tag to the gcode, cache the postion and
|
||||||
// replace the tag later. The tag is Layer_Change_Travel, the cached position is
|
// replace the tag later. The tag is Layer_Change_Travel, the cached position is
|
||||||
@ -2717,29 +2736,14 @@ LayerResult GCodeGenerator::process_layer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const auto comment_perimeter = "perimeter"sv;
|
static const auto comment_perimeter = "perimeter"sv;
|
||||||
// Comparing string_view pointer & length for speed.
|
|
||||||
static inline bool comment_is_perimeter(const std::string_view comment) {
|
|
||||||
return comment.data() == comment_perimeter.data() && comment.size() == comment_perimeter.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GCodeGenerator::process_layer_single_object(
|
void GCodeGenerator::initialize_layer(
|
||||||
std::string &gcode,
|
|
||||||
const InstanceToPrint &print_instance,
|
const InstanceToPrint &print_instance,
|
||||||
const ObjectLayerToPrint &layer_to_print,
|
const ObjectLayerToPrint &layer_to_print
|
||||||
const GCode::SmoothPathCache &smooth_path_cache,
|
|
||||||
const ExtrusionEntityReferences &support_extrusions,
|
|
||||||
const std::vector<SliceExtrusions> &slices_extrusions
|
|
||||||
) {
|
) {
|
||||||
const PrintObject &print_object = print_instance.print_object;
|
const PrintObject &print_object = print_instance.print_object;
|
||||||
const Print &print = *print_object.print();
|
const Print &print = *print_object.print();
|
||||||
|
|
||||||
bool first = true;
|
|
||||||
// Delay layer initialization as many layers may not print with all extruders.
|
|
||||||
auto init_layer_delayed = [this, &print_instance, &layer_to_print, &first]() {
|
|
||||||
if (first) {
|
|
||||||
first = false;
|
|
||||||
const PrintObject &print_object = print_instance.print_object;
|
|
||||||
const Print &print = *print_object.print();
|
|
||||||
m_config.apply(print_object.config(), true);
|
m_config.apply(print_object.config(), true);
|
||||||
m_layer = layer_to_print.layer();
|
m_layer = layer_to_print.layer();
|
||||||
if (print.config().avoid_crossing_perimeters)
|
if (print.config().avoid_crossing_perimeters)
|
||||||
@ -2753,49 +2757,37 @@ void GCodeGenerator::process_layer_single_object(
|
|||||||
m_current_instance = next_instance;
|
m_current_instance = next_instance;
|
||||||
this->set_origin(unscale(offset));
|
this->set_origin(unscale(offset));
|
||||||
m_label_objects.update(&print_instance.print_object.instances()[print_instance.instance_id]);
|
m_label_objects.update(&print_instance.print_object.instances()[print_instance.instance_id]);
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
if (!support_extrusions.empty()) {
|
std::string GCodeGenerator::extrude_slices(
|
||||||
init_layer_delayed();
|
const InstanceToPrint &print_instance,
|
||||||
m_layer = layer_to_print.support_layer;
|
const ObjectLayerToPrint &layer_to_print,
|
||||||
m_object_layer_over_raft = false;
|
const std::vector<SliceExtrusions> &slices_extrusions
|
||||||
gcode += this->extrude_support(support_extrusions, smooth_path_cache);
|
) {
|
||||||
}
|
const PrintObject &print_object = print_instance.print_object;
|
||||||
|
const Print &print = *print_object.print();
|
||||||
|
|
||||||
m_layer = layer_to_print.layer();
|
m_layer = layer_to_print.layer();
|
||||||
// To control print speed of the 1st object layer printed over raft interface.
|
// To control print speed of the 1st object layer printed over raft interface.
|
||||||
m_object_layer_over_raft = layer_to_print.object_layer && layer_to_print.object_layer->id() > 0 &&
|
m_object_layer_over_raft = layer_to_print.object_layer && layer_to_print.object_layer->id() > 0 &&
|
||||||
print_object.slicing_parameters().raft_layers() == layer_to_print.object_layer->id();
|
print_object.slicing_parameters().raft_layers() == layer_to_print.object_layer->id();
|
||||||
|
|
||||||
|
std::string gcode;
|
||||||
for (const SliceExtrusions &slice_extrusions : slices_extrusions) {
|
for (const SliceExtrusions &slice_extrusions : slices_extrusions) {
|
||||||
for (const IslandExtrusions &island_extrusions : slice_extrusions.common_extrusions) {
|
for (const IslandExtrusions &island_extrusions : slice_extrusions.common_extrusions) {
|
||||||
if (print.config().infill_first) {
|
if (print.config().infill_first) {
|
||||||
if (!island_extrusions.infill_ranges.empty()) {
|
gcode += this->extrude_infill_ranges(island_extrusions.infill_ranges, "infill");
|
||||||
init_layer_delayed();
|
gcode += this->extrude_perimeters(*island_extrusions.region, island_extrusions.perimeters, print_instance);
|
||||||
}
|
|
||||||
gcode += this->extrude_infill_ranges(island_extrusions.infill_ranges, "infill", smooth_path_cache);
|
|
||||||
if (!island_extrusions.perimeters.empty()) {
|
|
||||||
init_layer_delayed();
|
|
||||||
}
|
|
||||||
gcode += this->extrude_perimeters(print, *island_extrusions.region, island_extrusions.perimeters, print_instance, smooth_path_cache);
|
|
||||||
} else {
|
} else {
|
||||||
if (!island_extrusions.perimeters.empty()) {
|
gcode += this->extrude_perimeters(*island_extrusions.region, island_extrusions.perimeters, print_instance);
|
||||||
init_layer_delayed();
|
gcode += this->extrude_infill_ranges(island_extrusions.infill_ranges, "infill");
|
||||||
}
|
|
||||||
gcode += this->extrude_perimeters(print, *island_extrusions.region, island_extrusions.perimeters, print_instance, smooth_path_cache);
|
|
||||||
if (!island_extrusions.infill_ranges.empty()) {
|
|
||||||
init_layer_delayed();
|
|
||||||
}
|
|
||||||
gcode += this->extrude_infill_ranges(island_extrusions.infill_ranges, "infill", smooth_path_cache);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!slice_extrusions.ironing_extrusions.empty()) {
|
gcode += this->extrude_infill_ranges(slice_extrusions.ironing_extrusions, "ironing");
|
||||||
init_layer_delayed();
|
|
||||||
}
|
|
||||||
gcode += this->extrude_infill_ranges(slice_extrusions.ironing_extrusions, "ironing", smooth_path_cache);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return gcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GCodeGenerator::apply_print_config(const PrintConfig &print_config)
|
void GCodeGenerator::apply_print_config(const PrintConfig &print_config)
|
||||||
@ -2924,137 +2916,64 @@ static inline bool validate_smooth_path(const GCode::SmoothPath &smooth_path, bo
|
|||||||
}
|
}
|
||||||
#endif //NDEBUG
|
#endif //NDEBUG
|
||||||
|
|
||||||
std::string GCodeGenerator::extrude_perimeter(
|
std::string GCodeGenerator::extrude_smooth_path(
|
||||||
const GCode::ExtrusionOrder::Perimeter &perimeter, const std::string_view description
|
const GCode::SmoothPath &smooth_path, const bool is_loop, const std::string_view description, const double speed
|
||||||
) {
|
) {
|
||||||
double speed{-1};
|
|
||||||
// Apply the small perimeter speed.
|
|
||||||
if (perimeter.extrusion_entity->length() <= SMALL_PERIMETER_LENGTH)
|
|
||||||
speed = m_config.small_perimeter_speed.get_abs_value(m_config.perimeter_speed);
|
|
||||||
|
|
||||||
// Extrude along the smooth path.
|
// Extrude along the smooth path.
|
||||||
std::string gcode;
|
std::string gcode;
|
||||||
for (const GCode::SmoothPathElement &el : perimeter.smooth_path)
|
for (const GCode::SmoothPathElement &el : smooth_path)
|
||||||
gcode += this->_extrude(el.path_attributes, el.path, description, speed);
|
gcode += this->_extrude(el.path_attributes, el.path, description, speed);
|
||||||
|
|
||||||
// reset acceleration
|
// reset acceleration
|
||||||
gcode += m_writer.set_print_acceleration(fast_round_up<unsigned int>(m_config.default_acceleration.value));
|
gcode += m_writer.set_print_acceleration(fast_round_up<unsigned int>(m_config.default_acceleration.value));
|
||||||
|
|
||||||
if (m_wipe.enabled()) {
|
if (is_loop) {
|
||||||
// Wipe will hide the seam.
|
m_wipe.set_path(GCode::SmoothPath{smooth_path});
|
||||||
m_wipe.set_path(GCode::SmoothPath{perimeter.smooth_path});
|
} else {
|
||||||
} else if (perimeter.extrusion_entity->role().is_external_perimeter() && m_layer != nullptr && m_config.perimeters.value > 1) {
|
GCode::SmoothPath reversed_smooth_path{smooth_path};
|
||||||
// Only wipe inside if the wipe along the perimeter is disabled.
|
GCode::reverse(reversed_smooth_path);
|
||||||
// Make a little move inwards before leaving loop.
|
m_wipe.set_path(std::move(reversed_smooth_path));
|
||||||
if (std::optional<Point> pt = wipe_hide_seam(perimeter.smooth_path, perimeter.reversed, scale_(EXTRUDER_CONFIG(nozzle_diameter))); pt) {
|
|
||||||
// Generate the seam hiding travel move.
|
|
||||||
gcode += m_writer.travel_to_xy(this->point_to_gcode(*pt), "move inwards before travel");
|
|
||||||
this->last_position = *pt;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return gcode;
|
return gcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GCodeGenerator::extrude_skirt(
|
std::string GCodeGenerator::extrude_skirt(
|
||||||
GCode::SmoothPath smooth_path, const ExtrusionFlow &extrusion_flow_override,
|
GCode::SmoothPath smooth_path, const ExtrusionFlow &extrusion_flow_override,
|
||||||
const GCode::SmoothPathCache &smooth_path_cache, const std::string_view description, double speed)
|
const std::string_view description, double speed)
|
||||||
{
|
{
|
||||||
|
|
||||||
// Extrude along the smooth path.
|
// Extrude along the smooth path.
|
||||||
std::string gcode;
|
std::string gcode;
|
||||||
for (GCode::SmoothPathElement &el : smooth_path) {
|
for (GCode::SmoothPathElement &el : smooth_path) {
|
||||||
// Override extrusion parameters.
|
// Override extrusion parameters.
|
||||||
el.path_attributes.mm3_per_mm = extrusion_flow_override.mm3_per_mm;
|
el.path_attributes.mm3_per_mm = extrusion_flow_override.mm3_per_mm;
|
||||||
el.path_attributes.height = extrusion_flow_override.height;
|
el.path_attributes.height = extrusion_flow_override.height;
|
||||||
gcode += this->_extrude(el.path_attributes, el.path, description, speed);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset acceleration
|
gcode += this->extrude_smooth_path(smooth_path, true, description, m_config.support_material_speed.value);
|
||||||
gcode += m_writer.set_print_acceleration(fast_round_up<unsigned int>(m_config.default_acceleration.value));
|
|
||||||
|
|
||||||
if (m_wipe.enabled())
|
|
||||||
// Wipe will hide the seam.
|
|
||||||
m_wipe.set_path(std::move(smooth_path));
|
|
||||||
|
|
||||||
return gcode;
|
return gcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GCodeGenerator::extrude_brim(
|
|
||||||
const std::vector<GCode::ExtrusionOrder::BrimPath> &brim,
|
|
||||||
const std::string &extrusion_name,
|
|
||||||
const double speed
|
|
||||||
) {
|
|
||||||
std::string gcode{};
|
|
||||||
|
|
||||||
for (const auto &[path, is_loop] : brim) {
|
|
||||||
// extrude along the path
|
|
||||||
for (const GCode::SmoothPathElement &el : path)
|
|
||||||
gcode += this->_extrude(el.path_attributes, el.path, extrusion_name, speed);
|
|
||||||
|
|
||||||
|
|
||||||
// reset acceleration
|
|
||||||
gcode += m_writer.set_print_acceleration((unsigned int)floor(m_config.default_acceleration.value + 0.5));
|
|
||||||
|
|
||||||
if (is_loop) {
|
|
||||||
m_wipe.set_path(GCode::SmoothPath{path});
|
|
||||||
} else {
|
|
||||||
GCode::SmoothPath reversed_smooth_path{path};
|
|
||||||
GCode::reverse(reversed_smooth_path);
|
|
||||||
m_wipe.set_path(std::move(reversed_smooth_path));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return gcode;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::string GCodeGenerator::extrude_infill_range(
|
|
||||||
const std::vector<GCode::SmoothPath> &infill_range,
|
|
||||||
const PrintRegion ®ion,
|
|
||||||
const std::string &extrusion_name,
|
|
||||||
const GCode::SmoothPathCache &smooth_path_cache
|
|
||||||
) {
|
|
||||||
std::string gcode{};
|
|
||||||
|
|
||||||
if (!infill_range.empty()) {
|
|
||||||
this->m_config.apply(region.config());
|
|
||||||
|
|
||||||
for (const GCode::SmoothPath &path : infill_range) {
|
|
||||||
// extrude along the path
|
|
||||||
for (const GCode::SmoothPathElement &el : path)
|
|
||||||
gcode += this->_extrude(el.path_attributes, el.path, extrusion_name);
|
|
||||||
|
|
||||||
GCode::SmoothPath reversed_smooth_path{path};
|
|
||||||
GCode::reverse(reversed_smooth_path);
|
|
||||||
m_wipe.set_path(std::move(reversed_smooth_path));
|
|
||||||
|
|
||||||
// reset acceleration
|
|
||||||
gcode += m_writer.set_print_acceleration((unsigned int)floor(m_config.default_acceleration.value + 0.5));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return gcode;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::string GCodeGenerator::extrude_infill_ranges(
|
std::string GCodeGenerator::extrude_infill_ranges(
|
||||||
const std::vector<InfillRange> &infill_ranges,
|
const std::vector<InfillRange> &infill_ranges,
|
||||||
const std::string &comment,
|
const std::string &comment
|
||||||
const GCode::SmoothPathCache &smooth_path_cache
|
|
||||||
) {
|
) {
|
||||||
std::string gcode{};
|
std::string gcode{};
|
||||||
for (const InfillRange &infill_range : infill_ranges) {
|
for (const InfillRange &infill_range : infill_ranges) {
|
||||||
gcode += this->extrude_infill_range(
|
if (!infill_range.items.empty()) {
|
||||||
infill_range.items, *infill_range.region, comment, smooth_path_cache
|
this->m_config.apply(infill_range.region->config());
|
||||||
);
|
for (const GCode::SmoothPath &path : infill_range.items) {
|
||||||
|
gcode += this->extrude_smooth_path(path, false, comment, -1.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return gcode;
|
return gcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GCodeGenerator::extrude_perimeters(
|
std::string GCodeGenerator::extrude_perimeters(
|
||||||
const Print &print,
|
|
||||||
const PrintRegion ®ion,
|
const PrintRegion ®ion,
|
||||||
const std::vector<GCode::ExtrusionOrder::Perimeter> &perimeters,
|
const std::vector<GCode::ExtrusionOrder::Perimeter> &perimeters,
|
||||||
const InstanceToPrint &print_instance,
|
const InstanceToPrint &print_instance
|
||||||
const GCode::SmoothPathCache &smooth_path_cache
|
|
||||||
) {
|
) {
|
||||||
if (!perimeters.empty()) {
|
if (!perimeters.empty()) {
|
||||||
m_config.apply(region.config());
|
m_config.apply(region.config());
|
||||||
@ -3063,80 +2982,41 @@ std::string GCodeGenerator::extrude_perimeters(
|
|||||||
std::string gcode{};
|
std::string gcode{};
|
||||||
|
|
||||||
for (const GCode::ExtrusionOrder::Perimeter &perimeter : perimeters) {
|
for (const GCode::ExtrusionOrder::Perimeter &perimeter : perimeters) {
|
||||||
// Don't reorder, don't flip.
|
double speed{-1};
|
||||||
gcode += this->extrude_perimeter(perimeter, comment_perimeter);
|
// Apply the small perimeter speed.
|
||||||
|
if (perimeter.extrusion_entity->length() <= SMALL_PERIMETER_LENGTH)
|
||||||
|
speed = m_config.small_perimeter_speed.get_abs_value(m_config.perimeter_speed);
|
||||||
|
gcode += this->extrude_smooth_path(perimeter.smooth_path, true, comment_perimeter, speed);
|
||||||
this->m_travel_obstacle_tracker.mark_extruded(
|
this->m_travel_obstacle_tracker.mark_extruded(
|
||||||
perimeter.extrusion_entity, print_instance.object_layer_to_print_id, print_instance.instance_id
|
perimeter.extrusion_entity, print_instance.object_layer_to_print_id, print_instance.instance_id
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (!m_wipe.enabled() && perimeter.extrusion_entity->role().is_external_perimeter() && m_layer != nullptr && m_config.perimeters.value > 1) {
|
||||||
|
// Only wipe inside if the wipe along the perimeter is disabled.
|
||||||
|
// Make a little move inwards before leaving loop.
|
||||||
|
if (std::optional<Point> pt = wipe_hide_seam(perimeter.smooth_path, perimeter.reversed, scale_(EXTRUDER_CONFIG(nozzle_diameter))); pt) {
|
||||||
|
// Generate the seam hiding travel move.
|
||||||
|
gcode += m_writer.travel_to_xy(this->point_to_gcode(*pt), "move inwards before travel");
|
||||||
|
this->last_position = *pt;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return gcode;
|
return gcode;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string GCodeGenerator::extrude_multi_path(const ExtrusionMultiPath &multipath, bool reverse, const GCode::SmoothPathCache &smooth_path_cache, const std::string_view description, double speed)
|
std::string GCodeGenerator::extrude_support(const std::vector<GCode::ExtrusionOrder::SupportPath> &support_extrusions)
|
||||||
{
|
|
||||||
#ifndef NDEBUG
|
|
||||||
for (auto it = std::next(multipath.paths.begin()); it != multipath.paths.end(); ++ it) {
|
|
||||||
assert(it->polyline.points.size() >= 2);
|
|
||||||
assert(std::prev(it)->polyline.last_point() == it->polyline.first_point());
|
|
||||||
}
|
|
||||||
#endif // NDEBUG
|
|
||||||
GCode::SmoothPath smooth_path = smooth_path_cache.resolve_or_fit(multipath, reverse, m_scaled_resolution);
|
|
||||||
|
|
||||||
// extrude along the path
|
|
||||||
std::string gcode;
|
|
||||||
for (GCode::SmoothPathElement &el : smooth_path)
|
|
||||||
gcode += this->_extrude(el.path_attributes, el.path, description, speed);
|
|
||||||
|
|
||||||
GCode::reverse(smooth_path);
|
|
||||||
m_wipe.set_path(std::move(smooth_path));
|
|
||||||
|
|
||||||
// reset acceleration
|
|
||||||
gcode += m_writer.set_print_acceleration((unsigned int)floor(m_config.default_acceleration.value + 0.5));
|
|
||||||
return gcode;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string GCodeGenerator::extrude_path(const ExtrusionPath &path, bool reverse, const GCode::SmoothPathCache &smooth_path_cache, std::string_view description, double speed)
|
|
||||||
{
|
|
||||||
Geometry::ArcWelder::Path smooth_path = smooth_path_cache.resolve_or_fit(path, reverse, m_scaled_resolution);
|
|
||||||
std::string gcode = this->_extrude(path.attributes(), smooth_path, description, speed);
|
|
||||||
Geometry::ArcWelder::reverse(smooth_path);
|
|
||||||
m_wipe.set_path(std::move(smooth_path));
|
|
||||||
// reset acceleration
|
|
||||||
gcode += m_writer.set_print_acceleration((unsigned int)floor(m_config.default_acceleration.value + 0.5));
|
|
||||||
return gcode;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string GCodeGenerator::extrude_support(const ExtrusionEntityReferences &support_fills, const GCode::SmoothPathCache &smooth_path_cache)
|
|
||||||
{
|
{
|
||||||
static constexpr const auto support_label = "support material"sv;
|
static constexpr const auto support_label = "support material"sv;
|
||||||
static constexpr const auto support_interface_label = "support material interface"sv;
|
static constexpr const auto support_interface_label = "support material interface"sv;
|
||||||
|
|
||||||
std::string gcode;
|
std::string gcode;
|
||||||
if (! support_fills.empty()) {
|
if (! support_extrusions.empty()) {
|
||||||
const double support_speed = m_config.support_material_speed.value;
|
const double support_speed = m_config.support_material_speed.value;
|
||||||
const double support_interface_speed = m_config.support_material_interface_speed.get_abs_value(support_speed);
|
const double support_interface_speed = m_config.support_material_interface_speed.get_abs_value(support_speed);
|
||||||
for (const ExtrusionEntityReference &eref : support_fills) {
|
for (const GCode::ExtrusionOrder::SupportPath &path : support_extrusions) {
|
||||||
ExtrusionRole role = eref.extrusion_entity().role();
|
const auto label = path.is_interface ? support_interface_label : support_label;
|
||||||
assert(role == ExtrusionRole::SupportMaterial || role == ExtrusionRole::SupportMaterialInterface);
|
const double speed = path.is_interface ? support_interface_speed : support_speed;
|
||||||
const auto label = (role == ExtrusionRole::SupportMaterial) ? support_label : support_interface_label;
|
gcode += this->extrude_smooth_path(path.path, false, label, speed);
|
||||||
const double speed = (role == ExtrusionRole::SupportMaterial) ? support_speed : support_interface_speed;
|
|
||||||
const ExtrusionPath *path = dynamic_cast<const ExtrusionPath*>(&eref.extrusion_entity());
|
|
||||||
if (path)
|
|
||||||
gcode += this->extrude_path(*path, eref.flipped(), smooth_path_cache, label, speed);
|
|
||||||
else if (const ExtrusionMultiPath *multipath = dynamic_cast<const ExtrusionMultiPath*>(&eref.extrusion_entity()); multipath)
|
|
||||||
gcode += this->extrude_multi_path(*multipath, eref.flipped(), smooth_path_cache, label, speed);
|
|
||||||
else {
|
|
||||||
const ExtrusionEntityCollection *eec = dynamic_cast<const ExtrusionEntityCollection*>(&eref.extrusion_entity());
|
|
||||||
assert(eec);
|
|
||||||
if (eec) {
|
|
||||||
//FIXME maybe order the support here?
|
|
||||||
ExtrusionEntityReferences refs;
|
|
||||||
refs.reserve(eec->entities.size());
|
|
||||||
std::transform(eec->entities.begin(), eec->entities.end(), std::back_inserter(refs),
|
|
||||||
[flipped = eref.flipped()](const ExtrusionEntity *ee) { return ExtrusionEntityReference{ *ee, flipped }; });
|
|
||||||
gcode += this->extrude_support(refs, smooth_path_cache);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return gcode;
|
return gcode;
|
||||||
|
@ -281,12 +281,10 @@ private:
|
|||||||
coordf_t print_z,
|
coordf_t print_z,
|
||||||
bool vase_mode
|
bool vase_mode
|
||||||
);
|
);
|
||||||
std::string extrude_perimeter(const GCode::ExtrusionOrder::Perimeter &perimeter, const std::string_view description);
|
std::string extrude_smooth_path(
|
||||||
std::string extrude_skirt(GCode::SmoothPath smooth_path, const ExtrusionFlow &extrusion_flow_override,
|
const GCode::SmoothPath &smooth_path, const bool is_loop, const std::string_view description, const double speed
|
||||||
const GCode::SmoothPathCache &smooth_path_cache, const std::string_view description, double speed);
|
);
|
||||||
|
std::string extrude_skirt(GCode::SmoothPath smooth_path, const ExtrusionFlow &extrusion_flow_override, const std::string_view description, double speed);
|
||||||
std::string extrude_multi_path(const ExtrusionMultiPath &multipath, bool reverse, const GCode::SmoothPathCache &smooth_path_cache, const std::string_view description, double speed = -1.);
|
|
||||||
std::string extrude_path(const ExtrusionPath &path, bool reverse, const GCode::SmoothPathCache &smooth_path_cache, const std::string_view description, double speed = -1.);
|
|
||||||
|
|
||||||
std::vector<InstanceToPrint> sort_print_object_instances(
|
std::vector<InstanceToPrint> sort_print_object_instances(
|
||||||
// Object and Support layers for the current print_z, collected for a single object, or for possibly multiple objects with multiple instances.
|
// Object and Support layers for the current print_z, collected for a single object, or for possibly multiple objects with multiple instances.
|
||||||
@ -297,43 +295,32 @@ private:
|
|||||||
const size_t single_object_instance_idx);
|
const size_t single_object_instance_idx);
|
||||||
|
|
||||||
std::string extrude_perimeters(
|
std::string extrude_perimeters(
|
||||||
const Print &print,
|
|
||||||
const PrintRegion ®ion,
|
const PrintRegion ®ion,
|
||||||
const std::vector<GCode::ExtrusionOrder::Perimeter> &perimeters,
|
const std::vector<GCode::ExtrusionOrder::Perimeter> &perimeters,
|
||||||
const InstanceToPrint &print_instance,
|
const InstanceToPrint &print_instance
|
||||||
const GCode::SmoothPathCache &smooth_path_cache
|
|
||||||
);
|
|
||||||
|
|
||||||
std::string extrude_brim(
|
|
||||||
const std::vector<GCode::ExtrusionOrder::BrimPath> &brim,
|
|
||||||
const std::string &extrusion_name,
|
|
||||||
const double speed
|
|
||||||
);
|
|
||||||
|
|
||||||
std::string extrude_infill_range(
|
|
||||||
const std::vector<GCode::SmoothPath> &infill_range,
|
|
||||||
const PrintRegion ®ion,
|
|
||||||
const std::string &extrusion_name,
|
|
||||||
const GCode::SmoothPathCache &smooth_path_cache
|
|
||||||
);
|
);
|
||||||
|
|
||||||
std::string extrude_infill_ranges(
|
std::string extrude_infill_ranges(
|
||||||
const std::vector<InfillRange> &infill_ranges,
|
const std::vector<InfillRange> &infill_ranges,
|
||||||
const std::string &commment,
|
const std::string &commment
|
||||||
const GCode::SmoothPathCache &smooth_path_cache
|
);
|
||||||
|
|
||||||
|
void initialize_layer(
|
||||||
|
const InstanceToPrint &print_instance,
|
||||||
|
const ObjectLayerToPrint &layer_to_print
|
||||||
);
|
);
|
||||||
|
|
||||||
// This function will be called for each printing extruder, possibly twice: First for wiping extrusions, second for normal extrusions.
|
// This function will be called for each printing extruder, possibly twice: First for wiping extrusions, second for normal extrusions.
|
||||||
void process_layer_single_object(
|
std::string extrude_slices(
|
||||||
std::string &gcode,
|
|
||||||
const InstanceToPrint &print_instance,
|
const InstanceToPrint &print_instance,
|
||||||
const ObjectLayerToPrint &layer_to_print,
|
const ObjectLayerToPrint &layer_to_print,
|
||||||
const GCode::SmoothPathCache &smooth_path_cache,
|
|
||||||
const ExtrusionEntityReferences &support_extrusions,
|
|
||||||
const std::vector<SliceExtrusions> &slices_extrusions
|
const std::vector<SliceExtrusions> &slices_extrusions
|
||||||
);
|
);
|
||||||
|
|
||||||
std::string extrude_support(const ExtrusionEntityReferences &support_fills, const GCode::SmoothPathCache &smooth_path_cache);
|
std::string extrude_support(
|
||||||
|
const std::vector<GCode::ExtrusionOrder::SupportPath> &support_extrusions
|
||||||
|
);
|
||||||
|
|
||||||
std::string generate_travel_gcode(
|
std::string generate_travel_gcode(
|
||||||
const Points3& travel,
|
const Points3& travel,
|
||||||
const std::string& comment,
|
const std::string& comment,
|
||||||
|
@ -326,11 +326,13 @@ unsigned translate_support_extruder(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ExtrusionEntityReferences get_support_extrusions(
|
std::vector<SupportPath> get_support_extrusions(
|
||||||
const unsigned int extruder_id,
|
const unsigned int extruder_id,
|
||||||
const GCode::ObjectLayerToPrint &layer_to_print,
|
const GCode::ObjectLayerToPrint &layer_to_print,
|
||||||
unsigned int support_extruder,
|
unsigned int support_extruder,
|
||||||
unsigned int interface_extruder
|
unsigned int interface_extruder,
|
||||||
|
const PathSmoothingFunction &smooth_path,
|
||||||
|
std::optional<Point> &previous_position
|
||||||
) {
|
) {
|
||||||
if (const SupportLayer &support_layer = *layer_to_print.support_layer;
|
if (const SupportLayer &support_layer = *layer_to_print.support_layer;
|
||||||
!support_layer.support_fills.entities.empty()) {
|
!support_layer.support_fills.entities.empty()) {
|
||||||
@ -354,7 +356,23 @@ ExtrusionEntityReferences get_support_extrusions(
|
|||||||
if (ee->role() == role)
|
if (ee->role() == role)
|
||||||
entities_cache.emplace_back(ee);
|
entities_cache.emplace_back(ee);
|
||||||
}
|
}
|
||||||
return chain_extrusion_references(entities);
|
std::vector<SupportPath> paths;
|
||||||
|
for (const ExtrusionEntityReference &entity_reference : chain_extrusion_references(entities)) {
|
||||||
|
auto collection{dynamic_cast<const ExtrusionEntityCollection *>(&entity_reference.extrusion_entity())};
|
||||||
|
const bool is_interface{entity_reference.extrusion_entity().role() != ExtrusionRole::SupportMaterial};
|
||||||
|
if (collection != nullptr) {
|
||||||
|
for (const ExtrusionEntity * sub_entity : *collection) {
|
||||||
|
std::optional<InstancePoint> last_position{get_instance_point(previous_position, {0, 0})};
|
||||||
|
paths.push_back({smooth_path(nullptr, {*sub_entity, entity_reference.flipped()}, extruder_id, last_position), is_interface});
|
||||||
|
previous_position = get_gcode_point(last_position, {0, 0});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
std::optional<InstancePoint> last_position{get_instance_point(previous_position, {0, 0})};
|
||||||
|
paths.push_back({smooth_path(nullptr, entity_reference, extruder_id, last_position), is_interface});
|
||||||
|
previous_position = get_gcode_point(last_position, {0, 0});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return paths;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
@ -421,12 +439,10 @@ std::vector<NormalExtrusions> get_normal_extrusions(
|
|||||||
extruder_id,
|
extruder_id,
|
||||||
layers[instance.object_layer_to_print_id],
|
layers[instance.object_layer_to_print_id],
|
||||||
translate_support_extruder(instance.print_object.config().support_material_extruder.value, layer_tools, print.config().filament_soluble),
|
translate_support_extruder(instance.print_object.config().support_material_extruder.value, layer_tools, print.config().filament_soluble),
|
||||||
translate_support_extruder(instance.print_object.config().support_material_interface_extruder.value, layer_tools, print.config().filament_soluble)
|
translate_support_extruder(instance.print_object.config().support_material_interface_extruder.value, layer_tools, print.config().filament_soluble),
|
||||||
|
smooth_path,
|
||||||
|
previous_position
|
||||||
);
|
);
|
||||||
|
|
||||||
if (const auto last_position = get_last_position(result.back().support_extrusions, offset)) {
|
|
||||||
previous_position = last_position;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (const Layer *layer = layers[instance.object_layer_to_print_id].object_layer; layer) {
|
if (const Layer *layer = layers[instance.object_layer_to_print_id].object_layer; layer) {
|
||||||
@ -455,6 +471,38 @@ std::vector<NormalExtrusions> get_normal_extrusions(
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_empty(const std::vector<SliceExtrusions> &extrusions) {
|
||||||
|
for (const SliceExtrusions &slice_extrusions : extrusions) {
|
||||||
|
for (const IslandExtrusions &island_extrusions : slice_extrusions.common_extrusions) {
|
||||||
|
if (!island_extrusions.perimeters.empty() || !island_extrusions.infill_ranges.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!slice_extrusions.ironing_extrusions.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_empty(const ExtruderExtrusions &extruder_extrusions) {
|
||||||
|
for (const std::vector<SliceExtrusions> &slices_extrusions : extruder_extrusions.overriden_extrusions) {
|
||||||
|
if (!is_empty(slices_extrusions)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const NormalExtrusions &normal_extrusions : extruder_extrusions.normal_extrusions) {
|
||||||
|
if (!normal_extrusions.support_extrusions.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!is_empty(normal_extrusions.slices_extrusions)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
std::vector<ExtruderExtrusions> get_extrusions(
|
std::vector<ExtruderExtrusions> get_extrusions(
|
||||||
const Print &print,
|
const Print &print,
|
||||||
const GCode::WipeTowerIntegration *wipe_tower,
|
const GCode::WipeTowerIntegration *wipe_tower,
|
||||||
@ -522,6 +570,11 @@ std::vector<ExtruderExtrusions> get_extrusions(
|
|||||||
print, layers, layer_tools, instances_to_print, extruder_id, smooth_path,
|
print, layers, layer_tools, instances_to_print, extruder_id, smooth_path,
|
||||||
previous_position
|
previous_position
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (is_empty(extruder_extrusions)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
extrusions.push_back(std::move(extruder_extrusions));
|
extrusions.push_back(std::move(extruder_extrusions));
|
||||||
}
|
}
|
||||||
return extrusions;
|
return extrusions;
|
||||||
|
@ -74,8 +74,14 @@ struct SliceExtrusions {
|
|||||||
std::vector<InfillRange> ironing_extrusions;
|
std::vector<InfillRange> ironing_extrusions;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct SupportPath {
|
||||||
|
SmoothPath path;
|
||||||
|
bool is_interface;
|
||||||
|
};
|
||||||
|
|
||||||
struct NormalExtrusions {
|
struct NormalExtrusions {
|
||||||
ExtrusionEntityReferences support_extrusions;
|
std::vector<SupportPath> support_extrusions;
|
||||||
std::vector<SliceExtrusions> slices_extrusions;
|
std::vector<SliceExtrusions> slices_extrusions;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -104,6 +110,8 @@ struct ExtruderExtrusions {
|
|||||||
|
|
||||||
static constexpr const double min_gcode_segment_length = 0.002;
|
static constexpr const double min_gcode_segment_length = 0.002;
|
||||||
|
|
||||||
|
bool is_empty(const std::vector<SliceExtrusions> &extrusions);
|
||||||
|
|
||||||
std::vector<ExtruderExtrusions> get_extrusions(
|
std::vector<ExtruderExtrusions> get_extrusions(
|
||||||
const Print &print,
|
const Print &print,
|
||||||
const GCode::WipeTowerIntegration *wipe_tower,
|
const GCode::WipeTowerIntegration *wipe_tower,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user