Ported test_skirt_brim from upstream Slic3r, thanks @lordofhyphens
This commit is contained in:
parent
c99e7cb0df
commit
1964ac2e89
@ -29,6 +29,8 @@ public:
|
|||||||
float value(Axis axis) const { return m_axis[axis]; }
|
float value(Axis axis) const { return m_axis[axis]; }
|
||||||
bool has(char axis) const;
|
bool has(char axis) const;
|
||||||
bool has_value(char axis, float &value) const;
|
bool has_value(char axis, float &value) const;
|
||||||
|
float new_X(const GCodeReader &reader) const { return this->has(X) ? this->x() : reader.x(); }
|
||||||
|
float new_Y(const GCodeReader &reader) const { return this->has(Y) ? this->y() : reader.y(); }
|
||||||
float new_Z(const GCodeReader &reader) const { return this->has(Z) ? this->z() : reader.z(); }
|
float new_Z(const GCodeReader &reader) const { return this->has(Z) ? this->z() : reader.z(); }
|
||||||
float new_E(const GCodeReader &reader) const { return this->has(E) ? this->e() : reader.e(); }
|
float new_E(const GCodeReader &reader) const { return this->has(E) ? this->e() : reader.e(); }
|
||||||
float new_F(const GCodeReader &reader) const { return this->has(F) ? this->f() : reader.f(); }
|
float new_F(const GCodeReader &reader) const { return this->has(F) ? this->f() : reader.f(); }
|
||||||
|
@ -29,7 +29,7 @@ PrintConfigDef::PrintConfigDef()
|
|||||||
this->init_common_params();
|
this->init_common_params();
|
||||||
assign_printer_technology_to_unknown(this->options, ptAny);
|
assign_printer_technology_to_unknown(this->options, ptAny);
|
||||||
this->init_fff_params();
|
this->init_fff_params();
|
||||||
this->init_extruder_retract_keys();
|
this->init_extruder_option_keys();
|
||||||
assign_printer_technology_to_unknown(this->options, ptFFF);
|
assign_printer_technology_to_unknown(this->options, ptFFF);
|
||||||
this->init_sla_params();
|
this->init_sla_params();
|
||||||
assign_printer_technology_to_unknown(this->options, ptSLA);
|
assign_printer_technology_to_unknown(this->options, ptSLA);
|
||||||
@ -2270,8 +2270,17 @@ void PrintConfigDef::init_fff_params()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintConfigDef::init_extruder_retract_keys()
|
void PrintConfigDef::init_extruder_option_keys()
|
||||||
{
|
{
|
||||||
|
// ConfigOptionFloats, ConfigOptionPercents, ConfigOptionBools, ConfigOptionStrings
|
||||||
|
m_extruder_option_keys = {
|
||||||
|
"nozzle_diameter", "min_layer_height", "max_layer_height", "extruder_offset",
|
||||||
|
"retract_length", "retract_lift", "retract_lift_above", "retract_lift_below", "retract_speed", "deretract_speed",
|
||||||
|
"retract_before_wipe", "retract_restart_extra", "retract_before_travel", "wipe",
|
||||||
|
"retract_layer_change", "retract_length_toolchange", "retract_restart_extra_toolchange", "extruder_colour",
|
||||||
|
"default_filament_profile"
|
||||||
|
};
|
||||||
|
|
||||||
m_extruder_retract_keys = {
|
m_extruder_retract_keys = {
|
||||||
"deretract_speed",
|
"deretract_speed",
|
||||||
"retract_before_travel",
|
"retract_before_travel",
|
||||||
@ -2938,6 +2947,20 @@ void DynamicPrintConfig::normalize()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DynamicPrintConfig::set_num_extruders(unsigned int num_extruders)
|
||||||
|
{
|
||||||
|
const auto &defaults = FullPrintConfig::defaults();
|
||||||
|
for (const std::string &key : print_config_def.extruder_option_keys()) {
|
||||||
|
if (key == "default_filament_profile")
|
||||||
|
continue;
|
||||||
|
auto *opt = this->option(key, false);
|
||||||
|
assert(opt != nullptr);
|
||||||
|
assert(opt->is_vector());
|
||||||
|
if (opt != nullptr && opt->is_vector())
|
||||||
|
static_cast<ConfigOptionVectorBase*>(opt)->resize(num_extruders, defaults.option(key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string DynamicPrintConfig::validate()
|
std::string DynamicPrintConfig::validate()
|
||||||
{
|
{
|
||||||
// Full print config is initialized from the defaults.
|
// Full print config is initialized from the defaults.
|
||||||
|
@ -193,6 +193,8 @@ public:
|
|||||||
|
|
||||||
static void handle_legacy(t_config_option_key &opt_key, std::string &value);
|
static void handle_legacy(t_config_option_key &opt_key, std::string &value);
|
||||||
|
|
||||||
|
// Array options growing with the number of extruders
|
||||||
|
const std::vector<std::string>& extruder_option_keys() const { return m_extruder_option_keys; }
|
||||||
// Options defining the extruder retract properties. These keys are sorted lexicographically.
|
// Options defining the extruder retract properties. These keys are sorted lexicographically.
|
||||||
// The extruder retract keys could be overidden by the same values defined at the Filament level
|
// The extruder retract keys could be overidden by the same values defined at the Filament level
|
||||||
// (then the key is further prefixed with the "filament_" prefix).
|
// (then the key is further prefixed with the "filament_" prefix).
|
||||||
@ -201,9 +203,10 @@ public:
|
|||||||
private:
|
private:
|
||||||
void init_common_params();
|
void init_common_params();
|
||||||
void init_fff_params();
|
void init_fff_params();
|
||||||
void init_extruder_retract_keys();
|
void init_extruder_option_keys();
|
||||||
void init_sla_params();
|
void init_sla_params();
|
||||||
|
|
||||||
|
std::vector<std::string> m_extruder_option_keys;
|
||||||
std::vector<std::string> m_extruder_retract_keys;
|
std::vector<std::string> m_extruder_retract_keys;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -231,6 +234,8 @@ public:
|
|||||||
|
|
||||||
void normalize();
|
void normalize();
|
||||||
|
|
||||||
|
void set_num_extruders(unsigned int num_extruders);
|
||||||
|
|
||||||
// Validate the PrintConfig. Returns an empty string on success, otherwise an error message is returned.
|
// Validate the PrintConfig. Returns an empty string on success, otherwise an error message is returned.
|
||||||
std::string validate();
|
std::string validate();
|
||||||
|
|
||||||
|
@ -245,27 +245,13 @@ std::string Preset::remove_suffix_modified(const std::string &name)
|
|||||||
name;
|
name;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Preset::set_num_extruders(DynamicPrintConfig &config, unsigned int num_extruders)
|
|
||||||
{
|
|
||||||
const auto &defaults = FullPrintConfig::defaults();
|
|
||||||
for (const std::string &key : Preset::nozzle_options()) {
|
|
||||||
if (key == "default_filament_profile")
|
|
||||||
continue;
|
|
||||||
auto *opt = config.option(key, false);
|
|
||||||
assert(opt != nullptr);
|
|
||||||
assert(opt->is_vector());
|
|
||||||
if (opt != nullptr && opt->is_vector())
|
|
||||||
static_cast<ConfigOptionVectorBase*>(opt)->resize(num_extruders, defaults.option(key));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update new extruder fields at the printer profile.
|
// Update new extruder fields at the printer profile.
|
||||||
void Preset::normalize(DynamicPrintConfig &config)
|
void Preset::normalize(DynamicPrintConfig &config)
|
||||||
{
|
{
|
||||||
auto *nozzle_diameter = dynamic_cast<const ConfigOptionFloats*>(config.option("nozzle_diameter"));
|
auto *nozzle_diameter = dynamic_cast<const ConfigOptionFloats*>(config.option("nozzle_diameter"));
|
||||||
if (nozzle_diameter != nullptr)
|
if (nozzle_diameter != nullptr)
|
||||||
// Loaded the FFF Printer settings. Verify, that all extruder dependent values have enough values.
|
// Loaded the FFF Printer settings. Verify, that all extruder dependent values have enough values.
|
||||||
set_num_extruders(config, (unsigned int)nozzle_diameter->values.size());
|
config.set_num_extruders((unsigned int)nozzle_diameter->values.size());
|
||||||
if (config.option("filament_diameter") != nullptr) {
|
if (config.option("filament_diameter") != nullptr) {
|
||||||
// This config contains single or multiple filament presets.
|
// This config contains single or multiple filament presets.
|
||||||
// Ensure that the filament preset vector options contain the correct number of values.
|
// Ensure that the filament preset vector options contain the correct number of values.
|
||||||
@ -469,15 +455,7 @@ const std::vector<std::string>& Preset::printer_options()
|
|||||||
// of the nozzle_diameter vector.
|
// of the nozzle_diameter vector.
|
||||||
const std::vector<std::string>& Preset::nozzle_options()
|
const std::vector<std::string>& Preset::nozzle_options()
|
||||||
{
|
{
|
||||||
// ConfigOptionFloats, ConfigOptionPercents, ConfigOptionBools, ConfigOptionStrings
|
return print_config_def.extruder_option_keys();
|
||||||
static std::vector<std::string> s_opts {
|
|
||||||
"nozzle_diameter", "min_layer_height", "max_layer_height", "extruder_offset",
|
|
||||||
"retract_length", "retract_lift", "retract_lift_above", "retract_lift_below", "retract_speed", "deretract_speed",
|
|
||||||
"retract_before_wipe", "retract_restart_extra", "retract_before_travel", "wipe",
|
|
||||||
"retract_layer_change", "retract_length_toolchange", "retract_restart_extra_toolchange", "extruder_colour",
|
|
||||||
"default_filament_profile"
|
|
||||||
};
|
|
||||||
return s_opts;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<std::string>& Preset::sla_print_options()
|
const std::vector<std::string>& Preset::sla_print_options()
|
||||||
|
@ -202,7 +202,7 @@ public:
|
|||||||
void set_visible_from_appconfig(const AppConfig &app_config);
|
void set_visible_from_appconfig(const AppConfig &app_config);
|
||||||
|
|
||||||
// Resize the extruder specific fields, initialize them with the content of the 1st extruder.
|
// Resize the extruder specific fields, initialize them with the content of the 1st extruder.
|
||||||
void set_num_extruders(unsigned int n) { set_num_extruders(this->config, n); }
|
void set_num_extruders(unsigned int n) { this->config.set_num_extruders(n); }
|
||||||
|
|
||||||
// Sort lexicographically by a preset name. The preset name shall be unique across a single PresetCollection.
|
// Sort lexicographically by a preset name. The preset name shall be unique across a single PresetCollection.
|
||||||
bool operator<(const Preset &other) const { return this->name < other.name; }
|
bool operator<(const Preset &other) const { return this->name < other.name; }
|
||||||
@ -227,8 +227,6 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
friend class PresetCollection;
|
friend class PresetCollection;
|
||||||
friend class PresetBundle;
|
friend class PresetBundle;
|
||||||
// Resize the extruder specific vectors ()
|
|
||||||
static void set_num_extruders(DynamicPrintConfig &config, unsigned int n);
|
|
||||||
static std::string remove_suffix_modified(const std::string &name);
|
static std::string remove_suffix_modified(const std::string &name);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ add_executable(${_TEST_NAME}_tests
|
|||||||
test_data.cpp
|
test_data.cpp
|
||||||
test_data.hpp
|
test_data.hpp
|
||||||
test_flow.cpp
|
test_flow.cpp
|
||||||
|
test_skirt_brim.cpp
|
||||||
test_trianglemesh.cpp
|
test_trianglemesh.cpp
|
||||||
)
|
)
|
||||||
target_link_libraries(${_TEST_NAME}_tests test_common libslic3r)
|
target_link_libraries(${_TEST_NAME}_tests test_common libslic3r)
|
||||||
|
@ -226,11 +226,14 @@ std::shared_ptr<Print> init_print(std::initializer_list<TestMesh> meshes, Slic3r
|
|||||||
|
|
||||||
model.arrange_objects(PrintConfig::min_object_distance(config.get()));
|
model.arrange_objects(PrintConfig::min_object_distance(config.get()));
|
||||||
model.center_instances_around_point(Slic3r::Vec2d(100,100));
|
model.center_instances_around_point(Slic3r::Vec2d(100,100));
|
||||||
for (ModelObject *mo : model.objects)
|
for (ModelObject *mo : model.objects) {
|
||||||
|
mo->ensure_on_bed();
|
||||||
print->auto_assign_extruders(mo);
|
print->auto_assign_extruders(mo);
|
||||||
|
}
|
||||||
|
|
||||||
print->apply(model, *config);
|
print->apply(model, *config);
|
||||||
print->validate();
|
print->validate();
|
||||||
|
print->set_status_silent();
|
||||||
return print;
|
return print;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,11 +258,14 @@ std::shared_ptr<Print> init_print(std::initializer_list<TriangleMesh> meshes, Sl
|
|||||||
}
|
}
|
||||||
model.arrange_objects(PrintConfig::min_object_distance(config.get()));
|
model.arrange_objects(PrintConfig::min_object_distance(config.get()));
|
||||||
model.center_instances_around_point(Slic3r::Vec2d(100, 100));
|
model.center_instances_around_point(Slic3r::Vec2d(100, 100));
|
||||||
for (ModelObject *mo : model.objects)
|
for (ModelObject *mo : model.objects) {
|
||||||
|
mo->ensure_on_bed();
|
||||||
print->auto_assign_extruders(mo);
|
print->auto_assign_extruders(mo);
|
||||||
|
}
|
||||||
|
|
||||||
print->apply(model, *config);
|
print->apply(model, *config);
|
||||||
print->validate();
|
print->validate();
|
||||||
|
print->set_status_silent();
|
||||||
return print;
|
return print;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
263
tests/fff_print/test_skirt_brim.cpp
Normal file
263
tests/fff_print/test_skirt_brim.cpp
Normal file
@ -0,0 +1,263 @@
|
|||||||
|
#include <catch2/catch.hpp>
|
||||||
|
|
||||||
|
#include "libslic3r/GCodeReader.hpp"
|
||||||
|
#include "libslic3r/Config.hpp"
|
||||||
|
#include "libslic3r/Geometry.hpp"
|
||||||
|
|
||||||
|
#include <boost/algorithm/string.hpp>
|
||||||
|
|
||||||
|
#include "test_data.hpp" // get access to init_print, etc
|
||||||
|
|
||||||
|
using namespace Slic3r::Test;
|
||||||
|
using namespace Slic3r;
|
||||||
|
|
||||||
|
/// Helper method to find the tool used for the brim (always the first extrusion)
|
||||||
|
int get_brim_tool(std::string &gcode, Slic3r::GCodeReader& parser) {
|
||||||
|
int brim_tool = -1;
|
||||||
|
int tool = -1;
|
||||||
|
|
||||||
|
parser.parse_buffer(gcode, [&tool, &brim_tool] (Slic3r::GCodeReader& self, const Slic3r::GCodeReader::GCodeLine& line)
|
||||||
|
{
|
||||||
|
// if the command is a T command, set the the current tool
|
||||||
|
if (boost::starts_with(line.cmd(), "T")) {
|
||||||
|
tool = atoi(line.cmd().data() + 1);
|
||||||
|
} else if (line.cmd() == "G1" && line.extruding(self) && line.dist_XY(self) > 0 && brim_tool < 0) {
|
||||||
|
brim_tool = tool;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return brim_tool;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Skirt height is honored") {
|
||||||
|
std::shared_ptr<Slic3r::DynamicPrintConfig> config(Slic3r::DynamicPrintConfig::new_from_defaults());
|
||||||
|
config->opt_int("skirts") = 1;
|
||||||
|
config->opt_int("skirt_height") = 5;
|
||||||
|
config->opt_int("perimeters") = 0;
|
||||||
|
config->opt_float("support_material_speed") = 99;
|
||||||
|
|
||||||
|
// avoid altering speeds unexpectedly
|
||||||
|
config->set_deserialize("cooling", "0");
|
||||||
|
config->set_deserialize("first_layer_speed", "100%");
|
||||||
|
auto support_speed = config->opt<Slic3r::ConfigOptionFloat>("support_material_speed")->value * MM_PER_MIN;
|
||||||
|
|
||||||
|
std::map<double, bool> layers_with_skirt;
|
||||||
|
std::string gcode;
|
||||||
|
GCodeReader parser;
|
||||||
|
Slic3r::Model model;
|
||||||
|
|
||||||
|
SECTION("printing a single object") {
|
||||||
|
auto print {Slic3r::Test::init_print({TestMesh::cube_20x20x20}, model, config)};
|
||||||
|
gcode = Slic3r::Test::gcode(print);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("printing multiple objects") {
|
||||||
|
auto print {Slic3r::Test::init_print({TestMesh::cube_20x20x20, TestMesh::cube_20x20x20}, model, config)};
|
||||||
|
gcode = Slic3r::Test::gcode(print);
|
||||||
|
}
|
||||||
|
parser.parse_buffer(gcode, [&layers_with_skirt, &support_speed] (Slic3r::GCodeReader& self, const Slic3r::GCodeReader::GCodeLine& line)
|
||||||
|
{
|
||||||
|
if (line.extruding(self) && self.f() == Approx(support_speed)) {
|
||||||
|
layers_with_skirt[self.z()] = 1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
REQUIRE(layers_with_skirt.size() == (size_t)config->opt_int("skirt_height"));
|
||||||
|
}
|
||||||
|
|
||||||
|
SCENARIO("Original Slic3r Skirt/Brim tests", "[!mayfail]") {
|
||||||
|
auto parser {Slic3r::GCodeReader()};
|
||||||
|
Slic3r::Model model;
|
||||||
|
std::string gcode;
|
||||||
|
GIVEN("A default configuration") {
|
||||||
|
std::shared_ptr<Slic3r::DynamicPrintConfig> config(Slic3r::DynamicPrintConfig::new_from_defaults());
|
||||||
|
config->set_num_extruders(4);
|
||||||
|
config->opt_float("support_material_speed") = 99;
|
||||||
|
config->set_deserialize("first_layer_height", "0.3");
|
||||||
|
config->set_deserialize("gcode_comments", "1");
|
||||||
|
|
||||||
|
// avoid altering speeds unexpectedly
|
||||||
|
config->set_deserialize("cooling", "0");
|
||||||
|
config->set_deserialize("first_layer_speed", "100%");
|
||||||
|
// remove noise from top/solid layers
|
||||||
|
config->opt_int("top_solid_layers") = 0;
|
||||||
|
config->opt_int("bottom_solid_layers") = 1;
|
||||||
|
|
||||||
|
WHEN("Brim width is set to 5") {
|
||||||
|
config->opt_int("perimeters") = 0;
|
||||||
|
config->opt_int("skirts") = 0;
|
||||||
|
config->opt_float("brim_width") = 5;
|
||||||
|
THEN("Brim is generated") {
|
||||||
|
auto print {Slic3r::Test::init_print({TestMesh::cube_20x20x20}, model, config)};
|
||||||
|
gcode = Slic3r::Test::gcode(print);
|
||||||
|
bool brim_generated = false;
|
||||||
|
auto support_speed = config->opt<Slic3r::ConfigOptionFloat>("support_material_speed")->value * MM_PER_MIN;
|
||||||
|
parser.parse_buffer(gcode, [&brim_generated, support_speed] (Slic3r::GCodeReader& self, const Slic3r::GCodeReader::GCodeLine& line)
|
||||||
|
{
|
||||||
|
if (self.z() == Approx(0.3) || line.new_Z(self) == Approx(0.3)) {
|
||||||
|
if (line.extruding(self) && self.f() == Approx(support_speed)) {
|
||||||
|
brim_generated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
REQUIRE(brim_generated);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WHEN("Skirt area is smaller than the brim") {
|
||||||
|
config->opt_int("skirts") = 1;
|
||||||
|
config->opt_float("brim_width") = 10;
|
||||||
|
auto print {Slic3r::Test::init_print({TestMesh::cube_20x20x20}, model, config)};
|
||||||
|
THEN("Gcode generates") {
|
||||||
|
REQUIRE(! Slic3r::Test::gcode(print).empty());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WHEN("Skirt height is 0 and skirts > 0") {
|
||||||
|
config->opt_int("skirts") = 2;
|
||||||
|
config->opt_int("skirt_height") = 0;
|
||||||
|
|
||||||
|
auto print {Slic3r::Test::init_print({TestMesh::cube_20x20x20}, model, config)};
|
||||||
|
THEN("Gcode generates") {
|
||||||
|
REQUIRE(! Slic3r::Test::gcode(print).empty());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WHEN("Perimeter extruder = 2 and support extruders = 3") {
|
||||||
|
config->opt_int("skirts") = 0;
|
||||||
|
config->opt_float("brim_width") = 5;
|
||||||
|
config->opt_int("perimeter_extruder") = 2;
|
||||||
|
config->opt_int("support_material_extruder") = 3;
|
||||||
|
THEN("Brim is printed with the extruder used for the perimeters of first object") {
|
||||||
|
auto print {Slic3r::Test::init_print({TestMesh::cube_20x20x20}, model, config)};
|
||||||
|
gcode = Slic3r::Test::gcode(print);
|
||||||
|
int tool = get_brim_tool(gcode, parser);
|
||||||
|
REQUIRE(tool == config->opt_int("perimeter_extruder") - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WHEN("Perimeter extruder = 2, support extruders = 3, raft is enabled") {
|
||||||
|
config->opt_int("skirts") = 0;
|
||||||
|
config->opt_float("brim_width") = 5;
|
||||||
|
config->opt_int("perimeter_extruder") = 2;
|
||||||
|
config->opt_int("support_material_extruder") = 3;
|
||||||
|
config->opt_int("raft_layers") = 1;
|
||||||
|
THEN("brim is printed with same extruder as skirt") {
|
||||||
|
auto print {Slic3r::Test::init_print({TestMesh::cube_20x20x20}, model, config)};
|
||||||
|
gcode = Slic3r::Test::gcode(print);
|
||||||
|
int tool = get_brim_tool(gcode, parser);
|
||||||
|
REQUIRE(tool == config->opt_int("support_material_extruder") - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WHEN("brim width to 1 with layer_width of 0.5") {
|
||||||
|
config->opt_int("skirts") = 0;
|
||||||
|
config->set_deserialize("first_layer_extrusion_width", "0.5");
|
||||||
|
config->opt_float("brim_width") = 1;
|
||||||
|
|
||||||
|
THEN("2 brim lines") {
|
||||||
|
Slic3r::Model model;
|
||||||
|
auto print {Slic3r::Test::init_print({TestMesh::cube_20x20x20}, model, config)};
|
||||||
|
print->process();
|
||||||
|
REQUIRE(print->brim().entities.size() == 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
WHEN("brim ears on a square") {
|
||||||
|
config->opt_int("skirts") = 0);
|
||||||
|
config->set_deserialize("first_layer_extrusion_width", "0.5");
|
||||||
|
config->opt_float("brim_width") = 1;
|
||||||
|
config->set("brim_ears", true);
|
||||||
|
config->set("brim_ears_max_angle", 91);
|
||||||
|
|
||||||
|
Slic3r::Model model;
|
||||||
|
auto print {Slic3r::Test::init_print({TestMesh::cube_20x20x20}, model, config)};
|
||||||
|
print->process();
|
||||||
|
|
||||||
|
THEN("Four brim ears") {
|
||||||
|
REQUIRE(print->brim.size() == 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WHEN("brim ears on a square but with a too small max angle") {
|
||||||
|
config->set("skirts", 0);
|
||||||
|
config->set("first_layer_extrusion_width", 0.5);
|
||||||
|
config->set("brim_width", 1);
|
||||||
|
config->set("brim_ears", true);
|
||||||
|
config->set("brim_ears_max_angle", 89);
|
||||||
|
|
||||||
|
THEN("no brim") {
|
||||||
|
Slic3r::Model model;
|
||||||
|
auto print {Slic3r::Test::init_print({TestMesh::cube_20x20x20}, model, config)};
|
||||||
|
print->process();
|
||||||
|
REQUIRE(print->brim.size() == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
WHEN("Object is plated with overhang support and a brim") {
|
||||||
|
config->opt_float("layer_height") = 0.4;
|
||||||
|
config->set_deserialize("first_layer_height", "0.4");
|
||||||
|
config->opt_int("skirts") = 1;
|
||||||
|
config->opt_float("skirt_distance") = 0;
|
||||||
|
config->opt_float("support_material_speed") = 99;
|
||||||
|
config->opt_int("perimeter_extruder") = 1;
|
||||||
|
config->opt_int("support_material_extruder") = 2;
|
||||||
|
config->opt_int("infill_extruder") = 3; // ensure that a tool command gets emitted.
|
||||||
|
config->set_deserialize("cooling", "0"); // to prevent speeds to be altered
|
||||||
|
config->set_deserialize("first_layer_speed", "100%"); // to prevent speeds to be altered
|
||||||
|
|
||||||
|
Slic3r::Model model;
|
||||||
|
auto print {Slic3r::Test::init_print({TestMesh::overhang}, model, config)};
|
||||||
|
print->process();
|
||||||
|
|
||||||
|
// config->set("support_material", true); // to prevent speeds to be altered
|
||||||
|
|
||||||
|
THEN("skirt length is large enough to contain object with support") {
|
||||||
|
CHECK(config->opt_bool("support_material")); // test is not valid if support material is off
|
||||||
|
double skirt_length = 0.0;
|
||||||
|
Points extrusion_points;
|
||||||
|
int tool = -1;
|
||||||
|
|
||||||
|
auto print = Slic3r::Test::init_print({TestMesh::cube_20x20x20}, model, config);
|
||||||
|
std::string gcode = Slic3r::Test::gcode(print);
|
||||||
|
|
||||||
|
auto support_speed = config->opt<ConfigOptionFloat>("support_material_speed")->value * MM_PER_MIN;
|
||||||
|
parser.parse_buffer(gcode, [config, &extrusion_points, &tool, &skirt_length, support_speed] (Slic3r::GCodeReader& self, const Slic3r::GCodeReader::GCodeLine& line)
|
||||||
|
{
|
||||||
|
// std::cerr << line.cmd() << "\n";
|
||||||
|
if (boost::starts_with(line.cmd(), "T")) {
|
||||||
|
tool = atoi(line.cmd().data() + 1);
|
||||||
|
} else if (self.z() == Approx(config->opt<ConfigOptionFloat>("first_layer_height")->value)) {
|
||||||
|
// on first layer
|
||||||
|
if (line.extruding(self) && line.dist_XY(self) > 0) {
|
||||||
|
auto speed = ( self.f() > 0 ? self.f() : line.new_F(self));
|
||||||
|
// std::cerr << "Tool " << tool << "\n";
|
||||||
|
if (speed == Approx(support_speed) && tool == config->opt_int("perimeter_extruder") - 1) {
|
||||||
|
// Skirt uses first material extruder, support material speed.
|
||||||
|
skirt_length += line.dist_XY(self);
|
||||||
|
} else {
|
||||||
|
extrusion_points.push_back(Slic3r::Point::new_scale(line.new_X(self), line.new_Y(self)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self.z() == Approx(0.3) || line.new_Z(self) == Approx(0.3)) {
|
||||||
|
if (line.extruding(self) && self.f() == Approx(support_speed)) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Slic3r::Polygon convex_hull = Slic3r::Geometry::convex_hull(extrusion_points);
|
||||||
|
double hull_perimeter = unscale<double>(convex_hull.split_at_first_point().length());
|
||||||
|
REQUIRE(skirt_length > hull_perimeter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WHEN("Large minimum skirt length is used.") {
|
||||||
|
config->opt_float("min_skirt_length") = 20;
|
||||||
|
Slic3r::Model model;
|
||||||
|
auto print = Slic3r::Test::init_print({TestMesh::cube_20x20x20}, model, config);
|
||||||
|
THEN("Gcode generation doesn't crash") {
|
||||||
|
REQUIRE(! Slic3r::Test::gcode(print).empty());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user