Skip to content

Commit

Permalink
Add arc_fitting_tolerance, to choose the threshold for strait->curve …
Browse files Browse the repository at this point in the history
…transformation.
  • Loading branch information
supermerill committed Feb 24, 2023
1 parent 65d67c7 commit dd43846
Show file tree
Hide file tree
Showing 18 changed files with 62 additions and 33 deletions.
5 changes: 4 additions & 1 deletion resources/ui_layout/default/printer_fff.ui
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ group:silent_mode_event:Firmware
setting:max_gcode_per_second
setting:min_length
end_line
setting:arc_fitting
line:G2/G3 generation
setting:arc_fitting
setting:arc_fitting_tolerance
end_line
setting:gcode_filename_illegal_char
group:Cooling fan
line:Speedup time
Expand Down
4 changes: 4 additions & 0 deletions resources/ui_layout/example/printer_fff.ui
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ group:silent_mode_event:Firmware
setting:max_gcode_per_second
setting:min_length
end_line
line:G2/G3 generation
setting:arc_fitting
setting:arc_fitting_tolerance
end_line
setting:gcode_filename_illegal_char
group:Cooling fan
line:Speedup time
Expand Down
12 changes: 6 additions & 6 deletions src/libslic3r/ExtrusionEntity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,17 @@ void ExtrusionPath::clip_end(coordf_t distance)
this->polyline.clip_end(distance);
}

void ExtrusionPath::simplify(coordf_t tolerance, bool with_fitting_arc)
void ExtrusionPath::simplify(coordf_t tolerance, bool with_fitting_arc, double fitting_arc_tolerance)
{
this->polyline.simplify(tolerance, with_fitting_arc);
this->polyline.simplify(tolerance, with_fitting_arc, fitting_arc_tolerance);
}

void ExtrusionPath3D::simplify(coordf_t tolerance, bool with_fitting_arc)
void ExtrusionPath3D::simplify(coordf_t tolerance, bool with_fitting_arc, double fitting_arc_tolerance)
{
//TODO: simplify but only for sub-path with same zheight.
if (with_fitting_arc) {
this->polyline.simplify(tolerance, true);
}
//if (with_fitting_arc) {
// this->polyline.simplify(tolerance, with_fitting_arc, fitting_arc_tolerance);
//}
}

double ExtrusionPath::length() const
Expand Down
11 changes: 6 additions & 5 deletions src/libslic3r/ExtrusionEntity.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ class ExtrusionPath : public ExtrusionEntity
// Currently not used.
void subtract_expolygons(const ExPolygonCollection &collection, ExtrusionEntityCollection* retval) const;
void clip_end(coordf_t distance);
virtual void simplify(coordf_t tolerance, bool with_fitting_arc);
virtual void simplify(coordf_t tolerance, bool with_fitting_arc, double fitting_arc_tolerance);
double length() const override;
ExtrusionRole role() const override { return m_role; }
void set_role(ExtrusionRole new_role) { m_role = new_role; }
Expand Down Expand Up @@ -317,7 +317,7 @@ class ExtrusionPath3D : public ExtrusionPath {
}

//TODO: simplify only for points that have the same z-offset
void simplify(double tolerance, bool use_arc_fitting) override;
void simplify(double tolerance, bool use_arc_fitting, double fitting_arc_tolerance) override;
};
typedef std::vector<ExtrusionPath3D> ExtrusionPaths3D;

Expand Down Expand Up @@ -670,13 +670,14 @@ class ExtrusionVisitorRecursive : public ExtrusionVisitor {
class SimplifyVisitor : public ExtrusionVisitorRecursive {
bool m_use_arc_fitting;
coordf_t m_scaled_resolution;
const ConfigOptionFloatOrPercent* m_arc_fitting_tolearance;
public:
SimplifyVisitor(coordf_t scaled_resolution, bool use_arc_fitting) : m_scaled_resolution(scaled_resolution), m_use_arc_fitting(use_arc_fitting) {}
SimplifyVisitor(coordf_t scaled_resolution, bool use_arc_fitting, const ConfigOptionFloatOrPercent* arc_fitting_tolearance) : m_scaled_resolution(scaled_resolution), m_use_arc_fitting(use_arc_fitting), m_arc_fitting_tolearance(arc_fitting_tolearance){}
virtual void use(ExtrusionPath& path) override {
path.simplify(m_scaled_resolution, m_use_arc_fitting);
path.simplify(m_scaled_resolution, m_use_arc_fitting, scale_d(m_arc_fitting_tolearance->get_abs_value(path.width)));
}
virtual void use(ExtrusionPath3D& path3D) override {
path3D.simplify(m_scaled_resolution, m_use_arc_fitting);
path3D.simplify(m_scaled_resolution, m_use_arc_fitting, scale_d(m_arc_fitting_tolearance->get_abs_value(path3D.width)));
}
};
class GetPathsVisitor : public ExtrusionVisitorRecursive {
Expand Down
2 changes: 1 addition & 1 deletion src/libslic3r/GCode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5117,7 +5117,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, const std::string &descri
std::string descr = description.empty() ? ExtrusionEntity::role_to_string(path.role()) : description;
std::string gcode = this->_before_extrude(path, descr, speed);

std::function<void(std::string, Line, double, std::string)> func = [this](std::string& gcode, const Line& line, double e_per_mm, const std::string& comment) {
std::function<void(std::string&, const Line&, double, const std::string&)> func = [this](std::string& gcode, const Line& line, double e_per_mm, const std::string& comment) {
if (line.a == line.b) return; //todo: investigate if it happens (it happens in perimeters)
gcode += m_writer.extrude_to_xy(
this->point_to_gcode(line.b),
Expand Down
8 changes: 4 additions & 4 deletions src/libslic3r/Geometry/ArcFitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

namespace Slic3r { namespace Geometry {

void ArcFitter::do_arc_fitting(const Points& points, std::vector<PathFittingData>& result, double tolerance)
void ArcFitter::do_arc_fitting(const Points& points, std::vector<PathFittingData>& result, double tolerance, double fit_percent_tolerance)
{
#ifdef DEBUG_ARC_FITTING
static int irun = 0;
Expand Down Expand Up @@ -51,7 +51,7 @@ void ArcFitter::do_arc_fitting(const Points& points, std::vector<PathFittingData
can_fit = ArcSegment::try_create_arc(current_segment, target_arc, Polyline(current_segment).length(),
DEFAULT_SCALED_MAX_RADIUS,
tolerance,
DEFAULT_ARC_LENGTH_PERCENT_TOLERANCE);
fit_percent_tolerance);
if (can_fit) {
//BBS: can be fit as arc, then save arc data temperarily
last_arc = target_arc;
Expand Down Expand Up @@ -93,11 +93,11 @@ void ArcFitter::do_arc_fitting(const Points& points, std::vector<PathFittingData
result.shrink_to_fit();
}

void ArcFitter::do_arc_fitting_and_simplify(Points& points, std::vector<PathFittingData>& result, double tolerance)
void ArcFitter::do_arc_fitting_and_simplify(Points& points, std::vector<PathFittingData>& result, double tolerance, double fit_circle_tolerance)
{
//BBS: 1 do arc fit first
if (abs(tolerance) > SCALED_EPSILON)
ArcFitter::do_arc_fitting(points, result, tolerance);
ArcFitter::do_arc_fitting(points, result, fit_circle_tolerance, DEFAULT_ARC_LENGTH_PERCENT_TOLERANCE);
else
result.push_back(PathFittingData{ 0, points.size() - 1, EMovePathType::Linear_move, ArcSegment() });

Expand Down
4 changes: 2 additions & 2 deletions src/libslic3r/Geometry/ArcFitter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ struct PathFittingData{
class ArcFitter {
public:
//BBS: this function is used to check the point list and return which part can fit as arc, which part should be line
static void do_arc_fitting(const Points& points, std::vector<PathFittingData> &result, double tolerance);
static void do_arc_fitting(const Points& points, std::vector<PathFittingData> &result, double tolerance, double fit_percent_tolerance);
//BBS: this function is used to check the point list and return which part can fit as arc, which part should be line.
//By the way, it also use DP simplify to reduce point of straight part and only keep the start and end point of arc.
static void do_arc_fitting_and_simplify(Points& points, std::vector<PathFittingData>& result, double tolerance);
static void do_arc_fitting_and_simplify(Points& points, std::vector<PathFittingData>& result, double tolerance, double fit_circle_tolerance);
};

} } // namespace slic3r geometry
Expand Down
3 changes: 2 additions & 1 deletion src/libslic3r/Geometry/Circle.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,8 @@ enum class ArcDirection : unsigned char {

//// arc fitting ////

constexpr double ZERO_TOLERANCE = EPSILON / 20;//0.000005;
//constexpr double ZERO_TOLERANCE = EPSILON / 20;//0.000005;
#define ZERO_TOLERANCE EPSILON/20

class ArcCircle {
public:
Expand Down
2 changes: 1 addition & 1 deletion src/libslic3r/Layer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ void SupportLayer::simplify_support_extrusion_path() {
coordf_t scaled_resolution = scale_d(print_config.resolution.value);
if (scaled_resolution == 0) scaled_resolution = enable_arc_fitting ? SCALED_EPSILON * 2 : SCALED_EPSILON;

SimplifyVisitor visitor{ scaled_resolution , enable_arc_fitting };
SimplifyVisitor visitor{ scaled_resolution , enable_arc_fitting, &print_config.arc_fitting_tolerance };
this->support_fills.visit(visitor);
}

Expand Down
2 changes: 1 addition & 1 deletion src/libslic3r/LayerRegion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -622,7 +622,7 @@ void LayerRegion::simplify_extrusion_entity()
if (scaled_resolution == 0) scaled_resolution = enable_arc_fitting ? SCALED_EPSILON * 2 : SCALED_EPSILON;

//call simplify for all paths
SimplifyVisitor visitor{ scaled_resolution , enable_arc_fitting };
SimplifyVisitor visitor{ scaled_resolution , enable_arc_fitting, &print_config.arc_fitting_tolerance };
this->perimeters.visit(visitor);
this->fills.visit(visitor);
this->ironings.visit(visitor);
Expand Down
4 changes: 2 additions & 2 deletions src/libslic3r/Polyline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -502,11 +502,11 @@ void PolylineOrArc::clip_first_point() {
}
}

void PolylineOrArc::simplify(coordf_t tolerance, bool with_fitting_arc)
void PolylineOrArc::simplify(coordf_t tolerance, bool with_fitting_arc, double fit_percent_tolerance)
{
if (with_fitting_arc) {
//BBS: do arc fit first, then use DP simplify to handle the straight part to reduce point.
Slic3r::Geometry::ArcFitter::do_arc_fitting_and_simplify(this->points, this->m_fitting_result, tolerance);
Slic3r::Geometry::ArcFitter::do_arc_fitting_and_simplify(this->points, this->m_fitting_result, tolerance, fit_percent_tolerance);
} else {
this->points = MultiPoint::_douglas_peucker(this->points, tolerance);
this->m_fitting_result.clear();
Expand Down
2 changes: 1 addition & 1 deletion src/libslic3r/Polyline.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ class PolylineOrArc : /*public*/ Polyline {
}

Points equally_spaced_points(coordf_t distance) const;
void simplify(coordf_t tolerance, bool with_fitting_arc);
void simplify(coordf_t tolerance, bool with_fitting_arc, double fit_tolerance);

//split& & clip
// template <class T> void simplify_by_visibility(const T &area);
Expand Down
1 change: 1 addition & 0 deletions src/libslic3r/Preset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -782,6 +782,7 @@ static std::vector<std::string> s_Preset_machine_limits_options {

static std::vector<std::string> s_Preset_printer_options {
"arc_fitting",
"arc_fitting_tolerance",
"printer_technology",
"bed_shape", "bed_custom_texture", "bed_custom_model", "z_offset", "init_z_rotate",
"fan_kickstart",
Expand Down
10 changes: 6 additions & 4 deletions src/libslic3r/Print.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver& /* ne
} else if (
opt_key == "first_layer_extrusion_width"
|| opt_key == "arc_fitting"
|| opt_key == "arc_fitting_tolerance"
|| opt_key == "min_layer_height"
|| opt_key == "max_layer_height"
|| opt_key == "filament_max_overlap"
Expand Down Expand Up @@ -1232,9 +1233,10 @@ void Print::process()
obj->simplify_extrusion_path();
}
//also simplify object skirt & brim
if (enable_arc_fitting) {
if (enable_arc_fitting && (!this->m_skirt.empty() || !this->m_brim.empty())) {
coordf_t scaled_resolution = scale_d(config().resolution.value);
if (scaled_resolution == 0) scaled_resolution = enable_arc_fitting ? SCALED_EPSILON * 2 : SCALED_EPSILON;
const ConfigOptionFloatOrPercent& arc_fitting_tolerance = config().arc_fitting_tolerance;

this->set_status(0, L("Optimizing skirt & brim %s%%"), { std::to_string(0) }, PrintBase::SlicingStatus::SECONDARY_STATE);
std::atomic<int> atomic_count{ 0 };
Expand All @@ -1243,15 +1245,15 @@ void Print::process()
this->m_brim.visit(visitor);
tbb::parallel_for(
tbb::blocked_range<size_t>(0, visitor.paths.size() + visitor.paths3D.size()),
[this, &visitor, scaled_resolution, &atomic_count](const tbb::blocked_range<size_t>& range) {
[this, &visitor, scaled_resolution, &arc_fitting_tolerance, &atomic_count](const tbb::blocked_range<size_t>& range) {
size_t path_idx = range.begin();
for (; path_idx < range.end() && path_idx < visitor.paths.size(); ++path_idx) {
visitor.paths[path_idx]->simplify(scaled_resolution, true);
visitor.paths[path_idx]->simplify(scaled_resolution, true, scale_d(arc_fitting_tolerance.get_abs_value(visitor.paths[path_idx]->width)));
int nb_items_done = (++atomic_count);
this->set_status(int((nb_items_done * 100) / (visitor.paths.size() + visitor.paths3D.size())), L("Optimizing skirt & brim %s%%"), { std::to_string(int(100*nb_items_done / double(visitor.paths.size() + visitor.paths3D.size()))) }, PrintBase::SlicingStatus::SECONDARY_STATE);
}
for (; path_idx < range.end() && path_idx - visitor.paths.size() < visitor.paths3D.size(); ++path_idx) {
visitor.paths3D[path_idx - visitor.paths.size()]->simplify(scaled_resolution, true);
visitor.paths3D[path_idx - visitor.paths.size()]->simplify(scaled_resolution, true, scale_d(arc_fitting_tolerance.get_abs_value(visitor.paths[path_idx]->width)));
int nb_items_done = (++atomic_count);
this->set_status(int((nb_items_done * 100) / (visitor.paths.size() + visitor.paths3D.size())), L("Optimizing skirt & brim %s%%"), { std::to_string(int(100*nb_items_done / double(visitor.paths.size() + visitor.paths3D.size()))) }, PrintBase::SlicingStatus::SECONDARY_STATE);
}
Expand Down
13 changes: 12 additions & 1 deletion src/libslic3r/PrintConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,16 @@ void PrintConfigDef::init_fff_params()
def->mode = comAdvancedE | comSuSi;
def->set_default_value(new ConfigOptionBool(false));

def = this->add("arc_fitting_tolerance", coFloatOrPercent);
def->label = L("Arc fitting tolerance");
def->sidetext = L("mm or %");
def->category = OptionCategory::firmware;
def->tooltip = L("When using the arc_fitting option, allow the curve to deviate a cetain % from the collection of strait paths."
"\nCan be a mm value or a percentage of the current extrusion width.");
def->mode = comAdvancedE | comSuSi;
def->min = 0;
def->set_default_value(new ConfigOptionFloatOrPercent(5, true));

def = this->add("avoid_crossing_perimeters", coBool);
def->label = L("Avoid crossing perimeters");
def->category = OptionCategory::perimeter;
Expand Down Expand Up @@ -7498,7 +7508,8 @@ void ModelConfig::convert_from_prusa(const DynamicPrintConfig& global_config) {

std::unordered_set<std::string> prusa_export_to_remove_keys = {
"allow_empty_layers",
"arc_fitting"
"arc_fitting",
"arc_fitting_tolerance",
"avoid_crossing_not_first_layer",
"bridge_fill_pattern",
"bridge_internal_acceleration",
Expand Down
1 change: 1 addition & 0 deletions src/libslic3r/PrintConfig.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -985,6 +985,7 @@ PRINT_CONFIG_CLASS_DEFINE(
GCodeConfig,

((ConfigOptionBool, arc_fitting))
((ConfigOptionFloatOrPercent, arc_fitting_tolerance))
((ConfigOptionString, before_layer_gcode))
((ConfigOptionString, between_objects_gcode))
((ConfigOptionFloats, deretract_speed))
Expand Down
7 changes: 4 additions & 3 deletions src/libslic3r/PrintObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -657,19 +657,20 @@ std::vector<std::reference_wrapper<const PrintRegion>> PrintObject::all_regions(
if (enable_arc_fitting) {
coordf_t scaled_resolution = scale_d(print_config.resolution.value);
if (scaled_resolution == 0) scaled_resolution = enable_arc_fitting ? SCALED_EPSILON * 2 : SCALED_EPSILON;
const ConfigOptionFloatOrPercent& arc_fitting_tolerance = print_config.arc_fitting_tolerance;

GetPathsVisitor visitor;
this->m_skirt.visit(visitor);
this->m_brim.visit(visitor);
tbb::parallel_for(
tbb::blocked_range<size_t>(0, visitor.paths.size() + visitor.paths3D.size()),
[this, &visitor, scaled_resolution](const tbb::blocked_range<size_t>& range) {
[this, &visitor, scaled_resolution, &arc_fitting_tolerance](const tbb::blocked_range<size_t>& range) {
size_t path_idx = range.begin();
for (; path_idx < range.end() && path_idx < visitor.paths.size(); ++path_idx) {
visitor.paths[path_idx]->simplify(scaled_resolution, true);
visitor.paths[path_idx]->simplify(scaled_resolution, true, arc_fitting_tolerance.get_abs_value(visitor.paths[path_idx]->width));
}
for (; path_idx < range.end() && path_idx - visitor.paths.size() < visitor.paths3D.size(); ++path_idx) {
visitor.paths3D[path_idx - visitor.paths.size()]->simplify(scaled_resolution, true);
visitor.paths3D[path_idx - visitor.paths.size()]->simplify(scaled_resolution, true, arc_fitting_tolerance.get_abs_value(visitor.paths3D[path_idx - visitor.paths.size()]->width));
}
}
);
Expand Down
4 changes: 4 additions & 0 deletions src/slic3r/GUI/Tab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3350,6 +3350,10 @@ void TabPrinter::toggle_options()
bool have_remaining_times = m_config->opt_bool("remaining_times");
field = get_field("remaining_times_type");
if (field) field->toggle(have_remaining_times);

bool have_arc_fitting = m_config->opt_bool("arc_fitting");
field = get_field("arc_fitting_tolerance");
if (field) field->toggle(have_arc_fitting);

auto flavor = m_config->option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor")->value;
bool is_marlin_flavor = flavor == gcfMarlinLegacy || flavor == gcfMarlinFirmware;
Expand Down

0 comments on commit dd43846

Please sign in to comment.