diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 3ef21ee41f..c2133066f6 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -1,4 +1,5 @@ #include "PrintConfig.hpp" +#include "PrintConfigConstants.hpp" #include "ClipperUtils.hpp" #include "Config.hpp" #include "MaterialType.hpp" @@ -686,7 +687,7 @@ void PrintConfigDef::init_common_params() def->tooltip = L("Slicing height for each layer. Smaller layer height means more accurate and more printing time."); def->sidetext = "mm"; // milimeters, don't need translation def->min = 0; - def->set_default_value(new ConfigOptionFloat(0.2)); + def->set_default_value(new ConfigOptionFloat(INITIAL_LAYER_HEIGHT)); def = this->add("printable_height", coFloat); def->label = L("Printable height"); @@ -833,7 +834,7 @@ void PrintConfigDef::init_fff_params() def->category = L("Quality"); def->tooltip = L("Detour to avoid traveling across walls, which may cause blobs on the surface."); def->mode = comAdvanced; - def->set_default_value(new ConfigOptionBool(false)); + def->set_default_value(new ConfigOptionBool(INITIAL_REDUCE_CROSSING_WALL)); def = this->add("max_travel_detour_distance", coFloatOrPercent); def->label = L("Avoid crossing walls - Max detour length"); @@ -4540,7 +4541,7 @@ void PrintConfigDef::init_fff_params() def->min = 0; def->max = 100; def->mode = comAdvanced; - def->set_default_value(new ConfigOptionInt(0)); + def->set_default_value(new ConfigOptionInt(INITIAL_RAFT_LAYERS)); def = this->add("resolution", coFloat); def->label = L("Resolution"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 807ce56b36..e3cbc37291 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -510,7 +510,7 @@ CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(PerimeterGeneratorType) class DynamicPrintConfig; -// Defines each and every confiuration option of Slic3r, including the properties of the GUI dialogs. +// Defines each and every configuration option of Slic3r, including the properties of the GUI dialogs. // Does not store the actual values, but defines default values. class PrintConfigDef : public ConfigDef { diff --git a/src/libslic3r/PrintConfigConstants.hpp b/src/libslic3r/PrintConfigConstants.hpp new file mode 100644 index 0000000000..5520fbc72e --- /dev/null +++ b/src/libslic3r/PrintConfigConstants.hpp @@ -0,0 +1,7 @@ +#pragma once + +// These are here just for unit testing. + +#define INITIAL_LAYER_HEIGHT 0.2 +#define INITIAL_RAFT_LAYERS 0 +#define INITIAL_REDUCE_CROSSING_WALL false diff --git a/tests/libslic3r/test_3mf.cpp b/tests/libslic3r/test_3mf.cpp index 3602d6972d..8d389253aa 100644 --- a/tests/libslic3r/test_3mf.cpp +++ b/tests/libslic3r/test_3mf.cpp @@ -12,8 +12,8 @@ SCENARIO("Reading 3mf file", "[3mf]") { GIVEN("umlauts in the path of the file") { Model model; WHEN("3mf model is read") { - std::string path = std::string(TEST_DATA_DIR) + "/test_3mf/Geräte/Büchse.3mf"; - DynamicPrintConfig config; + std::string path = std::string(TEST_DATA_DIR) + "/test_3mf/Geräte/Büchse.3mf"; + DynamicPrintConfig config; ConfigSubstitutionContext ctxt{ ForwardCompatibilitySubstitutionRule::Disable }; bool ret = load_3mf(path.c_str(), config, ctxt, &model, false); THEN("load should succeed") { @@ -85,7 +85,7 @@ SCENARIO("2D convex hull of sinking object", "[3mf]") { // load a model Model model; std::string src_file = std::string(TEST_DATA_DIR) + "/test_3mf/Prusa.stl"; - load_stl(src_file.c_str(), &model); + REQUIRE(load_stl(src_file.c_str(), &model)); model.add_default_instances(); WHEN("model is rotated, scaled and set as sinking") { @@ -112,22 +112,20 @@ SCENARIO("2D convex hull of sinking object", "[3mf]") { { -91501496, 4243 } }; - // Allow 1um error due to floating point rounding. - bool res = hull_2d.points.size() == result.size(); - if (res) - for (size_t i = 0; i < result.size(); ++ i) { - const Point &p1 = result[i]; - const Point &p2 = hull_2d.points[i]; - if (std::abs(p1.x() - p2.x()) > 1 || std::abs(p1.y() - p2.y()) > 1) { - res = false; - break; + THEN("2D convex hull should match with reference") { + // Allow 1um error due to floating point rounding. + bool res = hull_2d.points.size() == result.size(); + if (res) { + for (size_t i = 0; i < result.size(); ++ i) { + const Point &p1 = result[i]; + const Point &p2 = hull_2d.points[i]; + CHECK((std::abs(p1.x() - p2.x()) > 1 || std::abs(p1.y() - p2.y()) > 1)); } } - THEN("2D convex hull should match with reference") { + CAPTURE(hull_2d.points); REQUIRE(res); } } } } - diff --git a/tests/libslic3r/test_config.cpp b/tests/libslic3r/test_config.cpp index 025459d689..f98dbcab5d 100644 --- a/tests/libslic3r/test_config.cpp +++ b/tests/libslic3r/test_config.cpp @@ -1,6 +1,7 @@ #include #include "libslic3r/PrintConfig.hpp" +#include "libslic3r/PrintConfigConstants.hpp" #include "libslic3r/LocalesUtils.hpp" #include @@ -13,23 +14,23 @@ using namespace Slic3r; SCENARIO("Generic config validation performs as expected.", "[Config]") { GIVEN("A config generated from default options") { Slic3r::DynamicPrintConfig config = Slic3r::DynamicPrintConfig::full_print_config(); - WHEN( "perimeter_extrusion_width is set to 250%, a valid value") { - config.set_deserialize_strict("perimeter_extrusion_width", "250%"); + WHEN( "outer_wall_line_width is set to 250%, a valid value") { + config.set_deserialize_strict("outer_wall_line_width", "250%"); THEN( "The config is read as valid.") { REQUIRE(config.validate().empty()); } } - WHEN( "perimeter_extrusion_width is set to -10, an invalid value") { - config.set("perimeter_extrusion_width", -10); + WHEN( "outer_wall_line_width is set to -10, an invalid value") { + config.set("outer_wall_line_width", -10); THEN( "Validate returns error") { - REQUIRE(! config.validate().empty()); + REQUIRE_FALSE(config.validate().empty()); } } - WHEN( "perimeters is set to -10, an invalid value") { - config.set("perimeters", -10); + WHEN( "wall_loops is set to -10, an invalid value") { + config.set("wall_loops", -10); THEN( "Validate returns error") { - REQUIRE(! config.validate().empty()); + REQUIRE_FALSE(config.validate().empty()); } } } @@ -64,95 +65,115 @@ SCENARIO("Config accessor functions perform as expected.", "[Config]") { } } WHEN("A numeric option is set from serialized string") { - config.set_deserialize_strict("bed_temperature", "100"); + config.set_deserialize_strict("raft_layers", "20"); THEN("The underlying value is set correctly.") { - REQUIRE(config.opt("bed_temperature")->get_at(0) == 100); + REQUIRE(config.opt("raft_layers")->getInt() == 20); } } -#if 0 - //FIXME better design accessors for vector elements. - WHEN("An integer-based option is set through the integer interface") { - config.set("bed_temperature", 100); - THEN("The underlying value is set correctly.") { - REQUIRE(config.opt("bed_temperature")->get_at(0) == 100); - } + WHEN("An integer-based option is set through the integer interface") { + config.set("raft_layers", 100); + THEN("The underlying value is set correctly.") { + REQUIRE(config.opt("raft_layers")->getInt() == 100); + } } -#endif WHEN("An floating-point option is set through the integer interface") { - config.set("perimeter_speed", 10); + config.set("default_acceleration", 10); THEN("The underlying value is set correctly.") { - REQUIRE(config.opt("perimeter_speed")->getFloat() == 10.0); + REQUIRE(config.opt("default_acceleration")->getFloat() == 10.0); } } WHEN("A floating-point option is set through the double interface") { - config.set("perimeter_speed", 5.5); + config.set("default_acceleration", 5.5); THEN("The underlying value is set correctly.") { - REQUIRE(config.opt("perimeter_speed")->getFloat() == 5.5); + REQUIRE(config.opt("default_acceleration")->getFloat() == 5.5); } } WHEN("An integer-based option is set through the double interface") { THEN("A BadOptionTypeException exception is thrown.") { - REQUIRE_THROWS_AS(config.set("bed_temperature", 5.5), BadOptionTypeException); + REQUIRE_THROWS_AS(config.set("top_shell_layers", 5.5), BadOptionTypeException); } } WHEN("A numeric option is set to a non-numeric value.") { - THEN("A BadOptionTypeException exception is thown.") { - REQUIRE_THROWS_AS(config.set_deserialize_strict("perimeter_speed", "zzzz"), BadOptionValueException); + auto prev_value = config.opt("default_acceleration")->getFloat(); + THEN("A BadOptionTypeException exception is thrown.") { + REQUIRE_THROWS_AS(config.set_deserialize_strict("default_acceleration", "zzzz"), BadOptionValueException); } THEN("The value does not change.") { - REQUIRE(config.opt("perimeter_speed")->getFloat() == 60.0); + REQUIRE(config.opt("default_acceleration")->getFloat() == prev_value); } } WHEN("A string option is set through the string interface") { - config.set("end_gcode", "100"); + config.set("machine_end_gcode", "100"); THEN("The underlying value is set correctly.") { - REQUIRE(config.opt("end_gcode")->value == "100"); + REQUIRE(config.opt("machine_end_gcode")->value == "100"); } } WHEN("A string option is set through the integer interface") { - config.set("end_gcode", 100); + config.set("machine_end_gcode", 100); THEN("The underlying value is set correctly.") { - REQUIRE(config.opt("end_gcode")->value == "100"); + REQUIRE(config.opt("machine_end_gcode")->value == "100"); } } WHEN("A string option is set through the double interface") { - config.set("end_gcode", 100.5); + config.set("machine_end_gcode", 100.5); THEN("The underlying value is set correctly.") { - REQUIRE(config.opt("end_gcode")->value == float_to_string_decimal_point(100.5)); + REQUIRE(config.opt("machine_end_gcode")->value == float_to_string_decimal_point(100.5)); } } WHEN("A float or percent is set as a percent through the string interface.") { - config.set_deserialize_strict("first_layer_extrusion_width", "100%"); + config.set_deserialize_strict("initial_layer_line_width", "100%"); THEN("Value and percent flag are 100/true") { - auto tmp = config.opt("first_layer_extrusion_width"); + auto tmp = config.opt("initial_layer_line_width"); REQUIRE(tmp->percent == true); REQUIRE(tmp->value == 100); } } WHEN("A float or percent is set as a float through the string interface.") { - config.set_deserialize_strict("first_layer_extrusion_width", "100"); + config.set_deserialize_strict("initial_layer_line_width", "100"); THEN("Value and percent flag are 100/false") { - auto tmp = config.opt("first_layer_extrusion_width"); + auto tmp = config.opt("initial_layer_line_width"); REQUIRE(tmp->percent == false); REQUIRE(tmp->value == 100); } } WHEN("A float or percent is set as a float through the int interface.") { - config.set("first_layer_extrusion_width", 100); + config.set("initial_layer_line_width", 100); THEN("Value and percent flag are 100/false") { - auto tmp = config.opt("first_layer_extrusion_width"); + auto tmp = config.opt("initial_layer_line_width"); REQUIRE(tmp->percent == false); REQUIRE(tmp->value == 100); } } WHEN("A float or percent is set as a float through the double interface.") { - config.set("first_layer_extrusion_width", 100.5); + config.set("initial_layer_line_width", 100.5); THEN("Value and percent flag are 100.5/false") { - auto tmp = config.opt("first_layer_extrusion_width"); + auto tmp = config.opt("initial_layer_line_width"); REQUIRE(tmp->percent == false); REQUIRE(tmp->value == 100.5); } } + WHEN("A numeric vector is set from serialized string") { + config.set_deserialize_strict("temperature_vitrification", "10,20"); + THEN("The underlying value is set correctly.") { + CHECK(config.opt("temperature_vitrification")->get_at(0) == 10); + CHECK(config.opt("temperature_vitrification")->get_at(1) == 20); + } + } + // FIXME: Design better accessors for vector elements + // The following isn't supported and probably shouldn't be: + // WHEN("An integer-based vector option is set through the integer interface") { + // config.set("temperature_vitrification", 100); + // THEN("The underlying value is set correctly.") { + // REQUIRE(config.opt("temperature_vitrification")->get_at(0) == 100); + // } + // } + WHEN("An integer-based vector option is set through the set_key_value interface") { + config.set_key_value("temperature_vitrification", new ConfigOptionInts{10,20}); + THEN("The underlying value is set correctly.") { + CHECK(config.opt("temperature_vitrification")->get_at(0) == 10); + CHECK(config.opt("temperature_vitrification")->get_at(1) == 20); + } + } WHEN("An invalid option is requested during set.") { THEN("A BadOptionTypeException exception is thrown.") { REQUIRE_THROWS_AS(config.set("deadbeef_invalid_option", 1), UnknownOptionException); @@ -181,16 +202,16 @@ SCENARIO("Config accessor functions perform as expected.", "[Config]") { WHEN("getX called on an unset option.") { THEN("The default is returned.") { - REQUIRE(config.opt_float("layer_height") == 0.3); - REQUIRE(config.opt_int("raft_layers") == 0); - REQUIRE(config.opt_bool("support_material") == false); + REQUIRE(config.opt_float("layer_height") == INITIAL_LAYER_HEIGHT); + REQUIRE(config.opt_int("raft_layers") == INITIAL_RAFT_LAYERS); + REQUIRE(config.opt_bool("reduce_crossing_wall") == INITIAL_REDUCE_CROSSING_WALL); } } - WHEN("getFloat called on an option that has been set.") { - config.set("layer_height", 0.5); + WHEN("opt_float called on an option that has been set.") { + config.set("layer_height", INITIAL_LAYER_HEIGHT*2); THEN("The set value is returned.") { - REQUIRE(config.opt_float("layer_height") == 0.5); + REQUIRE(config.opt_float("layer_height") == INITIAL_LAYER_HEIGHT*2); } } } diff --git a/tests/libslic3r/test_geometry.cpp b/tests/libslic3r/test_geometry.cpp index 75832771b1..6be0479c1a 100644 --- a/tests/libslic3r/test_geometry.cpp +++ b/tests/libslic3r/test_geometry.cpp @@ -33,7 +33,7 @@ TEST_CASE("Line::parallel_to", "[Geometry]"){ Line l4(l2); l4.rotate(1.1 * EPSILON, { 0, 0 }); - REQUIRE(! l.parallel_to(l4)); + REQUIRE_FALSE(l.parallel_to(l4)); // The angle epsilon is so low that vectors shorter than 100um rotated by epsilon radians are not rotated at all. Line l5{ { 20000, 0 }, { 0, 0 } }; @@ -48,13 +48,13 @@ TEST_CASE("Line::parallel_to", "[Geometry]"){ l4.rotate(1., { 0, 0 }); l4.translate(offset); REQUIRE(l.parallel_to(l3)); - REQUIRE(!l.parallel_to(l4)); + REQUIRE_FALSE(l.parallel_to(l4)); } TEST_CASE("Line::perpendicular_to", "[Geometry]") { Line l{ { 100000, 0 }, { 0, 0 } }; Line l2{ { 0, 200000 }, { 0, 0 } }; - REQUIRE(! l.perpendicular_to(l)); + REQUIRE_FALSE(l.perpendicular_to(l)); REQUIRE(l.perpendicular_to(l2)); Line l3(l2); @@ -63,7 +63,7 @@ TEST_CASE("Line::perpendicular_to", "[Geometry]") { Line l4(l2); l4.rotate(1.1 * EPSILON, { 0, 0 }); - REQUIRE(! l.perpendicular_to(l4)); + REQUIRE_FALSE(l.perpendicular_to(l4)); // The angle epsilon is so low that vectors shorter than 100um rotated by epsilon radians are not rotated at all. Line l5{ { 0, 20000 }, { 0, 0 } }; @@ -78,7 +78,7 @@ TEST_CASE("Line::perpendicular_to", "[Geometry]") { l4.rotate(1., { 0, 0 }); l4.translate(offset); REQUIRE(l.perpendicular_to(l3)); - REQUIRE(! l.perpendicular_to(l4)); + REQUIRE_FALSE(l.perpendicular_to(l4)); } TEST_CASE("Polygon::contains works properly", "[Geometry]"){ @@ -125,7 +125,7 @@ SCENARIO("polygon_is_convex works") { WHEN("Polygon is convex clockwise") { Polygon cw_square { { {0, 0}, {0,10}, {10,10}, {10,0} } }; THEN("it is not convex") { - REQUIRE(! polygon_is_convex(cw_square)); + REQUIRE_FALSE(polygon_is_convex(cw_square)); } } WHEN("Polygon is convex counter-clockwise") { @@ -138,7 +138,7 @@ SCENARIO("polygon_is_convex works") { GIVEN("A concave polygon") { Polygon concave = { {0,0}, {10,0}, {10,10}, {0,10}, {0,6}, {4,6}, {4,4}, {0,4} }; THEN("It is not convex") { - REQUIRE(! polygon_is_convex(concave)); + REQUIRE_FALSE(polygon_is_convex(concave)); } } } @@ -380,14 +380,30 @@ SCENARIO("Polygon convex/concave detection", "[Geometry]"){ Point(200,100), Point(200,200), Point(100,200)})); - THEN("It has 4 convex points counterclockwise"){ - REQUIRE(square.concave_points(PI*4/3).size() == 0); - REQUIRE(square.convex_points(PI*2/3).size() == 4); + THEN("It has 4 convex points counterclockwise no angle limit"){ + auto cave_pts = square.concave_points(0); + auto vex_pts = square.convex_points(0); + CAPTURE(cave_pts); + CAPTURE(vex_pts); + REQUIRE(cave_pts.size() == 0); + REQUIRE(vex_pts.size() == 4); + } + THEN("It has 4 convex points counterclockwise with angle limit"){ + auto cave_pts = square.concave_points(PI*4/3); + auto vex_pts = square.convex_points(PI*4/3); + CAPTURE(cave_pts); + CAPTURE(vex_pts); + REQUIRE(cave_pts.size() == 0); + REQUIRE(vex_pts.size() == 4); } THEN("It has 4 concave points clockwise"){ square.make_clockwise(); - REQUIRE(square.concave_points(PI*4/3).size() == 4); - REQUIRE(square.convex_points(PI*2/3).size() == 0); + auto cave_pts = square.concave_points(0); + auto vex_pts = square.convex_points(0); + CAPTURE(cave_pts); + CAPTURE(vex_pts); + REQUIRE(cave_pts.size() == 4); + REQUIRE(vex_pts.size() == 0); } } GIVEN("A Square with an extra colinearvertex"){ @@ -399,7 +415,7 @@ SCENARIO("Polygon convex/concave detection", "[Geometry]"){ Point(100,100)})); THEN("It has 4 convex points counterclockwise"){ REQUIRE(square.concave_points(PI*4/3).size() == 0); - REQUIRE(square.convex_points(PI*2/3).size() == 4); + REQUIRE(square.convex_points(PI*4/3).size() == 4); } } GIVEN("A Square with an extra collinear vertex in different order"){ @@ -482,8 +498,8 @@ SCENARIO("Ported from xs/t/14_geometry.t", "[Geometry]"){ REQUIRE(Slic3r::Geometry::directions_parallel(0, M_PI, 0)); REQUIRE(Slic3r::Geometry::directions_parallel(0, 0, M_PI / 180)); REQUIRE(Slic3r::Geometry::directions_parallel(0, M_PI, M_PI / 180)); - REQUIRE(! Slic3r::Geometry::directions_parallel(M_PI /2, M_PI, 0)); - REQUIRE(! Slic3r::Geometry::directions_parallel(M_PI /2, PI, M_PI /180)); + REQUIRE_FALSE(Slic3r::Geometry::directions_parallel(M_PI /2, M_PI, 0)); + REQUIRE_FALSE(Slic3r::Geometry::directions_parallel(M_PI /2, PI, M_PI /180)); } } diff --git a/tests/libslic3r/test_placeholder_parser.cpp b/tests/libslic3r/test_placeholder_parser.cpp index 8c2408fe7b..f7b6748bff 100644 --- a/tests/libslic3r/test_placeholder_parser.cpp +++ b/tests/libslic3r/test_placeholder_parser.cpp @@ -6,33 +6,48 @@ using namespace Slic3r; SCENARIO("Placeholder parser scripting", "[PlaceholderParser]") { - PlaceholderParser parser; - auto config = DynamicPrintConfig::full_print_config(); + PlaceholderParser parser; + auto config = DynamicPrintConfig::full_print_config(); - config.set_deserialize_strict( { - { "printer_notes", " PRINTER_VENDOR_PRUSA3D PRINTER_MODEL_MK2 " }, + config.set_deserialize_strict( { + { "printer_notes", " PRINTER_VENDOR_PRUSA3D PRINTER_MODEL_MK2 " }, { "nozzle_diameter", "0.6;0.6;0.6;0.6" }, - { "temperature", "357;359;363;378" } + { "nozzle_temperature", "357;359;363;378" } }); - // To test the "first_layer_extrusion_width" over "first_layer_heigth". - // "first_layer_heigth" over "layer_height" is no more supported after first_layer_height was moved from PrintObjectConfig to PrintConfig. -// config.option("first_layer_height")->value = 150.; -// config.option("first_layer_height")->percent = true; - config.option("first_layer_height")->value = 1.5 * config.opt_float("layer_height"); - config.option("first_layer_height")->percent = false; - // To let the PlaceholderParser throw when referencing first_layer_speed if it is set to percent, as the PlaceholderParser does not know + // To let the PlaceholderParser throw when referencing initial_layer_line_width if it is set to percent, as the PlaceholderParser does not know // a percent to what. - config.option("first_layer_speed")->value = 50.; - config.option("first_layer_speed")->percent = true; + config.option("initial_layer_line_width")->value = 50.; + config.option("initial_layer_line_width")->percent = true; parser.apply_config(config); - parser.set("foo", 0); - parser.set("bar", 2); - parser.set("num_extruders", 4); + parser.set("foo", 0); + parser.set("bar", 2); + parser.set("num_extruders", 4); - SECTION("nested config options (legacy syntax)") { REQUIRE(parser.process("[temperature_[foo]]") == "357"); } - SECTION("array reference") { REQUIRE(parser.process("{temperature[foo]}") == "357"); } - SECTION("whitespaces and newlines are maintained") { REQUIRE(parser.process("test [ temperature_ [foo] ] \n hu") == "test 357 \n hu"); } + SECTION("nested config options (legacy syntax)") { REQUIRE(parser.process("[nozzle_temperature_[foo]]") == "357"); } + SECTION("array reference") { REQUIRE(parser.process("{nozzle_temperature[foo]}") == "357"); } + SECTION("whitespaces and newlines are maintained") { REQUIRE(parser.process("test [ nozzle_temperature_ [foo] ] \n hu") == "test 357 \n hu"); } + + // Test the "coFloatOrPercent" and "xxx_width" substitutions. + + // FIXME: Don't know what exactly this referred to in Prusaslicer or + // whether it should apply to Orca or not. + // {outer_wall_line_width} returns as its default value, 0. + // SECTION("outer_wall_line_width") { REQUIRE(std::stod(parser.process("{outer_wall_line_width}")) == Approx(0.67500001192092896)); } + SECTION("support_object_xy_distance") { REQUIRE(std::stod(parser.process("{support_object_xy_distance}")) == Approx(0.35)); } + // initial_layer_line_width ratio over nozzle_diameter. + // FIXME: either something else which correctly calculates a ratio should be here, + // or something else should be found for for the REQUIRE_THROWS + // SECTION("initial_layer_line_width") { REQUIRE(std::stod(parser.process("{initial_layer_line_width}")) == Approx(0.9)); } + // small_perimeter_speed ratio over outer_wall_speed + SECTION("small_perimeter_speed") { REQUIRE(std::stod(parser.process("{small_perimeter_speed}")) == Approx(30.)); } + // infill_wall_overlap over inner_wall_line_width + // FIXME: Shouldn't this return the calculated value and not the percentage 15? + // SECTION("infill_wall_overlap") { REQUIRE(std::stod(parser.process("{infill_wall_overlap}")) == Approx(0.16875)); } + + // If initial_layer_line_width is set to percent, then it is applied over respective extrusion types by overriding their respective speeds. + // The PlaceholderParser has no way to know which extrusion type the caller has in mind, therefore it throws. + SECTION("initial_layer_line_width throws failed to resolve the ratio_over dependencies") { REQUIRE_THROWS(parser.process("{initial_layer_line_width}")); } // Test the math expressions. SECTION("math: 2*3") { REQUIRE(parser.process("{2*3}") == "6"); } @@ -69,19 +84,6 @@ SCENARIO("Placeholder parser scripting", "[PlaceholderParser]") { SECTION("math: interpolate_table(13, (0, 0), (20, 20), (30, 20))") { REQUIRE(std::stod(parser.process("{interpolate_table(13, (0, 0), (20, 20), (30, 20))}")) == Approx(13.)); } SECTION("math: interpolate_table(25, (0, 0), (20, 20), (30, 20))") { REQUIRE(std::stod(parser.process("{interpolate_table(25, (0, 0), (20, 20), (30, 20))}")) == Approx(20.)); } - // Test the "coFloatOrPercent" and "xxx_extrusion_width" substitutions. - // first_layer_extrusion_width ratio_over first_layer_heigth. - SECTION("perimeter_extrusion_width") { REQUIRE(std::stod(parser.process("{perimeter_extrusion_width}")) == Approx(0.67500001192092896)); } - SECTION("first_layer_extrusion_width") { REQUIRE(std::stod(parser.process("{first_layer_extrusion_width}")) == Approx(0.9)); } - SECTION("support_material_xy_spacing") { REQUIRE(std::stod(parser.process("{support_material_xy_spacing}")) == Approx(0.3375)); } - // external_perimeter_speed over perimeter_speed - SECTION("external_perimeter_speed") { REQUIRE(std::stod(parser.process("{external_perimeter_speed}")) == Approx(30.)); } - // infill_overlap over perimeter_extrusion_width - SECTION("infill_overlap") { REQUIRE(std::stod(parser.process("{infill_overlap}")) == Approx(0.16875)); } - // If first_layer_speed is set to percent, then it is applied over respective extrusion types by overriding their respective speeds. - // The PlaceholderParser has no way to know which extrusion type the caller has in mind, therefore it throws. - SECTION("first_layer_speed") { REQUIRE_THROWS(parser.process("{first_layer_speed}")); } - // Test the boolean expression parser. auto boolean_expression = [&parser](const std::string& templ) { return parser.evaluate_boolean_expression(templ, parser.config()); };