Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/supermerill/SuperSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorsupermerill <merill@free.fr>2021-12-29 18:03:23 +0300
committersupermerill <merill@free.fr>2021-12-29 18:03:23 +0300
commitb0a79d9ce5c9a5d8b792549b22e2477520c8aff1 (patch)
tree24b3a4d42fa97322847e3d88f06b5176c4802483 /src
parentde7bfabae8677914aab6bb047e5fcaf24f7b7d6d (diff)
parentfee585a0ae5833d3a782cde63afafe950d08ed9a (diff)
merge more fixes
Diffstat (limited to 'src')
-rw-r--r--src/libslic3r/GCode.cpp159
-rw-r--r--src/libslic3r/MedialAxis.cpp55
-rw-r--r--src/slic3r/GUI/Tab.cpp4
3 files changed, 138 insertions, 80 deletions
diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp
index 6a4b0a97a..8c034318b 100644
--- a/src/libslic3r/GCode.cpp
+++ b/src/libslic3r/GCode.cpp
@@ -2916,7 +2916,7 @@ std::string GCode::extrude_loop_vase(const ExtrusionLoop &original_loop, const s
speed = -1;
// get a copy; don't modify the orientation of the original loop object otherwise
// 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 (!*lower_layer_edge_grid) {
@@ -2941,31 +2941,31 @@ std::string GCode::extrude_loop_vase(const ExtrusionLoop &original_loop, const s
// extrude all loops ccw
//no! this was decided in perimeter_generator
- bool is_hole_loop = (loop.loop_role() & ExtrusionLoopRole::elrHole) != 0;// loop.make_counter_clockwise();
- bool reverse_turn = loop.polygon().is_clockwise() ^ is_hole_loop;
+ bool is_hole_loop = (loop_to_seam.loop_role() & ExtrusionLoopRole::elrHole) != 0;// loop.make_counter_clockwise();
+ 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_length = loop_to_seam.length();
- // 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
- coordf_t clip_length = 0;
+ // don't clip the path ?
+ ExtrusionPaths &paths = loop_to_seam.paths;
+ if (false && 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;
- 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
- ExtrusionPaths paths = loop.paths;
- ExtrusionPaths clipped;
- if (clip_length > min_clip_length) {
- clipped = clip_end(paths, clip_length);
- clip_end(clipped, min_clip_length);
- for (ExtrusionPath& ep : clipped)
- ep.mm3_per_mm = 0;
- append(paths, clipped);
- } else {
- clip_end(paths, clip_length);
+
+ // get paths
+ ExtrusionPaths clipped;
+ if (clip_length > min_clip_length) {
+ clipped = clip_end(paths, clip_length);
+ clip_end(clipped, min_clip_length);
+ for (ExtrusionPath& ep : clipped)
+ ep.mm3_per_mm = 0;
+ append(paths, clipped);
+ } else {
+ clip_end(paths, clip_length);
+ }
}
+
if (paths.empty()) return "";
// apply the small/external? perimeter speed
@@ -2973,12 +2973,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 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);
- if (loop.length() < max_length) {
- if (loop.length() <= min_length) {
+ if (full_loop_length < max_length) {
+ if (full_loop_length <= min_length) {
speed = SMALL_PERIMETER_SPEED_RATIO_OFFSET;
} else if (max_length > min_length) {
//use a negative speed: it will be use as a ratio when computing the real speed
- speed = SMALL_PERIMETER_SPEED_RATIO_OFFSET - (loop.length() - min_length) / (max_length - min_length);
+ speed = SMALL_PERIMETER_SPEED_RATIO_OFFSET - (full_loop_length - min_length) / (max_length - min_length);
}
}
}
@@ -3244,7 +3244,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
// 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 (! *lower_layer_edge_grid) {
@@ -3270,35 +3270,42 @@ std::string GCode::extrude_loop(const ExtrusionLoop &original_loop, const std::s
// extrude all loops ccw
//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.
- 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 (this->m_config.spiral_vase) {
- loop.make_counter_clockwise();
+ loop_to_seam.make_counter_clockwise();
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;
// if polyline was shorter than the clipping distance we'd get a null polyline, so
// we discard it in that case
- coordf_t clip_length = 0;
- 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
- ExtrusionPaths paths = loop.paths;
- ExtrusionPaths clipped;
- if (clip_length > min_clip_length) {
- clipped = clip_end(paths, clip_length);
- clip_end(clipped, min_clip_length);
- for (ExtrusionPath& ep : clipped)
- ep.mm3_per_mm = 0;
- append(paths, clipped);
- } else {
- clip_end(paths, clip_length);
+ 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;
+
+ // get paths
+ ExtrusionPaths clipped;
+ if (clip_length > min_clip_length) {
+ // remove clip_length, like normally, but keep the removed part
+ clipped = clip_end(paths, clip_length);
+ // remove min_clip_length from the removed paths
+ clip_end(clipped, min_clip_length);
+ // ensure that the removed paths are travels
+ for (ExtrusionPath& ep : clipped)
+ ep.mm3_per_mm = 0;
+ // re-add removed paths as travels.
+ append(paths, clipped);
+ } else {
+ clip_end(paths, clip_length);
+ }
}
if (paths.empty()) return "";
@@ -3306,12 +3313,12 @@ std::string GCode::extrude_loop(const ExtrusionLoop &original_loop, const std::s
if (speed == -1 && is_perimeter(paths.front().role()) && paths.front().role() != erThinWall) {
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)));
- if (loop.length() < max_length) {
- if (loop.length() <= min_length) {
+ if (full_loop_length < max_length) {
+ if (full_loop_length <= min_length) {
speed = SMALL_PERIMETER_SPEED_RATIO_OFFSET;
} else if (max_length > min_length) {
//use a negative speed: it will be use as a ratio when computing the real speed
- speed = SMALL_PERIMETER_SPEED_RATIO_OFFSET - (loop.length() - min_length) / (max_length - min_length);
+ speed = SMALL_PERIMETER_SPEED_RATIO_OFFSET - (full_loop_length - min_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)
m_wipe.path = paths.front().polyline; // TODO: don't limit wipe to last path
- //wipe for External Perimeter
- if (paths.back().role() == erExternalPerimeter && m_layer != NULL && m_config.perimeters.value > 0 && paths.front().size() >= 2 && paths.back().polyline.points.size() >= 2) {
+ //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
+ && (m_enable_loop_clipping && m_writer.tool_is_extruder()) ) {
//get points for wipe
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();
@@ -3349,32 +3357,32 @@ std::string GCode::extrude_loop(const ExtrusionLoop &original_loop, const std::s
ExtrusionPath& path = paths[i];
if (wipe_dist > 0) {
//first, we use the polyline for wipe_extra_perimeter
- if (path.length() < wipe_dist) {
- wipe_dist -= path.length();
- paths_wipe.push_back(path);
- } else {
- paths_wipe.push_back(path);
- paths_wipe.back().clip_end(path.length() - wipe_dist);
-
- ExtrusionPath next_point_path = path;
- next_point_path.reverse();
- next_point_path.clip_end(wipe_dist);
- next_point_path.reverse();
- if (next_point_path.size() > 1) {
- next_point = next_point_path.polyline.points[1];
- } else if (i + 1 < paths.size()) {
- next_point = paths[i + 1].first_point();
+ if (path.length() < wipe_dist) {
+ wipe_dist -= path.length();
+ paths_wipe.push_back(path);
} else {
- next_point = paths[0].first_point();
+ paths_wipe.push_back(path);
+ paths_wipe.back().clip_end(path.length() - wipe_dist);
+
+ ExtrusionPath next_point_path = path;
+ next_point_path.reverse();
+ next_point_path.clip_end(wipe_dist);
+ next_point_path.reverse();
+ if (next_point_path.size() > 1) {
+ next_point = next_point_path.polyline.points[1];
+ } else if (i + 1 < paths.size()) {
+ next_point = paths[i + 1].first_point();
+ } else {
+ next_point = paths[0].first_point();
+ }
+ m_wipe.path.append(path.polyline);
+ m_wipe.path.clip_start(wipe_dist);
+ wipe_dist -= path.length();
}
- m_wipe.path.append(path.polyline);
- m_wipe.path.clip_start(wipe_dist);
- wipe_dist -= path.length();
- }
} else {
//then, it's stored for the wipe on retract
m_wipe.path.append(path.polyline);
- }
+ }
}
//move
for (ExtrusionPath& path : paths_wipe) {
@@ -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).
Point a = next_point; // second 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
Point c = a; a = b; b = c;
}
double angle = current_point.ccw_angle(a, b) / 3;
// 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
// we make sure we don't exceed the segment length because we don't know
@@ -4438,13 +4446,18 @@ Polyline GCode::travel_to(std::string &gcode, const Point &point, ExtrusionRole
Point last_post_before_retract = this->last_pos();
gcode += this->retract();
// When "Wipe while retracting" is enabled, then extruder moves to another position, and travel from this position can cross perimeters.
+ bool updated_first_pos = false;
if (last_post_before_retract != this->last_pos() && can_avoid_cross_peri) {
// Is the distance is short enough to just shortcut it?
if (last_post_before_retract.distance_to(this->last_pos()) > scale_d(EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter, 0.4)) * 2) {
// Because of it, it is necessary to redo the thing
travel = m_avoid_crossing_perimeters.travel_to(*this, point);
+ updated_first_pos = true;
}
}
+ if (!updated_first_pos) {
+ travel.points.front() = this->last_pos();
+ }
} else {
// Reset the wipe path when traveling, so one would not wipe along an old path.
m_wipe.reset_path();
diff --git a/src/libslic3r/MedialAxis.cpp b/src/libslic3r/MedialAxis.cpp
index 02b4816e2..e9fc6ee4f 100644
--- a/src/libslic3r/MedialAxis.cpp
+++ b/src/libslic3r/MedialAxis.cpp
@@ -651,6 +651,8 @@ MedialAxis::remove_bits(ThickPolylines &pp)
///reorder, in case of change
std::sort(pp.begin(), pp.end(), [](const ThickPolyline & a, const ThickPolyline & b) { return a.length() < b.length(); });
}
+
+ //TODO: check if there is a U-turn (almost 180° direction change) : remove it.
}
void
@@ -1492,6 +1494,40 @@ MedialAxis::remove_too_short_polylines(ThickPolylines& pp, const coord_t min_siz
}
if (changes) concatThickPolylines(pp);
}
+
+ //remove points too near each other
+ changes = true;
+ while (changes) {
+ changes = false;
+
+ coordf_t shortest_size = (coordf_t)min_size;
+ size_t shortest_idx = -1;
+ for (size_t polyidx = 0; polyidx < pp.size(); ++polyidx) {
+ ThickPolyline& tp = pp[polyidx];
+ for (size_t pt_idx = 1; pt_idx < tp.points.size() - 1; pt_idx++) {
+ if (tp.points[pt_idx - 1].coincides_with_epsilon(tp.points[pt_idx])) {
+ tp.points.erase(tp.points.begin() + pt_idx);
+ tp.width.erase(tp.width.begin() + pt_idx);
+ pt_idx--;
+ changes = true;
+ }
+ }
+ //check last segment
+ if (tp.points.size() > 2 && tp.points[tp.points.size() - 2].coincides_with_epsilon(tp.points.back())) {
+ tp.points.erase(tp.points.end() - 2);
+ tp.width.erase(tp.width.end() - 2);
+ changes = true;
+ }
+ //delete null-length polylines
+ if (tp.length() < SCALED_EPSILON && tp.first_point().coincides_with_epsilon(tp.last_point())) {
+ pp.erase(pp.begin() + polyidx);
+ --polyidx;
+ changes = true;
+ }
+ }
+ if (changes) concatThickPolylines(pp);
+ }
+
}
void
@@ -2037,7 +2073,7 @@ thin_variable_width(const ThickPolylines &polylines, ExtrusionRole role, Flow fl
// variable extrusion within a single move; this value shall only affect the amount
// of segments, and any pruning shall be performed before we apply this tolerance
const coord_t tolerance = flow.scaled_width() / 10;//scale_(0.05);
-
+
ExtrusionEntityCollection coll;
for (const ThickPolyline &p : polylines) {
ExtrusionPaths paths;
@@ -2052,8 +2088,8 @@ thin_variable_width(const ThickPolylines &polylines, ExtrusionRole role, Flow fl
const coordf_t prev_line_len = saved_line_len;
saved_line_len = line_len;
- assert(line.a_width >= 0);
- assert(line.b_width >= 0);
+ assert(line.a_width >= 0 && !std::isnan(line.a_width));
+ assert(line.b_width >= 0 && !std::isnan(line.b_width));
coord_t thickness_delta = std::abs(line.a_width - line.b_width);
// split lines ?
@@ -2108,7 +2144,16 @@ thin_variable_width(const ThickPolylines &polylines, ExtrusionRole role, Flow fl
coordf_t width = prev_line_len * (prev_line.a_width + prev_line.b_width) / 2;
width += line_len * (line.a_width + line.b_width) / 2;
prev_line.b = line.b;
- coordf_t new_length = prev_line.length();
+ const coordf_t new_length = prev_line.length();
+ if (new_length < SCALED_EPSILON) {
+ // too short, remove it and restart
+ if (i > 1) {
+ line.a = lines[i - 2].b;
+ }
+ lines.erase(lines.begin() + i-1);
+ i-=2;
+ continue;
+ }
width /= new_length;
prev_line.a_width = width;
prev_line.b_width = width;
@@ -2131,7 +2176,7 @@ thin_variable_width(const ThickPolylines &polylines, ExtrusionRole role, Flow fl
// but we can't extrude with a negative spacing, so we have to gradually fall back to spacing if the width is too small.
// default: extrude a thin wall that doesn't go outside of the specified width.
- double wanted_width = unscaled(line.a_width);
+ coordf_t wanted_width = unscaled(line.a_width);
if (role == erGapFill) {
// Convert from spacing to extrusion width based on the extrusion model
// of a square extrusion ended with semi circles.
diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp
index 38ec11954..2e7ccf7c3 100644
--- a/src/slic3r/GUI/Tab.cpp
+++ b/src/slic3r/GUI/Tab.cpp
@@ -2348,7 +2348,7 @@ void TabFilament::add_filament_overrides_page()
"filament_retract_layer_change",
"filament_seam_gap",
"filament_wipe",
- "filament_wipe_extra_perimeter",
+ "filament_wipe_only_crossing",
"filament_wipe_speed",
"filament_wipe_extra_perimeter"
})
@@ -2378,7 +2378,7 @@ void TabFilament::update_filament_overrides_page()
"filament_retract_layer_change",
"filament_seam_gap",
"filament_wipe",
- "filament_wipe_extra_perimeter",
+ "filament_wipe_only_crossing",
"filament_wipe_speed",
"filament_wipe_extra_perimeter"
};