Fix vase mode: no seam gap.

supermerill/SuperSlicer#2114
This commit is contained in:
supermerill 2021-12-29 01:35:03 +01:00
parent d2c6929192
commit fee585a0ae

View File

@ -2917,7 +2917,7 @@ std::string GCode::extrude_loop_vase(const ExtrusionLoop &original_loop, const s
speed = -1; speed = -1;
// get a copy; don't modify the orientation of the original loop object otherwise // get a copy; don't modify the orientation of the original loop object otherwise
// next copies (if any) would not detect the correct orientation // next copies (if any) would not detect the correct orientation
ExtrusionLoop loop = original_loop; ExtrusionLoop loop_to_seam = original_loop;
if (m_layer->lower_layer != nullptr && lower_layer_edge_grid != nullptr) { if (m_layer->lower_layer != nullptr && lower_layer_edge_grid != nullptr) {
if (!*lower_layer_edge_grid) { if (!*lower_layer_edge_grid) {
@ -2942,21 +2942,19 @@ std::string GCode::extrude_loop_vase(const ExtrusionLoop &original_loop, const s
// extrude all loops ccw // extrude all loops ccw
//no! this was decided in perimeter_generator //no! this was decided in perimeter_generator
bool is_hole_loop = (loop.loop_role() & ExtrusionLoopRole::elrHole) != 0;// loop.make_counter_clockwise(); bool is_hole_loop = (loop_to_seam.loop_role() & ExtrusionLoopRole::elrHole) != 0;// loop.make_counter_clockwise();
bool reverse_turn = loop.polygon().is_clockwise() ^ is_hole_loop; bool reverse_turn = loop_to_seam.polygon().is_clockwise() ^ is_hole_loop;
split_at_seam_pos(loop, lower_layer_edge_grid, reverse_turn); split_at_seam_pos(loop_to_seam, lower_layer_edge_grid, reverse_turn);
const coordf_t full_loop_dist = loop_to_seam.length();
// clip the path to avoid the extruder to get exactly on the first point of the loop; // don't clip the path ?
// if polyline was shorter than the clipping distance we'd get a null polyline, so ExtrusionPaths &paths = loop_to_seam.paths;
// we discard it in that case if (false && m_enable_loop_clipping && m_writer.tool_is_extruder()) {
coordf_t clip_length = 0; coordf_t clip_length = scale_(m_config.seam_gap.get_abs_value(m_writer.tool()->id(), EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter, 0)));
coordf_t min_clip_length = scale_(EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter, 0)) * 0.15; coordf_t min_clip_length = scale_(EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter, 0)) * 0.15;
if (m_enable_loop_clipping && m_writer.tool_is_extruder())
clip_length = scale_(m_config.seam_gap.get_abs_value(m_writer.tool()->id(), EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter, 0)));
// get paths // get paths
ExtrusionPaths paths = loop.paths;
ExtrusionPaths clipped; ExtrusionPaths clipped;
if (clip_length > min_clip_length) { if (clip_length > min_clip_length) {
clipped = clip_end(paths, clip_length); clipped = clip_end(paths, clip_length);
@ -2967,6 +2965,8 @@ std::string GCode::extrude_loop_vase(const ExtrusionLoop &original_loop, const s
} else { } else {
clip_end(paths, clip_length); clip_end(paths, clip_length);
} }
}
if (paths.empty()) return ""; if (paths.empty()) return "";
// apply the small/external? perimeter speed // apply the small/external? perimeter speed
@ -2974,12 +2974,12 @@ std::string GCode::extrude_loop_vase(const ExtrusionLoop &original_loop, const s
coordf_t min_length = scale_d(this->m_config.small_perimeter_min_length.get_abs_value(EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter, 0))); coordf_t min_length = scale_d(this->m_config.small_perimeter_min_length.get_abs_value(EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter, 0)));
coordf_t max_length = scale_d(this->m_config.small_perimeter_max_length.get_abs_value(EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter, 0))); coordf_t max_length = scale_d(this->m_config.small_perimeter_max_length.get_abs_value(EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter, 0)));
max_length = std::max(min_length, max_length); max_length = std::max(min_length, max_length);
if (loop.length() < max_length) { if (full_loop_dist < max_length) {
if (loop.length() <= min_length) { if (full_loop_dist <= min_length) {
speed = m_config.small_perimeter_speed.get_abs_value(m_config.perimeter_speed); speed = m_config.small_perimeter_speed.get_abs_value(m_config.perimeter_speed);
} else if (max_length > min_length) { } else if (max_length > min_length) {
//use a negative speed: it will be use as a ratio when computing the real speed //use a negative speed: it will be use as a ratio when computing the real speed
speed = -(loop.length() - min_length) / (max_length - min_length); speed = -(full_loop_dist - min_length) / (max_length - min_length);
} }
} }
} }
@ -3245,7 +3245,7 @@ std::string GCode::extrude_loop(const ExtrusionLoop &original_loop, const std::s
// get a copy; don't modify the orientation of the original loop object otherwise // get a copy; don't modify the orientation of the original loop object otherwise
// next copies (if any) would not detect the correct orientation // next copies (if any) would not detect the correct orientation
ExtrusionLoop loop = original_loop; ExtrusionLoop loop_to_seam = original_loop;
if (m_layer->lower_layer != nullptr && lower_layer_edge_grid != nullptr) { if (m_layer->lower_layer != nullptr && lower_layer_edge_grid != nullptr) {
if (! *lower_layer_edge_grid) { if (! *lower_layer_edge_grid) {
@ -3271,48 +3271,55 @@ std::string GCode::extrude_loop(const ExtrusionLoop &original_loop, const std::s
// extrude all loops ccw // extrude all loops ccw
//no! this was decided in perimeter_generator //no! this was decided in perimeter_generator
//but we need to know where is "inside", so we will use is_hole_loop. if is_hole_loop, then we need toconsider that the right direction is clockwise, else counter clockwise. //but we need to know where is "inside", so we will use is_hole_loop. if is_hole_loop, then we need toconsider that the right direction is clockwise, else counter clockwise.
bool is_hole_loop = (loop.loop_role() & ExtrusionLoopRole::elrHole) != 0;// loop.make_counter_clockwise(); bool is_hole_loop = (loop_to_seam.loop_role() & ExtrusionLoopRole::elrHole) != 0;// loop.make_counter_clockwise();
//if spiral vase, we have to ensure that all loops are in the same orientation. //if spiral vase, we have to ensure that all loops are in the same orientation.
if (this->m_config.spiral_vase) { if (this->m_config.spiral_vase) {
loop.make_counter_clockwise(); loop_to_seam.make_counter_clockwise();
is_hole_loop = false; is_hole_loop = false;
} }
split_at_seam_pos(loop, lower_layer_edge_grid, is_hole_loop); split_at_seam_pos(loop_to_seam, lower_layer_edge_grid, is_hole_loop);
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
// clip the path to avoid the extruder to get exactly on the first point of the loop; // 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 // if polyline was shorter than the clipping distance we'd get a null polyline, so
// we discard it in that case // we discard it in that case
coordf_t clip_length = 0; ExtrusionPaths& paths = loop_to_seam.paths;
if (m_enable_loop_clipping && m_writer.tool_is_extruder()) {
coordf_t clip_length = scale_(m_config.seam_gap.get_abs_value(m_writer.tool()->id(), EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter, 0)));
coordf_t min_clip_length = scale_(EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter, 0)) * 0.15; coordf_t min_clip_length = scale_(EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter, 0)) * 0.15;
if (m_enable_loop_clipping && m_writer.tool_is_extruder())
clip_length = scale_(m_config.seam_gap.get_abs_value(m_writer.tool()->id(), EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter, 0)));
// get paths // get paths
ExtrusionPaths paths = loop.paths;
ExtrusionPaths clipped; ExtrusionPaths clipped;
if (clip_length > min_clip_length) { if (clip_length > min_clip_length) {
// remove clip_length, like normally, but keep the removed part
clipped = clip_end(paths, clip_length); clipped = clip_end(paths, clip_length);
// remove min_clip_length from the removed paths
clip_end(clipped, min_clip_length); clip_end(clipped, min_clip_length);
// ensure that the removed paths are travels
for (ExtrusionPath& ep : clipped) for (ExtrusionPath& ep : clipped)
ep.mm3_per_mm = 0; ep.mm3_per_mm = 0;
// re-add removed paths as travels.
append(paths, clipped); append(paths, clipped);
} else { } else {
clip_end(paths, clip_length); clip_end(paths, clip_length);
} }
}
if (paths.empty()) return ""; if (paths.empty()) return "";
// apply the small perimeter speed // apply the small perimeter speed
if (speed == -1 && is_perimeter(paths.front().role()) && loop.length() <= if (speed == -1 && is_perimeter(paths.front().role()) && full_loop_length <=
scale_(this->m_config.small_perimeter_max_length.get_abs_value(EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter, 0)))) { scale_(this->m_config.small_perimeter_max_length.get_abs_value(EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter, 0)))) {
double min_length = scale_d(this->m_config.small_perimeter_min_length.get_abs_value(EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter, 0))); double min_length = scale_d(this->m_config.small_perimeter_min_length.get_abs_value(EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter, 0)));
double max_length = scale_d(this->m_config.small_perimeter_max_length.get_abs_value(EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter, 0))); double max_length = scale_d(this->m_config.small_perimeter_max_length.get_abs_value(EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter, 0)));
if (loop.length() <= min_length) { if (full_loop_length <= min_length) {
speed = m_config.small_perimeter_speed.get_abs_value(m_config.perimeter_speed); speed = m_config.small_perimeter_speed.get_abs_value(m_config.perimeter_speed);
} else { } else {
//set speed between -1 and 0 you have to multiply the real peed by the opposite of that, and add the other part as small_perimeter_speed //set speed between -1 and 0 you have to multiply the real peed by the opposite of that, and add the other part as small_perimeter_speed
speed = (min_length - loop.length()) / (max_length - min_length); speed = (min_length - full_loop_length) / (max_length - min_length);
} }
} }
@ -3331,8 +3338,9 @@ std::string GCode::extrude_loop(const ExtrusionLoop &original_loop, const std::s
if (m_wipe.enable) if (m_wipe.enable)
m_wipe.path = paths.front().polyline; // TODO: don't limit wipe to last path m_wipe.path = paths.front().polyline; // TODO: don't limit wipe to last path
//wipe for External Perimeter //wipe for External Perimeter (and not vase)
if (paths.back().role() == erExternalPerimeter && m_layer != NULL && m_config.perimeters.value > 0 && paths.front().size() >= 2 && paths.back().polyline.points.size() >= 2) { if (paths.back().role() == erExternalPerimeter && m_layer != NULL && m_config.perimeters.value > 0 && paths.front().size() >= 2 && paths.back().polyline.points.size() >= 2
&& (m_enable_loop_clipping && m_writer.tool_is_extruder()) ) {
//get points for wipe //get points for wipe
Point prev_point = *(paths.back().polyline.points.end() - 2); // second to last point Point prev_point = *(paths.back().polyline.points.end() - 2); // second to last point
// *(paths.back().polyline.points.end() - 2) this is the same as (or should be) as paths.front().first_point(); // *(paths.back().polyline.points.end() - 2) this is the same as (or should be) as paths.front().first_point();
@ -3395,14 +3403,14 @@ std::string GCode::extrude_loop(const ExtrusionLoop &original_loop, const std::s
//FIXME improve the algorithm in case the loop is split into segments with a low number of points (see the Point b query). //FIXME improve the algorithm in case the loop is split into segments with a low number of points (see the Point b query).
Point a = next_point; // second point Point a = next_point; // second point
Point b = prev_point; // second to last point Point b = prev_point; // second to last point
if (is_hole_loop ? loop.polygon().is_counter_clockwise() : loop.polygon().is_clockwise()) { if (is_hole_loop ? is_full_loop_ccw : (!is_full_loop_ccw)) {
// swap points // swap points
Point c = a; a = b; b = c; Point c = a; a = b; b = c;
} }
double angle = current_point.ccw_angle(a, b) / 3; double angle = current_point.ccw_angle(a, b) / 3;
// turn left if contour, turn right if hole // turn left if contour, turn right if hole
if (is_hole_loop ? loop.polygon().is_counter_clockwise() : loop.polygon().is_clockwise()) angle *= -1; if (is_hole_loop ? is_full_loop_ccw : (!is_full_loop_ccw)) angle *= -1;
// create the destination point along the first segment and rotate it // create the destination point along the first segment and rotate it
// we make sure we don't exceed the segment length because we don't know // we make sure we don't exceed the segment length because we don't know