mirror of
https://github.com/QIDITECH/QIDISlicer.git
synced 2026-02-01 08:28:42 +03:00
Merge prusa 2.6.1
This commit is contained in:
@@ -792,8 +792,8 @@ std::string CoolingBuffer::apply_layer_cooldown(
|
||||
if (int(layer_id) >= disable_fan_first_layers && int(layer_id) + 1 < full_fan_speed_layer) {
|
||||
// Ramp up the fan speed from disable_fan_first_layers to full_fan_speed_layer.
|
||||
float factor = float(int(layer_id + 1) - disable_fan_first_layers) / float(full_fan_speed_layer - disable_fan_first_layers);
|
||||
fan_speed_new = std::clamp(int(float(fan_speed_new) * factor + 0.5f), 0, 255);
|
||||
bridge_fan_speed = std::clamp(int(float(bridge_fan_speed) * factor + 0.5f), 0, 255);
|
||||
fan_speed_new = std::clamp(int(float(fan_speed_new) * factor + 0.5f), 0, 100);
|
||||
bridge_fan_speed = std::clamp(int(float(bridge_fan_speed) * factor + 0.5f), 0, 100);
|
||||
custom_fan_speed_limits.second = fan_speed_new;
|
||||
}
|
||||
#undef EXTRUDER_CONFIG
|
||||
|
||||
@@ -146,67 +146,68 @@ std::vector<ExtendedPoint> estimate_points_properties(const POINTS
|
||||
std::vector<float> angles_for_curvature(points.size());
|
||||
std::vector<float> distances_for_curvature(points.size());
|
||||
|
||||
for (int point_idx = 0; point_idx < int(points.size()); ++point_idx) {
|
||||
for (size_t point_idx = 0; point_idx < points.size(); ++point_idx) {
|
||||
ExtendedPoint &a = points[point_idx];
|
||||
ExtendedPoint &prev = points[point_idx > 0 ? point_idx - 1 : point_idx];
|
||||
size_t prev = prev_idx_modulo(point_idx, points.size());
|
||||
size_t next = next_idx_modulo(point_idx, points.size());
|
||||
|
||||
int prev_point_idx = point_idx;
|
||||
while (prev_point_idx > 0) {
|
||||
prev_point_idx--;
|
||||
if ((a.position - points[prev_point_idx].position).squaredNorm() > EPSILON) {
|
||||
break;
|
||||
}
|
||||
int iter_limit = points.size();
|
||||
while ((a.position - points[prev].position).squaredNorm() < 1 && iter_limit > 0) {
|
||||
prev = prev_idx_modulo(prev, points.size());
|
||||
iter_limit--;
|
||||
}
|
||||
|
||||
int next_point_index = point_idx;
|
||||
while (next_point_index < int(points.size()) - 1) {
|
||||
next_point_index++;
|
||||
if ((a.position - points[next_point_index].position).squaredNorm() > EPSILON) {
|
||||
break;
|
||||
}
|
||||
while ((a.position - points[next].position).squaredNorm() < 1 && iter_limit > 0) {
|
||||
next = next_idx_modulo(next, points.size());
|
||||
iter_limit--;
|
||||
}
|
||||
|
||||
distances_for_curvature[point_idx] = (prev.position - a.position).norm();
|
||||
if (prev_point_idx != point_idx && next_point_index != point_idx) {
|
||||
float alfa = angle(a.position - points[prev_point_idx].position, points[next_point_index].position - a.position);
|
||||
angles_for_curvature[point_idx] = alfa;
|
||||
} // else keep zero
|
||||
distances_for_curvature[point_idx] = (points[prev].position - a.position).norm();
|
||||
float alfa = angle(a.position - points[prev].position, points[next].position - a.position);
|
||||
angles_for_curvature[point_idx] = alfa;
|
||||
}
|
||||
|
||||
for (float window_size : {3.0f, 9.0f, 16.0f}) {
|
||||
size_t tail_point = 0;
|
||||
float tail_window_acc = 0;
|
||||
float tail_angle_acc = 0;
|
||||
if (std::accumulate(distances_for_curvature.begin(), distances_for_curvature.end(), 0) > EPSILON)
|
||||
for (float window_size : {3.0f, 9.0f, 16.0f}) {
|
||||
size_t tail_point = 0;
|
||||
float tail_window_acc = 0;
|
||||
float tail_angle_acc = 0;
|
||||
|
||||
size_t head_point = 0;
|
||||
float head_window_acc = 0;
|
||||
float head_angle_acc = 0;
|
||||
size_t head_point = 0;
|
||||
float head_window_acc = 0;
|
||||
float head_angle_acc = 0;
|
||||
|
||||
for (int point_idx = 0; point_idx < int(points.size()); ++point_idx) {
|
||||
if (point_idx > 0) {
|
||||
tail_window_acc += distances_for_curvature[point_idx - 1];
|
||||
tail_angle_acc += angles_for_curvature[point_idx - 1];
|
||||
head_window_acc -= distances_for_curvature[point_idx - 1];
|
||||
head_angle_acc -= angles_for_curvature[point_idx - 1];
|
||||
}
|
||||
while (tail_window_acc > window_size * 0.5 && int(tail_point) < point_idx) {
|
||||
tail_window_acc -= distances_for_curvature[tail_point];
|
||||
tail_angle_acc -= angles_for_curvature[tail_point];
|
||||
tail_point++;
|
||||
}
|
||||
for (size_t point_idx = 0; point_idx < points.size(); ++point_idx) {
|
||||
if (point_idx == 0) {
|
||||
while (tail_window_acc < window_size * 0.5) {
|
||||
tail_window_acc += distances_for_curvature[tail_point];
|
||||
tail_angle_acc += angles_for_curvature[tail_point];
|
||||
tail_point = prev_idx_modulo(tail_point, points.size());
|
||||
}
|
||||
}
|
||||
while (tail_window_acc - distances_for_curvature[next_idx_modulo(tail_point, points.size())] > window_size * 0.5) {
|
||||
tail_point = next_idx_modulo(tail_point, points.size());
|
||||
tail_window_acc -= distances_for_curvature[tail_point];
|
||||
tail_angle_acc -= angles_for_curvature[tail_point];
|
||||
}
|
||||
|
||||
while (head_window_acc < window_size * 0.5 && int(head_point) < int(points.size()) - 1) {
|
||||
head_window_acc += distances_for_curvature[head_point];
|
||||
head_angle_acc += angles_for_curvature[head_point];
|
||||
head_point++;
|
||||
}
|
||||
while (head_window_acc < window_size * 0.5) {
|
||||
head_point = next_idx_modulo(head_point, points.size());
|
||||
head_window_acc += distances_for_curvature[head_point];
|
||||
head_angle_acc += angles_for_curvature[head_point];
|
||||
}
|
||||
|
||||
float curvature = (tail_angle_acc + head_angle_acc) / (tail_window_acc + head_window_acc);
|
||||
if (std::abs(curvature) > std::abs(points[point_idx].curvature)) {
|
||||
points[point_idx].curvature = curvature;
|
||||
float curvature = (tail_angle_acc + head_angle_acc) / window_size;
|
||||
if (std::abs(curvature) > std::abs(points[point_idx].curvature)) {
|
||||
points[point_idx].curvature = curvature;
|
||||
}
|
||||
|
||||
tail_window_acc += distances_for_curvature[point_idx];
|
||||
tail_angle_acc += angles_for_curvature[point_idx];
|
||||
head_window_acc -= distances_for_curvature[point_idx];
|
||||
head_angle_acc -= angles_for_curvature[point_idx];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return points;
|
||||
}
|
||||
|
||||
@@ -3610,7 +3610,8 @@ void GCodeProcessor::post_process()
|
||||
while (rev_it != m_lines.rend() && rev_it->time > time_threshold_i && curr_cmd != cmd && curr_cmd != "G28" && curr_cmd != "G29") {
|
||||
rev_it->line = line_replacer(rev_it->line);
|
||||
++rev_it;
|
||||
curr_cmd = GCodeReader::GCodeLine::extract_cmd(rev_it->line);
|
||||
if (rev_it != m_lines.rend())
|
||||
curr_cmd = GCodeReader::GCodeLine::extract_cmd(rev_it->line);
|
||||
}
|
||||
|
||||
// we met the previous evenience of cmd, or a G28/G29 command. stop inserting lines
|
||||
|
||||
@@ -16,7 +16,9 @@
|
||||
|
||||
// The standard Windows includes.
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
#include <Windows.h>
|
||||
#include <shellapi.h>
|
||||
|
||||
|
||||
@@ -169,6 +169,11 @@ ToolOrdering::ToolOrdering(const Print &print, unsigned int first_extruder, bool
|
||||
this->fill_wipe_tower_partitions(print.config(), object_bottom_z, max_layer_height);
|
||||
|
||||
if (this->insert_wipe_tower_extruder()) {
|
||||
// Now convert the 0-based list to 1-based again, because that is what reorder_extruder expects.
|
||||
for (LayerTools& lt : m_layer_tools) {
|
||||
for (auto& extruder : lt.extruders)
|
||||
++extruder;
|
||||
}
|
||||
this->reorder_extruders(first_extruder);
|
||||
this->fill_wipe_tower_partitions(print.config(), object_bottom_z, max_layer_height);
|
||||
}
|
||||
@@ -478,12 +483,7 @@ bool ToolOrdering::insert_wipe_tower_extruder()
|
||||
sort_remove_duplicates(lt.extruders);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
// Now convert the 0-based list to 1-based again.
|
||||
for (LayerTools& lt : m_layer_tools) {
|
||||
for (auto& extruder : lt.extruders)
|
||||
++extruder;
|
||||
}
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
@@ -516,7 +516,7 @@ WipeTower::ToolChangeResult WipeTower::construct_tcr(WipeTowerWriter& writer,
|
||||
|
||||
|
||||
|
||||
WipeTower::WipeTower(const PrintConfig& config, const std::vector<std::vector<float>>& wiping_matrix, size_t initial_tool) :
|
||||
WipeTower::WipeTower(const PrintConfig& config, const PrintRegionConfig& default_region_config, const std::vector<std::vector<float>>& wiping_matrix, size_t initial_tool) :
|
||||
m_semm(config.single_extruder_multi_material.value),
|
||||
m_wipe_tower_pos(config.wipe_tower_x, config.wipe_tower_y),
|
||||
m_wipe_tower_width(float(config.wipe_tower_width)),
|
||||
@@ -530,6 +530,8 @@ WipeTower::WipeTower(const PrintConfig& config, const std::vector<std::vector<fl
|
||||
m_no_sparse_layers(config.wipe_tower_no_sparse_layers),
|
||||
m_gcode_flavor(config.gcode_flavor),
|
||||
m_travel_speed(config.travel_speed),
|
||||
m_infill_speed(default_region_config.infill_speed),
|
||||
m_perimeter_speed(default_region_config.perimeter_speed),
|
||||
m_current_tool(initial_tool),
|
||||
wipe_volumes(wiping_matrix)
|
||||
{
|
||||
@@ -541,6 +543,13 @@ WipeTower::WipeTower(const PrintConfig& config, const std::vector<std::vector<fl
|
||||
if (m_first_layer_speed == 0.f) // just to make sure autospeed doesn't break it.
|
||||
m_first_layer_speed = default_speed / 2.f;
|
||||
|
||||
// Autospeed may be used...
|
||||
if (m_infill_speed == 0.f)
|
||||
m_infill_speed = 80.f;
|
||||
if (m_perimeter_speed == 0.f)
|
||||
m_perimeter_speed = 80.f;
|
||||
|
||||
|
||||
// If this is a single extruder MM printer, we will use all the SE-specific config values.
|
||||
// Otherwise, the defaults will be used to turn off the SE stuff.
|
||||
if (m_semm) {
|
||||
@@ -550,6 +559,7 @@ WipeTower::WipeTower(const PrintConfig& config, const std::vector<std::vector<fl
|
||||
m_extra_loading_move = float(config.extra_loading_move);
|
||||
m_set_extruder_trimpot = config.high_current_on_filament_swap;
|
||||
}
|
||||
|
||||
// Calculate where the priming lines should be - very naive test not detecting parallelograms etc.
|
||||
const std::vector<Vec2d>& bed_points = config.bed_shape.values;
|
||||
BoundingBoxf bb(bed_points);
|
||||
@@ -616,6 +626,24 @@ void WipeTower::set_extruder(size_t idx, const PrintConfig& config)
|
||||
m_filpar[idx].ramming_step_multiplicator /= 100;
|
||||
while (stream >> speed)
|
||||
m_filpar[idx].ramming_speed.push_back(speed);
|
||||
// ramming_speed now contains speeds to be used for every 0.25s piece of the ramming line.
|
||||
// This allows to have the ramming flow variable. The 0.25s value is how it is saved in config
|
||||
// and the same time step has to be used when the ramming is performed.
|
||||
} else {
|
||||
// We will use the same variables internally, but the correspondence to the configuration options will be different.
|
||||
float vol = config.filament_multitool_ramming_volume.get_at(idx);
|
||||
float flow = config.filament_multitool_ramming_flow.get_at(idx);
|
||||
m_filpar[idx].multitool_ramming = config.filament_multitool_ramming.get_at(idx);
|
||||
m_filpar[idx].ramming_line_width_multiplicator = 2.;
|
||||
m_filpar[idx].ramming_step_multiplicator = 1.;
|
||||
|
||||
// Now the ramming speed vector. In this case it contains just one value (flow).
|
||||
// The time is calculated and saved separately. This is here so that the MM ramming
|
||||
// is not limited by the 0.25s granularity - it is not possible to create a SEMM-style
|
||||
// ramming_speed vector that would respect both the volume and flow (because of
|
||||
// rounding issues with small volumes and high flow).
|
||||
m_filpar[idx].ramming_speed.push_back(flow);
|
||||
m_filpar[idx].multitool_ramming_time = vol/flow;
|
||||
}
|
||||
|
||||
m_used_filament_length.resize(std::max(m_used_filament_length.size(), idx + 1)); // makes sure that the vector is big enough so we don't have to check later
|
||||
@@ -830,12 +858,17 @@ void WipeTower::toolchange_Unload(
|
||||
float remaining = xr - xl ; // keeps track of distance to the next turnaround
|
||||
float e_done = 0; // measures E move done from each segment
|
||||
|
||||
if (m_semm)
|
||||
const bool do_ramming = m_semm || m_filpar[m_current_tool].multitool_ramming;
|
||||
|
||||
if (do_ramming) {
|
||||
writer.travel(ramming_start_pos); // move to starting position
|
||||
writer.disable_linear_advance();
|
||||
}
|
||||
else
|
||||
writer.set_position(ramming_start_pos);
|
||||
|
||||
// if the ending point of the ram would end up in mid air, align it with the end of the wipe tower:
|
||||
if (m_semm && (m_layer_info > m_plan.begin() && m_layer_info < m_plan.end() && (m_layer_info-1!=m_plan.begin() || !m_adhesion ))) {
|
||||
if (do_ramming && (m_layer_info > m_plan.begin() && m_layer_info < m_plan.end() && (m_layer_info-1!=m_plan.begin() || !m_adhesion ))) {
|
||||
|
||||
// this is y of the center of previous sparse infill border
|
||||
float sparse_beginning_y = 0.f;
|
||||
@@ -863,16 +896,18 @@ void WipeTower::toolchange_Unload(
|
||||
sum_of_depths += tch.required_depth;
|
||||
}
|
||||
}
|
||||
|
||||
writer.disable_linear_advance();
|
||||
|
||||
|
||||
// now the ramming itself:
|
||||
while (m_semm && i < m_filpar[m_current_tool].ramming_speed.size())
|
||||
while (do_ramming && i < m_filpar[m_current_tool].ramming_speed.size())
|
||||
{
|
||||
const float x = volume_to_length(m_filpar[m_current_tool].ramming_speed[i] * 0.25f, line_width, m_layer_height);
|
||||
const float e = m_filpar[m_current_tool].ramming_speed[i] * 0.25f / filament_area(); // transform volume per sec to E move;
|
||||
const float dist = std::min(x - e_done, remaining); // distance to travel for either the next 0.25s, or to the next turnaround
|
||||
const float actual_time = dist/x * 0.25f;
|
||||
// The time step is different for SEMM ramming and the MM ramming. See comments in set_extruder() for details.
|
||||
const float time_step = m_semm ? 0.25f : m_filpar[m_current_tool].multitool_ramming_time;
|
||||
|
||||
const float x = volume_to_length(m_filpar[m_current_tool].ramming_speed[i] * time_step, line_width, m_layer_height);
|
||||
const float e = m_filpar[m_current_tool].ramming_speed[i] * time_step / filament_area(); // transform volume per sec to E move;
|
||||
const float dist = std::min(x - e_done, remaining); // distance to travel for either the next time_step, or to the next turnaround
|
||||
const float actual_time = dist/x * time_step;
|
||||
writer.ram(writer.x(), writer.x() + (m_left_to_right ? 1.f : -1.f) * dist, 0.f, 0.f, e * (dist / x), dist / (actual_time / 60.f));
|
||||
remaining -= dist;
|
||||
|
||||
@@ -944,7 +979,7 @@ void WipeTower::toolchange_Unload(
|
||||
// this is to align ramming and future wiping extrusions, so the future y-steps can be uniform from the start:
|
||||
// the perimeter_width will later be subtracted, it is there to not load while moving over just extruded material
|
||||
Vec2f pos = Vec2f(end_of_ramming.x(), end_of_ramming.y() + (y_step/m_extra_spacing-m_perimeter_width) / 2.f + m_perimeter_width);
|
||||
if (m_semm)
|
||||
if (do_ramming)
|
||||
writer.travel(pos, 2400.f);
|
||||
else
|
||||
writer.set_position(pos);
|
||||
@@ -1031,10 +1066,11 @@ void WipeTower::toolchange_Wipe(
|
||||
// the ordered volume, even if it means violating the box. This can later be removed and simply
|
||||
// wipe until the end of the assigned area.
|
||||
|
||||
float x_to_wipe = volume_to_length(wipe_volume, m_perimeter_width, m_layer_height);
|
||||
float dy = m_extra_spacing*m_perimeter_width;
|
||||
float x_to_wipe = volume_to_length(wipe_volume, m_perimeter_width, m_layer_height) * (is_first_layer() ? m_extra_spacing : 1.f);
|
||||
float dy = (is_first_layer() ? 1.f : m_extra_spacing) * m_perimeter_width; // Don't use the extra spacing for the first layer.
|
||||
// All the calculations in all other places take the spacing into account for all the layers.
|
||||
|
||||
const float target_speed = is_first_layer() ? m_first_layer_speed * 60.f : 4800.f;
|
||||
const float target_speed = is_first_layer() ? m_first_layer_speed * 60.f : m_infill_speed * 60.f;
|
||||
float wipe_speed = 0.33f * target_speed;
|
||||
|
||||
// if there is less than 2.5*m_perimeter_width to the edge, advance straightaway (there is likely a blob anyway)
|
||||
@@ -1103,7 +1139,7 @@ WipeTower::ToolChangeResult WipeTower::finish_layer()
|
||||
|
||||
// Slow down on the 1st layer.
|
||||
bool first_layer = is_first_layer();
|
||||
float feedrate = first_layer ? m_first_layer_speed * 60.f : 2900.f;
|
||||
float feedrate = first_layer ? m_first_layer_speed * 60.f : m_infill_speed * 60.f;
|
||||
float current_depth = m_layer_info->depth - m_layer_info->toolchanges_depth();
|
||||
box_coordinates fill_box(Vec2f(m_perimeter_width, m_layer_info->depth-(current_depth-m_perimeter_width)),
|
||||
m_wipe_tower_width - 2 * m_perimeter_width, current_depth-m_perimeter_width);
|
||||
@@ -1203,7 +1239,7 @@ WipeTower::ToolChangeResult WipeTower::finish_layer()
|
||||
// First generate vector of annotated point which form the boundary.
|
||||
std::vector<std::pair<Vec2f, Type>> pts = {{wt_box.ru, Corner}};
|
||||
if (double alpha_start = std::asin((0.5*w)/r); ! std::isnan(alpha_start) && r > 0.5*w+0.01) {
|
||||
for (double alpha = alpha_start; alpha < M_PI-alpha_start+0.001; alpha+=(M_PI-2*alpha_start) / 20.)
|
||||
for (double alpha = alpha_start; alpha < M_PI-alpha_start+0.001; alpha+=(M_PI-2*alpha_start) / 40.)
|
||||
pts.emplace_back(Vec2f(center.x() + r*std::cos(alpha)/support_scale, center.y() + r*std::sin(alpha)), alpha == alpha_start ? ArcStart : Arc);
|
||||
pts.back().second = ArcEnd;
|
||||
}
|
||||
@@ -1285,6 +1321,8 @@ WipeTower::ToolChangeResult WipeTower::finish_layer()
|
||||
return poly;
|
||||
};
|
||||
|
||||
feedrate = first_layer ? m_first_layer_speed * 60.f : m_perimeter_speed * 60.f;
|
||||
|
||||
// outer contour (always)
|
||||
bool infill_cone = first_layer && m_wipe_tower_width > 2*spacing && m_wipe_tower_depth > 2*spacing;
|
||||
Polygon poly = supported_rectangle(wt_box, feedrate, infill_cone);
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Slic3r
|
||||
|
||||
class WipeTowerWriter;
|
||||
class PrintConfig;
|
||||
class PrintRegionConfig;
|
||||
enum GCodeFlavor : unsigned char;
|
||||
|
||||
|
||||
@@ -129,7 +130,10 @@ public:
|
||||
// y -- y coordinates of wipe tower in mm ( left bottom corner )
|
||||
// width -- width of wipe tower in mm ( default 60 mm - leave as it is )
|
||||
// wipe_area -- space available for one toolchange in mm
|
||||
WipeTower(const PrintConfig& config, const std::vector<std::vector<float>>& wiping_matrix, size_t initial_tool);
|
||||
WipeTower(const PrintConfig& config,
|
||||
const PrintRegionConfig& default_region_config,
|
||||
const std::vector<std::vector<float>>& wiping_matrix,
|
||||
size_t initial_tool);
|
||||
|
||||
|
||||
// Set the extruder properties.
|
||||
@@ -237,6 +241,8 @@ public:
|
||||
std::vector<float> ramming_speed;
|
||||
float nozzle_diameter;
|
||||
float filament_area;
|
||||
bool multitool_ramming;
|
||||
float multitool_ramming_time = 0.f;
|
||||
};
|
||||
|
||||
private:
|
||||
@@ -269,6 +275,8 @@ private:
|
||||
size_t m_max_color_changes = 0; // Maximum number of color changes per layer.
|
||||
int m_old_temperature = -1; // To keep track of what was the last temp that we set (so we don't issue the command when not neccessary)
|
||||
float m_travel_speed = 0.f;
|
||||
float m_infill_speed = 0.f;
|
||||
float m_perimeter_speed = 0.f;
|
||||
float m_first_layer_speed = 0.f;
|
||||
size_t m_first_layer_idx = size_t(-1);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user