Merge remote-tracking branch 'remotes/remi/master' into dev

This commit is contained in:
supermerill 2020-11-06 02:29:30 +01:00
commit c3dcf9864a
26 changed files with 325 additions and 103 deletions

View File

@ -7,6 +7,7 @@ Solid infill = D732D7
Top solid infill = FF1A1A Top solid infill = FF1A1A
Ironing = FF6868 Ironing = FF6868
Bridge infill = 9999FF Bridge infill = 9999FF
Internal Bridge infill = AAAADD
Thin wall = FFC000 Thin wall = FFC000
Gap fill = FFFFFF Gap fill = FFFFFF
Skirt = 845321 Skirt = 845321

View File

@ -87,12 +87,15 @@ group:Modifying slices
setting:width$6:curve_smoothing_angle_concave setting:width$6:curve_smoothing_angle_concave
setting:label_width$6:width$6:curve_smoothing_cutoff_dist setting:label_width$6:width$6:curve_smoothing_cutoff_dist
end_line end_line
setting:hole_to_polyhole
line:XY compensation line:XY compensation
setting:width$6:xy_size_compensation setting:width$6:xy_size_compensation
setting:width$6:xy_inner_size_compensation setting:width$6:xy_inner_size_compensation
setting:width$6:first_layer_size_compensation setting:width$6:first_layer_size_compensation
end_line
line:Vertical Hole shrinking compensation
setting:hole_to_polyhole
setting:width$6:hole_size_compensation setting:width$6:hole_size_compensation
setting:width$6:hole_size_threshold
end_line end_line
group:Other group:Other
setting:clip_multipart_objects setting:clip_multipart_objects
@ -213,7 +216,9 @@ group:label_width$8:Speed for print moves
setting:width$4:support_material_interface_speed setting:width$4:support_material_interface_speed
end_line end_line
line:Bridge speed line:Bridge speed
setting:label$_:width$4:bridge_speed setting:width$4:bridge_speed
setting:width$4:bridge_speed_internal
setting:width$4:overhangs_speed
end_line end_line
line:Thin extrusions speed line:Thin extrusions speed
setting:width$4:gap_fill_speed setting:width$4:gap_fill_speed

View File

@ -279,6 +279,7 @@ std::string ExtrusionEntity::role_to_string(ExtrusionRole role)
case erTopSolidInfill : return L("Top solid infill"); case erTopSolidInfill : return L("Top solid infill");
case erIroning : return L("Ironing"); case erIroning : return L("Ironing");
case erBridgeInfill : return L("Bridge infill"); case erBridgeInfill : return L("Bridge infill");
case erInternalBridgeInfill : return L("Internal bridge infill");
case erThinWall : return L("Thin wall"); case erThinWall : return L("Thin wall");
case erGapFill : return L("Gap fill"); case erGapFill : return L("Gap fill");
case erSkirt : return L("Skirt"); case erSkirt : return L("Skirt");
@ -313,6 +314,8 @@ ExtrusionRole ExtrusionEntity::string_to_role(const std::string_view role)
return erIroning; return erIroning;
else if (role == L("Bridge infill")) else if (role == L("Bridge infill"))
return erBridgeInfill; return erBridgeInfill;
else if (role == L("Internal bridge infill"))
return erBridgeInfill;
else if (role == L("Thin wall")) else if (role == L("Thin wall"))
return erThinWall; return erThinWall;
else if (role == L("Gap fill")) else if (role == L("Gap fill"))

View File

@ -15,6 +15,41 @@ class ExtrusionEntityCollection;
class Extruder; class Extruder;
// Each ExtrusionRole value identifies a distinct set of { extruder, speed } // Each ExtrusionRole value identifies a distinct set of { extruder, speed }
/*
enum ExtrusionRoleModifier : uint16_t {
ermPerimeter = (1 << 0),
ermInfill = (2 << 1),
ermThin = (2 << 2),
ermSkirt = (2 << 3),
ermOther = (2 << 4),
ermInternal = (1 << 10),
ermExternal = (1 << 11),
ermSolid = (1 << 12),
ermBridge = (1 << 13),
ermSupport = (1 << 13)
};
enum ExtrusionRole : uint16_t {
erNone = 0,
erPerimeter = ermPerimeter | ermInternal,
erExternalPerimeter = ermPerimeter | ermExternal,
erOverhangPerimeter = ermPerimeter | ermBridge,
erInternalInfill = ermInfill | ermInternal,
erSolidInfill = ermInfill | ermSolid | ermInternal,
erTopSolidInfill = ermInfill | ermSolid | ermExternal,
erBridgeInfill = ermInfill | ermSolid | ermBridge | ermExternal,
erInternalBridgeInfill = ermInfill | ermSolid | ermBridge,
erThinWall = ermThin | ermInternal,
erGapFill = ermThin | ermExternal,
erSkirt = ermSkirt,
erSupportMaterial = ermInfill | ermSupport | ermInternal,
erSupportMaterialInterface = ermInfill | ermSupport | ermExternal,
erWipeTower = ermSkirt | ermSupport,
erMilling = ermOther | ermPerimeter,
erCustom = ermOther | ermSkirt,
// Extrusion role for a collection with multiple extrusion roles.
erMixed = ermOther
};
*/
enum ExtrusionRole : uint8_t { enum ExtrusionRole : uint8_t {
erNone, erNone,
erPerimeter, erPerimeter,
@ -25,6 +60,7 @@ enum ExtrusionRole : uint8_t {
erTopSolidInfill, erTopSolidInfill,
erIroning, erIroning,
erBridgeInfill, erBridgeInfill,
erInternalBridgeInfill,
erThinWall, erThinWall,
erGapFill, erGapFill,
erSkirt, erSkirt,
@ -37,6 +73,7 @@ enum ExtrusionRole : uint8_t {
erMixed, erMixed,
erCount erCount
}; };
// perimeter / infill / support / skirt / gapfill / wipetower / custom / mixed // perimeter / infill / support / skirt / gapfill / wipetower / custom / mixed
// side / internal / top / bottom // side / internal / top / bottom
// bridge // bridge

View File

@ -606,7 +606,7 @@ Fill::do_gap_fill(const ExPolygons &gapfill_areas, const FillParams &params, Ext
MedialAxis{ ex, params.flow.scaled_width() * 2, params.flow.scaled_width() / 5, coord_t(params.flow.height) }.build(polylines_gapfill); MedialAxis{ ex, params.flow.scaled_width() * 2, params.flow.scaled_width() / 5, coord_t(params.flow.height) }.build(polylines_gapfill);
} }
} }
if (!polylines_gapfill.empty() && params.role != erBridgeInfill) { if (!polylines_gapfill.empty() && params.role != erBridgeInfill && params.role != erInternalBridgeInfill) {
//test //test
#ifdef _DEBUG #ifdef _DEBUG
for (ThickPolyline poly : polylines_gapfill) { for (ThickPolyline poly : polylines_gapfill) {

View File

@ -158,7 +158,7 @@ protected:
ExtrusionRole getRoleFromSurfaceType(const FillParams &params, const Surface *surface) const { ExtrusionRole getRoleFromSurfaceType(const FillParams &params, const Surface *surface) const {
if (params.role == erNone || params.role == erCustom) { if (params.role == erNone || params.role == erCustom) {
return params.flow.bridge ? return params.flow.bridge ?
erBridgeInfill : (surface->has_pos_bottom() ? erBridgeInfill :erInternalBridgeInfill) :
(surface->has_fill_solid() ? (surface->has_fill_solid() ?
((surface->has_pos_top()) ? erTopSolidInfill : erSolidInfill) : ((surface->has_pos_top()) ? erTopSolidInfill : erSolidInfill) :
erInternalInfill); erInternalInfill);

View File

@ -153,7 +153,7 @@ FillConcentricWGapFill::fill_surface_extrusion(
MedialAxis{ ex, coord_t(max), coord_t(min), coord_t(params.flow.height) }.build(polylines); MedialAxis{ ex, coord_t(max), coord_t(min), coord_t(params.flow.height) }.build(polylines);
} }
} }
if (!polylines.empty() && good_role != erBridgeInfill) { if (!polylines.empty() && good_role != erBridgeInfill && good_role != erInternalBridgeInfill) {
ExtrusionEntityCollection gap_fill = thin_variable_width(polylines, erGapFill, params.flow); ExtrusionEntityCollection gap_fill = thin_variable_width(polylines, erGapFill, params.flow);
//set role if needed //set role if needed
if (good_role != erSolidInfill) { if (good_role != erSolidInfill) {

View File

@ -162,7 +162,7 @@ struct SegmentIntersection
// Vertical link, up. // Vertical link, up.
Up, Up,
// Vertical link, down. // Vertical link, down.
Down, Down,
// Phony intersection point has no link. // Phony intersection point has no link.
Phony, Phony,
}; };
@ -2243,7 +2243,7 @@ static std::vector<MonotonousRegionLink> chain_monotonous_regions(
// After how many rounds without an improvement to exit? // After how many rounds without an improvement to exit?
constexpr int num_rounds_no_change_exit = 8; constexpr int num_rounds_no_change_exit = 8;
// With how many ants each of the run will be performed? // With how many ants each of the run will be performed?
const int num_ants = std::min(int(regions.size()), 10); const int num_ants = std::min(int(regions.size()), 10);
// Base (initial) pheromone level. This value will be adjusted based on the length of the first greedy path found. // Base (initial) pheromone level. This value will be adjusted based on the length of the first greedy path found.
float pheromone_initial_deposit = 0.5f; float pheromone_initial_deposit = 0.5f;
// Evaporation rate of pheromones. // Evaporation rate of pheromones.

View File

@ -90,8 +90,15 @@ namespace Slic3r {
return ok; return ok;
} }
void AvoidCrossingPerimeters::init_external_mp(const Print& print) double get_default_acceleration(PrintConfig & config) {
{ double max = 0;
// on 2.3, check for enable/disable if(config.print_machine_envelope)
max = config.machine_max_acceleration_extruding.values.front();
return config.default_acceleration.get_abs_value(max);
}
void AvoidCrossingPerimeters::init_external_mp(const Print &print)
{
m_external_mp = Slic3r::make_unique<MotionPlanner>(union_ex(this->collect_contours_all_layers(print.objects()))); m_external_mp = Slic3r::make_unique<MotionPlanner>(union_ex(this->collect_contours_all_layers(print.objects())));
} }
@ -974,12 +981,13 @@ namespace DoExport {
if (region->config().get_abs_value("perimeter_speed") == 0 || if (region->config().get_abs_value("perimeter_speed") == 0 ||
region->config().get_abs_value("small_perimeter_speed") == 0 || region->config().get_abs_value("small_perimeter_speed") == 0 ||
region->config().get_abs_value("external_perimeter_speed") == 0 || region->config().get_abs_value("external_perimeter_speed") == 0 ||
region->config().get_abs_value("bridge_speed") == 0) region->config().get_abs_value("overhangs_speed") == 0)
mm3_per_mm.push_back(layerm->perimeters.min_mm3_per_mm()); mm3_per_mm.push_back(layerm->perimeters.min_mm3_per_mm());
if (region->config().get_abs_value("infill_speed") == 0 || if (region->config().get_abs_value("infill_speed") == 0 ||
region->config().get_abs_value("solid_infill_speed") == 0 || region->config().get_abs_value("solid_infill_speed") == 0 ||
region->config().get_abs_value("top_solid_infill_speed") == 0 || region->config().get_abs_value("top_solid_infill_speed") == 0 ||
region->config().get_abs_value("bridge_speed") == 0) region->config().get_abs_value("bridge_speed") == 0 ||
region->config().get_abs_value("bridge_speed_internal") == 0)
mm3_per_mm.push_back(layerm->fills.min_mm3_per_mm()); mm3_per_mm.push_back(layerm->fills.min_mm3_per_mm());
} }
} }
@ -2918,7 +2926,9 @@ std::string GCode::preamble()
before the first layer change will raise the extruder from the correct before the first layer change will raise the extruder from the correct
initial Z instead of 0. */ initial Z instead of 0. */
m_writer.travel_to_z(m_config.z_offset.value); m_writer.travel_to_z(m_config.z_offset.value);
//as this phony thing skip the acceleration writing, they have to be reset after that for real initialisation at the next move/extrusion
m_writer.set_acceleration(0);
return gcode; return gcode;
} }
@ -3144,7 +3154,7 @@ std::string GCode::extrude_loop_vase(const ExtrusionLoop &original_loop, const s
} }
// reset acceleration // reset acceleration
m_writer.set_acceleration((unsigned int)(m_config.default_acceleration.value + 0.5)); m_writer.set_acceleration((unsigned int)floor(get_default_acceleration(m_config) + 0.5));
//don't wipe here //don't wipe here
//if (m_wipe.enable) //if (m_wipe.enable)
@ -3333,7 +3343,7 @@ std::string GCode::extrude_loop(const ExtrusionLoop &original_loop, const std::s
} }
// reset acceleration // reset acceleration
m_writer.set_acceleration((unsigned int)(m_config.default_acceleration.value + 0.5)); m_writer.set_acceleration((unsigned int)floor(get_default_acceleration(m_config) + 0.5));
if (m_wipe.enable) if (m_wipe.enable)
m_wipe.path = paths.front().polyline; // TODO: don't limit wipe to last path m_wipe.path = paths.front().polyline; // TODO: don't limit wipe to last path
@ -3431,7 +3441,7 @@ std::string GCode::extrude_multi_path(const ExtrusionMultiPath &multipath, const
m_wipe.path.reverse(); m_wipe.path.reverse();
} }
// reset acceleration // reset acceleration
m_writer.set_acceleration((unsigned int)floor(m_config.default_acceleration.value + 0.5)); m_writer.set_acceleration((unsigned int)floor(get_default_acceleration(m_config) + 0.5));
return gcode; return gcode;
} }
@ -3468,7 +3478,7 @@ std::string GCode::extrude_multi_path3D(const ExtrusionMultiPath3D &multipath3D,
m_wipe.path.reverse(); m_wipe.path.reverse();
} }
// reset acceleration // reset acceleration
m_writer.set_acceleration((unsigned int)floor(m_config.default_acceleration.value + 0.5)); m_writer.set_acceleration((unsigned int)floor(get_default_acceleration(m_config) + 0.5));
return gcode; return gcode;
} }
@ -3529,7 +3539,7 @@ std::string GCode::extrude_path(const ExtrusionPath &path, const std::string &de
m_wipe.path.reverse(); m_wipe.path.reverse();
} }
// reset acceleration // reset acceleration
m_writer.set_acceleration((unsigned int)floor(m_config.default_acceleration.value + 0.5)); m_writer.set_acceleration((unsigned int)floor(get_default_acceleration(m_config) + 0.5));
return gcode; return gcode;
} }
@ -3563,7 +3573,7 @@ std::string GCode::extrude_path_3D(const ExtrusionPath3D &path, const std::strin
m_wipe.path.reverse(); m_wipe.path.reverse();
} }
// reset acceleration // reset acceleration
m_writer.set_acceleration((unsigned int)floor(m_config.default_acceleration.value + 0.5)); m_writer.set_acceleration((unsigned int)floor(get_default_acceleration(m_config) + 0.5));
return gcode; return gcode;
} }
@ -3882,17 +3892,15 @@ std::string GCode::_before_extrude(const ExtrusionPath &path, const std::string
// adjust acceleration // adjust acceleration
{ {
double acceleration; double acceleration = get_default_acceleration(m_config);
if (this->on_first_layer() && m_config.first_layer_acceleration.value > 0) { if (this->on_first_layer() && m_config.first_layer_acceleration.value > 0) {
acceleration = m_config.first_layer_acceleration.value; acceleration = m_config.first_layer_acceleration.get_abs_value(acceleration);
} else if (m_config.perimeter_acceleration.value > 0 && is_perimeter(path.role())) { } else if (m_config.perimeter_acceleration.value > 0 && is_perimeter(path.role())) {
acceleration = m_config.perimeter_acceleration.value; acceleration = m_config.perimeter_acceleration.get_abs_value(acceleration);
} else if (m_config.bridge_acceleration.value > 0 && is_bridge(path.role())) { } else if (m_config.bridge_acceleration.value > 0 && is_bridge(path.role())) {
acceleration = m_config.bridge_acceleration.value; acceleration = m_config.bridge_acceleration.get_abs_value(acceleration);
} else if (m_config.infill_acceleration.value > 0 && is_infill(path.role())) { } else if (m_config.infill_acceleration.value > 0 && is_infill(path.role())) {
acceleration = m_config.infill_acceleration.value; acceleration = m_config.infill_acceleration.get_abs_value(acceleration);
} else {
acceleration = m_config.default_acceleration.value;
} }
//travel acceleration should be already set at startup via special gcode, and so it's automatically used by G0. //travel acceleration should be already set at startup via special gcode, and so it's automatically used by G0.
m_writer.set_acceleration((unsigned int)floor(acceleration + 0.5)); m_writer.set_acceleration((unsigned int)floor(acceleration + 0.5));
@ -3908,8 +3916,12 @@ std::string GCode::_before_extrude(const ExtrusionPath &path, const std::string
speed = m_config.get_abs_value("perimeter_speed"); speed = m_config.get_abs_value("perimeter_speed");
} else if (path.role() == erExternalPerimeter) { } else if (path.role() == erExternalPerimeter) {
speed = m_config.get_abs_value("external_perimeter_speed"); speed = m_config.get_abs_value("external_perimeter_speed");
} else if (path.role() == erOverhangPerimeter || path.role() == erBridgeInfill) { } else if (path.role() == erBridgeInfill) {
speed = m_config.get_abs_value("bridge_speed"); speed = m_config.get_abs_value("bridge_speed");
} else if (path.role() == erInternalBridgeInfill) {
speed = m_config.get_abs_value("bridge_speed_internal");
} else if (path.role() == erOverhangPerimeter) {
speed = m_config.get_abs_value("overhangs_speed");
} else if (path.role() == erInternalInfill) { } else if (path.role() == erInternalInfill) {
speed = m_config.get_abs_value("infill_speed"); speed = m_config.get_abs_value("infill_speed");
} else if (path.role() == erSolidInfill) { } else if (path.role() == erSolidInfill) {
@ -3930,7 +3942,7 @@ std::string GCode::_before_extrude(const ExtrusionPath &path, const std::string
throw Slic3r::InvalidArgument("Invalid speed"); throw Slic3r::InvalidArgument("Invalid speed");
} }
//don't modify bridge speed //don't modify bridge speed
if (factor < 1 && !(path.role() == erOverhangPerimeter || path.role() == erBridgeInfill)) { if (factor < 1 && !(path.role() == erOverhangPerimeter || path.role() == erBridgeInfill || path.role() == erInternalBridgeInfill)) {
float small_speed = m_config.small_perimeter_speed.get_abs_value(m_config.perimeter_speed); float small_speed = m_config.small_perimeter_speed.get_abs_value(m_config.perimeter_speed);
//apply factor between feature speed and small speed //apply factor between feature speed and small speed
speed = speed * factor + (1.f - factor) * small_speed; speed = speed * factor + (1.f - factor) * small_speed;
@ -3970,6 +3982,7 @@ std::string GCode::_before_extrude(const ExtrusionPath &path, const std::string
if (path.role() != m_last_extrusion_role && !m_config.feature_gcode.value.empty()) { if (path.role() != m_last_extrusion_role && !m_config.feature_gcode.value.empty()) {
DynamicConfig config; DynamicConfig config;
config.set_key_value("extrusion_role", new ConfigOptionString(extrusion_role_to_string_for_parser(path.role()))); config.set_key_value("extrusion_role", new ConfigOptionString(extrusion_role_to_string_for_parser(path.role())));
config.set_key_value("last_extrusion_role", new ConfigOptionString(extrusion_role_to_string_for_parser(m_last_extrusion_role)));
config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index + 1)); config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index + 1));
config.set_key_value("layer_z", new ConfigOptionFloat(m_config.z_offset.value)); config.set_key_value("layer_z", new ConfigOptionFloat(m_config.z_offset.value));
gcode += this->placeholder_parser_process("feature_gcode", gcode += this->placeholder_parser_process("feature_gcode",
@ -4444,6 +4457,7 @@ GCode::extrusion_role_to_string_for_parser(const ExtrusionRole & role) {
case erTopSolidInfill: case erTopSolidInfill:
return "TopSolidInfill"; return "TopSolidInfill";
case erBridgeInfill: case erBridgeInfill:
case erInternalBridgeInfill:
return "BridgeInfill"; return "BridgeInfill";
case erThinWall: case erThinWall:
return "ThinWall"; return "ThinWall";

View File

@ -62,6 +62,8 @@ void PressureEqualizer::reset()
// Don't regulate the pressure in infill. // Don't regulate the pressure in infill.
m_max_volumetric_extrusion_rate_slopes[erBridgeInfill].negative = 0; m_max_volumetric_extrusion_rate_slopes[erBridgeInfill].negative = 0;
m_max_volumetric_extrusion_rate_slopes[erBridgeInfill].positive = 0; m_max_volumetric_extrusion_rate_slopes[erBridgeInfill].positive = 0;
m_max_volumetric_extrusion_rate_slopes[erInternalBridgeInfill].negative = 0;
m_max_volumetric_extrusion_rate_slopes[erInternalBridgeInfill].positive = 0;
// Don't regulate the pressure in gap fill. // Don't regulate the pressure in gap fill.
m_max_volumetric_extrusion_rate_slopes[erGapFill].negative = 0; m_max_volumetric_extrusion_rate_slopes[erGapFill].negative = 0;
m_max_volumetric_extrusion_rate_slopes[erGapFill].positive = 0; m_max_volumetric_extrusion_rate_slopes[erGapFill].positive = 0;

View File

@ -138,6 +138,7 @@ const Color GCodePreviewData::Extrusion::Default_Extrusion_Role_Colors[erCount]
// Color(1.0f, 0.7f, 0.61f, 1.0f), // erIroning // Color(1.0f, 0.7f, 0.61f, 1.0f), // erIroning
Color(1.0f, 0.55f, 0.41f, 1.0f), // erIroning Color(1.0f, 0.55f, 0.41f, 1.0f), // erIroning
Color(0.5f, 0.5f, 0.5f, 1.0f), // erBridgeInfill Color(0.5f, 0.5f, 0.5f, 1.0f), // erBridgeInfill
Color(0.4f, 0.4f, 0.4f, 1.0f), // erInternalBridgeInfill
Color(0.0f, 1.0f, 0.4f, 1.0f), // erThinWall Color(0.0f, 1.0f, 0.4f, 1.0f), // erThinWall
Color(1.0f, 1.0f, 1.0f, 1.0f), // erGapFill Color(1.0f, 1.0f, 1.0f, 1.0f), // erGapFill
Color(0.5f, 0.0f, 0.0f, 1.0f), // erSkirt Color(0.5f, 0.0f, 0.0f, 1.0f), // erSkirt

View File

@ -97,14 +97,14 @@ void PerimeterGenerator::process()
coord_t ext_min_spacing = (coord_t)( ext_perimeter_spacing2 * (1 - 0.05/*INSET_OVERLAP_TOLERANCE*/) ); coord_t ext_min_spacing = (coord_t)( ext_perimeter_spacing2 * (1 - 0.05/*INSET_OVERLAP_TOLERANCE*/) );
// prepare grown lower layer slices for overhang detection // prepare grown lower layer slices for overhang detection
if (this->lower_slices != NULL && this->config->overhangs_width > 0) { if (this->lower_slices != NULL && this->config->overhangs_width.value > 0) {
// We consider overhang any part where the entire nozzle diameter is not supported by the // We consider overhang any part where the entire nozzle diameter is not supported by the
// lower layer, so we take lower slices and offset them by overhangs_width of the nozzle diameter used // lower layer, so we take lower slices and offset them by overhangs_width of the nozzle diameter used
// in the current layer // in the current layer
double offset_val = double(scale_(config->overhangs_width.get_abs_value(nozzle_diameter))) - (float)(ext_perimeter_width / 2); double offset_val = double(scale_(config->overhangs_width.get_abs_value(nozzle_diameter))) - (float)(ext_perimeter_width / 2);
this->_lower_slices_bridge_flow = offset(*this->lower_slices, offset_val); this->_lower_slices_bridge_flow = offset(*this->lower_slices, offset_val);
} }
if (this->lower_slices != NULL && this->config->overhangs_width_speed > 0) { if (this->lower_slices != NULL && this->config->overhangs_width_speed.value > 0) {
double offset_val = double(scale_(config->overhangs_width_speed.get_abs_value(nozzle_diameter))) - (float)(ext_perimeter_width / 2); double offset_val = double(scale_(config->overhangs_width_speed.get_abs_value(nozzle_diameter))) - (float)(ext_perimeter_width / 2);
this->_lower_slices_bridge_speed = offset(*this->lower_slices, offset_val); this->_lower_slices_bridge_speed = offset(*this->lower_slices, offset_val);
} }
@ -950,11 +950,19 @@ template<typename LINE>
ExtrusionPaths PerimeterGenerator::create_overhangs(LINE loop_polygons, ExtrusionRole role, bool is_external) const { ExtrusionPaths PerimeterGenerator::create_overhangs(LINE loop_polygons, ExtrusionRole role, bool is_external) const {
ExtrusionPaths paths; ExtrusionPaths paths;
double nozzle_diameter = this->print_config->nozzle_diameter.get_at(this->config->perimeter_extruder - 1); double nozzle_diameter = this->print_config->nozzle_diameter.get_at(this->config->perimeter_extruder - 1);
if (this->config->overhangs_width.get_abs_value(nozzle_diameter) > this->config->overhangs_width_speed.get_abs_value(nozzle_diameter)) { if (this->config->overhangs_width.get_abs_value(nozzle_diameter) ==0 && 0== this->config->overhangs_width_speed.get_abs_value(nozzle_diameter)) {
//error
return paths;
} else if (this->config->overhangs_width.get_abs_value(nozzle_diameter) > this->config->overhangs_width_speed.get_abs_value(nozzle_diameter)) {
//set the fan & speed before the flow
// get non-overhang paths by intersecting this loop with the grown lower slices // get non-overhang paths by intersecting this loop with the grown lower slices
extrusion_paths_append( extrusion_paths_append(
paths, paths,
intersection_pl(loop_polygons, this->_lower_slices_bridge_speed), (this->config->overhangs_width_speed.value > 0 ?
intersection_pl(loop_polygons, this->_lower_slices_bridge_speed) :
intersection_pl(loop_polygons, this->_lower_slices_bridge_flow)),
role, role,
is_external ? this->_ext_mm3_per_mm : this->_mm3_per_mm, is_external ? this->_ext_mm3_per_mm : this->_mm3_per_mm,
is_external ? this->ext_perimeter_flow.width : this->perimeter_flow.width, is_external ? this->ext_perimeter_flow.width : this->perimeter_flow.width,
@ -962,30 +970,38 @@ ExtrusionPaths PerimeterGenerator::create_overhangs(LINE loop_polygons, Extrusio
// get overhang paths by checking what parts of this loop fall // get overhang paths by checking what parts of this loop fall
// outside the grown lower slices // outside the grown lower slices
Polylines poly_speed = diff_pl(loop_polygons, this->_lower_slices_bridge_speed); Polylines poly_speed =
(this->config->overhangs_width_speed.value > 0 ?
diff_pl(loop_polygons, this->_lower_slices_bridge_speed):
Polylines{});
if(this->config->overhangs_width_speed.value > 0)
extrusion_paths_append(
paths,
intersection_pl(poly_speed, this->_lower_slices_bridge_flow),
erOverhangPerimeter,
is_external ? this->_ext_mm3_per_mm : this->_mm3_per_mm,
is_external ? this->ext_perimeter_flow.width : this->perimeter_flow.width,
(float)this->layer->height);
extrusion_paths_append( extrusion_paths_append(
paths, paths,
intersection_pl(poly_speed, this->_lower_slices_bridge_flow), (this->config->overhangs_width_speed.value > 0 ?
erOverhangPerimeter, diff_pl(poly_speed, this->_lower_slices_bridge_flow):
is_external ? this->_ext_mm3_per_mm : this->_mm3_per_mm, diff_pl(loop_polygons, this->_lower_slices_bridge_flow)),
is_external ? this->ext_perimeter_flow.width : this->perimeter_flow.width,
(float)this->layer->height);
extrusion_paths_append(
paths,
diff_pl(poly_speed, this->_lower_slices_bridge_flow),
erOverhangPerimeter, erOverhangPerimeter,
this->_mm3_per_mm_overhang, this->_mm3_per_mm_overhang,
this->overhang_flow.width, this->overhang_flow.width,
this->overhang_flow.height); this->overhang_flow.height);
} else { } else {
//can't set flow without fan & speed
// get non-overhang paths by intersecting this loop with the grown lower slices // get non-overhang paths by intersecting this loop with the grown lower slices
extrusion_paths_append( extrusion_paths_append(
paths, paths,
intersection_pl(loop_polygons, this->_lower_slices_bridge_flow), (this->config->overhangs_width.value > 0 ?
intersection_pl(loop_polygons, this->_lower_slices_bridge_flow) :
intersection_pl(loop_polygons, this->_lower_slices_bridge_speed) ),
role, role,
is_external ? this->_ext_mm3_per_mm : this->_mm3_per_mm, is_external ? this->_ext_mm3_per_mm : this->_mm3_per_mm,
is_external ? this->ext_perimeter_flow.width : this->perimeter_flow.width, is_external ? this->ext_perimeter_flow.width : this->perimeter_flow.width,
@ -993,13 +1009,23 @@ ExtrusionPaths PerimeterGenerator::create_overhangs(LINE loop_polygons, Extrusio
// get overhang paths by checking what parts of this loop fall // get overhang paths by checking what parts of this loop fall
// outside the grown lower slices // outside the grown lower slices
extrusion_paths_append( if (this->config->overhangs_width.value > 0) {
paths, extrusion_paths_append(
diff_pl(loop_polygons, this->_lower_slices_bridge_flow), paths,
erOverhangPerimeter, diff_pl(loop_polygons, this->_lower_slices_bridge_flow),
this->_mm3_per_mm_overhang, erOverhangPerimeter,
this->overhang_flow.width, this->_mm3_per_mm_overhang,
this->overhang_flow.height); this->overhang_flow.width,
this->overhang_flow.height);
} else {
extrusion_paths_append(
paths,
diff_pl(loop_polygons, this->_lower_slices_bridge_speed),
erOverhangPerimeter,
is_external ? this->_ext_mm3_per_mm : this->_mm3_per_mm,
is_external ? this->ext_perimeter_flow.width : this->perimeter_flow.width,
(float)this->layer->height);
}
} }
// reapply the nearest point search for starting point // reapply the nearest point search for starting point
@ -1038,7 +1064,7 @@ ExtrusionEntityCollection PerimeterGenerator::_traverse_loops(
// detect overhanging/bridging perimeters // detect overhanging/bridging perimeters
ExtrusionPaths paths; ExtrusionPaths paths;
if ( this->config->overhangs_width_speed > 0 && this->layer->id() > 0 if ( this->config->overhangs_width_speed.value > 0 && this->layer->id() > 0
&& !(this->object_config->support_material && this->object_config->support_material_contact_distance_type.value == zdNone)) { && !(this->object_config->support_material && this->object_config->support_material_contact_distance_type.value == zdNone)) {
paths = this->create_overhangs(loop.polygon, role, is_external); paths = this->create_overhangs(loop.polygon, role, is_external);
} else { } else {
@ -1468,7 +1494,7 @@ PerimeterGenerator::_extrude_and_cut_loop(const PerimeterGeneratorLoop &loop, co
} }
// detect overhanging/bridging perimeters // detect overhanging/bridging perimeters
if ( this->config->overhangs_width_speed > 0 && this->layer->id() > 0 if ( this->config->overhangs_width_speed.value > 0 && this->layer->id() > 0
&& !(this->object_config->support_material && this->object_config->support_material_contact_distance_type.value == zdNone)) { && !(this->object_config->support_material && this->object_config->support_material_contact_distance_type.value == zdNone)) {
ExtrusionPaths paths = this->create_overhangs(initial_polyline, role, is_external); ExtrusionPaths paths = this->create_overhangs(initial_polyline, role, is_external);

View File

@ -443,8 +443,9 @@ const std::vector<std::string>& Preset::print_options()
"avoid_crossing_not_first_layer", "avoid_crossing_not_first_layer",
"thin_perimeters", "thin_perimeters_all", "thin_perimeters", "thin_perimeters_all",
"thin_walls", "thin_walls",
"overhangs_speed",
"overhangs_width", "overhangs_width",
"overhangs_width_speed", "overhangs_width_speed",
"overhangs_reverse", "overhangs_reverse",
"overhangs_reverse_threshold", "overhangs_reverse_threshold",
"seam_position", "seam_position",
@ -483,6 +484,7 @@ const std::vector<std::string>& Preset::print_options()
"external_perimeter_speed", "infill_speed", "solid_infill_speed", "external_perimeter_speed", "infill_speed", "solid_infill_speed",
"top_solid_infill_speed", "support_material_speed", "support_material_xy_spacing", "support_material_interface_speed", "top_solid_infill_speed", "support_material_speed", "support_material_xy_spacing", "support_material_interface_speed",
"bridge_speed", "bridge_speed",
"bridge_speed_internal",
"gap_fill", "gap_fill",
"gap_fill_min_area", "gap_fill_min_area",
"gap_fill_overlap", "gap_fill_overlap",
@ -527,7 +529,8 @@ const std::vector<std::string>& Preset::print_options()
"first_layer_size_compensation", "first_layer_size_compensation",
"xy_size_compensation", "xy_size_compensation",
"xy_inner_size_compensation", "xy_inner_size_compensation",
"hole_size_compensation", "hole_size_compensation",
"hole_size_threshold",
"hole_to_polyhole", "hole_to_polyhole",
"threads", "resolution", "threads", "resolution",
"wipe_tower", "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_rotation_angle", "wipe_tower_bridging", "wipe_tower", "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_rotation_angle", "wipe_tower_bridging",

View File

@ -284,16 +284,17 @@ void PrintConfigDef::init_fff_params()
def->min = 0; def->min = 0;
def->set_default_value(new ConfigOptionFloat(0.)); def->set_default_value(new ConfigOptionFloat(0.));
def = this->add("bridge_acceleration", coFloat); def = this->add("bridge_acceleration", coFloatOrPercent);
def->label = L("Bridge"); def->label = L("Bridge");
def->full_label = L("Bridge acceleration"); def->full_label = L("Bridge acceleration");
def->category = OptionCategory::speed; def->category = OptionCategory::speed;
def->tooltip = L("This is the acceleration your printer will use for bridges. " def->tooltip = L("This is the acceleration your printer will use for bridges."
"Set zero to disable acceleration control for bridges."); "\nCan be a % of the default acceleration"
def->sidetext = L("mm/s²"); "\nSet zero to disable acceleration control for bridges.");
def->sidetext = L("mm/s² or %");
def->min = 0; def->min = 0;
def->mode = comExpert; def->mode = comExpert;
def->set_default_value(new ConfigOptionFloat(0)); def->set_default_value(new ConfigOptionFloatOrPercent(0,false));
def = this->add("bridge_angle", coFloat); def = this->add("bridge_angle", coFloat);
def->label = L("Bridging"); def->label = L("Bridging");
@ -381,6 +382,17 @@ void PrintConfigDef::init_fff_params()
def->min = 0; def->min = 0;
def->mode = comAdvanced; def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloat(60)); def->set_default_value(new ConfigOptionFloat(60));
def = this->add("bridge_speed_internal", coFloatOrPercent);
def->label = L("Internal bridges");
def->full_label = L("Internal bridge speed");
def->category = OptionCategory::speed;
def->tooltip = L("Speed for printing the bridges that support the top layer.\nCan be a % of the bridge speed.");
def->sidetext = L("mm/s");
def->ratio_over = "bridge_speed";
def->min = 0;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloatOrPercent(150,true));
def = this->add("brim_inside_holes", coBool); def = this->add("brim_inside_holes", coBool);
def->label = L("Brim inside holes"); def->label = L("Brim inside holes");
@ -575,17 +587,18 @@ void PrintConfigDef::init_fff_params()
def->mode = comAdvanced; def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloat(5.f)); def->set_default_value(new ConfigOptionFloat(5.f));
def = this->add("default_acceleration", coFloat); def = this->add("default_acceleration", coFloatOrPercent);
def->label = L("Default"); def->label = L("Default");
def->category = OptionCategory::speed; def->category = OptionCategory::speed;
def->full_label = L("Default acceleration"); def->full_label = L("Default acceleration");
def->tooltip = L("This is the acceleration your printer will be reset to after " def->tooltip = L("This is the acceleration your printer will be reset to after "
"the role-specific acceleration values are used (perimeter/infill). " "the role-specific acceleration values are used (perimeter/infill). "
"Set zero to prevent resetting acceleration at all."); "\nYou can set it as a % of the max of the X/Y machine acceleration limit."
def->sidetext = L("mm/s²"); "\nSet zero to prevent resetting acceleration at all.");
def->sidetext = L("mm/s² or %");
def->min = 0; def->min = 0;
def->mode = comExpert; def->mode = comExpert;
def->set_default_value(new ConfigOptionFloat(0)); def->set_default_value(new ConfigOptionFloatOrPercent(0,false));
def = this->add("default_filament_profile", coStrings); def = this->add("default_filament_profile", coStrings);
def->label = L("Default filament profile"); def->label = L("Default filament profile");
@ -898,7 +911,7 @@ void PrintConfigDef::init_fff_params()
def = this->add("external_perimeters_nothole", coBool); def = this->add("external_perimeters_nothole", coBool);
def->label = L("Only for outer side"); def->label = L("Only for outer side");
def->full_label = L("ext peri first for outer side"); def->full_label = L("Ext peri first for outer side");
def->category = OptionCategory::perimeter; def->category = OptionCategory::perimeter;
def->tooltip = L("Only do the vase trick on the external side. Useful when the thikness is too low."); def->tooltip = L("Only do the vase trick on the external side. Useful when the thikness is too low.");
def->mode = comExpert; def->mode = comExpert;
@ -1624,16 +1637,17 @@ void PrintConfigDef::init_fff_params()
def->sidetext = L("%"); def->sidetext = L("%");
def->set_default_value(new ConfigOptionPercent(10)); def->set_default_value(new ConfigOptionPercent(10));
def = this->add("first_layer_acceleration", coFloat); def = this->add("first_layer_acceleration", coFloatOrPercent);
def->label = L("First layer"); def->label = L("First layer");
def->full_label = L("First layer acceleration"); def->full_label = L("First layer acceleration");
def->category = OptionCategory::speed; def->category = OptionCategory::speed;
def->tooltip = L("This is the acceleration your printer will use for first layer. Set zero " def->tooltip = L("This is the acceleration your printer will use for first layer."
"to disable acceleration control for first layer."); "\nCan be a % of the default acceleration"
def->sidetext = L("mm/s²"); "\nSet zero to disable acceleration control for first layer.");
def->sidetext = L("mm/s² or %");
def->min = 0; def->min = 0;
def->mode = comExpert; def->mode = comExpert;
def->set_default_value(new ConfigOptionFloat(0)); def->set_default_value(new ConfigOptionFloatOrPercent(0, false));
def = this->add("first_layer_bed_temperature", coInts); def = this->add("first_layer_bed_temperature", coInts);
def->label = L("First layer"); def->label = L("First layer");
@ -1821,16 +1835,17 @@ void PrintConfigDef::init_fff_params()
def->mode = comExpert; def->mode = comExpert;
def->set_default_value(new ConfigOptionBool(0)); def->set_default_value(new ConfigOptionBool(0));
def = this->add("infill_acceleration", coFloat); def = this->add("infill_acceleration", coFloatOrPercent);
def->label = L("Infill"); def->label = L("Infill");
def->full_label = L("Infill acceleration"); def->full_label = L("Infill acceleration");
def->category = OptionCategory::speed; def->category = OptionCategory::speed;
def->tooltip = L("This is the acceleration your printer will use for infill. Set zero to disable " def->tooltip = L("This is the acceleration your printer will use for infill."
"acceleration control for infill."); "\nCan be a % of the default acceleration"
def->sidetext = L("mm/s²"); "\nSet zero to disable acceleration control for infill.");
def->sidetext = L("mm/s² or %");
def->min = 0; def->min = 0;
def->mode = comExpert; def->mode = comExpert;
def->set_default_value(new ConfigOptionFloat(0)); def->set_default_value(new ConfigOptionFloatOrPercent(0,false));
def = this->add("infill_every_layers", coInt); def = this->add("infill_every_layers", coInt);
def->label = L("Combine infill every"); def->label = L("Combine infill every");
@ -2472,6 +2487,17 @@ void PrintConfigDef::init_fff_params()
def->mode = comExpert; def->mode = comExpert;
def->set_default_value(new ConfigOptionString("[input_filename_base].gcode")); def->set_default_value(new ConfigOptionString("[input_filename_base].gcode"));
def = this->add("overhangs_speed", coFloatOrPercent);
def->label = L("Overhangs");
def->full_label = L("Overhangs speed");
def->category = OptionCategory::speed;
def->tooltip = L("Speed for printing overhangs.\nCan be a % of the bridge speed.");
def->sidetext = L("mm/s");
def->ratio_over = "bridge_speed";
def->min = 0;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloatOrPercent(20, false));
def = this->add("overhangs_width_speed", coFloatOrPercent); def = this->add("overhangs_width_speed", coFloatOrPercent);
def->label = L("'As bridge' speed threshold"); def->label = L("'As bridge' speed threshold");
def->full_label = L("Overhang bridge speed threshold"); def->full_label = L("Overhang bridge speed threshold");
@ -2557,16 +2583,17 @@ void PrintConfigDef::init_fff_params()
def->mode = comAdvanced; def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloat(-2.f)); def->set_default_value(new ConfigOptionFloat(-2.f));
def = this->add("perimeter_acceleration", coFloat); def = this->add("perimeter_acceleration", coFloatOrPercent);
def->label = L("Perimeters"); def->label = L("Perimeters");
def->full_label = ("Perimeter acceleration"); def->full_label = ("Perimeter acceleration");
def->category = OptionCategory::speed; def->category = OptionCategory::speed;
def->tooltip = L("This is the acceleration your printer will use for perimeters. " def->tooltip = L("This is the acceleration your printer will use for perimeters. "
"A high value like 9000 usually gives good results if your hardware is up to the job. " "A high value like 9000 usually gives good results if your hardware is up to the job."
"Set zero to disable acceleration control for perimeters."); "\nCan be a % of the default acceleration"
def->sidetext = L("mm/s²"); "\nSet zero to disable acceleration control for perimeters.");
def->sidetext = L("mm/s² or %");
def->mode = comExpert; def->mode = comExpert;
def->set_default_value(new ConfigOptionFloat(0)); def->set_default_value(new ConfigOptionFloatOrPercent(0,false));
def = this->add("perimeter_extruder", coInt); def = this->add("perimeter_extruder", coInt);
def->label = L("Perimeter extruder"); def->label = L("Perimeter extruder");
@ -3851,12 +3878,13 @@ void PrintConfigDef::init_fff_params()
def->set_default_value(new ConfigOptionFloat(10.)); def->set_default_value(new ConfigOptionFloat(10.));
def = this->add("xy_size_compensation", coFloat); def = this->add("xy_size_compensation", coFloat);
def->label = L("outer"); def->label = L("Outer");
def->full_label = L("outer XY size compensation"); def->full_label = L("Outer XY size compensation");
def->category = OptionCategory::slicing; def->category = OptionCategory::slicing;
def->tooltip = L("The object will be grown/shrunk in the XY plane by the configured value " def->tooltip = L("The object will be grown/shrunk in the XY plane by the configured value "
"(negative = inwards, positive = outwards). This might be useful for fine-tuning sizes." "(negative = inwards, positive = outwards). This might be useful for fine-tuning sizes."
"\nThis one only applies to the 'exterior' shell of the object"); "\nThis one only applies to the 'exterior' shell of the object."
"\n !!! it's recommended you put the same value into the 'Inner XY size compensation', unless you are sure you don't have horizontal holes. !!! ");
def->sidetext = L("mm"); def->sidetext = L("mm");
def->mode = comExpert; def->mode = comExpert;
def->set_default_value(new ConfigOptionFloat(0)); def->set_default_value(new ConfigOptionFloat(0));
@ -3867,7 +3895,7 @@ void PrintConfigDef::init_fff_params()
def->category = OptionCategory::slicing; def->category = OptionCategory::slicing;
def->tooltip = L("The object will be grown/shrunk in the XY plane by the configured value " def->tooltip = L("The object will be grown/shrunk in the XY plane by the configured value "
"(negative = inwards, positive = outwards). This might be useful for fine-tuning sizes." "(negative = inwards, positive = outwards). This might be useful for fine-tuning sizes."
"\nThis one only applies to the 'inner' shell of the object"); "\nThis one only applies to the 'inner' shell of the object (!!! horizontal holes break the shell !!!)");
def->sidetext = L("mm"); def->sidetext = L("mm");
def->mode = comExpert; def->mode = comExpert;
def->set_default_value(new ConfigOptionFloat(0)); def->set_default_value(new ConfigOptionFloat(0));
@ -3884,6 +3912,17 @@ void PrintConfigDef::init_fff_params()
def->mode = comExpert; def->mode = comExpert;
def->set_default_value(new ConfigOptionFloat(0)); def->set_default_value(new ConfigOptionFloat(0));
def = this->add("hole_size_threshold", coFloat);
def->label = L("Holes");
def->full_label = L("XY holes threshold");
def->category = OptionCategory::slicing;
def->tooltip = L("Maximum area for the hole where the hole_size_compensation will apply fully."
" After that, it will decraese down to 0 for four time this area."
" Set to 0 to let the hole_size_compensation apply fully for all detected holes");
def->sidetext = L("mm²");
def->mode = comExpert;
def->set_default_value(new ConfigOptionFloat(100));
def = this->add("hole_to_polyhole", coBool); def = this->add("hole_to_polyhole", coBool);
def->label = L("Convert round holes to polyholes"); def->label = L("Convert round holes to polyholes");
def->full_label = L("Convert round holes to polyholes"); def->full_label = L("Convert round holes to polyholes");

View File

@ -581,6 +581,7 @@ public:
ConfigOptionFloatOrPercent first_layer_height; ConfigOptionFloatOrPercent first_layer_height;
ConfigOptionFloat first_layer_size_compensation; ConfigOptionFloat first_layer_size_compensation;
ConfigOptionFloat hole_size_compensation; ConfigOptionFloat hole_size_compensation;
ConfigOptionFloat hole_size_threshold;
ConfigOptionBool infill_only_where_needed; ConfigOptionBool infill_only_where_needed;
// Force the generation of solid shells between adjacent materials/volumes. // Force the generation of solid shells between adjacent materials/volumes.
ConfigOptionBool interface_shells; ConfigOptionBool interface_shells;
@ -644,6 +645,7 @@ protected:
OPT_PTR(exact_last_layer_height); OPT_PTR(exact_last_layer_height);
OPT_PTR(extrusion_width); OPT_PTR(extrusion_width);
OPT_PTR(hole_size_compensation); OPT_PTR(hole_size_compensation);
OPT_PTR(hole_size_threshold);
OPT_PTR(first_layer_height); OPT_PTR(first_layer_height);
OPT_PTR(first_layer_size_compensation); OPT_PTR(first_layer_size_compensation);
OPT_PTR(infill_only_where_needed); OPT_PTR(infill_only_where_needed);
@ -702,7 +704,8 @@ public:
ConfigOptionPercent bridge_overlap; ConfigOptionPercent bridge_overlap;
ConfigOptionEnum<InfillPattern> bottom_fill_pattern; ConfigOptionEnum<InfillPattern> bottom_fill_pattern;
ConfigOptionFloatOrPercent bridged_infill_margin; ConfigOptionFloatOrPercent bridged_infill_margin;
ConfigOptionFloat bridge_speed; ConfigOptionFloat bridge_speed;
ConfigOptionFloatOrPercent bridge_speed_internal;
ConfigOptionFloat curve_smoothing_precision; ConfigOptionFloat curve_smoothing_precision;
ConfigOptionFloat curve_smoothing_cutoff_dist; ConfigOptionFloat curve_smoothing_cutoff_dist;
ConfigOptionFloat curve_smoothing_angle_convex; ConfigOptionFloat curve_smoothing_angle_convex;
@ -755,6 +758,7 @@ public:
ConfigOptionFloat milling_speed; ConfigOptionFloat milling_speed;
ConfigOptionFloatOrPercent min_width_top_surface; ConfigOptionFloatOrPercent min_width_top_surface;
// Detect bridging perimeters // Detect bridging perimeters
ConfigOptionFloatOrPercent overhangs_speed;
ConfigOptionFloatOrPercent overhangs_width; ConfigOptionFloatOrPercent overhangs_width;
ConfigOptionFloatOrPercent overhangs_width_speed; ConfigOptionFloatOrPercent overhangs_width_speed;
ConfigOptionBool overhangs_reverse; ConfigOptionBool overhangs_reverse;
@ -805,6 +809,7 @@ protected:
OPT_PTR(bottom_fill_pattern); OPT_PTR(bottom_fill_pattern);
OPT_PTR(bridged_infill_margin); OPT_PTR(bridged_infill_margin);
OPT_PTR(bridge_speed); OPT_PTR(bridge_speed);
OPT_PTR(bridge_speed_internal);
OPT_PTR(curve_smoothing_precision); OPT_PTR(curve_smoothing_precision);
OPT_PTR(curve_smoothing_cutoff_dist); OPT_PTR(curve_smoothing_cutoff_dist);
OPT_PTR(curve_smoothing_angle_convex); OPT_PTR(curve_smoothing_angle_convex);
@ -854,6 +859,7 @@ protected:
OPT_PTR(milling_post_process); OPT_PTR(milling_post_process);
OPT_PTR(milling_speed); OPT_PTR(milling_speed);
OPT_PTR(min_width_top_surface); OPT_PTR(min_width_top_surface);
OPT_PTR(overhangs_speed);
OPT_PTR(overhangs_width); OPT_PTR(overhangs_width);
OPT_PTR(overhangs_width_speed); OPT_PTR(overhangs_width_speed);
OPT_PTR(overhangs_reverse); OPT_PTR(overhangs_reverse);
@ -1170,7 +1176,7 @@ public:
ConfigOptionBool avoid_crossing_not_first_layer; ConfigOptionBool avoid_crossing_not_first_layer;
ConfigOptionPoints bed_shape; ConfigOptionPoints bed_shape;
ConfigOptionInts bed_temperature; ConfigOptionInts bed_temperature;
ConfigOptionFloat bridge_acceleration; ConfigOptionFloatOrPercent bridge_acceleration;
ConfigOptionInts bridge_fan_speed; ConfigOptionInts bridge_fan_speed;
ConfigOptionInts chamber_temperature; ConfigOptionInts chamber_temperature;
ConfigOptionBool complete_objects; ConfigOptionBool complete_objects;
@ -1178,7 +1184,7 @@ public:
ConfigOptionEnum<CompleteObjectSort> complete_objects_sort; ConfigOptionEnum<CompleteObjectSort> complete_objects_sort;
ConfigOptionFloats colorprint_heights; ConfigOptionFloats colorprint_heights;
ConfigOptionBools cooling; ConfigOptionBools cooling;
ConfigOptionFloat default_acceleration; ConfigOptionFloatOrPercent default_acceleration;
ConfigOptionInts disable_fan_first_layers; ConfigOptionInts disable_fan_first_layers;
ConfigOptionFloat duplicate_distance; ConfigOptionFloat duplicate_distance;
ConfigOptionInts external_perimeter_fan_speed; ConfigOptionInts external_perimeter_fan_speed;
@ -1191,14 +1197,14 @@ public:
ConfigOptionStrings filament_colour; ConfigOptionStrings filament_colour;
ConfigOptionStrings filament_notes; ConfigOptionStrings filament_notes;
ConfigOptionPercents filament_shrink; ConfigOptionPercents filament_shrink;
ConfigOptionFloat first_layer_acceleration; ConfigOptionFloatOrPercent first_layer_acceleration;
ConfigOptionInts first_layer_bed_temperature; ConfigOptionInts first_layer_bed_temperature;
ConfigOptionFloatOrPercent first_layer_extrusion_width; ConfigOptionFloatOrPercent first_layer_extrusion_width;
ConfigOptionPercent first_layer_flow_ratio; ConfigOptionPercent first_layer_flow_ratio;
ConfigOptionFloatOrPercent first_layer_speed; ConfigOptionFloatOrPercent first_layer_speed;
ConfigOptionFloatOrPercent first_layer_infill_speed; ConfigOptionFloatOrPercent first_layer_infill_speed;
ConfigOptionInts first_layer_temperature; ConfigOptionInts first_layer_temperature;
ConfigOptionFloat infill_acceleration; ConfigOptionFloatOrPercent infill_acceleration;
ConfigOptionInts max_fan_speed; ConfigOptionInts max_fan_speed;
ConfigOptionFloats max_layer_height; ConfigOptionFloats max_layer_height;
ConfigOptionFloat max_print_height; ConfigOptionFloat max_print_height;
@ -1217,7 +1223,7 @@ public:
ConfigOptionBool only_retract_when_crossing_perimeters; ConfigOptionBool only_retract_when_crossing_perimeters;
ConfigOptionBool ooze_prevention; ConfigOptionBool ooze_prevention;
ConfigOptionString output_filename_format; ConfigOptionString output_filename_format;
ConfigOptionFloat perimeter_acceleration; ConfigOptionFloatOrPercent perimeter_acceleration;
ConfigOptionStrings post_process; ConfigOptionStrings post_process;
ConfigOptionString printer_model; ConfigOptionString printer_model;
ConfigOptionString printer_notes; ConfigOptionString printer_notes;

View File

@ -713,6 +713,7 @@ bool PrintObject::invalidate_state_by_config_options(const std::vector<t_config_
|| opt_key == "support_material_contact_distance_bottom" || opt_key == "support_material_contact_distance_bottom"
|| opt_key == "xy_size_compensation" || opt_key == "xy_size_compensation"
|| opt_key == "hole_size_compensation" || opt_key == "hole_size_compensation"
|| opt_key == "hole_size_threshold"
|| opt_key == "hole_to_polyhole" || opt_key == "hole_to_polyhole"
|| opt_key == "z_step") { || opt_key == "z_step") {
steps.emplace_back(posSlice); steps.emplace_back(posSlice);
@ -810,10 +811,12 @@ bool PrintObject::invalidate_state_by_config_options(const std::vector<t_config_
//} //}
} else if ( } else if (
opt_key == "bridge_speed" opt_key == "bridge_speed"
|| opt_key == "bridge_speed_internal"
|| opt_key == "external_perimeter_speed" || opt_key == "external_perimeter_speed"
|| opt_key == "external_perimeters_vase" || opt_key == "external_perimeters_vase"
|| opt_key == "gap_fill_speed" || opt_key == "gap_fill_speed"
|| opt_key == "infill_speed" || opt_key == "infill_speed"
|| opt_key == "overhangs_speed"
|| opt_key == "perimeter_speed" || opt_key == "perimeter_speed"
|| opt_key == "seam_position" || opt_key == "seam_position"
|| opt_key == "seam_preferred_direction" || opt_key == "seam_preferred_direction"
@ -2603,6 +2606,7 @@ end:
ExPolygons PrintObject::_shrink_contour_holes(double contour_delta, double default_delta, double convex_delta, const ExPolygons& polys) const { ExPolygons PrintObject::_shrink_contour_holes(double contour_delta, double default_delta, double convex_delta, const ExPolygons& polys) const {
ExPolygons new_ex_polys; ExPolygons new_ex_polys;
double max_hole_area = scale_d(scale_d(m_config.hole_size_threshold.value));
for (const ExPolygon& ex_poly : polys) { for (const ExPolygon& ex_poly : polys) {
Polygons contours; Polygons contours;
Polygons holes; Polygons holes;
@ -2621,12 +2625,26 @@ ExPolygons PrintObject::_shrink_contour_holes(double contour_delta, double defau
// check whether last point forms a convex angle // check whether last point forms a convex angle
ok &= (hole.points.back().ccw_angle(*(hole.points.end() - 2), hole.points.front()) <= PI + 0.1); ok &= (hole.points.back().ccw_angle(*(hole.points.end() - 2), hole.points.front()) <= PI + 0.1);
if (ok) { if (ok) {
if (convex_delta != 0) { if (convex_delta != 0) {
for (Polygon &newHole : offset(hole, -convex_delta)) { //apply hole threshold cutoff
newHole.make_counter_clockwise(); double convex_delta_adapted = convex_delta;
holes.emplace_back(std::move(newHole)); double area = -hole.area();
if (area > max_hole_area * 4) {
convex_delta_adapted = 0;
}else if (area > max_hole_area) {
// not a hard threshold, to avoid artefacts on slopped holes.
convex_delta_adapted = convex_delta * (max_hole_area * 4 - area) / (max_hole_area * 3);
}
if (convex_delta_adapted != 0) {
for (Polygon &newHole : offset(hole, -convex_delta_adapted)) {
newHole.make_counter_clockwise();
holes.emplace_back(std::move(newHole));
}
} else {
holes.push_back(hole);
holes.back().make_counter_clockwise();
} }
} else { } else {
holes.push_back(hole); holes.push_back(hole);

View File

@ -808,7 +808,7 @@ namespace SupportMaterialInternal {
return true; return true;
} else { } else {
assert(! ee->is_loop()); assert(! ee->is_loop());
if (ee->role() == erBridgeInfill) if (ee->role() == erBridgeInfill || ee->role() == erInternalBridgeInfill)
return true; return true;
} }
} }

View File

@ -93,6 +93,8 @@ inline T unscale(Q v) { return T(v) * T(SCALING_FACTOR); }
inline double unscaled(double v) { return v * SCALING_FACTOR; } inline double unscaled(double v) { return v * SCALING_FACTOR; }
inline coordf_t unscale_(coord_t v) { return v * SCALING_FACTOR; } inline coordf_t unscale_(coord_t v) { return v * SCALING_FACTOR; }
inline coord_t scale_t(coordf_t v) { return (coord_t)(v / SCALING_FACTOR); } inline coord_t scale_t(coordf_t v) { return (coord_t)(v / SCALING_FACTOR); }
inline double scale_d(coordf_t v) { return (v / SCALING_FACTOR); }
inline double scale_d(coord_t v) { return ((double)v / SCALING_FACTOR); }
enum Axis { enum Axis {
X=0, X=0,

View File

@ -2,6 +2,7 @@
#include "I18N.hpp" #include "I18N.hpp"
#include "libslic3r/Model.hpp" #include "libslic3r/Model.hpp"
#include "libslic3r/Utils.hpp" #include "libslic3r/Utils.hpp"
#include "AppConfig.hpp"
#include "GUI.hpp" #include "GUI.hpp"
#include "GUI_ObjectList.hpp" #include "GUI_ObjectList.hpp"
#include "Plater.hpp" #include "Plater.hpp"
@ -33,6 +34,12 @@ void CalibrationBedDialog::create_geometry(wxCommandEvent& event_args) {
Plater* plat = this->main_frame->plater(); Plater* plat = this->main_frame->plater();
Model& model = plat->model(); Model& model = plat->model();
plat->reset(); plat->reset();
bool autocenter = gui_app->app_config->get("autocenter") == "1";
if(autocenter) {
//disable aut-ocenter for this calibration.
gui_app->app_config->set("autocenter", "0");
}
std::vector<size_t> objs_idx = plat->load_files(std::vector<std::string>{ std::vector<size_t> objs_idx = plat->load_files(std::vector<std::string>{
Slic3r::resources_dir()+"/calibration/bed_leveling/patch.amf", Slic3r::resources_dir()+"/calibration/bed_leveling/patch.amf",
Slic3r::resources_dir()+"/calibration/bed_leveling/patch.amf", Slic3r::resources_dir()+"/calibration/bed_leveling/patch.amf",
@ -135,7 +142,10 @@ void CalibrationBedDialog::create_geometry(wxCommandEvent& event_args) {
// plat->schedule_background_process(); // plat->schedule_background_process();
plat->reslice(); plat->reslice();
plat->select_view_3D("Preview"); plat->select_view_3D("Preview");
if (autocenter) {
//re-enable auto-center after this calibration.
gui_app->app_config->set("autocenter", "1");
}
} }
} // namespace GUI } // namespace GUI

View File

@ -2,6 +2,7 @@
#include "I18N.hpp" #include "I18N.hpp"
#include "libslic3r/Model.hpp" #include "libslic3r/Model.hpp"
#include "libslic3r/Utils.hpp" #include "libslic3r/Utils.hpp"
#include "AppConfig.hpp"
#include "GUI.hpp" #include "GUI.hpp"
#include "GUI_ObjectList.hpp" #include "GUI_ObjectList.hpp"
#include "Plater.hpp" #include "Plater.hpp"
@ -53,6 +54,12 @@ void CalibrationBridgeDialog::create_geometry(std::string setting_to_test, bool
Model& model = plat->model(); Model& model = plat->model();
plat->reset(); plat->reset();
bool autocenter = gui_app->app_config->get("autocenter") == "1";
if (autocenter) {
//disable auto-center for this calibration.
gui_app->app_config->set("autocenter", "0");
}
int idx_steps = steps->GetSelection(); int idx_steps = steps->GetSelection();
int idx_nb = nb_tests->GetSelection(); int idx_nb = nb_tests->GetSelection();
size_t step = 5 + (idx_steps == wxNOT_FOUND ? 0 : idx_steps * 5); size_t step = 5 + (idx_steps == wxNOT_FOUND ? 0 : idx_steps * 5);
@ -91,15 +98,15 @@ void CalibrationBridgeDialog::create_geometry(std::string setting_to_test, bool
} }
/// --- translate ---; /// --- translate ---;
const float brim_width = std::max(print_config->option<ConfigOptionFloat>("brim_width")->value, nozzle_diameter * 5.);
const ConfigOptionFloat* extruder_clearance_radius = print_config->option<ConfigOptionFloat>("extruder_clearance_radius"); const ConfigOptionFloat* extruder_clearance_radius = print_config->option<ConfigOptionFloat>("extruder_clearance_radius");
const ConfigOptionPoints* bed_shape = printer_config->option<ConfigOptionPoints>("bed_shape"); const ConfigOptionPoints* bed_shape = printer_config->option<ConfigOptionPoints>("bed_shape");
const float brim_width = std::max(print_config->option<ConfigOptionFloat>("brim_width")->value, nozzle_diameter * 5.);
Vec2d bed_size = BoundingBoxf(bed_shape->values).size(); Vec2d bed_size = BoundingBoxf(bed_shape->values).size();
Vec2d bed_min = BoundingBoxf(bed_shape->values).min; Vec2d bed_min = BoundingBoxf(bed_shape->values).min;
float offsety = 2 + 10 * 1 + extruder_clearance_radius->value + brim_width + (brim_width> extruder_clearance_radius->value ? brim_width - extruder_clearance_radius->value :0); float offsety = 2 + 10 * 1 + extruder_clearance_radius->value + brim_width + (brim_width > extruder_clearance_radius->value ? brim_width - extruder_clearance_radius->value : 0);
model.objects[objs_idx[0]]->translate({ bed_min.x() + bed_size.x() / 2, bed_min.y() + bed_size.y() / 2, 0 }); model.objects[objs_idx[0]]->translate({ bed_min.x() + bed_size.x() / 2, bed_min.y() + bed_size.y() / 2, 0 });
for (int i = 1; i < nb_items; i++) { for (int i = 1; i < nb_items; i++) {
model.objects[objs_idx[i]]->translate({ bed_min.x() + bed_size.x() / 2, bed_min.y() + bed_size.y() / 2 + (i%2==0?-1:1) * offsety * ((i+1)/2), 0 }); model.objects[objs_idx[i]]->translate({ bed_min.x() + bed_size.x() / 2, bed_min.y() + bed_size.y() / 2 + (i % 2 == 0 ? -1 : 1) * offsety * ((i + 1) / 2), 0 });
} }
//TODO: if not enough space, forget about complete_objects //TODO: if not enough space, forget about complete_objects
@ -137,6 +144,11 @@ void CalibrationBridgeDialog::create_geometry(std::string setting_to_test, bool
plat->reslice(); plat->reslice();
plat->select_view_3D("Preview"); plat->select_view_3D("Preview");
if (autocenter) {
//re-enable auto-center after this calibration.
gui_app->app_config->set("autocenter", "1");
}
} }
} // namespace GUI } // namespace GUI

View File

@ -2,6 +2,7 @@
#include "I18N.hpp" #include "I18N.hpp"
#include "libslic3r/Model.hpp" #include "libslic3r/Model.hpp"
#include "libslic3r/Utils.hpp" #include "libslic3r/Utils.hpp"
#include "AppConfig.hpp"
#include "GUI.hpp" #include "GUI.hpp"
#include "GUI_ObjectList.hpp" #include "GUI_ObjectList.hpp"
#include "Plater.hpp" #include "Plater.hpp"
@ -37,6 +38,13 @@ void CalibrationFlowDialog::create_geometry(float start, float delta) {
Plater* plat = this->main_frame->plater(); Plater* plat = this->main_frame->plater();
Model& model = plat->model(); Model& model = plat->model();
plat->reset(); plat->reset();
bool autocenter = gui_app->app_config->get("autocenter") == "1";
if (autocenter) {
//disable auto-center for this calibration.
gui_app->app_config->set("autocenter", "0");
}
std::vector<size_t> objs_idx = plat->load_files(std::vector<std::string>{ std::vector<size_t> objs_idx = plat->load_files(std::vector<std::string>{
Slic3r::resources_dir()+"/calibration/filament_flow/filament_flow_test_cube.amf", Slic3r::resources_dir()+"/calibration/filament_flow/filament_flow_test_cube.amf",
Slic3r::resources_dir()+"/calibration/filament_flow/filament_flow_test_cube.amf", Slic3r::resources_dir()+"/calibration/filament_flow/filament_flow_test_cube.amf",
@ -152,6 +160,11 @@ void CalibrationFlowDialog::create_geometry(float start, float delta) {
plat->reslice(); plat->reslice();
plat->select_view_3D("Preview"); plat->select_view_3D("Preview");
if (autocenter) {
//re-enable auto-center after this calibration.
gui_app->app_config->set("autocenter", "1");
}
} }
} // namespace GUI } // namespace GUI

View File

@ -2,6 +2,7 @@
#include "I18N.hpp" #include "I18N.hpp"
#include "libslic3r/Model.hpp" #include "libslic3r/Model.hpp"
#include "libslic3r/Utils.hpp" #include "libslic3r/Utils.hpp"
#include "AppConfig.hpp"
#include "GUI.hpp" #include "GUI.hpp"
#include "GUI_ObjectList.hpp" #include "GUI_ObjectList.hpp"
#include "Plater.hpp" #include "Plater.hpp"
@ -33,6 +34,12 @@ void CalibrationOverBridgeDialog::create_geometry(wxCommandEvent& event_args) {
Plater* plat = this->main_frame->plater(); Plater* plat = this->main_frame->plater();
Model& model = plat->model(); Model& model = plat->model();
plat->reset(); plat->reset();
bool autocenter = gui_app->app_config->get("autocenter") == "1";
if (autocenter) {
//disable aut-ocenter for this calibration.
gui_app->app_config->set("autocenter", "0");
}
std::vector<size_t> objs_idx = plat->load_files(std::vector<std::string>{ std::vector<size_t> objs_idx = plat->load_files(std::vector<std::string>{
Slic3r::resources_dir()+"/calibration/over-bridge_tuning/over-bridge_flow_ratio_test.amf", Slic3r::resources_dir()+"/calibration/over-bridge_tuning/over-bridge_flow_ratio_test.amf",
Slic3r::resources_dir()+"/calibration/over-bridge_tuning/over-bridge_flow_ratio_test.amf", Slic3r::resources_dir()+"/calibration/over-bridge_tuning/over-bridge_flow_ratio_test.amf",
@ -119,6 +126,11 @@ void CalibrationOverBridgeDialog::create_geometry(wxCommandEvent& event_args) {
plat->reslice(); plat->reslice();
plat->select_view_3D("Preview"); plat->select_view_3D("Preview");
if (autocenter) {
//re-enable auto-center after this calibration.
gui_app->app_config->set("autocenter", "1");
}
} }
} // namespace GUI } // namespace GUI

View File

@ -2,6 +2,7 @@
#include "I18N.hpp" #include "I18N.hpp"
#include "libslic3r/Model.hpp" #include "libslic3r/Model.hpp"
#include "libslic3r/Utils.hpp" #include "libslic3r/Utils.hpp"
#include "AppConfig.hpp"
#include "GUI.hpp" #include "GUI.hpp"
#include "GUI_ObjectList.hpp" #include "GUI_ObjectList.hpp"
#include "Plater.hpp" #include "Plater.hpp"
@ -100,6 +101,12 @@ void CalibrationRetractionDialog::create_geometry(wxCommandEvent& event_args) {
Model& model = plat->model(); Model& model = plat->model();
plat->reset(); plat->reset();
bool autocenter = gui_app->app_config->get("autocenter") == "1";
if (autocenter) {
//disable aut-ocenter for this calibration.
gui_app->app_config->set("autocenter", "0");
}
size_t nb_retract = nb_steps->GetSelection() < 4 ? ((int(nb_steps->GetSelection()) + 1) * 2) : ((int(nb_steps->GetSelection()) - 2) * 5); size_t nb_retract = nb_steps->GetSelection() < 4 ? ((int(nb_steps->GetSelection()) + 1) * 2) : ((int(nb_steps->GetSelection()) - 2) * 5);
size_t nb_items = 1; size_t nb_items = 1;
if (decr_temp->GetSelection() == 1) { if (decr_temp->GetSelection() == 1) {
@ -258,6 +265,11 @@ void CalibrationRetractionDialog::create_geometry(wxCommandEvent& event_args) {
plat->reslice(); plat->reslice();
plat->select_view_3D("Preview"); plat->select_view_3D("Preview");
if (autocenter) {
//re-enable auto-center after this calibration.
gui_app->app_config->set("autocenter", "1");
}
} }
} // namespace GUI } // namespace GUI

View File

@ -3,6 +3,7 @@
#include "libslic3r/Utils.hpp" #include "libslic3r/Utils.hpp"
#include "libslic3r/CustomGCode.hpp" #include "libslic3r/CustomGCode.hpp"
#include "libslic3r/Model.hpp" #include "libslic3r/Model.hpp"
#include "AppConfig.hpp"
#include "GUI.hpp" #include "GUI.hpp"
#include "GUI_ObjectList.hpp" #include "GUI_ObjectList.hpp"
#include "Plater.hpp" #include "Plater.hpp"
@ -110,10 +111,13 @@ void CalibrationTempDialog::create_geometry(wxCommandEvent& event_args) {
/// --- translate --- /// --- translate ---
const ConfigOptionPoints* bed_shape = printer_config->option<ConfigOptionPoints>("bed_shape"); bool autocenter = gui_app->app_config->get("autocenter") == "1";
Vec2d bed_size = BoundingBoxf(bed_shape->values).size(); if (!autocenter) {
Vec2d bed_min = BoundingBoxf(bed_shape->values).min; const ConfigOptionPoints* bed_shape = printer_config->option<ConfigOptionPoints>("bed_shape");
model.objects[objs_idx[0]]->translate({ bed_min.x() + bed_size.x() / 2, bed_min.y() + bed_size.y() / 2, 0 }); Vec2d bed_size = BoundingBoxf(bed_shape->values).size();
Vec2d bed_min = BoundingBoxf(bed_shape->values).min;
model.objects[objs_idx[0]]->translate({ bed_min.x() + bed_size.x() / 2, bed_min.y() + bed_size.y() / 2, 0 });
}
/// --- main config, please modify object config when possible --- /// --- main config, please modify object config when possible ---
DynamicPrintConfig new_print_config = *print_config; //make a copy DynamicPrintConfig new_print_config = *print_config; //make a copy

View File

@ -418,7 +418,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config)
for (auto el : { "top_infill_extrusion_width", "top_solid_infill_speed" }) for (auto el : { "top_infill_extrusion_width", "top_solid_infill_speed" })
toggle_field(el, has_top_solid_infill); toggle_field(el, has_top_solid_infill);
bool have_default_acceleration = config->opt_float("default_acceleration") > 0; bool have_default_acceleration = config->option<ConfigOptionFloatOrPercent>("default_acceleration")->value > 0;
for (auto el : { "perimeter_acceleration", "infill_acceleration", for (auto el : { "perimeter_acceleration", "infill_acceleration",
"bridge_acceleration", "first_layer_acceleration" }) "bridge_acceleration", "first_layer_acceleration" })
toggle_field(el, have_default_acceleration); toggle_field(el, have_default_acceleration);

View File

@ -336,6 +336,7 @@ bool Preview::init(wxWindow* parent, Model* model)
_L("Solid infill") + "|" + _L("Solid infill") + "|" +
_L("Top solid infill") + "|" + _L("Top solid infill") + "|" +
_L("Bridge infill") + "|" + _L("Bridge infill") + "|" +
_L("Internal bridge infill") + "|" +
_L("Thin wall") + "|" + _L("Thin wall") + "|" +
_L("Gap fill") + "|" + _L("Gap fill") + "|" +
_L("Skirt") + "|" + _L("Skirt") + "|" +
@ -446,6 +447,7 @@ bool Preview::init(wxWindow* parent, Model* model)
"Solid infill", "D732D7", "Solid infill", "D732D7",
"Top solid infill", "FF1A1A", "Top solid infill", "FF1A1A",
"Bridge infill", "9999FF", "Bridge infill", "9999FF",
"Internal bridge infill", "9999EE",
"Thin wall", "FFB000", "Thin wall", "FFB000",
"Gap fill", "FFFFFF", "Gap fill", "FFFFFF",
"Skirt", "845321", "Skirt", "845321",