mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-11 21:08:59 +08:00
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.
This commit is contained in:
parent
282db5bd4f
commit
0d25f9b266
@ -321,8 +321,11 @@ group:Overlap
|
||||
setting:label$External:external_perimeter_overlap
|
||||
setting:label$Gap Fill:gap_fill_overlap
|
||||
end_line
|
||||
setting:sidetext_width$7:infill_overlap
|
||||
line:Bridge lines density
|
||||
setting:bridge_overlap_min
|
||||
setting:bridge_overlap
|
||||
end_line
|
||||
setting:sidetext_width$7:infill_overlap
|
||||
group:Flow
|
||||
line:Flow ratio
|
||||
setting:bridge_flow_ratio
|
||||
|
@ -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());
|
||||
|
@ -84,7 +84,7 @@ Polylines Fill::fill_surface(const Surface *surface, const FillParams ¶ms) 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 ¶
|
||||
|
||||
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
|
||||
|
@ -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 ¶ms) { this->spacing_priv = spacing; }
|
||||
coordf_t get_spacing() const { return spacing_priv; }
|
||||
virtual void init_spacing(double spacing, const FillParams ¶ms) { 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.
|
||||
|
@ -14,7 +14,7 @@ FillConcentric::init_spacing(coordf_t spacing, const FillParams ¶ms)
|
||||
{
|
||||
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)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,7 @@ public:
|
||||
|
||||
protected:
|
||||
Fill* clone() const override { return new FillConcentric(*this); };
|
||||
void init_spacing(coordf_t spacing, const FillParams ¶ms) override;
|
||||
void init_spacing(double spacing, const FillParams ¶ms) override;
|
||||
void _fill_surface_single(
|
||||
const FillParams ¶ms,
|
||||
unsigned int thickness_layers,
|
||||
|
@ -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;
|
||||
|
@ -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 ¶ms,
|
||||
|
@ -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 ¶ms, 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,
|
||||
|
@ -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:
|
||||
|
@ -61,8 +61,9 @@ namespace Slic3r {
|
||||
}
|
||||
|
||||
void FillSmooth::fill_expolygon(const int idx, ExtrusionEntityCollection &eec, const Surface &srf_to_fill,
|
||||
const FillParams ¶ms, const double volume) const {
|
||||
const FillParams ¶ms_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);
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -404,16 +404,30 @@ void PrintConfigDef::init_fff_params()
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionPercent(100));
|
||||
|
||||
def = this->add("bridge_overlap", coPercent);
|
||||
def->label = L("Bridge overlap");
|
||||
def->full_label = L("Bridge overlap");
|
||||
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("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("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(100));
|
||||
def->set_default_value(new ConfigOptionPercent(80));
|
||||
|
||||
def = this->add("bridge_overlap", coPercent);
|
||||
def->label = L("Max");
|
||||
def->full_label = L("Max bridge density");
|
||||
def->sidetext = L("%");
|
||||
def->category = OptionCategory::width;
|
||||
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(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",
|
||||
|
@ -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);
|
||||
|
@ -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++) {
|
||||
|
@ -413,8 +413,43 @@ void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true
|
||||
break;
|
||||
case coFloatsOrPercents:
|
||||
case coFloatOrPercent: {
|
||||
if (!str.IsEmpty() && str.Last() != '%')
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
@ -447,7 +482,7 @@ void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true
|
||||
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 (!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;
|
||||
@ -464,30 +499,8 @@ void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true
|
||||
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 %
|
||||
|
||||
}
|
||||
if (not_ok && m_last_validated_value != str) {
|
||||
if (!check_value) {
|
||||
m_value.clear();
|
||||
break;
|
||||
@ -497,20 +510,23 @@ void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true
|
||||
|
||||
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"
|
||||
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);
|
||||
"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 += "%%";
|
||||
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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user