skirt brim

supermerill/SuperSlicer#795

also little fix: now preview shows object skirt & brim.
This commit is contained in:
supermerill 2021-08-21 19:11:32 +02:00
parent 43a7d347be
commit 1c3ad9de01
10 changed files with 92 additions and 28 deletions

View File

@ -177,6 +177,7 @@ group:Skirt
setting:skirt_distance
setting:skirt_height
setting:draft_shield
setting:skirt_brim
setting:min_skirt_length
group:Brim
setting:brim_width

View File

@ -833,6 +833,8 @@ namespace DoExport {
}
if (compute_min_mm3_per_mm.is_compatible({ erSkirt })) {
mm3_per_mm.push_back(compute_min_mm3_per_mm.reset_use_get(print.skirt()));
if(print.skirt_first_layer())
mm3_per_mm.push_back(compute_min_mm3_per_mm.reset_use_get(*print.skirt_first_layer()));
mm3_per_mm.push_back(compute_min_mm3_per_mm.reset_use_get(print.brim()));
}
// filter out 0-width segments
@ -2082,7 +2084,14 @@ namespace Skirt {
// not at the print_z of the interlaced support material layers.
std::map<uint16_t, std::pair<size_t, size_t>> skirt_loops_per_extruder_out;
if (skirt_done.empty() && print.has_skirt() && ! print.skirt().entities.empty()) {
skirt_loops_per_extruder_all_printing(print, layer_tools, skirt_loops_per_extruder_out);
if (print.skirt_first_layer()) {
size_t n_loops = print.skirt_first_layer()->entities.size();
size_t n_tools = layer_tools.extruders.size();
size_t lines_per_extruder = (n_loops + n_tools - 1) / n_tools;
for (size_t i = 0; i < n_loops; i += lines_per_extruder)
skirt_loops_per_extruder_out[layer_tools.extruders[i / lines_per_extruder]] = std::pair<size_t, size_t>(i, std::min(i + lines_per_extruder, n_loops));
} else
skirt_loops_per_extruder_all_printing(print, layer_tools, skirt_loops_per_extruder_out);
skirt_done.emplace_back(layer_tools.print_z);
}
return skirt_loops_per_extruder_out;
@ -2443,9 +2452,10 @@ void GCode::process_layer(
Flow layer_skirt_flow(print.skirt_flow(extruder_id));
layer_skirt_flow.height = float(m_skirt_done.back() - (m_skirt_done.size() == 1 ? 0. : m_skirt_done[m_skirt_done.size() - 2]));
double mm3_per_mm = layer_skirt_flow.mm3_per_mm();
const ExtrusionEntityCollection& coll = first_layer && print.skirt_first_layer() ? *print.skirt_first_layer() : print.skirt();
for (size_t i = loops.first; i < loops.second; ++i) {
// Adjust flow according to this layer's layer height.
ExtrusionLoop loop = *dynamic_cast<const ExtrusionLoop*>(print.skirt().entities[i]);
ExtrusionLoop loop = *dynamic_cast<const ExtrusionLoop*>(coll.entities[i]);
for (ExtrusionPath &path : loop.paths) {
assert(layer_skirt_flow.height == layer_skirt_flow.height);
assert(mm3_per_mm == mm3_per_mm);
@ -2475,6 +2485,7 @@ void GCode::process_layer(
m_avoid_crossing_perimeters.disable_once();
}
//extrude object-only skirt
//TODO: use it also for wiping like the other one (as they are exlusiev)
if (single_object_instance_idx != size_t(-1) && !layers.front().object()->skirt().empty()
&& extruder_id == layer_tools.extruders.front()) {
//if first layer, ask for a bigger lift for travel to object, to be on the safe side
@ -2483,8 +2494,12 @@ void GCode::process_layer(
const PrintObject *print_object = layers.front().object();
this->set_origin(unscale(print_object->instances()[single_object_instance_idx].shift));
if (this->m_layer != nullptr && (this->m_layer->id() < m_config.skirt_height || print.has_infinite_skirt() )) {
for (const ExtrusionEntity *ee : print_object->skirt().entities)
gcode += this->extrude_entity(*ee, "", m_config.support_material_speed.value);
if(first_layer && print.skirt_first_layer())
for (const ExtrusionEntity* ee : print_object->skirt_first_layer()->entities)
gcode += this->extrude_entity(*ee, "", m_config.support_material_speed.value);
else
for (const ExtrusionEntity *ee : print_object->skirt().entities)
gcode += this->extrude_entity(*ee, "", m_config.support_material_speed.value);
}
}
//extrude object-only brim

View File

@ -528,6 +528,7 @@ const std::vector<std::string>& Preset::print_options()
"travel_acceleration",
// skirt
"skirts", "skirt_distance", "skirt_height",
"skirt_brim",
"skirt_extrusion_width",
"min_skirt_length",
"draft_shield",

View File

@ -200,6 +200,7 @@ bool Print::invalidate_state_by_config_options(const std::vector<t_config_option
opt_key == "skirts"
|| opt_key == "skirt_height"
|| opt_key == "draft_shield"
|| opt_key == "skirt_brim"
|| opt_key == "skirt_distance"
|| opt_key == "min_skirt_length"
|| opt_key == "complete_objects_one_skirt"
@ -1641,7 +1642,7 @@ BoundingBox Print::total_bounding_box() const
extra = std::max(extra, m_config.brim_width.value + brim_flow.width/2);
}
if (this->has_skirt()) {
int skirts = m_config.skirts.value;
int skirts = m_config.skirts.value + m_config.skirt_brim.value;
if (skirts == 0 && this->has_infinite_skirt()) skirts = 1;
Flow skirt_flow = this->skirt_flow();
extra = std::max(
@ -1748,11 +1749,13 @@ void Print::process()
}
if (this->set_started(psSkirt)) {
m_skirt.clear();
m_skirt_first_layer.reset();
m_skirt_convex_hull.clear();
m_first_layer_convex_hull.points.clear();
for (PrintObject *obj : m_objects) {
obj->m_skirt.clear();
obj->m_skirt_first_layer.reset();
}
if (this->has_skirt()) {
this->set_status(88, L("Generating skirt"));
@ -1762,11 +1765,11 @@ void Print::process()
const std::vector<PrintInstance> copies{ obj->instances() };
obj->m_instances.clear();
obj->m_instances.emplace_back();
this->_make_skirt({ obj }, obj->m_skirt);
this->_make_skirt({ obj }, obj->m_skirt, obj->m_skirt_first_layer);
obj->m_instances = copies;
}
} else {
this->_make_skirt(m_objects, m_skirt);
this->_make_skirt(m_objects, m_skirt, m_skirt_first_layer);
}
}
this->set_done(psSkirt);
@ -1888,7 +1891,7 @@ std::string Print::export_gcode(const std::string& path_template, GCodeProcessor
return path.c_str();
}
void Print::_make_skirt(const PrintObjectPtrs &objects, ExtrusionEntityCollection &out)
void Print::_make_skirt(const PrintObjectPtrs &objects, ExtrusionEntityCollection &out, std::optional<ExtrusionEntityCollection>& out_first_layer)
{
// First off we need to decide how tall the skirt must be.
// The skirt_height option from config is expressed in layers, but our
@ -1973,9 +1976,11 @@ void Print::_make_skirt(const PrintObjectPtrs &objects, ExtrusionEntityCollectio
// Number of skirt loops per skirt layer.
size_t n_skirts = m_config.skirts.value;
size_t n_skirts_first_layer = n_skirts + m_config.skirt_brim.value;
if (this->has_infinite_skirt() && n_skirts == 0)
n_skirts = 1;
if (m_config.skirt_brim.value > 0)
out_first_layer.emplace();
// Initial offset of the brim inner edge from the object (possible with a support & raft).
// The skirt will touch the brim if the brim is extruded.
auto distance = float(scale_(m_config.skirt_distance.value) - this->skirt_flow(extruders[extruders.size()-1]).spacing()/2.);
@ -1986,7 +1991,8 @@ void Print::_make_skirt(const PrintObjectPtrs &objects, ExtrusionEntityCollectio
// Draw outlines from outside to inside.
// Loop while we have less skirts than required or any extruder hasn't reached the min length if any.
std::vector<coordf_t> extruded_length(extruders.size(), 0.);
for (size_t i = n_skirts, extruder_idx = 0, nb_skirts = 1; i > 0; -- i) {
for (size_t i = std::max(n_skirts, n_skirts_first_layer), extruder_idx = 0, nb_skirts = 1; i > 0; -- i) {
bool first_layer_only = i <= (n_skirts_first_layer - n_skirts);
Flow flow = this->skirt_flow(extruders[extruders.size() - (1+ extruder_idx)]);
float spacing = flow.spacing();
double mm3_per_mm = flow.mm3_per_mm();
@ -2016,8 +2022,11 @@ void Print::_make_skirt(const PrintObjectPtrs &objects, ExtrusionEntityCollectio
eloop.paths.back().polyline = loop.split_at_first_point();
//we make it clowkwise, but as it will be reversed, it will be ccw
eloop.make_clockwise();
out.append(eloop);
if (m_config.min_skirt_length.value > 0) {
if(!first_layer_only)
out.append(eloop);
if(out_first_layer)
out_first_layer->append(eloop);
if (m_config.min_skirt_length.value > 0 && !first_layer_only) {
// The skirt length is limited. Sum the total amount of filament length extruded, in mm.
extruded_length[extruder_idx] += unscale<double>(loop.length()) * extruders_e_per_mm[extruder_idx];
if (extruded_length[extruder_idx] < m_config.min_skirt_length.value) {
@ -2043,6 +2052,8 @@ void Print::_make_skirt(const PrintObjectPtrs &objects, ExtrusionEntityCollectio
}
// Brims were generated inside out, reverse to print the outmost contour first.
out.reverse();
if (out_first_layer)
out_first_layer->reverse();
// Remember the outer edge of the last skirt line extruded as m_skirt_convex_hull.
for (Polygon &poly : offset(convex_hull, distance + 0.5f * float(this->skirt_flow(extruders[extruders.size() - 1]).scaled_spacing()), ClipperLib::jtRound, float(scale_(0.1))))

View File

@ -202,6 +202,7 @@ public:
void project_and_append_custom_facets(bool seam, EnforcerBlockerType type, std::vector<ExPolygons>& expolys) const;
/// skirts if done per copy and not per platter
const std::optional<ExtrusionEntityCollection>& skirt_first_layer() const { return m_skirt_first_layer; }
const ExtrusionEntityCollection& skirt() const { return m_skirt; }
const ExtrusionEntityCollection& brim() const { return m_brim; }
@ -271,6 +272,7 @@ private:
// Ordered collections of extrusion paths to build skirt loops and brim.
// have to be duplicated per copy
std::optional<ExtrusionEntityCollection> m_skirt_first_layer;
ExtrusionEntityCollection m_skirt;
ExtrusionEntityCollection m_brim;
@ -460,6 +462,7 @@ public:
// If zero, then the print is empty and the print shall not be executed.
uint16_t num_object_instances() const;
const std::optional<ExtrusionEntityCollection>& skirt_first_layer() const { return m_skirt_first_layer; }
const ExtrusionEntityCollection& skirt() const { return m_skirt; }
const ExtrusionEntityCollection& brim() const { return m_brim; }
// Convex hull of the 1st layer extrusions, for bed leveling and placing the initial purge line.
@ -501,7 +504,7 @@ private:
t_config_option_keys &full_config_diff,
DynamicPrintConfig &filament_overrides) const;
void _make_skirt(const PrintObjectPtrs &objects, ExtrusionEntityCollection &out);
void _make_skirt(const PrintObjectPtrs &objects, ExtrusionEntityCollection &out, std::optional<ExtrusionEntityCollection> &out_first_layer);
void _make_brim(const Flow &flow, const PrintObjectPtrs &objects, ExPolygons &unbrimmable, ExtrusionEntityCollection &out);
void _make_brim_ears(const Flow &flow, const PrintObjectPtrs &objects, ExPolygons &unbrimmable, ExtrusionEntityCollection &out);
void _make_brim_interior(const Flow &flow, const PrintObjectPtrs &objects, ExPolygons &unbrimmable, ExtrusionEntityCollection &out);
@ -525,6 +528,7 @@ private:
PrintRegionPtrs m_regions;
// Ordered collections of extrusion paths to build skirt loops and brim.
std::optional<ExtrusionEntityCollection> m_skirt_first_layer;
ExtrusionEntityCollection m_skirt;
ExtrusionEntityCollection m_brim;
// Convex hull of the 1st layer extrusions.

View File

@ -674,6 +674,13 @@ void PrintConfigDef::init_fff_params()
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionBool(true));
def = this->add("draft_shield", coBool);
def->label = L("Draft shield");
def->tooltip = L("If enabled, the skirt will be as tall as a highest printed object. "
"This is useful to protect an ABS or ASA print from warping and detaching from print bed due to wind draft.");
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionBool(false));
def = this->add("duplicate_distance", coFloat);
def->label = L("Distance between objects");
def->category = OptionCategory::output;
@ -3272,6 +3279,14 @@ void PrintConfigDef::init_fff_params()
def->set_default_value(new ConfigOptionFloat(30);
def->set_default_value(new ConfigOptionFloat(30));
#endif
def = this->add("skirt_brim", coInt);
def->label = L("Brim");
def->full_label = L("Skirt brim");
def->category = OptionCategory::skirtBrim;
def->tooltip = L("Extra skirt lines on the first layer.");
def->sidetext = L("lines");
def->mode = comExpert;
def->set_default_value(new ConfigOptionInt(0));
def = this->add("skirt_distance", coFloat);
def->label = L("Distance from object");
@ -3287,7 +3302,7 @@ void PrintConfigDef::init_fff_params()
def->label = L("Skirt height");
def->category = OptionCategory::skirtBrim;
def->tooltip = L("Height of skirt expressed in layers. Set this to a tall value to use skirt "
"as a shield against drafts.");
"as a shield against drafts.");
def->sidetext = L("layers");
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionInt(1));
@ -3306,13 +3321,6 @@ void PrintConfigDef::init_fff_params()
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloatOrPercent(0, false));
def = this->add("draft_shield", coBool);
def->label = L("Draft shield");
def->tooltip = L("If enabled, the skirt will be as tall as a highest printed object. "
"This is useful to protect an ABS or ASA print from warping and detaching from print bed due to wind draft.");
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionBool(false));
def = this->add("skirts", coInt);
def->label = L("Loops (minimum)");
def->full_label = L("Skirt Loops");
@ -5530,6 +5538,7 @@ void PrintConfigDef::to_prusa(t_config_option_key& opt_key, std::string& value,
"retract_lift_top",
"seam_angle_cost",
"seam_travel_cost",
"skirt_brim",
"skirt_extrusion_width",
"small_perimeter_min_length",
"small_perimeter_max_length",
@ -5754,7 +5763,10 @@ double PrintConfig::min_object_distance(const ConfigBase *config, double ref_hei
const double first_layer_height = config->get_abs_value("first_layer_height");
//add the skirt
if (config->option("skirts")->getInt() > 0 && config->option("skirt_height")->getInt() >= 1 && !config->option("complete_objects_one_skirt")->getBool()) {
int skirts = config->option("skirts")->getInt();
if (skirts > 0 && ref_height == 0)
skirts += config->option("skirt_brim")->getInt();
if (skirts > 0 && config->option("skirt_height")->getInt() >= 1 && !config->option("complete_objects_one_skirt")->getBool()) {
if (ref_height == 0) {
skirt_dist = config->option("skirt_distance")->getFloat();
Flow skirt_flow = Flow::new_from_config_width(
@ -5763,7 +5775,7 @@ double PrintConfig::min_object_distance(const ConfigBase *config, double ref_hei
(float)max_nozzle_diam,
(float)first_layer_height
);
skirt_dist += skirt_flow.width + (skirt_flow.spacing() * ((double)config->option("skirts")->getInt() - 1));
skirt_dist += skirt_flow.width + (skirt_flow.spacing() * ((double)skirts - 1));
base_dist = std::max(base_dist, skirt_dist + 1);
//set to 0 becasue it's incorporated into the base_dist, so we don't want to be added in to it again.
skirt_dist = 0;
@ -5777,7 +5789,7 @@ double PrintConfig::min_object_distance(const ConfigBase *config, double ref_hei
(float)max_nozzle_diam,
(float)first_layer_height
);
skirt_dist += skirt_flow.width + (skirt_flow.spacing() * ((double)config->option("skirts")->getInt() - 1));
skirt_dist += skirt_flow.width + (skirt_flow.spacing() * ((double)skirts - 1));
}
}
}

View File

@ -1329,6 +1329,7 @@ public:
ConfigOptionFloat resolution;
ConfigOptionFloats retract_before_travel;
ConfigOptionBools retract_layer_change;
ConfigOptionInt skirt_brim;
ConfigOptionFloat skirt_distance;
ConfigOptionInt skirt_height;
ConfigOptionFloatOrPercent skirt_extrusion_width;
@ -1426,6 +1427,7 @@ protected:
OPT_PTR(resolution);
OPT_PTR(retract_before_travel);
OPT_PTR(retract_layer_change);
OPT_PTR(skirt_brim);
OPT_PTR(skirt_distance);
OPT_PTR(skirt_extrusion_width);
OPT_PTR(skirt_height);

View File

@ -440,7 +440,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config)
bool have_skirt = config->opt_int("skirts") > 0;
toggle_field("skirt_height", have_skirt && !config->opt_bool("draft_shield"));
toggle_field("skirt_width", have_skirt);
for (auto el : { "skirt_distance", "draft_shield", "min_skirt_length" })
for (auto el : { "skirt_distance", "skirt_brim", "draft_shield", "min_skirt_length" })
toggle_field(el, have_skirt);
bool have_brim = config->opt_float("brim_width") > 0 || config->opt_float("brim_width_interior") > 0;

View File

@ -5793,9 +5793,27 @@ void GLCanvas3D::_load_print_toolpaths()
volume->print_zs.emplace_back(print_zs[i]);
volume->offsets.emplace_back(volume->indexed_vertex_array.quad_indices.size());
volume->offsets.emplace_back(volume->indexed_vertex_array.triangle_indices.size());
if (i == 0)
if (i == 0) {
//skirt & brim from print
_3DScene::extrusionentity_to_verts(print->brim(), print_zs[i], Point(0, 0), *volume);
_3DScene::extrusionentity_to_verts(print->skirt(), print_zs[i], Point(0, 0), *volume);
if(print->skirt_first_layer())
_3DScene::extrusionentity_to_verts(*print->skirt_first_layer(), print_zs[i], Point(0, 0), *volume);
//skirt & brim from objects
for (const PrintObject* print_object : print->objects()) {
if (!print_object->brim().empty())
_3DScene::extrusionentity_to_verts(print_object->brim(), print_zs[i], Point(0, 0), *volume);
if (print_object->skirt_first_layer())
_3DScene::extrusionentity_to_verts(*print_object->skirt_first_layer(), print_zs[i], Point(0, 0), *volume);
}
}
//skirts from print
if (i != 0 || !print->skirt_first_layer())
_3DScene::extrusionentity_to_verts(print->skirt(), print_zs[i], Point(0, 0), *volume);
//skirts from objects
for (const PrintObject* print_object : print->objects()) {
if ( !print_object->skirt().empty() && (i != 0 || !print_object->skirt_first_layer()))
_3DScene::extrusionentity_to_verts(print_object->skirt(), print_zs[i], Point(0, 0), *volume);
}
// Ensure that no volume grows over the limits. If the volume is too large, allocate a new one.
if (volume->indexed_vertex_array.vertices_and_normals_interleaved.size() > MAX_VERTEX_BUFFER_SIZE) {
GLVolume &vol = *volume;

View File

@ -1984,7 +1984,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
"first_layer_extrusion_width",
"perimeter_extrusion_width",
"extrusion_width",
"skirts", "skirt_distance", "skirt_height", "draft_shield",
"skirts", "skirt_brim", "skirt_distance", "skirt_height", "draft_shield",
"brim_width", "variable_layer_height", "nozzle_diameter", "single_extruder_multi_material",
"wipe_tower", "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_rotation_angle",
"wipe_tower_brim",