overextruding a bit on top of bridge to come back to a correct height

This commit is contained in:
Merill 2018-03-21 22:19:42 +01:00
parent f22db7efbe
commit 2749c63b10
15 changed files with 281 additions and 21 deletions

View File

@ -34,6 +34,7 @@ avoid_crossing_perimeters = 0
bridge_acceleration = 1000
bridge_angle = 0
bridge_flow_ratio = 0.8
over_bridge_flow_ratio = 1.2
bridge_speed = 20
brim_width = 0
clip_multipart_objects = 1

View File

@ -531,6 +531,7 @@ Usage: slic3r.pl [ OPTIONS ] [ file.stl ] [ file2.stl ] ...
Set a different extrusion width for support material
--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})
--over-bridge-flow-ratio Multiplier for extrusion when solid-filling over a bridge (> 0, default: $config->{over_bridge_flow_ratio})
Multiple extruder options:
--extruder-offset Offset of each extruder, if firmware doesn't handle the displacement

View File

@ -44,6 +44,7 @@ use Slic3r::Test;
my $config = Slic3r::Config::new_from_defaults;
$config->set('bridge_speed', 99);
$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('first_layer_speed', '100%'); # to prevent speeds from being altered

View File

@ -248,6 +248,7 @@ use Slic3r::Test;
$config->set('slowdown_below_layer_time', [ 0 ]);
$config->set('bridge_fan_speed', [ 100 ]);
$config->set('bridge_flow_ratio', 33); # arbitrary value
$config->set('over_bridge_flow_ratio', 110); # arbitrary value
$config->set('overhangs', 1);
my $print = Slic3r::Test::init_print('overhang', config => $config);
my %layer_speeds = (); # print Z => [ speeds ]

View File

@ -63,14 +63,14 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
// (we'll use them for comparing compatible groups)
std::vector<SurfaceGroupAttrib> group_attrib(groups.size());
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
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].flow_width = (surface.surface_type == stTop) ? 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.surface_type == stBottom && surface.is_external()) ? layerm.region()->config.bottom_fill_pattern.value : ipRectilinear;
group_attrib[i].flow_width = (surface.is_top()) ? top_solid_infill_flow.width : solid_infill_flow.width;
group_attrib[i].pattern = (surface.is_top() && surface.is_external()) ? layerm.region()->config.top_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.
@ -155,14 +155,14 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
continue;
InfillPattern fill_pattern = layerm.region()->config.fill_pattern.value;
double density = fill_density;
FlowRole role = (surface.surface_type == stTop) ? frTopSolidInfill :
FlowRole role = (surface.is_top()) ? frTopSolidInfill :
(surface.is_solid() ? frSolidInfill : frInfill);
bool is_bridge = layerm.layer()->id() > 0 && surface.is_bridge();
if (surface.is_solid()) {
density = 100.;
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;
} else if (density <= 0)
continue;
@ -241,6 +241,11 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
} else {
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.
auto *eec = new ExtrusionEntityCollection();
@ -254,7 +259,7 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
(surface.is_solid() ?
((surface.surface_type == stTop) ? erTopSolidInfill : erSolidInfill) :
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

View File

@ -121,7 +121,7 @@ void LayerRegion::process_external_surfaces(const Layer* lower_layer)
fill_boundaries.reserve(number_polygons(surfaces));
bool has_infill = this->region()->config.fill_density.value > 0.;
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.
// This gives the priority to bottom surfaces.
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())
bridges.push_back(surface);
}
bool internal_surface = surface.surface_type != stTop && ! surface.is_bottom();
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.
internal.push_back(surface);
polygons_append(fill_boundaries, STDMOVE(surface.expolygon));
} else if (internal_surface)
} else if (!surface.is_external())
internal.push_back(STDMOVE(surface));
}
}
@ -304,7 +303,7 @@ void LayerRegion::process_external_surfaces(const Layer* lower_layer)
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.
polys = diff(polys, bottom_polygons);
surfaces_append(
@ -357,13 +356,13 @@ LayerRegion::prepare_fill_surfaces()
// if no solid layers are requested, turn top/bottom surfaces to internal
if (this->region()->config.top_solid_layers == 0) {
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) ?
stInternalVoid : stInternal;
}
if (this->region()->config.bottom_solid_layers == 0) {
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;
}
}

View File

@ -199,6 +199,7 @@ public:
void process_external_surfaces();
void discover_vertical_shells();
void bridge_over_infill();
void replaceSurfaceType(SurfaceType st_to_replace, SurfaceType st_replacement, SurfaceType st_under_it);
void _make_perimeters();
void _infill();
void clip_fill_surfaces();

View File

@ -113,6 +113,17 @@ PrintConfigDef::PrintConfigDef()
def->min = 0;
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->label = L("Bridges");
def->category = L("Speed");
@ -2013,6 +2024,10 @@ std::string FullPrintConfig::validate()
if (this->bridge_flow_ratio <= 0)
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
if (this->extruder_clearance_radius <= 0)
return "Invalid value for --extruder-clearance-radius";

View File

@ -376,6 +376,7 @@ public:
ConfigOptionFloat bridge_angle;
ConfigOptionInt bottom_solid_layers;
ConfigOptionFloat bridge_flow_ratio;
ConfigOptionFloat over_bridge_flow_ratio;
ConfigOptionFloat bridge_speed;
ConfigOptionBool ensure_vertical_shell_thickness;
ConfigOptionEnum<InfillPattern> top_fill_pattern;
@ -416,6 +417,7 @@ protected:
OPT_PTR(bridge_angle);
OPT_PTR(bottom_solid_layers);
OPT_PTR(bridge_flow_ratio);
OPT_PTR(over_bridge_flow_ratio);
OPT_PTR(bridge_speed);
OPT_PTR(ensure_vertical_shell_thickness);
OPT_PTR(top_fill_pattern);

View File

@ -363,10 +363,18 @@ void PrintObject::_prepare_infill()
// the following step needs to be done before combination because it may need
// to remove only half of the combined 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
this->combine_infill();
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
for (size_t region_id = 0; region_id < this->print()->regions.size(); ++ region_id) {
for (const Layer *layer : this->layers) {
@ -435,6 +443,7 @@ void PrintObject::detect_surfaces_type()
// unless internal shells are requested
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 *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)
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),
-offset, offset),
surface_type_bottom_other);
// if user requested internal shells, we need to identify surfaces
// lying on other slices not belonging to this region
if (interface_shells) {
@ -494,6 +504,7 @@ void PrintObject::detect_surfaces_type()
stBottom);
}
#endif
} else {
// if no lower layer, all surfaces of this one are solid
// we clone surfaces because we're going to clear the slices collection
@ -501,6 +512,22 @@ void PrintObject::detect_surfaces_type()
for (Surface &surface : bottom)
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
// and top surfaces; let's do an intersection to discover them and consider them
@ -522,6 +549,7 @@ void PrintObject::detect_surfaces_type()
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(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")));
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_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,
diff_ex(layerm_slices_surfaces, topbottom, false),
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
{
return SlicingParameters::create_from_config(
@ -1699,8 +1905,8 @@ void PrintObject::discover_horizontal_shells()
continue;
// 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;
for (int n = (type == stTop) ? i-1 : i+1; std::abs(n - i) < solid_layers; (type == stTop) ? -- n : ++ n) {
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 || 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()))
continue;
// Slic3r::debugf " looking for neighbors on layer %d...\n", $n;

View File

@ -22,7 +22,9 @@ Surface::is_solid() const
|| this->surface_type == stBottom
|| this->surface_type == stBottomBridge
|| this->surface_type == stInternalSolid
|| this->surface_type == stInternalBridge;
|| this->surface_type == stInternalBridge
|| this->surface_type == stInternalOverBridge
|| this->surface_type == stTopOverBridge;
}
bool
@ -30,7 +32,15 @@ Surface::is_external() const
{
return this->surface_type == stTop
|| 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
@ -38,6 +48,7 @@ Surface::is_internal() const
{
return this->surface_type == stInternal
|| this->surface_type == stInternalBridge
|| this->surface_type == stInternalOverBridge
|| this->surface_type == stInternalSolid
|| this->surface_type == stInternalVoid;
}
@ -55,6 +66,12 @@ Surface::is_bridge() const
return this->surface_type == stBottomBridge
|| this->surface_type == stInternalBridge;
}
bool
Surface::is_overBridge() const
{
return this->surface_type == stInternalOverBridge
|| this->surface_type == stTopOverBridge;
}
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 stInternal: return "rgb(255,255,128)"; // yellow
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 stPerimeter: return "rgb(128,0,0)"; // maroon
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;
svg.draw_legend(Point(pos_x, pos_y), "internal bridge", surface_type_to_color_name(stInternalBridge));
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));
}

View File

@ -19,6 +19,9 @@ enum SurfaceType {
stInternalSolid,
// 1st layer of dense infill over sparse infill, printed with a bridging extrusion flow.
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,
// or if sparse infill layers get combined into a single layer.
stInternalVoid,
@ -97,9 +100,11 @@ public:
void clear() { expolygon.clear(); }
bool is_solid() const;
bool is_external() const;
bool is_top() const;
bool is_internal() const;
bool is_bottom() const;
bool is_bridge() const;
bool is_overBridge() const;
};
typedef std::vector<Surface> Surfaces;

View File

@ -197,7 +197,8 @@ const std::vector<std::string>& Preset::print_options()
"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",
"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",
"wipe_tower_width", "wipe_tower_per_color_wipe", "only_one_perimeter_top",
"compatible_printers", "compatible_printers_condition"

View File

@ -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 bridge_speed = print_config.opt_float("bridge_speed");
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 external_perimeter_speed = print_config.get_abs_value("external_perimeter_speed", perimeter_speed);
double gap_fill_speed = print_config.opt_float("gap_fill_speed");

View File

@ -538,6 +538,7 @@ void TabPrint::build()
optgroup = page->new_optgroup(_(L("Flow")));
optgroup->append_single_option_line("bridge_flow_ratio");
optgroup->append_single_option_line("over_bridge_flow_ratio");
optgroup = page->new_optgroup(_(L("Other")));
optgroup->append_single_option_line("clip_multipart_objects");