mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-10-22 16:21:24 -06:00
Merge remote-tracking branch 'remotes/origin/wipe_tower_improvements'
This commit is contained in:
commit
b79692c35e
32 changed files with 2288 additions and 775 deletions
|
@ -9,74 +9,115 @@
|
|||
|
||||
namespace Slic3r {
|
||||
|
||||
static inline Polyline make_wave_vertical(
|
||||
double width, double height, double x0,
|
||||
double segmentSize, double scaleFactor,
|
||||
double z_cos, double z_sin, bool flip)
|
||||
static inline double f(double x, double z_sin, double z_cos, bool vertical, bool flip)
|
||||
{
|
||||
Polyline polyline;
|
||||
polyline.points.emplace_back(Point(coord_t(clamp(0., width, x0) * scaleFactor), 0));
|
||||
double phase_offset_sin = (z_cos < 0 ? M_PI : 0) + M_PI;
|
||||
double phase_offset_cos = (z_cos < 0 ? M_PI : 0) + M_PI + (flip ? M_PI : 0.);
|
||||
for (double y = 0.; y < height + segmentSize; y += segmentSize) {
|
||||
y = std::min(y, height);
|
||||
double a = sin(y + phase_offset_sin);
|
||||
if (vertical) {
|
||||
double phase_offset = (z_cos < 0 ? M_PI : 0) + M_PI;
|
||||
double a = sin(x + phase_offset);
|
||||
double b = - z_cos;
|
||||
double res = z_sin * cos(y + phase_offset_cos);
|
||||
double res = z_sin * cos(x + phase_offset + (flip ? M_PI : 0.));
|
||||
double r = sqrt(sqr(a) + sqr(b));
|
||||
double x = clamp(0., width, asin(a/r) + asin(res/r) + M_PI + x0);
|
||||
polyline.points.emplace_back(convert_to<Point>(Pointf(x, y) * scaleFactor));
|
||||
return asin(a/r) + asin(res/r) + M_PI;
|
||||
}
|
||||
if (flip)
|
||||
std::reverse(polyline.points.begin(), polyline.points.end());
|
||||
else {
|
||||
double phase_offset = z_sin < 0 ? M_PI : 0.;
|
||||
double a = cos(x + phase_offset);
|
||||
double b = - z_sin;
|
||||
double res = z_cos * sin(x + phase_offset + (flip ? 0 : M_PI));
|
||||
double r = sqrt(sqr(a) + sqr(b));
|
||||
return (asin(a/r) + asin(res/r) + 0.5 * M_PI);
|
||||
}
|
||||
}
|
||||
|
||||
static inline Polyline make_wave(
|
||||
const std::vector<Pointf>& one_period, double width, double height, double offset, double scaleFactor,
|
||||
double z_cos, double z_sin, bool vertical)
|
||||
{
|
||||
std::vector<Pointf> points = one_period;
|
||||
double period = points.back().x;
|
||||
points.pop_back();
|
||||
int n = points.size();
|
||||
do {
|
||||
points.emplace_back(Pointf(points[points.size()-n].x + period, points[points.size()-n].y));
|
||||
} while (points.back().x < width);
|
||||
points.back().x = width;
|
||||
|
||||
// and construct the final polyline to return:
|
||||
Polyline polyline;
|
||||
for (auto& point : points) {
|
||||
point.y += offset;
|
||||
point.y = clamp(0., height, double(point.y));
|
||||
if (vertical)
|
||||
std::swap(point.x, point.y);
|
||||
polyline.points.emplace_back(convert_to<Point>(point * scaleFactor));
|
||||
}
|
||||
|
||||
return polyline;
|
||||
}
|
||||
|
||||
static inline Polyline make_wave_horizontal(
|
||||
double width, double height, double y0,
|
||||
double segmentSize, double scaleFactor,
|
||||
double z_cos, double z_sin, bool flip)
|
||||
static std::vector<Pointf> make_one_period(double width, double scaleFactor, double z_cos, double z_sin, bool vertical, bool flip)
|
||||
{
|
||||
Polyline polyline;
|
||||
polyline.points.emplace_back(Point(0, coord_t(clamp(0., height, y0) * scaleFactor)));
|
||||
double phase_offset_sin = (z_sin < 0 ? M_PI : 0) + (flip ? 0 : M_PI);
|
||||
double phase_offset_cos = z_sin < 0 ? M_PI : 0.;
|
||||
for (double x = 0.; x < width + segmentSize; x += segmentSize) {
|
||||
x = std::min(x, width);
|
||||
double a = cos(x + phase_offset_cos);
|
||||
double b = - z_sin;
|
||||
double res = z_cos * sin(x + phase_offset_sin);
|
||||
double r = sqrt(sqr(a) + sqr(b));
|
||||
double y = clamp(0., height, asin(a/r) + asin(res/r) + 0.5 * M_PI + y0);
|
||||
polyline.points.emplace_back(convert_to<Point>(Pointf(x, y) * scaleFactor));
|
||||
std::vector<Pointf> points;
|
||||
double dx = M_PI_4; // very coarse spacing to begin with
|
||||
double limit = std::min(2*M_PI, width);
|
||||
for (double x = 0.; x < limit + EPSILON; x += dx) { // so the last point is there too
|
||||
x = std::min(x, limit);
|
||||
points.emplace_back(Pointf(x,f(x, z_sin,z_cos, vertical, flip)));
|
||||
}
|
||||
if (flip)
|
||||
std::reverse(polyline.points.begin(), polyline.points.end());
|
||||
return polyline;
|
||||
|
||||
// now we will check all internal points and in case some are too far from the line connecting its neighbours,
|
||||
// we will add one more point on each side:
|
||||
const double tolerance = .1;
|
||||
for (unsigned int i=1;i<points.size()-1;++i) {
|
||||
auto& lp = points[i-1]; // left point
|
||||
auto& tp = points[i]; // this point
|
||||
auto& rp = points[i+1]; // right point
|
||||
// calculate distance of the point to the line:
|
||||
double dist_mm = unscale(scaleFactor * std::abs( (rp.y - lp.y)*tp.x + (lp.x - rp.x)*tp.y + (rp.x*lp.y - rp.y*lp.x) ) / std::hypot((rp.y - lp.y),(lp.x - rp.x)));
|
||||
|
||||
if (dist_mm > tolerance) { // if the difference from straight line is more than this
|
||||
double x = 0.5f * (points[i-1].x + points[i].x);
|
||||
points.emplace_back(Pointf(x, f(x, z_sin, z_cos, vertical, flip)));
|
||||
x = 0.5f * (points[i+1].x + points[i].x);
|
||||
points.emplace_back(Pointf(x, f(x, z_sin, z_cos, vertical, flip)));
|
||||
std::sort(points.begin(), points.end()); // we added the points to the end, but need them all in order
|
||||
--i; // decrement i so we also check the first newly added point
|
||||
}
|
||||
}
|
||||
return points;
|
||||
}
|
||||
|
||||
static Polylines make_gyroid_waves(double gridZ, double density_adjusted, double line_spacing, double width, double height)
|
||||
{
|
||||
double scaleFactor = scale_(line_spacing) / density_adjusted;
|
||||
double segmentSize = 0.5 * density_adjusted;
|
||||
const double scaleFactor = scale_(line_spacing) / density_adjusted;
|
||||
//scale factor for 5% : 8 712 388
|
||||
// 1z = 10^-6 mm ?
|
||||
double z = gridZ / scaleFactor;
|
||||
double z_sin = sin(z);
|
||||
double z_cos = cos(z);
|
||||
Polylines result;
|
||||
if (std::abs(z_sin) <= std::abs(z_cos)) {
|
||||
// Vertical wave
|
||||
double x0 = M_PI * (int)((- 0.5 * M_PI) / M_PI - 1.);
|
||||
bool flip = ((int)(x0 / M_PI + 1.) & 1) != 0;
|
||||
for (; x0 < width - 0.5 * M_PI; x0 += M_PI, flip = ! flip)
|
||||
result.emplace_back(make_wave_vertical(width, height, x0, segmentSize, scaleFactor, z_cos, z_sin, flip));
|
||||
} else {
|
||||
// Horizontal wave
|
||||
bool flip = true;
|
||||
for (double y0 = 0.; y0 < height; y0 += M_PI, flip = !flip)
|
||||
result.emplace_back(make_wave_horizontal(width, height, y0, segmentSize, scaleFactor, z_cos, z_sin, flip));
|
||||
const double z = gridZ / scaleFactor;
|
||||
const double z_sin = sin(z);
|
||||
const double z_cos = cos(z);
|
||||
|
||||
bool vertical = (std::abs(z_sin) <= std::abs(z_cos));
|
||||
double lower_bound = 0.;
|
||||
double upper_bound = height;
|
||||
bool flip = true;
|
||||
if (vertical) {
|
||||
flip = false;
|
||||
lower_bound = -M_PI;
|
||||
upper_bound = width - M_PI_2;
|
||||
std::swap(width,height);
|
||||
}
|
||||
|
||||
std::vector<Pointf> one_period = make_one_period(width, scaleFactor, z_cos, z_sin, vertical, flip); // creates one period of the waves, so it doesn't have to be recalculated all the time
|
||||
Polylines result;
|
||||
|
||||
for (double y0 = lower_bound; y0 < upper_bound+EPSILON; y0 += 2*M_PI) // creates odd polylines
|
||||
result.emplace_back(make_wave(one_period, width, height, y0, scaleFactor, z_cos, z_sin, vertical));
|
||||
|
||||
flip = !flip; // even polylines are a bit shifted
|
||||
one_period = make_one_period(width, scaleFactor, z_cos, z_sin, vertical, flip); // updates the one period sample
|
||||
for (double y0 = lower_bound + M_PI; y0 < upper_bound+EPSILON; y0 += 2*M_PI) // creates even polylines
|
||||
result.emplace_back(make_wave(one_period, width, height, y0, scaleFactor, z_cos, z_sin, vertical));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -90,13 +131,13 @@ void FillGyroid::_fill_surface_single(
|
|||
// no rotation is supported for this infill pattern (yet)
|
||||
BoundingBox bb = expolygon.contour.bounding_box();
|
||||
// Density adjusted to have a good %of weight.
|
||||
double density_adjusted = params.density * 1.75;
|
||||
double density_adjusted = std::max(0., params.density * 2.);
|
||||
// Distance between the gyroid waves in scaled coordinates.
|
||||
coord_t distance = coord_t(scale_(this->spacing) / density_adjusted);
|
||||
|
||||
// align bounding box to a multiple of our grid module
|
||||
bb.merge(_align_to_grid(bb.min, Point(2.*M_PI*distance, 2.*M_PI*distance)));
|
||||
|
||||
|
||||
// generate pattern
|
||||
Polylines polylines = make_gyroid_waves(
|
||||
scale_(this->z),
|
||||
|
|
|
@ -17,12 +17,26 @@ public:
|
|||
struct xy
|
||||
{
|
||||
xy(float x = 0.f, float y = 0.f) : x(x), y(y) {}
|
||||
xy(const xy& pos,float xp,float yp) : x(pos.x+xp), y(pos.y+yp) {}
|
||||
xy operator+(const xy &rhs) const { xy out(*this); out.x += rhs.x; out.y += rhs.y; return out; }
|
||||
xy operator-(const xy &rhs) const { xy out(*this); out.x -= rhs.x; out.y -= rhs.y; return out; }
|
||||
xy& operator+=(const xy &rhs) { x += rhs.x; y += rhs.y; return *this; }
|
||||
xy& operator-=(const xy &rhs) { x -= rhs.x; y -= rhs.y; return *this; }
|
||||
bool operator==(const xy &rhs) const { return x == rhs.x && y == rhs.y; }
|
||||
bool operator!=(const xy &rhs) const { return x != rhs.x || y != rhs.y; }
|
||||
|
||||
// Rotate the point around given point about given angle (in degrees)
|
||||
// shifts the result so that point of rotation is in the middle of the tower
|
||||
xy rotate(const xy& origin, float width, float depth, float angle) const {
|
||||
xy out(0,0);
|
||||
float temp_x = x - width / 2.f;
|
||||
float temp_y = y - depth / 2.f;
|
||||
angle *= M_PI/180.;
|
||||
out.x += (temp_x - origin.x) * cos(angle) - (temp_y - origin.y) * sin(angle);
|
||||
out.y += (temp_x - origin.x) * sin(angle) + (temp_y - origin.y) * cos(angle);
|
||||
return out + origin;
|
||||
}
|
||||
|
||||
float x;
|
||||
float y;
|
||||
};
|
||||
|
@ -112,17 +126,15 @@ public:
|
|||
const std::vector<unsigned int> &tools,
|
||||
// If true, the last priming are will be the same as the other priming areas, and the rest of the wipe will be performed inside the wipe tower.
|
||||
// If false, the last priming are will be large enough to wipe the last extruder sufficiently.
|
||||
bool last_wipe_inside_wipe_tower,
|
||||
// May be used by a stand alone post processor.
|
||||
Purpose purpose = PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) = 0;
|
||||
bool last_wipe_inside_wipe_tower) = 0;
|
||||
|
||||
// Returns gcode for toolchange and the end position.
|
||||
// if new_tool == -1, just unload the current filament over the wipe tower.
|
||||
virtual ToolChangeResult tool_change(unsigned int new_tool, bool last_in_layer, Purpose purpose = PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) = 0;
|
||||
virtual ToolChangeResult tool_change(unsigned int new_tool, bool last_in_layer) = 0;
|
||||
|
||||
// Close the current wipe tower layer with a perimeter and possibly fill the unfilled space with a zig-zag.
|
||||
// Call this method only if layer_finished() is false.
|
||||
virtual ToolChangeResult finish_layer(Purpose purpose = PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) = 0;
|
||||
virtual ToolChangeResult finish_layer() = 0;
|
||||
|
||||
// Is the current layer finished? A layer is finished if either the wipe tower is finished, or
|
||||
// the wipe tower has been completely covered by the tool change extrusions,
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,13 +1,14 @@
|
|||
#ifndef WipeTowerPrusaMM_hpp_
|
||||
#define WipeTowerPrusaMM_hpp_
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
|
||||
#include "WipeTower.hpp"
|
||||
|
||||
|
||||
namespace Slic3r
|
||||
{
|
||||
|
||||
|
@ -15,6 +16,8 @@ namespace PrusaMultiMaterial {
|
|||
class Writer;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class WipeTowerPrusaMM : public WipeTower
|
||||
{
|
||||
public:
|
||||
|
@ -39,65 +42,98 @@ 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
|
||||
WipeTowerPrusaMM(float x, float y, float width, float wipe_area, unsigned int initial_tool) :
|
||||
WipeTowerPrusaMM(float x, float y, float width, float rotation_angle, float cooling_tube_retraction,
|
||||
float cooling_tube_length, float parking_pos_retraction, float bridging, const std::vector<float>& wiping_matrix,
|
||||
unsigned int initial_tool) :
|
||||
m_wipe_tower_pos(x, y),
|
||||
m_wipe_tower_width(width),
|
||||
m_wipe_area(wipe_area),
|
||||
m_wipe_tower_rotation_angle(rotation_angle),
|
||||
m_y_shift(0.f),
|
||||
m_z_pos(0.f),
|
||||
m_current_tool(initial_tool)
|
||||
m_is_first_layer(false),
|
||||
m_cooling_tube_retraction(cooling_tube_retraction),
|
||||
m_cooling_tube_length(cooling_tube_length),
|
||||
m_parking_pos_retraction(parking_pos_retraction),
|
||||
m_bridging(bridging),
|
||||
m_current_tool(initial_tool)
|
||||
{
|
||||
for (size_t i = 0; i < 4; ++ i) {
|
||||
// Extruder specific parameters.
|
||||
m_material[i] = PLA;
|
||||
m_temperature[i] = 0;
|
||||
m_first_layer_temperature[i] = 0;
|
||||
}
|
||||
unsigned int number_of_extruders = (unsigned int)(sqrt(wiping_matrix.size())+WT_EPSILON);
|
||||
for (unsigned int i = 0; i<number_of_extruders; ++i)
|
||||
wipe_volumes.push_back(std::vector<float>(wiping_matrix.begin()+i*number_of_extruders,wiping_matrix.begin()+(i+1)*number_of_extruders));
|
||||
}
|
||||
|
||||
virtual ~WipeTowerPrusaMM() {}
|
||||
|
||||
// _retract - retract value in mm
|
||||
void set_retract(float retract) { m_retract = retract; }
|
||||
|
||||
// _zHop - z hop value in mm
|
||||
void set_zhop(float zhop) { m_zhop = zhop; }
|
||||
|
||||
// Set the extruder properties.
|
||||
void set_extruder(size_t idx, material_type material, int temp, int first_layer_temp)
|
||||
void set_extruder(size_t idx, material_type material, int temp, int first_layer_temp, float loading_speed,
|
||||
float unloading_speed, float delay, float cooling_time, std::string ramming_parameters, float nozzle_diameter)
|
||||
{
|
||||
m_material[idx] = material;
|
||||
m_temperature[idx] = temp;
|
||||
m_first_layer_temperature[idx] = first_layer_temp;
|
||||
//while (m_filpar.size() < idx+1) // makes sure the required element is in the vector
|
||||
m_filpar.push_back(FilamentParameters());
|
||||
|
||||
m_filpar[idx].material = material;
|
||||
m_filpar[idx].temperature = temp;
|
||||
m_filpar[idx].first_layer_temperature = first_layer_temp;
|
||||
m_filpar[idx].loading_speed = loading_speed;
|
||||
m_filpar[idx].unloading_speed = unloading_speed;
|
||||
m_filpar[idx].delay = delay;
|
||||
m_filpar[idx].cooling_time = cooling_time;
|
||||
m_filpar[idx].nozzle_diameter = nozzle_diameter; // to be used in future with (non-single) multiextruder MM
|
||||
|
||||
m_perimeter_width = nozzle_diameter * Width_To_Nozzle_Ratio; // all extruders are now assumed to have the same diameter
|
||||
|
||||
std::stringstream stream{ramming_parameters};
|
||||
float speed = 0.f;
|
||||
stream >> m_filpar[idx].ramming_line_width_multiplicator >> m_filpar[idx].ramming_step_multiplicator;
|
||||
m_filpar[idx].ramming_line_width_multiplicator /= 100;
|
||||
m_filpar[idx].ramming_step_multiplicator /= 100;
|
||||
while (stream >> speed)
|
||||
m_filpar[idx].ramming_speed.push_back(speed);
|
||||
}
|
||||
|
||||
|
||||
// Appends into internal structure m_plan containing info about the future wipe tower
|
||||
// to be used before building begins. The entries must be added ordered in z.
|
||||
void plan_toolchange(float z_par, float layer_height_par, unsigned int old_tool, unsigned int new_tool, bool brim);
|
||||
|
||||
// Iterates through prepared m_plan, generates ToolChangeResults and appends them to "result"
|
||||
void generate(std::vector<std::vector<WipeTower::ToolChangeResult>> &result);
|
||||
|
||||
|
||||
|
||||
// Switch to a next layer.
|
||||
virtual void set_layer(
|
||||
// Print height of this layer.
|
||||
float print_z,
|
||||
// Layer height, used to calculate extrusion the rate.
|
||||
float layer_height,
|
||||
float print_z,
|
||||
// Layer height, used to calculate extrusion the rate.
|
||||
float layer_height,
|
||||
// Maximum number of tool changes on this layer or the layers below.
|
||||
size_t max_tool_changes,
|
||||
size_t max_tool_changes,
|
||||
// Is this the first layer of the print? In that case print the brim first.
|
||||
bool is_first_layer,
|
||||
bool is_first_layer,
|
||||
// Is this the last layer of the waste tower?
|
||||
bool is_last_layer)
|
||||
bool is_last_layer)
|
||||
{
|
||||
m_z_pos = print_z;
|
||||
m_layer_height = layer_height;
|
||||
m_max_color_changes = max_tool_changes;
|
||||
m_is_first_layer = is_first_layer;
|
||||
m_is_last_layer = is_last_layer;
|
||||
// Start counting the color changes from zero. Special case: -1 - extrude a brim first.
|
||||
m_idx_tool_change_in_layer = is_first_layer ? (unsigned int)(-1) : 0;
|
||||
m_current_wipe_start_y = 0.f;
|
||||
m_print_brim = is_first_layer;
|
||||
m_depth_traversed = 0.f;
|
||||
m_current_shape = (! is_first_layer && m_current_shape == SHAPE_NORMAL) ? SHAPE_REVERSED : SHAPE_NORMAL;
|
||||
++ m_num_layer_changes;
|
||||
// Extrusion rate for an extrusion aka perimeter width 0.35mm.
|
||||
// Clamp the extrusion height to a 0.2mm layer height, independent of the nozzle diameter.
|
||||
// m_extrusion_flow = std::min(0.2f, layer_height) * 0.145f;
|
||||
// Use a strictly
|
||||
m_extrusion_flow = layer_height * 0.145f;
|
||||
if (is_first_layer) {
|
||||
this->m_num_layer_changes = 0;
|
||||
this->m_num_tool_changes = 0;
|
||||
}
|
||||
else
|
||||
++ m_num_layer_changes;
|
||||
|
||||
// Calculate extrusion flow from desired line width, nozzle diameter, filament diameter and layer_height:
|
||||
m_extrusion_flow = extrusion_flow(layer_height);
|
||||
|
||||
// Advance m_layer_info iterator, making sure we got it right
|
||||
while (!m_plan.empty() && m_layer_info->z < print_z - WT_EPSILON && m_layer_info+1 != m_plan.end())
|
||||
++m_layer_info;
|
||||
}
|
||||
|
||||
// Return the wipe tower position.
|
||||
|
@ -115,79 +151,114 @@ public:
|
|||
const std::vector<unsigned int> &tools,
|
||||
// If true, the last priming are will be the same as the other priming areas, and the rest of the wipe will be performed inside the wipe tower.
|
||||
// If false, the last priming are will be large enough to wipe the last extruder sufficiently.
|
||||
bool last_wipe_inside_wipe_tower,
|
||||
// May be used by a stand alone post processor.
|
||||
Purpose purpose = PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE);
|
||||
bool last_wipe_inside_wipe_tower);
|
||||
|
||||
// Returns gcode for a toolchange and a final print head position.
|
||||
// On the first layer, extrude a brim around the future wipe tower first.
|
||||
virtual ToolChangeResult tool_change(unsigned int new_tool, bool last_in_layer, Purpose purpose);
|
||||
virtual ToolChangeResult tool_change(unsigned int new_tool, bool last_in_layer);
|
||||
|
||||
// Close the current wipe tower layer with a perimeter and possibly fill the unfilled space with a zig-zag.
|
||||
// Fill the unfilled space with a sparse infill.
|
||||
// Call this method only if layer_finished() is false.
|
||||
virtual ToolChangeResult finish_layer(Purpose purpose);
|
||||
virtual ToolChangeResult finish_layer();
|
||||
|
||||
// Is the current layer finished?
|
||||
virtual bool layer_finished() const {
|
||||
return ( (m_is_first_layer ? m_wipe_tower_depth - m_perimeter_width : m_layer_info->depth) - WT_EPSILON < m_depth_traversed);
|
||||
}
|
||||
|
||||
// Is the current layer finished? A layer is finished if either the wipe tower is finished, or
|
||||
// the wipe tower has been completely covered by the tool change extrusions,
|
||||
// or the rest of the tower has been filled by a sparse infill with the finish_layer() method.
|
||||
virtual bool layer_finished() const
|
||||
{ return m_idx_tool_change_in_layer == m_max_color_changes; }
|
||||
|
||||
private:
|
||||
WipeTowerPrusaMM();
|
||||
|
||||
// A fill-in direction (positive Y, negative Y) alternates with each layer.
|
||||
enum wipe_shape
|
||||
enum wipe_shape // A fill-in direction
|
||||
{
|
||||
SHAPE_NORMAL = 1,
|
||||
SHAPE_NORMAL = 1,
|
||||
SHAPE_REVERSED = -1
|
||||
};
|
||||
|
||||
// Left front corner of the wipe tower in mm.
|
||||
xy m_wipe_tower_pos;
|
||||
// Width of the wipe tower.
|
||||
float m_wipe_tower_width;
|
||||
// Per color Y span.
|
||||
float m_wipe_area;
|
||||
// Current Z position.
|
||||
float m_z_pos = 0.f;
|
||||
// Current layer height.
|
||||
float m_layer_height = 0.f;
|
||||
// Maximum number of color changes per layer.
|
||||
size_t m_max_color_changes = 0;
|
||||
// Is this the 1st layer of the print? If so, print the brim around the waste tower.
|
||||
bool m_is_first_layer = false;
|
||||
// Is this the last layer of this waste tower?
|
||||
bool m_is_last_layer = false;
|
||||
|
||||
const bool m_peters_wipe_tower = false; // sparse wipe tower inspired by Peter's post processor - not finished yet
|
||||
const float Filament_Area = M_PI * 1.75f * 1.75f / 4.f; // filament area in mm^2
|
||||
const float Width_To_Nozzle_Ratio = 1.25f; // desired line width (oval) in multiples of nozzle diameter - may not be actually neccessary to adjust
|
||||
const float WT_EPSILON = 1e-3f;
|
||||
|
||||
|
||||
xy m_wipe_tower_pos; // Left front corner of the wipe tower in mm.
|
||||
float m_wipe_tower_width; // Width of the wipe tower.
|
||||
float m_wipe_tower_depth = 0.f; // Depth of the wipe tower
|
||||
float m_wipe_tower_rotation_angle = 0.f; // Wipe tower rotation angle in degrees (with respect to x axis)
|
||||
float m_y_shift = 0.f; // y shift passed to writer
|
||||
float m_z_pos = 0.f; // Current Z position.
|
||||
float m_layer_height = 0.f; // Current layer height.
|
||||
size_t m_max_color_changes = 0; // Maximum number of color changes per layer.
|
||||
bool m_is_first_layer = false;// Is this the 1st layer of the print? If so, print the brim around the waste tower.
|
||||
|
||||
// G-code generator parameters.
|
||||
float m_zhop = 0.5f;
|
||||
float m_retract = 4.f;
|
||||
// Width of an extrusion line, also a perimeter spacing for 100% infill.
|
||||
float m_perimeter_width = 0.5f;
|
||||
// Extrusion flow is derived from m_perimeter_width, layer height and filament diameter.
|
||||
float m_extrusion_flow = 0.029f;
|
||||
float m_cooling_tube_retraction = 0.f;
|
||||
float m_cooling_tube_length = 0.f;
|
||||
float m_parking_pos_retraction = 0.f;
|
||||
float m_bridging = 0.f;
|
||||
bool m_adhesion = true;
|
||||
|
||||
float m_perimeter_width = 0.4 * Width_To_Nozzle_Ratio; // Width of an extrusion line, also a perimeter spacing for 100% infill.
|
||||
float m_extrusion_flow = 0.038; //0.029f;// Extrusion flow is derived from m_perimeter_width, layer height and filament diameter.
|
||||
|
||||
|
||||
struct FilamentParameters {
|
||||
material_type material = PLA;
|
||||
int temperature = 0;
|
||||
int first_layer_temperature = 0;
|
||||
float loading_speed = 0.f;
|
||||
float unloading_speed = 0.f;
|
||||
float delay = 0.f ;
|
||||
float cooling_time = 0.f;
|
||||
float ramming_line_width_multiplicator = 0.f;
|
||||
float ramming_step_multiplicator = 0.f;
|
||||
std::vector<float> ramming_speed;
|
||||
float nozzle_diameter;
|
||||
};
|
||||
|
||||
// Extruder specific parameters.
|
||||
material_type m_material[4];
|
||||
int m_temperature[4];
|
||||
int m_first_layer_temperature[4];
|
||||
std::vector<FilamentParameters> m_filpar;
|
||||
|
||||
// State of the wiper tower generator.
|
||||
// Layer change counter for the output statistics.
|
||||
unsigned int m_num_layer_changes = 0;
|
||||
// Tool change change counter for the output statistics.
|
||||
unsigned int m_num_tool_changes = 0;
|
||||
// Layer change counter in this layer. Counting up to m_max_color_changes.
|
||||
unsigned int m_idx_tool_change_in_layer = 0;
|
||||
|
||||
// State of the wipe tower generator.
|
||||
unsigned int m_num_layer_changes = 0; // Layer change counter for the output statistics.
|
||||
unsigned int m_num_tool_changes = 0; // Tool change change counter for the output statistics.
|
||||
///unsigned int m_idx_tool_change_in_layer = 0; // Layer change counter in this layer. Counting up to m_max_color_changes.
|
||||
bool m_print_brim = true;
|
||||
// A fill-in direction (positive Y, negative Y) alternates with each layer.
|
||||
wipe_shape m_current_shape = SHAPE_NORMAL;
|
||||
unsigned int m_current_tool = 0;
|
||||
// Current y position at the wipe tower.
|
||||
float m_current_wipe_start_y = 0.f;
|
||||
// How much to wipe the 1st extruder over the wipe tower at the 1st layer
|
||||
// after the wipe tower brim has been extruded?
|
||||
float m_initial_extra_wipe = 0.f;
|
||||
std::vector<std::vector<float>> wipe_volumes;
|
||||
|
||||
float m_depth_traversed = 0.f; // Current y position at the wipe tower.
|
||||
bool m_left_to_right = true;
|
||||
float m_extra_spacing = 1.f;
|
||||
|
||||
|
||||
// Calculates extrusion flow needed to produce required line width for given layer height
|
||||
float extrusion_flow(float layer_height = -1.f) const // negative layer_height - return current m_extrusion_flow
|
||||
{
|
||||
if ( layer_height < 0 )
|
||||
return m_extrusion_flow;
|
||||
return layer_height * ( m_perimeter_width - layer_height * (1-M_PI/4.f)) / Filament_Area;
|
||||
}
|
||||
|
||||
// Calculates length of extrusion line to extrude given volume
|
||||
float volume_to_length(float volume, float line_width, float layer_height) const {
|
||||
return volume / (layer_height * (line_width - layer_height * (1. - M_PI / 4.)));
|
||||
}
|
||||
|
||||
// Calculates depth for all layers and propagates them downwards
|
||||
void plan_tower();
|
||||
|
||||
// Goes through m_plan and recalculates depths and width of the WT to make it exactly square - experimental
|
||||
void make_wipe_tower_square();
|
||||
|
||||
// Goes through m_plan, calculates border and finish_layer extrusions and subtracts them from last wipe
|
||||
void save_on_last_wipe();
|
||||
|
||||
|
||||
struct box_coordinates
|
||||
{
|
||||
|
@ -216,14 +287,42 @@ private:
|
|||
}
|
||||
xy ld; // left down
|
||||
xy lu; // left upper
|
||||
xy ru; // right upper
|
||||
xy rd; // right lower
|
||||
xy ru; // right upper
|
||||
};
|
||||
|
||||
|
||||
// to store information about tool changes for a given layer
|
||||
struct WipeTowerInfo{
|
||||
struct ToolChange {
|
||||
unsigned int old_tool;
|
||||
unsigned int new_tool;
|
||||
float required_depth;
|
||||
float ramming_depth;
|
||||
float first_wipe_line;
|
||||
ToolChange(unsigned int old,unsigned int newtool,float depth=0.f,float ramming_depth=0.f,float fwl=0.f)
|
||||
: old_tool{old}, new_tool{newtool}, required_depth{depth}, ramming_depth{ramming_depth},first_wipe_line{fwl} {}
|
||||
};
|
||||
float z; // z position of the layer
|
||||
float height; // layer height
|
||||
float depth; // depth of the layer based on all layers above
|
||||
float extra_spacing;
|
||||
float toolchanges_depth() const { float sum = 0.f; for (const auto &a : tool_changes) sum += a.required_depth; return sum; }
|
||||
|
||||
std::vector<ToolChange> tool_changes;
|
||||
|
||||
WipeTowerInfo(float z_par, float layer_height_par)
|
||||
: z{z_par}, height{layer_height_par}, depth{0}, extra_spacing{1.f} {}
|
||||
};
|
||||
|
||||
std::vector<WipeTowerInfo> m_plan; // Stores information about all layers and toolchanges for the future wipe tower (filled by plan_toolchange(...))
|
||||
std::vector<WipeTowerInfo>::iterator m_layer_info = m_plan.end();
|
||||
|
||||
|
||||
// Returns gcode for wipe tower brim
|
||||
// sideOnly -- set to false -- experimental, draw brim on sides of wipe tower
|
||||
// sideOnly -- set to false -- experimental, draw brim on sides of wipe tower
|
||||
// offset -- set to 0 -- experimental, offset to replace brim in front / rear of wipe tower
|
||||
ToolChangeResult toolchange_Brim(Purpose purpose, bool sideOnly = false, float y_offset = 0.f);
|
||||
ToolChangeResult toolchange_Brim(bool sideOnly = false, float y_offset = 0.f);
|
||||
|
||||
void toolchange_Unload(
|
||||
PrusaMultiMaterial::Writer &writer,
|
||||
|
@ -243,11 +342,12 @@ private:
|
|||
void toolchange_Wipe(
|
||||
PrusaMultiMaterial::Writer &writer,
|
||||
const box_coordinates &cleaning_box,
|
||||
bool skip_initial_y_move);
|
||||
|
||||
void toolchange_Perimeter();
|
||||
float wipe_volume);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
}; // namespace Slic3r
|
||||
|
||||
#endif /* WipeTowerPrusaMM_hpp_ */
|
||||
|
|
|
@ -183,6 +183,11 @@ bool Print::invalidate_state_by_config_options(const std::vector<t_config_option
|
|||
|| opt_key == "filament_type"
|
||||
|| opt_key == "filament_soluble"
|
||||
|| opt_key == "first_layer_temperature"
|
||||
|| opt_key == "filament_loading_speed"
|
||||
|| opt_key == "filament_unloading_speed"
|
||||
|| opt_key == "filament_toolchange_delay"
|
||||
|| opt_key == "filament_cooling_time"
|
||||
|| opt_key == "filament_ramming_parameters"
|
||||
|| opt_key == "gcode_flavor"
|
||||
|| opt_key == "single_extruder_multi_material"
|
||||
|| opt_key == "spiral_vase"
|
||||
|
@ -191,7 +196,12 @@ bool Print::invalidate_state_by_config_options(const std::vector<t_config_option
|
|||
|| opt_key == "wipe_tower_x"
|
||||
|| opt_key == "wipe_tower_y"
|
||||
|| opt_key == "wipe_tower_width"
|
||||
|| opt_key == "wipe_tower_per_color_wipe"
|
||||
|| opt_key == "wipe_tower_rotation_angle"
|
||||
|| opt_key == "wipe_tower_bridging"
|
||||
|| opt_key == "wiping_volumes_matrix"
|
||||
|| opt_key == "parking_pos_retraction"
|
||||
|| opt_key == "cooling_tube_retraction"
|
||||
|| opt_key == "cooling_tube_length"
|
||||
|| opt_key == "z_offset") {
|
||||
steps.emplace_back(psWipeTower);
|
||||
} else if (
|
||||
|
@ -571,6 +581,12 @@ std::string Print::validate() const
|
|||
return "The Spiral Vase option can only be used when printing single material objects.";
|
||||
}
|
||||
|
||||
if (this->config.single_extruder_multi_material) {
|
||||
for (size_t i=1; i<this->config.nozzle_diameter.values.size(); ++i)
|
||||
if (this->config.nozzle_diameter.values[i] != this->config.nozzle_diameter.values[i-1])
|
||||
return "All extruders must have the same diameter for single extruder multimaterial printer.";
|
||||
}
|
||||
|
||||
if (this->has_wipe_tower() && ! this->objects.empty()) {
|
||||
#if 0
|
||||
for (auto dmr : this->config.nozzle_diameter.values)
|
||||
|
@ -596,10 +612,21 @@ std::string Print::validate() const
|
|||
bool was_layer_height_profile_valid = object->layer_height_profile_valid;
|
||||
object->update_layer_height_profile();
|
||||
object->layer_height_profile_valid = was_layer_height_profile_valid;
|
||||
for (size_t i = 5; i < object->layer_height_profile.size(); i += 2)
|
||||
|
||||
if ( this->config.variable_layer_height ) {
|
||||
PrintObject* first_object = this->objects.front();
|
||||
int i = 0;
|
||||
while ( i < first_object->layer_height_profile.size() && i < object->layer_height_profile.size() ) {
|
||||
if (std::abs(first_object->layer_height_profile[i] - object->layer_height_profile[i]) > EPSILON )
|
||||
return "The Wipe tower is only supported if all objects have the same layer height profile";
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
/*for (size_t i = 5; i < object->layer_height_profile.size(); i += 2)
|
||||
if (object->layer_height_profile[i-1] > slicing_params.object_print_z_min + EPSILON &&
|
||||
std::abs(object->layer_height_profile[i] - object->config.layer_height) > EPSILON)
|
||||
return "The Wipe Tower is currently only supported with constant Z layer spacing. Layer editing is not allowed.";
|
||||
return "The Wipe Tower is currently only supported with constant Z layer spacing. Layer editing is not allowed.";*/
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -613,7 +640,12 @@ std::string Print::validate() const
|
|||
for (unsigned int extruder_id : extruders)
|
||||
nozzle_diameters.push_back(this->config.nozzle_diameter.get_at(extruder_id));
|
||||
double min_nozzle_diameter = *std::min_element(nozzle_diameters.begin(), nozzle_diameters.end());
|
||||
|
||||
|
||||
unsigned int total_extruders_count = this->config.nozzle_diameter.size();
|
||||
for (const auto& extruder_idx : extruders)
|
||||
if ( extruder_idx >= total_extruders_count )
|
||||
return "One or more object were assigned an extruder that the printer does not have.";
|
||||
|
||||
for (PrintObject *object : this->objects) {
|
||||
if ((object->config.support_material_extruder == -1 || object->config.support_material_interface_extruder == -1) &&
|
||||
(object->config.raft_layers > 0 || object->config.support_material.value)) {
|
||||
|
@ -1026,22 +1058,33 @@ void Print::_make_wipe_tower()
|
|||
}
|
||||
}
|
||||
|
||||
// Get wiping matrix to get number of extruders and convert vector<double> to vector<float>:
|
||||
std::vector<float> wiping_volumes((this->config.wiping_volumes_matrix.values).begin(),(this->config.wiping_volumes_matrix.values).end());
|
||||
|
||||
// Initialize the wipe tower.
|
||||
WipeTowerPrusaMM wipe_tower(
|
||||
float(this->config.wipe_tower_x.value), float(this->config.wipe_tower_y.value),
|
||||
float(this->config.wipe_tower_width.value), float(this->config.wipe_tower_per_color_wipe.value),
|
||||
m_tool_ordering.first_extruder());
|
||||
|
||||
float(this->config.wipe_tower_width.value),
|
||||
float(this->config.wipe_tower_rotation_angle.value), float(this->config.cooling_tube_retraction.value),
|
||||
float(this->config.cooling_tube_length.value), float(this->config.parking_pos_retraction.value),
|
||||
float(this->config.wipe_tower_bridging), wiping_volumes, m_tool_ordering.first_extruder());
|
||||
|
||||
//wipe_tower.set_retract();
|
||||
//wipe_tower.set_zhop();
|
||||
|
||||
// Set the extruder & material properties at the wipe tower object.
|
||||
for (size_t i = 0; i < 4; ++ i)
|
||||
for (size_t i = 0; i < (int)(sqrt(wiping_volumes.size())+EPSILON); ++ i)
|
||||
wipe_tower.set_extruder(
|
||||
i,
|
||||
WipeTowerPrusaMM::parse_material(this->config.filament_type.get_at(i).c_str()),
|
||||
this->config.temperature.get_at(i),
|
||||
this->config.first_layer_temperature.get_at(i));
|
||||
this->config.first_layer_temperature.get_at(i),
|
||||
this->config.filament_loading_speed.get_at(i),
|
||||
this->config.filament_unloading_speed.get_at(i),
|
||||
this->config.filament_toolchange_delay.get_at(i),
|
||||
this->config.filament_cooling_time.get_at(i),
|
||||
this->config.filament_ramming_parameters.get_at(i),
|
||||
this->config.nozzle_diameter.get_at(i));
|
||||
|
||||
// When printing the first layer's wipe tower, the first extruder is expected to be active and primed.
|
||||
// Therefore the number of wipe sections at the wipe tower will be (m_tool_ordering.front().extruders-1) at the 1st layer.
|
||||
|
@ -1049,12 +1092,37 @@ void Print::_make_wipe_tower()
|
|||
bool last_priming_wipe_full = m_tool_ordering.front().extruders.size() > m_tool_ordering.front().wipe_tower_partitions;
|
||||
|
||||
m_wipe_tower_priming = Slic3r::make_unique<WipeTower::ToolChangeResult>(
|
||||
wipe_tower.prime(this->skirt_first_layer_height(), m_tool_ordering.all_extruders(), ! last_priming_wipe_full, WipeTower::PURPOSE_EXTRUDE));
|
||||
wipe_tower.prime(this->skirt_first_layer_height(), m_tool_ordering.all_extruders(), ! last_priming_wipe_full));
|
||||
|
||||
|
||||
// Lets go through the wipe tower layers and determine pairs of extruder changes for each
|
||||
// to pass to wipe_tower (so that it can use it for planning the layout of the tower)
|
||||
{
|
||||
unsigned int current_extruder_id = m_tool_ordering.all_extruders().back();
|
||||
for (const auto &layer_tools : m_tool_ordering.layer_tools()) { // for all layers
|
||||
if (!layer_tools.has_wipe_tower) continue;
|
||||
bool first_layer = &layer_tools == &m_tool_ordering.front();
|
||||
wipe_tower.plan_toolchange(layer_tools.print_z, layer_tools.wipe_tower_layer_height, current_extruder_id, current_extruder_id,false);
|
||||
for (const auto extruder_id : layer_tools.extruders) {
|
||||
if ((first_layer && extruder_id == m_tool_ordering.all_extruders().back()) || extruder_id != current_extruder_id) {
|
||||
wipe_tower.plan_toolchange(layer_tools.print_z, layer_tools.wipe_tower_layer_height, current_extruder_id, extruder_id, first_layer && extruder_id == m_tool_ordering.all_extruders().back());
|
||||
current_extruder_id = extruder_id;
|
||||
}
|
||||
}
|
||||
if (&layer_tools == &m_tool_ordering.back() || (&layer_tools + 1)->wipe_tower_partitions == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Generate the wipe tower layers.
|
||||
m_wipe_tower_tool_changes.reserve(m_tool_ordering.layer_tools().size());
|
||||
wipe_tower.generate(m_wipe_tower_tool_changes);
|
||||
|
||||
// Set current_extruder_id to the last extruder primed.
|
||||
unsigned int current_extruder_id = m_tool_ordering.all_extruders().back();
|
||||
/*unsigned int current_extruder_id = m_tool_ordering.all_extruders().back();
|
||||
|
||||
for (const ToolOrdering::LayerTools &layer_tools : m_tool_ordering.layer_tools()) {
|
||||
if (! layer_tools.has_wipe_tower)
|
||||
// This is a support only layer, or the wipe tower does not reach to this height.
|
||||
|
@ -1098,7 +1166,7 @@ void Print::_make_wipe_tower()
|
|||
m_wipe_tower_tool_changes.emplace_back(std::move(tool_changes));
|
||||
if (last_layer)
|
||||
break;
|
||||
}
|
||||
}*/
|
||||
|
||||
// Unload the current filament over the purge tower.
|
||||
coordf_t layer_height = this->objects.front()->config.layer_height.value;
|
||||
|
@ -1117,7 +1185,7 @@ void Print::_make_wipe_tower()
|
|||
wipe_tower.set_layer(float(m_tool_ordering.back().print_z), float(layer_height), 0, false, true);
|
||||
}
|
||||
m_wipe_tower_final_purge = Slic3r::make_unique<WipeTower::ToolChangeResult>(
|
||||
wipe_tower.tool_change((unsigned int)-1, false, WipeTower::PURPOSE_EXTRUDE));
|
||||
wipe_tower.tool_change((unsigned int)-1, false));
|
||||
}
|
||||
|
||||
std::string Print::output_filename()
|
||||
|
|
|
@ -166,6 +166,22 @@ PrintConfigDef::PrintConfigDef()
|
|||
def->cli = "cooling!";
|
||||
def->default_value = new ConfigOptionBools { true };
|
||||
|
||||
def = this->add("cooling_tube_retraction", coFloat);
|
||||
def->label = L("Cooling tube position");
|
||||
def->tooltip = L("Distance of the center-point of the cooling tube from the extruder tip ");
|
||||
def->sidetext = L("mm");
|
||||
def->cli = "cooling_tube_retraction=f";
|
||||
def->min = 0;
|
||||
def->default_value = new ConfigOptionFloat(91.5f);
|
||||
|
||||
def = this->add("cooling_tube_length", coFloat);
|
||||
def->label = L("Cooling tube length");
|
||||
def->tooltip = L("Length of the cooling tube to limit space for cooling moves inside it ");
|
||||
def->sidetext = L("mm");
|
||||
def->cli = "cooling_tube_length=f";
|
||||
def->min = 0;
|
||||
def->default_value = new ConfigOptionFloat(5.f);
|
||||
|
||||
def = this->add("default_acceleration", coFloat);
|
||||
def->label = L("Default");
|
||||
def->tooltip = L("This is the acceleration your printer will be reset to after "
|
||||
|
@ -439,6 +455,49 @@ PrintConfigDef::PrintConfigDef()
|
|||
def->min = 0;
|
||||
def->default_value = new ConfigOptionFloats { 0. };
|
||||
|
||||
def = this->add("filament_loading_speed", coFloats);
|
||||
def->label = L("Loading speed");
|
||||
def->tooltip = L("Speed used for loading the filament on the wipe tower. ");
|
||||
def->sidetext = L("mm/s");
|
||||
def->cli = "filament-loading-speed=f@";
|
||||
def->min = 0;
|
||||
def->default_value = new ConfigOptionFloats { 28. };
|
||||
|
||||
def = this->add("filament_unloading_speed", coFloats);
|
||||
def->label = L("Unloading speed");
|
||||
def->tooltip = L("Speed used for unloading the filament on the wipe tower (does not affect "
|
||||
" initial part of unloading just after ramming). ");
|
||||
def->sidetext = L("mm/s");
|
||||
def->cli = "filament-unloading-speed=f@";
|
||||
def->min = 0;
|
||||
def->default_value = new ConfigOptionFloats { 90. };
|
||||
|
||||
def = this->add("filament_toolchange_delay", coFloats);
|
||||
def->label = L("Delay after unloading");
|
||||
def->tooltip = L("Time to wait after the filament is unloaded. "
|
||||
"May help to get reliable toolchanges with flexible materials "
|
||||
"that may need more time to shrink to original dimensions. ");
|
||||
def->sidetext = L("s");
|
||||
def->cli = "filament-toolchange-delay=f@";
|
||||
def->min = 0;
|
||||
def->default_value = new ConfigOptionFloats { 0. };
|
||||
|
||||
def = this->add("filament_cooling_time", coFloats);
|
||||
def->label = L("Cooling time");
|
||||
def->tooltip = L("The filament is slowly moved back and forth after retraction into the cooling tube "
|
||||
"for this amount of time.");
|
||||
def->cli = "filament_cooling_time=i@";
|
||||
def->sidetext = L("s");
|
||||
def->min = 0;
|
||||
def->default_value = new ConfigOptionFloats { 14.f };
|
||||
|
||||
def = this->add("filament_ramming_parameters", coStrings);
|
||||
def->label = L("Ramming parameters");
|
||||
def->tooltip = L("This string is edited by RammingDialog and contains ramming specific parameters ");
|
||||
def->cli = "filament-ramming-parameters=s@";
|
||||
def->default_value = new ConfigOptionStrings { "120 100 6.6 6.8 7.2 7.6 7.9 8.2 8.7 9.4 9.9 10.0|"
|
||||
" 0.05 6.6 0.45 6.8 0.95 7.8 1.45 8.3 1.95 9.7 2.45 10 2.95 7.6 3.45 7.6 3.95 7.6 4.45 7.6 4.95 7.6" };
|
||||
|
||||
def = this->add("filament_diameter", coFloats);
|
||||
def->label = L("Diameter");
|
||||
def->tooltip = L("Enter your filament diameter here. Good precision is required, so use a caliper "
|
||||
|
@ -977,6 +1036,15 @@ PrintConfigDef::PrintConfigDef()
|
|||
def->cli = "overhangs!";
|
||||
def->default_value = new ConfigOptionBool(true);
|
||||
|
||||
def = this->add("parking_pos_retraction", coFloat);
|
||||
def->label = L("Filament parking position");
|
||||
def->tooltip = L("Distance of the extruder tip from the position where the filament is parked "
|
||||
"when unloaded. This should match the value in printer firmware. ");
|
||||
def->sidetext = L("mm");
|
||||
def->cli = "parking_pos_retraction=f";
|
||||
def->min = 0;
|
||||
def->default_value = new ConfigOptionFloat(92.f);
|
||||
|
||||
def = this->add("perimeter_acceleration", coFloat);
|
||||
def->label = L("Perimeters");
|
||||
def->tooltip = L("This is the acceleration your printer will use for perimeters. "
|
||||
|
@ -1744,6 +1812,25 @@ PrintConfigDef::PrintConfigDef()
|
|||
def->cli = "wipe-tower!";
|
||||
def->default_value = new ConfigOptionBool(false);
|
||||
|
||||
def = this->add("wiping_volumes_extruders", coFloats);
|
||||
def->label = L("Purging volumes - load/unload volumes");
|
||||
def->tooltip = L("This vector saves required volumes to change from/to each tool used on the "
|
||||
"wipe tower. These values are used to simplify creation of the full purging "
|
||||
"volumes below. ");
|
||||
def->cli = "wiping-volumes-extruders=f@";
|
||||
def->default_value = new ConfigOptionFloats { 70.f, 70.f, 70.f, 70.f, 70.f, 70.f, 70.f, 70.f, 70.f, 70.f };
|
||||
|
||||
def = this->add("wiping_volumes_matrix", coFloats);
|
||||
def->label = L("Purging volumes - matrix");
|
||||
def->tooltip = L("This matrix describes volumes (in cubic milimetres) required to purge the"
|
||||
" new filament on the wipe tower for any given pair of tools. ");
|
||||
def->cli = "wiping-volumes-matrix=f@";
|
||||
def->default_value = new ConfigOptionFloats { 0.f, 140.f, 140.f, 140.f, 140.f,
|
||||
140.f, 0.f, 140.f, 140.f, 140.f,
|
||||
140.f, 140.f, 0.f, 140.f, 140.f,
|
||||
140.f, 140.f, 140.f, 0.f, 140.f,
|
||||
140.f, 140.f, 140.f, 140.f, 0.f };
|
||||
|
||||
def = this->add("wipe_tower_x", coFloat);
|
||||
def->label = L("Position X");
|
||||
def->tooltip = L("X coordinate of the left front corner of a wipe tower");
|
||||
|
@ -1765,14 +1852,19 @@ PrintConfigDef::PrintConfigDef()
|
|||
def->cli = "wipe-tower-width=f";
|
||||
def->default_value = new ConfigOptionFloat(60.);
|
||||
|
||||
def = this->add("wipe_tower_per_color_wipe", coFloat);
|
||||
def->label = L("Per color change depth");
|
||||
def->tooltip = L("Depth of a wipe color per color change. For N colors, there will be "
|
||||
"maximum (N-1) tool switches performed, therefore the total depth "
|
||||
"of the wipe tower will be (N-1) times this value.");
|
||||
def = this->add("wipe_tower_rotation_angle", coFloat);
|
||||
def->label = L("Wipe tower rotation angle");
|
||||
def->tooltip = L("Wipe tower rotation angle with respect to x-axis ");
|
||||
def->sidetext = L("degrees");
|
||||
def->cli = "wipe-tower-rotation-angle=f";
|
||||
def->default_value = new ConfigOptionFloat(0.);
|
||||
|
||||
def = this->add("wipe_tower_bridging", coFloat);
|
||||
def->label = L("Maximal bridging distance");
|
||||
def->tooltip = L("Maximal distance between supports on sparse infill sections. ");
|
||||
def->sidetext = L("mm");
|
||||
def->cli = "wipe-tower-per-color-wipe=f";
|
||||
def->default_value = new ConfigOptionFloat(15.);
|
||||
def->cli = "wipe-tower-bridging=f";
|
||||
def->default_value = new ConfigOptionFloat(10.);
|
||||
|
||||
def = this->add("xy_size_compensation", coFloat);
|
||||
def->label = L("XY Size Compensation");
|
||||
|
@ -1852,8 +1944,9 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va
|
|||
"standby_temperature", "scale", "rotate", "duplicate", "duplicate_grid",
|
||||
"start_perimeters_at_concave_points", "start_perimeters_at_non_overhang", "randomize_start",
|
||||
"seal_position", "vibration_limit", "bed_size", "octoprint_host",
|
||||
"print_center", "g0", "threads", "pressure_advance"
|
||||
"print_center", "g0", "threads", "pressure_advance", "wipe_tower_per_color_wipe"
|
||||
};
|
||||
|
||||
if (ignore.find(opt_key) != ignore.end()) {
|
||||
opt_key = "";
|
||||
return;
|
||||
|
|
|
@ -154,6 +154,13 @@ public:
|
|||
|
||||
// Validate the PrintConfig. Returns an empty string on success, otherwise an error message is returned.
|
||||
std::string validate();
|
||||
|
||||
// Verify whether the opt_key has not been obsoleted or renamed.
|
||||
// Both opt_key and value may be modified by handle_legacy().
|
||||
// If the opt_key is no more valid in this version of Slic3r, opt_key is cleared by handle_legacy().
|
||||
// handle_legacy() is called internally by set_deserialize().
|
||||
void handle_legacy(t_config_option_key &opt_key, std::string &value) const override
|
||||
{ PrintConfigDef::handle_legacy(opt_key, value); }
|
||||
};
|
||||
|
||||
template<typename CONFIG>
|
||||
|
@ -466,6 +473,11 @@ public:
|
|||
ConfigOptionBools filament_soluble;
|
||||
ConfigOptionFloats filament_cost;
|
||||
ConfigOptionFloats filament_max_volumetric_speed;
|
||||
ConfigOptionFloats filament_loading_speed;
|
||||
ConfigOptionFloats filament_unloading_speed;
|
||||
ConfigOptionFloats filament_toolchange_delay;
|
||||
ConfigOptionFloats filament_cooling_time;
|
||||
ConfigOptionStrings filament_ramming_parameters;
|
||||
ConfigOptionBool gcode_comments;
|
||||
ConfigOptionEnum<GCodeFlavor> gcode_flavor;
|
||||
ConfigOptionString layer_gcode;
|
||||
|
@ -491,7 +503,11 @@ public:
|
|||
ConfigOptionBool use_relative_e_distances;
|
||||
ConfigOptionBool use_volumetric_e;
|
||||
ConfigOptionBool variable_layer_height;
|
||||
|
||||
ConfigOptionFloat cooling_tube_retraction;
|
||||
ConfigOptionFloat cooling_tube_length;
|
||||
ConfigOptionFloat parking_pos_retraction;
|
||||
|
||||
|
||||
std::string get_extrusion_axis() const
|
||||
{
|
||||
return
|
||||
|
@ -515,6 +531,11 @@ protected:
|
|||
OPT_PTR(filament_soluble);
|
||||
OPT_PTR(filament_cost);
|
||||
OPT_PTR(filament_max_volumetric_speed);
|
||||
OPT_PTR(filament_loading_speed);
|
||||
OPT_PTR(filament_unloading_speed);
|
||||
OPT_PTR(filament_toolchange_delay);
|
||||
OPT_PTR(filament_cooling_time);
|
||||
OPT_PTR(filament_ramming_parameters);
|
||||
OPT_PTR(gcode_comments);
|
||||
OPT_PTR(gcode_flavor);
|
||||
OPT_PTR(layer_gcode);
|
||||
|
@ -540,6 +561,9 @@ protected:
|
|||
OPT_PTR(use_relative_e_distances);
|
||||
OPT_PTR(use_volumetric_e);
|
||||
OPT_PTR(variable_layer_height);
|
||||
OPT_PTR(cooling_tube_retraction);
|
||||
OPT_PTR(cooling_tube_length);
|
||||
OPT_PTR(parking_pos_retraction);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -610,6 +634,10 @@ public:
|
|||
ConfigOptionFloat wipe_tower_y;
|
||||
ConfigOptionFloat wipe_tower_width;
|
||||
ConfigOptionFloat wipe_tower_per_color_wipe;
|
||||
ConfigOptionFloat wipe_tower_rotation_angle;
|
||||
ConfigOptionFloat wipe_tower_bridging;
|
||||
ConfigOptionFloats wiping_volumes_matrix;
|
||||
ConfigOptionFloats wiping_volumes_extruders;
|
||||
ConfigOptionFloat z_offset;
|
||||
|
||||
protected:
|
||||
|
@ -675,6 +703,10 @@ protected:
|
|||
OPT_PTR(wipe_tower_y);
|
||||
OPT_PTR(wipe_tower_width);
|
||||
OPT_PTR(wipe_tower_per_color_wipe);
|
||||
OPT_PTR(wipe_tower_rotation_angle);
|
||||
OPT_PTR(wipe_tower_bridging);
|
||||
OPT_PTR(wiping_volumes_matrix);
|
||||
OPT_PTR(wiping_volumes_extruders);
|
||||
OPT_PTR(z_offset);
|
||||
}
|
||||
};
|
||||
|
@ -713,6 +745,7 @@ class FullPrintConfig :
|
|||
public:
|
||||
// Validate the FullPrintConfig. Returns an empty string on success, otherwise an error message is returned.
|
||||
std::string validate();
|
||||
|
||||
protected:
|
||||
// Protected constructor to be called to initialize ConfigCache::m_default.
|
||||
FullPrintConfig(int) : PrintObjectConfig(0), PrintRegionConfig(0), PrintConfig(0), HostConfig(0) {}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue