WIP Extending the expressivity of ExtrusionRole

Co-authored-by: supermerill <merill@free.fr>
Based on the unfinished idea of @supermerill, defining ExtrusionRole
as a bit mask of ExtrusionRoleModifier.
Because the ExtrusionRole was used for both ExtrusionEntity and
G-code export / G-code viewer, the original ExtrusionRole had to be split
to ExtrusionRole and GCodeExtrusionRole to support bitmask attributes
for the former while keeing a low number of ordinary values for the latter.
This commit is contained in:
Vojtech Bubnik 2023-01-16 10:14:32 +01:00
parent 661463645b
commit 5991850db1
25 changed files with 307 additions and 216 deletions

View File

@ -490,7 +490,7 @@ static void make_inner_brim(const Print &print,
loops = union_pt_chained_outside_in(loops); loops = union_pt_chained_outside_in(loops);
std::reverse(loops.begin(), loops.end()); std::reverse(loops.begin(), loops.end());
extrusion_entities_append_loops(brim.entities, std::move(loops), erSkirt, float(flow.mm3_per_mm()), extrusion_entities_append_loops(brim.entities, std::move(loops), ExtrusionRole::Skirt, float(flow.mm3_per_mm()),
float(flow.width()), float(print.skirt_first_layer_height())); float(flow.width()), float(print.skirt_first_layer_height()));
} }
@ -672,7 +672,7 @@ ExtrusionEntityCollection make_brim(const Print &print, PrintTryCancel try_cance
if (i + 1 == j && first_path.size() > 3 && first_path.front().x() == first_path.back().x() && first_path.front().y() == first_path.back().y()) { if (i + 1 == j && first_path.size() > 3 && first_path.front().x() == first_path.back().x() && first_path.front().y() == first_path.back().y()) {
auto *loop = new ExtrusionLoop(); auto *loop = new ExtrusionLoop();
brim.entities.emplace_back(loop); brim.entities.emplace_back(loop);
loop->paths.emplace_back(erSkirt, float(flow.mm3_per_mm()), float(flow.width()), float(print.skirt_first_layer_height())); loop->paths.emplace_back(ExtrusionRole::Skirt, float(flow.mm3_per_mm()), float(flow.width()), float(print.skirt_first_layer_height()));
Points &points = loop->paths.front().polyline.points; Points &points = loop->paths.front().polyline.points;
points.reserve(first_path.size()); points.reserve(first_path.size());
for (const ClipperLib_Z::IntPoint &pt : first_path) for (const ClipperLib_Z::IntPoint &pt : first_path)
@ -683,7 +683,7 @@ ExtrusionEntityCollection make_brim(const Print &print, PrintTryCancel try_cance
ExtrusionEntityCollection this_loop_trimmed; ExtrusionEntityCollection this_loop_trimmed;
this_loop_trimmed.entities.reserve(j - i); this_loop_trimmed.entities.reserve(j - i);
for (; i < j; ++ i) { for (; i < j; ++ i) {
this_loop_trimmed.entities.emplace_back(new ExtrusionPath(erSkirt, float(flow.mm3_per_mm()), float(flow.width()), float(print.skirt_first_layer_height()))); this_loop_trimmed.entities.emplace_back(new ExtrusionPath(ExtrusionRole::Skirt, float(flow.mm3_per_mm()), float(flow.width()), float(print.skirt_first_layer_height())));
const ClipperLib_Z::Path &path = *loops_trimmed_order[i].first; const ClipperLib_Z::Path &path = *loops_trimmed_order[i].first;
Points &points = dynamic_cast<ExtrusionPath*>(this_loop_trimmed.entities.back())->polyline.points; Points &points = dynamic_cast<ExtrusionPath*>(this_loop_trimmed.entities.back())->polyline.points;
points.reserve(path.size()); points.reserve(path.size());
@ -699,7 +699,7 @@ ExtrusionEntityCollection make_brim(const Print &print, PrintTryCancel try_cance
} }
} }
} else { } else {
extrusion_entities_append_loops_and_paths(brim.entities, std::move(all_loops), erSkirt, float(flow.mm3_per_mm()), float(flow.width()), float(print.skirt_first_layer_height())); extrusion_entities_append_loops_and_paths(brim.entities, std::move(all_loops), ExtrusionRole::Skirt, float(flow.mm3_per_mm()), float(flow.width()), float(print.skirt_first_layer_height()));
} }
make_inner_brim(print, top_level_objects_with_brim, bottom_layers_expolygons, brim); make_inner_brim(print, top_level_objects_with_brim, bottom_layers_expolygons, brim);

View File

@ -322,8 +322,29 @@ double ExtrusionLoop::min_mm3_per_mm() const
return min_mm3_per_mm; return min_mm3_per_mm;
} }
// Convert a rich bitmask based ExtrusionRole to a less expressive ordinal GCodeExtrusionRole.
// GCodeExtrusionRole is to be serialized into G-code and deserialized by G-code viewer,
GCodeExtrusionRole extrusion_role_to_gcode_extrusion_role(ExtrusionRole role)
{
if (role == ExtrusionRole::None) return erNone;
if (role == ExtrusionRole::Perimeter) return erPerimeter;
if (role == ExtrusionRole::ExternalPerimeter) return erExternalPerimeter;
if (role == ExtrusionRole::OverhangPerimeter) return erOverhangPerimeter;
if (role == ExtrusionRole::InternalInfill) return erInternalInfill;
if (role == ExtrusionRole::SolidInfill) return erSolidInfill;
if (role == ExtrusionRole::TopSolidInfill) return erTopSolidInfill;
if (role == ExtrusionRole::Ironing) return erIroning;
if (role == ExtrusionRole::BridgeInfill) return erBridgeInfill;
if (role == ExtrusionRole::GapFill) return erGapFill;
if (role == ExtrusionRole::Skirt) return erSkirt;
if (role == ExtrusionRole::SupportMaterial) return erSupportMaterial;
if (role == ExtrusionRole::SupportMaterialInterface) return erSupportMaterialInterface;
if (role == ExtrusionRole::WipeTower) return erWipeTower;
assert(false);
return erNone;
}
std::string ExtrusionEntity::role_to_string(ExtrusionRole role) std::string gcode_extrusion_role_to_string(GCodeExtrusionRole role)
{ {
switch (role) { switch (role) {
case erNone : return L("Unknown"); case erNone : return L("Unknown");
@ -341,13 +362,12 @@ std::string ExtrusionEntity::role_to_string(ExtrusionRole role)
case erSupportMaterialInterface : return L("Support material interface"); case erSupportMaterialInterface : return L("Support material interface");
case erWipeTower : return L("Wipe tower"); case erWipeTower : return L("Wipe tower");
case erCustom : return L("Custom"); case erCustom : return L("Custom");
case erMixed : return L("Mixed");
default : assert(false); default : assert(false);
} }
return ""; return {};
} }
ExtrusionRole ExtrusionEntity::string_to_role(const std::string_view role) GCodeExtrusionRole string_to_gcode_extrusion_role(const std::string_view role)
{ {
if (role == L("Perimeter")) if (role == L("Perimeter"))
return erPerimeter; return erPerimeter;
@ -377,8 +397,6 @@ ExtrusionRole ExtrusionEntity::string_to_role(const std::string_view role)
return erWipeTower; return erWipeTower;
else if (role == L("Custom")) else if (role == L("Custom"))
return erCustom; return erCustom;
else if (role == L("Mixed"))
return erMixed;
else else
return erNone; return erNone;
} }

View File

@ -4,6 +4,7 @@
#include "libslic3r.h" #include "libslic3r.h"
#include "Polygon.hpp" #include "Polygon.hpp"
#include "Polyline.hpp" #include "Polyline.hpp"
#include "enum_bitmask.hpp"
#include <assert.h> #include <assert.h>
#include <string_view> #include <string_view>
@ -16,8 +17,113 @@ using ExPolygons = std::vector<ExPolygon>;
class ExtrusionEntityCollection; class ExtrusionEntityCollection;
class Extruder; class Extruder;
// Each ExtrusionRole value identifies a distinct set of { extruder, speed } enum class ExtrusionRoleModifier : uint16_t {
enum ExtrusionRole : uint8_t { // 1) Extrusion types
// Perimeter (external, inner, ...)
Perimeter,
// Infill (top / bottom / solid inner / sparse inner / bridging inner ...)
Infill,
// Variable width extrusion
Thin,
// Support material extrusion
Support,
Skirt,
Wipe,
// 2) Extrusion modifiers
External,
Solid,
Ironing,
Bridge,
// 3) Special types
// Indicator that the extrusion role was mixed from multiple differing extrusion roles,
// for example from Support and SupportInterface.
Mixed,
// Stopper, there should be maximum 16 modifiers defined for uint16_t bit mask.
Count
};
// There should be maximum 16 modifiers defined for uint16_t bit mask.
static_assert(int(ExtrusionRoleModifier::Count) <= 16, "ExtrusionRoleModifier: there must be maximum 16 modifiers defined to fit a 16 bit bitmask");
using ExtrusionRoleModifiers = enum_bitmask<ExtrusionRoleModifier>;
ENABLE_ENUM_BITMASK_OPERATORS(ExtrusionRoleModifier);
struct ExtrusionRole : public ExtrusionRoleModifiers
{
constexpr ExtrusionRole(const ExtrusionRoleModifier bit) : ExtrusionRoleModifiers(bit) {}
constexpr ExtrusionRole(const ExtrusionRoleModifiers bits) : ExtrusionRoleModifiers(bits) {}
static constexpr const ExtrusionRoleModifiers None{};
// Internal perimeter, not bridging.
static constexpr const ExtrusionRoleModifiers Perimeter{ ExtrusionRoleModifier::Perimeter };
// External perimeter, not bridging.
static constexpr const ExtrusionRoleModifiers ExternalPerimeter{ ExtrusionRoleModifier::Perimeter | ExtrusionRoleModifier::External };
// Perimeter, bridging. To be or'ed with ExtrusionRoleModifier::External for external bridging perimeter.
static constexpr const ExtrusionRoleModifiers OverhangPerimeter{ ExtrusionRoleModifier::Perimeter | ExtrusionRoleModifier::Bridge };
// Sparse internal infill.
static constexpr const ExtrusionRoleModifiers InternalInfill{ ExtrusionRoleModifier::Infill };
// Solid internal infill.
static constexpr const ExtrusionRoleModifiers SolidInfill{ ExtrusionRoleModifier::Infill | ExtrusionRoleModifier::Solid };
// Top solid infill (visible).
//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 };
// 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 };
// Gap fill extrusion, currently used for any variable width extrusion: Thin walls outside of the outer extrusion,
// gap fill in between perimeters, gap fill between the inner perimeter and infill.
//FIXME revise GapFill and ThinWall types, split Gap Fill to Gap Fill and ThinWall.
static constexpr const ExtrusionRoleModifiers GapFill{ ExtrusionRoleModifier::Thin }; // | ExtrusionRoleModifier::External };
// static constexpr const ExtrusionRoleModifiers ThinWall{ ExtrusionRoleModifier::Thin };
static constexpr const ExtrusionRoleModifiers Skirt{ ExtrusionRoleModifier::Skirt };
// Support base material, printed with non-soluble plastic.
static constexpr const ExtrusionRoleModifiers SupportMaterial{ ExtrusionRoleModifier::Support };
// Support interface material, printed with soluble plastic.
static constexpr const ExtrusionRoleModifiers SupportMaterialInterface{ ExtrusionRoleModifier::Support | ExtrusionRoleModifier::External };
// Wipe tower material.
static constexpr const ExtrusionRoleModifiers WipeTower{ ExtrusionRoleModifier::Wipe };
// Extrusion role for a collection with multiple extrusion roles.
static constexpr const ExtrusionRoleModifiers Mixed{ ExtrusionRoleModifier::Mixed };
};
// Special flags describing loop
enum ExtrusionLoopRole {
elrDefault,
elrContourInternalPerimeter,
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;
}
enum GCodeExtrusionRole : uint8_t {
erNone, erNone,
erPerimeter, erPerimeter,
erExternalPerimeter, erExternalPerimeter,
@ -32,49 +138,12 @@ enum ExtrusionRole : uint8_t {
erSupportMaterial, erSupportMaterial,
erSupportMaterialInterface, erSupportMaterialInterface,
erWipeTower, erWipeTower,
// Custom (user defined) G-code block, for example start / end G-code.
erCustom, erCustom,
// Extrusion role for a collection with multiple extrusion roles. // Stopper to count number of enums.
erMixed,
erCount erCount
}; };
// Special flags describing loop
enum ExtrusionLoopRole {
elrDefault,
elrContourInternalPerimeter,
elrSkirt,
};
inline bool is_perimeter(ExtrusionRole role)
{
return role == erPerimeter
|| role == erExternalPerimeter
|| role == erOverhangPerimeter;
}
inline bool is_infill(ExtrusionRole role)
{
return role == erBridgeInfill
|| role == erInternalInfill
|| role == erSolidInfill
|| role == erTopSolidInfill
|| role == erIroning;
}
inline bool is_solid_infill(ExtrusionRole role)
{
return role == erBridgeInfill
|| role == erSolidInfill
|| role == erTopSolidInfill
|| role == erIroning;
}
inline bool is_bridge(ExtrusionRole role) {
return role == erBridgeInfill
|| role == erOverhangPerimeter;
}
class ExtrusionEntity class ExtrusionEntity
{ {
public: public:
@ -108,11 +177,15 @@ public:
virtual Polylines as_polylines() const { Polylines dst; this->collect_polylines(dst); return dst; } virtual Polylines as_polylines() const { Polylines dst; this->collect_polylines(dst); return dst; }
virtual double length() const = 0; virtual double length() const = 0;
virtual double total_volume() const = 0; virtual double total_volume() const = 0;
static std::string role_to_string(ExtrusionRole role);
static ExtrusionRole string_to_role(const std::string_view role);
}; };
// Convert a rich bitmask based ExtrusionRole to a less expressive ordinal GCodeExtrusionRole.
// GCodeExtrusionRole is to be serialized into G-code and deserialized by G-code viewer,
GCodeExtrusionRole extrusion_role_to_gcode_extrusion_role(ExtrusionRole role);
std::string gcode_extrusion_role_to_string(GCodeExtrusionRole role);
GCodeExtrusionRole string_to_gcode_extrusion_role(const std::string_view role);
typedef std::vector<ExtrusionEntity*> ExtrusionEntitiesPtr; typedef std::vector<ExtrusionEntity*> ExtrusionEntitiesPtr;
class ExtrusionPath : public ExtrusionEntity class ExtrusionPath : public ExtrusionEntity
@ -217,7 +290,7 @@ public:
size_t size() const { return this->paths.size(); } size_t size() const { return this->paths.size(); }
bool empty() const { return this->paths.empty(); } bool empty() const { return this->paths.empty(); }
double length() const override; double length() const override;
ExtrusionRole role() const override { return this->paths.empty() ? erNone : this->paths.front().role(); } ExtrusionRole role() const override { return this->paths.empty() ? ExtrusionRole::None : this->paths.front().role(); }
// Produce a list of 2D polygons covered by the extruded paths, offsetted by the extrusion width. // Produce a list of 2D polygons covered by the extruded paths, offsetted by the extrusion width.
// Increase the offset by scaled_epsilon to achieve an overlap, so a union will produce no gaps. // Increase the offset by scaled_epsilon to achieve an overlap, so a union will produce no gaps.
void polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const override; void polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const override;
@ -279,7 +352,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;
ExtrusionRole role() const override { return this->paths.empty() ? erNone : this->paths.front().role(); } ExtrusionRole role() const override { return this->paths.empty() ? ExtrusionRole::None : this->paths.front().role(); }
ExtrusionLoopRole loop_role() const { return m_loop_role; } ExtrusionLoopRole loop_role() const { return m_loop_role; }
// Produce a list of 2D polygons covered by the extruded paths, offsetted by the extrusion width. // Produce a list of 2D polygons covered by the extruded paths, offsetted by the extrusion width.
// Increase the offset by scaled_epsilon to achieve an overlap, so a union will produce no gaps. // Increase the offset by scaled_epsilon to achieve an overlap, so a union will produce no gaps.
@ -304,8 +377,6 @@ public:
} }
double total_volume() const override { double volume =0.; for (const auto& path : paths) volume += path.total_volume(); return volume; } double total_volume() const override { double volume =0.; for (const auto& path : paths) volume += path.total_volume(); return volume; }
//static inline std::string role_to_string(ExtrusionLoopRole role);
#ifndef NDEBUG #ifndef NDEBUG
bool validate() const { bool validate() const {
assert(this->first_point() == this->paths.back().polyline.points.back()); assert(this->first_point() == this->paths.back().polyline.points.back());

View File

@ -8,7 +8,7 @@ namespace Slic3r {
void filter_by_extrusion_role_in_place(ExtrusionEntitiesPtr &extrusion_entities, ExtrusionRole role) void filter_by_extrusion_role_in_place(ExtrusionEntitiesPtr &extrusion_entities, ExtrusionRole role)
{ {
if (role != erMixed) { if (role != ExtrusionRole::Mixed) {
auto first = extrusion_entities.begin(); auto first = extrusion_entities.begin();
auto last = extrusion_entities.end(); auto last = extrusion_entities.end();
extrusion_entities.erase( extrusion_entities.erase(

View File

@ -54,10 +54,10 @@ public:
bool is_collection() const override { return true; } bool is_collection() const override { return true; }
ExtrusionRole role() const override { ExtrusionRole role() const override {
ExtrusionRole out = erNone; ExtrusionRole out{ ExtrusionRole::None };
for (const ExtrusionEntity *ee : entities) { for (const ExtrusionEntity *ee : entities) {
ExtrusionRole er = ee->role(); ExtrusionRole er = ee->role();
out = (out == erNone || out == er) ? er : erMixed; out = (out == ExtrusionRole::None || out == er) ? er : ExtrusionRole::Mixed;
} }
return out; return out;
} }
@ -96,8 +96,8 @@ public:
} }
void replace(size_t i, const ExtrusionEntity &entity); void replace(size_t i, const ExtrusionEntity &entity);
void remove(size_t i); void remove(size_t i);
static ExtrusionEntityCollection chained_path_from(const ExtrusionEntitiesPtr &extrusion_entities, const Point &start_near, ExtrusionRole role = erMixed); static ExtrusionEntityCollection chained_path_from(const ExtrusionEntitiesPtr &extrusion_entities, const Point &start_near, ExtrusionRole role = ExtrusionRole::Mixed);
ExtrusionEntityCollection chained_path_from(const Point &start_near, ExtrusionRole role = erMixed) const ExtrusionEntityCollection chained_path_from(const Point &start_near, ExtrusionRole role = ExtrusionRole::Mixed) const
{ return this->no_sort ? *this : chained_path_from(this->entities, start_near, role); } { return this->no_sort ? *this : chained_path_from(this->entities, start_near, role); }
void reverse() override; void reverse() override;
const Point& first_point() const override { return this->entities.front()->first_point(); } const Point& first_point() const override { return this->entities.front()->first_point(); }

View File

@ -52,7 +52,7 @@ struct SurfaceFillParams
Flow flow; Flow flow;
// For the output // For the output
ExtrusionRole extrusion_role = ExtrusionRole(0); ExtrusionRole extrusion_role{ ExtrusionRole::None };
// Various print settings? // Various print settings?
@ -81,8 +81,7 @@ struct SurfaceFillParams
RETURN_COMPARE_NON_EQUAL(flow.height()); RETURN_COMPARE_NON_EQUAL(flow.height());
RETURN_COMPARE_NON_EQUAL(flow.nozzle_diameter()); RETURN_COMPARE_NON_EQUAL(flow.nozzle_diameter());
RETURN_COMPARE_NON_EQUAL_TYPED(unsigned, bridge); RETURN_COMPARE_NON_EQUAL_TYPED(unsigned, bridge);
RETURN_COMPARE_NON_EQUAL_TYPED(unsigned, extrusion_role); return this->extrusion_role.lower(rhs.extrusion_role);
return false;
} }
bool operator==(const SurfaceFillParams &rhs) const { bool operator==(const SurfaceFillParams &rhs) const {
@ -145,10 +144,10 @@ std::vector<SurfaceFill> group_fills(const Layer &layer)
params.extrusion_role = params.extrusion_role =
is_bridge ? is_bridge ?
erBridgeInfill : ExtrusionRole::BridgeInfill :
(surface.is_solid() ? (surface.is_solid() ?
(surface.is_top() ? erTopSolidInfill : erSolidInfill) : (surface.is_top() ? ExtrusionRole::TopSolidInfill : ExtrusionRole::SolidInfill) :
erInternalInfill); ExtrusionRole::InternalInfill);
params.bridge_angle = float(surface.bridge_angle); params.bridge_angle = float(surface.bridge_angle);
params.angle = float(Geometry::deg2rad(region_config.fill_angle.value)); params.angle = float(Geometry::deg2rad(region_config.fill_angle.value));
@ -282,7 +281,7 @@ std::vector<SurfaceFill> group_fills(const Layer &layer)
params.extruder = layerm.region().extruder(frSolidInfill); params.extruder = layerm.region().extruder(frSolidInfill);
params.pattern = layerm.region().config().top_fill_pattern == ipMonotonic ? ipMonotonic : ipRectilinear; params.pattern = layerm.region().config().top_fill_pattern == ipMonotonic ? ipMonotonic : ipRectilinear;
params.density = 100.f; params.density = 100.f;
params.extrusion_role = erInternalInfill; params.extrusion_role = ExtrusionRole::InternalInfill;
params.angle = float(Geometry::deg2rad(layerm.region().config().fill_angle.value)); params.angle = float(Geometry::deg2rad(layerm.region().config().fill_angle.value));
// calculate the actual flow we'll be using for this infill // calculate the actual flow we'll be using for this infill
params.flow = layerm.flow(frSolidInfill); params.flow = layerm.flow(frSolidInfill);
@ -785,7 +784,7 @@ void Layer::make_ironing()
eec->no_sort = true; eec->no_sort = true;
extrusion_entities_append_paths( extrusion_entities_append_paths(
eec->entities, std::move(polylines), eec->entities, std::move(polylines),
erIroning, ExtrusionRole::Ironing,
flow_mm3_per_mm, extrusion_width, float(extrusion_height)); flow_mm3_per_mm, extrusion_width, float(extrusion_height));
insert_fills_into_islands(*this, ironing_params.region_id, fill_begin, uint32_t(ironing_params.layerm->fills().size())); insert_fills_into_islands(*this, ironing_params.region_id, fill_begin, uint32_t(ironing_params.layerm->fills().size()));
} }

View File

@ -148,7 +148,7 @@ namespace Slic3r {
int int
OozePrevention::_get_temp(GCode& gcodegen) OozePrevention::_get_temp(GCode& gcodegen)
{ {
return (gcodegen.layer() != NULL && gcodegen.layer()->id() == 0) return (gcodegen.layer() != nullptr && gcodegen.layer()->id() == 0)
? gcodegen.config().first_layer_temperature.get_at(gcodegen.writer().extruder()->id()) ? gcodegen.config().first_layer_temperature.get_at(gcodegen.writer().extruder()->id())
: gcodegen.config().temperature.get_at(gcodegen.writer().extruder()->id()); : gcodegen.config().temperature.get_at(gcodegen.writer().extruder()->id());
} }
@ -244,7 +244,7 @@ namespace Slic3r {
gcodegen.m_avoid_crossing_perimeters.use_external_mp_once(); gcodegen.m_avoid_crossing_perimeters.use_external_mp_once();
gcode += gcodegen.travel_to( gcode += gcodegen.travel_to(
wipe_tower_point_to_object_point(gcodegen, start_pos), wipe_tower_point_to_object_point(gcodegen, start_pos),
erMixed, ExtrusionRole::Mixed,
"Travel to a Wipe Tower"); "Travel to a Wipe Tower");
gcode += gcodegen.unretract(); gcode += gcodegen.unretract();
} }
@ -864,7 +864,7 @@ namespace DoExport {
auto min_mm3_per_mm_no_ironing = [](const ExtrusionEntityCollection& eec) -> double { auto min_mm3_per_mm_no_ironing = [](const ExtrusionEntityCollection& eec) -> double {
double min = std::numeric_limits<double>::max(); double min = std::numeric_limits<double>::max();
for (const ExtrusionEntity* ee : eec.entities) for (const ExtrusionEntity* ee : eec.entities)
if (ee->role() != erIroning) if (ee->role() != ExtrusionRole::Ironing)
min = std::min(min, ee->min_mm3_per_mm()); min = std::min(min, ee->min_mm3_per_mm());
return min; return min;
}; };
@ -1271,7 +1271,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
this->_print_first_layer_extruder_temperatures(file, print, start_gcode, initial_extruder_id, false); this->_print_first_layer_extruder_temperatures(file, print, start_gcode, initial_extruder_id, false);
// adds tag for processor // adds tag for processor
file.write_format(";%s%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Role).c_str(), ExtrusionEntity::role_to_string(erCustom).c_str()); file.write_format(";%s%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Role).c_str(), gcode_extrusion_role_to_string(erCustom).c_str());
// Write the custom start G-code // Write the custom start G-code
file.writeln(start_gcode); file.writeln(start_gcode);
@ -1320,7 +1320,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
m_enable_cooling_markers = false; // we're not filtering these moves through CoolingBuffer m_enable_cooling_markers = false; // we're not filtering these moves through CoolingBuffer
m_avoid_crossing_perimeters.use_external_mp_once(); m_avoid_crossing_perimeters.use_external_mp_once();
file.write(this->retract()); file.write(this->retract());
file.write(this->travel_to(Point(0, 0), erNone, "move to origin position for next object")); file.write(this->travel_to(Point(0, 0), ExtrusionRole::None, "move to origin position for next object"));
m_enable_cooling_markers = true; m_enable_cooling_markers = true;
// Disable motion planner when traveling to first object point. // Disable motion planner when traveling to first object point.
m_avoid_crossing_perimeters.disable_once(); m_avoid_crossing_perimeters.disable_once();
@ -1407,7 +1407,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
file.write(m_writer.set_fan(0)); file.write(m_writer.set_fan(0));
// adds tag for processor // adds tag for processor
file.write_format(";%s%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Role).c_str(), ExtrusionEntity::role_to_string(erCustom).c_str()); file.write_format(";%s%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Role).c_str(), gcode_extrusion_role_to_string(erCustom).c_str());
// Process filament-specific gcode in extruder order. // Process filament-specific gcode in extruder order.
{ {
@ -2305,8 +2305,8 @@ void GCode::process_layer_single_object(
if (! print_wipe_extrusions && layer_to_print.support_layer != nullptr) if (! print_wipe_extrusions && layer_to_print.support_layer != nullptr)
if (const SupportLayer &support_layer = *layer_to_print.support_layer; ! support_layer.support_fills.entities.empty()) { if (const SupportLayer &support_layer = *layer_to_print.support_layer; ! support_layer.support_fills.entities.empty()) {
ExtrusionRole role = support_layer.support_fills.role(); ExtrusionRole role = support_layer.support_fills.role();
bool has_support = role == erMixed || role == erSupportMaterial; bool has_support = role == ExtrusionRole::Mixed || role == ExtrusionRole::SupportMaterial;
bool has_interface = role == erMixed || role == erSupportMaterialInterface; bool has_interface = role == ExtrusionRole::Mixed || role == ExtrusionRole::SupportMaterialInterface;
// Extruder ID of the support base. -1 if "don't care". // Extruder ID of the support base. -1 if "don't care".
unsigned int support_extruder = print_object.config().support_material_extruder.value - 1; unsigned int support_extruder = print_object.config().support_material_extruder.value - 1;
// Shall the support be printed with the active extruder, preferably with non-soluble, to avoid tool changes? // Shall the support be printed with the active extruder, preferably with non-soluble, to avoid tool changes?
@ -2340,8 +2340,8 @@ void GCode::process_layer_single_object(
m_layer = layer_to_print.support_layer; m_layer = layer_to_print.support_layer;
m_object_layer_over_raft = false; m_object_layer_over_raft = false;
gcode += this->extrude_support( gcode += this->extrude_support(
// support_extrusion_role is erSupportMaterial, erSupportMaterialInterface or erMixed for all extrusion paths. // support_extrusion_role is ExtrusionRole::SupportMaterial, ExtrusionRole::SupportMaterialInterface or ExtrusionRole::Mixed for all extrusion paths.
support_layer.support_fills.chained_path_from(m_last_pos, has_support ? (has_interface ? erMixed : erSupportMaterial) : erSupportMaterialInterface)); support_layer.support_fills.chained_path_from(m_last_pos, has_support ? (has_interface ? ExtrusionRole::Mixed : ExtrusionRole::SupportMaterial) : ExtrusionRole::SupportMaterialInterface));
} }
} }
@ -2385,7 +2385,7 @@ void GCode::process_layer_single_object(
for (uint32_t fill_id : *it_fill_range) { for (uint32_t fill_id : *it_fill_range) {
assert(dynamic_cast<ExtrusionEntityCollection*>(fills.entities[fill_id])); assert(dynamic_cast<ExtrusionEntityCollection*>(fills.entities[fill_id]));
if (auto *eec = static_cast<ExtrusionEntityCollection*>(fills.entities[fill_id]); if (auto *eec = static_cast<ExtrusionEntityCollection*>(fills.entities[fill_id]);
(eec->role() == erIroning) == ironing && shall_print_this_extrusion_collection(eec, region)) { (eec->role() == ExtrusionRole::Ironing) == ironing && shall_print_this_extrusion_collection(eec, region)) {
if (eec->can_reverse()) if (eec->can_reverse())
// Flatten the infill collection for better path planning. // Flatten the infill collection for better path planning.
for (auto *ee : eec->entities) for (auto *ee : eec->entities)
@ -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() == erExternalPerimeter && m_layer != NULL && m_config.perimeters.value > 1 && paths.front().size() >= 2 && paths.back().polyline.points.size() >= 3) { if (paths.back().role() == ExtrusionRole::ExternalPerimeter && 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.
@ -2739,9 +2739,9 @@ std::string GCode::extrude_support(const ExtrusionEntityCollection &support_fill
const double support_interface_speed = m_config.support_material_interface_speed.get_abs_value(support_speed); const double support_interface_speed = m_config.support_material_interface_speed.get_abs_value(support_speed);
for (const ExtrusionEntity *ee : support_fills.entities) { for (const ExtrusionEntity *ee : support_fills.entities) {
ExtrusionRole role = ee->role(); ExtrusionRole role = ee->role();
assert(role == erSupportMaterial || role == erSupportMaterialInterface); assert(role == ExtrusionRole::SupportMaterial || role == ExtrusionRole::SupportMaterialInterface);
const auto label = (role == erSupportMaterial) ? support_label : support_interface_label; const auto label = (role == ExtrusionRole::SupportMaterial) ? support_label : support_interface_label;
const double speed = (role == erSupportMaterial) ? support_speed : support_interface_speed; const double speed = (role == ExtrusionRole::SupportMaterial) ? support_speed : support_interface_speed;
const ExtrusionPath *path = dynamic_cast<const ExtrusionPath*>(ee); const ExtrusionPath *path = dynamic_cast<const ExtrusionPath*>(ee);
if (path) if (path)
gcode += this->extrude_path(*path, label, speed); gcode += this->extrude_path(*path, label, speed);
@ -2872,21 +2872,21 @@ std::string GCode::_extrude(const ExtrusionPath &path, const std::string_view de
// set speed // set speed
if (speed == -1) { if (speed == -1) {
if (path.role() == erPerimeter) { if (path.role() == ExtrusionRole::Perimeter) {
speed = m_config.get_abs_value("perimeter_speed"); speed = m_config.get_abs_value("perimeter_speed");
} else if (path.role() == erExternalPerimeter) { } 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() == erOverhangPerimeter || path.role() == erBridgeInfill) { } else if (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() == erInternalInfill) { } else if (path.role() == ExtrusionRole::InternalInfill) {
speed = m_config.get_abs_value("infill_speed"); speed = m_config.get_abs_value("infill_speed");
} else if (path.role() == erSolidInfill) { } else if (path.role() == ExtrusionRole::SolidInfill) {
speed = m_config.get_abs_value("solid_infill_speed"); speed = m_config.get_abs_value("solid_infill_speed");
} else if (path.role() == erTopSolidInfill) { } else if (path.role() == ExtrusionRole::TopSolidInfill) {
speed = m_config.get_abs_value("top_solid_infill_speed"); speed = m_config.get_abs_value("top_solid_infill_speed");
} else if (path.role() == erIroning) { } else if (path.role() == ExtrusionRole::Ironing) {
speed = m_config.get_abs_value("ironing_speed"); speed = m_config.get_abs_value("ironing_speed");
} else if (path.role() == erGapFill) { } else if (path.role() == ExtrusionRole::GapFill) {
speed = m_config.get_abs_value("gap_fill_speed"); speed = m_config.get_abs_value("gap_fill_speed");
} else { } else {
throw Slic3r::InvalidArgument("Invalid speed"); throw Slic3r::InvalidArgument("Invalid speed");
@ -2927,9 +2927,9 @@ std::string GCode::_extrude(const ExtrusionPath &path, const std::string_view de
// extrude arc or line // extrude arc or line
if (m_enable_extrusion_role_markers) if (m_enable_extrusion_role_markers)
{ {
if (path.role() != m_last_extrusion_role) if (GCodeExtrusionRole role = extrusion_role_to_gcode_extrusion_role(path.role()); role != m_last_extrusion_role)
{ {
m_last_extrusion_role = path.role(); m_last_extrusion_role = role;
if (m_enable_extrusion_role_markers) if (m_enable_extrusion_role_markers)
{ {
char buf[32]; char buf[32];
@ -2945,10 +2945,10 @@ std::string GCode::_extrude(const ExtrusionPath &path, const std::string_view de
bool last_was_wipe_tower = (m_last_processor_extrusion_role == erWipeTower); bool last_was_wipe_tower = (m_last_processor_extrusion_role == erWipeTower);
assert(is_decimal_separator_point()); assert(is_decimal_separator_point());
if (path.role() != m_last_processor_extrusion_role) { if (GCodeExtrusionRole role = extrusion_role_to_gcode_extrusion_role(path.role()); role != m_last_processor_extrusion_role) {
m_last_processor_extrusion_role = path.role(); m_last_processor_extrusion_role = role;
char buf[64]; char buf[64];
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(), gcode_extrusion_role_to_string(m_last_processor_extrusion_role).c_str());
gcode += buf; gcode += buf;
} }
@ -2979,7 +2979,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, const std::string_view de
gcode += ";_BRIDGE_FAN_START\n"; gcode += ";_BRIDGE_FAN_START\n";
else else
comment = ";_EXTRUDE_SET_SPEED"; comment = ";_EXTRUDE_SET_SPEED";
if (path.role() == erExternalPerimeter) if (path.role() == ExtrusionRole::ExternalPerimeter)
comment += ";_EXTERNAL_PERIMETER"; comment += ";_EXTERNAL_PERIMETER";
} }
@ -3112,7 +3112,7 @@ bool GCode::needs_retraction(const Polyline &travel, ExtrusionRole role)
return false; return false;
} }
if (role == erSupportMaterial) if (role == ExtrusionRole::SupportMaterial)
if (const SupportLayer *support_layer = dynamic_cast<const SupportLayer*>(m_layer); if (const SupportLayer *support_layer = dynamic_cast<const SupportLayer*>(m_layer);
support_layer != nullptr && ! support_layer->support_islands_bboxes.empty()) { support_layer != nullptr && ! support_layer->support_islands_bboxes.empty()) {
BoundingBox bbox_travel = get_extents(travel); BoundingBox bbox_travel = get_extents(travel);

View File

@ -326,7 +326,7 @@ private:
std::string extrude_support(const ExtrusionEntityCollection &support_fills); std::string extrude_support(const ExtrusionEntityCollection &support_fills);
std::string travel_to(const Point &point, ExtrusionRole role, std::string comment); std::string travel_to(const Point &point, ExtrusionRole role, std::string comment);
bool needs_retraction(const Polyline &travel, ExtrusionRole role = erNone); bool needs_retraction(const Polyline &travel, ExtrusionRole role = ExtrusionRole::None);
std::string retract(bool toolchange = false); std::string retract(bool toolchange = false);
std::string unretract() { return m_writer.unlift() + m_writer.unretract(); } std::string unretract() { return m_writer.unlift() + m_writer.unretract(); }
std::string set_extruder(unsigned int extruder_id, double print_z); std::string set_extruder(unsigned int extruder_id, double print_z);
@ -363,7 +363,7 @@ private:
// The Pressure Equalizer removes the markers from the final G-code. // The Pressure Equalizer removes the markers from the final G-code.
bool m_enable_extrusion_role_markers; bool m_enable_extrusion_role_markers;
// Keeps track of the last extrusion role passed to the processor // Keeps track of the last extrusion role passed to the processor
ExtrusionRole m_last_processor_extrusion_role; GCodeExtrusionRole m_last_processor_extrusion_role;
// How many times will change_layer() be called? // How many times will change_layer() be called?
// change_layer() will update the progress bar. // change_layer() will update the progress bar.
unsigned int m_layer_count; unsigned int m_layer_count;
@ -376,7 +376,7 @@ private:
bool m_object_layer_over_raft; bool m_object_layer_over_raft;
double m_volumetric_speed; double m_volumetric_speed;
// Support for the extrusion role markers. Which marker is active? // Support for the extrusion role markers. Which marker is active?
ExtrusionRole m_last_extrusion_role; GCodeExtrusionRole m_last_extrusion_role;
// Support for G-Code Processor // Support for G-Code Processor
float m_last_height{ 0.0f }; float m_last_height{ 0.0f };
float m_last_layer_z{ 0.0f }; float m_last_layer_z{ 0.0f };

View File

@ -415,7 +415,7 @@ void GCodeProcessor::UsedFilaments::process_role_cache(const GCodeProcessor* pro
filament.first = role_cache / s * 0.001; filament.first = role_cache / s * 0.001;
filament.second = role_cache * processor->m_result.filament_densities[processor->m_extruder_id] * 0.001; filament.second = role_cache * processor->m_result.filament_densities[processor->m_extruder_id] * 0.001;
ExtrusionRole active_role = processor->m_extrusion_role; GCodeExtrusionRole active_role = processor->m_extrusion_role;
if (filaments_per_role.find(active_role) != filaments_per_role.end()) { if (filaments_per_role.find(active_role) != filaments_per_role.end()) {
filaments_per_role[active_role].first += filament.first; filaments_per_role[active_role].first += filament.first;
filaments_per_role[active_role].second += filament.second; filaments_per_role[active_role].second += filament.second;
@ -1170,14 +1170,14 @@ std::vector<std::pair<EMoveType, float>> GCodeProcessor::get_moves_time(PrintEst
return ret; return ret;
} }
std::vector<std::pair<ExtrusionRole, float>> GCodeProcessor::get_roles_time(PrintEstimatedStatistics::ETimeMode mode) const std::vector<std::pair<GCodeExtrusionRole, float>> GCodeProcessor::get_roles_time(PrintEstimatedStatistics::ETimeMode mode) const
{ {
std::vector<std::pair<ExtrusionRole, float>> ret; std::vector<std::pair<GCodeExtrusionRole, float>> ret;
if (mode < PrintEstimatedStatistics::ETimeMode::Count) { if (mode < PrintEstimatedStatistics::ETimeMode::Count) {
for (size_t i = 0; i < m_time_processor.machines[static_cast<size_t>(mode)].roles_time.size(); ++i) { for (size_t i = 0; i < m_time_processor.machines[static_cast<size_t>(mode)].roles_time.size(); ++i) {
float time = m_time_processor.machines[static_cast<size_t>(mode)].roles_time[i]; float time = m_time_processor.machines[static_cast<size_t>(mode)].roles_time[i];
if (time > 0.0f) if (time > 0.0f)
ret.push_back({ static_cast<ExtrusionRole>(i), time }); ret.push_back({ static_cast<GCodeExtrusionRole>(i), time });
} }
} }
return ret; return ret;
@ -1645,7 +1645,7 @@ void GCodeProcessor::process_tags(const std::string_view comment, bool producers
// extrusion role tag // extrusion role tag
if (boost::starts_with(comment, reserved_tag(ETags::Role))) { if (boost::starts_with(comment, reserved_tag(ETags::Role))) {
set_extrusion_role(ExtrusionEntity::string_to_role(comment.substr(reserved_tag(ETags::Role).length()))); set_extrusion_role(string_to_gcode_extrusion_role(comment.substr(reserved_tag(ETags::Role).length())));
if (m_extrusion_role == erExternalPerimeter) if (m_extrusion_role == erExternalPerimeter)
m_seams_detector.activate(true); m_seams_detector.activate(true);
return; return;
@ -3771,7 +3771,7 @@ void GCodeProcessor::store_move_vertex(EMoveType type, bool internal_only)
} }
} }
void GCodeProcessor::set_extrusion_role(ExtrusionRole role) void GCodeProcessor::set_extrusion_role(GCodeExtrusionRole role)
{ {
m_used_filaments.process_role_cache(this); m_used_filaments.process_role_cache(this);
m_extrusion_role = role; m_extrusion_role = role;

View File

@ -47,7 +47,7 @@ namespace Slic3r {
float travel_time; float travel_time;
std::vector<std::pair<CustomGCode::Type, std::pair<float, float>>> custom_gcode_times; std::vector<std::pair<CustomGCode::Type, std::pair<float, float>>> custom_gcode_times;
std::vector<std::pair<EMoveType, float>> moves_times; std::vector<std::pair<EMoveType, float>> moves_times;
std::vector<std::pair<ExtrusionRole, float>> roles_times; std::vector<std::pair<GCodeExtrusionRole, float>> roles_times;
std::vector<float> layers_times; std::vector<float> layers_times;
void reset() { void reset() {
@ -62,7 +62,7 @@ namespace Slic3r {
std::vector<double> volumes_per_color_change; std::vector<double> volumes_per_color_change;
std::map<size_t, double> volumes_per_extruder; std::map<size_t, double> volumes_per_extruder;
std::map<ExtrusionRole, std::pair<double, double>> used_filaments_per_role; std::map<GCodeExtrusionRole, std::pair<double, double>> used_filaments_per_role;
std::map<size_t, double> cost_per_extruder; std::map<size_t, double> cost_per_extruder;
std::array<Mode, static_cast<size_t>(ETimeMode::Count)> modes; std::array<Mode, static_cast<size_t>(ETimeMode::Count)> modes;
@ -99,7 +99,7 @@ namespace Slic3r {
{ {
unsigned int gcode_id{ 0 }; unsigned int gcode_id{ 0 };
EMoveType type{ EMoveType::Noop }; EMoveType type{ EMoveType::Noop };
ExtrusionRole extrusion_role{ erNone }; GCodeExtrusionRole extrusion_role{ erNone };
unsigned char extruder_id{ 0 }; unsigned char extruder_id{ 0 };
unsigned char cp_color_id{ 0 }; unsigned char cp_color_id{ 0 };
Vec3f position{ Vec3f::Zero() }; // mm Vec3f position{ Vec3f::Zero() }; // mm
@ -238,7 +238,7 @@ namespace Slic3r {
}; };
EMoveType move_type{ EMoveType::Noop }; EMoveType move_type{ EMoveType::Noop };
ExtrusionRole role{ erNone }; GCodeExtrusionRole role{ erNone };
unsigned int g1_line_id{ 0 }; unsigned int g1_line_id{ 0 };
unsigned int layer_id{ 0 }; unsigned int layer_id{ 0 };
float distance{ 0.0f }; // mm float distance{ 0.0f }; // mm
@ -310,7 +310,7 @@ namespace Slic3r {
std::vector<TimeBlock> blocks; std::vector<TimeBlock> blocks;
std::vector<G1LinesCacheItem> g1_times_cache; std::vector<G1LinesCacheItem> g1_times_cache;
std::array<float, static_cast<size_t>(EMoveType::Count)> moves_time; std::array<float, static_cast<size_t>(EMoveType::Count)> moves_time;
std::array<float, static_cast<size_t>(ExtrusionRole::erCount)> roles_time; std::array<float, static_cast<size_t>(GCodeExtrusionRole::erCount)> roles_time;
std::vector<float> layers_time; std::vector<float> layers_time;
void reset(); void reset();
@ -360,7 +360,7 @@ namespace Slic3r {
std::map<size_t, double> volumes_per_extruder; std::map<size_t, double> volumes_per_extruder;
double role_cache; double role_cache;
std::map<ExtrusionRole, std::pair<double, double>> filaments_per_role; // ExtrusionRole -> (m, g) std::map<GCodeExtrusionRole, std::pair<double, double>> filaments_per_role; // ExtrusionRole -> (m, g)
void reset(); void reset();
@ -441,7 +441,7 @@ namespace Slic3r {
{ {
float value; float value;
float tag_value; float tag_value;
ExtrusionRole role; GCodeExtrusionRole role;
}; };
std::string type; std::string type;
@ -454,7 +454,7 @@ namespace Slic3r {
: type(type), threshold(threshold) : type(type), threshold(threshold)
{} {}
void update(float value, ExtrusionRole role) { void update(float value, GCodeExtrusionRole role) {
if (role != erCustom) { if (role != erCustom) {
++count; ++count;
if (last_tag_value != 0.0f) { if (last_tag_value != 0.0f) {
@ -539,7 +539,7 @@ namespace Slic3r {
float m_mm3_per_mm; float m_mm3_per_mm;
float m_fan_speed; // percentage float m_fan_speed; // percentage
float m_z_offset; // mm float m_z_offset; // mm
ExtrusionRole m_extrusion_role; GCodeExtrusionRole m_extrusion_role;
unsigned char m_extruder_id; unsigned char m_extruder_id;
ExtruderColors m_extruder_colors; ExtruderColors m_extruder_colors;
ExtruderTemps m_extruder_temps; ExtruderTemps m_extruder_temps;
@ -620,7 +620,7 @@ namespace Slic3r {
std::vector<std::pair<CustomGCode::Type, std::pair<float, float>>> get_custom_gcode_times(PrintEstimatedStatistics::ETimeMode mode, bool include_remaining) const; std::vector<std::pair<CustomGCode::Type, std::pair<float, float>>> get_custom_gcode_times(PrintEstimatedStatistics::ETimeMode mode, bool include_remaining) const;
std::vector<std::pair<EMoveType, float>> get_moves_time(PrintEstimatedStatistics::ETimeMode mode) const; std::vector<std::pair<EMoveType, float>> get_moves_time(PrintEstimatedStatistics::ETimeMode mode) const;
std::vector<std::pair<ExtrusionRole, float>> get_roles_time(PrintEstimatedStatistics::ETimeMode mode) const; std::vector<std::pair<GCodeExtrusionRole, float>> get_roles_time(PrintEstimatedStatistics::ETimeMode mode) const;
std::vector<float> get_layers_time(PrintEstimatedStatistics::ETimeMode mode) const; std::vector<float> get_layers_time(PrintEstimatedStatistics::ETimeMode mode) const;
private: private:
@ -757,7 +757,7 @@ namespace Slic3r {
void store_move_vertex(EMoveType type, bool internal_only = false); void store_move_vertex(EMoveType type, bool internal_only = false);
void set_extrusion_role(ExtrusionRole role); void set_extrusion_role(GCodeExtrusionRole role);
float minimum_feedrate(PrintEstimatedStatistics::ETimeMode mode, float feedrate) const; float minimum_feedrate(PrintEstimatedStatistics::ETimeMode mode, float feedrate) const;
float minimum_travel_feedrate(PrintEstimatedStatistics::ETimeMode mode, float feedrate) const; float minimum_travel_feedrate(PrintEstimatedStatistics::ETimeMode mode, float feedrate) const;

View File

@ -60,7 +60,7 @@ PressureEqualizer::PressureEqualizer(const Slic3r::GCodeConfig &config) : m_use_
} }
// Don't regulate the pressure before and after gap-fill and ironing. // Don't regulate the pressure before and after gap-fill and ironing.
for (const ExtrusionRole er : {erGapFill, erIroning}) { for (const GCodeExtrusionRole er : {erGapFill, erIroning}) {
m_max_volumetric_extrusion_rate_slopes[er].negative = 0; m_max_volumetric_extrusion_rate_slopes[er].negative = 0;
m_max_volumetric_extrusion_rate_slopes[er].positive = 0; m_max_volumetric_extrusion_rate_slopes[er].positive = 0;
} }
@ -185,7 +185,7 @@ bool PressureEqualizer::process_line(const char *line, const char *line_end, GCo
if (strncmp(line, EXTRUSION_ROLE_TAG.data(), EXTRUSION_ROLE_TAG.length()) == 0) { if (strncmp(line, EXTRUSION_ROLE_TAG.data(), EXTRUSION_ROLE_TAG.length()) == 0) {
line += EXTRUSION_ROLE_TAG.length(); line += EXTRUSION_ROLE_TAG.length();
int role = atoi(line); int role = atoi(line);
m_current_extrusion_role = ExtrusionRole(role); m_current_extrusion_role = GCodeExtrusionRole(role);
#ifdef PRESSURE_EQUALIZER_DEBUG #ifdef PRESSURE_EQUALIZER_DEBUG
++line_idx; ++line_idx;
#endif #endif
@ -542,7 +542,7 @@ void PressureEqualizer::adjust_volumetric_rate()
for (size_t iRole = 1; iRole < erCount; ++ iRole) { for (size_t iRole = 1; iRole < erCount; ++ iRole) {
const float &rate_slope = m_max_volumetric_extrusion_rate_slopes[iRole].negative; const float &rate_slope = m_max_volumetric_extrusion_rate_slopes[iRole].negative;
if (rate_slope == 0 || feedrate_per_extrusion_role[iRole] == std::numeric_limits<float>::max()) if (rate_slope == 0 || feedrate_per_extrusion_role[iRole] == std::numeric_limits<float>::max())
continue; // The negative rate is unlimited or the rate for ExtrusionRole iRole is unlimited. continue; // The negative rate is unlimited or the rate for GCodeExtrusionRole iRole is unlimited.
float rate_end = feedrate_per_extrusion_role[iRole]; float rate_end = feedrate_per_extrusion_role[iRole];
if (iRole == line.extrusion_role && rate_succ < rate_end) if (iRole == line.extrusion_role && rate_succ < rate_end)
@ -600,7 +600,7 @@ void PressureEqualizer::adjust_volumetric_rate()
for (size_t iRole = 1; iRole < erCount; ++ iRole) { for (size_t iRole = 1; iRole < erCount; ++ iRole) {
const float &rate_slope = m_max_volumetric_extrusion_rate_slopes[iRole].positive; const float &rate_slope = m_max_volumetric_extrusion_rate_slopes[iRole].positive;
if (rate_slope == 0 || feedrate_per_extrusion_role[iRole] == std::numeric_limits<float>::max()) if (rate_slope == 0 || feedrate_per_extrusion_role[iRole] == std::numeric_limits<float>::max())
continue; // The positive rate is unlimited or the rate for ExtrusionRole iRole is unlimited. continue; // The positive rate is unlimited or the rate for GCodeExtrusionRole iRole is unlimited.
float rate_start = feedrate_per_extrusion_role[iRole]; float rate_start = feedrate_per_extrusion_role[iRole];
if (!line.adjustable_flow || line.extrusion_role == erExternalPerimeter || line.extrusion_role == erGapFill || line.extrusion_role == erBridgeInfill || line.extrusion_role == erIroning) { if (!line.adjustable_flow || line.extrusion_role == erExternalPerimeter || line.extrusion_role == erGapFill || line.extrusion_role == erBridgeInfill || line.extrusion_role == erIroning) {

View File

@ -77,7 +77,7 @@ private:
// X,Y,Z,E,F // X,Y,Z,E,F
float m_current_pos[5]; float m_current_pos[5];
size_t m_current_extruder; size_t m_current_extruder;
ExtrusionRole m_current_extrusion_role; GCodeExtrusionRole m_current_extrusion_role;
bool m_retracted; bool m_retracted;
bool m_use_relative_e_distances; bool m_use_relative_e_distances;
@ -149,7 +149,7 @@ private:
// Index of the active extruder. // Index of the active extruder.
size_t extruder_id; size_t extruder_id;
// Extrusion role of this segment. // Extrusion role of this segment.
ExtrusionRole extrusion_role; GCodeExtrusionRole extrusion_role;
// Current volumetric extrusion rate. // Current volumetric extrusion rate.
float volumetric_extrusion_rate; float volumetric_extrusion_rate;

View File

@ -407,13 +407,13 @@ Polygons extract_perimeter_polygons(const Layer *layer, std::vector<const LayerR
ExtrusionRole role = perimeter->role(); ExtrusionRole role = perimeter->role();
if (perimeter->is_loop()) { if (perimeter->is_loop()) {
for (const ExtrusionPath &path : static_cast<const ExtrusionLoop*>(perimeter)->paths) { for (const ExtrusionPath &path : static_cast<const ExtrusionLoop*>(perimeter)->paths) {
if (path.role() == ExtrusionRole::erExternalPerimeter) { if (path.role() == ExtrusionRole::ExternalPerimeter) {
role = ExtrusionRole::erExternalPerimeter; role = ExtrusionRole::ExternalPerimeter;
} }
} }
} }
if (role == ExtrusionRole::erExternalPerimeter) { if (role == ExtrusionRole::ExternalPerimeter) {
Points p; Points p;
perimeter->collect_points(p); perimeter->collect_points(p);
polygons.emplace_back(std::move(p)); polygons.emplace_back(std::move(p));
@ -1548,7 +1548,7 @@ void SeamPlacer::place_seam(const Layer *layer, ExtrusionLoop &loop, bool extern
Point seam_point = Point::new_scale(seam_position.x(), seam_position.y()); Point seam_point = Point::new_scale(seam_position.x(), seam_position.y());
if (loop.role() == ExtrusionRole::erPerimeter) { //Hopefully inner perimeter if (loop.role() == ExtrusionRole::Perimeter) { //Hopefully inner perimeter
const SeamCandidate &perimeter_point = layer_perimeters.points[seam_index]; const SeamCandidate &perimeter_point = layer_perimeters.points[seam_index];
ExtrusionLoop::ClosestPathPoint projected_point = loop.get_closest_path_and_point(seam_point, false); ExtrusionLoop::ClosestPathPoint projected_point = loop.get_closest_path_and_point(seam_point, false);
// determine depth of the seam point. // determine depth of the seam point.

View File

@ -197,7 +197,7 @@ void ToolOrdering::initialize_layers(std::vector<coordf_t> &zs)
if (object.config().wipe_into_objects) if (object.config().wipe_into_objects)
return true; return true;
if (!region.config().wipe_into_infill || eec.role() != erInternalInfill) if (!region.config().wipe_into_infill || eec.role() != ExtrusionRole::InternalInfill)
return false; return false;
return true; return true;
@ -210,8 +210,8 @@ void ToolOrdering::collect_extruders(const PrintObject &object, const std::vecto
for (auto support_layer : object.support_layers()) { for (auto support_layer : object.support_layers()) {
LayerTools &layer_tools = this->tools_for_layer(support_layer->print_z); LayerTools &layer_tools = this->tools_for_layer(support_layer->print_z);
ExtrusionRole role = support_layer->support_fills.role(); ExtrusionRole role = support_layer->support_fills.role();
bool has_support = role == erMixed || role == erSupportMaterial; bool has_support = role == ExtrusionRole::Mixed || role == ExtrusionRole::SupportMaterial;
bool has_interface = role == erMixed || role == erSupportMaterialInterface; bool has_interface = role == ExtrusionRole::Mixed || role == ExtrusionRole::SupportMaterialInterface;
unsigned int extruder_support = object.config().support_material_extruder.value; unsigned int extruder_support = object.config().support_material_extruder.value;
unsigned int extruder_interface = object.config().support_material_interface_extruder.value; unsigned int extruder_interface = object.config().support_material_interface_extruder.value;
if (has_support) if (has_support)
@ -266,10 +266,10 @@ void ToolOrdering::collect_extruders(const PrintObject &object, const std::vecto
for (const ExtrusionEntity *ee : layerm->fills()) { for (const ExtrusionEntity *ee : layerm->fills()) {
// 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() ? erNone : fill->entities.front()->role(); ExtrusionRole role = fill->entities.empty() ? ExtrusionRole::None : fill->entities.front()->role();
if (is_solid_infill(role)) if (is_solid_infill(role))
has_solid_infill = true; has_solid_infill = true;
else if (role != erNone) else if (role != ExtrusionRole::None)
has_infill = true; has_infill = true;
if (m_print_config_ptr) { if (m_print_config_ptr) {

View File

@ -37,7 +37,7 @@ public:
// adds tag for analyzer: // adds tag for analyzer:
std::ostringstream str; std::ostringstream str;
str << ";" << GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Height) << m_layer_height << "\n"; // don't rely on GCodeAnalyzer knowing the layer height - it knows nothing at priming str << ";" << GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Height) << m_layer_height << "\n"; // don't rely on GCodeAnalyzer knowing the layer height - it knows nothing at priming
str << ";" << GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Role) << ExtrusionEntity::role_to_string(erWipeTower) << "\n"; str << ";" << GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Role) << gcode_extrusion_role_to_string(erWipeTower) << "\n";
m_gcode += str.str(); m_gcode += str.str();
change_analyzer_line_width(line_width); change_analyzer_line_width(line_width);
} }

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 == erOverhangPerimeter && flow.bridge()) ? flow : flow.with_width(unscale<float>(w) + flow.height() * float(1. - 0.25 * PI)); const Flow new_flow = (role == ExtrusionRole::OverhangPerimeter && 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 role = ExtrusionRole::None;
ExtrusionLoopRole loop_role; ExtrusionLoopRole loop_role;
role = is_external ? erExternalPerimeter : erPerimeter; role = is_external ? ExtrusionRole::ExternalPerimeter : ExtrusionRole::Perimeter;
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.
@ -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),
erOverhangPerimeter, ExtrusionRole::OverhangPerimeter,
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());
@ -354,7 +354,7 @@ static ExtrusionEntityCollection traverse_loops_classic(const PerimeterGenerator
// Append thin walls to the nearest-neighbor search (only for first iteration) // Append thin walls to the nearest-neighbor search (only for first iteration)
if (! thin_walls.empty()) { if (! thin_walls.empty()) {
variable_width_classic(thin_walls, erExternalPerimeter, params.ext_perimeter_flow, coll.entities); variable_width_classic(thin_walls, ExtrusionRole::ExternalPerimeter, params.ext_perimeter_flow, coll.entities);
thin_walls.clear(); thin_walls.clear();
} }
@ -503,7 +503,7 @@ 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 ? erExternalPerimeter : erPerimeter; ExtrusionRole role = is_external ? ExtrusionRole::ExternalPerimeter : ExtrusionRole::Perimeter;
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));
@ -547,7 +547,7 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator::P
// 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), erOverhangPerimeter, extrusion_paths_append(paths, clip_extrusion(extrusion_path, lower_slices_paths, ClipperLib_Z::ctDifference), ExtrusionRole::OverhangPerimeter,
params.overhang_flow); params.overhang_flow);
// Reapply the nearest point search for starting point. // Reapply the nearest point search for starting point.
@ -568,7 +568,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() == erOverhangPerimeter) { if (path.role() == ExtrusionRole::OverhangPerimeter) {
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;
} }
@ -938,7 +938,7 @@ std::tuple<std::vector<ExtrusionPaths>, Polygons> generate_extra_perimeters_over
Polygons shrinked = offset(prev, -0.4 * overhang_flow.scaled_spacing()); Polygons shrinked = offset(prev, -0.4 * overhang_flow.scaled_spacing());
if (!shrinked.empty()) { if (!shrinked.empty()) {
overhang_region.emplace_back(); overhang_region.emplace_back();
extrusion_paths_append(overhang_region.back(), perimeter, erOverhangPerimeter, overhang_flow.mm3_per_mm(), extrusion_paths_append(overhang_region.back(), perimeter, ExtrusionRole::OverhangPerimeter, overhang_flow.mm3_per_mm(),
overhang_flow.width(), overhang_flow.height()); overhang_flow.width(), overhang_flow.height());
} }
@ -953,13 +953,13 @@ std::tuple<std::vector<ExtrusionPaths>, Polygons> generate_extra_perimeters_over
if (!fills.empty()) { if (!fills.empty()) {
fills = intersection_pl(fills, inset_overhang_area); fills = intersection_pl(fills, inset_overhang_area);
overhang_region.emplace_back(); overhang_region.emplace_back();
extrusion_paths_append(overhang_region.back(), fills, erOverhangPerimeter, overhang_flow.mm3_per_mm(), extrusion_paths_append(overhang_region.back(), fills, ExtrusionRole::OverhangPerimeter, overhang_flow.mm3_per_mm(),
overhang_flow.width(), overhang_flow.height()); overhang_flow.width(), overhang_flow.height());
} }
break; break;
} else { } else {
overhang_region.emplace_back(); overhang_region.emplace_back();
extrusion_paths_append(overhang_region.back(), perimeter, erOverhangPerimeter, overhang_flow.mm3_per_mm(), extrusion_paths_append(overhang_region.back(), perimeter, ExtrusionRole::OverhangPerimeter, overhang_flow.mm3_per_mm(),
overhang_flow.width(), overhang_flow.height()); overhang_flow.width(), overhang_flow.height());
} }
@ -981,7 +981,7 @@ std::tuple<std::vector<ExtrusionPaths>, Polygons> generate_extra_perimeters_over
} }
Polylines perimeter = intersection_pl(to_polylines(perimeter_polygon), shrinked_overhang_to_cover); Polylines perimeter = intersection_pl(to_polylines(perimeter_polygon), shrinked_overhang_to_cover);
overhang_region.emplace_back(); overhang_region.emplace_back();
extrusion_paths_append(overhang_region.back(), perimeter, erOverhangPerimeter, overhang_flow.mm3_per_mm(), extrusion_paths_append(overhang_region.back(), perimeter, ExtrusionRole::OverhangPerimeter, overhang_flow.mm3_per_mm(),
overhang_flow.width(), overhang_flow.height()); overhang_flow.width(), overhang_flow.height());
perimeter_polygon = expand(perimeter_polygon, 0.5 * overhang_flow.scaled_spacing()); perimeter_polygon = expand(perimeter_polygon, 0.5 * overhang_flow.scaled_spacing());
@ -1502,7 +1502,7 @@ void PerimeterGenerator::process_classic(
ex.medial_axis(min, max, &polylines); ex.medial_axis(min, max, &polylines);
if (! polylines.empty()) { if (! polylines.empty()) {
ExtrusionEntityCollection gap_fill; ExtrusionEntityCollection gap_fill;
variable_width_classic(polylines, erGapFill, params.solid_infill_flow, gap_fill.entities); variable_width_classic(polylines, ExtrusionRole::GapFill, params.solid_infill_flow, gap_fill.entities);
/* Make sure we don't infill narrow parts that are already gap-filled /* Make sure we don't infill narrow parts that are already gap-filled
(we only consider this surface's gaps to reduce the diff() complexity). (we only consider this surface's gaps to reduce the diff() complexity).
Growing actual extrusions ensures that gaps not filled by medial axis Growing actual extrusions ensures that gaps not filled by medial axis

View File

@ -1029,7 +1029,7 @@ void Print::_make_skirt()
ExtrusionLoop eloop(elrSkirt); ExtrusionLoop eloop(elrSkirt);
eloop.paths.emplace_back(ExtrusionPath( eloop.paths.emplace_back(ExtrusionPath(
ExtrusionPath( ExtrusionPath(
erSkirt, ExtrusionRole::Skirt,
(float)mm3_per_mm, // this will be overridden at G-code export time (float)mm3_per_mm, // this will be overridden at G-code export time
flow.width(), flow.width(),
(float)first_layer_height // this will be overridden at G-code export time (float)first_layer_height // this will be overridden at G-code export time

View File

@ -1178,7 +1178,7 @@ namespace SupportMaterialInternal {
static inline bool has_bridging_perimeters(const ExtrusionLoop &loop) static inline bool has_bridging_perimeters(const ExtrusionLoop &loop)
{ {
for (const ExtrusionPath &ep : loop.paths) for (const ExtrusionPath &ep : loop.paths)
if (ep.role() == erOverhangPerimeter && ! ep.polyline.empty()) if (ep.role() == ExtrusionRole::OverhangPerimeter && ! ep.polyline.empty())
return int(ep.size()) >= (ep.is_closed() ? 3 : 2); return int(ep.size()) >= (ep.is_closed() ? 3 : 2);
return false; return false;
} }
@ -1204,7 +1204,7 @@ namespace SupportMaterialInternal {
for (const ExtrusionEntity *ee2 : static_cast<const ExtrusionEntityCollection*>(ee)->entities) { for (const ExtrusionEntity *ee2 : static_cast<const ExtrusionEntityCollection*>(ee)->entities) {
assert(! ee2->is_collection()); assert(! ee2->is_collection());
assert(! ee2->is_loop()); assert(! ee2->is_loop());
if (ee2->role() == erBridgeInfill) if (ee2->role() == ExtrusionRole::BridgeInfill)
return true; return true;
} }
} }
@ -1225,7 +1225,7 @@ namespace SupportMaterialInternal {
{ {
assert(expansion_scaled >= 0.f); assert(expansion_scaled >= 0.f);
for (const ExtrusionPath &ep : loop.paths) for (const ExtrusionPath &ep : loop.paths)
if (ep.role() == erOverhangPerimeter && ! ep.polyline.empty()) { if (ep.role() == ExtrusionRole::OverhangPerimeter && ! ep.polyline.empty()) {
float exp = 0.5f * (float)scale_(ep.width) + expansion_scaled; float exp = 0.5f * (float)scale_(ep.width) + expansion_scaled;
if (ep.is_closed()) { if (ep.is_closed()) {
if (ep.size() >= 3) { if (ep.size() >= 3) {
@ -3357,7 +3357,7 @@ static inline void tree_supports_generate_paths(
ExPolygons level2 = offset2_ex({ expoly }, -1.5 * flow.scaled_width(), 0.5 * flow.scaled_width()); ExPolygons level2 = offset2_ex({ expoly }, -1.5 * flow.scaled_width(), 0.5 * flow.scaled_width());
if (level2.size() == 1) { if (level2.size() == 1) {
Polylines polylines; Polylines polylines;
extrusion_entities_append_paths(dst, draw_perimeters(expoly, clip_length), erSupportMaterial, flow.mm3_per_mm(), flow.width(), flow.height(), extrusion_entities_append_paths(dst, draw_perimeters(expoly, clip_length), ExtrusionRole::SupportMaterial, flow.mm3_per_mm(), flow.width(), flow.height(),
// Disable reversal of the path, always start with the anchor, always print CCW. // Disable reversal of the path, always start with the anchor, always print CCW.
false); false);
expoly = level2.front(); expoly = level2.front();
@ -3460,7 +3460,7 @@ static inline void tree_supports_generate_paths(
pl.reverse(); pl.reverse();
polylines.emplace_back(std::move(pl)); polylines.emplace_back(std::move(pl));
} }
extrusion_entities_append_paths(dst, polylines, erSupportMaterial, flow.mm3_per_mm(), flow.width(), flow.height(), extrusion_entities_append_paths(dst, polylines, ExtrusionRole::SupportMaterial, flow.mm3_per_mm(), flow.width(), flow.height(),
// Disable reversal of the path, always start with the anchor, always print CCW. // Disable reversal of the path, always start with the anchor, always print CCW.
false); false);
} }
@ -3505,7 +3505,7 @@ static inline void fill_expolygons_with_sheath_generate_paths(
eec->no_sort = true; eec->no_sort = true;
} }
ExtrusionEntitiesPtr &out = no_sort ? eec->entities : dst; ExtrusionEntitiesPtr &out = no_sort ? eec->entities : dst;
extrusion_entities_append_paths(out, draw_perimeters(expoly, clip_length), erSupportMaterial, flow.mm3_per_mm(), flow.width(), flow.height()); extrusion_entities_append_paths(out, draw_perimeters(expoly, clip_length), ExtrusionRole::SupportMaterial, flow.mm3_per_mm(), flow.width(), flow.height());
// Fill in the rest. // Fill in the rest.
fill_expolygons_generate_paths(out, offset_ex(expoly, float(-0.4 * spacing)), filler, fill_params, density, role, flow); fill_expolygons_generate_paths(out, offset_ex(expoly, float(-0.4 * spacing)), filler, fill_params, density, role, flow);
if (no_sort && ! eec->empty()) if (no_sort && ! eec->empty())
@ -3817,7 +3817,7 @@ void LoopInterfaceProcessor::generate(SupportGeneratorLayerExtruded &top_contact
extrusion_entities_append_paths( extrusion_entities_append_paths(
top_contact_layer.extrusions, top_contact_layer.extrusions,
std::move(loop_lines), std::move(loop_lines),
erSupportMaterialInterface, flow.mm3_per_mm(), flow.width(), flow.height()); ExtrusionRole::SupportMaterialInterface, flow.mm3_per_mm(), flow.width(), flow.height());
} }
#ifdef SLIC3R_DEBUG #ifdef SLIC3R_DEBUG
@ -4252,7 +4252,7 @@ void generate_support_toolpaths(
// Filler and its parameters // Filler and its parameters
filler, float(support_params.support_density), filler, float(support_params.support_density),
// Extrusion parameters // Extrusion parameters
erSupportMaterial, flow, ExtrusionRole::SupportMaterial, flow,
support_params.with_sheath, false); support_params.with_sheath, false);
} }
} }
@ -4284,7 +4284,7 @@ void generate_support_toolpaths(
// Filler and its parameters // Filler and its parameters
filler, density, filler, density,
// Extrusion parameters // Extrusion parameters
(support_layer_id < slicing_params.base_raft_layers) ? erSupportMaterial : erSupportMaterialInterface, flow, (support_layer_id < slicing_params.base_raft_layers) ? ExtrusionRole::SupportMaterial : ExtrusionRole::SupportMaterialInterface, flow,
// sheath at first layer // sheath at first layer
support_layer_id == 0, support_layer_id == 0); support_layer_id == 0, support_layer_id == 0);
} }
@ -4440,7 +4440,7 @@ void generate_support_toolpaths(
// Filler and its parameters // Filler and its parameters
filler_interface.get(), float(density), filler_interface.get(), float(density),
// Extrusion parameters // Extrusion parameters
erSupportMaterialInterface, interface_flow); ExtrusionRole::SupportMaterialInterface, interface_flow);
} }
// Base interface layers under soluble interfaces // Base interface layers under soluble interfaces
@ -4462,7 +4462,7 @@ void generate_support_toolpaths(
// Filler and its parameters // Filler and its parameters
filler, float(support_params.interface_density), filler, float(support_params.interface_density),
// Extrusion parameters // Extrusion parameters
erSupportMaterial, interface_flow); ExtrusionRole::SupportMaterial, interface_flow);
} }
// Base support or flange. // Base support or flange.
@ -4500,7 +4500,7 @@ void generate_support_toolpaths(
// Filler and its parameters // Filler and its parameters
filler, density, filler, density,
// Extrusion parameters // Extrusion parameters
erSupportMaterial, flow, ExtrusionRole::SupportMaterial, flow,
sheath, no_sort); sheath, no_sort);
} }

View File

@ -58,7 +58,7 @@ public:
bool is_external_perimeter() const bool is_external_perimeter() const
{ {
assert(origin_entity != nullptr); assert(origin_entity != nullptr);
return origin_entity->role() == erExternalPerimeter || origin_entity->role() == erOverhangPerimeter; return origin_entity->role() == ExtrusionRole::ExternalPerimeter || origin_entity->role() == ExtrusionRole::OverhangPerimeter;
} }
Vec2f a; Vec2f a;
@ -170,16 +170,15 @@ struct SliceConnection
float get_flow_width(const LayerRegion *region, ExtrusionRole role) float get_flow_width(const LayerRegion *region, ExtrusionRole role)
{ {
switch (role) { if (role == ExtrusionRole::BridgeInfill) return region->flow(FlowRole::frExternalPerimeter).width();
case ExtrusionRole::erBridgeInfill: return region->flow(FlowRole::frExternalPerimeter).width(); if (role == ExtrusionRole::ExternalPerimeter) return region->flow(FlowRole::frExternalPerimeter).width();
case ExtrusionRole::erExternalPerimeter: return region->flow(FlowRole::frExternalPerimeter).width(); if (role == ExtrusionRole::GapFill) return region->flow(FlowRole::frInfill).width();
case ExtrusionRole::erGapFill: return region->flow(FlowRole::frInfill).width(); if (role == ExtrusionRole::Perimeter) return region->flow(FlowRole::frPerimeter).width();
case ExtrusionRole::erPerimeter: return region->flow(FlowRole::frPerimeter).width(); if (role == ExtrusionRole::SolidInfill) return region->flow(FlowRole::frSolidInfill).width();
case ExtrusionRole::erSolidInfill: return region->flow(FlowRole::frSolidInfill).width(); if (role == ExtrusionRole::InternalInfill) return region->flow(FlowRole::frInfill).width();
case ExtrusionRole::erInternalInfill: return region->flow(FlowRole::frInfill).width(); if (role == ExtrusionRole::TopSolidInfill) return region->flow(FlowRole::frTopSolidInfill).width();
case ExtrusionRole::erTopSolidInfill: return region->flow(FlowRole::frTopSolidInfill).width(); // default
default: return region->flow(FlowRole::frPerimeter).width(); return region->flow(FlowRole::frPerimeter).width();
}
} }
std::vector<ExtrusionLine> to_short_lines(const ExtrusionEntity *e, float length_limit) std::vector<ExtrusionLine> to_short_lines(const ExtrusionEntity *e, float length_limit)
@ -800,7 +799,7 @@ SupportPoints check_stability(const PrintObject *po, const PrintTryCancel& cance
const LayerRegion *fill_region = layer->get_region(fill_range.region()); const LayerRegion *fill_region = layer->get_region(fill_range.region());
for (const auto &fill_idx : fill_range) { for (const auto &fill_idx : fill_range) {
const ExtrusionEntity *entity = fill_region->fills().entities[fill_idx]; const ExtrusionEntity *entity = fill_region->fills().entities[fill_idx];
if (entity->role() == erBridgeInfill) { if (entity->role() == ExtrusionRole::BridgeInfill) {
for (const ExtrusionLine &bridge : for (const ExtrusionLine &bridge :
check_extrusion_entity_stability(entity, fill_region, prev_layer_ext_perim_lines,prev_layer_boundary, params)) { check_extrusion_entity_stability(entity, fill_region, prev_layer_ext_perim_lines,prev_layer_boundary, params)) {
if (bridge.support_point_generated) { if (bridge.support_point_generated) {

View File

@ -40,13 +40,18 @@ public:
constexpr bool operator&(option_type t) { return m_bits & mask_value(t); } 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 has(option_type t) { 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; }
// For sorting by the enum values.
constexpr bool lower(const enum_bitmask r) const { return m_bits < r.m_bits; }
private: private:
underlying_type m_bits = 0; underlying_type m_bits = 0;
}; };
// For enabling free functions producing enum_bitmask<> type from bit operations on enums. // For enabling free functions producing enum_bitmask<> type from bit operations on enums.
template<typename Enum> struct is_enum_bitmask_type { static const bool enable = false; }; template<typename Enum> struct is_enum_bitmask_type { static constexpr const bool enable = false; };
#define ENABLE_ENUM_BITMASK_OPERATORS(x) template<> struct is_enum_bitmask_type<x> { static const bool enable = true; }; #define ENABLE_ENUM_BITMASK_OPERATORS(x) template<> struct is_enum_bitmask_type<x> { static constexpr const bool enable = true; };
template<class Enum> inline constexpr bool is_enum_bitmask_type_v = is_enum_bitmask_type<Enum>::enable; template<class Enum> inline constexpr bool is_enum_bitmask_type_v = is_enum_bitmask_type<Enum>::enable;
// Creates an enum_bitmask from two options, convenient for passing of options to a function: // Creates an enum_bitmask from two options, convenient for passing of options to a function:

View File

@ -899,7 +899,7 @@ void GCodeViewer::reset()
m_shells.volumes.clear(); m_shells.volumes.clear();
m_layers.reset(); m_layers.reset();
m_layers_z_range = { 0, 0 }; m_layers_z_range = { 0, 0 };
m_roles = std::vector<ExtrusionRole>(); m_roles = std::vector<GCodeExtrusionRole>();
m_print_statistics.reset(); m_print_statistics.reset();
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) { for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
m_layers_times[i] = std::vector<float>(); m_layers_times[i] = std::vector<float>();
@ -1607,8 +1607,7 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result)
curr.extrusion_role != erSupportMaterial && curr.extrusion_role != erSupportMaterial &&
curr.extrusion_role != erSupportMaterialInterface && curr.extrusion_role != erSupportMaterialInterface &&
curr.extrusion_role != erWipeTower && curr.extrusion_role != erWipeTower &&
curr.extrusion_role != erCustom && curr.extrusion_role != erCustom) {
curr.extrusion_role != erMixed) {
const Vec3d curr_pos = curr.position.cast<double>(); const Vec3d curr_pos = curr.position.cast<double>();
const Vec3d prev_pos = prev.position.cast<double>(); const Vec3d prev_pos = prev.position.cast<double>();
m_cog.add_segment(curr_pos, prev_pos, curr.mm3_per_mm * (curr_pos - prev_pos).norm()); m_cog.add_segment(curr_pos, prev_pos, curr.mm3_per_mm * (curr_pos - prev_pos).norm());
@ -3469,12 +3468,12 @@ void GCodeViewer::render_legend(float& legend_height)
return _u8L("from") + " " + std::string(buf1) + " " + _u8L("to") + " " + std::string(buf2) + " " + _u8L("mm"); return _u8L("from") + " " + std::string(buf1) + " " + _u8L("to") + " " + std::string(buf2) + " " + _u8L("mm");
}; };
auto role_time_and_percent = [time_mode](ExtrusionRole role) { auto role_time_and_percent = [time_mode](GCodeExtrusionRole role) {
auto it = std::find_if(time_mode.roles_times.begin(), time_mode.roles_times.end(), [role](const std::pair<ExtrusionRole, float>& item) { return role == item.first; }); auto it = std::find_if(time_mode.roles_times.begin(), time_mode.roles_times.end(), [role](const std::pair<GCodeExtrusionRole, float>& item) { return role == item.first; });
return (it != time_mode.roles_times.end()) ? std::make_pair(it->second, it->second / time_mode.time) : std::make_pair(0.0f, 0.0f); return (it != time_mode.roles_times.end()) ? std::make_pair(it->second, it->second / time_mode.time) : std::make_pair(0.0f, 0.0f);
}; };
auto used_filament_per_role = [this, imperial_units](ExtrusionRole role) { auto used_filament_per_role = [this, imperial_units](GCodeExtrusionRole role) {
auto it = m_print_statistics.used_filaments_per_role.find(role); auto it = m_print_statistics.used_filaments_per_role.find(role);
if (it == m_print_statistics.used_filaments_per_role.end()) if (it == m_print_statistics.used_filaments_per_role.end())
return std::make_pair(0.0, 0.0); return std::make_pair(0.0, 0.0);
@ -3494,10 +3493,10 @@ void GCodeViewer::render_legend(float& legend_height)
if (m_view_type == EViewType::FeatureType) { if (m_view_type == EViewType::FeatureType) {
// calculate offsets to align time/percentage data // calculate offsets to align time/percentage data
for (size_t i = 0; i < m_roles.size(); ++i) { for (GCodeExtrusionRole role : m_roles) {
ExtrusionRole role = m_roles[i]; assert(role < erCount);
if (role < erCount) { if (role < erCount) {
labels.push_back(_u8L(ExtrusionEntity::role_to_string(role))); labels.push_back(_u8L(gcode_extrusion_role_to_string(role)));
auto [time, percent] = role_time_and_percent(role); auto [time, percent] = role_time_and_percent(role);
times.push_back((time > 0.0f) ? short_time(get_time_dhms(time)) : ""); times.push_back((time > 0.0f) ? short_time(get_time_dhms(time)) : "");
percents.push_back(percent); percents.push_back(percent);
@ -3610,7 +3609,7 @@ void GCodeViewer::render_legend(float& legend_height)
max_time_percent = std::max(max_time_percent, time_mode.travel_time / time_mode.time); max_time_percent = std::max(max_time_percent, time_mode.travel_time / time_mode.time);
for (size_t i = 0; i < m_roles.size(); ++i) { for (size_t i = 0; i < m_roles.size(); ++i) {
ExtrusionRole role = m_roles[i]; GCodeExtrusionRole role = m_roles[i];
if (role >= erCount) if (role >= erCount)
continue; continue;
const bool visible = is_visible(role); const bool visible = is_visible(role);

View File

@ -208,7 +208,7 @@ class GCodeViewer
}; };
EMoveType type{ EMoveType::Noop }; EMoveType type{ EMoveType::Noop };
ExtrusionRole role{ erNone }; GCodeExtrusionRole role{ erNone };
float delta_extruder{ 0.0f }; float delta_extruder{ 0.0f };
float height{ 0.0f }; float height{ 0.0f };
float width{ 0.0f }; float width{ 0.0f };
@ -753,7 +753,7 @@ private:
std::vector<ColorRGBA> m_tool_colors; std::vector<ColorRGBA> m_tool_colors;
Layers m_layers; Layers m_layers;
std::array<unsigned int, 2> m_layers_z_range; std::array<unsigned int, 2> m_layers_z_range;
std::vector<ExtrusionRole> m_roles; std::vector<GCodeExtrusionRole> m_roles;
size_t m_extruders_count; size_t m_extruders_count;
std::vector<unsigned char> m_extruder_ids; std::vector<unsigned char> m_extruder_ids;
std::vector<float> m_filament_diameters; std::vector<float> m_filament_diameters;
@ -849,7 +849,7 @@ private:
#if ENABLE_GCODE_VIEWER_STATISTICS #if ENABLE_GCODE_VIEWER_STATISTICS
void render_statistics(); void render_statistics();
#endif // ENABLE_GCODE_VIEWER_STATISTICS #endif // ENABLE_GCODE_VIEWER_STATISTICS
bool is_visible(ExtrusionRole role) const { bool is_visible(GCodeExtrusionRole role) const {
return role < erCount && (m_extrusions.role_visibility_flags & (1 << role)) != 0; return role < erCount && (m_extrusions.role_visibility_flags & (1 << role)) != 0;
} }
bool is_visible(const Path& path) const { return is_visible(path.role); } bool is_visible(const Path& path) const { return is_visible(path.role); }

View File

@ -6567,7 +6567,7 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c
if (support_layer) { if (support_layer) {
for (const ExtrusionEntity *extrusion_entity : support_layer->support_fills.entities) for (const ExtrusionEntity *extrusion_entity : support_layer->support_fills.entities)
_3DScene::extrusionentity_to_verts(extrusion_entity, float(layer->print_z), copy, _3DScene::extrusionentity_to_verts(extrusion_entity, float(layer->print_z), copy,
select_geometry(idx_layer, (extrusion_entity->role() == erSupportMaterial) ? select_geometry(idx_layer, (extrusion_entity->role() == ExtrusionRole::SupportMaterial) ?
support_layer->object()->config().support_material_extruder : support_layer->object()->config().support_material_extruder :
support_layer->object()->config().support_material_interface_extruder, 2)); support_layer->object()->config().support_material_interface_extruder, 2));
} }

View File

@ -21,7 +21,7 @@ static inline Slic3r::Point random_point(float LO=-50, float HI=50)
// build a sample extrusion entity collection with random start and end points. // build a sample extrusion entity collection with random start and end points.
static Slic3r::ExtrusionPath random_path(size_t length = 20, float LO = -50, float HI = 50) static Slic3r::ExtrusionPath random_path(size_t length = 20, float LO = -50, float HI = 50)
{ {
ExtrusionPath t {erPerimeter, 1.0, 1.0, 1.0}; ExtrusionPath t { ExtrusionRole::Perimeter, 1.0, 1.0, 1.0 };
for (size_t j = 0; j < length; ++ j) for (size_t j = 0; j < length; ++ j)
t.polyline.append(random_point(LO, HI)); t.polyline.append(random_point(LO, HI));
return t; return t;
@ -37,7 +37,7 @@ static Slic3r::ExtrusionPaths random_paths(size_t count = 10, size_t length = 20
SCENARIO("ExtrusionPath", "[ExtrusionEntity]") { SCENARIO("ExtrusionPath", "[ExtrusionEntity]") {
GIVEN("Simple path") { GIVEN("Simple path") {
Slic3r::ExtrusionPath path{ erExternalPerimeter }; Slic3r::ExtrusionPath path{ ExtrusionRole::ExternalPerimeter };
path.polyline = { { 100, 100 }, { 200, 100 }, { 200, 200 } }; path.polyline = { { 100, 100 }, { 200, 100 }, { 200, 200 } };
path.mm3_per_mm = 1.; path.mm3_per_mm = 1.;
THEN("first point") { THEN("first point") {
@ -64,7 +64,7 @@ SCENARIO("ExtrusionLoop", "[ExtrusionEntity]")
Polygon square { { 100, 100 }, { 200, 100 }, { 200, 200 }, { 100, 200 } }; Polygon square { { 100, 100 }, { 200, 100 }, { 200, 200 }, { 100, 200 } };
ExtrusionLoop loop; ExtrusionLoop loop;
loop.paths.emplace_back(new_extrusion_path(square.split_at_first_point(), erExternalPerimeter, 1.)); loop.paths.emplace_back(new_extrusion_path(square.split_at_first_point(), ExtrusionRole::ExternalPerimeter, 1.));
THEN("polygon area") { THEN("polygon area") {
REQUIRE(loop.polygon().area() == Approx(square.area())); REQUIRE(loop.polygon().area() == Approx(square.area()));
} }
@ -81,7 +81,7 @@ SCENARIO("ExtrusionLoop", "[ExtrusionEntity]")
REQUIRE(loop2->paths.size() == 1); REQUIRE(loop2->paths.size() == 1);
} }
THEN("cloned role") { THEN("cloned role") {
REQUIRE(loop2->paths.front().role() == erExternalPerimeter); REQUIRE(loop2->paths.front().role() == ExtrusionRole::ExternalPerimeter);
} }
} }
WHEN("cloned and split") { WHEN("cloned and split") {
@ -107,8 +107,8 @@ SCENARIO("ExtrusionLoop", "[ExtrusionEntity]")
Polyline polyline1 { { 100, 100 }, { 200, 100 }, { 200, 200 } }; Polyline polyline1 { { 100, 100 }, { 200, 100 }, { 200, 200 } };
Polyline polyline2 { { 200, 200 }, { 100, 200 }, { 100, 100 } }; Polyline polyline2 { { 200, 200 }, { 100, 200 }, { 100, 100 } };
ExtrusionLoop loop; ExtrusionLoop loop;
loop.paths.emplace_back(new_extrusion_path(polyline1, erExternalPerimeter, 1.)); loop.paths.emplace_back(new_extrusion_path(polyline1, ExtrusionRole::ExternalPerimeter, 1.));
loop.paths.emplace_back(new_extrusion_path(polyline2, erOverhangPerimeter, 1.)); loop.paths.emplace_back(new_extrusion_path(polyline2, ExtrusionRole::OverhangPerimeter, 1.));
double tot_len = polyline1.length() + polyline2.length(); double tot_len = polyline1.length() + polyline2.length();
THEN("length") { THEN("length") {
@ -135,9 +135,9 @@ SCENARIO("ExtrusionLoop", "[ExtrusionEntity]")
REQUIRE(loop2->paths[1].polyline.back() == loop2->paths[2].polyline.front()); REQUIRE(loop2->paths[1].polyline.back() == loop2->paths[2].polyline.front());
} }
THEN("expected order after splitting") { THEN("expected order after splitting") {
REQUIRE(loop2->paths.front().role() == erExternalPerimeter); REQUIRE(loop2->paths.front().role() == ExtrusionRole::ExternalPerimeter);
REQUIRE(loop2->paths[1].role() == erOverhangPerimeter); REQUIRE(loop2->paths[1].role() == ExtrusionRole::OverhangPerimeter);
REQUIRE(loop2->paths[2].role() == erExternalPerimeter); REQUIRE(loop2->paths[2].role() == ExtrusionRole::ExternalPerimeter);
} }
THEN("path has correct number of points") { THEN("path has correct number of points") {
REQUIRE(loop2->paths.front().polyline.size() == 2); REQUIRE(loop2->paths.front().polyline.size() == 2);
@ -175,8 +175,8 @@ SCENARIO("ExtrusionLoop", "[ExtrusionEntity]")
REQUIRE(loop2->paths[1].polyline.back() == loop2->paths.front().polyline.front()); REQUIRE(loop2->paths[1].polyline.back() == loop2->paths.front().polyline.front());
} }
THEN("expected order after splitting") { THEN("expected order after splitting") {
REQUIRE(loop2->paths.front().role() == erOverhangPerimeter); REQUIRE(loop2->paths.front().role() == ExtrusionRole::OverhangPerimeter);
REQUIRE(loop2->paths[1].role() == erExternalPerimeter); REQUIRE(loop2->paths[1].role() == ExtrusionRole::ExternalPerimeter);
} }
THEN("path has correct number of points") { THEN("path has correct number of points") {
REQUIRE(loop2->paths.front().polyline.size() == 3); REQUIRE(loop2->paths.front().polyline.size() == 3);
@ -207,10 +207,10 @@ SCENARIO("ExtrusionLoop", "[ExtrusionEntity]")
Polyline polyline3 { { 9829401, 9321068 }, { 4821067, 9321068 }, { 4821067, 4821067 }, { 9829401, 4821067 } }; Polyline polyline3 { { 9829401, 9321068 }, { 4821067, 9321068 }, { 4821067, 4821067 }, { 9829401, 4821067 } };
Polyline polyline4 { { 9829401, 4821067 }, { 59312736,4821067 } }; Polyline polyline4 { { 9829401, 4821067 }, { 59312736,4821067 } };
ExtrusionLoop loop; ExtrusionLoop loop;
loop.paths.emplace_back(new_extrusion_path(polyline1, erExternalPerimeter, 1.)); loop.paths.emplace_back(new_extrusion_path(polyline1, ExtrusionRole::ExternalPerimeter, 1.));
loop.paths.emplace_back(new_extrusion_path(polyline2, erOverhangPerimeter, 1.)); loop.paths.emplace_back(new_extrusion_path(polyline2, ExtrusionRole::OverhangPerimeter, 1.));
loop.paths.emplace_back(new_extrusion_path(polyline3, erExternalPerimeter, 1.)); loop.paths.emplace_back(new_extrusion_path(polyline3, ExtrusionRole::ExternalPerimeter, 1.));
loop.paths.emplace_back(new_extrusion_path(polyline4, erOverhangPerimeter, 1.)); loop.paths.emplace_back(new_extrusion_path(polyline4, ExtrusionRole::OverhangPerimeter, 1.));
double len = loop.length(); double len = loop.length();
WHEN("splitting at vertex") { WHEN("splitting at vertex") {
Point point(4821067, 9321068); Point point(4821067, 9321068);
@ -220,10 +220,10 @@ SCENARIO("ExtrusionLoop", "[ExtrusionEntity]")
REQUIRE(loop.length() == Approx(len)); REQUIRE(loop.length() == Approx(len));
} }
THEN("order is correctly preserved after splitting") { THEN("order is correctly preserved after splitting") {
REQUIRE(loop.paths.front().role() == erExternalPerimeter); REQUIRE(loop.paths.front().role() == ExtrusionRole::ExternalPerimeter);
REQUIRE(loop.paths[1].role() == erOverhangPerimeter); REQUIRE(loop.paths[1].role() == ExtrusionRole::OverhangPerimeter);
REQUIRE(loop.paths[2].role() == erExternalPerimeter); REQUIRE(loop.paths[2].role() == ExtrusionRole::ExternalPerimeter);
REQUIRE(loop.paths[3].role() == erOverhangPerimeter); REQUIRE(loop.paths[3].role() == ExtrusionRole::OverhangPerimeter);
} }
} }
} }
@ -233,7 +233,7 @@ SCENARIO("ExtrusionLoop", "[ExtrusionEntity]")
loop.paths.emplace_back(new_extrusion_path( loop.paths.emplace_back(new_extrusion_path(
Polyline { { 15896783, 15868739 }, { 24842049, 12117558 }, { 33853238, 15801279 }, { 37591780, 24780128 }, { 37591780, 24844970 }, Polyline { { 15896783, 15868739 }, { 24842049, 12117558 }, { 33853238, 15801279 }, { 37591780, 24780128 }, { 37591780, 24844970 },
{ 33853231, 33825297 }, { 24842049, 37509013 }, { 15896798, 33757841 }, { 12211841, 24812544 }, { 15896783, 15868739 } }, { 33853231, 33825297 }, { 24842049, 37509013 }, { 15896798, 33757841 }, { 12211841, 24812544 }, { 15896783, 15868739 } },
erExternalPerimeter, 1.)); ExtrusionRole::ExternalPerimeter, 1.));
double len = loop.length(); double len = loop.length();
THEN("split_at() preserves total length") { THEN("split_at() preserves total length") {
loop.split_at({ 15896783, 15868739 }, false, 0); loop.split_at({ 15896783, 15868739 }, false, 0);
@ -245,9 +245,9 @@ SCENARIO("ExtrusionLoop", "[ExtrusionEntity]")
SCENARIO("ExtrusionEntityCollection: Basics", "[ExtrusionEntity]") SCENARIO("ExtrusionEntityCollection: Basics", "[ExtrusionEntity]")
{ {
Polyline polyline { { 100, 100 }, { 200, 100 }, { 200, 200 } }; Polyline polyline { { 100, 100 }, { 200, 100 }, { 200, 200 } };
ExtrusionPath path = new_extrusion_path(polyline, erExternalPerimeter, 1.); ExtrusionPath path = new_extrusion_path(polyline, ExtrusionRole::ExternalPerimeter, 1.);
ExtrusionLoop loop; ExtrusionLoop loop;
loop.paths.emplace_back(new_extrusion_path(Polygon(polyline.points).split_at_first_point(), erInternalInfill, 1.)); loop.paths.emplace_back(new_extrusion_path(Polygon(polyline.points).split_at_first_point(), ExtrusionRole::InternalInfill, 1.));
ExtrusionEntityCollection collection; ExtrusionEntityCollection collection;
collection.append(path); collection.append(path);
THEN("no_sort is false by default") { THEN("no_sort is false by default") {
@ -378,7 +378,7 @@ TEST_CASE("ExtrusionEntityCollection: Chained path", "[ExtrusionEntity]") {
REQUIRE(chained == test.chained); REQUIRE(chained == test.chained);
ExtrusionEntityCollection unchained_extrusions; ExtrusionEntityCollection unchained_extrusions;
extrusion_entities_append_paths(unchained_extrusions.entities, test.unchained, extrusion_entities_append_paths(unchained_extrusions.entities, test.unchained,
erInternalInfill, 0., 0.4f, 0.3f); ExtrusionRole::InternalInfill, 0., 0.4f, 0.3f);
THEN("Chaining works") { THEN("Chaining works") {
ExtrusionEntityCollection chained_extrusions = unchained_extrusions.chained_path_from(test.initial_point); ExtrusionEntityCollection chained_extrusions = unchained_extrusions.chained_path_from(test.initial_point);
REQUIRE(chained_extrusions.entities.size() == test.chained.size()); REQUIRE(chained_extrusions.entities.size() == test.chained.size());

View File

@ -80,13 +80,13 @@ SCENARIO("Perimeter nesting", "[Perimeters]")
} }
THEN("expected number of external loops") { THEN("expected number of external loops") {
size_t num_external = std::count_if(loops.entities.begin(), loops.entities.end(), size_t num_external = std::count_if(loops.entities.begin(), loops.entities.end(),
[](const ExtrusionEntity *ee){ return ee->role() == erExternalPerimeter; }); [](const ExtrusionEntity *ee){ return ee->role() == ExtrusionRole::ExternalPerimeter; });
REQUIRE(num_external == data.external); REQUIRE(num_external == data.external);
} }
THEN("expected external order") { THEN("expected external order") {
std::vector<bool> ext_order; std::vector<bool> ext_order;
for (auto *ee : loops.entities) for (auto *ee : loops.entities)
ext_order.emplace_back(ee->role() == erExternalPerimeter); ext_order.emplace_back(ee->role() == ExtrusionRole::ExternalPerimeter);
REQUIRE(ext_order == data.ext_order); REQUIRE(ext_order == data.ext_order);
} }
THEN("expected number of internal contour loops") { THEN("expected number of internal contour loops") {