ENH: support circle speed compensation
Jira: none Change-Id: I05f31ff26463cdf6fd900f8f1ca6cf0e0b283925
This commit is contained in:
parent
e617e933b8
commit
7d44a8bdca
|
@ -14,6 +14,7 @@
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
static const double slope_path_ratio = 0.3;
|
static const double slope_path_ratio = 0.3;
|
||||||
static const double slope_inner_outer_wall_gap = 0.4;
|
static const double slope_inner_outer_wall_gap = 0.4;
|
||||||
|
static const int overhang_threshold = 1;
|
||||||
|
|
||||||
void ExtrusionPath::intersect_expolygons(const ExPolygons &collection, ExtrusionEntityCollection* retval) const
|
void ExtrusionPath::intersect_expolygons(const ExPolygons &collection, ExtrusionEntityCollection* retval) const
|
||||||
{
|
{
|
||||||
|
@ -418,6 +419,17 @@ bool ExtrusionLoop::has_overhang_point(const Point &point) const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ExtrusionLoop::has_overhang_paths() const
|
||||||
|
{
|
||||||
|
for (const ExtrusionPath &path : this->paths) {
|
||||||
|
if (is_bridge(path.role()))
|
||||||
|
return true;
|
||||||
|
if (path.overhang_degree >= overhang_threshold)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void ExtrusionLoop::polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const
|
void ExtrusionLoop::polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const
|
||||||
{
|
{
|
||||||
for (const ExtrusionPath &path : this->paths)
|
for (const ExtrusionPath &path : this->paths)
|
||||||
|
|
|
@ -66,6 +66,11 @@ enum ExtrusionRole : uint8_t {
|
||||||
erCount
|
erCount
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum CustomizeFlag : uint8_t {
|
||||||
|
cfNone,
|
||||||
|
cfCircleCompensation // shaft hole tolerance compensation
|
||||||
|
};
|
||||||
|
|
||||||
// Special flags describing loop
|
// Special flags describing loop
|
||||||
enum ExtrusionLoopRole {
|
enum ExtrusionLoopRole {
|
||||||
elrDefault = 1 << 0,
|
elrDefault = 1 << 0,
|
||||||
|
@ -119,6 +124,12 @@ inline bool is_bridge(ExtrusionRole role) {
|
||||||
class ExtrusionEntity
|
class ExtrusionEntity
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
ExtrusionEntity() = default;
|
||||||
|
ExtrusionEntity(const ExtrusionEntity &rhs) { m_customize_flag = rhs.m_customize_flag; };
|
||||||
|
ExtrusionEntity(ExtrusionEntity &&rhs) { m_customize_flag = rhs.m_customize_flag; };
|
||||||
|
ExtrusionEntity &operator=(const ExtrusionEntity &rhs) { m_customize_flag = rhs.m_customize_flag; return *this; }
|
||||||
|
ExtrusionEntity &operator=(ExtrusionEntity &&rhs) { m_customize_flag = rhs.m_customize_flag; return *this; }
|
||||||
|
|
||||||
virtual ExtrusionRole role() const = 0;
|
virtual ExtrusionRole role() const = 0;
|
||||||
virtual bool is_collection() const { return false; }
|
virtual bool is_collection() const { return false; }
|
||||||
virtual bool is_loop() const { return false; }
|
virtual bool is_loop() const { return false; }
|
||||||
|
@ -154,6 +165,12 @@ public:
|
||||||
|
|
||||||
static std::string role_to_string(ExtrusionRole role);
|
static std::string role_to_string(ExtrusionRole role);
|
||||||
static ExtrusionRole string_to_role(const std::string_view role);
|
static ExtrusionRole string_to_role(const std::string_view role);
|
||||||
|
|
||||||
|
virtual CustomizeFlag get_customize_flag() const { return m_customize_flag; };
|
||||||
|
virtual void set_customize_flag(CustomizeFlag flag) { m_customize_flag = flag; };
|
||||||
|
|
||||||
|
protected:
|
||||||
|
CustomizeFlag m_customize_flag{CustomizeFlag::cfNone};
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector<ExtrusionEntity*> ExtrusionEntitiesPtr;
|
typedef std::vector<ExtrusionEntity*> ExtrusionEntitiesPtr;
|
||||||
|
@ -178,7 +195,8 @@ public:
|
||||||
ExtrusionPath(double overhang_degree, int curve_degree, ExtrusionRole role, double mm3_per_mm, float width, float height) : overhang_degree(overhang_degree), curve_degree(curve_degree), mm3_per_mm(mm3_per_mm), width(width), height(height), m_role(role) {}
|
ExtrusionPath(double overhang_degree, int curve_degree, ExtrusionRole role, double mm3_per_mm, float width, float height) : overhang_degree(overhang_degree), curve_degree(curve_degree), mm3_per_mm(mm3_per_mm), width(width), height(height), m_role(role) {}
|
||||||
|
|
||||||
ExtrusionPath(const ExtrusionPath &rhs)
|
ExtrusionPath(const ExtrusionPath &rhs)
|
||||||
: polyline(rhs.polyline)
|
: ExtrusionEntity(rhs)
|
||||||
|
, polyline(rhs.polyline)
|
||||||
, overhang_degree(rhs.overhang_degree)
|
, overhang_degree(rhs.overhang_degree)
|
||||||
, curve_degree(rhs.curve_degree)
|
, curve_degree(rhs.curve_degree)
|
||||||
, mm3_per_mm(rhs.mm3_per_mm)
|
, mm3_per_mm(rhs.mm3_per_mm)
|
||||||
|
@ -190,7 +208,8 @@ public:
|
||||||
, m_no_extrusion(rhs.m_no_extrusion)
|
, m_no_extrusion(rhs.m_no_extrusion)
|
||||||
{}
|
{}
|
||||||
ExtrusionPath(ExtrusionPath &&rhs)
|
ExtrusionPath(ExtrusionPath &&rhs)
|
||||||
: polyline(std::move(rhs.polyline))
|
: ExtrusionEntity(rhs)
|
||||||
|
, polyline(std::move(rhs.polyline))
|
||||||
, overhang_degree(rhs.overhang_degree)
|
, overhang_degree(rhs.overhang_degree)
|
||||||
, curve_degree(rhs.curve_degree)
|
, curve_degree(rhs.curve_degree)
|
||||||
, mm3_per_mm(rhs.mm3_per_mm)
|
, mm3_per_mm(rhs.mm3_per_mm)
|
||||||
|
@ -202,7 +221,8 @@ public:
|
||||||
, m_no_extrusion(rhs.m_no_extrusion)
|
, m_no_extrusion(rhs.m_no_extrusion)
|
||||||
{}
|
{}
|
||||||
ExtrusionPath(const Polyline &polyline, const ExtrusionPath &rhs)
|
ExtrusionPath(const Polyline &polyline, const ExtrusionPath &rhs)
|
||||||
: polyline(polyline)
|
: ExtrusionEntity(rhs)
|
||||||
|
, polyline(polyline)
|
||||||
, overhang_degree(rhs.overhang_degree)
|
, overhang_degree(rhs.overhang_degree)
|
||||||
, curve_degree(rhs.curve_degree)
|
, curve_degree(rhs.curve_degree)
|
||||||
, mm3_per_mm(rhs.mm3_per_mm)
|
, mm3_per_mm(rhs.mm3_per_mm)
|
||||||
|
@ -214,7 +234,8 @@ public:
|
||||||
, m_no_extrusion(rhs.m_no_extrusion)
|
, m_no_extrusion(rhs.m_no_extrusion)
|
||||||
{}
|
{}
|
||||||
ExtrusionPath(Polyline &&polyline, const ExtrusionPath &rhs)
|
ExtrusionPath(Polyline &&polyline, const ExtrusionPath &rhs)
|
||||||
: polyline(std::move(polyline))
|
: ExtrusionEntity(rhs)
|
||||||
|
, polyline(std::move(polyline))
|
||||||
, overhang_degree(rhs.overhang_degree)
|
, overhang_degree(rhs.overhang_degree)
|
||||||
, curve_degree(rhs.curve_degree)
|
, curve_degree(rhs.curve_degree)
|
||||||
, mm3_per_mm(rhs.mm3_per_mm)
|
, mm3_per_mm(rhs.mm3_per_mm)
|
||||||
|
@ -227,6 +248,7 @@ public:
|
||||||
{}
|
{}
|
||||||
|
|
||||||
ExtrusionPath& operator=(const ExtrusionPath& rhs) {
|
ExtrusionPath& operator=(const ExtrusionPath& rhs) {
|
||||||
|
ExtrusionEntity::operator=(rhs);
|
||||||
m_can_reverse = rhs.m_can_reverse;
|
m_can_reverse = rhs.m_can_reverse;
|
||||||
m_role = rhs.m_role;
|
m_role = rhs.m_role;
|
||||||
m_no_extrusion = rhs.m_no_extrusion;
|
m_no_extrusion = rhs.m_no_extrusion;
|
||||||
|
@ -240,6 +262,7 @@ public:
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
ExtrusionPath& operator=(ExtrusionPath&& rhs) {
|
ExtrusionPath& operator=(ExtrusionPath&& rhs) {
|
||||||
|
ExtrusionEntity::operator=(rhs);
|
||||||
m_can_reverse = rhs.m_can_reverse;
|
m_can_reverse = rhs.m_can_reverse;
|
||||||
m_role = rhs.m_role;
|
m_role = rhs.m_role;
|
||||||
m_no_extrusion = rhs.m_no_extrusion;
|
m_no_extrusion = rhs.m_no_extrusion;
|
||||||
|
@ -441,6 +464,7 @@ public:
|
||||||
ExtrusionLoop(ExtrusionLoopRole role = elrDefault) : m_loop_role(role) {}
|
ExtrusionLoop(ExtrusionLoopRole role = elrDefault) : m_loop_role(role) {}
|
||||||
ExtrusionLoop(const ExtrusionPaths &paths, ExtrusionLoopRole role = elrDefault) : paths(paths), m_loop_role(role) {}
|
ExtrusionLoop(const ExtrusionPaths &paths, ExtrusionLoopRole role = elrDefault) : paths(paths), m_loop_role(role) {}
|
||||||
ExtrusionLoop(ExtrusionPaths &&paths, ExtrusionLoopRole role = elrDefault) : paths(std::move(paths)), m_loop_role(role) {}
|
ExtrusionLoop(ExtrusionPaths &&paths, ExtrusionLoopRole role = elrDefault) : paths(std::move(paths)), m_loop_role(role) {}
|
||||||
|
ExtrusionLoop(ExtrusionPaths &&paths, ExtrusionLoopRole role, CustomizeFlag flag) : paths(std::move(paths)), m_loop_role(role) { m_customize_flag = flag; }
|
||||||
ExtrusionLoop(const ExtrusionPath &path, ExtrusionLoopRole role = elrDefault) : m_loop_role(role)
|
ExtrusionLoop(const ExtrusionPath &path, ExtrusionLoopRole role = elrDefault) : m_loop_role(role)
|
||||||
{ this->paths.push_back(path); }
|
{ this->paths.push_back(path); }
|
||||||
ExtrusionLoop(const ExtrusionPath &&path, ExtrusionLoopRole role = elrDefault) : m_loop_role(role)
|
ExtrusionLoop(const ExtrusionPath &&path, ExtrusionLoopRole role = elrDefault) : m_loop_role(role)
|
||||||
|
@ -472,6 +496,7 @@ public:
|
||||||
// Test, whether the point is extruded by a bridging flow.
|
// Test, whether the point is extruded by a bridging flow.
|
||||||
// This used to be used to avoid placing seams on overhangs, but now the EdgeGrid is used instead.
|
// This used to be used to avoid placing seams on overhangs, but now the EdgeGrid is used instead.
|
||||||
bool has_overhang_point(const Point &point) const;
|
bool has_overhang_point(const Point &point) const;
|
||||||
|
bool has_overhang_paths() const;
|
||||||
ExtrusionRole role() const override { return this->paths.empty() ? erNone : this->paths.front().role(); }
|
ExtrusionRole role() const override { return this->paths.empty() ? erNone : this->paths.front().role(); }
|
||||||
ExtrusionLoopRole loop_role() const { return m_loop_role; }
|
ExtrusionLoopRole loop_role() const { return m_loop_role; }
|
||||||
void set_loop_role(ExtrusionLoopRole role) { m_loop_role = role; }
|
void set_loop_role(ExtrusionLoopRole role) { m_loop_role = role; }
|
||||||
|
|
|
@ -4388,6 +4388,7 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
|
||||||
const double clip_length = m_enable_loop_clipping && !enable_seam_slope ? seam_gap : 0;
|
const double clip_length = m_enable_loop_clipping && !enable_seam_slope ? seam_gap : 0;
|
||||||
// get paths
|
// get paths
|
||||||
ExtrusionPaths paths;
|
ExtrusionPaths paths;
|
||||||
|
bool set_holes_and_compensation_speed = loop.get_customize_flag() && !loop.has_overhang_paths();
|
||||||
loop.clip_end(clip_length, &paths);
|
loop.clip_end(clip_length, &paths);
|
||||||
if (paths.empty()) return "";
|
if (paths.empty()) return "";
|
||||||
|
|
||||||
|
@ -4449,7 +4450,7 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
|
||||||
smooth_speed_discontinuity_area(new_loop.paths);
|
smooth_speed_discontinuity_area(new_loop.paths);
|
||||||
// Then extrude it
|
// Then extrude it
|
||||||
for (const auto &p : new_loop.get_all_paths()) {
|
for (const auto &p : new_loop.get_all_paths()) {
|
||||||
gcode += this->_extrude(*p, description, speed_for_path(*p));
|
gcode += this->_extrude(*p, description, speed_for_path(*p), set_holes_and_compensation_speed);
|
||||||
}
|
}
|
||||||
set_last_scarf_seam_flag(true);
|
set_last_scarf_seam_flag(true);
|
||||||
|
|
||||||
|
@ -4474,7 +4475,7 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
|
||||||
smooth_speed_discontinuity_area(paths);
|
smooth_speed_discontinuity_area(paths);
|
||||||
|
|
||||||
for (ExtrusionPaths::iterator path = paths.begin(); path != paths.end(); ++path) {
|
for (ExtrusionPaths::iterator path = paths.begin(); path != paths.end(); ++path) {
|
||||||
gcode += this->_extrude(*path, description, speed_for_path(*path));
|
gcode += this->_extrude(*path, description, speed_for_path(*path), set_holes_and_compensation_speed);
|
||||||
}
|
}
|
||||||
set_last_scarf_seam_flag(false);
|
set_last_scarf_seam_flag(false);
|
||||||
}
|
}
|
||||||
|
@ -5006,7 +5007,7 @@ void GCode::smooth_speed_discontinuity_area(ExtrusionPaths &paths) {
|
||||||
paths = std::move(inter_paths);
|
paths = std::move(inter_paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GCode::_extrude(const ExtrusionPath &path, std::string description, double speed, bool is_first_slope)
|
std::string GCode::_extrude(const ExtrusionPath &path, std::string description, double speed, bool set_holes_and_compensation_speed, bool is_first_slope)
|
||||||
{
|
{
|
||||||
std::string gcode;
|
std::string gcode;
|
||||||
|
|
||||||
|
@ -5099,7 +5100,10 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
||||||
if (speed == -1) {
|
if (speed == -1) {
|
||||||
if (path.role() == erPerimeter) {
|
if (path.role() == erPerimeter) {
|
||||||
speed = m_config.inner_wall_speed.get_at(cur_extruder_index());
|
speed = m_config.inner_wall_speed.get_at(cur_extruder_index());
|
||||||
if (m_config.detect_overhang_wall && m_config.smooth_speed_discontinuity_area && path.smooth_speed != 0)
|
//reset speed by auto compensation speed
|
||||||
|
if(set_holes_and_compensation_speed) {
|
||||||
|
speed = m_config.circle_compensation_speed;
|
||||||
|
}else if (m_config.detect_overhang_wall && m_config.smooth_speed_discontinuity_area && path.smooth_speed != 0)
|
||||||
speed = path.smooth_speed;
|
speed = path.smooth_speed;
|
||||||
else if (m_config.enable_overhang_speed.get_at(cur_extruder_index())) {
|
else if (m_config.enable_overhang_speed.get_at(cur_extruder_index())) {
|
||||||
double new_speed = 0;
|
double new_speed = 0;
|
||||||
|
@ -5108,12 +5112,14 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
||||||
}
|
}
|
||||||
} else if (path.role() == erExternalPerimeter) {
|
} else if (path.role() == erExternalPerimeter) {
|
||||||
speed = m_config.outer_wall_speed.get_at(cur_extruder_index());
|
speed = m_config.outer_wall_speed.get_at(cur_extruder_index());
|
||||||
if (m_config.detect_overhang_wall && m_config.smooth_speed_discontinuity_area && path.smooth_speed != 0)
|
// reset speed by auto compensation speed
|
||||||
|
if (set_holes_and_compensation_speed) {
|
||||||
|
speed = m_config.circle_compensation_speed;
|
||||||
|
} else if (m_config.detect_overhang_wall && m_config.smooth_speed_discontinuity_area && path.smooth_speed != 0)
|
||||||
speed = path.smooth_speed;
|
speed = path.smooth_speed;
|
||||||
else if (m_config.enable_overhang_speed.get_at(cur_extruder_index())) {
|
else if (m_config.enable_overhang_speed.get_at(cur_extruder_index())) {
|
||||||
double new_speed = 0;
|
double new_speed = 0;
|
||||||
new_speed = get_overhang_degree_corr_speed(speed, path.overhang_degree);
|
new_speed = get_overhang_degree_corr_speed(speed, path.overhang_degree);
|
||||||
|
|
||||||
speed = new_speed == 0.0 ? speed : new_speed;
|
speed = new_speed == 0.0 ? speed : new_speed;
|
||||||
}
|
}
|
||||||
} else if (path.role() == erOverhangPerimeter && path.overhang_degree == 5) {
|
} else if (path.role() == erOverhangPerimeter && path.overhang_degree == 5) {
|
||||||
|
@ -5198,6 +5204,10 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
||||||
char buf[64];
|
char buf[64];
|
||||||
assert(is_decimal_separator_point());
|
assert(is_decimal_separator_point());
|
||||||
|
|
||||||
|
|
||||||
|
if (set_holes_and_compensation_speed)
|
||||||
|
gcode += "; Slow Down Start\n";
|
||||||
|
|
||||||
if (path.role() != m_last_processor_extrusion_role) {
|
if (path.role() != m_last_processor_extrusion_role) {
|
||||||
m_last_processor_extrusion_role = path.role();
|
m_last_processor_extrusion_role = path.role();
|
||||||
sprintf(buf, ";%s%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Role).c_str(), ExtrusionEntity::role_to_string(m_last_processor_extrusion_role).c_str());
|
sprintf(buf, ";%s%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Role).c_str(), ExtrusionEntity::role_to_string(m_last_processor_extrusion_role).c_str());
|
||||||
|
@ -5349,6 +5359,10 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (set_holes_and_compensation_speed) {
|
||||||
|
gcode += "; Slow Down End\n";
|
||||||
|
}
|
||||||
|
|
||||||
this->set_last_pos(path.last_point());
|
this->set_last_pos(path.last_point());
|
||||||
return gcode;
|
return gcode;
|
||||||
}
|
}
|
||||||
|
|
|
@ -560,7 +560,7 @@ private:
|
||||||
// BBS
|
// BBS
|
||||||
int get_bed_temperature(const int extruder_id, const bool is_first_layer, const BedType bed_type) const;
|
int get_bed_temperature(const int extruder_id, const bool is_first_layer, const BedType bed_type) const;
|
||||||
|
|
||||||
std::string _extrude(const ExtrusionPath &path, std::string description = "", double speed = -1, bool is_first_slope = false);
|
std::string _extrude(const ExtrusionPath &path, std::string description = "", double speed = -1, bool set_holes_and_compensation_speed = false, bool is_first_slope = false);
|
||||||
ExtrusionPaths set_speed_transition(ExtrusionPaths &paths);
|
ExtrusionPaths set_speed_transition(ExtrusionPaths &paths);
|
||||||
ExtrusionPaths split_and_mapping_speed(double &other_path_v, double &final_v, ExtrusionPath &this_path, double max_smooth_length, bool split_from_left = true);
|
ExtrusionPaths split_and_mapping_speed(double &other_path_v, double &final_v, ExtrusionPath &this_path, double max_smooth_length, bool split_from_left = true);
|
||||||
double get_path_speed(const ExtrusionPath &path);
|
double get_path_speed(const ExtrusionPath &path);
|
||||||
|
|
|
@ -128,7 +128,7 @@ std::vector<PerExtruderAdjustments> GCodeEditer::parse_layer_gcode(
|
||||||
std::string cooling_node_label = "; COOLING_NODE: ";
|
std::string cooling_node_label = "; COOLING_NODE: ";
|
||||||
bool append_wall_ptr = false;
|
bool append_wall_ptr = false;
|
||||||
bool append_inner_wall_ptr = false;
|
bool append_inner_wall_ptr = false;
|
||||||
|
bool not_join_cooling = false;
|
||||||
std::pair<int, int> node_pos;
|
std::pair<int, int> node_pos;
|
||||||
int line_idx = -1;
|
int line_idx = -1;
|
||||||
for (; *line_start != 0; line_start = line_end)
|
for (; *line_start != 0; line_start = line_end)
|
||||||
|
@ -199,7 +199,7 @@ std::vector<PerExtruderAdjustments> GCodeEditer::parse_layer_gcode(
|
||||||
|
|
||||||
if (wipe)
|
if (wipe)
|
||||||
line.type |= CoolingLine::TYPE_WIPE;
|
line.type |= CoolingLine::TYPE_WIPE;
|
||||||
if (boost::contains(sline, ";_EXTRUDE_SET_SPEED") && ! wipe) {
|
if (boost::contains(sline, ";_EXTRUDE_SET_SPEED") && !wipe && !not_join_cooling) {
|
||||||
line.type |= CoolingLine::TYPE_ADJUSTABLE;
|
line.type |= CoolingLine::TYPE_ADJUSTABLE;
|
||||||
active_speed_modifier = adjustment->lines.size();
|
active_speed_modifier = adjustment->lines.size();
|
||||||
}
|
}
|
||||||
|
@ -279,6 +279,10 @@ std::vector<PerExtruderAdjustments> GCodeEditer::parse_layer_gcode(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
current_pos = std::move(new_pos);
|
current_pos = std::move(new_pos);
|
||||||
|
} else if (boost::starts_with(sline, "; Slow Down Start")) {
|
||||||
|
not_join_cooling = true;
|
||||||
|
} else if (boost::starts_with(sline, "; Slow Down End")) {
|
||||||
|
not_join_cooling = false;
|
||||||
} else if (boost::starts_with(sline, ";_EXTRUDE_END")) {
|
} else if (boost::starts_with(sline, ";_EXTRUDE_END")) {
|
||||||
line.type = CoolingLine::TYPE_EXTRUDE_END;
|
line.type = CoolingLine::TYPE_EXTRUDE_END;
|
||||||
active_speed_modifier = size_t(-1);
|
active_speed_modifier = size_t(-1);
|
||||||
|
|
|
@ -197,7 +197,13 @@ void Layer::make_perimeters()
|
||||||
|
|
||||||
if (layerms.size() == 1) { // optimization
|
if (layerms.size() == 1) { // optimization
|
||||||
(*layerm)->fill_surfaces.surfaces.clear();
|
(*layerm)->fill_surfaces.surfaces.clear();
|
||||||
(*layerm)->make_perimeters((*layerm)->slices, &(*layerm)->fill_surfaces, &(*layerm)->fill_no_overlap_expolygons, this->loop_nodes);
|
if (this->object()->config().enable_circle_compensation) {
|
||||||
|
SurfaceCollection copy_slices = (*layerm)->slices;
|
||||||
|
(*layerm)->auto_circle_compensation(copy_slices);
|
||||||
|
(*layerm)->make_perimeters(copy_slices, &(*layerm)->fill_surfaces, &(*layerm)->fill_no_overlap_expolygons, this->loop_nodes);
|
||||||
|
} else
|
||||||
|
(*layerm)->make_perimeters((*layerm)->slices, &(*layerm)->fill_surfaces, &(*layerm)->fill_no_overlap_expolygons, this->loop_nodes);
|
||||||
|
|
||||||
(*layerm)->fill_expolygons = to_expolygons((*layerm)->fill_surfaces.surfaces);
|
(*layerm)->fill_expolygons = to_expolygons((*layerm)->fill_surfaces.surfaces);
|
||||||
} else {
|
} else {
|
||||||
SurfaceCollection new_slices;
|
SurfaceCollection new_slices;
|
||||||
|
@ -221,6 +227,8 @@ void Layer::make_perimeters()
|
||||||
SurfaceCollection fill_surfaces;
|
SurfaceCollection fill_surfaces;
|
||||||
//BBS
|
//BBS
|
||||||
ExPolygons fill_no_overlap;
|
ExPolygons fill_no_overlap;
|
||||||
|
if (this->object()->config().enable_circle_compensation)
|
||||||
|
layerm_config->auto_circle_compensation(new_slices);
|
||||||
layerm_config->make_perimeters(new_slices, &fill_surfaces, &fill_no_overlap, this->loop_nodes);
|
layerm_config->make_perimeters(new_slices, &fill_surfaces, &fill_no_overlap, this->loop_nodes);
|
||||||
|
|
||||||
// assign fill_surfaces to each layer
|
// assign fill_surfaces to each layer
|
||||||
|
|
|
@ -80,6 +80,7 @@ public:
|
||||||
void slices_to_fill_surfaces_clipped();
|
void slices_to_fill_surfaces_clipped();
|
||||||
void prepare_fill_surfaces();
|
void prepare_fill_surfaces();
|
||||||
//BBS
|
//BBS
|
||||||
|
void auto_circle_compensation(SurfaceCollection &slices);
|
||||||
void make_perimeters(const SurfaceCollection &slices, SurfaceCollection* fill_surfaces, ExPolygons* fill_no_overlap, std::vector<LoopNode> &loop_nodes);
|
void make_perimeters(const SurfaceCollection &slices, SurfaceCollection* fill_surfaces, ExPolygons* fill_no_overlap, std::vector<LoopNode> &loop_nodes);
|
||||||
void process_external_surfaces(const Layer *lower_layer, const Polygons *lower_layer_covered);
|
void process_external_surfaces(const Layer *lower_layer, const Polygons *lower_layer_covered);
|
||||||
double infill_area_threshold() const;
|
double infill_area_threshold() const;
|
||||||
|
|
|
@ -64,12 +64,73 @@ void LayerRegion::slices_to_fill_surfaces_clipped()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LayerRegion::auto_circle_compensation(SurfaceCollection& slices)
|
||||||
|
{
|
||||||
|
const PrintObjectConfig &object_config = this->layer()->object()->config();
|
||||||
|
double max_deviation = object_config.max_deviation * 1e6;
|
||||||
|
double max_variance = object_config.max_variance * 1e6;
|
||||||
|
double limited_speed = object_config.circle_compensation_speed;
|
||||||
|
|
||||||
|
double counter_speed_coef = object_config.counter_coef_1 / 1e6;
|
||||||
|
double counter_diameter_coef = object_config.counter_coef_2 / 1e6;
|
||||||
|
double counter_compensate_coef = object_config.counter_coef_3;
|
||||||
|
|
||||||
|
double hole_speed_coef = object_config.hole_coef_1 / 1e6;
|
||||||
|
double hole_diameter_coef = object_config.hole_coef_2 / 1e6;
|
||||||
|
double hole_compensate_coef = object_config.hole_coef_3;
|
||||||
|
|
||||||
|
double counter_limit_min_value = object_config.counter_limit_min;
|
||||||
|
double counter_limit_max_value = object_config.counter_limit_max;
|
||||||
|
double hole_limit_min_value = object_config.hole_limit_min;
|
||||||
|
double hole_limit_max_value = object_config.hole_limit_max;
|
||||||
|
|
||||||
|
double diameter_limit_value = object_config.diameter_limit;
|
||||||
|
|
||||||
|
for (Surface &surface : slices.surfaces) {
|
||||||
|
Point center;
|
||||||
|
double diameter = 0;
|
||||||
|
if (surface.expolygon.contour.is_approx_circle(max_deviation, max_variance, center, diameter)) {
|
||||||
|
double offset_value = counter_speed_coef * limited_speed + counter_diameter_coef * diameter + counter_compensate_coef;
|
||||||
|
if (offset_value < counter_limit_min_value) {
|
||||||
|
offset_value = counter_limit_min_value;
|
||||||
|
} else if (offset_value > counter_limit_max_value) {
|
||||||
|
offset_value = counter_limit_max_value;
|
||||||
|
}
|
||||||
|
Polygons offseted_polys = offset(surface.expolygon.contour, offset_value);
|
||||||
|
if (offseted_polys.size() == 1) {
|
||||||
|
surface.expolygon.contour = offseted_polys[0];
|
||||||
|
if (diameter < diameter_limit_value * 1e6)
|
||||||
|
surface.counter_circle_compensation = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < surface.expolygon.holes.size(); ++i) {
|
||||||
|
Polygon &hole = surface.expolygon.holes[i];
|
||||||
|
if (hole.is_approx_circle(max_deviation, max_variance, center, diameter)) {
|
||||||
|
double offset_value = hole_speed_coef * limited_speed + hole_diameter_coef * diameter + hole_compensate_coef;
|
||||||
|
if (offset_value < hole_limit_min_value) {
|
||||||
|
offset_value = hole_limit_min_value;
|
||||||
|
} else if (offset_value > hole_limit_max_value) {
|
||||||
|
offset_value = hole_limit_max_value;
|
||||||
|
}
|
||||||
|
// positive value means shrinking hole, which oppsite to contour
|
||||||
|
offset_value = -offset_value;
|
||||||
|
Polygons offseted_polys = offset(hole, offset_value);
|
||||||
|
if (offseted_polys.size() == 1) {
|
||||||
|
hole = offseted_polys[0];
|
||||||
|
if (diameter < diameter_limit_value * 1e6)
|
||||||
|
surface.holes_circle_compensation.push_back(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void LayerRegion::make_perimeters(const SurfaceCollection &slices, SurfaceCollection *fill_surfaces, ExPolygons *fill_no_overlap, std::vector<LoopNode> &loop_nodes)
|
void LayerRegion::make_perimeters(const SurfaceCollection &slices, SurfaceCollection *fill_surfaces, ExPolygons *fill_no_overlap, std::vector<LoopNode> &loop_nodes)
|
||||||
{
|
{
|
||||||
this->perimeters.clear();
|
this->perimeters.clear();
|
||||||
this->thin_fills.clear();
|
this->thin_fills.clear();
|
||||||
|
|
||||||
const PrintConfig &print_config = this->layer()->object()->print()->config();
|
const PrintConfig & print_config = this->layer()->object()->print()->config();
|
||||||
const PrintRegionConfig ®ion_config = this->region().config();
|
const PrintRegionConfig ®ion_config = this->region().config();
|
||||||
const PrintObjectConfig& object_config = this->layer()->object()->config();
|
const PrintObjectConfig& object_config = this->layer()->object()->config();
|
||||||
// This needs to be in sync with PrintObject::_slice() slicing_mode_normal_below_layer!
|
// This needs to be in sync with PrintObject::_slice() slicing_mode_normal_below_layer!
|
||||||
|
@ -87,7 +148,6 @@ void LayerRegion::make_perimeters(const SurfaceCollection &slices, SurfaceCollec
|
||||||
&this->layer()->object()->config(),
|
&this->layer()->object()->config(),
|
||||||
&print_config,
|
&print_config,
|
||||||
spiral_mode,
|
spiral_mode,
|
||||||
|
|
||||||
// output:
|
// output:
|
||||||
&this->perimeters,
|
&this->perimeters,
|
||||||
&this->thin_fills,
|
&this->thin_fills,
|
||||||
|
@ -1049,4 +1109,3 @@ void LayerRegion::simplify_loop(ExtrusionLoop* loop)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,14 +46,16 @@ public:
|
||||||
// BBS: is perimeter using smaller width
|
// BBS: is perimeter using smaller width
|
||||||
bool is_smaller_width_perimeter;
|
bool is_smaller_width_perimeter;
|
||||||
// Depth in the hierarchy. External perimeter has depth = 0. An external perimeter could be both a contour and a hole.
|
// Depth in the hierarchy. External perimeter has depth = 0. An external perimeter could be both a contour and a hole.
|
||||||
unsigned short depth;
|
unsigned short depth;
|
||||||
// Should this contur be fuzzyfied on path generation?
|
// Should this contur be fuzzyfied on path generation?
|
||||||
bool fuzzify;
|
bool fuzzify;
|
||||||
|
// Slow down speed for circle
|
||||||
|
bool need_circle_compensation = false;
|
||||||
// Children contour, may be both CCW and CW oriented (outer contours or holes).
|
// Children contour, may be both CCW and CW oriented (outer contours or holes).
|
||||||
std::vector<PerimeterGeneratorLoop> children;
|
std::vector<PerimeterGeneratorLoop> children;
|
||||||
|
|
||||||
PerimeterGeneratorLoop(const Polygon &polygon, unsigned short depth, bool is_contour, bool fuzzify, bool is_small_width_perimeter = false) :
|
PerimeterGeneratorLoop(const Polygon &polygon, unsigned short depth, bool is_contour, bool fuzzify, bool is_small_width_perimeter = false, bool need_circle_compensation_ = false) :
|
||||||
polygon(polygon), is_contour(is_contour), is_smaller_width_perimeter(is_small_width_perimeter), depth(depth), fuzzify(fuzzify) {}
|
polygon(polygon), is_contour(is_contour), is_smaller_width_perimeter(is_small_width_perimeter), depth(depth), fuzzify(fuzzify), need_circle_compensation(need_circle_compensation_) {}
|
||||||
// External perimeter. It may be CCW or CW oriented (outer contour or hole contour).
|
// External perimeter. It may be CCW or CW oriented (outer contour or hole contour).
|
||||||
bool is_external() const { return this->depth == 0; }
|
bool is_external() const { return this->depth == 0; }
|
||||||
// An island, which may have holes, but it does not have another internal island.
|
// An island, which may have holes, but it does not have another internal island.
|
||||||
|
@ -452,6 +454,7 @@ static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perime
|
||||||
for (const PerimeterGeneratorLoop &loop : loops) {
|
for (const PerimeterGeneratorLoop &loop : loops) {
|
||||||
bool is_external = loop.is_external();
|
bool is_external = loop.is_external();
|
||||||
bool is_small_width = loop.is_smaller_width_perimeter;
|
bool is_small_width = loop.is_smaller_width_perimeter;
|
||||||
|
CustomizeFlag flag = loop.need_circle_compensation ? CustomizeFlag::cfCircleCompensation : CustomizeFlag::cfNone;
|
||||||
|
|
||||||
ExtrusionRole role;
|
ExtrusionRole role;
|
||||||
ExtrusionLoopRole loop_role;
|
ExtrusionLoopRole loop_role;
|
||||||
|
@ -631,7 +634,11 @@ static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perime
|
||||||
paths.emplace_back(std::move(path));
|
paths.emplace_back(std::move(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
coll.append(ExtrusionLoop(std::move(paths), loop_role));
|
for (ExtrusionPath& path : paths) {
|
||||||
|
path.set_customize_flag(flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
coll.append(ExtrusionLoop(std::move(paths), loop_role, flag));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Append thin walls to the nearest-neighbor search (only for first iteration)
|
// Append thin walls to the nearest-neighbor search (only for first iteration)
|
||||||
|
@ -1185,7 +1192,26 @@ void PerimeterGenerator::process_classic()
|
||||||
if (loop_number > 0 && ((this->object_config->top_one_wall_type != TopOneWallType::None && this->upper_slices == nullptr) || (this->object_config->only_one_wall_first_layer && layer_id == 0)))
|
if (loop_number > 0 && ((this->object_config->top_one_wall_type != TopOneWallType::None && this->upper_slices == nullptr) || (this->object_config->only_one_wall_first_layer && layer_id == 0)))
|
||||||
loop_number = 0;
|
loop_number = 0;
|
||||||
|
|
||||||
|
bool counter_circle_compensation = surface.counter_circle_compensation;
|
||||||
|
std::vector<Point> compensation_holes_centers;
|
||||||
|
for (size_t i = 0; i < surface.holes_circle_compensation.size(); ++i) {
|
||||||
|
Point center = surface.expolygon.holes[i].centroid();
|
||||||
|
compensation_holes_centers.emplace_back(center);
|
||||||
|
}
|
||||||
|
|
||||||
|
double eps = 1000;
|
||||||
|
auto is_compensation_hole = [&compensation_holes_centers, &eps](const Polygon &hole) -> bool {
|
||||||
|
auto iter = std::find_if(compensation_holes_centers.begin(), compensation_holes_centers.end(), [&hole, &eps](const Point &item) {
|
||||||
|
double distance = std::sqrt(std::pow(hole.centroid().x() - item.x(), 2) + std::pow(hole.centroid().y() - item.y(), 2));
|
||||||
|
return distance < eps;
|
||||||
|
});
|
||||||
|
|
||||||
|
return iter != compensation_holes_centers.end();
|
||||||
|
};
|
||||||
|
|
||||||
ExPolygons last = union_ex(surface.expolygon.simplify_p(surface_simplify_resolution));
|
ExPolygons last = union_ex(surface.expolygon.simplify_p(surface_simplify_resolution));
|
||||||
|
if (last.size() != 1)
|
||||||
|
counter_circle_compensation = false;
|
||||||
ExPolygons gaps;
|
ExPolygons gaps;
|
||||||
ExPolygons top_fills;
|
ExPolygons top_fills;
|
||||||
ExPolygons fill_clip;
|
ExPolygons fill_clip;
|
||||||
|
@ -1304,12 +1330,11 @@ void PerimeterGenerator::process_classic()
|
||||||
// outer contour may overlap with itself.
|
// outer contour may overlap with itself.
|
||||||
//FIXME evaluate the overlaps, annotate each point with an overlap depth,
|
//FIXME evaluate the overlaps, annotate each point with an overlap depth,
|
||||||
// compensate for the depth of intersection.
|
// compensate for the depth of intersection.
|
||||||
contours[i].emplace_back(expolygon.contour, i, true, fuzzify_contours);
|
contours[i].emplace_back(PerimeterGeneratorLoop(expolygon.contour, i, true, fuzzify_contours, false, counter_circle_compensation));
|
||||||
|
|
||||||
if (!expolygon.holes.empty()) {
|
if (!expolygon.holes.empty()) {
|
||||||
holes[i].reserve(holes[i].size() + expolygon.holes.size());
|
holes[i].reserve(holes[i].size() + expolygon.holes.size());
|
||||||
for (const Polygon& hole : expolygon.holes)
|
for (const Polygon &hole : expolygon.holes)
|
||||||
holes[i].emplace_back(hole, i, false, fuzzify_holes);
|
holes[i].emplace_back(hole, i, false, fuzzify_holes, false, is_compensation_hole(hole));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1345,11 +1370,11 @@ void PerimeterGenerator::process_classic()
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const ExPolygon& expolygon : offsets_with_smaller_width) {
|
for (const ExPolygon& expolygon : offsets_with_smaller_width) {
|
||||||
contours[i].emplace_back(PerimeterGeneratorLoop(expolygon.contour, i, true, fuzzify_contours, true));
|
contours[i].emplace_back(PerimeterGeneratorLoop(expolygon.contour, i, true, fuzzify_contours, true, counter_circle_compensation));
|
||||||
if (!expolygon.holes.empty()) {
|
if (!expolygon.holes.empty()) {
|
||||||
holes[i].reserve(holes[i].size() + expolygon.holes.size());
|
holes[i].reserve(holes[i].size() + expolygon.holes.size());
|
||||||
for (const Polygon& hole : expolygon.holes)
|
for (const Polygon& hole : expolygon.holes)
|
||||||
holes[i].emplace_back(PerimeterGeneratorLoop(hole, i, false, fuzzify_contours, true));
|
holes[i].emplace_back(PerimeterGeneratorLoop(hole, i, false, fuzzify_contours, true, is_compensation_hole(hole)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,6 +99,39 @@ void Polygon::douglas_peucker(double tolerance)
|
||||||
this->points = std::move(p);
|
this->points = std::move(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Polygon::is_approx_circle(double max_deviation, double max_variance, Point ¢er, double &diameter) const
|
||||||
|
{
|
||||||
|
if (this->points.size() < 8) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
center = centroid();
|
||||||
|
std::vector<double> distances;
|
||||||
|
for (const auto &point : this->points) {
|
||||||
|
double distance = std::sqrt(std::pow(point.x() - center.x(), 2) + std::pow(point.y() - center.y(), 2));
|
||||||
|
distances.push_back(distance);
|
||||||
|
}
|
||||||
|
|
||||||
|
double max_dist = *std::max_element(distances.begin(), distances.end());
|
||||||
|
double min_dist = *std::min_element(distances.begin(), distances.end());
|
||||||
|
|
||||||
|
if ((max_dist - min_dist) > max_deviation) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
double avg_dist = std::accumulate(distances.begin(), distances.end(), 0.0) / distances.size();
|
||||||
|
double variance = 0;
|
||||||
|
for (double d : distances) { variance += std::pow(d - avg_dist, 2); }
|
||||||
|
variance /= distances.size();
|
||||||
|
|
||||||
|
if (variance > max_variance) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
diameter = 2 * avg_dist;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
Polygons Polygon::simplify(double tolerance) const
|
Polygons Polygon::simplify(double tolerance) const
|
||||||
{
|
{
|
||||||
// Works on CCW polygons only, CW contour will be reoriented to CCW by Clipper's simplify_polygons()!
|
// Works on CCW polygons only, CW contour will be reoriented to CCW by Clipper's simplify_polygons()!
|
||||||
|
|
|
@ -61,6 +61,10 @@ public:
|
||||||
bool is_valid() const { return this->points.size() >= 3; }
|
bool is_valid() const { return this->points.size() >= 3; }
|
||||||
void douglas_peucker(double tolerance);
|
void douglas_peucker(double tolerance);
|
||||||
|
|
||||||
|
// Point ¢er : out, the center of circle
|
||||||
|
// double &diameter: out, the diameter of circle
|
||||||
|
bool is_approx_circle(double max_deviation, double max_variance, Point ¢er, double &diameter) const;
|
||||||
|
|
||||||
// Does an unoriented polygon contain a point?
|
// Does an unoriented polygon contain a point?
|
||||||
bool contains(const Point &point) const { return Slic3r::contains(*this, point, true); }
|
bool contains(const Point &point) const { return Slic3r::contains(*this, point, true); }
|
||||||
// Approximate on boundary test.
|
// Approximate on boundary test.
|
||||||
|
|
|
@ -880,6 +880,9 @@ static std::vector<std::string> s_Preset_print_options {
|
||||||
"top_surface_line_width", "support_line_width", "infill_wall_overlap", "bridge_flow",
|
"top_surface_line_width", "support_line_width", "infill_wall_overlap", "bridge_flow",
|
||||||
"elefant_foot_compensation", "xy_contour_compensation", "xy_hole_compensation", "resolution", "enable_prime_tower",
|
"elefant_foot_compensation", "xy_contour_compensation", "xy_hole_compensation", "resolution", "enable_prime_tower",
|
||||||
"prime_tower_width", "prime_tower_brim_width", "prime_tower_outer_first", "prime_volume",
|
"prime_tower_width", "prime_tower_brim_width", "prime_tower_outer_first", "prime_volume",
|
||||||
|
"enable_circle_compensation", "circle_compensation_speed", "max_deviation", "max_variance",
|
||||||
|
"counter_coef_1", "counter_coef_2", "counter_coef_3", "hole_coef_1", "hole_coef_2", "hole_coef_3",
|
||||||
|
"counter_limit_min", "counter_limit_max", "hole_limit_min", "hole_limit_max", "diameter_limit",
|
||||||
"wipe_tower_no_sparse_layers", "compatible_printers", "compatible_printers_condition", "inherits",
|
"wipe_tower_no_sparse_layers", "compatible_printers", "compatible_printers_condition", "inherits",
|
||||||
"flush_into_infill", "flush_into_objects", "flush_into_support","process_notes",
|
"flush_into_infill", "flush_into_objects", "flush_into_support","process_notes",
|
||||||
// BBS
|
// BBS
|
||||||
|
|
|
@ -4164,8 +4164,100 @@ void PrintConfigDef::init_fff_params()
|
||||||
def->mode = comSimple;
|
def->mode = comSimple;
|
||||||
def->set_default_value(new ConfigOptionBool(false));
|
def->set_default_value(new ConfigOptionBool(false));
|
||||||
|
|
||||||
|
def = this->add("enable_circle_compensation", coBool);
|
||||||
|
def->label = L("Auto holes-contour compensation");
|
||||||
|
def->tooltip = L("enable_circle_compensation");
|
||||||
|
def->mode = comAdvanced;
|
||||||
|
def->set_default_value(new ConfigOptionBool(false));
|
||||||
|
|
||||||
|
def = this->add("circle_compensation_speed", coFloat);
|
||||||
|
def->label = L("Circle Compensation Speed");
|
||||||
|
def->tooltip = L("circle_compensation_speed");
|
||||||
|
def->sidetext = L("mm/s");
|
||||||
|
def->min = 0;
|
||||||
|
def->set_default_value(new ConfigOptionFloat(200));
|
||||||
|
|
||||||
|
def = this->add("max_deviation", coFloat);
|
||||||
|
def->label = L("Deviation");
|
||||||
|
def->tooltip = L("max_deviation");
|
||||||
|
def->sidetext = L("mm");
|
||||||
|
def->min = 0;
|
||||||
|
def->set_default_value(new ConfigOptionFloat(0.5));
|
||||||
|
|
||||||
|
def = this->add("max_variance", coFloat);
|
||||||
|
def->label = L("Variance");
|
||||||
|
def->tooltip = L("max_variance");
|
||||||
|
def->min = 0;
|
||||||
|
def->set_default_value(new ConfigOptionFloat(500));
|
||||||
|
|
||||||
|
def = this->add("counter_coef_1", coFloat);
|
||||||
|
def->label = L("Counter Coef 1");
|
||||||
|
def->tooltip = L("counter_coef_1");
|
||||||
|
def->sidetext = L("/1e6");
|
||||||
|
def->set_default_value(new ConfigOptionFloat(0));
|
||||||
|
|
||||||
|
def = this->add("counter_coef_2", coFloat);
|
||||||
|
def->label = L("Counter Coef 2");
|
||||||
|
def->tooltip = L("counter_coef_2");
|
||||||
|
def->sidetext = L("/1e6");
|
||||||
|
def->set_default_value(new ConfigOptionFloat(25000));
|
||||||
|
|
||||||
|
def = this->add("counter_coef_3", coFloat);
|
||||||
|
def->label = L("Counter Coef 3");
|
||||||
|
def->tooltip = L("counter_coef_3");
|
||||||
|
def->sidetext = L("/1e6");
|
||||||
|
def->set_default_value(new ConfigOptionFloat(-110000));
|
||||||
|
|
||||||
|
def = this->add("hole_coef_1", coFloat);
|
||||||
|
def->label = L("Hole Coef 1");
|
||||||
|
def->tooltip = L("hole_coef_1");
|
||||||
|
def->sidetext = L("/1e6");
|
||||||
|
def->set_default_value(new ConfigOptionFloat(0));
|
||||||
|
|
||||||
|
def = this->add("hole_coef_2", coFloat);
|
||||||
|
def->label = L("Hole Coef 2");
|
||||||
|
def->tooltip = L("hole_coef_2");
|
||||||
|
def->sidetext = L("/1e6");
|
||||||
|
def->set_default_value(new ConfigOptionFloat(-25000));
|
||||||
|
|
||||||
|
def = this->add("hole_coef_3", coFloat);
|
||||||
|
def->label = L("Hole Coef 3");
|
||||||
|
def->tooltip = L("hole_coef_3");
|
||||||
|
def->sidetext = L("/1e6");
|
||||||
|
def->set_default_value(new ConfigOptionFloat(280000));
|
||||||
|
|
||||||
|
def = this->add("counter_limit_min", coFloat);
|
||||||
|
def->label = L("Counter limit min");
|
||||||
|
def->tooltip = L("counter_limit_min");
|
||||||
|
def->sidetext = L("/1e6");
|
||||||
|
def->set_default_value(new ConfigOptionFloat(-40000));
|
||||||
|
|
||||||
|
def = this->add("counter_limit_max", coFloat);
|
||||||
|
def->label = L("Counter limit max");
|
||||||
|
def->tooltip = L("counter_limit_max");
|
||||||
|
def->sidetext = L("/1e6");
|
||||||
|
def->set_default_value(new ConfigOptionFloat(50000));
|
||||||
|
|
||||||
|
def = this->add("hole_limit_min", coFloat);
|
||||||
|
def->label = L("Hole limit min");
|
||||||
|
def->tooltip = L("hole_limit_min");
|
||||||
|
def->sidetext = L("/1e6");
|
||||||
|
def->set_default_value(new ConfigOptionFloat(80000));
|
||||||
|
|
||||||
|
def = this->add("hole_limit_max", coFloat);
|
||||||
|
def->label = L("Hole limit max");
|
||||||
|
def->tooltip = L("hole_limit_max");
|
||||||
|
def->sidetext = L("/1e6");
|
||||||
|
def->set_default_value(new ConfigOptionFloat(250000));
|
||||||
|
|
||||||
|
def = this->add("diameter_limit", coFloat);
|
||||||
|
def->label = L("Diameter limit");
|
||||||
|
def->tooltip = L("diameter_limit");
|
||||||
|
def->sidetext = L("mm");
|
||||||
|
def->set_default_value(new ConfigOptionFloat(50));
|
||||||
|
|
||||||
def = this->add("flush_volumes_vector", coFloats);
|
def = this->add("flush_volumes_vector", coFloats);
|
||||||
// BBS: remove _L()
|
// BBS: remove _L()w
|
||||||
def->label = ("Purging volumes - load/unload volumes");
|
def->label = ("Purging volumes - load/unload volumes");
|
||||||
//def->tooltip = L("This vector saves required volumes to change from/to each tool used on the "
|
//def->tooltip = L("This vector saves required volumes to change from/to each tool used on the "
|
||||||
// "wipe tower. These values are used to simplify creation of the full purging "
|
// "wipe tower. These values are used to simplify creation of the full purging "
|
||||||
|
|
|
@ -822,6 +822,22 @@ PRINT_CONFIG_CLASS_DEFINE(
|
||||||
((ConfigOptionFloat, support_object_first_layer_gap))
|
((ConfigOptionFloat, support_object_first_layer_gap))
|
||||||
((ConfigOptionFloat, xy_hole_compensation))
|
((ConfigOptionFloat, xy_hole_compensation))
|
||||||
((ConfigOptionFloat, xy_contour_compensation))
|
((ConfigOptionFloat, xy_contour_compensation))
|
||||||
|
//BBS auto hole contour compensation
|
||||||
|
((ConfigOptionBool, enable_circle_compensation))
|
||||||
|
((ConfigOptionFloat, circle_compensation_speed))
|
||||||
|
((ConfigOptionFloat, max_deviation))
|
||||||
|
((ConfigOptionFloat, max_variance))
|
||||||
|
((ConfigOptionFloat, counter_coef_1))
|
||||||
|
((ConfigOptionFloat, counter_coef_2))
|
||||||
|
((ConfigOptionFloat, counter_coef_3))
|
||||||
|
((ConfigOptionFloat, hole_coef_1))
|
||||||
|
((ConfigOptionFloat, hole_coef_2))
|
||||||
|
((ConfigOptionFloat, hole_coef_3))
|
||||||
|
((ConfigOptionFloat, counter_limit_min))
|
||||||
|
((ConfigOptionFloat, counter_limit_max))
|
||||||
|
((ConfigOptionFloat, hole_limit_min))
|
||||||
|
((ConfigOptionFloat, hole_limit_max))
|
||||||
|
((ConfigOptionFloat, diameter_limit))
|
||||||
((ConfigOptionBool, flush_into_objects))
|
((ConfigOptionBool, flush_into_objects))
|
||||||
// BBS
|
// BBS
|
||||||
((ConfigOptionBool, flush_into_infill))
|
((ConfigOptionBool, flush_into_infill))
|
||||||
|
|
|
@ -798,7 +798,22 @@ bool PrintObject::invalidate_state_by_config_options(
|
||||||
|| opt_key == "only_one_wall_first_layer"
|
|| opt_key == "only_one_wall_first_layer"
|
||||||
|| opt_key == "initial_layer_line_width"
|
|| opt_key == "initial_layer_line_width"
|
||||||
|| opt_key == "inner_wall_line_width"
|
|| opt_key == "inner_wall_line_width"
|
||||||
|| opt_key == "infill_wall_overlap") {
|
|| opt_key == "infill_wall_overlap"
|
||||||
|
|| opt_key == "enable_circle_compensation"
|
||||||
|
|| opt_key == "circle_compensation_speed"
|
||||||
|
|| opt_key == "max_deviation"
|
||||||
|
|| opt_key == "max_variance"
|
||||||
|
|| opt_key == "counter_coef_1"
|
||||||
|
|| opt_key == "counter_coef_2"
|
||||||
|
|| opt_key == "counter_coef_3"
|
||||||
|
|| opt_key == "hole_coef_1"
|
||||||
|
|| opt_key == "hole_coef_2"
|
||||||
|
|| opt_key == "hole_coef_3"
|
||||||
|
|| opt_key == "counter_limit_min"
|
||||||
|
|| opt_key == "counter_limit_max"
|
||||||
|
|| opt_key == "hole_limit_min"
|
||||||
|
|| opt_key == "hole_limit_max"
|
||||||
|
|| opt_key == "diameter_limit") {
|
||||||
steps.emplace_back(posPerimeters);
|
steps.emplace_back(posPerimeters);
|
||||||
} else if (opt_key == "gap_infill_speed" || opt_key == "filter_out_gap_fill") {
|
} else if (opt_key == "gap_infill_speed" || opt_key == "filter_out_gap_fill") {
|
||||||
// Return true if gap-fill speed has changed from zero value to non-zero or from non-zero value to zero.
|
// Return true if gap-fill speed has changed from zero value to non-zero or from non-zero value to zero.
|
||||||
|
|
|
@ -37,6 +37,8 @@ public:
|
||||||
unsigned short thickness_layers; // in layers
|
unsigned short thickness_layers; // in layers
|
||||||
double bridge_angle; // in radians, ccw, 0 = East, only 0+ (negative means undefined)
|
double bridge_angle; // in radians, ccw, 0 = East, only 0+ (negative means undefined)
|
||||||
unsigned short extra_perimeters;
|
unsigned short extra_perimeters;
|
||||||
|
bool counter_circle_compensation{false};
|
||||||
|
std::vector<int> holes_circle_compensation; // hole index
|
||||||
|
|
||||||
Surface(SurfaceType _surface_type = stInternal)
|
Surface(SurfaceType _surface_type = stInternal)
|
||||||
: surface_type(_surface_type),
|
: surface_type(_surface_type),
|
||||||
|
|
|
@ -266,6 +266,16 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con
|
||||||
is_msg_dlg_already_exist = false;
|
is_msg_dlg_already_exist = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//if enable auto hole and contour compensation, disable the manner
|
||||||
|
if (config->opt_bool("enable_circle_compensation")) {
|
||||||
|
DynamicPrintConfig new_conf = *config;
|
||||||
|
is_msg_dlg_already_exist = true;
|
||||||
|
new_conf.set_key_value("xy_contour_compensation", new ConfigOptionFloat(0));
|
||||||
|
new_conf.set_key_value("xy_hole_compensation", new ConfigOptionFloat(0));
|
||||||
|
apply(config, &new_conf);
|
||||||
|
is_msg_dlg_already_exist = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (config->option<ConfigOptionFloat>("elefant_foot_compensation")->value > 1)
|
if (config->option<ConfigOptionFloat>("elefant_foot_compensation")->value > 1)
|
||||||
{
|
{
|
||||||
const wxString msg_text = _(L("Too large elephant foot compensation is unreasonable.\n"
|
const wxString msg_text = _(L("Too large elephant foot compensation is unreasonable.\n"
|
||||||
|
@ -715,6 +725,12 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, in
|
||||||
toggle_line("interlocking_beam_layer_count", use_beam_interlocking);
|
toggle_line("interlocking_beam_layer_count", use_beam_interlocking);
|
||||||
toggle_line("interlocking_depth", use_beam_interlocking);
|
toggle_line("interlocking_depth", use_beam_interlocking);
|
||||||
toggle_line("interlocking_boundary_avoidance", use_beam_interlocking);
|
toggle_line("interlocking_boundary_avoidance", use_beam_interlocking);
|
||||||
|
|
||||||
|
bool enable_auto_hole_and_contour_compensation = config->opt_bool("enable_circle_compensation");
|
||||||
|
for (auto el : {"max_deviation", "max_variance", "circle_compensation_speed", "counter_coef_1", "counter_coef_2", "counter_coef_3", "hole_coef_1", "hole_coef_2", "hole_coef_3", "counter_limit_min", "counter_limit_max", "hole_limit_min", "hole_limit_max", "diameter_limit"})
|
||||||
|
toggle_line(el, enable_auto_hole_and_contour_compensation);
|
||||||
|
toggle_field("xy_hole_compensation", !enable_auto_hole_and_contour_compensation);
|
||||||
|
toggle_field("xy_contour_compensation", !enable_auto_hole_and_contour_compensation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigManipulation::update_print_sla_config(DynamicPrintConfig* config, const bool is_global_config/* = false*/)
|
void ConfigManipulation::update_print_sla_config(DynamicPrintConfig* config, const bool is_global_config/* = false*/)
|
||||||
|
|
|
@ -2006,6 +2006,21 @@ void TabPrint::build()
|
||||||
optgroup->append_single_option_line("xy_hole_compensation", "xy-hole-contour-compensation");
|
optgroup->append_single_option_line("xy_hole_compensation", "xy-hole-contour-compensation");
|
||||||
optgroup->append_single_option_line("xy_contour_compensation", "xy-hole-contour-compensation");
|
optgroup->append_single_option_line("xy_contour_compensation", "xy-hole-contour-compensation");
|
||||||
optgroup->append_single_option_line("elefant_foot_compensation", "parameter/elephant-foot");
|
optgroup->append_single_option_line("elefant_foot_compensation", "parameter/elephant-foot");
|
||||||
|
optgroup->append_single_option_line("enable_circle_compensation");
|
||||||
|
optgroup->append_single_option_line("circle_compensation_speed");
|
||||||
|
optgroup->append_single_option_line("max_deviation");
|
||||||
|
optgroup->append_single_option_line("max_variance");
|
||||||
|
optgroup->append_single_option_line("counter_coef_1");
|
||||||
|
optgroup->append_single_option_line("counter_coef_2");
|
||||||
|
optgroup->append_single_option_line("counter_coef_3");
|
||||||
|
optgroup->append_single_option_line("hole_coef_1");
|
||||||
|
optgroup->append_single_option_line("hole_coef_2");
|
||||||
|
optgroup->append_single_option_line("hole_coef_3");
|
||||||
|
optgroup->append_single_option_line("counter_limit_min");
|
||||||
|
optgroup->append_single_option_line("counter_limit_max");
|
||||||
|
optgroup->append_single_option_line("hole_limit_min");
|
||||||
|
optgroup->append_single_option_line("hole_limit_max");
|
||||||
|
optgroup->append_single_option_line("diameter_limit");
|
||||||
optgroup->append_single_option_line("precise_z_height");
|
optgroup->append_single_option_line("precise_z_height");
|
||||||
|
|
||||||
optgroup = page->new_optgroup(L("Ironing"), L"param_ironing");
|
optgroup = page->new_optgroup(L("Ironing"), L"param_ironing");
|
||||||
|
|
Loading…
Reference in New Issue