Extending the expressivity of ExtrusionRole

Moved is_xx() test functions to ExtrusionRole enum class,
changed the tests to use the new ExtrusionRole bitmask.
Follow-up to 5991850db1
e50e96bb26
c64dbacf88
This commit is contained in:
Vojtech Bubnik 2023-01-16 12:39:08 +01:00
parent c64dbacf88
commit d1f610d957
7 changed files with 35 additions and 54 deletions

View File

@ -50,7 +50,7 @@ void ExtrusionPath::polygons_covered_by_spacing(Polygons &out, const float scale
{ {
// Instantiating the Flow class to get the line spacing. // Instantiating the Flow class to get the line spacing.
// Don't know the nozzle diameter, setting to zero. It shall not matter it shall be optimized out by the compiler. // Don't know the nozzle diameter, setting to zero. It shall not matter it shall be optimized out by the compiler.
bool bridge = is_bridge(this->role()); bool bridge = this->role().is_bridge();
assert(! bridge || this->width == this->height); assert(! bridge || this->width == this->height);
auto flow = bridge ? Flow::bridging_flow(this->width, 0.f) : Flow(this->width, this->height, 0.f); auto flow = bridge ? Flow::bridging_flow(this->width, 0.f) : Flow(this->width, this->height, 0.f);
polygons_append(out, offset(this->polyline, 0.5f * float(flow.scaled_spacing()) + scaled_epsilon)); polygons_append(out, offset(this->polyline, 0.5f * float(flow.scaled_spacing()) + scaled_epsilon));
@ -208,7 +208,7 @@ ExtrusionLoop::ClosestPathPoint ExtrusionLoop::get_closest_path_and_point(const
out.segment_idx = foot_pt_.first; out.segment_idx = foot_pt_.first;
min2 = d2; min2 = d2;
} }
if (prefer_non_overhang && !is_bridge(path.role()) && d2 < min2_non_overhang) { if (prefer_non_overhang && ! path.role().is_bridge() && d2 < min2_non_overhang) {
best_non_overhang.foot_pt = foot_pt_.second; best_non_overhang.foot_pt = foot_pt_.second;
best_non_overhang.path_idx = &path - &this->paths.front(); best_non_overhang.path_idx = &path - &this->paths.front();
best_non_overhang.segment_idx = foot_pt_.first; best_non_overhang.segment_idx = foot_pt_.first;
@ -294,7 +294,7 @@ bool ExtrusionLoop::has_overhang_point(const Point &point) const
if (pos != -1) { if (pos != -1) {
// point belongs to this path // point belongs to this path
// we consider it overhang only if it's not an endpoint // we consider it overhang only if it's not an endpoint
return (is_bridge(path.role()) && pos > 0 && pos != (int)(path.polyline.points.size())-1); return (path.role().is_bridge() && pos > 0 && pos != int(path.polyline.points.size())-1);
} }
} }
return false; return false;

View File

@ -58,7 +58,7 @@ struct ExtrusionRole : public ExtrusionRoleModifiers
//FIXME why there is no bottom solid infill type? //FIXME why there is no bottom solid infill type?
static constexpr const ExtrusionRoleModifiers TopSolidInfill{ ExtrusionRoleModifier::Infill | ExtrusionRoleModifier::Solid | ExtrusionRoleModifier::External }; static constexpr const ExtrusionRoleModifiers TopSolidInfill{ ExtrusionRoleModifier::Infill | ExtrusionRoleModifier::Solid | ExtrusionRoleModifier::External };
// Ironing infill at the top surfaces. // Ironing infill at the top surfaces.
static constexpr const ExtrusionRoleModifiers Ironing{ ExtrusionRoleModifier::Infill | ExtrusionRoleModifier::Ironing | ExtrusionRoleModifier::External }; static constexpr const ExtrusionRoleModifiers Ironing{ ExtrusionRoleModifier::Infill | ExtrusionRoleModifier::Solid | ExtrusionRoleModifier::Ironing | ExtrusionRoleModifier::External };
// Visible bridging infill at the bottom of an object. // Visible bridging infill at the bottom of an object.
static constexpr const ExtrusionRoleModifiers BridgeInfill{ ExtrusionRoleModifier::Infill | ExtrusionRoleModifier::Solid | ExtrusionRoleModifier::Bridge | ExtrusionRoleModifier::External }; static constexpr const ExtrusionRoleModifiers BridgeInfill{ ExtrusionRoleModifier::Infill | ExtrusionRoleModifier::Solid | ExtrusionRoleModifier::Bridge | ExtrusionRoleModifier::External };
// static constexpr const ExtrusionRoleModifiers InternalBridgeInfill{ ExtrusionRoleModifier::Infill | ExtrusionRoleModifier::Solid | ExtrusionRoleModifier::Bridge }; // static constexpr const ExtrusionRoleModifiers InternalBridgeInfill{ ExtrusionRoleModifier::Infill | ExtrusionRoleModifier::Solid | ExtrusionRoleModifier::Bridge };
@ -76,6 +76,13 @@ struct ExtrusionRole : public ExtrusionRoleModifiers
static constexpr const ExtrusionRoleModifiers WipeTower{ ExtrusionRoleModifier::Wipe }; static constexpr const ExtrusionRoleModifiers WipeTower{ ExtrusionRoleModifier::Wipe };
// Extrusion role for a collection with multiple extrusion roles. // Extrusion role for a collection with multiple extrusion roles.
static constexpr const ExtrusionRoleModifiers Mixed{ ExtrusionRoleModifier::Mixed }; static constexpr const ExtrusionRoleModifiers Mixed{ ExtrusionRoleModifier::Mixed };
bool is_perimeter() const { return this->ExtrusionRoleModifiers::has(ExtrusionRoleModifier::Perimeter); }
bool is_external_perimeter() const { return this->is_perimeter() && this->is_external(); }
bool is_infill() const { return this->ExtrusionRoleModifiers::has(ExtrusionRoleModifier::Infill); }
bool is_solid_infill() const { return this->is_infill() && this->ExtrusionRoleModifiers::has(ExtrusionRoleModifier::Solid); }
bool is_external() const { return this->ExtrusionRoleModifiers::has(ExtrusionRoleModifier::External); }
bool is_bridge() const { return this->ExtrusionRoleModifiers::has(ExtrusionRoleModifier::Bridge); }
}; };
// Special flags describing loop // Special flags describing loop
@ -85,35 +92,6 @@ enum ExtrusionLoopRole {
elrSkirt, elrSkirt,
}; };
inline bool is_perimeter(ExtrusionRole role)
{
return role == ExtrusionRole::Perimeter
|| role == ExtrusionRole::ExternalPerimeter
|| role == ExtrusionRole::OverhangPerimeter;
}
inline bool is_infill(ExtrusionRole role)
{
return role == ExtrusionRole::BridgeInfill
|| role == ExtrusionRole::InternalInfill
|| role == ExtrusionRole::SolidInfill
|| role == ExtrusionRole::TopSolidInfill
|| role == ExtrusionRole::Ironing;
}
inline bool is_solid_infill(ExtrusionRole role)
{
return role == ExtrusionRole::BridgeInfill
|| role == ExtrusionRole::SolidInfill
|| role == ExtrusionRole::TopSolidInfill
|| role == ExtrusionRole::Ironing;
}
inline bool is_bridge(ExtrusionRole role) {
return role == ExtrusionRole::BridgeInfill
|| role == ExtrusionRole::OverhangPerimeter;
}
// Be careful when editing this list as many parts of the code depend // Be careful when editing this list as many parts of the code depend
// on the values of these ordinars, for example // on the values of these ordinars, for example
// GCodeViewer::Extrusion_Role_Colors // GCodeViewer::Extrusion_Role_Colors

View File

@ -2601,7 +2601,7 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, const std::string_view descr
if (paths.empty()) return ""; if (paths.empty()) return "";
// apply the small perimeter speed // apply the small perimeter speed
if (is_perimeter(paths.front().role()) && loop.length() <= SMALL_PERIMETER_LENGTH && speed == -1) if (paths.front().role().is_perimeter() && loop.length() <= SMALL_PERIMETER_LENGTH && speed == -1)
speed = m_config.small_perimeter_speed.get_abs_value(m_config.perimeter_speed); speed = m_config.small_perimeter_speed.get_abs_value(m_config.perimeter_speed);
// extrude along the path // extrude along the path
@ -2618,7 +2618,7 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, const std::string_view descr
m_wipe.path = paths.front().polyline; m_wipe.path = paths.front().polyline;
for (auto it = std::next(paths.begin()); it != paths.end(); ++it) { for (auto it = std::next(paths.begin()); it != paths.end(); ++it) {
if (is_bridge(it->role())) if (it->role().is_bridge())
break; // Don't perform a wipe on bridges. break; // Don't perform a wipe on bridges.
assert(it->polyline.points.size() >= 2); assert(it->polyline.points.size() >= 2);
@ -2686,7 +2686,7 @@ std::string GCode::extrude_multi_path(ExtrusionMultiPath multipath, const std::s
m_wipe.path.reverse(); m_wipe.path.reverse();
for (auto it = std::next(multipath.paths.rbegin()); it != multipath.paths.rend(); ++it) { for (auto it = std::next(multipath.paths.rbegin()); it != multipath.paths.rend(); ++it) {
if (is_bridge(it->role())) if (it->role().is_bridge())
break; // Do not perform a wipe on bridges. break; // Do not perform a wipe on bridges.
assert(it->polyline.points.size() >= 2); assert(it->polyline.points.size() >= 2);
@ -2831,7 +2831,7 @@ void GCode::GCodeOutputStream::write_format(const char* format, ...)
std::string GCode::_extrude(const ExtrusionPath &path, const std::string_view description, double speed) std::string GCode::_extrude(const ExtrusionPath &path, const std::string_view description, double speed)
{ {
std::string gcode; std::string gcode;
const std::string_view description_bridge = is_bridge(path.role()) ? " (bridge)"sv : ""sv; const std::string_view description_bridge = path.role().is_bridge() ? " (bridge)"sv : ""sv;
// go to first point of extrusion path // go to first point of extrusion path
if (!m_last_pos_defined || m_last_pos != path.first_point()) { if (!m_last_pos_defined || m_last_pos != path.first_point()) {
@ -2852,11 +2852,11 @@ std::string GCode::_extrude(const ExtrusionPath &path, const std::string_view de
acceleration = m_config.first_layer_acceleration.value; acceleration = m_config.first_layer_acceleration.value;
} else if (this->object_layer_over_raft() && m_config.first_layer_acceleration_over_raft.value > 0) { } else if (this->object_layer_over_raft() && m_config.first_layer_acceleration_over_raft.value > 0) {
acceleration = m_config.first_layer_acceleration_over_raft.value; acceleration = m_config.first_layer_acceleration_over_raft.value;
} else if (m_config.bridge_acceleration.value > 0 && is_bridge(path.role())) { } else if (m_config.bridge_acceleration.value > 0 && path.role().is_bridge()) {
acceleration = m_config.bridge_acceleration.value; acceleration = m_config.bridge_acceleration.value;
} else if (m_config.infill_acceleration.value > 0 && is_infill(path.role())) { } else if (m_config.infill_acceleration.value > 0 && path.role().is_infill()) {
acceleration = m_config.infill_acceleration.value; acceleration = m_config.infill_acceleration.value;
} else if (m_config.perimeter_acceleration.value > 0 && is_perimeter(path.role())) { } else if (m_config.perimeter_acceleration.value > 0 && path.role().is_perimeter()) {
acceleration = m_config.perimeter_acceleration.value; acceleration = m_config.perimeter_acceleration.value;
} else { } else {
acceleration = m_config.default_acceleration.value; acceleration = m_config.default_acceleration.value;
@ -2876,7 +2876,8 @@ std::string GCode::_extrude(const ExtrusionPath &path, const std::string_view de
speed = m_config.get_abs_value("perimeter_speed"); speed = m_config.get_abs_value("perimeter_speed");
} else if (path.role() == ExtrusionRole::ExternalPerimeter) { } else if (path.role() == ExtrusionRole::ExternalPerimeter) {
speed = m_config.get_abs_value("external_perimeter_speed"); speed = m_config.get_abs_value("external_perimeter_speed");
} else if (path.role() == ExtrusionRole::OverhangPerimeter || path.role() == ExtrusionRole::BridgeInfill) { } else if (path.role().is_bridge()) {
assert(path.role() == ExtrusionRole::OverhangPerimeter || path.role() == ExtrusionRole::BridgeInfill);
speed = m_config.get_abs_value("bridge_speed"); speed = m_config.get_abs_value("bridge_speed");
} else if (path.role() == ExtrusionRole::InternalInfill) { } else if (path.role() == ExtrusionRole::InternalInfill) {
speed = m_config.get_abs_value("infill_speed"); speed = m_config.get_abs_value("infill_speed");
@ -2915,7 +2916,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, const std::string_view de
bool variable_speed = false; bool variable_speed = false;
std::vector<ProcessedPoint> new_points{}; std::vector<ProcessedPoint> new_points{};
if (this->m_config.enable_dynamic_overhang_speeds && !this->on_first_layer() && is_perimeter(path.role())) { if (this->m_config.enable_dynamic_overhang_speeds && !this->on_first_layer() && path.role().is_perimeter()) {
new_points = m_extrusion_quality_estimator.estimate_extrusion_quality(path, m_config.overhang_overlap_levels, new_points = m_extrusion_quality_estimator.estimate_extrusion_quality(path, m_config.overhang_overlap_levels,
m_config.dynamic_overhang_speeds, m_config.dynamic_overhang_speeds,
m_config.get_abs_value("external_perimeter_speed"), speed); m_config.get_abs_value("external_perimeter_speed"), speed);
@ -2975,7 +2976,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, const std::string_view de
std::string comment; std::string comment;
if (m_enable_cooling_markers) { if (m_enable_cooling_markers) {
if (is_bridge(path.role())) if (path.role().is_bridge())
gcode += ";_BRIDGE_FAN_START\n"; gcode += ";_BRIDGE_FAN_START\n";
else else
comment = ";_EXTRUDE_SET_SPEED"; comment = ";_EXTRUDE_SET_SPEED";
@ -3026,7 +3027,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, const std::string_view de
} }
if (m_enable_cooling_markers) if (m_enable_cooling_markers)
gcode += is_bridge(path.role()) ? ";_BRIDGE_FAN_END\n" : ";_EXTRUDE_END\n"; gcode += path.role().is_bridge() ? ";_BRIDGE_FAN_END\n" : ";_EXTRUDE_END\n";
this->set_last_pos(path.last_point()); this->set_last_pos(path.last_point());
return gcode; return gcode;

View File

@ -63,11 +63,11 @@ unsigned int LayerTools::extruder(const ExtrusionEntityCollection &extrusions, c
assert(region.config().infill_extruder.value > 0); assert(region.config().infill_extruder.value > 0);
assert(region.config().solid_infill_extruder.value > 0); assert(region.config().solid_infill_extruder.value > 0);
// 1 based extruder ID. // 1 based extruder ID.
unsigned int extruder = ((this->extruder_override == 0) ? unsigned int extruder = this->extruder_override == 0 ?
(is_infill(extrusions.role()) ? (extrusions.role().is_infill() ?
(is_solid_infill(extrusions.entities.front()->role()) ? region.config().solid_infill_extruder : region.config().infill_extruder) : (extrusions.entities.front()->role().is_solid_infill() ? region.config().solid_infill_extruder : region.config().infill_extruder) :
region.config().perimeter_extruder.value) : region.config().perimeter_extruder.value) :
this->extruder_override); this->extruder_override;
return (extruder == 0) ? 0 : extruder - 1; return (extruder == 0) ? 0 : extruder - 1;
} }
@ -267,7 +267,7 @@ void ToolOrdering::collect_extruders(const PrintObject &object, const std::vecto
// fill represents infill extrusions of a single island. // fill represents infill extrusions of a single island.
const auto *fill = dynamic_cast<const ExtrusionEntityCollection*>(ee); const auto *fill = dynamic_cast<const ExtrusionEntityCollection*>(ee);
ExtrusionRole role = fill->entities.empty() ? ExtrusionRole::None : fill->entities.front()->role(); ExtrusionRole role = fill->entities.empty() ? ExtrusionRole::None : fill->entities.front()->role();
if (is_solid_infill(role)) if (role.is_solid_infill())
has_solid_infill = true; has_solid_infill = true;
else if (role != ExtrusionRole::None) else if (role != ExtrusionRole::None)
has_infill = true; has_infill = true;

View File

@ -58,6 +58,8 @@ public:
bool is_external_perimeter() const bool is_external_perimeter() const
{ {
assert(origin_entity != nullptr); assert(origin_entity != nullptr);
//FIXME origin_entity->role() == ExtrusionRole::OverhangPerimeter is not quite right.
// rather use origin_entity->role().is_external_perimeter()
return origin_entity->role() == ExtrusionRole::ExternalPerimeter || origin_entity->role() == ExtrusionRole::OverhangPerimeter; return origin_entity->role() == ExtrusionRole::ExternalPerimeter || origin_entity->role() == ExtrusionRole::OverhangPerimeter;
} }

View File

@ -31,14 +31,14 @@ public:
constexpr enum_bitmask(option_type o) : m_bits(mask_value(o)) {} constexpr enum_bitmask(option_type o) : m_bits(mask_value(o)) {}
// Set the bit corresponding to the given option. // Set the bit corresponding to the given option.
constexpr enum_bitmask operator|(option_type t) { return enum_bitmask(m_bits | mask_value(t)); } constexpr enum_bitmask operator|(option_type t) const { return enum_bitmask(m_bits | mask_value(t)); }
// Combine with another enum_bitmask of the same type. // Combine with another enum_bitmask of the same type.
constexpr enum_bitmask operator|(enum_bitmask<option_type> t) { return enum_bitmask(m_bits | t.m_bits); } constexpr enum_bitmask operator|(enum_bitmask<option_type> t) const { return enum_bitmask(m_bits | t.m_bits); }
// Get the value of the bit corresponding to the given option. // Get the value of the bit corresponding to the given option.
constexpr bool operator&(option_type t) { return m_bits & mask_value(t); } constexpr bool operator&(option_type t) const { return m_bits & mask_value(t); }
constexpr bool has(option_type t) { return m_bits & mask_value(t); } constexpr bool has(option_type t) const { return m_bits & mask_value(t); }
constexpr bool operator==(const enum_bitmask r) const { return m_bits == r.m_bits; } constexpr bool operator==(const enum_bitmask r) const { return m_bits == r.m_bits; }
constexpr bool operator!=(const enum_bitmask r) const { return m_bits != r.m_bits; } constexpr bool operator!=(const enum_bitmask r) const { return m_bits != r.m_bits; }

View File

@ -6556,7 +6556,7 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c
const auto *fill = dynamic_cast<const ExtrusionEntityCollection*>(ee); const auto *fill = dynamic_cast<const ExtrusionEntityCollection*>(ee);
if (! fill->entities.empty()) if (! fill->entities.empty())
_3DScene::extrusionentity_to_verts(*fill, float(layer->print_z), copy, _3DScene::extrusionentity_to_verts(*fill, float(layer->print_z), copy,
select_geometry(idx_layer, is_solid_infill(fill->entities.front()->role()) ? select_geometry(idx_layer, fill->entities.front()->role().is_solid_infill() ?
layerm->region().config().solid_infill_extruder : layerm->region().config().solid_infill_extruder :
layerm->region().config().infill_extruder, 1)); layerm->region().config().infill_extruder, 1));
} }