From d1f610d957e41cbea3ce09010bab7f72148a15c3 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Mon, 16 Jan 2023 12:39:08 +0100 Subject: [PATCH] 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 5991850db1f2d09d1b7713f42300e2bfe4a42128 e50e96bb26eab4f9d56c98706c03166635cf4fff c64dbacf88c617e3d676bdaa6c8c81317ccaee5d --- src/libslic3r/ExtrusionEntity.cpp | 6 ++-- src/libslic3r/ExtrusionRole.hpp | 38 ++++++------------------- src/libslic3r/GCode.cpp | 23 ++++++++------- src/libslic3r/GCode/ToolOrdering.cpp | 10 +++---- src/libslic3r/SupportSpotsGenerator.cpp | 2 ++ src/libslic3r/enum_bitmask.hpp | 8 +++--- src/slic3r/GUI/GLCanvas3D.cpp | 2 +- 7 files changed, 35 insertions(+), 54 deletions(-) diff --git a/src/libslic3r/ExtrusionEntity.cpp b/src/libslic3r/ExtrusionEntity.cpp index 2b7bebc37..8a1a88b4b 100644 --- a/src/libslic3r/ExtrusionEntity.cpp +++ b/src/libslic3r/ExtrusionEntity.cpp @@ -50,7 +50,7 @@ void ExtrusionPath::polygons_covered_by_spacing(Polygons &out, const float scale { // 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. - bool bridge = is_bridge(this->role()); + bool bridge = this->role().is_bridge(); assert(! bridge || this->width == this->height); 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)); @@ -208,7 +208,7 @@ ExtrusionLoop::ClosestPathPoint ExtrusionLoop::get_closest_path_and_point(const out.segment_idx = foot_pt_.first; 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.path_idx = &path - &this->paths.front(); best_non_overhang.segment_idx = foot_pt_.first; @@ -294,7 +294,7 @@ bool ExtrusionLoop::has_overhang_point(const Point &point) const if (pos != -1) { // point belongs to this path // 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; diff --git a/src/libslic3r/ExtrusionRole.hpp b/src/libslic3r/ExtrusionRole.hpp index b99eb5034..a6426e0c6 100644 --- a/src/libslic3r/ExtrusionRole.hpp +++ b/src/libslic3r/ExtrusionRole.hpp @@ -58,7 +58,7 @@ struct ExtrusionRole : public ExtrusionRoleModifiers //FIXME why there is no bottom solid infill type? static constexpr const ExtrusionRoleModifiers TopSolidInfill{ ExtrusionRoleModifier::Infill | ExtrusionRoleModifier::Solid | ExtrusionRoleModifier::External }; // 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. static constexpr const ExtrusionRoleModifiers BridgeInfill{ ExtrusionRoleModifier::Infill | ExtrusionRoleModifier::Solid | ExtrusionRoleModifier::Bridge | ExtrusionRoleModifier::External }; // 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 }; // Extrusion role for a collection with multiple extrusion roles. 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 @@ -85,35 +92,6 @@ enum ExtrusionLoopRole { 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 // on the values of these ordinars, for example // GCodeViewer::Extrusion_Role_Colors diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 0f84c1a53..e26e0b55e 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -2601,7 +2601,7 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, const std::string_view descr if (paths.empty()) return ""; // 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); // 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; 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. 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(); 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. 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; - 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 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; } 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; - } 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; - } 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; - } 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; } else { 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"); } else if (path.role() == ExtrusionRole::ExternalPerimeter) { 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"); } else if (path.role() == ExtrusionRole::InternalInfill) { 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; std::vector 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, m_config.dynamic_overhang_speeds, 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; if (m_enable_cooling_markers) { - if (is_bridge(path.role())) + if (path.role().is_bridge()) gcode += ";_BRIDGE_FAN_START\n"; else 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) - 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()); return gcode; diff --git a/src/libslic3r/GCode/ToolOrdering.cpp b/src/libslic3r/GCode/ToolOrdering.cpp index 874a134b7..6a8a7a812 100644 --- a/src/libslic3r/GCode/ToolOrdering.cpp +++ b/src/libslic3r/GCode/ToolOrdering.cpp @@ -63,11 +63,11 @@ unsigned int LayerTools::extruder(const ExtrusionEntityCollection &extrusions, c assert(region.config().infill_extruder.value > 0); assert(region.config().solid_infill_extruder.value > 0); // 1 based extruder ID. - unsigned int extruder = ((this->extruder_override == 0) ? - (is_infill(extrusions.role()) ? - (is_solid_infill(extrusions.entities.front()->role()) ? region.config().solid_infill_extruder : region.config().infill_extruder) : + unsigned int extruder = this->extruder_override == 0 ? + (extrusions.role().is_infill() ? + (extrusions.entities.front()->role().is_solid_infill() ? region.config().solid_infill_extruder : region.config().infill_extruder) : region.config().perimeter_extruder.value) : - this->extruder_override); + this->extruder_override; 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. const auto *fill = dynamic_cast(ee); 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; else if (role != ExtrusionRole::None) has_infill = true; diff --git a/src/libslic3r/SupportSpotsGenerator.cpp b/src/libslic3r/SupportSpotsGenerator.cpp index 4800a2210..43637d25f 100644 --- a/src/libslic3r/SupportSpotsGenerator.cpp +++ b/src/libslic3r/SupportSpotsGenerator.cpp @@ -58,6 +58,8 @@ public: bool is_external_perimeter() const { 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; } diff --git a/src/libslic3r/enum_bitmask.hpp b/src/libslic3r/enum_bitmask.hpp index 72172fad9..274952cb0 100644 --- a/src/libslic3r/enum_bitmask.hpp +++ b/src/libslic3r/enum_bitmask.hpp @@ -31,14 +31,14 @@ public: constexpr enum_bitmask(option_type o) : m_bits(mask_value(o)) {} // 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. - constexpr enum_bitmask operator|(enum_bitmask t) { return enum_bitmask(m_bits | t.m_bits); } + constexpr enum_bitmask operator|(enum_bitmask t) const { return enum_bitmask(m_bits | t.m_bits); } // 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 has(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) 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; } diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 92289b9df..d8a005b34 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -6556,7 +6556,7 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c const auto *fill = dynamic_cast(ee); if (! fill->entities.empty()) _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().infill_extruder, 1)); }