failed arc welder in path ordering

This commit is contained in:
Martin Šach 2024-06-18 21:09:51 +02:00 committed by Lukas Matena
parent 773c34f906
commit d54f20a12c
4 changed files with 171 additions and 134 deletions

View File

@ -2299,24 +2299,59 @@ std::vector<GCode::ExtrusionOrder::ExtruderExtrusions> GCodeGenerator::get_sorte
Skirt::make_skirt_loops_per_extruder_1st_layer(print, layer_tools, m_skirt_done) :
Skirt::make_skirt_loops_per_extruder_other_layers(print, layer_tools, m_skirt_done)};
const auto place_seam =[&](
const Layer &layer, ExtrusionEntity *perimeter, const std::optional<Point> &previous_position
) {
auto loop{dynamic_cast<ExtrusionLoop *>(perimeter)};
const auto smooth_path{
[&](const Layer *layer, const ExtrusionEntityReference &extrusion_reference,
const unsigned extruder_id, std::optional<Point> &previous_position) {
const ExtrusionEntity *extrusion_entity{&extrusion_reference.extrusion_entity()};
Point seam_point{previous_position ? *previous_position : Point::Zero()};
if (!this->m_config.spiral_vase && loop != nullptr) {
seam_point = this->m_seam_placer.place_seam(&layer, *loop, seam_point);
loop->seam = seam_point;
}
GCode::SmoothPath result;
auto path{dynamic_cast<const ExtrusionMultiPath *>(perimeter)};
if (path != nullptr) {
return path->last_point();
} else {
return seam_point;
}
};
if (auto loop = dynamic_cast<const ExtrusionLoop *>(extrusion_entity)) {
Point seam_point = previous_position ? *previous_position : Point::Zero();
if (loop->role().is_perimeter() && layer != nullptr) {
seam_point = this->m_seam_placer.place_seam(layer, *loop, seam_point);
}
const GCode::SmoothPathCache &smooth_path_cache{loop->role().is_perimeter() ? smooth_path_caches.layer_local() : smooth_path_caches.global()};
// Because the G-code export has 1um resolution, don't generate segments shorter
// than 1.5 microns, thus empty path segments will not be produced by G-code export.
GCode::SmoothPath smooth_path =
smooth_path_cache.resolve_or_fit_split_with_seam(
*loop, extrusion_reference.flipped(), m_scaled_resolution, seam_point, scaled<double>(0.0015)
);
// Clip the path to avoid the extruder to get exactly on the first point of the
// loop; if polyline was shorter than the clipping distance we'd get a null
// polyline, so we discard it in that case.
const auto nozzle_diameter{m_config.nozzle_diameter.get_at(extruder_id)};
if (m_enable_loop_clipping) {
clip_end(
smooth_path,
scale_(nozzle_diameter) * LOOP_CLIPPING_LENGTH_OVER_NOZZLE_DIAMETER,
scaled<double>(GCode::ExtrusionOrder::min_gcode_segment_length)
);
}
assert(validate_smooth_path(smooth_path, !enable_loop_clipping));
result = smooth_path;
} else if (auto multipath = dynamic_cast<const ExtrusionMultiPath *>(extrusion_entity)) {
result = smooth_path_caches.layer_local().resolve_or_fit(*multipath, extrusion_reference.flipped(), m_scaled_resolution);
} else if (auto path = dynamic_cast<const ExtrusionPath *>(extrusion_entity)) {
result = smooth_path_caches.layer_local().resolve_or_fit(*path, extrusion_reference.flipped(), m_scaled_resolution);
}
using GCode::SmoothPathElement;
for (const SmoothPathElement &element : result) {
if (!element.path.empty()) {
previous_position = element.path.back().point;
break;
}
}
return result;
}};
using GCode::ExtrusionOrder::ExtruderExtrusions;
using GCode::ExtrusionOrder::get_extrusions;
@ -2332,13 +2367,9 @@ std::vector<GCode::ExtrusionOrder::ExtruderExtrusions> GCodeGenerator::get_sorte
first_layer,
layer_tools,
instances_to_print,
smooth_path_caches.global(),
skirt_loops_per_extruder,
m_enable_loop_clipping,
m_config,
m_scaled_resolution,
this->m_writer.extruder()->id(),
place_seam,
smooth_path,
!this->m_brim_done,
previous_position
)
@ -2894,6 +2925,38 @@ static inline bool validate_smooth_path(const GCode::SmoothPath &smooth_path, bo
}
#endif //NDEBUG
std::string GCodeGenerator::extrude_perimeter(
const GCode::ExtrusionOrder::Perimeter &perimeter, const std::string_view description
) {
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.
std::string gcode;
for (const GCode::SmoothPathElement &el : perimeter.smooth_path)
gcode += this->_extrude(el.path_attributes, el.path, description, speed);
// reset acceleration
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(GCode::SmoothPath{perimeter.smooth_path});
} else if (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;
}
std::string GCodeGenerator::extrude_loop(const ExtrusionLoop &loop_src, const GCode::SmoothPathCache &smooth_path_cache, const std::string_view description, double speed)
{
// Extrude all loops CCW unless CW movements are prefered.
@ -2973,17 +3036,27 @@ std::string GCodeGenerator::extrude_skirt(
}
std::string GCodeGenerator::extrude_infill_range(
const std::vector<ExtrusionEntityReference> &sorted_extrusions,
const std::vector<GCode::SmoothPath> &sorted_paths,
const PrintRegion &region,
const std::string &extrusion_name,
const GCode::SmoothPathCache &smooth_path_cache
) {
std::string gcode{};
if (!sorted_extrusions.empty()) {
if (!sorted_paths.empty()) {
this->m_config.apply(region.config());
for (const ExtrusionEntityReference &ee : sorted_extrusions) {
gcode += this->extrude_entity(ee, smooth_path_cache, extrusion_name);
for (const GCode::SmoothPath &smooth_path : sorted_paths) {
// extrude along the path
std::string gcode;
for (const GCode::SmoothPathElement &el : smooth_path)
gcode += this->_extrude(el.path_attributes, el.path, extrusion_name);
GCode::SmoothPath reversed_smooth_path{smooth_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;
@ -3006,7 +3079,7 @@ std::string GCodeGenerator::extrude_infill_ranges(
std::string GCodeGenerator::extrude_perimeters(
const Print &print,
const PrintRegion &region,
const std::vector<ExtrusionEntity *> &perimeters,
const std::vector<GCode::ExtrusionOrder::Perimeter> &perimeters,
const InstanceToPrint &print_instance,
const GCode::SmoothPathCache &smooth_path_cache
) {
@ -3016,13 +3089,11 @@ std::string GCodeGenerator::extrude_perimeters(
std::string gcode{};
for (const ExtrusionEntity *ee : perimeters) {
for (const GCode::ExtrusionOrder::Perimeter &perimeter : perimeters) {
// Don't reorder, don't flip.
gcode += this->extrude_entity(
{*ee, false}, smooth_path_cache, comment_perimeter, -1.
);
gcode += this->extrude_perimeter(perimeter, comment_perimeter);
this->m_travel_obstacle_tracker.mark_extruded(
ee, 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
);
}
return gcode;

View File

@ -282,6 +282,8 @@ private:
bool vase_mode
);
std::string extrude_entity(const ExtrusionEntityReference &entity, const GCode::SmoothPathCache &smooth_path_cache, const std::string_view description, double speed = -1.);
std::string extrude_perimeter(const GCode::ExtrusionOrder::Perimeter &perimeter, const std::string_view description);
std::string extrude_loop(const ExtrusionLoop &loop, const GCode::SmoothPathCache &smooth_path_cache, const std::string_view description, double speed = -1.);
std::string extrude_skirt(GCode::SmoothPath smooth_path, const ExtrusionFlow &extrusion_flow_override,
const GCode::SmoothPathCache &smooth_path_cache, const std::string_view description, double speed);
@ -300,13 +302,13 @@ private:
std::string extrude_perimeters(
const Print &print,
const PrintRegion &region,
const std::vector<ExtrusionEntity *> &perimeters,
const std::vector<GCode::ExtrusionOrder::Perimeter> &perimeters,
const InstanceToPrint &print_instance,
const GCode::SmoothPathCache &smooth_path_cache
);
std::string extrude_infill_range(
const std::vector<ExtrusionEntityReference> &sorted_extrusions,
const std::vector<GCode::SmoothPath> &sorted_paths,
const PrintRegion &region,
const std::string &extrusion_name,
const GCode::SmoothPathCache &smooth_path_cache

View File

@ -106,13 +106,17 @@ ExtrusionEntitiesPtr extract_infill_extrusions(
return result;
}
std::vector<ExtrusionEntity *> extract_perimeter_extrusions(
std::vector<Perimeter> extract_perimeter_extrusions(
const Print &print,
const Layer &layer,
const LayerIsland &island,
const ExtractEntityPredicate &predicate
const ExtractEntityPredicate &predicate,
const unsigned extruder_id,
const Vec2d &offset,
std::optional<Vec2d> &previous_position,
const PathSmoothingFunction &smooth_path
) {
std::vector<ExtrusionEntity *> result;
std::vector<Perimeter> result;
const LayerRegion &layerm = *layer.get_region(island.perimeters.region());
const PrintRegion &region = print.get_print_region(layerm.region().print_region_id());
@ -127,7 +131,17 @@ std::vector<ExtrusionEntity *> extract_perimeter_extrusions(
}
for (ExtrusionEntity *ee : *eec) {
result.push_back(ee);
if (ee != nullptr) {
std::optional<Point> last_position{get_instance_point(previous_position, offset)};
bool reverse_loop{false};
if (auto loop = dynamic_cast<const ExtrusionLoop *>(ee)) {
const bool is_hole = loop->is_clockwise();
reverse_loop = print.config().prefer_clockwise_movements ? !is_hole : is_hole;
}
SmoothPath path{smooth_path(&layer, ExtrusionEntityReference{*ee, reverse_loop}, extruder_id, last_position)};
previous_position = get_gcode_point(last_position, offset);
result.push_back(Perimeter{std::move(path), reverse_loop, ee});
}
}
}
@ -158,7 +172,9 @@ std::vector<InfillRange> extract_infill_ranges(
const LayerIsland &island,
const Vec2d &offset,
std::optional<Vec2d> &previous_position,
const ExtractEntityPredicate &predicate
const ExtractEntityPredicate &predicate,
const PathSmoothingFunction &smooth_path,
const unsigned extruder_id
) {
std::vector<InfillRange> result;
for (auto it = island.fills.begin(); it != island.fills.end();) {
@ -182,12 +198,13 @@ std::vector<InfillRange> extract_infill_ranges(
const Point* start_near{previous_position_scaled ? &(*(previous_position_scaled)) : nullptr};
const ExtrusionEntityReferences sorted_extrusions{sort_fill_extrusions(extrusions, start_near)};
if (!sorted_extrusions.empty()) {
result.push_back({sorted_extrusions, &region});
}
if (const auto last_position = get_last_position(sorted_extrusions, offset)) {
previous_position = last_position;
std::vector<SmoothPath> paths;
for (const ExtrusionEntityReference &extrusion_reference : sorted_extrusions) {
std::optional<Point> last_position{get_instance_point(previous_position, offset)};
paths.push_back(smooth_path(&layer, extrusion_reference, extruder_id, last_position));
previous_position = get_gcode_point(previous_position, offset);
}
result.push_back({std::move(paths), &region});
it = it_end;
}
return result;
@ -198,8 +215,9 @@ std::vector<IslandExtrusions> extract_island_extrusions(
const Print &print,
const Layer &layer,
const ExtractEntityPredicate &predicate,
const SeamPlacingFunciton &place_seam,
const PathSmoothingFunction &smooth_path,
const Vec2d &offset,
const unsigned extruder_id,
std::optional<Vec2d> &previous_position
) {
std::vector<IslandExtrusions> result;
@ -217,31 +235,17 @@ std::vector<IslandExtrusions> extract_island_extrusions(
result.push_back(IslandExtrusions{&region});
IslandExtrusions &island_extrusions{result.back()};
island_extrusions.perimeters = extract_perimeter_extrusions(print, layer, island, predicate);
if (print.config().infill_first) {
island_extrusions.infill_ranges = extract_infill_ranges(
print, layer, island, offset, previous_position, infill_predicate
print, layer, island, offset, previous_position, infill_predicate, smooth_path, extruder_id
);
for (ExtrusionEntity* perimeter : island_extrusions.perimeters) {
std::optional<Point> instance_point{get_instance_point(previous_position, offset)};
const std::optional<Point> seam_point{place_seam(layer, perimeter, instance_point)};
if (seam_point) {
previous_position = get_gcode_point(*seam_point, offset);
}
}
island_extrusions.perimeters = extract_perimeter_extrusions(print, layer, island, predicate, extruder_id, offset, previous_position, smooth_path);
} else {
for (ExtrusionEntity* perimeter : island_extrusions.perimeters) {
std::optional<Point> instance_point{get_instance_point(previous_position, offset)};
const std::optional<Point> seam_point{place_seam(layer, perimeter, instance_point)};
if (seam_point) {
previous_position = get_gcode_point(*seam_point, offset);
}
}
island_extrusions.perimeters = extract_perimeter_extrusions(print, layer, island, predicate, extruder_id, offset, previous_position, smooth_path);
island_extrusions.infill_ranges = {extract_infill_ranges(
print, layer, island, offset, previous_position, infill_predicate
print, layer, island, offset, previous_position, infill_predicate, smooth_path, extruder_id
)};
}
}
@ -253,7 +257,9 @@ std::vector<InfillRange> extract_ironing_extrusions(
const Print &print,
const Layer &layer,
const ExtractEntityPredicate &predicate,
const PathSmoothingFunction &smooth_path,
const Vec2d &offset,
const unsigned extruder_id,
std::optional<Vec2d> &previous_position
) {
std::vector<InfillRange> result;
@ -264,7 +270,7 @@ std::vector<InfillRange> extract_ironing_extrusions(
};
const std::vector<InfillRange> ironing_ranges{extract_infill_ranges(
print, layer, island, offset, previous_position, ironing_predicate
print, layer, island, offset, previous_position, ironing_predicate, smooth_path, extruder_id
)};
result.insert(
result.end(), ironing_ranges.begin(), ironing_ranges.end()
@ -277,8 +283,9 @@ std::vector<SliceExtrusions> get_slices_extrusions(
const Print &print,
const Layer &layer,
const ExtractEntityPredicate &predicate,
const SeamPlacingFunciton &place_seam,
const PathSmoothingFunction &smooth_path,
const Vec2d &offset,
const unsigned extruder_id,
std::optional<Vec2d> &previous_position
) {
// Note: ironing.
@ -293,9 +300,9 @@ std::vector<SliceExtrusions> get_slices_extrusions(
const LayerSlice &lslice = layer.lslices_ex[idx];
result.emplace_back(SliceExtrusions{
extract_island_extrusions(
lslice, print, layer, predicate, place_seam, offset, previous_position
lslice, print, layer, predicate, smooth_path, offset, extruder_id, previous_position
),
extract_ironing_extrusions(lslice, print, layer, predicate, offset, previous_position)
extract_ironing_extrusions(lslice, print, layer, predicate, smooth_path, offset, extruder_id, previous_position)
});
}
return result;
@ -359,7 +366,7 @@ std::vector<std::vector<SliceExtrusions>> get_overriden_extrusions(
const LayerTools &layer_tools,
const std::vector<InstanceToPrint> &instances_to_print,
const unsigned int extruder_id,
const SeamPlacingFunciton &place_seam,
const PathSmoothingFunction &smooth_path,
std::optional<Vec2d> &previous_position
) {
std::vector<std::vector<SliceExtrusions>> result;
@ -384,7 +391,7 @@ std::vector<std::vector<SliceExtrusions>> get_overriden_extrusions(
const Vec2d &offset = unscale(print_object.instances()[instance.instance_id].shift);
result.emplace_back(get_slices_extrusions(
print, *layer, predicate, place_seam, offset, previous_position
print, *layer, predicate, smooth_path, offset, extruder_id, previous_position
));
}
}
@ -397,7 +404,7 @@ std::vector<NormalExtrusions> get_normal_extrusions(
const LayerTools &layer_tools,
const std::vector<InstanceToPrint> &instances_to_print,
const unsigned int extruder_id,
const SeamPlacingFunciton &place_seam,
const PathSmoothingFunction &smooth_path,
std::optional<Vec2d> &previous_position
) {
std::vector<NormalExtrusions> result;
@ -438,8 +445,9 @@ std::vector<NormalExtrusions> get_normal_extrusions(
print,
*layer,
predicate,
place_seam,
smooth_path,
offset,
extruder_id,
previous_position
);
}
@ -454,13 +462,9 @@ std::vector<ExtruderExtrusions> get_extrusions(
const bool is_first_layer,
const LayerTools &layer_tools,
const std::vector<InstanceToPrint> &instances_to_print,
const GCode::SmoothPathCache &smooth_path_cache,
const std::map<unsigned int, std::pair<size_t, size_t>> &skirt_loops_per_extruder,
const bool enable_loop_clipping,
const FullPrintConfig &config,
const double scaled_resolution,
unsigned current_extruder_id,
const SeamPlacingFunciton &place_seam,
const PathSmoothingFunction &smooth_path,
bool get_brim,
std::optional<Vec2d> previous_position
) {
@ -482,35 +486,11 @@ std::vector<ExtruderExtrusions> get_extrusions(
if (auto loops_it = skirt_loops_per_extruder.find(extruder_id); loops_it != skirt_loops_per_extruder.end()) {
const std::pair<size_t, size_t> loops = loops_it->second;
for (std::size_t i = loops.first; i < loops.second; ++i) {
auto loop_src{dynamic_cast<const ExtrusionLoop *>(print.skirt().entities[i])};
if (loop_src != nullptr) {
const Point seam_point = previous_position ? get_instance_point(*previous_position, {0.0, 0.0}) : Point::Zero();
const bool reverse_loop = config.prefer_clockwise_movements;
// Because the G-code export has 1um resolution, don't generate segments shorter than 1.5 microns,
// thus empty path segments will not be produced by G-code export.
GCode::SmoothPath smooth_path = smooth_path_cache.resolve_or_fit_split_with_seam(*loop_src, reverse_loop, scaled_resolution, seam_point, scaled<double>(0.0015));
// Clip the path to avoid the extruder to get exactly on the first point of the loop;
// if polyline was shorter than the clipping distance we'd get a null polyline, so
// we discard it in that case.
const auto nozzle_diameter{config.nozzle_diameter.get_at(extruder_id)};
if (enable_loop_clipping)
clip_end(smooth_path, scale_(nozzle_diameter) * LOOP_CLIPPING_LENGTH_OVER_NOZZLE_DIAMETER, scaled<double>(min_gcode_segment_length));
if (smooth_path.empty())
continue;
assert(validate_smooth_path(smooth_path, ! enable_loop_clipping));
for (const SmoothPathElement &element : smooth_path) {
if (!element.path.empty()) {
previous_position = get_gcode_point(element.path.back().point, {0.0, 0.0});
break;
}
}
extruder_extrusions.skirt.emplace_back(i, std::move(smooth_path));
}
const ExtrusionEntityReference entity{*print.skirt().entities[i], false};
std::optional<Point> last_position{get_instance_point(previous_position, {0.0, 0.0})};
SmoothPath path{smooth_path(nullptr, entity, extruder_id, last_position)};
previous_position = get_gcode_point(last_position, {0.0, 0.0});
extruder_extrusions.skirt.emplace_back(i, std::move(path));
}
}
@ -526,14 +506,14 @@ std::vector<ExtruderExtrusions> get_extrusions(
bool is_anything_overridden = layer_tools.wiping_extrusions().is_anything_overridden();
if (is_anything_overridden) {
extruder_extrusions.overriden_extrusions = get_overriden_extrusions(
print, layers, layer_tools, instances_to_print, extruder_id, place_seam,
print, layers, layer_tools, instances_to_print, extruder_id, smooth_path,
previous_position
);
}
using GCode::ExtrusionOrder::get_normal_extrusions;
extruder_extrusions.normal_extrusions = get_normal_extrusions(
print, layers, layer_tools, instances_to_print, extruder_id, place_seam,
print, layers, layer_tools, instances_to_print, extruder_id, smooth_path,
previous_position
);
extrusions.push_back(std::move(extruder_extrusions));

View File

@ -53,13 +53,19 @@ struct InstanceToPrint
namespace Slic3r::GCode::ExtrusionOrder {
struct InfillRange {
std::vector<ExtrusionEntityReference> items;
std::vector<SmoothPath> items;
const PrintRegion *region;
};
struct Perimeter {
GCode::SmoothPath smooth_path;
bool reversed;
const ExtrusionEntity *extrusion_entity;
};
struct IslandExtrusions {
const PrintRegion *region;
std::vector<ExtrusionEntity *> perimeters;
std::vector<Perimeter> perimeters;
std::vector<InfillRange> infill_ranges;
};
@ -75,27 +81,9 @@ struct NormalExtrusions {
std::optional<Vec2d> get_last_position(const ExtrusionEntitiesPtr &extrusions, const Vec2d &offset);
using SeamPlacingFunciton = std::function<std::optional<Point>(const Layer &layer, ExtrusionEntity* perimeter, const std::optional<Point>&)>;
std::vector<std::vector<SliceExtrusions>> get_overriden_extrusions(
const Print &print,
const GCode::ObjectsLayerToPrint &layers,
const LayerTools &layer_tools,
const std::vector<InstanceToPrint> &instances_to_print,
const unsigned int extruder_id,
const SeamPlacingFunciton &place_seam,
std::optional<Vec2d> &previous_position
);
std::vector<NormalExtrusions> get_normal_extrusions(
const Print &print,
const GCode::ObjectsLayerToPrint &layers,
const LayerTools &layer_tools,
const std::vector<InstanceToPrint> &instances_to_print,
const unsigned int extruder_id,
const SeamPlacingFunciton &place_seam,
std::optional<Vec2d> &previous_position
);
using PathSmoothingFunction = std::function<SmoothPath(
const Layer *, const ExtrusionEntityReference &, const unsigned extruder_id, std::optional<Point> &previous_position
)>;
struct ExtruderExtrusions {
unsigned extruder_id;
@ -114,13 +102,9 @@ std::vector<ExtruderExtrusions> get_extrusions(
const bool is_first_layer,
const LayerTools &layer_tools,
const std::vector<InstanceToPrint> &instances_to_print,
const GCode::SmoothPathCache &smooth_path_cache,
const std::map<unsigned int, std::pair<size_t, size_t>> &skirt_loops_per_extruder,
const bool enable_loop_clipping,
const FullPrintConfig &config,
const double scaled_resolution,
unsigned current_extruder_id,
const SeamPlacingFunciton &place_seam,
const PathSmoothingFunction &smooth_path,
bool get_brim,
std::optional<Vec2d> previous_position
);