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);
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()));
}
@ -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()) {
auto *loop = new ExtrusionLoop();
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.reserve(first_path.size());
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;
this_loop_trimmed.entities.reserve(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;
Points &points = dynamic_cast<ExtrusionPath*>(this_loop_trimmed.entities.back())->polyline.points;
points.reserve(path.size());
@ -699,7 +699,7 @@ ExtrusionEntityCollection make_brim(const Print &print, PrintTryCancel try_cance
}
}
} 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);

View File

@ -322,8 +322,29 @@ double ExtrusionLoop::min_mm3_per_mm() const
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) {
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 erWipeTower : return L("Wipe tower");
case erCustom : return L("Custom");
case erMixed : return L("Mixed");
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"))
return erPerimeter;
@ -377,8 +397,6 @@ ExtrusionRole ExtrusionEntity::string_to_role(const std::string_view role)
return erWipeTower;
else if (role == L("Custom"))
return erCustom;
else if (role == L("Mixed"))
return erMixed;
else
return erNone;
}

View File

@ -4,6 +4,7 @@
#include "libslic3r.h"
#include "Polygon.hpp"
#include "Polyline.hpp"
#include "enum_bitmask.hpp"
#include <assert.h>
#include <string_view>
@ -16,8 +17,113 @@ using ExPolygons = std::vector<ExPolygon>;
class ExtrusionEntityCollection;
class Extruder;
// Each ExtrusionRole value identifies a distinct set of { extruder, speed }
enum ExtrusionRole : uint8_t {
enum class ExtrusionRoleModifier : uint16_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,
erPerimeter,
erExternalPerimeter,
@ -32,49 +138,12 @@ enum ExtrusionRole : uint8_t {
erSupportMaterial,
erSupportMaterialInterface,
erWipeTower,
// Custom (user defined) G-code block, for example start / end G-code.
erCustom,
// Extrusion role for a collection with multiple extrusion roles.
erMixed,
// Stopper to count number of enums.
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
{
public:
@ -108,11 +177,15 @@ public:
virtual Polylines as_polylines() const { Polylines dst; this->collect_polylines(dst); return dst; }
virtual double length() 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;
class ExtrusionPath : public ExtrusionEntity
@ -217,7 +290,7 @@ public:
size_t size() const { return this->paths.size(); }
bool empty() const { return this->paths.empty(); }
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.
// 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;
@ -279,7 +352,7 @@ public:
// 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.
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; }
// 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.
@ -304,8 +377,6 @@ public:
}
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
bool validate() const {
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)
{
if (role != erMixed) {
if (role != ExtrusionRole::Mixed) {
auto first = extrusion_entities.begin();
auto last = extrusion_entities.end();
extrusion_entities.erase(

View File

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

View File

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

View File

@ -148,7 +148,7 @@ namespace Slic3r {
int
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().temperature.get_at(gcodegen.writer().extruder()->id());
}
@ -244,7 +244,7 @@ namespace Slic3r {
gcodegen.m_avoid_crossing_perimeters.use_external_mp_once();
gcode += gcodegen.travel_to(
wipe_tower_point_to_object_point(gcodegen, start_pos),
erMixed,
ExtrusionRole::Mixed,
"Travel to a Wipe Tower");
gcode += gcodegen.unretract();
}
@ -864,7 +864,7 @@ namespace DoExport {
auto min_mm3_per_mm_no_ironing = [](const ExtrusionEntityCollection& eec) -> double {
double min = std::numeric_limits<double>::max();
for (const ExtrusionEntity* ee : eec.entities)
if (ee->role() != erIroning)
if (ee->role() != ExtrusionRole::Ironing)
min = std::min(min, ee->min_mm3_per_mm());
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);
// 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
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_avoid_crossing_perimeters.use_external_mp_once();
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;
// Disable motion planner when traveling to first object point.
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));
// 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.
{
@ -2305,8 +2305,8 @@ void GCode::process_layer_single_object(
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()) {
ExtrusionRole role = support_layer.support_fills.role();
bool has_support = role == erMixed || role == erSupportMaterial;
bool has_interface = role == erMixed || role == erSupportMaterialInterface;
bool has_support = role == ExtrusionRole::Mixed || role == ExtrusionRole::SupportMaterial;
bool has_interface = role == ExtrusionRole::Mixed || role == ExtrusionRole::SupportMaterialInterface;
// Extruder ID of the support base. -1 if "don't care".
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?
@ -2340,8 +2340,8 @@ void GCode::process_layer_single_object(
m_layer = layer_to_print.support_layer;
m_object_layer_over_raft = false;
gcode += this->extrude_support(
// support_extrusion_role is erSupportMaterial, erSupportMaterialInterface or erMixed for all extrusion paths.
support_layer.support_fills.chained_path_from(m_last_pos, has_support ? (has_interface ? erMixed : erSupportMaterial) : erSupportMaterialInterface));
// 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 ? ExtrusionRole::Mixed : ExtrusionRole::SupportMaterial) : ExtrusionRole::SupportMaterialInterface));
}
}
@ -2385,7 +2385,7 @@ void GCode::process_layer_single_object(
for (uint32_t fill_id : *it_fill_range) {
assert(dynamic_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())
// Flatten the infill collection for better path planning.
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
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
// 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.
@ -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);
for (const ExtrusionEntity *ee : support_fills.entities) {
ExtrusionRole role = ee->role();
assert(role == erSupportMaterial || role == erSupportMaterialInterface);
const auto label = (role == erSupportMaterial) ? support_label : support_interface_label;
const double speed = (role == erSupportMaterial) ? support_speed : support_interface_speed;
assert(role == ExtrusionRole::SupportMaterial || role == ExtrusionRole::SupportMaterialInterface);
const auto label = (role == ExtrusionRole::SupportMaterial) ? support_label : support_interface_label;
const double speed = (role == ExtrusionRole::SupportMaterial) ? support_speed : support_interface_speed;
const ExtrusionPath *path = dynamic_cast<const ExtrusionPath*>(ee);
if (path)
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
if (speed == -1) {
if (path.role() == erPerimeter) {
if (path.role() == ExtrusionRole::Perimeter) {
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");
} 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");
} else if (path.role() == erInternalInfill) {
} else if (path.role() == ExtrusionRole::InternalInfill) {
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");
} else if (path.role() == erTopSolidInfill) {
} else if (path.role() == ExtrusionRole::TopSolidInfill) {
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");
} else if (path.role() == erGapFill) {
} else if (path.role() == ExtrusionRole::GapFill) {
speed = m_config.get_abs_value("gap_fill_speed");
} else {
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
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)
{
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);
assert(is_decimal_separator_point());
if (path.role() != m_last_processor_extrusion_role) {
m_last_processor_extrusion_role = path.role();
if (GCodeExtrusionRole role = extrusion_role_to_gcode_extrusion_role(path.role()); role != m_last_processor_extrusion_role) {
m_last_processor_extrusion_role = role;
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;
}
@ -2979,7 +2979,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, const std::string_view de
gcode += ";_BRIDGE_FAN_START\n";
else
comment = ";_EXTRUDE_SET_SPEED";
if (path.role() == erExternalPerimeter)
if (path.role() == ExtrusionRole::ExternalPerimeter)
comment += ";_EXTERNAL_PERIMETER";
}
@ -3112,7 +3112,7 @@ bool GCode::needs_retraction(const Polyline &travel, ExtrusionRole role)
return false;
}
if (role == erSupportMaterial)
if (role == ExtrusionRole::SupportMaterial)
if (const SupportLayer *support_layer = dynamic_cast<const SupportLayer*>(m_layer);
support_layer != nullptr && ! support_layer->support_islands_bboxes.empty()) {
BoundingBox bbox_travel = get_extents(travel);

View File

@ -326,7 +326,7 @@ private:
std::string extrude_support(const ExtrusionEntityCollection &support_fills);
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 unretract() { return m_writer.unlift() + m_writer.unretract(); }
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.
bool m_enable_extrusion_role_markers;
// 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?
// change_layer() will update the progress bar.
unsigned int m_layer_count;
@ -376,7 +376,7 @@ private:
bool m_object_layer_over_raft;
double m_volumetric_speed;
// 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
float m_last_height{ 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.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()) {
filaments_per_role[active_role].first += filament.first;
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;
}
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) {
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];
if (time > 0.0f)
ret.push_back({ static_cast<ExtrusionRole>(i), time });
ret.push_back({ static_cast<GCodeExtrusionRole>(i), time });
}
}
return ret;
@ -1645,7 +1645,7 @@ void GCodeProcessor::process_tags(const std::string_view comment, bool producers
// extrusion role tag
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)
m_seams_detector.activate(true);
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_extrusion_role = role;

View File

@ -47,7 +47,7 @@ namespace Slic3r {
float travel_time;
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<ExtrusionRole, float>> roles_times;
std::vector<std::pair<GCodeExtrusionRole, float>> roles_times;
std::vector<float> layers_times;
void reset() {
@ -62,7 +62,7 @@ namespace Slic3r {
std::vector<double> volumes_per_color_change;
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::array<Mode, static_cast<size_t>(ETimeMode::Count)> modes;
@ -99,7 +99,7 @@ namespace Slic3r {
{
unsigned int gcode_id{ 0 };
EMoveType type{ EMoveType::Noop };
ExtrusionRole extrusion_role{ erNone };
GCodeExtrusionRole extrusion_role{ erNone };
unsigned char extruder_id{ 0 };
unsigned char cp_color_id{ 0 };
Vec3f position{ Vec3f::Zero() }; // mm
@ -238,7 +238,7 @@ namespace Slic3r {
};
EMoveType move_type{ EMoveType::Noop };
ExtrusionRole role{ erNone };
GCodeExtrusionRole role{ erNone };
unsigned int g1_line_id{ 0 };
unsigned int layer_id{ 0 };
float distance{ 0.0f }; // mm
@ -310,7 +310,7 @@ namespace Slic3r {
std::vector<TimeBlock> blocks;
std::vector<G1LinesCacheItem> g1_times_cache;
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;
void reset();
@ -360,7 +360,7 @@ namespace Slic3r {
std::map<size_t, double> volumes_per_extruder;
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();
@ -441,7 +441,7 @@ namespace Slic3r {
{
float value;
float tag_value;
ExtrusionRole role;
GCodeExtrusionRole role;
};
std::string type;
@ -454,7 +454,7 @@ namespace Slic3r {
: type(type), threshold(threshold)
{}
void update(float value, ExtrusionRole role) {
void update(float value, GCodeExtrusionRole role) {
if (role != erCustom) {
++count;
if (last_tag_value != 0.0f) {
@ -539,7 +539,7 @@ namespace Slic3r {
float m_mm3_per_mm;
float m_fan_speed; // percentage
float m_z_offset; // mm
ExtrusionRole m_extrusion_role;
GCodeExtrusionRole m_extrusion_role;
unsigned char m_extruder_id;
ExtruderColors m_extruder_colors;
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<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;
private:
@ -757,7 +757,7 @@ namespace Slic3r {
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_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.
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].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) {
line += EXTRUSION_ROLE_TAG.length();
int role = atoi(line);
m_current_extrusion_role = ExtrusionRole(role);
m_current_extrusion_role = GCodeExtrusionRole(role);
#ifdef PRESSURE_EQUALIZER_DEBUG
++line_idx;
#endif
@ -542,7 +542,7 @@ void PressureEqualizer::adjust_volumetric_rate()
for (size_t iRole = 1; iRole < erCount; ++ iRole) {
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())
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];
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) {
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())
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];
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
float m_current_pos[5];
size_t m_current_extruder;
ExtrusionRole m_current_extrusion_role;
GCodeExtrusionRole m_current_extrusion_role;
bool m_retracted;
bool m_use_relative_e_distances;
@ -149,7 +149,7 @@ private:
// Index of the active extruder.
size_t extruder_id;
// Extrusion role of this segment.
ExtrusionRole extrusion_role;
GCodeExtrusionRole extrusion_role;
// Current 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();
if (perimeter->is_loop()) {
for (const ExtrusionPath &path : static_cast<const ExtrusionLoop*>(perimeter)->paths) {
if (path.role() == ExtrusionRole::erExternalPerimeter) {
role = ExtrusionRole::erExternalPerimeter;
if (path.role() == ExtrusionRole::ExternalPerimeter) {
role = ExtrusionRole::ExternalPerimeter;
}
}
}
if (role == ExtrusionRole::erExternalPerimeter) {
if (role == ExtrusionRole::ExternalPerimeter) {
Points p;
perimeter->collect_points(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());
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];
ExtrusionLoop::ClosestPathPoint projected_point = loop.get_closest_path_and_point(seam_point, false);
// 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)
return true;
if (!region.config().wipe_into_infill || eec.role() != erInternalInfill)
if (!region.config().wipe_into_infill || eec.role() != ExtrusionRole::InternalInfill)
return false;
return true;
@ -210,8 +210,8 @@ void ToolOrdering::collect_extruders(const PrintObject &object, const std::vecto
for (auto support_layer : object.support_layers()) {
LayerTools &layer_tools = this->tools_for_layer(support_layer->print_z);
ExtrusionRole role = support_layer->support_fills.role();
bool has_support = role == erMixed || role == erSupportMaterial;
bool has_interface = role == erMixed || role == erSupportMaterialInterface;
bool has_support = role == ExtrusionRole::Mixed || role == ExtrusionRole::SupportMaterial;
bool has_interface = role == ExtrusionRole::Mixed || role == ExtrusionRole::SupportMaterialInterface;
unsigned int extruder_support = object.config().support_material_extruder.value;
unsigned int extruder_interface = object.config().support_material_interface_extruder.value;
if (has_support)
@ -266,10 +266,10 @@ void ToolOrdering::collect_extruders(const PrintObject &object, const std::vecto
for (const ExtrusionEntity *ee : layerm->fills()) {
// fill represents infill extrusions of a single island.
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))
has_solid_infill = true;
else if (role != erNone)
else if (role != ExtrusionRole::None)
has_infill = true;
if (m_print_config_ptr) {

View File

@ -37,7 +37,7 @@ public:
// adds tag for analyzer:
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::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();
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 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()) {
path.polyline.append(line.a);
path.polyline.append(line.b);
@ -292,9 +292,9 @@ static ExtrusionEntityCollection traverse_loops_classic(const PerimeterGenerator
for (const PerimeterGeneratorLoop &loop : loops) {
bool is_external = loop.is_external();
ExtrusionRole role;
ExtrusionRole role = ExtrusionRole::None;
ExtrusionLoopRole loop_role;
role = is_external ? erExternalPerimeter : erPerimeter;
role = is_external ? ExtrusionRole::ExternalPerimeter : ExtrusionRole::Perimeter;
if (loop.is_internal_contour()) {
// Note that we set loop role to ContourInternalPerimeter
// also when loop is both internal and external (i.e.
@ -332,7 +332,7 @@ static ExtrusionEntityCollection traverse_loops_classic(const PerimeterGenerator
extrusion_paths_append(
paths,
diff_pl({ polygon }, lower_slices_polygons_clipped),
erOverhangPerimeter,
ExtrusionRole::OverhangPerimeter,
params.mm3_per_mm_overhang,
params.overhang_flow.width(),
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)
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();
}
@ -503,7 +503,7 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator::P
continue;
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)
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
// outside the grown lower slices (thus where the distance between
// 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);
// Reapply the nearest point search for starting point.
@ -568,7 +568,7 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator::P
for (const ExtrusionPath &path : paths) {
++point_occurrence[path.polyline.first_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.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());
if (!shrinked.empty()) {
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());
}
@ -953,13 +953,13 @@ std::tuple<std::vector<ExtrusionPaths>, Polygons> generate_extra_perimeters_over
if (!fills.empty()) {
fills = intersection_pl(fills, inset_overhang_area);
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());
}
break;
} else {
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());
}
@ -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);
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());
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);
if (! polylines.empty()) {
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
(we only consider this surface's gaps to reduce the diff() complexity).
Growing actual extrusions ensures that gaps not filled by medial axis

View File

@ -1029,7 +1029,7 @@ void Print::_make_skirt()
ExtrusionLoop eloop(elrSkirt);
eloop.paths.emplace_back(ExtrusionPath(
ExtrusionPath(
erSkirt,
ExtrusionRole::Skirt,
(float)mm3_per_mm, // this will be overridden at G-code export time
flow.width(),
(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)
{
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 false;
}
@ -1204,7 +1204,7 @@ namespace SupportMaterialInternal {
for (const ExtrusionEntity *ee2 : static_cast<const ExtrusionEntityCollection*>(ee)->entities) {
assert(! ee2->is_collection());
assert(! ee2->is_loop());
if (ee2->role() == erBridgeInfill)
if (ee2->role() == ExtrusionRole::BridgeInfill)
return true;
}
}
@ -1225,7 +1225,7 @@ namespace SupportMaterialInternal {
{
assert(expansion_scaled >= 0.f);
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;
if (ep.is_closed()) {
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());
if (level2.size() == 1) {
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.
false);
expoly = level2.front();
@ -3460,7 +3460,7 @@ static inline void tree_supports_generate_paths(
pl.reverse();
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.
false);
}
@ -3505,7 +3505,7 @@ static inline void fill_expolygons_with_sheath_generate_paths(
eec->no_sort = true;
}
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_expolygons_generate_paths(out, offset_ex(expoly, float(-0.4 * spacing)), filler, fill_params, density, role, flow);
if (no_sort && ! eec->empty())
@ -3817,7 +3817,7 @@ void LoopInterfaceProcessor::generate(SupportGeneratorLayerExtruded &top_contact
extrusion_entities_append_paths(
top_contact_layer.extrusions,
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
@ -4252,7 +4252,7 @@ void generate_support_toolpaths(
// Filler and its parameters
filler, float(support_params.support_density),
// Extrusion parameters
erSupportMaterial, flow,
ExtrusionRole::SupportMaterial, flow,
support_params.with_sheath, false);
}
}
@ -4284,7 +4284,7 @@ void generate_support_toolpaths(
// Filler and its parameters
filler, density,
// 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
support_layer_id == 0, support_layer_id == 0);
}
@ -4440,7 +4440,7 @@ void generate_support_toolpaths(
// Filler and its parameters
filler_interface.get(), float(density),
// Extrusion parameters
erSupportMaterialInterface, interface_flow);
ExtrusionRole::SupportMaterialInterface, interface_flow);
}
// Base interface layers under soluble interfaces
@ -4462,7 +4462,7 @@ void generate_support_toolpaths(
// Filler and its parameters
filler, float(support_params.interface_density),
// Extrusion parameters
erSupportMaterial, interface_flow);
ExtrusionRole::SupportMaterial, interface_flow);
}
// Base support or flange.
@ -4500,7 +4500,7 @@ void generate_support_toolpaths(
// Filler and its parameters
filler, density,
// Extrusion parameters
erSupportMaterial, flow,
ExtrusionRole::SupportMaterial, flow,
sheath, no_sort);
}

View File

@ -58,7 +58,7 @@ public:
bool is_external_perimeter() const
{
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;
@ -170,16 +170,15 @@ struct SliceConnection
float get_flow_width(const LayerRegion *region, ExtrusionRole role)
{
switch (role) {
case ExtrusionRole::erBridgeInfill: return region->flow(FlowRole::frExternalPerimeter).width();
case ExtrusionRole::erExternalPerimeter: return region->flow(FlowRole::frExternalPerimeter).width();
case ExtrusionRole::erGapFill: return region->flow(FlowRole::frInfill).width();
case ExtrusionRole::erPerimeter: return region->flow(FlowRole::frPerimeter).width();
case ExtrusionRole::erSolidInfill: return region->flow(FlowRole::frSolidInfill).width();
case ExtrusionRole::erInternalInfill: return region->flow(FlowRole::frInfill).width();
case ExtrusionRole::erTopSolidInfill: return region->flow(FlowRole::frTopSolidInfill).width();
default: return region->flow(FlowRole::frPerimeter).width();
}
if (role == ExtrusionRole::BridgeInfill) return region->flow(FlowRole::frExternalPerimeter).width();
if (role == ExtrusionRole::ExternalPerimeter) return region->flow(FlowRole::frExternalPerimeter).width();
if (role == ExtrusionRole::GapFill) return region->flow(FlowRole::frInfill).width();
if (role == ExtrusionRole::Perimeter) return region->flow(FlowRole::frPerimeter).width();
if (role == ExtrusionRole::SolidInfill) return region->flow(FlowRole::frSolidInfill).width();
if (role == ExtrusionRole::InternalInfill) return region->flow(FlowRole::frInfill).width();
if (role == ExtrusionRole::TopSolidInfill) return region->flow(FlowRole::frTopSolidInfill).width();
// default
return region->flow(FlowRole::frPerimeter).width();
}
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());
for (const auto &fill_idx : fill_range) {
const ExtrusionEntity *entity = fill_region->fills().entities[fill_idx];
if (entity->role() == erBridgeInfill) {
if (entity->role() == ExtrusionRole::BridgeInfill) {
for (const ExtrusionLine &bridge :
check_extrusion_entity_stability(entity, fill_region, prev_layer_ext_perim_lines,prev_layer_boundary, params)) {
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 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:
underlying_type m_bits = 0;
};
// 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; };
#define ENABLE_ENUM_BITMASK_OPERATORS(x) template<> struct is_enum_bitmask_type<x> { static const bool enable = true; };
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 constexpr const bool enable = true; };
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:

View File

@ -899,7 +899,7 @@ void GCodeViewer::reset()
m_shells.volumes.clear();
m_layers.reset();
m_layers_z_range = { 0, 0 };
m_roles = std::vector<ExtrusionRole>();
m_roles = std::vector<GCodeExtrusionRole>();
m_print_statistics.reset();
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
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 != erSupportMaterialInterface &&
curr.extrusion_role != erWipeTower &&
curr.extrusion_role != erCustom &&
curr.extrusion_role != erMixed) {
curr.extrusion_role != erCustom) {
const Vec3d curr_pos = curr.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());
@ -3469,12 +3468,12 @@ void GCodeViewer::render_legend(float& legend_height)
return _u8L("from") + " " + std::string(buf1) + " " + _u8L("to") + " " + std::string(buf2) + " " + _u8L("mm");
};
auto role_time_and_percent = [time_mode](ExtrusionRole 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 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<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);
};
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);
if (it == m_print_statistics.used_filaments_per_role.end())
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) {
// calculate offsets to align time/percentage data
for (size_t i = 0; i < m_roles.size(); ++i) {
ExtrusionRole role = m_roles[i];
for (GCodeExtrusionRole role : m_roles) {
assert(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);
times.push_back((time > 0.0f) ? short_time(get_time_dhms(time)) : "");
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);
for (size_t i = 0; i < m_roles.size(); ++i) {
ExtrusionRole role = m_roles[i];
GCodeExtrusionRole role = m_roles[i];
if (role >= erCount)
continue;
const bool visible = is_visible(role);

View File

@ -208,7 +208,7 @@ class GCodeViewer
};
EMoveType type{ EMoveType::Noop };
ExtrusionRole role{ erNone };
GCodeExtrusionRole role{ erNone };
float delta_extruder{ 0.0f };
float height{ 0.0f };
float width{ 0.0f };
@ -753,7 +753,7 @@ private:
std::vector<ColorRGBA> m_tool_colors;
Layers m_layers;
std::array<unsigned int, 2> m_layers_z_range;
std::vector<ExtrusionRole> m_roles;
std::vector<GCodeExtrusionRole> m_roles;
size_t m_extruders_count;
std::vector<unsigned char> m_extruder_ids;
std::vector<float> m_filament_diameters;
@ -849,7 +849,7 @@ private:
#if ENABLE_GCODE_VIEWER_STATISTICS
void render_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;
}
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) {
for (const ExtrusionEntity *extrusion_entity : support_layer->support_fills.entities)
_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_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.
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)
t.polyline.append(random_point(LO, HI));
return t;
@ -37,7 +37,7 @@ static Slic3r::ExtrusionPaths random_paths(size_t count = 10, size_t length = 20
SCENARIO("ExtrusionPath", "[ExtrusionEntity]") {
GIVEN("Simple path") {
Slic3r::ExtrusionPath path{ erExternalPerimeter };
Slic3r::ExtrusionPath path{ ExtrusionRole::ExternalPerimeter };
path.polyline = { { 100, 100 }, { 200, 100 }, { 200, 200 } };
path.mm3_per_mm = 1.;
THEN("first point") {
@ -64,7 +64,7 @@ SCENARIO("ExtrusionLoop", "[ExtrusionEntity]")
Polygon square { { 100, 100 }, { 200, 100 }, { 200, 200 }, { 100, 200 } };
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") {
REQUIRE(loop.polygon().area() == Approx(square.area()));
}
@ -81,7 +81,7 @@ SCENARIO("ExtrusionLoop", "[ExtrusionEntity]")
REQUIRE(loop2->paths.size() == 1);
}
THEN("cloned role") {
REQUIRE(loop2->paths.front().role() == erExternalPerimeter);
REQUIRE(loop2->paths.front().role() == ExtrusionRole::ExternalPerimeter);
}
}
WHEN("cloned and split") {
@ -107,8 +107,8 @@ SCENARIO("ExtrusionLoop", "[ExtrusionEntity]")
Polyline polyline1 { { 100, 100 }, { 200, 100 }, { 200, 200 } };
Polyline polyline2 { { 200, 200 }, { 100, 200 }, { 100, 100 } };
ExtrusionLoop loop;
loop.paths.emplace_back(new_extrusion_path(polyline1, erExternalPerimeter, 1.));
loop.paths.emplace_back(new_extrusion_path(polyline2, erOverhangPerimeter, 1.));
loop.paths.emplace_back(new_extrusion_path(polyline1, ExtrusionRole::ExternalPerimeter, 1.));
loop.paths.emplace_back(new_extrusion_path(polyline2, ExtrusionRole::OverhangPerimeter, 1.));
double tot_len = polyline1.length() + polyline2.length();
THEN("length") {
@ -135,9 +135,9 @@ SCENARIO("ExtrusionLoop", "[ExtrusionEntity]")
REQUIRE(loop2->paths[1].polyline.back() == loop2->paths[2].polyline.front());
}
THEN("expected order after splitting") {
REQUIRE(loop2->paths.front().role() == erExternalPerimeter);
REQUIRE(loop2->paths[1].role() == erOverhangPerimeter);
REQUIRE(loop2->paths[2].role() == erExternalPerimeter);
REQUIRE(loop2->paths.front().role() == ExtrusionRole::ExternalPerimeter);
REQUIRE(loop2->paths[1].role() == ExtrusionRole::OverhangPerimeter);
REQUIRE(loop2->paths[2].role() == ExtrusionRole::ExternalPerimeter);
}
THEN("path has correct number of points") {
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());
}
THEN("expected order after splitting") {
REQUIRE(loop2->paths.front().role() == erOverhangPerimeter);
REQUIRE(loop2->paths[1].role() == erExternalPerimeter);
REQUIRE(loop2->paths.front().role() == ExtrusionRole::OverhangPerimeter);
REQUIRE(loop2->paths[1].role() == ExtrusionRole::ExternalPerimeter);
}
THEN("path has correct number of points") {
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 polyline4 { { 9829401, 4821067 }, { 59312736,4821067 } };
ExtrusionLoop loop;
loop.paths.emplace_back(new_extrusion_path(polyline1, erExternalPerimeter, 1.));
loop.paths.emplace_back(new_extrusion_path(polyline2, erOverhangPerimeter, 1.));
loop.paths.emplace_back(new_extrusion_path(polyline3, erExternalPerimeter, 1.));
loop.paths.emplace_back(new_extrusion_path(polyline4, erOverhangPerimeter, 1.));
loop.paths.emplace_back(new_extrusion_path(polyline1, ExtrusionRole::ExternalPerimeter, 1.));
loop.paths.emplace_back(new_extrusion_path(polyline2, ExtrusionRole::OverhangPerimeter, 1.));
loop.paths.emplace_back(new_extrusion_path(polyline3, ExtrusionRole::ExternalPerimeter, 1.));
loop.paths.emplace_back(new_extrusion_path(polyline4, ExtrusionRole::OverhangPerimeter, 1.));
double len = loop.length();
WHEN("splitting at vertex") {
Point point(4821067, 9321068);
@ -220,10 +220,10 @@ SCENARIO("ExtrusionLoop", "[ExtrusionEntity]")
REQUIRE(loop.length() == Approx(len));
}
THEN("order is correctly preserved after splitting") {
REQUIRE(loop.paths.front().role() == erExternalPerimeter);
REQUIRE(loop.paths[1].role() == erOverhangPerimeter);
REQUIRE(loop.paths[2].role() == erExternalPerimeter);
REQUIRE(loop.paths[3].role() == erOverhangPerimeter);
REQUIRE(loop.paths.front().role() == ExtrusionRole::ExternalPerimeter);
REQUIRE(loop.paths[1].role() == ExtrusionRole::OverhangPerimeter);
REQUIRE(loop.paths[2].role() == ExtrusionRole::ExternalPerimeter);
REQUIRE(loop.paths[3].role() == ExtrusionRole::OverhangPerimeter);
}
}
}
@ -233,7 +233,7 @@ SCENARIO("ExtrusionLoop", "[ExtrusionEntity]")
loop.paths.emplace_back(new_extrusion_path(
Polyline { { 15896783, 15868739 }, { 24842049, 12117558 }, { 33853238, 15801279 }, { 37591780, 24780128 }, { 37591780, 24844970 },
{ 33853231, 33825297 }, { 24842049, 37509013 }, { 15896798, 33757841 }, { 12211841, 24812544 }, { 15896783, 15868739 } },
erExternalPerimeter, 1.));
ExtrusionRole::ExternalPerimeter, 1.));
double len = loop.length();
THEN("split_at() preserves total length") {
loop.split_at({ 15896783, 15868739 }, false, 0);
@ -245,9 +245,9 @@ SCENARIO("ExtrusionLoop", "[ExtrusionEntity]")
SCENARIO("ExtrusionEntityCollection: Basics", "[ExtrusionEntity]")
{
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;
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;
collection.append(path);
THEN("no_sort is false by default") {
@ -378,7 +378,7 @@ TEST_CASE("ExtrusionEntityCollection: Chained path", "[ExtrusionEntity]") {
REQUIRE(chained == test.chained);
ExtrusionEntityCollection unchained_extrusions;
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") {
ExtrusionEntityCollection chained_extrusions = unchained_extrusions.chained_path_from(test.initial_point);
REQUIRE(chained_extrusions.entities.size() == test.chained.size());

View File

@ -80,13 +80,13 @@ SCENARIO("Perimeter nesting", "[Perimeters]")
}
THEN("expected number of external loops") {
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);
}
THEN("expected external order") {
std::vector<bool> ext_order;
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);
}
THEN("expected number of internal contour loops") {