The new ExtrusionRole implementation newly supports both "Bridging"

and "External" attributes at the same time.
PerimeterGenerator was updated to make use of it and set "External"
attribute for overhang perimeters.
This commit is contained in:
Vojtech Bubnik 2023-01-16 14:39:48 +01:00
parent 50bb164263
commit ca0c83d914
5 changed files with 25 additions and 19 deletions

View File

@ -13,9 +13,10 @@ namespace Slic3r {
GCodeExtrusionRole extrusion_role_to_gcode_extrusion_role(ExtrusionRole role) GCodeExtrusionRole extrusion_role_to_gcode_extrusion_role(ExtrusionRole role)
{ {
if (role == ExtrusionRole::None) return GCodeExtrusionRole::None; if (role == ExtrusionRole::None) return GCodeExtrusionRole::None;
if (role == ExtrusionRole::Perimeter) return GCodeExtrusionRole::Perimeter; if (role.is_perimeter()) {
if (role == ExtrusionRole::ExternalPerimeter) return GCodeExtrusionRole::ExternalPerimeter; return role.is_bridge() ? GCodeExtrusionRole::OverhangPerimeter :
if (role == ExtrusionRole::OverhangPerimeter) return GCodeExtrusionRole::OverhangPerimeter; role.is_external() ? GCodeExtrusionRole::ExternalPerimeter : GCodeExtrusionRole::Perimeter;
}
if (role == ExtrusionRole::InternalInfill) return GCodeExtrusionRole::InternalInfill; if (role == ExtrusionRole::InternalInfill) return GCodeExtrusionRole::InternalInfill;
if (role == ExtrusionRole::SolidInfill) return GCodeExtrusionRole::SolidInfill; if (role == ExtrusionRole::SolidInfill) return GCodeExtrusionRole::SolidInfill;
if (role == ExtrusionRole::TopSolidInfill) return GCodeExtrusionRole::TopSolidInfill; if (role == ExtrusionRole::TopSolidInfill) return GCodeExtrusionRole::TopSolidInfill;

View File

@ -2631,7 +2631,7 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, const std::string_view descr
} }
// make a little move inwards before leaving loop // make a little move inwards before leaving loop
if (paths.back().role() == ExtrusionRole::ExternalPerimeter && m_layer != NULL && m_config.perimeters.value > 1 && paths.front().size() >= 2 && paths.back().polyline.points.size() >= 3) { if (paths.back().role().is_external_perimeter() && m_layer != NULL && m_config.perimeters.value > 1 && paths.front().size() >= 2 && paths.back().polyline.points.size() >= 3) {
// detect angle between last and first segment // detect angle between last and first segment
// the side depends on the original winding order of the polygon (left for contours, right for holes) // the side depends on the original winding order of the polygon (left for contours, right for holes)
//FIXME improve the algorithm in case the loop is tiny. //FIXME improve the algorithm in case the loop is tiny.
@ -2877,7 +2877,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, const std::string_view de
} 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().is_bridge()) { } else if (path.role().is_bridge()) {
assert(path.role() == ExtrusionRole::OverhangPerimeter || path.role() == ExtrusionRole::BridgeInfill); assert(path.role().is_perimeter() || 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");

View File

@ -114,7 +114,7 @@ ExtrusionMultiPath PerimeterGenerator::thick_polyline_to_multi_path(const ThickP
} }
const double w = fmax(line.a_width, line.b_width); const double w = fmax(line.a_width, line.b_width);
const Flow new_flow = (role == ExtrusionRole::OverhangPerimeter && flow.bridge()) ? flow : flow.with_width(unscale<float>(w) + flow.height() * float(1. - 0.25 * PI)); const Flow new_flow = (role.is_bridge() && flow.bridge()) ? flow : flow.with_width(unscale<float>(w) + flow.height() * float(1. - 0.25 * PI));
if (path.polyline.points.empty()) { if (path.polyline.points.empty()) {
path.polyline.append(line.a); path.polyline.append(line.a);
path.polyline.append(line.b); path.polyline.append(line.b);
@ -292,9 +292,9 @@ static ExtrusionEntityCollection traverse_loops_classic(const PerimeterGenerator
for (const PerimeterGeneratorLoop &loop : loops) { for (const PerimeterGeneratorLoop &loop : loops) {
bool is_external = loop.is_external(); bool is_external = loop.is_external();
ExtrusionRole role = ExtrusionRole::None;
ExtrusionLoopRole loop_role; ExtrusionLoopRole loop_role;
role = is_external ? ExtrusionRole::ExternalPerimeter : ExtrusionRole::Perimeter; ExtrusionRole role_normal = is_external ? ExtrusionRole::ExternalPerimeter : ExtrusionRole::Perimeter;
ExtrusionRole role_overhang = role_normal | ExtrusionRoleModifier::Bridge;
if (loop.is_internal_contour()) { if (loop.is_internal_contour()) {
// Note that we set loop role to ContourInternalPerimeter // Note that we set loop role to ContourInternalPerimeter
// also when loop is both internal and external (i.e. // also when loop is both internal and external (i.e.
@ -321,7 +321,7 @@ static ExtrusionEntityCollection traverse_loops_classic(const PerimeterGenerator
extrusion_paths_append( extrusion_paths_append(
paths, paths,
intersection_pl({ polygon }, lower_slices_polygons_clipped), intersection_pl({ polygon }, lower_slices_polygons_clipped),
role, role_normal,
is_external ? params.ext_mm3_per_mm : params.mm3_per_mm, is_external ? params.ext_mm3_per_mm : params.mm3_per_mm,
is_external ? params.ext_perimeter_flow.width() : params.perimeter_flow.width(), is_external ? params.ext_perimeter_flow.width() : params.perimeter_flow.width(),
float(params.layer_height)); float(params.layer_height));
@ -332,7 +332,7 @@ static ExtrusionEntityCollection traverse_loops_classic(const PerimeterGenerator
extrusion_paths_append( extrusion_paths_append(
paths, paths,
diff_pl({ polygon }, lower_slices_polygons_clipped), diff_pl({ polygon }, lower_slices_polygons_clipped),
ExtrusionRole::OverhangPerimeter, role_overhang,
params.mm3_per_mm_overhang, params.mm3_per_mm_overhang,
params.overhang_flow.width(), params.overhang_flow.width(),
params.overhang_flow.height()); params.overhang_flow.height());
@ -341,7 +341,7 @@ static ExtrusionEntityCollection traverse_loops_classic(const PerimeterGenerator
// We allow polyline reversal because Clipper may have randomly reversed polylines during clipping. // We allow polyline reversal because Clipper may have randomly reversed polylines during clipping.
chain_and_reorder_extrusion_paths(paths, &paths.front().first_point()); chain_and_reorder_extrusion_paths(paths, &paths.front().first_point());
} else { } else {
ExtrusionPath path(role); ExtrusionPath path(role_normal);
path.polyline = polygon.split_at_first_point(); path.polyline = polygon.split_at_first_point();
path.mm3_per_mm = is_external ? params.ext_mm3_per_mm : params.mm3_per_mm; path.mm3_per_mm = is_external ? params.ext_mm3_per_mm : params.mm3_per_mm;
path.width = is_external ? params.ext_perimeter_flow.width() : params.perimeter_flow.width(); path.width = is_external ? params.ext_perimeter_flow.width() : params.perimeter_flow.width();
@ -503,7 +503,8 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator::P
continue; continue;
const bool is_external = extrusion->inset_idx == 0; const bool is_external = extrusion->inset_idx == 0;
ExtrusionRole role = is_external ? ExtrusionRole::ExternalPerimeter : ExtrusionRole::Perimeter; ExtrusionRole role_normal = is_external ? ExtrusionRole::ExternalPerimeter : ExtrusionRole::Perimeter;
ExtrusionRole role_overhang = role_normal | ExtrusionRoleModifier::Bridge;
if (pg_extrusion.fuzzify) if (pg_extrusion.fuzzify)
fuzzy_extrusion_line(*extrusion, scaled<float>(params.config.fuzzy_skin_thickness.value), scaled<float>(params.config.fuzzy_skin_point_dist.value)); fuzzy_extrusion_line(*extrusion, scaled<float>(params.config.fuzzy_skin_thickness.value), scaled<float>(params.config.fuzzy_skin_point_dist.value));
@ -541,13 +542,13 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator::P
} }
// get non-overhang paths by intersecting this loop with the grown lower slices // get non-overhang paths by intersecting this loop with the grown lower slices
extrusion_paths_append(paths, clip_extrusion(extrusion_path, lower_slices_paths, ClipperLib_Z::ctIntersection), role, extrusion_paths_append(paths, clip_extrusion(extrusion_path, lower_slices_paths, ClipperLib_Z::ctIntersection), role_normal,
is_external ? params.ext_perimeter_flow : params.perimeter_flow); is_external ? params.ext_perimeter_flow : params.perimeter_flow);
// get overhang paths by checking what parts of this loop fall // get overhang paths by checking what parts of this loop fall
// outside the grown lower slices (thus where the distance between // outside the grown lower slices (thus where the distance between
// the loop centerline and original lower slices is >= half nozzle diameter // the loop centerline and original lower slices is >= half nozzle diameter
extrusion_paths_append(paths, clip_extrusion(extrusion_path, lower_slices_paths, ClipperLib_Z::ctDifference), ExtrusionRole::OverhangPerimeter, extrusion_paths_append(paths, clip_extrusion(extrusion_path, lower_slices_paths, ClipperLib_Z::ctDifference), role_overhang,
params.overhang_flow); params.overhang_flow);
// Reapply the nearest point search for starting point. // Reapply the nearest point search for starting point.
@ -568,7 +569,7 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator::P
for (const ExtrusionPath &path : paths) { for (const ExtrusionPath &path : paths) {
++point_occurrence[path.polyline.first_point()].occurrence; ++point_occurrence[path.polyline.first_point()].occurrence;
++point_occurrence[path.polyline.last_point()].occurrence; ++point_occurrence[path.polyline.last_point()].occurrence;
if (path.role() == ExtrusionRole::OverhangPerimeter) { if (path.role().is_bridge()) {
point_occurrence[path.polyline.first_point()].is_overhang = true; point_occurrence[path.polyline.first_point()].is_overhang = true;
point_occurrence[path.polyline.last_point()].is_overhang = true; point_occurrence[path.polyline.last_point()].is_overhang = true;
} }
@ -588,7 +589,7 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator::P
chain_and_reorder_extrusion_paths(paths, &start_point); chain_and_reorder_extrusion_paths(paths, &start_point);
} }
} else { } else {
extrusion_paths_append(paths, *extrusion, role, is_external ? params.ext_perimeter_flow : params.perimeter_flow); extrusion_paths_append(paths, *extrusion, role_normal, is_external ? params.ext_perimeter_flow : params.perimeter_flow);
} }
// Append paths to collection. // Append paths to collection.

View File

@ -58,9 +58,7 @@ 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. return origin_entity->role().is_external_perimeter();
// rather use origin_entity->role().is_external_perimeter()
return origin_entity->role() == ExtrusionRole::ExternalPerimeter || origin_entity->role() == ExtrusionRole::OverhangPerimeter;
} }
Vec2f a; Vec2f a;

View File

@ -36,6 +36,12 @@ public:
// 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) const { 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); }
// Set the bit corresponding to the given option.
constexpr void operator|=(option_type t) { m_bits = enum_bitmask(m_bits | mask_value(t)); }
// Combine with another enum_bitmask of the same type.
constexpr void operator|=(enum_bitmask<option_type> t) { m_bits = 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) const { 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 has(option_type t) const { return m_bits & mask_value(t); }