mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-16 19:05:59 +08:00
overextruding a bit on top of bridge to come back to a correct height
This commit is contained in:
parent
f22db7efbe
commit
2749c63b10
@ -34,6 +34,7 @@ avoid_crossing_perimeters = 0
|
|||||||
bridge_acceleration = 1000
|
bridge_acceleration = 1000
|
||||||
bridge_angle = 0
|
bridge_angle = 0
|
||||||
bridge_flow_ratio = 0.8
|
bridge_flow_ratio = 0.8
|
||||||
|
over_bridge_flow_ratio = 1.2
|
||||||
bridge_speed = 20
|
bridge_speed = 20
|
||||||
brim_width = 0
|
brim_width = 0
|
||||||
clip_multipart_objects = 1
|
clip_multipart_objects = 1
|
||||||
|
@ -531,6 +531,7 @@ Usage: slic3r.pl [ OPTIONS ] [ file.stl ] [ file2.stl ] ...
|
|||||||
Set a different extrusion width for support material
|
Set a different extrusion width for support material
|
||||||
--infill-overlap Overlap between infill and perimeters (default: $config->{infill_overlap})
|
--infill-overlap Overlap between infill and perimeters (default: $config->{infill_overlap})
|
||||||
--bridge-flow-ratio Multiplier for extrusion when bridging (> 0, default: $config->{bridge_flow_ratio})
|
--bridge-flow-ratio Multiplier for extrusion when bridging (> 0, default: $config->{bridge_flow_ratio})
|
||||||
|
--over-bridge-flow-ratio Multiplier for extrusion when solid-filling over a bridge (> 0, default: $config->{over_bridge_flow_ratio})
|
||||||
|
|
||||||
Multiple extruder options:
|
Multiple extruder options:
|
||||||
--extruder-offset Offset of each extruder, if firmware doesn't handle the displacement
|
--extruder-offset Offset of each extruder, if firmware doesn't handle the displacement
|
||||||
|
1
t/flow.t
1
t/flow.t
@ -44,6 +44,7 @@ use Slic3r::Test;
|
|||||||
my $config = Slic3r::Config::new_from_defaults;
|
my $config = Slic3r::Config::new_from_defaults;
|
||||||
$config->set('bridge_speed', 99);
|
$config->set('bridge_speed', 99);
|
||||||
$config->set('bridge_flow_ratio', 1);
|
$config->set('bridge_flow_ratio', 1);
|
||||||
|
$config->set('over_bridge_flow_ratio', 1);
|
||||||
$config->set('cooling', [ 0 ]); # to prevent speeds from being altered
|
$config->set('cooling', [ 0 ]); # to prevent speeds from being altered
|
||||||
$config->set('first_layer_speed', '100%'); # to prevent speeds from being altered
|
$config->set('first_layer_speed', '100%'); # to prevent speeds from being altered
|
||||||
|
|
||||||
|
@ -248,6 +248,7 @@ use Slic3r::Test;
|
|||||||
$config->set('slowdown_below_layer_time', [ 0 ]);
|
$config->set('slowdown_below_layer_time', [ 0 ]);
|
||||||
$config->set('bridge_fan_speed', [ 100 ]);
|
$config->set('bridge_fan_speed', [ 100 ]);
|
||||||
$config->set('bridge_flow_ratio', 33); # arbitrary value
|
$config->set('bridge_flow_ratio', 33); # arbitrary value
|
||||||
|
$config->set('over_bridge_flow_ratio', 110); # arbitrary value
|
||||||
$config->set('overhangs', 1);
|
$config->set('overhangs', 1);
|
||||||
my $print = Slic3r::Test::init_print('overhang', config => $config);
|
my $print = Slic3r::Test::init_print('overhang', config => $config);
|
||||||
my %layer_speeds = (); # print Z => [ speeds ]
|
my %layer_speeds = (); # print Z => [ speeds ]
|
||||||
|
@ -63,14 +63,14 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
|
|||||||
// (we'll use them for comparing compatible groups)
|
// (we'll use them for comparing compatible groups)
|
||||||
std::vector<SurfaceGroupAttrib> group_attrib(groups.size());
|
std::vector<SurfaceGroupAttrib> group_attrib(groups.size());
|
||||||
for (size_t i = 0; i < groups.size(); ++ i) {
|
for (size_t i = 0; i < groups.size(); ++ i) {
|
||||||
// we can only merge solid non-bridge surfaces, so discard
|
// we can only merge solid non-bridge non-overextruded surfaces, so discard
|
||||||
// non-solid surfaces
|
// non-solid surfaces
|
||||||
const Surface &surface = *groups[i].front();
|
const Surface &surface = *groups[i].front();
|
||||||
if (surface.is_solid() && (!surface.is_bridge() || layerm.layer()->id() == 0)) {
|
if (surface.is_solid() && (!surface.is_bridge() || layerm.layer()->id() == 0) && !surface.is_overBridge()) {
|
||||||
group_attrib[i].is_solid = true;
|
group_attrib[i].is_solid = true;
|
||||||
group_attrib[i].flow_width = (surface.surface_type == stTop) ? top_solid_infill_flow.width : solid_infill_flow.width;
|
group_attrib[i].flow_width = (surface.is_top()) ? top_solid_infill_flow.width : solid_infill_flow.width;
|
||||||
group_attrib[i].pattern = (surface.surface_type == stTop && surface.is_external()) ? layerm.region()->config.top_fill_pattern.value : ipRectilinear;
|
group_attrib[i].pattern = (surface.is_top() && surface.is_external()) ? layerm.region()->config.top_fill_pattern.value : ipRectilinear;
|
||||||
group_attrib[i].pattern = (surface.surface_type == stBottom && surface.is_external()) ? layerm.region()->config.bottom_fill_pattern.value : ipRectilinear;
|
group_attrib[i].pattern = (surface.is_bottom() && surface.is_external()) ? layerm.region()->config.bottom_fill_pattern.value : ipRectilinear;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Loop through solid groups, find compatible groups and append them to this one.
|
// Loop through solid groups, find compatible groups and append them to this one.
|
||||||
@ -155,14 +155,14 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
|
|||||||
continue;
|
continue;
|
||||||
InfillPattern fill_pattern = layerm.region()->config.fill_pattern.value;
|
InfillPattern fill_pattern = layerm.region()->config.fill_pattern.value;
|
||||||
double density = fill_density;
|
double density = fill_density;
|
||||||
FlowRole role = (surface.surface_type == stTop) ? frTopSolidInfill :
|
FlowRole role = (surface.is_top()) ? frTopSolidInfill :
|
||||||
(surface.is_solid() ? frSolidInfill : frInfill);
|
(surface.is_solid() ? frSolidInfill : frInfill);
|
||||||
bool is_bridge = layerm.layer()->id() > 0 && surface.is_bridge();
|
bool is_bridge = layerm.layer()->id() > 0 && surface.is_bridge();
|
||||||
|
|
||||||
if (surface.is_solid()) {
|
if (surface.is_solid()) {
|
||||||
density = 100.;
|
density = 100.;
|
||||||
fill_pattern = (surface.is_external() && ! is_bridge) ?
|
fill_pattern = (surface.is_external() && ! is_bridge) ?
|
||||||
(surface.surface_type == stTop ? layerm.region()->config.top_fill_pattern.value : layerm.region()->config.bottom_fill_pattern.value) :
|
(surface.is_top() ? layerm.region()->config.top_fill_pattern.value : layerm.region()->config.bottom_fill_pattern.value) :
|
||||||
ipRectilinear;
|
ipRectilinear;
|
||||||
} else if (density <= 0)
|
} else if (density <= 0)
|
||||||
continue;
|
continue;
|
||||||
@ -242,6 +242,11 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
|
|||||||
flow = Flow::new_from_spacing(f->spacing, flow.nozzle_diameter, h, is_bridge || f->use_bridge_flow());
|
flow = Flow::new_from_spacing(f->spacing, flow.nozzle_diameter, h, is_bridge || f->use_bridge_flow());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float flow_percent = 1;
|
||||||
|
if(surface.is_overBridge()){
|
||||||
|
flow_percent = layerm.region()->config.over_bridge_flow_ratio;
|
||||||
|
}
|
||||||
|
|
||||||
// Save into layer.
|
// Save into layer.
|
||||||
auto *eec = new ExtrusionEntityCollection();
|
auto *eec = new ExtrusionEntityCollection();
|
||||||
out.entities.push_back(eec);
|
out.entities.push_back(eec);
|
||||||
@ -254,7 +259,7 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
|
|||||||
(surface.is_solid() ?
|
(surface.is_solid() ?
|
||||||
((surface.surface_type == stTop) ? erTopSolidInfill : erSolidInfill) :
|
((surface.surface_type == stTop) ? erTopSolidInfill : erSolidInfill) :
|
||||||
erInternalInfill),
|
erInternalInfill),
|
||||||
flow.mm3_per_mm(), flow.width, flow.height);
|
flow.mm3_per_mm()*flow_percent, flow.width*flow_percent, flow.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
// add thin fill regions
|
// add thin fill regions
|
||||||
|
@ -121,7 +121,7 @@ void LayerRegion::process_external_surfaces(const Layer* lower_layer)
|
|||||||
fill_boundaries.reserve(number_polygons(surfaces));
|
fill_boundaries.reserve(number_polygons(surfaces));
|
||||||
bool has_infill = this->region()->config.fill_density.value > 0.;
|
bool has_infill = this->region()->config.fill_density.value > 0.;
|
||||||
for (const Surface &surface : this->fill_surfaces.surfaces) {
|
for (const Surface &surface : this->fill_surfaces.surfaces) {
|
||||||
if (surface.surface_type == stTop) {
|
if (surface.is_top()) {
|
||||||
// Collect the top surfaces, inflate them and trim them by the bottom surfaces.
|
// Collect the top surfaces, inflate them and trim them by the bottom surfaces.
|
||||||
// This gives the priority to bottom surfaces.
|
// This gives the priority to bottom surfaces.
|
||||||
surfaces_append(top, offset_ex(surface.expolygon, float(margin), EXTERNAL_SURFACES_OFFSET_PARAMETERS), surface);
|
surfaces_append(top, offset_ex(surface.expolygon, float(margin), EXTERNAL_SURFACES_OFFSET_PARAMETERS), surface);
|
||||||
@ -132,13 +132,12 @@ void LayerRegion::process_external_surfaces(const Layer* lower_layer)
|
|||||||
if (! surface.empty())
|
if (! surface.empty())
|
||||||
bridges.push_back(surface);
|
bridges.push_back(surface);
|
||||||
}
|
}
|
||||||
bool internal_surface = surface.surface_type != stTop && ! surface.is_bottom();
|
|
||||||
if (has_infill || surface.surface_type != stInternal) {
|
if (has_infill || surface.surface_type != stInternal) {
|
||||||
if (internal_surface)
|
if (!surface.is_external())
|
||||||
// Make a copy as the following line uses the move semantics.
|
// Make a copy as the following line uses the move semantics.
|
||||||
internal.push_back(surface);
|
internal.push_back(surface);
|
||||||
polygons_append(fill_boundaries, STDMOVE(surface.expolygon));
|
polygons_append(fill_boundaries, STDMOVE(surface.expolygon));
|
||||||
} else if (internal_surface)
|
} else if (!surface.is_external())
|
||||||
internal.push_back(STDMOVE(surface));
|
internal.push_back(STDMOVE(surface));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -304,7 +303,7 @@ void LayerRegion::process_external_surfaces(const Layer* lower_layer)
|
|||||||
s2.clear();
|
s2.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (s1.surface_type == stTop)
|
if (s1.is_top())
|
||||||
// Trim the top surfaces by the bottom surfaces. This gives the priority to the bottom surfaces.
|
// Trim the top surfaces by the bottom surfaces. This gives the priority to the bottom surfaces.
|
||||||
polys = diff(polys, bottom_polygons);
|
polys = diff(polys, bottom_polygons);
|
||||||
surfaces_append(
|
surfaces_append(
|
||||||
@ -357,13 +356,13 @@ LayerRegion::prepare_fill_surfaces()
|
|||||||
// if no solid layers are requested, turn top/bottom surfaces to internal
|
// if no solid layers are requested, turn top/bottom surfaces to internal
|
||||||
if (this->region()->config.top_solid_layers == 0) {
|
if (this->region()->config.top_solid_layers == 0) {
|
||||||
for (Surfaces::iterator surface = this->fill_surfaces.surfaces.begin(); surface != this->fill_surfaces.surfaces.end(); ++surface)
|
for (Surfaces::iterator surface = this->fill_surfaces.surfaces.begin(); surface != this->fill_surfaces.surfaces.end(); ++surface)
|
||||||
if (surface->surface_type == stTop)
|
if (surface->is_top())
|
||||||
surface->surface_type = (this->layer()->object()->config.infill_only_where_needed) ?
|
surface->surface_type = (this->layer()->object()->config.infill_only_where_needed) ?
|
||||||
stInternalVoid : stInternal;
|
stInternalVoid : stInternal;
|
||||||
}
|
}
|
||||||
if (this->region()->config.bottom_solid_layers == 0) {
|
if (this->region()->config.bottom_solid_layers == 0) {
|
||||||
for (Surfaces::iterator surface = this->fill_surfaces.surfaces.begin(); surface != this->fill_surfaces.surfaces.end(); ++surface) {
|
for (Surfaces::iterator surface = this->fill_surfaces.surfaces.begin(); surface != this->fill_surfaces.surfaces.end(); ++surface) {
|
||||||
if (surface->surface_type == stBottom || surface->surface_type == stBottomBridge)
|
if (surface->is_bottom())
|
||||||
surface->surface_type = stInternal;
|
surface->surface_type = stInternal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -199,6 +199,7 @@ public:
|
|||||||
void process_external_surfaces();
|
void process_external_surfaces();
|
||||||
void discover_vertical_shells();
|
void discover_vertical_shells();
|
||||||
void bridge_over_infill();
|
void bridge_over_infill();
|
||||||
|
void replaceSurfaceType(SurfaceType st_to_replace, SurfaceType st_replacement, SurfaceType st_under_it);
|
||||||
void _make_perimeters();
|
void _make_perimeters();
|
||||||
void _infill();
|
void _infill();
|
||||||
void clip_fill_surfaces();
|
void clip_fill_surfaces();
|
||||||
|
@ -113,6 +113,17 @@ PrintConfigDef::PrintConfigDef()
|
|||||||
def->min = 0;
|
def->min = 0;
|
||||||
def->default_value = new ConfigOptionFloat(1);
|
def->default_value = new ConfigOptionFloat(1);
|
||||||
|
|
||||||
|
def = this->add("over_bridge_flow_ratio", coFloat);
|
||||||
|
def->label = L("Over-bridge flow ratio");
|
||||||
|
def->category = L("Advanced");
|
||||||
|
def->tooltip = L("This factor affects the amount of plastic to overextrude "
|
||||||
|
"when we are filling on top of a bridge surface."
|
||||||
|
"With a number >1, we can retreive the correct z-height "
|
||||||
|
"even if the bridged layer has fallen a bit.");
|
||||||
|
def->cli = "over-bridge-flow-ratio=f";
|
||||||
|
def->min = 0;
|
||||||
|
def->default_value = new ConfigOptionFloat(1);
|
||||||
|
|
||||||
def = this->add("bridge_speed", coFloat);
|
def = this->add("bridge_speed", coFloat);
|
||||||
def->label = L("Bridges");
|
def->label = L("Bridges");
|
||||||
def->category = L("Speed");
|
def->category = L("Speed");
|
||||||
@ -2013,6 +2024,10 @@ std::string FullPrintConfig::validate()
|
|||||||
if (this->bridge_flow_ratio <= 0)
|
if (this->bridge_flow_ratio <= 0)
|
||||||
return "Invalid value for --bridge-flow-ratio";
|
return "Invalid value for --bridge-flow-ratio";
|
||||||
|
|
||||||
|
// --over-bridge-flow-ratio
|
||||||
|
if (this->over_bridge_flow_ratio <= 0)
|
||||||
|
return "Invalid value for --over-bridge-flow-ratio";
|
||||||
|
|
||||||
// extruder clearance
|
// extruder clearance
|
||||||
if (this->extruder_clearance_radius <= 0)
|
if (this->extruder_clearance_radius <= 0)
|
||||||
return "Invalid value for --extruder-clearance-radius";
|
return "Invalid value for --extruder-clearance-radius";
|
||||||
|
@ -376,6 +376,7 @@ public:
|
|||||||
ConfigOptionFloat bridge_angle;
|
ConfigOptionFloat bridge_angle;
|
||||||
ConfigOptionInt bottom_solid_layers;
|
ConfigOptionInt bottom_solid_layers;
|
||||||
ConfigOptionFloat bridge_flow_ratio;
|
ConfigOptionFloat bridge_flow_ratio;
|
||||||
|
ConfigOptionFloat over_bridge_flow_ratio;
|
||||||
ConfigOptionFloat bridge_speed;
|
ConfigOptionFloat bridge_speed;
|
||||||
ConfigOptionBool ensure_vertical_shell_thickness;
|
ConfigOptionBool ensure_vertical_shell_thickness;
|
||||||
ConfigOptionEnum<InfillPattern> top_fill_pattern;
|
ConfigOptionEnum<InfillPattern> top_fill_pattern;
|
||||||
@ -416,6 +417,7 @@ protected:
|
|||||||
OPT_PTR(bridge_angle);
|
OPT_PTR(bridge_angle);
|
||||||
OPT_PTR(bottom_solid_layers);
|
OPT_PTR(bottom_solid_layers);
|
||||||
OPT_PTR(bridge_flow_ratio);
|
OPT_PTR(bridge_flow_ratio);
|
||||||
|
OPT_PTR(over_bridge_flow_ratio);
|
||||||
OPT_PTR(bridge_speed);
|
OPT_PTR(bridge_speed);
|
||||||
OPT_PTR(ensure_vertical_shell_thickness);
|
OPT_PTR(ensure_vertical_shell_thickness);
|
||||||
OPT_PTR(top_fill_pattern);
|
OPT_PTR(top_fill_pattern);
|
||||||
|
@ -363,10 +363,18 @@ void PrintObject::_prepare_infill()
|
|||||||
// the following step needs to be done before combination because it may need
|
// the following step needs to be done before combination because it may need
|
||||||
// to remove only half of the combined infill
|
// to remove only half of the combined infill
|
||||||
this->bridge_over_infill();
|
this->bridge_over_infill();
|
||||||
|
std::cout<<"INTERNAL BRIDGE ===========================================\n";
|
||||||
|
this->replaceSurfaceType( stInternalSolid, stInternalOverBridge, stInternalBridge);
|
||||||
|
std::cout<<"BOTTOM BRIDGE ===========================================\n";
|
||||||
|
this->replaceSurfaceType( stInternalSolid, stInternalOverBridge, stBottomBridge);
|
||||||
|
std::cout<<"TOP BRIDGE ===========================================\n";
|
||||||
|
this->replaceSurfaceType( stTop, stTopOverBridge, stInternalBridge);
|
||||||
|
this->replaceSurfaceType( stTop, stTopOverBridge, stBottomBridge);
|
||||||
|
|
||||||
// combine fill surfaces to honor the "infill every N layers" option
|
// combine fill surfaces to honor the "infill every N layers" option
|
||||||
this->combine_infill();
|
this->combine_infill();
|
||||||
|
|
||||||
|
|
||||||
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
||||||
for (size_t region_id = 0; region_id < this->print()->regions.size(); ++ region_id) {
|
for (size_t region_id = 0; region_id < this->print()->regions.size(); ++ region_id) {
|
||||||
for (const Layer *layer : this->layers) {
|
for (const Layer *layer : this->layers) {
|
||||||
@ -435,6 +443,7 @@ void PrintObject::detect_surfaces_type()
|
|||||||
// unless internal shells are requested
|
// unless internal shells are requested
|
||||||
Layer *upper_layer = (idx_layer + 1 < this->layer_count()) ? this->layers[idx_layer + 1] : nullptr;
|
Layer *upper_layer = (idx_layer + 1 < this->layer_count()) ? this->layers[idx_layer + 1] : nullptr;
|
||||||
Layer *lower_layer = (idx_layer > 0) ? this->layers[idx_layer - 1] : nullptr;
|
Layer *lower_layer = (idx_layer > 0) ? this->layers[idx_layer - 1] : nullptr;
|
||||||
|
Layer *under_lower_layer = (idx_layer > 1) ? this->layers[idx_layer - 2] : nullptr;
|
||||||
// collapse very narrow parts (using the safety offset in the diff is not enough)
|
// collapse very narrow parts (using the safety offset in the diff is not enough)
|
||||||
float offset = layerm->flow(frExternalPerimeter).scaled_width() / 10.f;
|
float offset = layerm->flow(frExternalPerimeter).scaled_width() / 10.f;
|
||||||
|
|
||||||
@ -478,6 +487,7 @@ void PrintObject::detect_surfaces_type()
|
|||||||
diff(layerm_slices_surfaces, to_polygons(lower_layer->slices), true),
|
diff(layerm_slices_surfaces, to_polygons(lower_layer->slices), true),
|
||||||
-offset, offset),
|
-offset, offset),
|
||||||
surface_type_bottom_other);
|
surface_type_bottom_other);
|
||||||
|
|
||||||
// if user requested internal shells, we need to identify surfaces
|
// if user requested internal shells, we need to identify surfaces
|
||||||
// lying on other slices not belonging to this region
|
// lying on other slices not belonging to this region
|
||||||
if (interface_shells) {
|
if (interface_shells) {
|
||||||
@ -494,6 +504,7 @@ void PrintObject::detect_surfaces_type()
|
|||||||
stBottom);
|
stBottom);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// if no lower layer, all surfaces of this one are solid
|
// if no lower layer, all surfaces of this one are solid
|
||||||
// we clone surfaces because we're going to clear the slices collection
|
// we clone surfaces because we're going to clear the slices collection
|
||||||
@ -502,6 +513,22 @@ void PrintObject::detect_surfaces_type()
|
|||||||
surface.surface_type = surface_type_bottom_1st;
|
surface.surface_type = surface_type_bottom_1st;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Any surface lying on the void is a true bottom bridge (an overhang)
|
||||||
|
// and we have to conpensate if we are over that
|
||||||
|
// Surfaces bottomOverBridge;
|
||||||
|
// if(under_lower_layer){
|
||||||
|
// surfaces_append(
|
||||||
|
// bottomOverBridge,
|
||||||
|
// offset2_ex(
|
||||||
|
// diff(layerm_slices_surfaces, to_polygons(under_lower_layer->slices), true),
|
||||||
|
// -offset, offset),
|
||||||
|
// stInternalOverBridge);
|
||||||
|
// std::cout<<idx_layer<<" under_lower_layer "<<under_lower_layer->slices.expolygons.size()<<" > "<<bottomOverBridge.size()<<", bot="<<bottom.size()<<"\n";
|
||||||
|
// for(int i=0;i<under_lower_layer->slices.expolygons.size();i++) std::cout<<" area of under_lower_layer "<<under_lower_layer->slices.expolygons[i].area()<<"\n";
|
||||||
|
// for(int i=0;i<bottom.size();i++) std::cout<<" area of bottom "<<bottom[i].area()<<"\n";
|
||||||
|
// for(int i=0;i<bottomOverBridge.size();i++) std::cout<<" area of overbridge "<<bottomOverBridge[i].area()<<"\n";
|
||||||
|
// }
|
||||||
|
|
||||||
// now, if the object contained a thin membrane, we could have overlapping bottom
|
// now, if the object contained a thin membrane, we could have overlapping bottom
|
||||||
// and top surfaces; let's do an intersection to discover them and consider them
|
// and top surfaces; let's do an intersection to discover them and consider them
|
||||||
// as bottom surfaces (to allow for bridge detection)
|
// as bottom surfaces (to allow for bridge detection)
|
||||||
@ -522,6 +549,7 @@ void PrintObject::detect_surfaces_type()
|
|||||||
std::vector<std::pair<Slic3r::ExPolygons, SVG::ExPolygonAttributes>> expolygons_with_attributes;
|
std::vector<std::pair<Slic3r::ExPolygons, SVG::ExPolygonAttributes>> expolygons_with_attributes;
|
||||||
expolygons_with_attributes.emplace_back(std::make_pair(union_ex(top), SVG::ExPolygonAttributes("green")));
|
expolygons_with_attributes.emplace_back(std::make_pair(union_ex(top), SVG::ExPolygonAttributes("green")));
|
||||||
expolygons_with_attributes.emplace_back(std::make_pair(union_ex(bottom), SVG::ExPolygonAttributes("brown")));
|
expolygons_with_attributes.emplace_back(std::make_pair(union_ex(bottom), SVG::ExPolygonAttributes("brown")));
|
||||||
|
expolygons_with_attributes.emplace_back(std::make_pair(union_ex(bottomOverBridge), SVG::ExPolygonAttributes("grey")));
|
||||||
expolygons_with_attributes.emplace_back(std::make_pair(to_expolygons(layerm->slices.surfaces), SVG::ExPolygonAttributes("black")));
|
expolygons_with_attributes.emplace_back(std::make_pair(to_expolygons(layerm->slices.surfaces), SVG::ExPolygonAttributes("black")));
|
||||||
SVG::export_expolygons(debug_out_path("1_detect_surfaces_type_%d_region%d-layer_%f.svg", iRun ++, idx_region, layer->print_z).c_str(), expolygons_with_attributes);
|
SVG::export_expolygons(debug_out_path("1_detect_surfaces_type_%d_region%d-layer_%f.svg", iRun ++, idx_region, layer->print_z).c_str(), expolygons_with_attributes);
|
||||||
}
|
}
|
||||||
@ -535,6 +563,12 @@ void PrintObject::detect_surfaces_type()
|
|||||||
{
|
{
|
||||||
Polygons topbottom = to_polygons(top);
|
Polygons topbottom = to_polygons(top);
|
||||||
polygons_append(topbottom, to_polygons(bottom));
|
polygons_append(topbottom, to_polygons(bottom));
|
||||||
|
// ExPolygons overExPolygons = diff_ex(to_polygons(bottomOverBridge), topbottom, false);
|
||||||
|
// surfaces_append(surfaces_out,
|
||||||
|
// overExPolygons,
|
||||||
|
// stInternalOverBridge);
|
||||||
|
// for(int i=0;i<overExPolygons.size();i++) std::cout<<" area of overExPolygons "<<overExPolygons[i].area()<<"\n";
|
||||||
|
// polygons_append(topbottom, to_polygons(bottomOverBridge));
|
||||||
surfaces_append(surfaces_out,
|
surfaces_append(surfaces_out,
|
||||||
diff_ex(layerm_slices_surfaces, topbottom, false),
|
diff_ex(layerm_slices_surfaces, topbottom, false),
|
||||||
stInternal);
|
stInternal);
|
||||||
@ -1106,6 +1140,178 @@ void PrintObject::bridge_over_infill()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* This method applies overextrude flow to the first internal solid layer above
|
||||||
|
bridge (which is over sparse infill) note: it's almost complete copy/paste from the method behind,
|
||||||
|
i think it should be merged before gitpull that.
|
||||||
|
*/
|
||||||
|
void PrintObject::replaceSurfaceType(SurfaceType st_to_replace, SurfaceType st_replacement, SurfaceType st_under_it)
|
||||||
|
{
|
||||||
|
BOOST_LOG_TRIVIAL(info) << "overextrude over Bridge...";
|
||||||
|
|
||||||
|
FOREACH_REGION(this->_print, region) {
|
||||||
|
size_t region_id = region - this->_print->regions.begin();
|
||||||
|
|
||||||
|
FOREACH_LAYER(this, layer_it) {
|
||||||
|
// skip first layer
|
||||||
|
if (layer_it == this->layers.begin()) continue;
|
||||||
|
|
||||||
|
Layer* layer = *layer_it;
|
||||||
|
LayerRegion* layerm = layer->regions[region_id];
|
||||||
|
|
||||||
|
// extract the stInternalSolid surfaces that might be transformed into bridges
|
||||||
|
Polygons internal_solid;
|
||||||
|
layerm->fill_surfaces.filter_by_type(st_to_replace, &internal_solid);
|
||||||
|
|
||||||
|
double internsolidareainit=0;
|
||||||
|
for (ExPolygon &ex : union_ex(internal_solid)) internsolidareainit+=ex.area();
|
||||||
|
|
||||||
|
Polygons internal_over_tot_init;
|
||||||
|
layerm->fill_surfaces.filter_by_type(st_replacement, &internal_over_tot_init);
|
||||||
|
double totoverareaInit=0;
|
||||||
|
for (ExPolygon &ex : union_ex(internal_over_tot_init)) totoverareaInit+=ex.area();
|
||||||
|
|
||||||
|
Polygons stBottom_init;
|
||||||
|
layerm->fill_surfaces.filter_by_type(stBottom, &stBottom_init);
|
||||||
|
double bottomeareainit=0;
|
||||||
|
for (ExPolygon &ex : union_ex(stBottom_init)) bottomeareainit+=ex.area();
|
||||||
|
|
||||||
|
Polygons stBottomBridge_init;
|
||||||
|
layerm->fill_surfaces.filter_by_type(stBottomBridge, &stBottomBridge_init);
|
||||||
|
double bottombridgearea=0;
|
||||||
|
for (ExPolygon &ex : union_ex(stBottomBridge_init)) bottombridgearea+=ex.area();
|
||||||
|
|
||||||
|
Polygons stIntBridge_init;
|
||||||
|
layerm->fill_surfaces.filter_by_type(st_under_it, &stIntBridge_init);
|
||||||
|
double intbridgeareainit=0;
|
||||||
|
for (ExPolygon &ex : union_ex(stIntBridge_init)) intbridgeareainit+=ex.area();
|
||||||
|
|
||||||
|
std::cout<<"init st_replacement="<<totoverareaInit<<", bottombridgearea="<<bottombridgearea
|
||||||
|
<<", st_to_replace="<<internsolidareainit<<", bottomeareainit="<<bottomeareainit
|
||||||
|
<<", st_under_it="<<intbridgeareainit<<"\n";
|
||||||
|
|
||||||
|
// check whether the lower area is deep enough for absorbing the extra flow
|
||||||
|
// (for obvious physical reasons but also for preventing the bridge extrudates
|
||||||
|
// from overflowing in 3D preview)
|
||||||
|
ExPolygons to_overextrude;
|
||||||
|
{
|
||||||
|
Polygons to_overextrude_pp = internal_solid;
|
||||||
|
|
||||||
|
// get previous layer
|
||||||
|
if (int(layer_it - this->layers.begin()) - 1 >= 0) {
|
||||||
|
const Layer* lower_layer = this->layers[int(layer_it - this->layers.begin()) - 1];
|
||||||
|
|
||||||
|
// iterate through regions and collect internal surfaces
|
||||||
|
Polygons lower_internal;
|
||||||
|
FOREACH_LAYERREGION(lower_layer, lower_layerm_it){
|
||||||
|
Polygons lower_internal_OK;
|
||||||
|
Polygons lower_internal_Bridge;
|
||||||
|
Polygons lower_internal_Over;
|
||||||
|
(*lower_layerm_it)->fill_surfaces.filter_by_type(st_replacement, &lower_internal_OK);
|
||||||
|
(*lower_layerm_it)->fill_surfaces.filter_by_type(st_under_it, &lower_internal_Bridge);
|
||||||
|
(*lower_layerm_it)->fill_surfaces.filter_by_type(st_to_replace, &lower_internal_Over);
|
||||||
|
double okarea =0, bridgearea=0, overarea=0;
|
||||||
|
for (ExPolygon &ex : union_ex(lower_internal_OK)) okarea+=ex.area();
|
||||||
|
for (ExPolygon &ex : union_ex(lower_internal_Bridge)) bridgearea+=ex.area();
|
||||||
|
for (ExPolygon &ex : union_ex(lower_internal_Over)) overarea+=ex.area();
|
||||||
|
std::cout<<"@layer "<<int(layer_it - this->layers.begin())
|
||||||
|
<<" region under has "<<lower_internal_OK.size()<<" st_replacement : "<<okarea
|
||||||
|
<<" , has "<<lower_internal_Bridge.size()<<" st_under_it: "<<bridgearea
|
||||||
|
<<" , has "<<lower_internal_Over.size()<<" st_to_replace: "<<overarea<<"\n";
|
||||||
|
(*lower_layerm_it)->fill_surfaces.filter_by_type(st_under_it, &lower_internal);
|
||||||
|
}
|
||||||
|
double sumarea=0;
|
||||||
|
for (ExPolygon &ex : union_ex(lower_internal)) sumarea+=ex.area();
|
||||||
|
std::cout<<"@layer "<<int(layer_it - this->layers.begin())<<" region under has "<<union_ex(lower_internal).size()<<" sum bridge : "<<sumarea<<"\n";
|
||||||
|
|
||||||
|
// intersect such lower internal surfaces with the candidate solid surfaces
|
||||||
|
to_overextrude_pp = intersection(to_overextrude_pp, lower_internal);
|
||||||
|
}
|
||||||
|
|
||||||
|
// there's no point in overextruding too thin/short regions
|
||||||
|
//FIXME Vojtech: The offset2 function is not a geometric offset,
|
||||||
|
// therefore it may create 1) gaps, and 2) sharp corners, which are outside the original contour.
|
||||||
|
// The gaps will be filled by a separate region, which makes the infill less stable and it takes longer.
|
||||||
|
// {
|
||||||
|
// float min_width = float(bridge_flow.scaled_width()) * 3.f;
|
||||||
|
// to_overextrude_pp = offset2(to_overextrude_pp, -min_width, +min_width);
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (to_overextrude_pp.empty()) continue;
|
||||||
|
|
||||||
|
// convert into ExPolygons
|
||||||
|
to_overextrude = union_ex(to_overextrude_pp);
|
||||||
|
double finalarea = 0;
|
||||||
|
for (ExPolygon &ex : to_overextrude) finalarea+=ex.area();
|
||||||
|
std::cout<<"find an overextruding area of "<<finalarea<<" on layer "<<int(layer_it - this->layers.begin())<<"\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef SLIC3R_DEBUG
|
||||||
|
printf("Bridging " PRINTF_ZU " internal areas at layer " PRINTF_ZU "\n", to_overextrude.size(), layer->id());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// compute the remaning internal solid surfaces as difference
|
||||||
|
ExPolygons not_to_overextrude = diff_ex(internal_solid, to_polygons(to_overextrude), true);
|
||||||
|
to_overextrude = intersection_ex(to_polygons(to_overextrude), internal_solid, true);
|
||||||
|
// build the new collection of fill_surfaces
|
||||||
|
layerm->fill_surfaces.remove_type(st_to_replace);
|
||||||
|
double overareafinal = 0, solidareafinal=0;
|
||||||
|
for (ExPolygon &ex : to_overextrude){
|
||||||
|
overareafinal += ex.area();
|
||||||
|
layerm->fill_surfaces.surfaces.push_back(Surface(st_replacement, ex));
|
||||||
|
}
|
||||||
|
for (ExPolygon &ex : not_to_overextrude){
|
||||||
|
solidareafinal += ex.area();
|
||||||
|
layerm->fill_surfaces.surfaces.push_back(Surface(st_to_replace, ex));
|
||||||
|
}
|
||||||
|
Polygons internal_over_tot;
|
||||||
|
layerm->fill_surfaces.filter_by_type(stInternalOverBridge, &internal_over_tot);
|
||||||
|
double totoverarea=0;
|
||||||
|
for (ExPolygon &ex : union_ex(internal_over_tot)) totoverarea+=ex.area();
|
||||||
|
std::cout<<"final: st_to_replace="<<solidareafinal<<", st_replacement="<<overareafinal<<", totstInternalOverBridge="<<totoverarea<<"\n";
|
||||||
|
/*
|
||||||
|
# exclude infill from the layers below if needed
|
||||||
|
# see discussion at https://github.com/alexrj/Slic3r/issues/240
|
||||||
|
# Update: do not exclude any infill. Sparse infill is able to absorb the excess material.
|
||||||
|
if (0) {
|
||||||
|
my $excess = $layerm->extruders->{infill}->bridge_flow->width - $layerm->height;
|
||||||
|
for (my $i = $layer_id-1; $excess >= $self->get_layer($i)->height; $i--) {
|
||||||
|
Slic3r::debugf " skipping infill below those areas at layer %d\n", $i;
|
||||||
|
foreach my $lower_layerm (@{$self->get_layer($i)->regions}) {
|
||||||
|
my @new_surfaces = ();
|
||||||
|
# subtract the area from all types of surfaces
|
||||||
|
foreach my $group (@{$lower_layerm->fill_surfaces->group}) {
|
||||||
|
push @new_surfaces, map $group->[0]->clone(expolygon => $_),
|
||||||
|
@{diff_ex(
|
||||||
|
[ map $_->p, @$group ],
|
||||||
|
[ map @$_, @$to_overextrude ],
|
||||||
|
)};
|
||||||
|
push @new_surfaces, map Slic3r::Surface->new(
|
||||||
|
expolygon => $_,
|
||||||
|
surface_type => S_TYPE_INTERNALVOID,
|
||||||
|
), @{intersection_ex(
|
||||||
|
[ map $_->p, @$group ],
|
||||||
|
[ map @$_, @$to_overextrude ],
|
||||||
|
)};
|
||||||
|
}
|
||||||
|
$lower_layerm->fill_surfaces->clear;
|
||||||
|
$lower_layerm->fill_surfaces->append($_) for @new_surfaces;
|
||||||
|
}
|
||||||
|
|
||||||
|
$excess -= $self->get_layer($i)->height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
||||||
|
layerm->export_region_slices_to_svg_debug("7_overextrude_over_bridge");
|
||||||
|
layerm->export_region_fill_surfaces_to_svg_debug("7_overextrude_over_bridge");
|
||||||
|
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
SlicingParameters PrintObject::slicing_parameters() const
|
SlicingParameters PrintObject::slicing_parameters() const
|
||||||
{
|
{
|
||||||
return SlicingParameters::create_from_config(
|
return SlicingParameters::create_from_config(
|
||||||
@ -1699,8 +1905,8 @@ void PrintObject::discover_horizontal_shells()
|
|||||||
continue;
|
continue;
|
||||||
// Slic3r::debugf "Layer %d has %s surfaces\n", $i, ($type == S_TYPE_TOP) ? 'top' : 'bottom';
|
// Slic3r::debugf "Layer %d has %s surfaces\n", $i, ($type == S_TYPE_TOP) ? 'top' : 'bottom';
|
||||||
|
|
||||||
size_t solid_layers = (type == stTop) ? region_config.top_solid_layers.value : region_config.bottom_solid_layers.value;
|
size_t solid_layers = (type == stTop || type == stTopOverBridge) ? region_config.top_solid_layers.value : region_config.bottom_solid_layers.value;
|
||||||
for (int n = (type == stTop) ? i-1 : i+1; std::abs(n - i) < solid_layers; (type == stTop) ? -- n : ++ n) {
|
for (int n = (type == stTop || type == stTopOverBridge) ? i-1 : i+1; std::abs(n - i) < solid_layers; (type == stTop || type == stTopOverBridge) ? -- n : ++ n) {
|
||||||
if (n < 0 || n >= int(this->layers.size()))
|
if (n < 0 || n >= int(this->layers.size()))
|
||||||
continue;
|
continue;
|
||||||
// Slic3r::debugf " looking for neighbors on layer %d...\n", $n;
|
// Slic3r::debugf " looking for neighbors on layer %d...\n", $n;
|
||||||
|
@ -22,7 +22,9 @@ Surface::is_solid() const
|
|||||||
|| this->surface_type == stBottom
|
|| this->surface_type == stBottom
|
||||||
|| this->surface_type == stBottomBridge
|
|| this->surface_type == stBottomBridge
|
||||||
|| this->surface_type == stInternalSolid
|
|| this->surface_type == stInternalSolid
|
||||||
|| this->surface_type == stInternalBridge;
|
|| this->surface_type == stInternalBridge
|
||||||
|
|| this->surface_type == stInternalOverBridge
|
||||||
|
|| this->surface_type == stTopOverBridge;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -30,7 +32,15 @@ Surface::is_external() const
|
|||||||
{
|
{
|
||||||
return this->surface_type == stTop
|
return this->surface_type == stTop
|
||||||
|| this->surface_type == stBottom
|
|| this->surface_type == stBottom
|
||||||
|| this->surface_type == stBottomBridge;
|
|| this->surface_type == stBottomBridge
|
||||||
|
|| this->surface_type == stTopOverBridge;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Surface::is_top() const
|
||||||
|
{
|
||||||
|
return this->surface_type == stTop
|
||||||
|
|| this->surface_type == stTopOverBridge;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -38,6 +48,7 @@ Surface::is_internal() const
|
|||||||
{
|
{
|
||||||
return this->surface_type == stInternal
|
return this->surface_type == stInternal
|
||||||
|| this->surface_type == stInternalBridge
|
|| this->surface_type == stInternalBridge
|
||||||
|
|| this->surface_type == stInternalOverBridge
|
||||||
|| this->surface_type == stInternalSolid
|
|| this->surface_type == stInternalSolid
|
||||||
|| this->surface_type == stInternalVoid;
|
|| this->surface_type == stInternalVoid;
|
||||||
}
|
}
|
||||||
@ -55,6 +66,12 @@ Surface::is_bridge() const
|
|||||||
return this->surface_type == stBottomBridge
|
return this->surface_type == stBottomBridge
|
||||||
|| this->surface_type == stInternalBridge;
|
|| this->surface_type == stInternalBridge;
|
||||||
}
|
}
|
||||||
|
bool
|
||||||
|
Surface::is_overBridge() const
|
||||||
|
{
|
||||||
|
return this->surface_type == stInternalOverBridge
|
||||||
|
|| this->surface_type == stTopOverBridge;
|
||||||
|
}
|
||||||
|
|
||||||
BoundingBox get_extents(const Surface &surface)
|
BoundingBox get_extents(const Surface &surface)
|
||||||
{
|
{
|
||||||
@ -91,7 +108,8 @@ const char* surface_type_to_color_name(const SurfaceType surface_type)
|
|||||||
case stBottomBridge: return "rgb(0,0,255)"; // "blue";
|
case stBottomBridge: return "rgb(0,0,255)"; // "blue";
|
||||||
case stInternal: return "rgb(255,255,128)"; // yellow
|
case stInternal: return "rgb(255,255,128)"; // yellow
|
||||||
case stInternalSolid: return "rgb(255,0,255)"; // magenta
|
case stInternalSolid: return "rgb(255,0,255)"; // magenta
|
||||||
case stInternalBridge: return "rgb(0,255,255)";
|
case stInternalBridge: return "rgb(0,255,255)"; // cyan
|
||||||
|
case stInternalOverBridge: return "rgb(0,255,128)"; // green-cyan
|
||||||
case stInternalVoid: return "rgb(128,128,128)";
|
case stInternalVoid: return "rgb(128,128,128)";
|
||||||
case stPerimeter: return "rgb(128,0,0)"; // maroon
|
case stPerimeter: return "rgb(128,0,0)"; // maroon
|
||||||
default: return "rgb(64,64,64)";
|
default: return "rgb(64,64,64)";
|
||||||
@ -128,6 +146,8 @@ void export_surface_type_legend_to_svg(SVG &svg, const Point &pos)
|
|||||||
pos_x += step_x;
|
pos_x += step_x;
|
||||||
svg.draw_legend(Point(pos_x, pos_y), "internal bridge", surface_type_to_color_name(stInternalBridge));
|
svg.draw_legend(Point(pos_x, pos_y), "internal bridge", surface_type_to_color_name(stInternalBridge));
|
||||||
pos_x += step_x;
|
pos_x += step_x;
|
||||||
|
svg.draw_legend(Point(pos_x, pos_y), "internal over bridge", surface_type_to_color_name(stInternalOverBridge));
|
||||||
|
pos_x += step_x;
|
||||||
svg.draw_legend(Point(pos_x, pos_y), "internal void" , surface_type_to_color_name(stInternalVoid));
|
svg.draw_legend(Point(pos_x, pos_y), "internal void" , surface_type_to_color_name(stInternalVoid));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,9 @@ enum SurfaceType {
|
|||||||
stInternalSolid,
|
stInternalSolid,
|
||||||
// 1st layer of dense infill over sparse infill, printed with a bridging extrusion flow.
|
// 1st layer of dense infill over sparse infill, printed with a bridging extrusion flow.
|
||||||
stInternalBridge,
|
stInternalBridge,
|
||||||
|
// 2nd layer of dense infill over sparse infill/nothing, printed with an over-extruding flow.
|
||||||
|
stInternalOverBridge,
|
||||||
|
stTopOverBridge,
|
||||||
// stInternal turns into void surfaces if the sparse infill is used for supports only,
|
// stInternal turns into void surfaces if the sparse infill is used for supports only,
|
||||||
// or if sparse infill layers get combined into a single layer.
|
// or if sparse infill layers get combined into a single layer.
|
||||||
stInternalVoid,
|
stInternalVoid,
|
||||||
@ -97,9 +100,11 @@ public:
|
|||||||
void clear() { expolygon.clear(); }
|
void clear() { expolygon.clear(); }
|
||||||
bool is_solid() const;
|
bool is_solid() const;
|
||||||
bool is_external() const;
|
bool is_external() const;
|
||||||
|
bool is_top() const;
|
||||||
bool is_internal() const;
|
bool is_internal() const;
|
||||||
bool is_bottom() const;
|
bool is_bottom() const;
|
||||||
bool is_bridge() const;
|
bool is_bridge() const;
|
||||||
|
bool is_overBridge() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector<Surface> Surfaces;
|
typedef std::vector<Surface> Surfaces;
|
||||||
|
@ -197,7 +197,8 @@ const std::vector<std::string>& Preset::print_options()
|
|||||||
"infill_extruder", "solid_infill_extruder", "support_material_extruder", "support_material_interface_extruder",
|
"infill_extruder", "solid_infill_extruder", "support_material_extruder", "support_material_interface_extruder",
|
||||||
"ooze_prevention", "standby_temperature_delta", "interface_shells", "extrusion_width", "first_layer_extrusion_width",
|
"ooze_prevention", "standby_temperature_delta", "interface_shells", "extrusion_width", "first_layer_extrusion_width",
|
||||||
"perimeter_extrusion_width", "external_perimeter_extrusion_width", "infill_extrusion_width", "solid_infill_extrusion_width",
|
"perimeter_extrusion_width", "external_perimeter_extrusion_width", "infill_extrusion_width", "solid_infill_extrusion_width",
|
||||||
"top_infill_extrusion_width", "support_material_extrusion_width", "infill_overlap", "bridge_flow_ratio", "clip_multipart_objects",
|
"top_infill_extrusion_width", "support_material_extrusion_width", "infill_overlap", "bridge_flow_ratio",
|
||||||
|
"over_bridge_flow_ratio", "clip_multipart_objects",
|
||||||
"elefant_foot_compensation", "xy_size_compensation", "threads", "resolution", "wipe_tower", "wipe_tower_x", "wipe_tower_y",
|
"elefant_foot_compensation", "xy_size_compensation", "threads", "resolution", "wipe_tower", "wipe_tower_x", "wipe_tower_y",
|
||||||
"wipe_tower_width", "wipe_tower_per_color_wipe", "only_one_perimeter_top",
|
"wipe_tower_width", "wipe_tower_per_color_wipe", "only_one_perimeter_top",
|
||||||
"compatible_printers", "compatible_printers_condition"
|
"compatible_printers", "compatible_printers_condition"
|
||||||
|
@ -84,6 +84,7 @@ std::string PresetHints::maximum_volumetric_flow_description(const PresetBundle
|
|||||||
double support_material_interface_speed = print_config.get_abs_value("support_material_interface_speed", support_material_speed);
|
double support_material_interface_speed = print_config.get_abs_value("support_material_interface_speed", support_material_speed);
|
||||||
double bridge_speed = print_config.opt_float("bridge_speed");
|
double bridge_speed = print_config.opt_float("bridge_speed");
|
||||||
double bridge_flow_ratio = print_config.opt_float("bridge_flow_ratio");
|
double bridge_flow_ratio = print_config.opt_float("bridge_flow_ratio");
|
||||||
|
double over_bridge_flow_ratio = print_config.opt_float("over_bridge_flow_ratio");
|
||||||
double perimeter_speed = print_config.opt_float("perimeter_speed");
|
double perimeter_speed = print_config.opt_float("perimeter_speed");
|
||||||
double external_perimeter_speed = print_config.get_abs_value("external_perimeter_speed", perimeter_speed);
|
double external_perimeter_speed = print_config.get_abs_value("external_perimeter_speed", perimeter_speed);
|
||||||
double gap_fill_speed = print_config.opt_float("gap_fill_speed");
|
double gap_fill_speed = print_config.opt_float("gap_fill_speed");
|
||||||
|
@ -538,6 +538,7 @@ void TabPrint::build()
|
|||||||
|
|
||||||
optgroup = page->new_optgroup(_(L("Flow")));
|
optgroup = page->new_optgroup(_(L("Flow")));
|
||||||
optgroup->append_single_option_line("bridge_flow_ratio");
|
optgroup->append_single_option_line("bridge_flow_ratio");
|
||||||
|
optgroup->append_single_option_line("over_bridge_flow_ratio");
|
||||||
|
|
||||||
optgroup = page->new_optgroup(_(L("Other")));
|
optgroup = page->new_optgroup(_(L("Other")));
|
||||||
optgroup->append_single_option_line("clip_multipart_objects");
|
optgroup->append_single_option_line("clip_multipart_objects");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user