Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/local_27/dev' into nematxslicer
Browse files Browse the repository at this point in the history
  • Loading branch information
supermerill committed Feb 11, 2025
2 parents 7b530c7 + bcad932 commit cee06ff
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 27 deletions.
5 changes: 5 additions & 0 deletions src/libslic3r/GCode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4827,6 +4827,7 @@ std::string GCodeGenerator::extrude_loop(const ExtrusionLoop &original_loop, con
assert(!path.polyline.get_point(i - 1).coincides_with_epsilon(path.polyline.get_point(i)));

split_at_seam_pos(loop_to_seam, is_hole_loop);
const Point seam_pos = loop_to_seam.first_point();
const coordf_t full_loop_length = loop_to_seam.length();
const bool is_full_loop_ccw = loop_to_seam.polygon().is_counter_clockwise();
//after that point, loop_to_seam can be modified by 'paths', so don't use it anymore
Expand Down Expand Up @@ -5011,6 +5012,10 @@ std::string GCodeGenerator::extrude_loop(const ExtrusionLoop &original_loop, con
gcode += extrude_path(path, description, speed);
}

// print seam tag with seam position
Vec2d seam_gcode_point = point_to_gcode(seam_pos);
gcode += ";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Seam) + ":" + to_string_nozero(seam_gcode_point.x(),3) + ":" + to_string_nozero(seam_gcode_point.y(),3) + "\n";

// reset acceleration
m_writer.set_acceleration((uint16_t)floor(get_default_acceleration(m_config) + 0.5));

Expand Down
45 changes: 41 additions & 4 deletions src/libslic3r/GCode/GCodeProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ const std::vector<std::string> GCodeProcessor::Reserved_Tags = {
"WIPE_END",
"HEIGHT:",
"WIDTH:",
"SEAM",
"LAYER_CHANGE",
"LAYER_CHANGE_TRAVEL",
"LAYER_CHANGE_RETRACTION_START",
Expand Down Expand Up @@ -1148,6 +1149,8 @@ void GCodeProcessor::reset()
m_use_volumetric_e = false;
m_last_default_color_id = 0;

m_seam.reset();

m_options_z_corrector.reset();

m_spiral_vase_active = false;
Expand Down Expand Up @@ -2151,7 +2154,7 @@ void GCodeProcessor::process_gcode_line(const GCodeReader::GCodeLine& line, bool
}
}
}

#pragma UNOPTIMIZE
void GCodeProcessor::process_tags(const std::string_view comment, bool producers_enabled)
{
// producers tags
Expand All @@ -2178,6 +2181,27 @@ void GCodeProcessor::process_tags(const std::string_view comment, bool producers
return;
}

// seam tag
if (boost::starts_with(comment, reserved_tag(ETags::Seam))) {
std::string_view first_part = comment.substr(reserved_tag(ETags::Seam).size() + 1);
size_t pos_separator = first_part.find(":");
assert(pos_separator != std::string::npos);
if (pos_separator == std::string::npos) {
return;
}
std::string_view second_part = first_part.substr(pos_separator + 1);
first_part = first_part.substr(0, pos_separator);
double seam_x, seam_y;
bool ok = parse_number(first_part, seam_x);
ok = ok && parse_number(second_part, seam_y);
assert(!m_seam);
m_seam = m_end_position;
(*m_seam)[0] = seam_x;
(*m_seam)[1] = seam_y;
(*m_seam)[3] = 0;
return;
}

if (!producers_enabled || m_producer == EProducer::PrusaSlicer || m_producer == EProducer::Slic3r || m_producer == EProducer::SuperSlicer) {
// height tag
if (boost::starts_with(comment, reserved_tag(ETags::Height))) {
Expand Down Expand Up @@ -3212,7 +3236,21 @@ void GCodeProcessor::process_G1(const std::array<std::optional<double>, 4>& axes
}
}

if (m_seams_detector.is_active()) {
if (m_seam) {
// use tag for easy seam detection
if (m_extrusion_role == GCodeExtrusionRole::ExternalPerimeter) {
AxisCoords end_position = m_end_position;
m_end_position = *m_seam;
store_move_vertex(EMoveType::Seam);
m_end_position = end_position;
// seam already set, deactivate detector to avoid double detection.
assert(m_seams_detector.is_active());
if (m_seams_detector.is_active()) {
m_seams_detector.activate(false);
}
}
m_seam.reset();
} else if (m_seams_detector.is_active()) {
// check for seam starting vertex
if (type == EMoveType::Extrude && m_extrusion_role == GCodeExtrusionRole::ExternalPerimeter && !m_seams_detector.has_first_vertex())
m_seams_detector.set_first_vertex(m_result.moves.back().position - m_extruder_offsets[m_extruder_id]);
Expand All @@ -3238,8 +3276,7 @@ void GCodeProcessor::process_G1(const std::array<std::optional<double>, 4>& axes

m_seams_detector.activate(false);
}
}
else if (type == EMoveType::Extrude && m_extrusion_role == GCodeExtrusionRole::ExternalPerimeter) {
} else if (type == EMoveType::Extrude && m_extrusion_role == GCodeExtrusionRole::ExternalPerimeter) {
m_seams_detector.activate(true);
m_seams_detector.set_first_vertex(m_result.moves.back().position - m_extruder_offsets[m_extruder_id]);
}
Expand Down
2 changes: 2 additions & 0 deletions src/libslic3r/GCode/GCodeProcessor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ namespace Slic3r {
Wipe_End,
Height,
Width,
Seam,
Layer_Change,
Layer_Change_Travel,
Layer_Change_Retraction_Start,
Expand Down Expand Up @@ -632,6 +633,7 @@ namespace Slic3r {
float m_temperature;
bool m_use_volumetric_e;
SeamsDetector m_seams_detector;
std::optional<AxisCoords> m_seam;
OptionsZCorrector m_options_z_corrector;
size_t m_last_default_color_id;
bool m_spiral_vase_active;
Expand Down
49 changes: 26 additions & 23 deletions src/libslic3r/GCode/SeamPlacer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,8 @@ PolylineWithEnds extract_perimeter_polylines(const Layer *layer, const SeamPosit
SeamPosition configured_seam_preference;
PerimeterGeneratorType perimeter_type = PerimeterGeneratorType::Classic;
public:
bool also_overhangs = false;
// set to true to resolve some issues. when overhangs cut a loop in two, it can fail to go to the right spot.
bool also_overhangs = true; // false;
bool also_thin_walls = false;
PerimeterCopy(std::vector<const LayerRegion*>& regions_out, PolylineWithEnds* polys, SeamPosition configured_seam)
: m_corresponding_regions_out(regions_out), configured_seam_preference(configured_seam), polylines(polys) {
Expand Down Expand Up @@ -503,22 +504,17 @@ PolylineWithEnds extract_perimeter_polylines(const Layer *layer, const SeamPosit
bool current_collected = false;
for (const ExtrusionPath &path : loop.paths) {
current_collected = false;
if (path.role() == ExtrusionRole::ExternalPerimeter) {
if(!previous_collected)
polys.emplace_back(false, false, is_ccw ? PolylineWithEnd::PolyDir::CCW : PolylineWithEnd::PolyDir::CW);
path.collect_points(polys.back().points);
assert(polys.back().size() > 1);
count_paths_collected++;
current_collected = true;
}
if ( path.role().is_overhang() &&
also_overhangs) { // TODO find a way to search for external overhangs only
if(!previous_collected)
polys.emplace_back(false, false, is_ccw ? PolylineWithEnd::PolyDir::CCW : PolylineWithEnd::PolyDir::CW);
path.collect_points(polys.back().points);
assert(polys.back().size() > 1);
count_paths_collected++;
current_collected = true;
if (path.role().is_external_perimeter()) {
if (!path.role().is_overhang() || also_overhangs) {
if (!previous_collected)
polys.emplace_back(false, false,
is_ccw ? PolylineWithEnd::PolyDir::CCW :
PolylineWithEnd::PolyDir::CW);
path.collect_points(polys.back().points);
assert(polys.back().size() > 1);
count_paths_collected++;
current_collected = true;
}
}
//if (path.role() == ExtrusionRole::erThinWall && also_thin_walls) {
// path.collect_points(p); // TODO: 2.7: reactivate when it's possible to distinguish between thinwalltravel & thinextrusions
Expand Down Expand Up @@ -583,9 +579,10 @@ PolylineWithEnds extract_perimeter_polylines(const Layer *layer, const SeamPosit
ex_entity->visit(visitor);
if (polylines.empty()) {
// can happen if the external is fully an overhang
bool old = visitor.also_overhangs;
visitor.also_overhangs = true;
ex_entity->visit(visitor);
visitor.also_overhangs = false;
visitor.also_overhangs = old;
if (polylines.empty()) {
// shouldn't happen
assert(ex_entity->role() == ExtrusionRole::ThinWall || layer_region->region().config().perimeter_generator == PerimeterGeneratorType::Arachne); // no loops
Expand Down Expand Up @@ -962,9 +959,14 @@ struct SeamComparator {
}

//avoid overhangs
float overhang_penalty_a = 0.f;
float overhang_penalty_b = 0.f;
if ((a.overhang > a.perimeter.flow_width / 4 && b.overhang == 0.0f) ||
(b.overhang > b.perimeter.flow_width / 4 && a.overhang == 0.0f)) {
return a.overhang < b.overhang;
} else if (a.overhang > 0 || b.overhang > 0) {
overhang_penalty_a = std::clamp(2 * (a.overhang - a.perimeter.flow_width / 8) / a.perimeter.flow_width, 0.f, 3.f);
overhang_penalty_b = std::clamp(2 * (b.overhang - b.perimeter.flow_width / 8) / b.perimeter.flow_width, 0.f, 3.f);
}

// prefer hidden points (more than 0.5 mm inside)
Expand All @@ -987,11 +989,11 @@ struct SeamComparator {
}

// the penalites are kept close to range [0-1.x] however, it should not be relied upon
float penalty_a = 2 * a.overhang / a.perimeter.flow_width
float penalty_a = overhang_penalty_a
+ visibility_importance * a.visibility
+ angle_importance * compute_angle_penalty(a.local_ccw_angle)
+ travel_importance * distance_penalty_a;
float penalty_b = 2 * b.overhang / b.perimeter.flow_width
float penalty_b = overhang_penalty_b
+ visibility_importance * b.visibility
+ angle_importance * compute_angle_penalty(b.local_ccw_angle)
+ travel_importance * distance_penalty_b;
Expand Down Expand Up @@ -1948,10 +1950,11 @@ Point SeamPlacer::place_seam(const Layer *layer, const ExtrusionLoop &loop, cons
seam_index = perimeter.seam_index;
} else {
seam_index =
// only recompute for spNearest, spCost and spCustom, as these are the only one that uses the current position to compute the seam ( see is_first_better).
(po->config().seam_position.value == spNearest || po->config().seam_position.value == spCost || po->config().seam_position.value == spCustom) ?
pick_nearest_seam_point_index(layer_perimeters.points, perimeter.start_index,
unscaled<float>(last_pos), *po) :
perimeter.seam_index;
pick_nearest_seam_point_index(layer_perimeters.points, perimeter.start_index, unscaled<float>(last_pos), *po)
: perimeter.seam_index
;
seam_position = layer_perimeters.points[seam_index].position;
}

Expand Down

0 comments on commit cee06ff

Please sign in to comment.