Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/supermerill/SuperSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsupermerill <merill@free.fr>2021-11-17 02:39:46 +0300
committersupermerill <merill@free.fr>2021-11-18 03:05:09 +0300
commit0d25f9b266ebe279a14e1a494bb60262f8ff9f2f (patch)
treecdf1dc8f70d37d3f59163cc3e2823a0a10df5eb1
parent282db5bd4f623e7d49648b6b4a056e7250df65af (diff)
bridge_overlap fix & redesign
* now has a min setting. * the density can be chosen between the two values, with the highest density possible. * remove the hardcoded 87.5% density modifier. Replaced by a max of 90% and a min of 80% * try to place the bridge at the right position (only works if the shape is simple). FIXME: bridge can be printed on top of the previous one (if began in the wrong direction, or it has a odd number and need to go back to the same side) try to mitigate that.
-rw-r--r--resources/ui_layout/print.ui5
-rw-r--r--src/libslic3r/Fill/Fill.cpp69
-rw-r--r--src/libslic3r/Fill/FillBase.cpp7
-rw-r--r--src/libslic3r/Fill/FillBase.hpp11
-rw-r--r--src/libslic3r/Fill/FillConcentric.cpp2
-rw-r--r--src/libslic3r/Fill/FillConcentric.hpp2
-rw-r--r--src/libslic3r/Fill/FillLine.cpp4
-rw-r--r--src/libslic3r/Fill/FillLine.hpp2
-rw-r--r--src/libslic3r/Fill/FillRectilinear.cpp26
-rw-r--r--src/libslic3r/Fill/FillRectilinear.hpp2
-rw-r--r--src/libslic3r/Fill/FillSmooth.cpp5
-rw-r--r--src/libslic3r/Flow.cpp8
-rw-r--r--src/libslic3r/Flow.hpp3
-rw-r--r--src/libslic3r/Preset.cpp1
-rw-r--r--src/libslic3r/PrintConfig.cpp30
-rw-r--r--src/libslic3r/PrintConfig.hpp2
-rw-r--r--src/slic3r/GUI/ConfigManipulation.cpp1
-rw-r--r--src/slic3r/GUI/Field.cpp180
-rw-r--r--src/slic3r/GUI/Field.hpp4
19 files changed, 231 insertions, 133 deletions
diff --git a/resources/ui_layout/print.ui b/resources/ui_layout/print.ui
index 2eb5ff0d6..b5f893b70 100644
--- a/resources/ui_layout/print.ui
+++ b/resources/ui_layout/print.ui
@@ -321,8 +321,11 @@ group:Overlap
setting:label$External:external_perimeter_overlap
setting:label$Gap Fill:gap_fill_overlap
end_line
+ line:Bridge lines density
+ setting:bridge_overlap_min
+ setting:bridge_overlap
+ end_line
setting:sidetext_width$7:infill_overlap
- setting:bridge_overlap
group:Flow
line:Flow ratio
setting:bridge_flow_ratio
diff --git a/src/libslic3r/Fill/Fill.cpp b/src/libslic3r/Fill/Fill.cpp
index 9f0030fa3..aa1b38d76 100644
--- a/src/libslic3r/Fill/Fill.cpp
+++ b/src/libslic3r/Fill/Fill.cpp
@@ -23,9 +23,9 @@ struct SurfaceFillParams : FillParams
// FillBase
// in unscaled coordinates
- coordf_t spacing = 0.;
+ double spacing = 0.;
// infill / perimeter overlap, in unscaled coordinates
- coordf_t overlap = 0.;
+ double overlap = 0.;
// Angle as provided by the region config, in radians.
float angle = 0.f;
// Non-negative for a bridge.
@@ -435,6 +435,7 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
store_fill(current_region_id);
}
current_region_id = surface_fill.region_id;
+ const LayerRegion* layerm = this->m_regions[surface_fill.region_id];
// Create the filler object.
std::unique_ptr<Fill> f = std::unique_ptr<Fill>(Fill::new_from_type(surface_fill.params.pattern));
@@ -446,6 +447,8 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
// calculate flow spacing for infill pattern generation
bool using_internal_flow = ! surface_fill.surface.has_fill_solid() && ! surface_fill.params.flow.bridge;
+ //init spacing, it may also use & modify a bit the surface_fill.params, so most of these should be set before.
+ // note that the bridge overlap is applied here via the rectilinear init_spacing.
f->init_spacing(surface_fill.params.spacing, surface_fill.params);
double link_max_length = 0.;
if (! surface_fill.params.flow.bridge) {
@@ -463,7 +466,6 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
//give the overlap size to let the infill do his overlap
//add overlap if at least one perimeter
- const LayerRegion* layerm = this->m_regions[surface_fill.region_id];
const float perimeter_spacing = layerm->flow(frPerimeter).spacing();
// Used by the concentric infill pattern to clip the loops to create extrusion paths.
@@ -485,10 +487,6 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
surface_fill.params.flow = Flow::new_from_spacing((float)f->get_spacing(), surface_fill.params.flow.nozzle_diameter, (float)surface_fill.params.flow.height, overlap, surface_fill.params.flow.bridge);
}
- //apply bridge_overlap if needed
- if (surface_fill.params.flow.bridge && surface_fill.params.density > 0.99 && layerm->region()->config().bridge_overlap.get_abs_value(1) != 1) {
- surface_fill.params.density *= float(layerm->region()->config().bridge_overlap.get_abs_value(1));
- }
for (ExPolygon &expoly : surface_fill.expolygons) {
//set overlap polygons
@@ -509,6 +507,63 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
if (!expoly.contour.empty()) {
surface_fill.surface.expolygon = std::move(expoly);
+ //adjust the bridge density
+ if (surface_fill.params.flow.bridge && surface_fill.params.density > 0.99 /*&& layerm->region()->config().bridge_overlap.get_abs_value(1) != 1*/) {
+ ////varies the overlap to have teh best coverage for the bridge
+ //surface_fill.params.density *= float(layerm->region()->config().bridge_overlap.get_abs_value(1));
+ double min_spacing = 0.999 * surface_fill.params.spacing / surface_fill.params.config->bridge_overlap.get_abs_value(surface_fill.params.density);
+ double max_spacing = 1.001 * surface_fill.params.spacing / surface_fill.params.config->bridge_overlap_min.get_abs_value(surface_fill.params.density);
+ double factor = 1.00001;
+ if (min_spacing < max_spacing * 1.01) {
+ // create a bouding box of the rotated surface
+ coord_t bounding_box_size_x = 0;
+ Polygon poly = surface_fill.surface.expolygon.contour;
+ coord_t bounding_box_min_x = 0;
+ poly.rotate(PI / 2 - (surface_fill.params.bridge_angle < 0 ? surface_fill.params.angle : surface_fill.params.bridge_angle));
+ ExPolygons expolys;
+ if (surface_fill.params.bridge_angle > 0 && !f->no_overlap_expolygons.empty()) {
+ //take only the no-overlap area
+ expolys = offset_ex(intersection_ex(ExPolygons{ ExPolygon{surface_fill.surface.expolygon.contour} }, f->no_overlap_expolygons), -scale_t(surface_fill.params.spacing) / 2 - 10);
+ } else {
+ expolys = offset_ex(ExPolygon{surface_fill.surface.expolygon.contour}, -scale_t(surface_fill.params.spacing) / 2 - 10);
+ }
+ BoundingBox bb;
+ bool first = true;
+ for (ExPolygon& expoly : expolys) {
+ expoly.holes.clear();
+ expoly.rotate(PI / 2 - (surface_fill.params.bridge_angle < 0 ? surface_fill.params.angle : surface_fill.params.bridge_angle));
+ if (first) {
+ bb = expoly.contour.bounding_box();
+ first = false;
+ } else {
+ bb.merge(expoly.contour.points);
+ }
+ }
+ bounding_box_size_x = bb.size().x();
+ bounding_box_min_x = bb.min.x();
+
+ //compute the dist
+ double new_spacing = unscaled(f->_adjust_solid_spacing(bounding_box_size_x, scale_t(min_spacing), 2));
+ if (new_spacing <= max_spacing) {
+ surface_fill.params.density = factor * surface_fill.params.spacing / new_spacing;
+ } else {
+ double new_spacing2 = unscaled(f->_adjust_solid_spacing(bounding_box_size_x, scale_t(min_spacing * 1.999 - new_spacing), 2));
+ if (new_spacing2 < min_spacing) {
+ if (min_spacing - new_spacing2 < new_spacing - max_spacing) {
+ surface_fill.params.density = surface_fill.params.config->bridge_overlap.get_abs_value(surface_fill.params.density);
+ } else {
+ surface_fill.params.density = surface_fill.params.config->bridge_overlap_min.get_abs_value(surface_fill.params.density);
+ }
+ } else {
+ //use the highest density
+ surface_fill.params.density = surface_fill.params.config->bridge_overlap.get_abs_value(surface_fill.params.density);
+ }
+ }
+ surface_fill.params.dont_adjust = true;
+ surface_fill.params.bridge_offset = std::abs(poly.bounding_box().min.x() - bounding_box_min_x);
+ }
+ }
+
//make fill
while ((size_t)surface_fill.params.priority >= fills_by_priority.size())
fills_by_priority.push_back(new ExtrusionEntityCollection());
diff --git a/src/libslic3r/Fill/FillBase.cpp b/src/libslic3r/Fill/FillBase.cpp
index 08bcc9d9f..b2806c19d 100644
--- a/src/libslic3r/Fill/FillBase.cpp
+++ b/src/libslic3r/Fill/FillBase.cpp
@@ -84,7 +84,7 @@ Polylines Fill::fill_surface(const Surface *surface, const FillParams &params) c
// This function possibly increases the spacing, never decreases,
// and for a narrow width the increase in spacing may become severe,
// therefore the adjustment is limited to 20% increase.
-coord_t Fill::_adjust_solid_spacing(const coord_t width, const coord_t distance)
+coord_t Fill::_adjust_solid_spacing(const coord_t width, const coord_t distance, const double factor_max)
{
assert(width >= 0);
assert(distance > 0);
@@ -93,10 +93,9 @@ coord_t Fill::_adjust_solid_spacing(const coord_t width, const coord_t distance)
coord_t distance_new = (number_of_intervals == 0) ?
distance :
(coord_t)(((width - EPSILON) / number_of_intervals));
- const coordf_t factor = coordf_t(distance_new) / coordf_t(distance);
+ const double factor = coordf_t(distance_new) / coordf_t(distance);
assert(factor > 1. - 1e-5);
// How much could the extrusion width be increased? By 20%.
- const coordf_t factor_max = 1.2;
if (factor > factor_max)
distance_new = coord_t(floor((coordf_t(distance) * factor_max + 0.5)));
return distance_new;
@@ -228,7 +227,7 @@ void Fill::fill_surface_extrusion(const Surface *surface, const FillParams &para
coord_t Fill::_line_spacing_for_density(float density) const
{
- return scale_(this->get_spacing() / density);
+ return scale_t(this->get_spacing() / density);
}
//FIXME: add recent improvmeent from perimetergenerator: avoid thick gapfill
diff --git a/src/libslic3r/Fill/FillBase.hpp b/src/libslic3r/Fill/FillBase.hpp
index bfac2d55b..5c5773b10 100644
--- a/src/libslic3r/Fill/FillBase.hpp
+++ b/src/libslic3r/Fill/FillBase.hpp
@@ -44,6 +44,9 @@ struct FillParams
// Fill density, fraction in <0, 1>
float density { 0.f };
+ // bridge offset from the centerline.
+ coord_t bridge_offset = -1;
+
// Fill extruding flow multiplier, fraction in <0, 1>. Used by "over bridge compensation"
float flow_mult { 1.0f };
@@ -108,7 +111,7 @@ public:
FillAdaptive::Octree* adapt_fill_octree = nullptr;
protected:
// in unscaled coordinates, please use init (after settings all others settings) as some algos want to modify the value
- coordf_t spacing_priv;
+ double spacing_priv;
public:
virtual ~Fill() {}
@@ -118,8 +121,8 @@ public:
static Fill* new_from_type(const std::string &type);
void set_bounding_box(const Slic3r::BoundingBox &bbox) { bounding_box = bbox; }
- virtual void init_spacing(coordf_t spacing, const FillParams &params) { this->spacing_priv = spacing; }
- coordf_t get_spacing() const { return spacing_priv; }
+ virtual void init_spacing(double spacing, const FillParams &params) { this->spacing_priv = spacing; }
+ double get_spacing() const { return spacing_priv; }
// Do not sort the fill lines to optimize the print head path?
virtual bool no_sort() const { return false; }
@@ -181,7 +184,7 @@ public:
//for rectilinear
static void connect_infill(Polylines&& infill_ordered, const ExPolygon& boundary, const Polygons& polygons_src, Polylines& polylines_out, const double spacing, const FillParams& params);
- static coord_t _adjust_solid_spacing(const coord_t width, const coord_t distance);
+ static coord_t _adjust_solid_spacing(const coord_t width, const coord_t distance, const double factor_max = 1.2);
// Align a coordinate to a grid. The coordinate may be negative,
// the aligned value will never be bigger than the original one.
diff --git a/src/libslic3r/Fill/FillConcentric.cpp b/src/libslic3r/Fill/FillConcentric.cpp
index 86de14193..6da55e454 100644
--- a/src/libslic3r/Fill/FillConcentric.cpp
+++ b/src/libslic3r/Fill/FillConcentric.cpp
@@ -14,7 +14,7 @@ FillConcentric::init_spacing(coordf_t spacing, const FillParams &params)
{
Fill::init_spacing(spacing, params);
if (params.density > 0.9999f && !params.dont_adjust) {
- this->spacing_priv = unscale<double>(this->_adjust_solid_spacing(bounding_box.size()(0), _line_spacing_for_density(params.density)));
+ this->spacing_priv = unscaled(this->_adjust_solid_spacing(bounding_box.size()(0), _line_spacing_for_density(params.density)));
}
}
diff --git a/src/libslic3r/Fill/FillConcentric.hpp b/src/libslic3r/Fill/FillConcentric.hpp
index b111ed7cf..8a6e97f9e 100644
--- a/src/libslic3r/Fill/FillConcentric.hpp
+++ b/src/libslic3r/Fill/FillConcentric.hpp
@@ -12,7 +12,7 @@ public:
protected:
Fill* clone() const override { return new FillConcentric(*this); };
- void init_spacing(coordf_t spacing, const FillParams &params) override;
+ void init_spacing(double spacing, const FillParams &params) override;
void _fill_surface_single(
const FillParams &params,
unsigned int thickness_layers,
diff --git a/src/libslic3r/Fill/FillLine.cpp b/src/libslic3r/Fill/FillLine.cpp
index eb2a17af5..356528e94 100644
--- a/src/libslic3r/Fill/FillLine.cpp
+++ b/src/libslic3r/Fill/FillLine.cpp
@@ -7,9 +7,9 @@
namespace Slic3r {
-void FillLine::init_spacing(coordf_t spacing, const FillParams& params) {
+void FillLine::init_spacing(double spacing, const FillParams& params) {
- this->_min_spacing = scale_(spacing);
+ this->_min_spacing = scale_t(spacing);
assert(params.density > 0.0001f && params.density <= 1.f);
this->_line_spacing = coord_t(coordf_t(this->_min_spacing) / params.density);
this->_diagonal_distance = this->_line_spacing * 2;
diff --git a/src/libslic3r/Fill/FillLine.hpp b/src/libslic3r/Fill/FillLine.hpp
index f14b9c4bb..771639d4f 100644
--- a/src/libslic3r/Fill/FillLine.hpp
+++ b/src/libslic3r/Fill/FillLine.hpp
@@ -15,7 +15,7 @@ public:
Fill* clone() const override { return new FillLine(*this); };
~FillLine() override = default;
- void init_spacing(coordf_t spacing, const FillParams& params) override;
+ void init_spacing(double spacing, const FillParams& params) override;
protected:
void _fill_surface_single(
const FillParams &params,
diff --git a/src/libslic3r/Fill/FillRectilinear.cpp b/src/libslic3r/Fill/FillRectilinear.cpp
index 3457f3b4e..ab5418b56 100644
--- a/src/libslic3r/Fill/FillRectilinear.cpp
+++ b/src/libslic3r/Fill/FillRectilinear.cpp
@@ -754,13 +754,13 @@ static inline float measure_outer_contour_slab(
*/
void
-FillRectilinear::init_spacing(coordf_t spacing, const FillParams& params)
+FillRectilinear::init_spacing(double spacing, const FillParams& params)
{
Fill::init_spacing(spacing, params);
//remove this code path becaus it's only really useful for squares at 45° and it override a setting
// define flow spacing according to requested density
//if (params.full_infill() && !params.dont_adjust) {
- // this->spacing = unscale<coordf_t>(this->_adjust_solid_spacing(bounding_box.size()(0), _line_spacing_for_density(params.density)));
+ // this->spacing = unscaled(this->_adjust_solid_spacing(bounding_box.size()(0), _line_spacing_for_density(params.density)));
//}
}
@@ -774,9 +774,11 @@ enum DirectionMask
std::vector<SegmentedIntersectionLine> FillRectilinear::_vert_lines_for_polygon(const ExPolygonWithOffset &poly_with_offset, const BoundingBox &bounding_box, const FillParams &params, coord_t line_spacing) const
{
// n_vlines = ceil(bbox_width / line_spacing)
- size_t n_vlines = (bounding_box.max(0) - bounding_box.min(0) + line_spacing - 1) / line_spacing;
- coord_t x0 = bounding_box.min(0);
- if (params.full_infill())
+ size_t n_vlines = 1 + (bounding_box.max.x() - bounding_box.min.x() - 10) / line_spacing;
+ coord_t x0 = bounding_box.min.x();
+ if (params.flow.bridge && params.bridge_offset >= 0) {
+ x0 += params.bridge_offset;
+ }else if (params.full_infill())
x0 += (line_spacing + coord_t(SCALED_EPSILON)) / 2;
#ifdef SLIC3R_DEBUG
@@ -2813,8 +2815,8 @@ bool FillRectilinear::fill_surface_by_lines(const Surface *surface, const FillPa
// Shrink the input polygon a bit first to not push the infill lines out of the perimeters.
// const float INFILL_OVERLAP_OVER_SPACING = 0.3f;
- const float INFILL_OVERLAP_OVER_SPACING = 0.45f; //merill: what is this value??? shouldn't it be like flow.width()?
- assert(INFILL_OVERLAP_OVER_SPACING > 0 && INFILL_OVERLAP_OVER_SPACING < 0.5f);
+ //const float INFILL_OVERLAP_OVER_SPACING = 0.45f; //merill: what is this value???
+ //assert(INFILL_OVERLAP_OVER_SPACING > 0 && INFILL_OVERLAP_OVER_SPACING < 0.5f);
// Rotate polygons so that we can work with vertical lines here
std::pair<float, Point> rotate_vector = this->_infill_direction(surface);
@@ -2827,8 +2829,8 @@ bool FillRectilinear::fill_surface_by_lines(const Surface *surface, const FillPa
ExPolygonWithOffset poly_with_offset(
surface->expolygon,
- rotate_vector.first,
- (scale_t(0 /*this->overlap*/ - (0.5 - INFILL_OVERLAP_OVER_SPACING) * this->get_spacing())),
- (scale_t(0 /*this->overlap*/ - 0.5f * this->get_spacing())));
+ (scale_t(0 /*this->overlap*/ - /*(0.5 - INFILL_OVERLAP_OVER_SPACING)*/ 0.05 * this->get_spacing())), // outer offset, have to be > to the inner one (less negative)
+ (scale_t(0 /*this->overlap*/ - 0.48f * this->get_spacing()))); // inner offset (don't put 0.5, as it will cut full-filled area when it's exactly at the right place)
if (poly_with_offset.n_contours_inner == 0) {
// Not a single infill line fits.
//Prusa: maybe one shall trigger the gap fill here?
@@ -2839,15 +2841,15 @@ bool FillRectilinear::fill_surface_by_lines(const Surface *surface, const FillPa
BoundingBox bounding_box = poly_with_offset.bounding_box_src();
// define flow spacing according to requested density
- if (params.full_infill() && !params.dont_adjust || line_spacing == 0 ) {
+ if ((params.full_infill() && !params.dont_adjust) || line_spacing == 0 ) {
//it's == this->_adjust_solid_spacing(bounding_box.size()(0), line_spacing) because of the init_spacing
line_spacing = scale_(this->get_spacing());
- } else {
+ } else if (!params.full_infill()) {
// extend bounding box so that our pattern will be aligned with other layers
// Transform the reference point to the rotated coordinate system.
Point refpt = rotate_vector.second.rotated(- rotate_vector.first);
// _align_to_grid will not work correctly with positive pattern_shift.
- coord_t pattern_shift_scaled = coord_t(scale_(pattern_shift)) % line_spacing;
+ coord_t pattern_shift_scaled = scale_t(pattern_shift) % line_spacing;
refpt.x() -= (pattern_shift_scaled >= 0) ? pattern_shift_scaled : (line_spacing + pattern_shift_scaled);
bounding_box.merge(_align_to_grid(
bounding_box.min,
diff --git a/src/libslic3r/Fill/FillRectilinear.hpp b/src/libslic3r/Fill/FillRectilinear.hpp
index 9e3cc056e..d15abf4e5 100644
--- a/src/libslic3r/Fill/FillRectilinear.hpp
+++ b/src/libslic3r/Fill/FillRectilinear.hpp
@@ -16,7 +16,7 @@ class FillRectilinear : public Fill
public:
Fill* clone() const override { return new FillRectilinear(*this); };
~FillRectilinear() override = default;
- virtual void init_spacing(coordf_t spacing, const FillParams& params) override;
+ virtual void init_spacing(double spacing, const FillParams& params) override;
Polylines fill_surface(const Surface* surface, const FillParams& params) const override;
protected:
diff --git a/src/libslic3r/Fill/FillSmooth.cpp b/src/libslic3r/Fill/FillSmooth.cpp
index 4f6276ee6..3fa43d673 100644
--- a/src/libslic3r/Fill/FillSmooth.cpp
+++ b/src/libslic3r/Fill/FillSmooth.cpp
@@ -61,11 +61,12 @@ namespace Slic3r {
}
void FillSmooth::fill_expolygon(const int idx, ExtrusionEntityCollection &eec, const Surface &srf_to_fill,
- const FillParams &params, const double volume) const {
+ const FillParams &params_init, const double volume) const {
+ FillParams params = params_init;
std::unique_ptr<Fill> f2 = std::unique_ptr<Fill>(Fill::new_from_type(fillPattern[idx]));
f2->bounding_box = this->bounding_box;
- f2->init_spacing(this->get_spacing(),params);
+ f2->init_spacing(this->get_spacing(), params);
f2->layer_id = this->layer_id;
f2->z = this->z;
f2->angle = anglePass[idx] + this->angle;
diff --git a/src/libslic3r/Flow.cpp b/src/libslic3r/Flow.cpp
index 274c5af26..9f71af4b7 100644
--- a/src/libslic3r/Flow.cpp
+++ b/src/libslic3r/Flow.cpp
@@ -215,7 +215,7 @@ Flow Flow::new_from_spacing(float spacing, float nozzle_diameter, float height,
// For normal extrusons, extrusion width is wider than the spacing due to the rounding and squishing of the extrusions.
// For bridge extrusions, the extrusions are placed with a tiny BRIDGE_EXTRA_SPACING gaps between the threads.
float width = float(bridge ?
- (spacing - BRIDGE_EXTRA_SPACING_MULT * nozzle_diameter) :
+ (spacing /*- BRIDGE_EXTRA_SPACING_MULT (0.125) * nozzle_diameter*/) :
#ifdef HAS_PERIMETER_LINE_OVERLAP
(spacing + PERIMETER_LINE_OVERLAP_FACTOR * height * (1. - 0.25 * PI) * spacing_ratio);
#else
@@ -235,7 +235,7 @@ float Flow::spacing() const
float min_flow_spacing = this->width - this->height * (1. - 0.25 * PI) * spacing_ratio;
float res = this->width - PERIMETER_LINE_OVERLAP_FACTOR * (this->width - min_flow_spacing);
#else
- float res = float(this->bridge ? (this->width + BRIDGE_EXTRA_SPACING_MULT * nozzle_diameter) : (this->width - this->height * (1. - 0.25 * PI) * spacing_ratio));
+ float res = float(this->bridge ? (this->width /*+ BRIDGE_EXTRA_SPACING_MULT * nozzle_diameter*/) : (this->width - this->height * (1. - 0.25 * PI) * spacing_ratio));
#endif
// assert(res > 0.f);
if (res <= 0.f)
@@ -250,8 +250,8 @@ float Flow::spacing(const Flow &other) const
{
assert(this->height == other.height);
assert(this->bridge == other.bridge);
- float res = float(this->bridge ?
- 0.5 * this->width + 0.5 * other.width + BRIDGE_EXTRA_SPACING_MULT * nozzle_diameter :
+ float res = float((this->bridge || other.bridge) ?
+ 0.5 * this->width + 0.5 * other.width :
0.5 * this->spacing() + 0.5 * other.spacing());
// assert(res > 0.f);
if (res <= 0.f)
diff --git a/src/libslic3r/Flow.hpp b/src/libslic3r/Flow.hpp
index 06c4a158f..9d9be77ee 100644
--- a/src/libslic3r/Flow.hpp
+++ b/src/libslic3r/Flow.hpp
@@ -10,9 +10,6 @@ namespace Slic3r {
class PrintObject;
-// Extra spacing of bridge threads, in mult of nozzle_width/extrusion_width. 0.05 for 0.4
-#define BRIDGE_EXTRA_SPACING_MULT 0.125
-
// Overlap factor of perimeter lines. Currently no overlap.
#ifdef HAS_PERIMETER_LINE_OVERLAP
#define PERIMETER_LINE_OVERLAP_FACTOR 1.0
diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp
index caee17188..d8be8af9e 100644
--- a/src/libslic3r/Preset.cpp
+++ b/src/libslic3r/Preset.cpp
@@ -591,6 +591,7 @@ const std::vector<std::string>& Preset::print_options()
"clip_multipart_objects",
"over_bridge_flow_ratio",
"bridge_overlap",
+ "bridge_overlap_min",
"first_layer_flow_ratio",
"clip_multipart_objects", "enforce_full_fill_volume", "external_infill_margin", "bridged_infill_margin",
// compensation
diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp
index 505200986..32c89872e 100644
--- a/src/libslic3r/PrintConfig.cpp
+++ b/src/libslic3r/PrintConfig.cpp
@@ -404,16 +404,30 @@ void PrintConfigDef::init_fff_params()
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionPercent(100));
+ def = this->add("bridge_overlap_min", coPercent);
+ def->label = L("Min");
+ def->full_label = L("Min bridge density");
+ def->sidetext = L("%");
+ def->category = OptionCategory::width;
+ def->tooltip = L("Minimum density for bridge lines. If Lower than bridge_overlap, then the overlap value can be lowered automatically down to this value."
+ " If the value is higher, this parameter has no effect."
+ "\nDefault to 87.5% to allow a little void between the lines.");
+ def->min = 50;
+ def->max = 200;
+ def->mode = comExpert;
+ def->set_default_value(new ConfigOptionPercent(80));
+
def = this->add("bridge_overlap", coPercent);
- def->label = L("Bridge overlap");
- def->full_label = L("Bridge overlap");
+ def->label = L("Max");
+ def->full_label = L("Max bridge density");
def->sidetext = L("%");
def->category = OptionCategory::width;
- def->tooltip = L("Amount of overlap between lines of the bridge. If want more space between line (or less), you can modify it. Default to 100%. A value of 50% will create two times less lines.");
+ def->tooltip = L("Maximum density for bridge lines. If you want more space between line (or less), you can modify it."
+ " A value of 50% will create two times less lines, and a value of 200% will create two time more lines that overlap each other.");
def->min = 50;
def->max = 200;
def->mode = comExpert;
- def->set_default_value(new ConfigOptionPercent(100));
+ def->set_default_value(new ConfigOptionPercent(90));
def = this->add("bridge_speed", coFloat);
def->label = L("Bridges");
@@ -2406,15 +2420,16 @@ void PrintConfigDef::init_fff_params()
def->set_default_value(new ConfigOptionBool(false));
def = this->add("infill_overlap", coFloatOrPercent);
- def->label = L("Infill/perimeters overlap");
+ def->label = L("Infill/perimeters encroachment");
def->category = OptionCategory::width;
def->tooltip = L("This setting applies an additional overlap between infill and perimeters for better bonding. "
"Theoretically this shouldn't be needed, but backlash might cause gaps. If expressed "
- "as percentage (example: 15%) it is calculated over perimeter extrusion width.");
+ "as percentage (example: 15%) it is calculated over perimeter extrusion width."
+ "\nDon't put a value higher than 50% (of the perimeter width), as it will fuse with it and follow the perimeter.");
def->sidetext = L("mm or %");
def->ratio_over = "perimeter_extrusion_width";
def->min = 0;
- def->max_literal = { 1, true };
+ def->max_literal = { 0.5, true };
def->mode = comExpert;
def->set_default_value(new ConfigOptionFloatOrPercent(25, true));
@@ -5916,6 +5931,7 @@ std::unordered_set<std::string> prusa_export_to_remove_keys = {
"avoid_crossing_not_first_layer",
"bridge_internal_fan_speed",
"bridge_overlap",
+"bridge_overlap_min",
"bridge_speed_internal",
"bridged_infill_margin",
"brim_ears_detection_length",
diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp
index ce90d35f5..32537c609 100644
--- a/src/libslic3r/PrintConfig.hpp
+++ b/src/libslic3r/PrintConfig.hpp
@@ -782,6 +782,7 @@ public:
ConfigOptionPercent bridge_flow_ratio;
ConfigOptionPercent over_bridge_flow_ratio;
ConfigOptionPercent bridge_overlap;
+ ConfigOptionPercent bridge_overlap_min;
ConfigOptionEnum<InfillPattern> bottom_fill_pattern;
ConfigOptionFloatOrPercent bridged_infill_margin;
ConfigOptionFloat bridge_speed;
@@ -900,6 +901,7 @@ protected:
OPT_PTR(bridge_flow_ratio);
OPT_PTR(over_bridge_flow_ratio);
OPT_PTR(bridge_overlap);
+ OPT_PTR(bridge_overlap_min);
OPT_PTR(bottom_fill_pattern);
OPT_PTR(bridged_infill_margin);
OPT_PTR(bridge_speed);
diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp
index 3a75e57ae..1aff59ca0 100644
--- a/src/slic3r/GUI/ConfigManipulation.cpp
+++ b/src/slic3r/GUI/ConfigManipulation.cpp
@@ -216,6 +216,7 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con
names.push_back("bridge_flow_ratio");
names.push_back("over_bridge_flow_ratio");
names.push_back("bridge_overlap");
+ names.push_back("bridge_overlap_min");
names.push_back("fill_top_flow_ratio");
names.push_back("first_layer_flow_ratio");
for (int i = 0; i < names.size(); i++) {
diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp
index 793652f26..0bc236e43 100644
--- a/src/slic3r/GUI/Field.cpp
+++ b/src/slic3r/GUI/Field.cpp
@@ -413,104 +413,120 @@ void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true
break;
case coFloatsOrPercents:
case coFloatOrPercent: {
- if (!str.IsEmpty() && str.Last() != '%')
- {
- double val = 0.;
- // Replace the first occurence of comma in decimal number.
- str.Replace(",", ".", false);
-
- // remove space and "mm" substring, if any exists
- str.Replace(" ", "", true);
- str.Replace("m", "", true);
-
- if (m_opt.nullable && str == na_value()) {
- val = ConfigOptionFloatsNullable::nil_value();
- str = "nan";
- } else if (!str.ToCDouble(&val)) {
- if (!check_value) {
- m_value.clear();
- break;
+ if (!str.IsEmpty()) {
+ if ("infill_overlap" == m_opt_id && m_last_validated_value != str) {
+ bool bad = false;
+ double val = 0.;
+ if (str.Last() != '%') {
+ if (str.ToCDouble(&val)) {
+ const DynamicPrintConfig& printer_config = wxGetApp().preset_bundle->printers.get_edited_preset().config;
+ const std::vector<double>& nozzle_diameters = printer_config.option<ConfigOptionFloats>("nozzle_diameter")->values;
+ double nozzle_diameter = 0;
+ for (double diameter : nozzle_diameters)
+ nozzle_diameter = std::max(nozzle_diameter, diameter);
+ if (val > nozzle_diameter / 2) {
+ bad = true;
+ }
+ }
+ } else {
+ if (str.substr(0, str.size() - 1).ToCDouble(&val)) {
+ if (val >= 50) {
+ bad = true;
+ }
+ }
}
- show_error(m_parent, _(L("Invalid numeric input.")));
- set_value(double_to_string(val, m_opt.precision), true);
- } else {
-
- //at least check min, as we can want a 0 min
- if (m_opt.min > val)
- {
+ if (bad && check_value) {
+ const wxString msg_text = from_u8(_u8L("The infill / perimeter encroachment can't be higher than half of the perimeter width.\n"
+ "Are you sure to use this value?"));
+ wxMessageDialog dialog(m_parent, msg_text, _L("Parameter validation") + ": " + m_opt_id, wxICON_WARNING | wxYES | wxNO);
+ auto ret = dialog.ShowModal();
+ if (ret == wxID_NO) {
+ str = from_u8("49%");
+ m_last_validated_value = str;
+ set_value(str, false);
+ str = m_last_validated_value;
+ }
+ m_last_validated_value = str;
+ }
+ }
+ else if (str.Last() != '%') {
+ double val = 0.;
+ // Replace the first occurence of comma in decimal number.
+ str.Replace(",", ".", false);
+
+ // remove space and "mm" substring, if any exists
+ str.Replace(" ", "", true);
+ str.Replace("m", "", true);
+
+ if (m_opt.nullable && str == na_value()) {
+ val = ConfigOptionFloatsNullable::nil_value();
+ str = "nan";
+ } else if (!str.ToCDouble(&val)) {
if (!check_value) {
m_value.clear();
break;
}
- show_error(m_parent, _(L("Input value is out of range")));
- if (m_opt.min > val) val = m_opt.min;
+ show_error(m_parent, _(L("Invalid numeric input.")));
set_value(double_to_string(val, m_opt.precision), true);
- } else if (m_value.empty() || std::string(str.ToUTF8().data()) != boost::any_cast<std::string>(m_value)) {
- bool not_ok = (m_opt.sidetext.rfind("mm/s") != std::string::npos && val > m_opt.max);
- if( !not_ok && m_opt.max_literal.value != 0 )
- if (m_opt.max_literal.percent) {
- const DynamicPrintConfig& printer_config = wxGetApp().preset_bundle->printers.get_edited_preset().config;
- const std::vector<double>& nozzle_diameters = printer_config.option<ConfigOptionFloats>("nozzle_diameter")->values;
- double nozzle_diameter = 0;
- for (double diameter : nozzle_diameters)
- nozzle_diameter = std::max(nozzle_diameter, diameter);
- if (m_opt.max_literal.value > 0)
- not_ok = val > nozzle_diameter * m_opt.max_literal.value;
- else
- not_ok = val < nozzle_diameter * (-m_opt.max_literal.value);
- }else{
- if(m_opt.max_literal.value > 0)
- not_ok = val > m_opt.max_literal.value;
- else
- not_ok = val < -m_opt.max_literal.value;
- }
- if (not_ok) {
-
- // if (
- // (
- // (m_opt.sidetext.rfind("mm/s") != std::string::npos && val > m_opt.max)
- // ||
- // (m_opt.sidetext.rfind("mm ") != std::string::npos && val > m_opt.max_literal)
- // )
- // &&
- // (m_value.empty() || std::string(str.ToUTF8().data()) != boost::any_cast<std::string>(m_value)))
- //{
- // if (m_opt.opt_key.find("extrusion_width") != std::string::npos || m_opt.opt_key.find("extrusion_spacing") != std::string::npos) {
- // const DynamicPrintConfig& printer_config = wxGetApp().preset_bundle->printers.get_edited_preset().config;
- // const std::vector<double>& nozzle_diameters = printer_config.option<ConfigOptionFloats>("nozzle_diameter")->values;
- // double nozzle_diameter = 0;
- // for (double diameter : nozzle_diameters)
- // nozzle_diameter = std::max(nozzle_diameter, diameter);
- // if (val < nozzle_diameter * 10) {
- // m_value = std::string(str.ToUTF8().data());
- // break;
- // }
- // }
- //TODO: chack for infill_overlap from diameter% => allow max_literal to be a %
+ } else {
+ //at least check min, as we can want a 0 min
+ if (m_opt.min > val)
+ {
if (!check_value) {
m_value.clear();
break;
}
+ show_error(m_parent, _(L("Input value is out of range")));
+ if (m_opt.min > val) val = m_opt.min;
+ set_value(double_to_string(val, m_opt.precision), true);
+ } else if (m_value.empty() || std::string(str.ToUTF8().data()) != boost::any_cast<std::string>(m_value)) {
+ bool not_ok = (m_opt.sidetext.rfind("mm/s") != std::string::npos && val > m_opt.max);
+ if (!not_ok && m_opt.max_literal.value != 0) {
+ if (m_opt.max_literal.percent) {
+ const DynamicPrintConfig& printer_config = wxGetApp().preset_bundle->printers.get_edited_preset().config;
+ const std::vector<double>& nozzle_diameters = printer_config.option<ConfigOptionFloats>("nozzle_diameter")->values;
+ double nozzle_diameter = 0;
+ for (double diameter : nozzle_diameters)
+ nozzle_diameter = std::max(nozzle_diameter, diameter);
+ if (m_opt.max_literal.value > 0)
+ not_ok = val > nozzle_diameter * m_opt.max_literal.value;
+ else
+ not_ok = val < nozzle_diameter* (-m_opt.max_literal.value);
+ } else {
+ if (m_opt.max_literal.value > 0)
+ not_ok = val > m_opt.max_literal.value;
+ else
+ not_ok = val < -m_opt.max_literal.value;
+ }
+ }
+ if (not_ok && m_last_validated_value != str) {
+ if (!check_value) {
+ m_value.clear();
+ break;
+ }
- bool infill_anchors = m_opt.opt_key == "infill_anchor" || m_opt.opt_key == "infill_anchor_max";
-
- const std::string sidetext = m_opt.sidetext.rfind("mm/s") != std::string::npos ? "mm/s" : "mm";
- const wxString stVal = double_to_string(val, m_opt.precision);
- const wxString msg_text = from_u8((boost::format(_utf8(L("Do you mean %s%% instead of %s %s?\n"
- "Select YES if you want to change this value to %s%%, \n"
- "or NO if you are sure that %s %s is a correct value."))) % stVal % stVal % sidetext % stVal % stVal % sidetext).str());
- wxMessageDialog dialog(m_parent, msg_text, _(L("Parameter validation")) + ": " + m_opt_id, wxICON_WARNING | wxYES | wxNO);
- if ((!infill_anchors || val > 100) && dialog.ShowModal() == wxID_YES) {
- set_value(from_u8((boost::format("%s%%") % stVal).str()), false/*true*/);
- str += "%%";
- } else
- set_value(stVal, false); // it's no needed but can be helpful, when inputted value contained "," instead of "."
+ bool infill_anchors = m_opt.opt_key == "infill_anchor" || m_opt.opt_key == "infill_anchor_max";
+
+ const std::string sidetext = m_opt.sidetext.rfind("mm/s") != std::string::npos ? "mm/s" : "mm";
+ const wxString stVal = double_to_string(val, m_opt.precision);
+ const wxString msg_text = from_u8((boost::format(_u8L("Do you mean %s%% instead of %s %s?\n"
+ "Select YES if you want to change this value to %s%%, \n"
+ "or NO if you are sure that %s %s is a correct value.")) % stVal % stVal % sidetext % stVal % stVal % sidetext).str());
+ wxMessageDialog dialog(m_parent, msg_text, _L("Parameter validation") + ": " + m_opt_id, wxICON_WARNING | wxYES | wxNO);
+ if ((!infill_anchors || val > 100) && dialog.ShowModal() == wxID_YES) {
+ str += "%";
+ m_last_validated_value = str;
+ set_value(str, false/*true*/);
+ str = m_last_validated_value;
+ } else
+ set_value(stVal, false); // it's no needed but can be helpful, when inputted value contained "," instead of "."
+ m_last_validated_value = str;
+ }
}
}
}
}
-
m_value = std::string(str.ToUTF8().data());
break;
}
diff --git a/src/slic3r/GUI/Field.hpp b/src/slic3r/GUI/Field.hpp
index 3c361f94b..e48473346 100644
--- a/src/slic3r/GUI/Field.hpp
+++ b/src/slic3r/GUI/Field.hpp
@@ -230,8 +230,10 @@ protected:
// current value
boost::any m_value;
- // last maeningful value
+ // last meaningful value
boost::any m_last_meaningful_value;
+ // last validated value
+ wxString m_last_validated_value;
int m_em_unit;