2017-05-16 11:45:28 +00:00
|
|
|
#ifndef WipeTowerPrusaMM_hpp_
|
|
|
|
#define WipeTowerPrusaMM_hpp_
|
|
|
|
|
2017-05-16 14:02:52 +00:00
|
|
|
#include <cmath>
|
2017-05-16 11:45:28 +00:00
|
|
|
#include <string>
|
2018-02-28 15:04:56 +00:00
|
|
|
#include <sstream>
|
2017-05-16 11:45:28 +00:00
|
|
|
#include <utility>
|
|
|
|
|
|
|
|
#include "WipeTower.hpp"
|
|
|
|
|
2017-12-07 10:59:14 +00:00
|
|
|
// Following is used to calculate extrusion flow - should be taken from config in future
|
2018-02-28 18:53:32 +00:00
|
|
|
const float Filament_Area = M_PI * 1.75f * 1.75f / 4.f; // filament area in mm^3
|
|
|
|
const float Nozzle_Diameter = 0.4f; // nozzle diameter in mm
|
2017-12-07 10:59:14 +00:00
|
|
|
// desired line width (oval) in multiples of nozzle diameter - may not be actually neccessary to adjust
|
2018-02-28 18:53:32 +00:00
|
|
|
const float Width_To_Nozzle_Ratio = 1.25f;
|
2017-12-21 12:28:26 +00:00
|
|
|
|
2018-02-21 12:07:32 +00:00
|
|
|
// m_perimeter_width was hardcoded until now as 0.5 (for 0.4 nozzle and 0.2 layer height)
|
|
|
|
// FIXME m_perimeter_width is used in plan_toolchange - take care of proper initialization value when changing to variable
|
2018-02-28 18:53:32 +00:00
|
|
|
const float Konst = 1.f;
|
|
|
|
const float m_perimeter_width = Nozzle_Diameter * Width_To_Nozzle_Ratio * Konst;
|
2018-02-28 15:04:56 +00:00
|
|
|
|
2018-02-28 18:53:32 +00:00
|
|
|
const float WT_EPSILON = 1e-3f;
|
2018-02-28 15:04:56 +00:00
|
|
|
|
|
|
|
|
2017-05-16 11:45:28 +00:00
|
|
|
namespace Slic3r
|
|
|
|
{
|
|
|
|
|
|
|
|
namespace PrusaMultiMaterial {
|
|
|
|
class Writer;
|
|
|
|
};
|
|
|
|
|
2018-02-28 15:04:56 +00:00
|
|
|
|
|
|
|
|
|
|
|
// Operator overload to output std::pairs
|
|
|
|
template <typename T>
|
|
|
|
std::ostream& operator<<(std::ostream& stream,const std::pair<T,T>& pair) {
|
|
|
|
return stream << pair.first << " " << pair.second;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Operator overload to output elements of a vector to std::ofstream easily:
|
|
|
|
template <typename T>
|
|
|
|
std::ostream& operator<<(std::ostream& stream,const std::vector<T>& vect) {
|
|
|
|
for (const auto& element : vect)
|
|
|
|
stream << element << " ";
|
|
|
|
return stream;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Operator overload to input elements of a vector from std::ifstream easily (reads until a fail)
|
|
|
|
template <typename T>
|
|
|
|
std::istream& operator>>(std::istream& stream, std::vector<T>& vect) {
|
|
|
|
vect.clear();
|
|
|
|
T value{};
|
|
|
|
bool we_read_something = false;
|
|
|
|
while (stream >> value) {
|
|
|
|
vect.push_back(value);
|
|
|
|
we_read_something = true;
|
|
|
|
}
|
|
|
|
if (!stream.eof() && we_read_something) { // if this is not eof, we might be at separator - let's get rid of it
|
|
|
|
stream.clear(); // if we failed on very first line or reached eof, return stream in !good() state
|
|
|
|
stream.get(); // get() whatever we are stuck at
|
|
|
|
}
|
|
|
|
return stream;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// This struct is used to store parameters and to pass it to wipe tower generator
|
|
|
|
struct WipeTowerParameters {
|
|
|
|
WipeTowerParameters() { } // create new empty object
|
|
|
|
WipeTowerParameters(const std::string& init_data) { // create object and initialize from std::string
|
|
|
|
std::istringstream in(init_data); // validation of input is left to the caller
|
|
|
|
in >> bridging >> adhesion >> sampling;
|
|
|
|
for (std::vector<float> vect{} ; in >> vect ;) { // until we get to fail state ("**")...
|
|
|
|
if (vect.size()>=3) {
|
|
|
|
cooling_time.push_back(vect[0]);
|
|
|
|
ramming_line_width_multiplicator.push_back(vect[1]);
|
|
|
|
ramming_step_multiplicator.push_back(vect[2]);
|
|
|
|
vect.erase(vect.begin(),vect.begin()+3);
|
|
|
|
}
|
|
|
|
else vect.clear(); // something's not right, we will restore defaults anyway
|
|
|
|
ramming_speed.push_back(vect);
|
|
|
|
|
|
|
|
if (in.good()) {
|
|
|
|
in >> vect;
|
|
|
|
std::vector<std::pair<float,float>> pairs;
|
|
|
|
for (unsigned int i=0;i<vect.size();++i)
|
|
|
|
if (i%2==1)
|
|
|
|
pairs.push_back(std::make_pair(vect[i-1],vect[i]));
|
|
|
|
ramming_buttons.push_back(pairs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
in.clear();
|
|
|
|
in.get();
|
|
|
|
|
|
|
|
for (std::vector<float> vect{} ; in >> vect ;) { // let's keep reading
|
|
|
|
wipe_volumes.push_back(vect);
|
|
|
|
}
|
|
|
|
in.clear();
|
|
|
|
in.get();
|
|
|
|
|
|
|
|
std::vector<int> vect{};
|
|
|
|
in >> vect;
|
|
|
|
for (unsigned int i=0;i<vect.size();++i)
|
|
|
|
if (i%2==1)
|
|
|
|
filament_wipe_volumes.push_back(std::make_pair(vect[i-1],vect[i]));
|
2018-03-02 12:26:16 +00:00
|
|
|
|
|
|
|
if (!validate()) // in case we did not parse the input right
|
|
|
|
set_defaults();
|
2018-02-28 15:04:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
std::string to_string() {
|
|
|
|
std::ostringstream out;
|
|
|
|
out << bridging << " " << int(adhesion) << " " << sampling << "\n";
|
|
|
|
for (unsigned extruder=0;extruder<cooling_time.size();++extruder) {
|
|
|
|
out << "\n" << cooling_time[extruder] << " " << ramming_line_width_multiplicator[extruder] << " "
|
|
|
|
<< ramming_step_multiplicator[extruder] << " " << ramming_speed[extruder] << "*"
|
|
|
|
<< ramming_buttons[extruder] << "*";
|
|
|
|
}
|
|
|
|
out << "*\n";
|
|
|
|
for (auto& radek : wipe_volumes)
|
|
|
|
out << "\n" << radek << "*";
|
|
|
|
out << "*\n";
|
|
|
|
out << filament_wipe_volumes << "*";
|
|
|
|
return out.str();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool validate() const { // basic check for validity to distinguish most dramatic failures
|
|
|
|
const unsigned int num = cooling_time.size();
|
|
|
|
if ( num < 1 || ramming_line_width_multiplicator.size()!=num || ramming_step_multiplicator.size()!=num ||
|
|
|
|
ramming_buttons.size()!=num || wipe_volumes.size()!=num ||
|
|
|
|
filament_wipe_volumes.size()!=num)
|
|
|
|
return false;
|
|
|
|
for (const auto& row : wipe_volumes)
|
|
|
|
if (row.size()!=num)
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
void set_defaults() {
|
|
|
|
bridging = 10;
|
|
|
|
adhesion = true;
|
|
|
|
sampling = 0.25f;
|
|
|
|
cooling_time = {15,15,15,15};
|
|
|
|
ramming_line_width_multiplicator = {1.5f, 1.5f, 1.5f, 1.5f};
|
|
|
|
ramming_step_multiplicator = {1.1f, 1.1f, 1.1f, 1.1f};
|
|
|
|
ramming_speed.clear();
|
|
|
|
ramming_buttons.clear();
|
|
|
|
for (unsigned int i=0;i<4;++i) {
|
2018-02-28 18:53:32 +00:00
|
|
|
ramming_speed.push_back(std::vector<float>{7.6f, 7.6f, 7.6f, 7.6f, 9.f, 9.f, 9.f, 10.7f, 10.7f, 10.7f});
|
|
|
|
ramming_buttons.push_back(std::vector<std::pair<float,float>>{{0.05f, 6.6f},{0.45f, 6.8f},{0.95f, 7.8f},{1.45f, 8.3f},{1.95f, 9.7f},{2.45f,10.f},{2.95f, 7.6f},{3.45f, 7.6f},{3.95f, 7.6f},{4.45f, 7.6f},{4.95f, 7.6f}});
|
2018-02-28 15:04:56 +00:00
|
|
|
}
|
2018-02-28 18:53:32 +00:00
|
|
|
wipe_volumes = {{ 0.f, 60.f, 60.f, 60.f},
|
|
|
|
{ 60.f, 0.f, 60.f, 60.f},
|
|
|
|
{ 60.f, 60.f, 0.f, 60.f},
|
|
|
|
{ 60.f, 60.f, 60.f, 0.f}};
|
|
|
|
filament_wipe_volumes = {{30.f,30.f},{30.f,30.f},{30.f,30.f},{30.f,30.f}};
|
2018-02-28 15:04:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int bridging = 0.f;
|
|
|
|
bool adhesion = false;
|
|
|
|
float sampling = 0.25f; // this does not quite work yet, keep it fixed to 0.25f
|
|
|
|
std::vector<int> cooling_time;
|
|
|
|
std::vector<float> ramming_line_width_multiplicator;
|
|
|
|
std::vector<float> ramming_step_multiplicator;
|
|
|
|
std::vector<std::vector<float>> ramming_speed;
|
|
|
|
std::vector<std::vector<std::pair<float,float>>> ramming_buttons;
|
|
|
|
std::vector<std::vector<float>> wipe_volumes;
|
|
|
|
std::vector<std::pair<int,int>> filament_wipe_volumes;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2017-05-16 11:45:28 +00:00
|
|
|
class WipeTowerPrusaMM : public WipeTower
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
enum material_type
|
|
|
|
{
|
|
|
|
INVALID = -1,
|
|
|
|
PLA = 0, // E:210C B:55C
|
|
|
|
ABS = 1, // E:255C B:100C
|
|
|
|
PET = 2, // E:240C B:90C
|
|
|
|
HIPS = 3, // E:220C B:100C
|
|
|
|
FLEX = 4, // E:245C B:80C
|
|
|
|
SCAFF = 5, // E:215C B:55C
|
|
|
|
EDGE = 6, // E:240C B:80C
|
|
|
|
NGEN = 7, // E:230C B:80C
|
|
|
|
PVA = 8 // E:210C B:80C
|
|
|
|
};
|
|
|
|
|
|
|
|
// Parse material name into material_type.
|
|
|
|
static material_type parse_material(const char *name);
|
|
|
|
|
|
|
|
// x -- x coordinates of wipe tower in mm ( left bottom corner )
|
|
|
|
// 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
|
2018-03-01 15:15:00 +00:00
|
|
|
WipeTowerPrusaMM(float x, float y, float width, float wipe_area, float rotation_angle, float cooling_tube_retraction,
|
|
|
|
float cooling_tube_length, float parking_pos_retraction, std::string& parameters,
|
|
|
|
unsigned int initial_tool) :
|
2017-05-16 11:45:28 +00:00
|
|
|
m_wipe_tower_pos(x, y),
|
|
|
|
m_wipe_tower_width(width),
|
2017-11-30 11:08:22 +00:00
|
|
|
m_wipe_tower_rotation_angle(rotation_angle),
|
2018-02-21 12:07:32 +00:00
|
|
|
m_y_shift(0.f),
|
2017-05-25 20:27:53 +00:00
|
|
|
m_z_pos(0.f),
|
2018-02-21 12:07:32 +00:00
|
|
|
m_is_first_layer(false),
|
2018-02-28 15:04:56 +00:00
|
|
|
m_is_last_layer(false),
|
2018-03-02 12:26:16 +00:00
|
|
|
m_cooling_tube_retraction(cooling_tube_retraction),
|
|
|
|
m_cooling_tube_length(cooling_tube_length),
|
|
|
|
m_parking_pos_retraction(parking_pos_retraction),
|
2018-02-28 15:04:56 +00:00
|
|
|
m_current_tool(initial_tool),
|
|
|
|
m_par(parameters)
|
2017-05-25 20:27:53 +00:00
|
|
|
{
|
2017-05-16 11:45:28 +00:00
|
|
|
for (size_t i = 0; i < 4; ++ i) {
|
|
|
|
// Extruder specific parameters.
|
2018-03-05 09:45:35 +00:00
|
|
|
m_filpar[i].material = PLA;
|
|
|
|
m_filpar[i].temperature = 0;
|
|
|
|
m_filpar[i].first_layer_temperature = 0;
|
2017-05-16 11:45:28 +00:00
|
|
|
}
|
|
|
|
}
|
2017-05-25 20:27:53 +00:00
|
|
|
|
2017-05-16 11:45:28 +00:00
|
|
|
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; }
|
2017-12-21 12:28:26 +00:00
|
|
|
|
|
|
|
|
2017-05-16 11:45:28 +00:00
|
|
|
// Set the extruder properties.
|
2018-03-05 09:45:35 +00:00
|
|
|
void set_extruder(size_t idx, material_type material, int temp, int first_layer_temp, float loading_speed,
|
|
|
|
float unloading_speed, float delay)
|
2017-05-16 11:45:28 +00:00
|
|
|
{
|
2018-03-05 09:45:35 +00:00
|
|
|
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;
|
2017-05-16 11:45:28 +00:00
|
|
|
}
|
|
|
|
|
2017-12-21 12:28:26 +00:00
|
|
|
|
|
|
|
// Setter for 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.
|
2017-12-22 10:26:43 +00:00
|
|
|
void plan_toolchange(float z_par, float layer_height_par, unsigned int old_tool, unsigned int new_tool, bool brim);
|
2017-12-21 12:28:26 +00:00
|
|
|
|
2018-02-22 10:03:29 +00:00
|
|
|
// Iterates through prepared m_plan, generates ToolChangeResults and appends them to "result"
|
2017-12-21 12:28:26 +00:00
|
|
|
void generate(std::vector<std::vector<WipeTower::ToolChangeResult>> &result);
|
|
|
|
|
2018-02-22 10:03:29 +00:00
|
|
|
// Calculates depth for all layers and propagates them downwards
|
2018-02-21 12:07:32 +00:00
|
|
|
void plan_tower();
|
|
|
|
|
2018-02-22 10:03:29 +00:00
|
|
|
// Goes through m_plan and recalculates depths and width of the WT to make it exactly square - experimental
|
2018-02-21 12:07:32 +00:00
|
|
|
void make_wipe_tower_square();
|
|
|
|
|
2018-03-06 18:14:12 +00:00
|
|
|
// Goes through m_plan, calculates border and finish_layer extrusions and subtracts them from last wipe
|
|
|
|
void save_on_last_wipe();
|
|
|
|
|
2017-05-16 11:45:28 +00:00
|
|
|
// Switch to a next layer.
|
|
|
|
virtual void set_layer(
|
|
|
|
// Print height of this layer.
|
2017-12-21 12:28:26 +00:00
|
|
|
float print_z,
|
|
|
|
// Layer height, used to calculate extrusion the rate.
|
|
|
|
float layer_height,
|
2017-05-16 11:45:28 +00:00
|
|
|
// Maximum number of tool changes on this layer or the layers below.
|
2017-12-21 12:28:26 +00:00
|
|
|
size_t max_tool_changes,
|
2017-05-16 11:45:28 +00:00
|
|
|
// Is this the first layer of the print? In that case print the brim first.
|
2017-12-21 12:28:26 +00:00
|
|
|
bool is_first_layer,
|
2017-05-16 11:45:28 +00:00
|
|
|
// Is this the last layer of the waste tower?
|
2017-12-21 12:28:26 +00:00
|
|
|
bool is_last_layer)
|
2017-05-16 11:45:28 +00:00
|
|
|
{
|
|
|
|
m_z_pos = print_z;
|
2017-05-25 20:27:53 +00:00
|
|
|
m_layer_height = layer_height;
|
2017-05-16 11:45:28 +00:00
|
|
|
m_is_first_layer = is_first_layer;
|
2017-12-21 12:28:26 +00:00
|
|
|
m_print_brim = is_first_layer;
|
2018-02-21 12:07:32 +00:00
|
|
|
m_depth_traversed = 0.f; // to make room for perimeter line
|
2017-05-17 14:45:37 +00:00
|
|
|
m_current_shape = (! is_first_layer && m_current_shape == SHAPE_NORMAL) ? SHAPE_REVERSED : SHAPE_NORMAL;
|
2018-02-21 12:07:32 +00:00
|
|
|
|
2017-05-18 14:53:19 +00:00
|
|
|
++ m_num_layer_changes;
|
2017-12-07 10:59:14 +00:00
|
|
|
|
|
|
|
// Calculates extrusion flow from desired line width, nozzle diameter, filament diameter and layer_height
|
2017-12-21 12:28:26 +00:00
|
|
|
m_extrusion_flow = extrusion_flow(layer_height);
|
|
|
|
|
2018-02-22 10:03:29 +00:00
|
|
|
while (!m_plan.empty() && m_layer_info->z < print_z - WT_EPSILON && m_layer_info+1!=m_plan.end())
|
|
|
|
++m_layer_info;
|
2017-05-16 11:45:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Return the wipe tower position.
|
2017-05-25 20:27:53 +00:00
|
|
|
virtual const xy& position() const { return m_wipe_tower_pos; }
|
2017-05-19 17:24:21 +00:00
|
|
|
// Return the wipe tower width.
|
2017-05-25 20:27:53 +00:00
|
|
|
virtual float width() const { return m_wipe_tower_width; }
|
2017-05-16 11:45:28 +00:00
|
|
|
// The wipe tower is finished, there should be no more tool changes or wipe tower prints.
|
2017-05-25 20:27:53 +00:00
|
|
|
virtual bool finished() const { return m_max_color_changes == 0; }
|
2017-05-16 11:45:28 +00:00
|
|
|
|
2017-09-01 15:30:18 +00:00
|
|
|
// Returns gcode to prime the nozzles at the front edge of the print bed.
|
2017-09-12 13:55:38 +00:00
|
|
|
virtual ToolChangeResult prime(
|
|
|
|
// print_z of the first layer.
|
|
|
|
float first_layer_height,
|
|
|
|
// Extruder indices, in the order to be primed. The last extruder will later print the wipe tower brim, print brim and the object.
|
2017-12-03 08:43:00 +00:00
|
|
|
const std::vector<unsigned int> &tools,
|
2017-09-12 13:55:38 +00:00
|
|
|
// 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.
|
2018-03-08 15:44:52 +00:00
|
|
|
bool last_wipe_inside_wipe_tower);
|
2017-09-01 15:30:18 +00:00
|
|
|
|
2017-05-17 08:42:39 +00:00
|
|
|
// Returns gcode for a toolchange and a final print head position.
|
|
|
|
// On the first layer, extrude a brim around the future wipe tower first.
|
2018-03-08 15:44:52 +00:00
|
|
|
virtual ToolChangeResult tool_change(unsigned int new_tool, bool last_in_layer);
|
2017-05-16 11:45:28 +00:00
|
|
|
|
2018-02-22 10:03:29 +00:00
|
|
|
// Fill the unfilled space with a zig-zag.
|
2017-05-17 14:45:37 +00:00
|
|
|
// Call this method only if layer_finished() is false.
|
2018-03-08 15:44:52 +00:00
|
|
|
virtual ToolChangeResult finish_layer();
|
2017-05-17 14:45:37 +00:00
|
|
|
|
2018-02-22 10:03:29 +00:00
|
|
|
// Is the current layer finished?
|
2017-12-21 12:28:26 +00:00
|
|
|
virtual bool layer_finished() const {
|
2018-02-21 12:07:32 +00:00
|
|
|
return ( (m_is_first_layer ? m_wipe_tower_depth - m_perimeter_width : m_layer_info->depth) - WT_EPSILON < m_depth_traversed);
|
2017-12-21 12:28:26 +00:00
|
|
|
}
|
|
|
|
|
2017-05-16 11:45:28 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
WipeTowerPrusaMM();
|
|
|
|
|
2018-02-21 12:07:32 +00:00
|
|
|
enum wipe_shape // A fill-in direction (positive Y, negative Y) alternates with each layer.
|
2017-05-16 11:45:28 +00:00
|
|
|
{
|
2018-02-21 12:07:32 +00:00
|
|
|
SHAPE_NORMAL = 1,
|
2017-05-16 11:45:28 +00:00
|
|
|
SHAPE_REVERSED = -1
|
|
|
|
};
|
|
|
|
|
2018-02-21 12:07:32 +00:00
|
|
|
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
|
2018-02-22 08:28:31 +00:00
|
|
|
float m_wipe_tower_rotation_angle = 0.f; // Wipe tower rotation angle in degrees (with respect to x axis
|
2018-02-21 12:07:32 +00:00
|
|
|
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.
|
|
|
|
bool m_is_last_layer = false;// Is this the last layer of this waste tower?
|
2018-03-07 14:34:12 +00:00
|
|
|
bool m_layer_parity = false;
|
2017-05-16 11:45:28 +00:00
|
|
|
|
|
|
|
// G-code generator parameters.
|
2017-05-18 14:53:19 +00:00
|
|
|
float m_zhop = 0.5f;
|
|
|
|
float m_retract = 4.f;
|
2018-03-01 15:15:00 +00:00
|
|
|
float m_cooling_tube_retraction = 0.f;
|
|
|
|
float m_cooling_tube_length = 0.f;
|
|
|
|
float m_parking_pos_retraction = 0.f;
|
2018-03-05 09:45:35 +00:00
|
|
|
|
2018-02-21 12:07:32 +00:00
|
|
|
float m_line_width = Nozzle_Diameter * 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.
|
2017-05-16 11:45:28 +00:00
|
|
|
|
2018-03-05 09:45:35 +00:00
|
|
|
|
|
|
|
struct FilamentParameters {
|
|
|
|
material_type material;
|
|
|
|
int temperature;
|
|
|
|
int first_layer_temperature;
|
|
|
|
float loading_speed;
|
|
|
|
float unloading_speed;
|
|
|
|
float delay;
|
|
|
|
};
|
|
|
|
|
2017-05-16 11:45:28 +00:00
|
|
|
// Extruder specific parameters.
|
2018-03-05 09:45:35 +00:00
|
|
|
FilamentParameters m_filpar[4];
|
|
|
|
|
2017-05-16 11:45:28 +00:00
|
|
|
|
|
|
|
// State of the wiper tower generator.
|
2018-02-21 12:07:32 +00:00
|
|
|
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.
|
2017-12-21 12:28:26 +00:00
|
|
|
bool m_print_brim = true;
|
2017-05-17 08:42:39 +00:00
|
|
|
// A fill-in direction (positive Y, negative Y) alternates with each layer.
|
2017-05-16 11:45:28 +00:00
|
|
|
wipe_shape m_current_shape = SHAPE_NORMAL;
|
2017-05-25 20:27:53 +00:00
|
|
|
unsigned int m_current_tool = 0;
|
2018-02-28 15:04:56 +00:00
|
|
|
WipeTowerParameters m_par;
|
2018-02-21 12:07:32 +00:00
|
|
|
|
|
|
|
float m_depth_traversed = 0.f; // Current y position at the wipe tower.
|
2017-09-12 13:55:38 +00:00
|
|
|
// 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;
|
2018-01-04 11:03:06 +00:00
|
|
|
bool m_left_to_right = true;
|
2018-02-21 12:07:32 +00:00
|
|
|
float m_extra_spacing = 1.f;
|
2017-05-16 11:45:28 +00:00
|
|
|
|
2018-02-22 10:03:29 +00:00
|
|
|
// 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
|
2017-12-21 12:28:26 +00:00
|
|
|
{
|
|
|
|
if ( layer_height < 0 )
|
|
|
|
return m_extrusion_flow;
|
|
|
|
return layer_height * ( Width_To_Nozzle_Ratio * Nozzle_Diameter - layer_height * (1-M_PI/4.f)) / (Filament_Area);
|
|
|
|
}
|
|
|
|
|
2018-02-22 10:03:29 +00:00
|
|
|
// Calculates length of extrusion line to extrude given volume
|
2018-02-21 12:07:32 +00:00
|
|
|
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.)));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-05-16 11:45:28 +00:00
|
|
|
struct box_coordinates
|
|
|
|
{
|
|
|
|
box_coordinates(float left, float bottom, float width, float height) :
|
|
|
|
ld(left , bottom ),
|
|
|
|
lu(left , bottom + height),
|
|
|
|
rd(left + width, bottom ),
|
|
|
|
ru(left + width, bottom + height) {}
|
|
|
|
box_coordinates(const xy &pos, float width, float height) : box_coordinates(pos.x, pos.y, width, height) {}
|
2017-05-17 14:45:37 +00:00
|
|
|
void translate(const xy &shift) {
|
|
|
|
ld += shift; lu += shift;
|
|
|
|
rd += shift; ru += shift;
|
|
|
|
}
|
|
|
|
void translate(const float dx, const float dy) { translate(xy(dx, dy)); }
|
2017-05-16 11:45:28 +00:00
|
|
|
void expand(const float offset) {
|
|
|
|
ld += xy(- offset, - offset);
|
|
|
|
lu += xy(- offset, offset);
|
|
|
|
rd += xy( offset, - offset);
|
|
|
|
ru += xy( offset, offset);
|
|
|
|
}
|
2017-05-17 14:45:37 +00:00
|
|
|
void expand(const float offset_x, const float offset_y) {
|
|
|
|
ld += xy(- offset_x, - offset_y);
|
|
|
|
lu += xy(- offset_x, offset_y);
|
|
|
|
rd += xy( offset_x, - offset_y);
|
|
|
|
ru += xy( offset_x, offset_y);
|
|
|
|
}
|
2017-05-16 11:45:28 +00:00
|
|
|
xy ld; // left down
|
|
|
|
xy lu; // left upper
|
|
|
|
xy rd; // right lower
|
2018-02-21 12:07:32 +00:00
|
|
|
xy ru; // right upper
|
2017-05-16 11:45:28 +00:00
|
|
|
};
|
|
|
|
|
2017-12-21 12:28:26 +00:00
|
|
|
|
|
|
|
// 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;
|
2018-03-06 18:14:12 +00:00
|
|
|
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} {}
|
2017-12-21 12:28:26 +00:00
|
|
|
};
|
|
|
|
float z; // z position of the layer
|
|
|
|
float height; // layer height
|
|
|
|
float depth; // depth of the layer based on all layers above
|
2018-02-21 12:07:32 +00:00
|
|
|
float extra_spacing;
|
2017-12-21 12:28:26 +00:00
|
|
|
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)
|
2018-02-21 12:07:32 +00:00
|
|
|
: z{z_par}, height{layer_height_par}, depth{0}, extra_spacing{1.f} {}
|
2017-12-21 12:28:26 +00:00
|
|
|
};
|
|
|
|
|
2018-02-22 10:03:29 +00:00
|
|
|
std::vector<WipeTowerInfo> m_plan; // Stores information about all layers and toolchanges for the future wipe tower (filled by plan_toolchange(...))
|
2018-03-07 10:44:47 +00:00
|
|
|
std::vector<WipeTowerInfo>::iterator m_layer_info = m_plan.end();
|
2017-12-21 12:28:26 +00:00
|
|
|
|
|
|
|
|
2017-05-16 11:45:28 +00:00
|
|
|
// Returns gcode for wipe tower brim
|
2017-12-21 12:28:26 +00:00
|
|
|
// sideOnly -- set to false -- experimental, draw brim on sides of wipe tower
|
2017-05-16 11:45:28 +00:00
|
|
|
// offset -- set to 0 -- experimental, offset to replace brim in front / rear of wipe tower
|
2018-03-08 15:44:52 +00:00
|
|
|
ToolChangeResult toolchange_Brim(bool sideOnly = false, float y_offset = 0.f);
|
2017-05-16 11:45:28 +00:00
|
|
|
|
|
|
|
void toolchange_Unload(
|
|
|
|
PrusaMultiMaterial::Writer &writer,
|
|
|
|
const box_coordinates &cleaning_box,
|
2017-05-17 14:45:37 +00:00
|
|
|
const material_type current_material,
|
|
|
|
const int new_temperature);
|
2017-05-16 11:45:28 +00:00
|
|
|
|
|
|
|
void toolchange_Change(
|
|
|
|
PrusaMultiMaterial::Writer &writer,
|
2017-09-01 15:30:18 +00:00
|
|
|
const unsigned int new_tool,
|
2017-05-16 11:45:28 +00:00
|
|
|
material_type new_material);
|
|
|
|
|
|
|
|
void toolchange_Load(
|
|
|
|
PrusaMultiMaterial::Writer &writer,
|
|
|
|
const box_coordinates &cleaning_box);
|
|
|
|
|
|
|
|
void toolchange_Wipe(
|
|
|
|
PrusaMultiMaterial::Writer &writer,
|
2017-09-12 13:55:38 +00:00
|
|
|
const box_coordinates &cleaning_box,
|
2018-02-21 12:07:32 +00:00
|
|
|
float wipe_volume);
|
2017-05-16 11:45:28 +00:00
|
|
|
};
|
|
|
|
|
2018-02-28 15:04:56 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2017-05-16 11:45:28 +00:00
|
|
|
}; // namespace Slic3r
|
|
|
|
|
|
|
|
#endif /* WipeTowerPrusaMM_hpp_ */
|