ENH: Add gaps in the outer wall of the wipe_tower
and modify the path of travel to the wipe_tower after flushing jira:none Change-Id: Id4b0571fd12372c59cf522c13e256c7cc4ac3565 (cherry picked from commit 17771d0fbf753dd22411ce490586958bd643264e)
This commit is contained in:
@@ -2840,6 +2840,98 @@ bool GCodeProcessor::get_last_z_from_gcode(const std::string& gcode_str, double&
|
||||
return is_z_changed;
|
||||
}
|
||||
|
||||
bool GCodeProcessor::get_last_position_from_gcode(const std::string &gcode_str, Vec3f &pos)
|
||||
{
|
||||
int str_size = gcode_str.size();
|
||||
int start_index = 0;
|
||||
int end_index = 0;
|
||||
bool is_z_changed = false;
|
||||
while (end_index < str_size) {
|
||||
// find a full line
|
||||
if (gcode_str[end_index] != '\n') {
|
||||
end_index++;
|
||||
continue;
|
||||
}
|
||||
// parse the line
|
||||
if (end_index > start_index) {
|
||||
std::string line_str = gcode_str.substr(start_index, end_index - start_index);
|
||||
line_str.erase(0, line_str.find_first_not_of(" "));
|
||||
line_str.erase(line_str.find_last_not_of(";") + 1);
|
||||
line_str.erase(line_str.find_last_not_of(" ") + 1);
|
||||
|
||||
// command which may have z movement
|
||||
if (line_str.size() > 5 && (line_str.find("G0 ") == 0 || line_str.find("G1 ") == 0 || line_str.find("G2 ") == 0 || line_str.find("G3 ") == 0)) {
|
||||
{
|
||||
float &x = pos.x();
|
||||
auto z_pos = line_str.find(" X");
|
||||
float temp_z = 0;
|
||||
if (z_pos != line_str.npos && z_pos + 2 < line_str.size()) {
|
||||
// Try to parse the numeric value.
|
||||
std::string z_sub = line_str.substr(z_pos + 2);
|
||||
char *c = &z_sub[0];
|
||||
char *end = c + sizeof(z_sub.c_str());
|
||||
|
||||
auto is_end_of_word = [](char c) { return c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == 0 || c == ';'; };
|
||||
|
||||
auto [pend, ec] = fast_float::from_chars(c, end, temp_z);
|
||||
if (pend != c && is_end_of_word(*pend)) {
|
||||
// The axis value has been parsed correctly.
|
||||
x = temp_z;
|
||||
is_z_changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
float &y = pos.y();
|
||||
auto z_pos = line_str.find(" Y");
|
||||
float temp_z = 0;
|
||||
if (z_pos != line_str.npos && z_pos + 2 < line_str.size()) {
|
||||
// Try to parse the numeric value.
|
||||
std::string z_sub = line_str.substr(z_pos + 2);
|
||||
char *c = &z_sub[0];
|
||||
char *end = c + sizeof(z_sub.c_str());
|
||||
|
||||
auto is_end_of_word = [](char c) { return c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == 0 || c == ';'; };
|
||||
|
||||
auto [pend, ec] = fast_float::from_chars(c, end, temp_z);
|
||||
if (pend != c && is_end_of_word(*pend)) {
|
||||
// The axis value has been parsed correctly.
|
||||
y = temp_z;
|
||||
is_z_changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
float &z = pos.z();
|
||||
auto z_pos = line_str.find(" Z");
|
||||
float temp_z = 0;
|
||||
if (z_pos != line_str.npos && z_pos + 2 < line_str.size()) {
|
||||
// Try to parse the numeric value.
|
||||
std::string z_sub = line_str.substr(z_pos + 2);
|
||||
char *c = &z_sub[0];
|
||||
char *end = c + sizeof(z_sub.c_str());
|
||||
|
||||
auto is_end_of_word = [](char c) { return c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == 0 || c == ';'; };
|
||||
|
||||
auto [pend, ec] = fast_float::from_chars(c, end, temp_z);
|
||||
if (pend != c && is_end_of_word(*pend)) {
|
||||
// The axis value has been parsed correctly.
|
||||
z = temp_z;
|
||||
is_z_changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// loop to handle next line
|
||||
start_index = end_index + 1;
|
||||
end_index = start_index;
|
||||
}
|
||||
return is_z_changed;
|
||||
}
|
||||
|
||||
void GCodeProcessor::process_tags(const std::string_view comment, bool producers_enabled)
|
||||
{
|
||||
// producers tags
|
||||
|
||||
@@ -347,6 +347,7 @@ class Print;
|
||||
|
||||
static int get_gcode_last_filament(const std::string &gcode_str);
|
||||
static bool get_last_z_from_gcode(const std::string& gcode_str, double& z);
|
||||
static bool get_last_position_from_gcode(const std::string &gcode_str, Vec3f &pos);
|
||||
|
||||
static const float Wipe_Width;
|
||||
static const float Wipe_Height;
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
namespace Slic3r
|
||||
{
|
||||
static const double wipe_tower_wall_infill_overlap = 0.0;
|
||||
|
||||
static const double wipe_tower_wall_infill_overlap_new = -0.2;
|
||||
static bool is_used_gap_wall = true;
|
||||
inline float align_round(float value, float base)
|
||||
{
|
||||
return std::round(value / base) * base;
|
||||
@@ -60,6 +61,39 @@ static bool is_valid_gcode(const std::string &gcode)
|
||||
return is_valid;
|
||||
}
|
||||
|
||||
struct Segment
|
||||
{
|
||||
Vec2f start;
|
||||
Vec2f end;
|
||||
|
||||
Segment(const Vec2f &s, const Vec2f &e) : start(s), end(e) {}
|
||||
bool is_valid() const { return start.y() < end.y(); }
|
||||
};
|
||||
|
||||
static std::vector<Segment> remove_points_from_segment(const Segment &segment, const std::vector<Vec2f> &skip_points, double range)
|
||||
{
|
||||
std::vector<Segment> result;
|
||||
result.push_back(segment);
|
||||
float x = segment.start.x();
|
||||
|
||||
for (const Vec2f &point : skip_points) {
|
||||
std::vector<Segment> newResult;
|
||||
for (const auto &seg : result) {
|
||||
if (point.y() + range <= seg.start.y() || point.y() - range >= seg.end.y()) {
|
||||
newResult.push_back(seg);
|
||||
} else {
|
||||
if (point.y() - range > seg.start.y()) { newResult.push_back(Segment(Vec2f(x, seg.start.y()), Vec2f(x, point.y() - range))); }
|
||||
if (point.y() + range < seg.end.y()) { newResult.push_back(Segment(Vec2f(x, point.y() + range), Vec2f(x, seg.end.y()))); }
|
||||
}
|
||||
}
|
||||
|
||||
result = newResult;
|
||||
}
|
||||
|
||||
result.erase(std::remove_if(result.begin(), result.end(), [](const Segment &seg) { return !seg.is_valid(); }), result.end());
|
||||
return result;
|
||||
}
|
||||
|
||||
class WipeTowerWriter
|
||||
{
|
||||
public:
|
||||
@@ -773,18 +807,19 @@ Vec2f WipeTower::get_next_pos(const WipeTower::box_coordinates &cleaning_box, fl
|
||||
|
||||
Vec2f res;
|
||||
int index = m_cur_layer_id % 4;
|
||||
Vec2f offset = is_used_gap_wall ? Vec2f(5 * m_perimeter_width, 0) : Vec2f{0, 0};
|
||||
switch (index % 4) {
|
||||
case 0:
|
||||
res = cleaning_box.ld + pos_offset;
|
||||
res = offset +cleaning_box.ld + pos_offset;
|
||||
break;
|
||||
case 1:
|
||||
res = cleaning_box.rd + pos_offset + Vec2f(0, y_offset);
|
||||
res = -offset +cleaning_box.rd + pos_offset + Vec2f(0, y_offset);
|
||||
break;
|
||||
case 2:
|
||||
res = cleaning_box.rd + pos_offset;
|
||||
res = -offset+ cleaning_box.rd + pos_offset;
|
||||
break;
|
||||
case 3:
|
||||
res = cleaning_box.ld + pos_offset + Vec2f(0, y_offset);
|
||||
res = offset+cleaning_box.ld + pos_offset + Vec2f(0, y_offset);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
@@ -1821,7 +1856,7 @@ static WipeTower::ToolChangeResult merge_tcr(WipeTower::ToolChangeResult& first,
|
||||
{
|
||||
assert(first.new_tool == second.initial_tool);
|
||||
WipeTower::ToolChangeResult out = first;
|
||||
if (first.end_pos != second.start_pos)
|
||||
if ((first.end_pos - second.start_pos).norm()> (float)EPSILON)
|
||||
out.gcode += "G1 X" + Slic3r::float_to_string_decimal_point(second.start_pos.x(), 3)
|
||||
+ " Y" + Slic3r::float_to_string_decimal_point(second.start_pos.y(), 3)
|
||||
+ " F7200\n";
|
||||
@@ -1842,6 +1877,50 @@ static WipeTower::ToolChangeResult merge_tcr(WipeTower::ToolChangeResult& first,
|
||||
return out;
|
||||
}
|
||||
|
||||
void WipeTower::get_wall_skip_points(const WipeTowerInfo &layer)
|
||||
{
|
||||
m_wall_skip_points.clear();
|
||||
std::unordered_map<int, float> cur_block_depth;
|
||||
for (int i = 0; i < int(layer.tool_changes.size()); ++i) {
|
||||
const WipeTowerInfo::ToolChange &tool_change = layer.tool_changes[i];
|
||||
size_t old_filament = tool_change.old_tool;
|
||||
size_t new_filament = tool_change.new_tool;
|
||||
float spacing = m_layer_info->extra_spacing;
|
||||
if (has_tpu_filament() && m_layer_info->extra_spacing < m_tpu_fixed_spacing) spacing = 1;
|
||||
float nozzle_change_depth = tool_change.nozzle_change_depth * spacing;
|
||||
//float nozzle_change_depth = tool_change.nozzle_change_depth * (has_tpu_filament() ? m_tpu_fixed_spacing : layer.extra_spacing);
|
||||
auto &block = get_block_by_category(m_filpar[new_filament].category);
|
||||
float wipe_depth = tool_change.required_depth - nozzle_change_depth;
|
||||
float process_depth = 0.f;
|
||||
if (!cur_block_depth.count(m_filpar[new_filament].category))
|
||||
cur_block_depth[m_filpar[new_filament].category] = block.start_depth;
|
||||
process_depth = cur_block_depth[m_filpar[new_filament].category];
|
||||
if (!m_filament_map.empty() && new_filament < m_filament_map.size() && m_filament_map[old_filament] != m_filament_map[new_filament]) {
|
||||
if (m_filament_categories[new_filament] == m_filament_categories[old_filament])
|
||||
process_depth += nozzle_change_depth;
|
||||
else {
|
||||
if (!cur_block_depth.count(m_filpar[old_filament].category))
|
||||
cur_block_depth[m_filpar[old_filament].category]=m_perimeter_width; //Here, it is assumed that the bottom-most lines of the blocks are adjacent to the previous line.
|
||||
cur_block_depth[m_filpar[old_filament].category] += nozzle_change_depth;
|
||||
}
|
||||
}
|
||||
{
|
||||
Vec2f res;
|
||||
int index = m_cur_layer_id % 4;
|
||||
switch (index % 4) {
|
||||
case 0: res = Vec2f(0, process_depth); break;
|
||||
case 1: res = Vec2f(m_wipe_tower_width, process_depth + wipe_depth - layer.extra_spacing*m_perimeter_width); break;
|
||||
case 2: res = Vec2f(m_wipe_tower_width, process_depth); break;
|
||||
case 3: res = Vec2f(0, process_depth + wipe_depth - layer.extra_spacing * m_perimeter_width); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
m_wall_skip_points.emplace_back(res);
|
||||
}
|
||||
cur_block_depth[m_filpar[new_filament].category] = process_depth + wipe_depth ;
|
||||
}
|
||||
}
|
||||
|
||||
WipeTower::ToolChangeResult WipeTower::tool_change_new(size_t new_tool)
|
||||
{
|
||||
m_nozzle_change_result.gcode.clear();
|
||||
@@ -1930,7 +2009,6 @@ WipeTower::ToolChangeResult WipeTower::tool_change_new(size_t new_tool)
|
||||
Vec2f initial_position = get_next_pos(cleaning_box, wipe_length);
|
||||
//Vec2f initial_position = cleaning_box.ld;
|
||||
writer.set_initial_position(initial_position + Vec2f(m_perimeter_width, m_perimeter_width), m_wipe_tower_width, m_wipe_tower_depth, m_internal_rotation);
|
||||
|
||||
writer.travel(initial_position);
|
||||
|
||||
toolchange_wipe_new(writer, cleaning_box, wipe_length);
|
||||
@@ -2164,7 +2242,10 @@ WipeTower::ToolChangeResult WipeTower::finish_layer_new(bool extrude_perimeter,
|
||||
box_coordinates wt_box(Vec2f(0.f, 0.f), m_wipe_tower_width, wipe_tower_depth);
|
||||
wt_box = align_perimeter(wt_box);
|
||||
if (extrude_perimeter) {
|
||||
writer.rectangle(wt_box, feedrate);
|
||||
if (is_used_gap_wall)
|
||||
generate_support_wall(writer, wt_box, feedrate, first_layer);
|
||||
else
|
||||
writer.rectangle(wt_box, feedrate);
|
||||
}
|
||||
|
||||
// brim chamfer
|
||||
@@ -2436,10 +2517,33 @@ void WipeTower::toolchange_wipe_new(WipeTowerWriter &writer, const box_coordinat
|
||||
need_change_flow = true;
|
||||
}
|
||||
|
||||
if (m_left_to_right)
|
||||
writer.extrude(xr + wipe_tower_wall_infill_overlap * m_perimeter_width, writer.y(), wipe_speed);
|
||||
else
|
||||
writer.extrude(xl - wipe_tower_wall_infill_overlap * m_perimeter_width, writer.y(), wipe_speed);
|
||||
float ironing_length = 3.;
|
||||
if (i == 0 && is_used_gap_wall) { // BBS: add ironing after extruding start
|
||||
if (m_left_to_right) {
|
||||
float dx = xr + wipe_tower_wall_infill_overlap_new * m_perimeter_width - writer.pos().x();
|
||||
if (abs(dx) < ironing_length) ironing_length = abs(dx);
|
||||
writer.extrude(writer.x() + ironing_length, writer.y(), wipe_speed);
|
||||
writer.retract(0.8, 1800.);
|
||||
writer.travel(writer.x() - 1.5 * ironing_length, writer.y(), 600.);
|
||||
writer.travel(writer.x() + 1.5 * ironing_length, writer.y(), 240.);
|
||||
writer.retract(-0.8, 1800.);
|
||||
writer.extrude(xr + wipe_tower_wall_infill_overlap_new * m_perimeter_width, writer.y(), wipe_speed);
|
||||
} else {
|
||||
float dx = xl - wipe_tower_wall_infill_overlap_new * m_perimeter_width - writer.pos().x();
|
||||
if (abs(dx) < ironing_length) ironing_length = abs(dx);
|
||||
writer.extrude(writer.x() - ironing_length, writer.y(), wipe_speed);
|
||||
writer.retract(0.8, 1800.);
|
||||
writer.travel(writer.x() + 1.5 * ironing_length, writer.y(), 600.);
|
||||
writer.travel(writer.x() - 1.5 * ironing_length, writer.y(), 240.);
|
||||
writer.retract(-0.8, 1800.);
|
||||
writer.extrude(xl - wipe_tower_wall_infill_overlap_new * m_perimeter_width, writer.y(), wipe_speed);
|
||||
}
|
||||
} else {
|
||||
if (m_left_to_right)
|
||||
writer.extrude(xr + wipe_tower_wall_infill_overlap * m_perimeter_width, writer.y(), wipe_speed);
|
||||
else
|
||||
writer.extrude(xl - wipe_tower_wall_infill_overlap * m_perimeter_width, writer.y(), wipe_speed);
|
||||
}
|
||||
|
||||
// BBS: recover the flow in non-bridging area
|
||||
if (need_change_flow) {
|
||||
@@ -2782,7 +2886,6 @@ void WipeTower::generate_new(std::vector<std::vector<WipeTower::ToolChangeResult
|
||||
{
|
||||
if (m_plan.empty())
|
||||
return;
|
||||
|
||||
m_extra_spacing = 1.f;
|
||||
|
||||
plan_tower_new();
|
||||
@@ -2820,6 +2923,8 @@ void WipeTower::generate_new(std::vector<std::vector<WipeTower::ToolChangeResult
|
||||
}
|
||||
}
|
||||
|
||||
get_wall_skip_points(layer);
|
||||
|
||||
ToolChangeResult finish_layer_tcr;
|
||||
ToolChangeResult timelapse_wall;
|
||||
|
||||
@@ -2957,7 +3062,6 @@ void WipeTower::generate_new(std::vector<std::vector<WipeTower::ToolChangeResult
|
||||
if (m_enable_timelapse_print) {
|
||||
layer_result.insert(layer_result.begin(), std::move(timelapse_wall));
|
||||
}
|
||||
|
||||
result.emplace_back(std::move(layer_result));
|
||||
}
|
||||
}
|
||||
@@ -3103,7 +3207,10 @@ WipeTower::ToolChangeResult WipeTower::only_generate_out_wall(bool is_new_mode)
|
||||
wipe_tower_depth = m_wipe_tower_width;
|
||||
box_coordinates wt_box(Vec2f(0.f, (m_current_shape == SHAPE_REVERSED ? m_layer_info->toolchanges_depth() : 0.f)), m_wipe_tower_width, wipe_tower_depth);
|
||||
wt_box = align_perimeter(wt_box);
|
||||
writer.rectangle(wt_box, feedrate);
|
||||
if (is_used_gap_wall)
|
||||
generate_support_wall(writer, wt_box, feedrate, first_layer);
|
||||
else
|
||||
writer.rectangle(wt_box, feedrate);
|
||||
|
||||
// Now prepare future wipe. box contains rectangle that was extruded last (ccw).
|
||||
Vec2f target = (writer.pos() == wt_box.ld ? wt_box.rd : (writer.pos() == wt_box.rd ? wt_box.ru : (writer.pos() == wt_box.ru ? wt_box.lu : wt_box.ld)));
|
||||
@@ -3119,6 +3226,109 @@ WipeTower::ToolChangeResult WipeTower::only_generate_out_wall(bool is_new_mode)
|
||||
return construct_tcr(writer, false, old_tool, true, 0.f);
|
||||
}
|
||||
|
||||
Polygon WipeTower::generate_support_wall(WipeTowerWriter &writer, const box_coordinates &wt_box, double feedrate, bool first_layer)
|
||||
{
|
||||
bool is_left = false;
|
||||
bool is_right = false;
|
||||
for (auto pt : m_wall_skip_points) {
|
||||
if (abs(pt.x()) < EPSILON) {
|
||||
is_left = true;
|
||||
} else if (abs(pt.x() - m_wipe_tower_width) < EPSILON) {
|
||||
is_right = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_left && is_right) {
|
||||
Vec2f *p = nullptr;
|
||||
p->x();
|
||||
}
|
||||
|
||||
if (!is_left && !is_right) {
|
||||
Vec2f *p = nullptr;
|
||||
p->x();
|
||||
}
|
||||
|
||||
// 3 ------------- 2
|
||||
// | |
|
||||
// | |
|
||||
// 0 ------------- 1
|
||||
|
||||
int index = 0;
|
||||
Vec2f cur_pos = writer.pos();
|
||||
if (abs(cur_pos.x() - wt_box.ld.x()) > abs(cur_pos.x() - wt_box.rd.x())) {
|
||||
if (abs(cur_pos.y() - wt_box.ld.y()) > abs(cur_pos.y() - wt_box.lu.y())) {
|
||||
index = 2;
|
||||
} else {
|
||||
index = 1;
|
||||
}
|
||||
} else {
|
||||
if (abs(cur_pos.y() - wt_box.ld.y()) > abs(cur_pos.y() - wt_box.lu.y())) {
|
||||
index = 3;
|
||||
} else {
|
||||
index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Vec2f> points;
|
||||
points.emplace_back(wt_box.ld);
|
||||
points.emplace_back(wt_box.rd);
|
||||
points.emplace_back(wt_box.ru);
|
||||
points.emplace_back(wt_box.lu);
|
||||
|
||||
writer.travel(points[index]);
|
||||
int extruded_nums = 0;
|
||||
while (extruded_nums < 4) {
|
||||
index = (index + 1) % 4;
|
||||
if (index == 2) {
|
||||
if (is_right) {
|
||||
std::vector<Segment> break_segments = remove_points_from_segment(Segment(wt_box.rd, wt_box.ru), m_wall_skip_points, 2.5 * m_perimeter_width);
|
||||
for (auto iter = break_segments.begin(); iter != break_segments.end(); ++iter) {
|
||||
float dx = iter->start.x() - writer.pos().x();
|
||||
float dy = iter->start.y() - writer.pos().y();
|
||||
float len = std::sqrt(dx * dx + dy * dy);
|
||||
if (len > 0) {
|
||||
writer.retract(0.8, 1800.);
|
||||
writer.travel(iter->start, 600.);
|
||||
writer.retract(-0.8, 1800.);
|
||||
} else
|
||||
writer.travel(iter->start, 600.);
|
||||
|
||||
writer.extrude(iter->end, feedrate);
|
||||
}
|
||||
writer.travel(wt_box.ru, feedrate);
|
||||
} else {
|
||||
writer.extrude(wt_box.ru, feedrate);
|
||||
}
|
||||
} else if (index == 0) {
|
||||
if (is_left) {
|
||||
std::vector<Segment> break_segments = remove_points_from_segment(Segment(wt_box.ld, wt_box.lu), m_wall_skip_points, 2.5 * m_perimeter_width);
|
||||
for (auto iter = break_segments.rbegin(); iter != break_segments.rend(); ++iter) {
|
||||
float dx = iter->end.x() - writer.pos().x();
|
||||
float dy = iter->end.y() - writer.pos().y();
|
||||
float len = std::sqrt(dx * dx + dy * dy);
|
||||
if (len > 0) {
|
||||
writer.retract(0.8, 1800.);
|
||||
writer.travel(iter->end, 600.);
|
||||
writer.retract(-0.8, 1800.);
|
||||
} else
|
||||
writer.travel(iter->end, 600.);
|
||||
|
||||
writer.extrude(iter->start, feedrate);
|
||||
}
|
||||
writer.travel(wt_box.ld, feedrate);
|
||||
} else {
|
||||
writer.extrude(wt_box.ld, feedrate);
|
||||
}
|
||||
} else {
|
||||
writer.extrude(points[index], feedrate);
|
||||
}
|
||||
extruded_nums++;
|
||||
}
|
||||
|
||||
return Polygon();
|
||||
}
|
||||
|
||||
|
||||
bool WipeTower::get_floating_area(float &start_pos_y, float &end_pos_y) const {
|
||||
if (m_layer_info == m_plan.begin() || (m_layer_info - 1) == m_plan.begin())
|
||||
return false;
|
||||
|
||||
@@ -175,6 +175,7 @@ public:
|
||||
void generate(std::vector<std::vector<ToolChangeResult>> &result);
|
||||
|
||||
WipeTower::ToolChangeResult only_generate_out_wall(bool is_new_mode = false);
|
||||
Polygon generate_support_wall(WipeTowerWriter &writer, const box_coordinates &wt_box, double feedrate, bool first_layer);
|
||||
|
||||
float get_depth() const { return m_wipe_tower_depth; }
|
||||
float get_brim_width() const { return m_wipe_tower_brim_width_real; }
|
||||
@@ -438,6 +439,7 @@ private:
|
||||
float m_extra_spacing = 1.f;
|
||||
float m_tpu_fixed_spacing = 2;
|
||||
|
||||
std::vector<Vec2f> m_wall_skip_points;
|
||||
bool is_first_layer() const { return size_t(m_layer_info - m_plan.begin()) == m_first_layer_idx; }
|
||||
|
||||
// Calculates length of extrusion line to extrude given volume
|
||||
@@ -522,6 +524,7 @@ private:
|
||||
WipeTowerWriter &writer,
|
||||
const box_coordinates &cleaning_box,
|
||||
float wipe_volume);
|
||||
void get_wall_skip_points(const WipeTowerInfo &layer);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -306,7 +306,7 @@ struct Segment
|
||||
bool is_valid() const { return start.y() < end.y(); }
|
||||
};
|
||||
|
||||
std::vector<Segment> remove_points_from_segment(const Segment& segment, const std::vector<Vec2f>& skip_points, double range)
|
||||
static std::vector<Segment> remove_points_from_segment(const Segment& segment, const std::vector<Vec2f>& skip_points, double range)
|
||||
{
|
||||
std::vector<Segment> result;
|
||||
result.push_back(segment);
|
||||
|
||||
Reference in New Issue
Block a user