mirror of
https://github.com/QIDITECH/QIDISlicer.git
synced 2026-01-30 15:38:43 +03:00
update src and test
This commit is contained in:
@@ -14,6 +14,7 @@ add_executable(${_TEST_NAME}_tests
|
||||
test_gaps.cpp
|
||||
test_gcode.cpp
|
||||
test_gcode_travels.cpp
|
||||
test_infill_above_bridges.cpp
|
||||
test_seam_perimeters.cpp
|
||||
test_seam_shells.cpp
|
||||
test_seam_geometry.cpp
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <catch2/benchmark/catch_benchmark_all.hpp>
|
||||
#include "test_data.hpp"
|
||||
|
||||
#include "libslic3r/GCode/SeamGeometry.hpp"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include "test_data.hpp"
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include <libslic3r/BridgeDetector.hpp>
|
||||
#include <libslic3r/Geometry.hpp>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <catch2/catch_approx.hpp>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
|
||||
@@ -7,6 +8,7 @@
|
||||
|
||||
using namespace Slic3r;
|
||||
using namespace Test;
|
||||
using namespace Catch;
|
||||
|
||||
constexpr bool debug_files{false};
|
||||
|
||||
@@ -168,7 +170,7 @@ TEST_CASE_METHOD(CancelObjectFixture, "Single extruder", "[CancelObject]") {
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(CancelObjectFixture, "Sequential print", "[CancelObject]") {
|
||||
config.set_deserialize_strict({{"complete_objects", 1}});
|
||||
config.set_deserialize_strict({{"complete_objects", 1} });
|
||||
|
||||
Print print;
|
||||
print.apply(two_cubes, config);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include "test_data.hpp"
|
||||
#include "libslic3r/ClipperZUtils.hpp"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include <numeric>
|
||||
#include <sstream>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include <exception>
|
||||
#include <numeric>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include "test_data.hpp"
|
||||
|
||||
#include "libslic3r/TriangleMesh.hpp"
|
||||
@@ -399,7 +400,6 @@ bool contains_regex(const std::string &data, const std::string &pattern)
|
||||
|
||||
} } // namespace Slic3r::Test
|
||||
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
SCENARIO("init_print functionality", "[test_data]") {
|
||||
GIVEN("A default config") {
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#include "libslic3r/GCode/SeamPlacer.hpp"
|
||||
#include "libslic3r/GCode/SeamAligned.hpp"
|
||||
|
||||
#include <filesystem>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace Slic3r { namespace Test {
|
||||
@@ -159,7 +159,7 @@ std::string slice(
|
||||
bool contains(const std::string &data, const std::string &pattern);
|
||||
bool contains_regex(const std::string &data, const std::string &pattern);
|
||||
|
||||
inline std::unique_ptr<Print> process_3mf(const std::filesystem::path &path) {
|
||||
inline std::unique_ptr<Print> process_3mf(const boost::filesystem::path &path) {
|
||||
DynamicPrintConfig config;
|
||||
auto print{std::make_unique<Print>()};
|
||||
Model model;
|
||||
@@ -176,7 +176,7 @@ inline std::unique_ptr<Print> process_3mf(const std::filesystem::path &path) {
|
||||
|
||||
static std::map<std::string, std::unique_ptr<Print>> prints_3mfs;
|
||||
// Lazy getter, to avoid processing the 3mf multiple times, it already takes ages.
|
||||
inline Print *get_print(const std::filesystem::path &file_path) {
|
||||
inline Print *get_print(const boost::filesystem::path &file_path) {
|
||||
if (!prints_3mfs.count(file_path.string())) {
|
||||
prints_3mfs[file_path.string()] = process_3mf(file_path.string());
|
||||
}
|
||||
@@ -204,8 +204,8 @@ inline void serialize_seam(std::ostream &output, const std::vector<std::vector<S
|
||||
|
||||
struct SeamsFixture
|
||||
{
|
||||
const std::filesystem::path file_3mf{
|
||||
std::filesystem::path{TEST_DATA_DIR} / std::filesystem::path{"seam_test_object.3mf"}};
|
||||
const boost::filesystem::path file_3mf{
|
||||
boost::filesystem::path{TEST_DATA_DIR} / boost::filesystem::path{"seam_test_object.3mf"}};
|
||||
const Print *print{Test::get_print(file_3mf)};
|
||||
const PrintObject *print_object{print->objects()[0]};
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <catch2/catch_approx.hpp>
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
@@ -11,6 +12,7 @@
|
||||
#include "test_data.hpp"
|
||||
|
||||
using namespace Slic3r;
|
||||
using namespace Catch;
|
||||
|
||||
static inline Slic3r::Point random_point(float LO=-50, float HI=50)
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include <numeric>
|
||||
#include <sstream>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <catch2/catch_approx.hpp>
|
||||
|
||||
#include <numeric>
|
||||
#include <sstream>
|
||||
@@ -12,6 +13,7 @@
|
||||
|
||||
using namespace Slic3r::Test;
|
||||
using namespace Slic3r;
|
||||
using namespace Catch;
|
||||
|
||||
SCENARIO("Extrusion width specifics", "[Flow]") {
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include "libslic3r/GCodeReader.hpp"
|
||||
#include "libslic3r/Geometry/ConvexHull.hpp"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <catch2/catch_approx.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <regex>
|
||||
@@ -10,6 +11,7 @@
|
||||
|
||||
using namespace Slic3r;
|
||||
using namespace Test;
|
||||
using namespace Catch;
|
||||
|
||||
constexpr bool debug_files = false;
|
||||
|
||||
@@ -61,7 +63,7 @@ TEST_CASE("Wiping speeds", "[GCode]") {
|
||||
INFO("Wipe moves don\'t retract faster than configured speed");
|
||||
CHECK(retract_speed < expected_retract_speed);
|
||||
}
|
||||
INFO("No wiping after layer change")
|
||||
INFO("No wiping after layer change");
|
||||
CHECK(!wiping_on_new_layer);
|
||||
}
|
||||
|
||||
@@ -115,12 +117,12 @@ std::optional<double> parse_axis(const std::string& line, const std::string& axi
|
||||
* - no travel moves go outside skirt
|
||||
* - temperatures are set correctly
|
||||
*/
|
||||
TEST_CASE("Extrusion, travels, temeperatures", "[GCode]") {
|
||||
TEST_CASE("Extrusion, travels, temperatures", "[GCode]") {
|
||||
DynamicPrintConfig config = Slic3r::DynamicPrintConfig::full_print_config();
|
||||
config.set_deserialize_strict({
|
||||
{ "gcode_comments", 1 },
|
||||
{ "complete_objects", 1 },
|
||||
{ "extrusion_axis", 'A' },
|
||||
{ "extrusion_axis", "A" },
|
||||
{ "start_gcode", "" }, // prevent any default extra Z move
|
||||
{ "layer_height", 0.4 },
|
||||
{ "first_layer_height", 0.4 },
|
||||
@@ -170,6 +172,11 @@ TEST_CASE("Extrusion, travels, temeperatures", "[GCode]") {
|
||||
}
|
||||
});
|
||||
|
||||
// Remove last travel_moves returning to origin
|
||||
if (travel_moves.back().x() == 0 && travel_moves.back().y() == 0) {
|
||||
travel_moves.pop_back();
|
||||
}
|
||||
|
||||
const unsigned layer_count = 20 / 0.4;
|
||||
INFO("Complete_objects generates the correct number of Z moves.");
|
||||
CHECK(z_moves.size() == layer_count * 2);
|
||||
@@ -188,20 +195,30 @@ TEST_CASE("Extrusion, travels, temeperatures", "[GCode]") {
|
||||
|
||||
|
||||
TEST_CASE("Used filament", "[GCode]") {
|
||||
DynamicPrintConfig config = Slic3r::DynamicPrintConfig::full_print_config();
|
||||
config.set_deserialize_strict({
|
||||
{ "retract_length", "1000000" },
|
||||
DynamicPrintConfig config1 = Slic3r::DynamicPrintConfig::full_print_config();
|
||||
config1.set_deserialize_strict({
|
||||
{ "retract_length", "0" },
|
||||
{ "use_relative_e_distances", 1 },
|
||||
{ "layer_gcode", "G92 E0\n" },
|
||||
});
|
||||
GCodeReader parser;
|
||||
Print print;
|
||||
Model model;
|
||||
Test::init_print({TestMesh::cube_20x20x20}, print, model, config);
|
||||
Test::gcode(print);
|
||||
Print print1;
|
||||
Model model1;
|
||||
Test::init_print({TestMesh::cube_20x20x20}, print1, model1, config1);
|
||||
Test::gcode(print1);
|
||||
|
||||
DynamicPrintConfig config2 = Slic3r::DynamicPrintConfig::full_print_config();
|
||||
config2.set_deserialize_strict({
|
||||
{ "retract_length", "999" },
|
||||
{ "use_relative_e_distances", 1 },
|
||||
{ "layer_gcode", "G92 E0\n" },
|
||||
});
|
||||
Print print2;
|
||||
Model model2;
|
||||
Test::init_print({TestMesh::cube_20x20x20}, print2, model2, config2);
|
||||
Test::gcode(print2);
|
||||
|
||||
INFO("Final retraction is not considered in total used filament");
|
||||
CHECK(print.print_statistics().total_used_filament > 0);
|
||||
CHECK(print1.print_statistics().total_used_filament == print2.print_statistics().total_used_filament);
|
||||
}
|
||||
|
||||
void check_m73s(Print& print){
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <catch2/matchers/catch_matchers_all.hpp>
|
||||
#include <catch2/catch_approx.hpp>
|
||||
#include <libslic3r/GCode/Travels.hpp>
|
||||
#include <libslic3r/ExPolygon.hpp>
|
||||
#include <libslic3r/GCode.hpp>
|
||||
@@ -6,8 +8,9 @@
|
||||
|
||||
using namespace Slic3r;
|
||||
using namespace Slic3r::GCode::Impl::Travels;
|
||||
using namespace Catch;
|
||||
|
||||
struct ApproxEqualsPoints : public Catch::MatcherBase<Points> {
|
||||
struct ApproxEqualsPoints : public Catch::Matchers::MatcherBase<Points> {
|
||||
ApproxEqualsPoints(const Points& expected, unsigned tolerance): expected(expected), tolerance(tolerance) {}
|
||||
bool match(const Points& points) const override {
|
||||
if (points.size() != expected.size()) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <catch2/catch_approx.hpp>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <catch2/matchers/catch_matchers.hpp>
|
||||
#include <catch2/matchers/catch_matchers_string.hpp>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "libslic3r/GCode/GCodeWriter.hpp"
|
||||
#include "libslic3r/GCodeReader.hpp"
|
||||
|
||||
using namespace Slic3r;
|
||||
using Catch::Approx;
|
||||
|
||||
SCENARIO("set_speed emits values with fixed-point output.", "[GCodeWriter]") {
|
||||
|
||||
@@ -12,23 +17,523 @@ SCENARIO("set_speed emits values with fixed-point output.", "[GCodeWriter]") {
|
||||
GCodeWriter writer;
|
||||
WHEN("set_speed is called to set speed to 99999.123") {
|
||||
THEN("Output string is G1 F99999.123") {
|
||||
REQUIRE_THAT(writer.set_speed(99999.123), Catch::Equals("G1 F99999.123\n"));
|
||||
REQUIRE_THAT(writer.set_speed(99999.123), Catch::Matchers::Equals("G1 F99999.123\n"));
|
||||
}
|
||||
}
|
||||
WHEN("set_speed is called to set speed to 1") {
|
||||
THEN("Output string is G1 F1") {
|
||||
REQUIRE_THAT(writer.set_speed(1.0), Catch::Equals("G1 F1\n"));
|
||||
REQUIRE_THAT(writer.set_speed(1.0), Catch::Matchers::Equals("G1 F1\n"));
|
||||
}
|
||||
}
|
||||
WHEN("set_speed is called to set speed to 203.200022") {
|
||||
THEN("Output string is G1 F203.2") {
|
||||
REQUIRE_THAT(writer.set_speed(203.200022), Catch::Equals("G1 F203.2\n"));
|
||||
REQUIRE_THAT(writer.set_speed(203.200022), Catch::Matchers::Equals("G1 F203.2\n"));
|
||||
}
|
||||
}
|
||||
WHEN("set_speed is called to set speed to 203.200522") {
|
||||
THEN("Output string is G1 F203.201") {
|
||||
REQUIRE_THAT(writer.set_speed(203.200522), Catch::Equals("G1 F203.201\n"));
|
||||
REQUIRE_THAT(writer.set_speed(203.200522), Catch::Matchers::Equals("G1 F203.201\n"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void check_gcode_feedrate(const std::string& gcode, const GCodeConfig& config, double expected_speed) {
|
||||
GCodeReader parser;
|
||||
parser.parse_buffer(gcode, [&] (Slic3r::GCodeReader &self, const Slic3r::GCodeReader::GCodeLine &line) {
|
||||
|
||||
const double travel_speed = config.opt_float("travel_speed");
|
||||
|
||||
const double feedrate = line.has_f() ? line.f() : self.f();
|
||||
CHECK(feedrate == Approx(expected_speed * 60).epsilon(GCodeFormatter::XYZ_EPSILON));
|
||||
|
||||
if (line.dist_Z(self) != 0) {
|
||||
// lift move or lift + change layer
|
||||
const double travel_speed_z = config.opt_float("travel_speed_z");
|
||||
if (travel_speed_z) {
|
||||
Vec3d move{line.dist_X(self), line.dist_Y(self), line.dist_Z(self)};
|
||||
double move_u_z = move.z() / move.norm();
|
||||
double travel_speed_ = std::abs(travel_speed_z / move_u_z);
|
||||
INFO("move Z feedrate Z component is less than or equal to travel_speed_z");
|
||||
CHECK(feedrate * std::abs(move_u_z) <= Approx(travel_speed_z * 60).epsilon(GCodeFormatter::XYZ_EPSILON));
|
||||
if (travel_speed_ < travel_speed) {
|
||||
INFO("move Z at travel speed Z");
|
||||
CHECK(feedrate == Approx(travel_speed_ * 60).epsilon(GCodeFormatter::XYZ_EPSILON));
|
||||
INFO("move Z feedrate Z component is equal to travel_speed_z");
|
||||
CHECK(feedrate * std::abs(move_u_z) == Approx(travel_speed_z * 60).epsilon(GCodeFormatter::XYZ_EPSILON));
|
||||
} else {
|
||||
INFO("move Z at travel speed");
|
||||
CHECK(feedrate == Approx(travel_speed * 60).epsilon(GCodeFormatter::XYZ_EPSILON));
|
||||
}
|
||||
} else {
|
||||
INFO("move Z at travel speed");
|
||||
CHECK(feedrate == Approx(travel_speed * 60).epsilon(GCodeFormatter::XYZ_EPSILON));
|
||||
}
|
||||
} else if (not line.extruding(self)) {
|
||||
// normal move
|
||||
INFO("move XY at travel speed");
|
||||
CHECK(feedrate == Approx(travel_speed * 60));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
SCENARIO("travel_speed_z is zero should use travel_speed.", "[GCodeWriter]") {
|
||||
GIVEN("GCodeWriter instance") {
|
||||
GCodeWriter writer;
|
||||
WHEN("travel_speed_z is set to 0") {
|
||||
writer.config.travel_speed.value = 1000;
|
||||
writer.config.travel_speed_z.value = 0;
|
||||
THEN("XYZ move feed rate should be equal to travel_speed") {
|
||||
const Vec3d move{10, 10, 10};
|
||||
const double speed = writer.config.travel_speed.value;
|
||||
const Vec3d p1 = writer.get_position();
|
||||
const Vec3d p2 = p1 + move;
|
||||
const std::string result = writer.travel_to_xyz(p2);
|
||||
check_gcode_feedrate(result, writer.config, speed);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SCENARIO("travel_speed_z is respected in Z speed component.", "[GCodeWriter]") {
|
||||
GIVEN("GCodeWriter instance") {
|
||||
GCodeWriter writer;
|
||||
WHEN("travel_speed_z is set to 10") {
|
||||
writer.config.travel_speed.value = 1000;
|
||||
writer.config.travel_speed_z.value = 10;
|
||||
THEN("Z move feed rate should be equal to travel_speed_z") {
|
||||
const Vec3d move{0, 0, 10};
|
||||
const double speed = writer.config.travel_speed_z.value;
|
||||
const Vec3d p1 = writer.get_position();
|
||||
const Vec3d p2 = p1 + move;
|
||||
const std::string result = writer.travel_to_xyz(p2);
|
||||
check_gcode_feedrate(result, writer.config, speed);
|
||||
}
|
||||
THEN("-Z move feed rate should be equal to travel_speed_z") {
|
||||
const Vec3d move{0, 0, -10};
|
||||
const double speed = writer.config.travel_speed_z.value;
|
||||
const Vec3d p1 = writer.get_position();
|
||||
const Vec3d p2 = p1 + move;
|
||||
const std::string result = writer.travel_to_xyz(p2);
|
||||
check_gcode_feedrate(result, writer.config, speed);
|
||||
}
|
||||
THEN("XY move feed rate should be equal to travel_speed") {
|
||||
const Vec3d move{10, 10, 0};
|
||||
const double speed = writer.config.travel_speed.value;
|
||||
const Vec3d p1 = writer.get_position();
|
||||
const Vec3d p2 = p1 + move;
|
||||
const std::string result = writer.travel_to_xyz(p2);
|
||||
check_gcode_feedrate(result, writer.config, speed);
|
||||
}
|
||||
THEN("-XY move feed rate should be equal to travel_speed") {
|
||||
const Vec3d move{-10, 10, 0};
|
||||
const double speed = writer.config.travel_speed.value;
|
||||
const Vec3d p1 = writer.get_position();
|
||||
const Vec3d p2 = p1 + move;
|
||||
const std::string result = writer.travel_to_xyz(p2);
|
||||
check_gcode_feedrate(result, writer.config, speed);
|
||||
}
|
||||
THEN("X-Y move feed rate should be equal to travel_speed") {
|
||||
const Vec3d move{10, -10, 0};
|
||||
const double speed = writer.config.travel_speed.value;
|
||||
const Vec3d p1 = writer.get_position();
|
||||
const Vec3d p2 = p1 + move;
|
||||
const std::string result = writer.travel_to_xyz(p2);
|
||||
check_gcode_feedrate(result, writer.config, speed);
|
||||
}
|
||||
THEN("-X-Y move feed rate should be equal to travel_speed") {
|
||||
const Vec3d move{-10, -10, 0};
|
||||
const double speed = writer.config.travel_speed.value;
|
||||
const Vec3d p1 = writer.get_position();
|
||||
const Vec3d p2 = p1 + move;
|
||||
const std::string result = writer.travel_to_xyz(p2);
|
||||
check_gcode_feedrate(result, writer.config, speed);
|
||||
}
|
||||
THEN("XZ move feed rate Z component should be equal to travel_speed_z") {
|
||||
const Vec3d move{10, 0, 10};
|
||||
const Vec3d move_u = move / move.norm();
|
||||
const double speed = std::abs(writer.config.travel_speed_z.value / move_u.z());
|
||||
Vec3d p1 = writer.get_position();
|
||||
Vec3d p2 = p1 + move;
|
||||
std::string result = writer.travel_to_xyz(p2);
|
||||
check_gcode_feedrate(result, writer.config, speed);
|
||||
}
|
||||
THEN("-XZ move feed rate Z component should be equal to travel_speed_z") {
|
||||
const Vec3d move{-10, 0, 10};
|
||||
const Vec3d move_u = move / move.norm();
|
||||
const double speed = std::abs(writer.config.travel_speed_z.value / move_u.z());
|
||||
const Vec3d p1 = writer.get_position();
|
||||
const Vec3d p2 = p1 + move;
|
||||
const std::string result = writer.travel_to_xyz(p2);
|
||||
check_gcode_feedrate(result, writer.config, speed);
|
||||
}
|
||||
THEN("X-Z move feed rate Z component should be equal to travel_speed_z") {
|
||||
const Vec3d move{10, 0, -10};
|
||||
const Vec3d move_u = move / move.norm();
|
||||
const double speed = std::abs(writer.config.travel_speed_z.value / move_u.z());
|
||||
const Vec3d p1 = writer.get_position();
|
||||
const Vec3d p2 = p1 + move;
|
||||
const std::string result = writer.travel_to_xyz(p2);
|
||||
check_gcode_feedrate(result, writer.config, speed);
|
||||
}
|
||||
THEN("-X-Z move feed rate Z component should be equal to travel_speed_z") {
|
||||
const Vec3d move{-10, 0, -10};
|
||||
const Vec3d move_u = move / move.norm();
|
||||
const double speed = std::abs(writer.config.travel_speed_z.value / move_u.z());
|
||||
const Vec3d p1 = writer.get_position();
|
||||
const Vec3d p2 = p1 + move;
|
||||
const std::string result = writer.travel_to_xyz(p2);
|
||||
check_gcode_feedrate(result, writer.config, speed);
|
||||
}
|
||||
THEN("YZ move feed rate Z component should be equal to travel_speed_z") {
|
||||
const Vec3d move{0, 10, 10};
|
||||
const Vec3d move_u = move / move.norm();
|
||||
const double speed = std::abs(writer.config.travel_speed_z.value / move_u.z());
|
||||
const Vec3d p1 = writer.get_position();
|
||||
const Vec3d p2 = p1 + move;
|
||||
const std::string result = writer.travel_to_xyz(p2);
|
||||
check_gcode_feedrate(result, writer.config, speed);
|
||||
}
|
||||
THEN("-YZ move feed rate Z component should be equal to travel_speed_z") {
|
||||
const Vec3d move{0, -10, 10};
|
||||
const Vec3d move_u = move / move.norm();
|
||||
const double speed = std::abs(writer.config.travel_speed_z.value / move_u.z());
|
||||
const Vec3d p1 = writer.get_position();
|
||||
const Vec3d p2 = p1 + move;
|
||||
const std::string result = writer.travel_to_xyz(p2);
|
||||
check_gcode_feedrate(result, writer.config, speed);
|
||||
}
|
||||
THEN("Y-Z move feed rate Z component should be equal to travel_speed_z") {
|
||||
const Vec3d move{0, 10, -10};
|
||||
const Vec3d move_u = move / move.norm();
|
||||
const double speed = std::abs(writer.config.travel_speed_z.value / move_u.z());
|
||||
const Vec3d p1 = writer.get_position();
|
||||
const Vec3d p2 = p1 + move;
|
||||
const std::string result = writer.travel_to_xyz(p2);
|
||||
check_gcode_feedrate(result, writer.config, speed);
|
||||
}
|
||||
THEN("-Y-Z move feed rate Z component should be equal to travel_speed_z") {
|
||||
const Vec3d move{0, -10, -10};
|
||||
const Vec3d move_u = move / move.norm();
|
||||
const double speed = std::abs(writer.config.travel_speed_z.value / move_u.z());
|
||||
const Vec3d p1 = writer.get_position();
|
||||
const Vec3d p2 = p1 + move;
|
||||
const std::string result = writer.travel_to_xyz(p2);
|
||||
check_gcode_feedrate(result, writer.config, speed);
|
||||
}
|
||||
THEN("XYZ move feed rate Z component should be equal to travel_speed_z") {
|
||||
const Vec3d move{10, 10, 10};
|
||||
const Vec3d move_u = move / move.norm();
|
||||
const double speed = std::abs(writer.config.travel_speed_z.value / move_u.z());
|
||||
const Vec3d p1 = writer.get_position();
|
||||
const Vec3d p2 = p1 + move;
|
||||
const std::string result = writer.travel_to_xyz(p2);
|
||||
check_gcode_feedrate(result, writer.config, speed);
|
||||
}
|
||||
THEN("-XYZ move feed rate Z component should be equal to travel_speed_z") {
|
||||
const Vec3d move{-10, 10, 10};
|
||||
const Vec3d move_u = move / move.norm();
|
||||
const double speed = std::abs(writer.config.travel_speed_z.value / move_u.z());
|
||||
const Vec3d p1 = writer.get_position();
|
||||
const Vec3d p2 = p1 + move;
|
||||
const std::string result = writer.travel_to_xyz(p2);
|
||||
check_gcode_feedrate(result, writer.config, speed);
|
||||
}
|
||||
THEN("X-YZ move feed rate Z component should be equal to travel_speed_z") {
|
||||
const Vec3d move{10, -10, 10};
|
||||
const Vec3d move_u = move / move.norm();
|
||||
const double speed = std::abs(writer.config.travel_speed_z.value / move_u.z());
|
||||
const Vec3d p1 = writer.get_position();
|
||||
const Vec3d p2 = p1 + move;
|
||||
const std::string result = writer.travel_to_xyz(p2);
|
||||
check_gcode_feedrate(result, writer.config, speed);
|
||||
}
|
||||
THEN("-X-YZ move feed rate Z component should be equal to travel_speed_z") {
|
||||
const Vec3d move{-10, -10, 10};
|
||||
const Vec3d move_u = move / move.norm();
|
||||
const double speed = std::abs(writer.config.travel_speed_z.value / move_u.z());
|
||||
const Vec3d p1 = writer.get_position();
|
||||
const Vec3d p2 = p1 + move;
|
||||
const std::string result = writer.travel_to_xyz(p2);
|
||||
check_gcode_feedrate(result, writer.config, speed);
|
||||
}
|
||||
THEN("XY-Z move feed rate Z component should be equal to travel_speed_z") {
|
||||
const Vec3d move{10, 10, -10};
|
||||
const Vec3d move_u = move / move.norm();
|
||||
const double speed = std::abs(writer.config.travel_speed_z.value / move_u.z());
|
||||
const Vec3d p1 = writer.get_position();
|
||||
const Vec3d p2 = p1 + move;
|
||||
const std::string result = writer.travel_to_xyz(p2);
|
||||
check_gcode_feedrate(result, writer.config, speed);
|
||||
}
|
||||
THEN("-XY-Z move feed rate Z component should be equal to travel_speed_z") {
|
||||
const Vec3d move{-10, 10, -10};
|
||||
const Vec3d move_u = move / move.norm();
|
||||
const double speed = std::abs(writer.config.travel_speed_z.value / move_u.z());
|
||||
const Vec3d p1 = writer.get_position();
|
||||
const Vec3d p2 = p1 + move;
|
||||
const std::string result = writer.travel_to_xyz(p2);
|
||||
check_gcode_feedrate(result, writer.config, speed);
|
||||
}
|
||||
THEN("X-Y-Z move feed rate Z component should be equal to travel_speed_z") {
|
||||
const Vec3d move{10, -10, -10};
|
||||
const Vec3d move_u = move / move.norm();
|
||||
const double speed = std::abs(writer.config.travel_speed_z.value / move_u.z());
|
||||
const Vec3d p1 = writer.get_position();
|
||||
const Vec3d p2 = p1 + move;
|
||||
const std::string result = writer.travel_to_xyz(p2);
|
||||
check_gcode_feedrate(result, writer.config, speed);
|
||||
}
|
||||
THEN("-X-Y-Z move feed rate Z component should be equal to travel_speed_z") {
|
||||
const Vec3d move{-10, -10, -10};
|
||||
const Vec3d move_u = move / move.norm();
|
||||
const double speed = std::abs(writer.config.travel_speed_z.value / move_u.z());
|
||||
const Vec3d p1 = writer.get_position();
|
||||
const Vec3d p2 = p1 + move;
|
||||
const std::string result = writer.travel_to_xyz(p2);
|
||||
check_gcode_feedrate(result, writer.config, speed);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("GCodeWriter emits G1 code correctly according to XYZF_EXPORT_DIGITS", "[GCodeWriter]") {
|
||||
GCodeWriter writer;
|
||||
|
||||
SECTION("Check quantize") {
|
||||
CHECK(GCodeFormatter::quantize(1.0,0) == 1.);
|
||||
CHECK(GCodeFormatter::quantize(0.0,0) == 0.);
|
||||
CHECK(GCodeFormatter::quantize(0.1,0) == 0);
|
||||
|
||||
CHECK(GCodeFormatter::quantize(1.0,1) == 1.);
|
||||
CHECK(GCodeFormatter::quantize(0.0,1) == 0.);
|
||||
CHECK(GCodeFormatter::quantize(0.1,1) == Approx(0.1));
|
||||
CHECK(GCodeFormatter::quantize(0.01,1) == 0.);
|
||||
|
||||
CHECK(GCodeFormatter::quantize(1.0,2) == 1.);
|
||||
CHECK(GCodeFormatter::quantize(0.0,2) == 0.);
|
||||
CHECK(GCodeFormatter::quantize(0.1,2) == Approx(0.1));
|
||||
CHECK(GCodeFormatter::quantize(0.01,2) == Approx(0.01));
|
||||
CHECK(GCodeFormatter::quantize(0.001,2) == 0.);
|
||||
|
||||
CHECK(GCodeFormatter::quantize(1.0,3) == 1.);
|
||||
CHECK(GCodeFormatter::quantize(0.0,3) == 0.);
|
||||
CHECK(GCodeFormatter::quantize(0.1,3) == Approx(0.1));
|
||||
CHECK(GCodeFormatter::quantize(0.01,3) == Approx(0.01));
|
||||
CHECK(GCodeFormatter::quantize(0.001,3) == Approx(0.001));
|
||||
CHECK(GCodeFormatter::quantize(0.0001,3) == 0.);
|
||||
|
||||
CHECK(GCodeFormatter::quantize(1.0,4) == 1.);
|
||||
CHECK(GCodeFormatter::quantize(0.0,4) == 0.);
|
||||
CHECK(GCodeFormatter::quantize(0.1,4) == Approx(0.1));
|
||||
CHECK(GCodeFormatter::quantize(0.01,4) == Approx(0.01));
|
||||
CHECK(GCodeFormatter::quantize(0.001,4) == Approx(0.001));
|
||||
CHECK(GCodeFormatter::quantize(0.0001,4) == Approx(0.0001));
|
||||
CHECK(GCodeFormatter::quantize(0.00001,4) == 0.);
|
||||
|
||||
CHECK(GCodeFormatter::quantize(1.0,5) == 1.);
|
||||
CHECK(GCodeFormatter::quantize(0.0,5) == 0.);
|
||||
CHECK(GCodeFormatter::quantize(0.1,5) == Approx(0.1));
|
||||
CHECK(GCodeFormatter::quantize(0.01,5) == Approx(0.01));
|
||||
CHECK(GCodeFormatter::quantize(0.001,5) == Approx(0.001));
|
||||
CHECK(GCodeFormatter::quantize(0.0001,5) == Approx(0.0001));
|
||||
CHECK(GCodeFormatter::quantize(0.00001,5) == Approx(0.00001));
|
||||
CHECK(GCodeFormatter::quantize(0.000001,5) == 0.);
|
||||
|
||||
CHECK(GCodeFormatter::quantize(1.0,6) == 1.);
|
||||
CHECK(GCodeFormatter::quantize(0.0,6) == 0.);
|
||||
CHECK(GCodeFormatter::quantize(0.1,6) == Approx(0.1));
|
||||
CHECK(GCodeFormatter::quantize(0.01,6) == Approx(0.01));
|
||||
CHECK(GCodeFormatter::quantize(0.001,6) == Approx(0.001));
|
||||
CHECK(GCodeFormatter::quantize(0.0001,6) == Approx(0.0001));
|
||||
CHECK(GCodeFormatter::quantize(0.00001,6) == Approx(0.00001));
|
||||
CHECK(GCodeFormatter::quantize(0.000001,6) == Approx(0.000001));
|
||||
CHECK(GCodeFormatter::quantize(0.0000001,6) == 0.);
|
||||
}
|
||||
|
||||
SECTION("Check pow_10") {
|
||||
// IEEE 754 floating point numbers can represent these numbers EXACTLY.
|
||||
CHECK(GCodeFormatter::pow_10[0] == 1.);
|
||||
CHECK(GCodeFormatter::pow_10[1] == 10.);
|
||||
CHECK(GCodeFormatter::pow_10[2] == 100.);
|
||||
CHECK(GCodeFormatter::pow_10[3] == 1000.);
|
||||
CHECK(GCodeFormatter::pow_10[4] == 10000.);
|
||||
CHECK(GCodeFormatter::pow_10[5] == 100000.);
|
||||
CHECK(GCodeFormatter::pow_10[6] == 1000000.);
|
||||
CHECK(GCodeFormatter::pow_10[7] == 10000000.);
|
||||
CHECK(GCodeFormatter::pow_10[8] == 100000000.);
|
||||
CHECK(GCodeFormatter::pow_10[9] == 1000000000.);
|
||||
}
|
||||
|
||||
SECTION("Check pow_10_inv") {
|
||||
// IEEE 754 floating point numbers can NOT represent these numbers exactly.
|
||||
CHECK(GCodeFormatter::pow_10_inv[0] == 1.);
|
||||
CHECK(GCodeFormatter::pow_10_inv[1] == 0.1);
|
||||
CHECK(GCodeFormatter::pow_10_inv[2] == 0.01);
|
||||
CHECK(GCodeFormatter::pow_10_inv[3] == 0.001);
|
||||
CHECK(GCodeFormatter::pow_10_inv[4] == 0.0001);
|
||||
CHECK(GCodeFormatter::pow_10_inv[5] == 0.00001);
|
||||
CHECK(GCodeFormatter::pow_10_inv[6] == 0.000001);
|
||||
CHECK(GCodeFormatter::pow_10_inv[7] == 0.0000001);
|
||||
CHECK(GCodeFormatter::pow_10_inv[8] == 0.00000001);
|
||||
CHECK(GCodeFormatter::pow_10_inv[9] == 0.000000001);
|
||||
}
|
||||
|
||||
SECTION("travel_to_z Emit G1 code for very significant movement") {
|
||||
double z1 = 10.0;
|
||||
std::string result1{ writer.travel_to_z(z1) };
|
||||
CHECK(result1 == "G1 Z10 F7800\n");
|
||||
|
||||
double z2 = z1 * 2;
|
||||
std::string result2{ writer.travel_to_z(z2) };
|
||||
CHECK(result2 == "G1 Z20 F7800\n");
|
||||
}
|
||||
|
||||
SECTION("travel_to_z Emit G1 code for significant movement") {
|
||||
double z1 = 10.0;
|
||||
std::string result1{ writer.travel_to_z(z1) };
|
||||
CHECK(result1 == "G1 Z10 F7800\n");
|
||||
|
||||
// This should test with XYZ_EPSILON exactly,
|
||||
// but IEEE 754 floating point numbers cannot pass the test.
|
||||
double z2 = z1 + GCodeFormatter::XYZ_EPSILON * 1.001;
|
||||
std::string result2{ writer.travel_to_z(z2) };
|
||||
|
||||
std::ostringstream oss;
|
||||
oss << "G1 Z"
|
||||
<< GCodeFormatter::quantize_xyzf(z2)
|
||||
<< " F7800\n";
|
||||
|
||||
CHECK(result2 == oss.str());
|
||||
}
|
||||
|
||||
SECTION("travel_to_z Do not emit G1 code for insignificant movement") {
|
||||
double z1 = 10.0;
|
||||
std::string result1{ writer.travel_to_z(z1) };
|
||||
CHECK(result1 == "G1 Z10 F7800\n");
|
||||
|
||||
// Movement smaller than XYZ_EPSILON
|
||||
double z2 = z1 + (GCodeFormatter::XYZ_EPSILON * 0.999);
|
||||
std::string result2{ writer.travel_to_z(z2) };
|
||||
CHECK(result2 == "");
|
||||
|
||||
double z3 = z1 + (GCodeFormatter::XYZ_EPSILON * 0.1);
|
||||
std::string result3{ writer.travel_to_z(z3) };
|
||||
CHECK(result3 == "");
|
||||
}
|
||||
|
||||
SECTION("travel_to_xyz Emit G1 code for very significant movement") {
|
||||
Vec3d v1{10.0, 10.0, 10.0};
|
||||
std::string result1{ writer.travel_to_xyz(v1) };
|
||||
CHECK(result1 == "G1 X10 Y10 Z10 F7800\n");
|
||||
|
||||
Vec3d v2 = v1 * 2;
|
||||
std::string result2{ writer.travel_to_xyz(v2) };
|
||||
CHECK(result2 == "G1 X20 Y20 Z20 F7800\n");
|
||||
}
|
||||
|
||||
SECTION("travel_to_xyz Emit G1 code for significant XYZ movement") {
|
||||
Vec3d v1{10.0, 10.0, 10.0};
|
||||
std::string result1{ writer.travel_to_xyz(v1) };
|
||||
CHECK(result1 == "G1 X10 Y10 Z10 F7800\n");
|
||||
|
||||
Vec3d v2 = v1;
|
||||
// This should test with XYZ_EPSILON exactly,
|
||||
// but IEEE 754 floating point numbers cannot pass the test.
|
||||
v2.array() += GCodeFormatter::XYZ_EPSILON * 1.001;
|
||||
std::string result2{ writer.travel_to_xyz(v2) };
|
||||
|
||||
std::ostringstream oss;
|
||||
oss << "G1 X"
|
||||
<< GCodeFormatter::quantize_xyzf(v2.x())
|
||||
<< " Y"
|
||||
<< GCodeFormatter::quantize_xyzf(v2.y())
|
||||
<< " Z"
|
||||
<< GCodeFormatter::quantize_xyzf(v2.z())
|
||||
<< " F7800\n";
|
||||
|
||||
CHECK(result2 == oss.str());
|
||||
}
|
||||
|
||||
SECTION("travel_to_xyz Emit G1 code for significant X movement") {
|
||||
Vec3d v1{10.0, 10.0, 10.0};
|
||||
std::string result1{ writer.travel_to_xyz(v1) };
|
||||
CHECK(result1 == "G1 X10 Y10 Z10 F7800\n");
|
||||
|
||||
Vec3d v2 = v1;
|
||||
// This should test with XYZ_EPSILON exactly,
|
||||
// but IEEE 754 floating point numbers cannot pass the test.
|
||||
v2.x() += GCodeFormatter::XYZ_EPSILON * 1.001;
|
||||
std::string result2{ writer.travel_to_xyz(v2) };
|
||||
|
||||
std::ostringstream oss;
|
||||
// Only X needs to be emitted in this case,
|
||||
// but this is how the code currently works.
|
||||
oss << "G1 X"
|
||||
<< GCodeFormatter::quantize_xyzf(v2.x())
|
||||
<< " Y"
|
||||
<< GCodeFormatter::quantize_xyzf(v2.y())
|
||||
<< " F7800\n";
|
||||
|
||||
CHECK(result2 == oss.str());
|
||||
}
|
||||
|
||||
SECTION("travel_to_xyz Emit G1 code for significant Y movement") {
|
||||
Vec3d v1{10.0, 10.0, 10.0};
|
||||
std::string result1{ writer.travel_to_xyz(v1) };
|
||||
CHECK(result1 == "G1 X10 Y10 Z10 F7800\n");
|
||||
|
||||
Vec3d v2 = v1;
|
||||
// This should test with XYZ_EPSILON exactly,
|
||||
// but IEEE 754 floating point numbers cannot pass the test.
|
||||
v2.y() += GCodeFormatter::XYZ_EPSILON * 1.001;
|
||||
std::string result2{ writer.travel_to_xyz(v2) };
|
||||
|
||||
std::ostringstream oss;
|
||||
// Only Y needs to be emitted in this case,
|
||||
// but this is how the code currently works.
|
||||
oss << "G1 X"
|
||||
<< GCodeFormatter::quantize_xyzf(v2.x())
|
||||
<< " Y"
|
||||
<< GCodeFormatter::quantize_xyzf(v2.y())
|
||||
<< " F7800\n";
|
||||
|
||||
CHECK(result2 == oss.str());
|
||||
}
|
||||
|
||||
SECTION("travel_to_xyz Emit G1 code for significant Z movement") {
|
||||
Vec3d v1{10.0, 10.0, 10.0};
|
||||
std::string result1{ writer.travel_to_xyz(v1) };
|
||||
CHECK(result1 == "G1 X10 Y10 Z10 F7800\n");
|
||||
|
||||
Vec3d v2 = v1;
|
||||
// This should test with XYZ_EPSILON exactly,
|
||||
// but IEEE 754 floating point numbers cannot pass the test.
|
||||
v2.z() += GCodeFormatter::XYZ_EPSILON * 1.001;
|
||||
std::string result2{ writer.travel_to_xyz(v2) };
|
||||
|
||||
std::ostringstream oss;
|
||||
oss << "G1 Z"
|
||||
<< GCodeFormatter::quantize_xyzf(v2.z())
|
||||
<< " F7800\n";
|
||||
|
||||
CHECK(result2 == oss.str());
|
||||
}
|
||||
|
||||
SECTION("travel_to_xyz Do not emit G1 code for insignificant movement") {
|
||||
Vec3d v1{10.0, 10.0, 10.0};
|
||||
std::string result1{ writer.travel_to_xyz(v1) };
|
||||
CHECK(result1 == "G1 X10 Y10 Z10 F7800\n");
|
||||
|
||||
// Movement smaller than XYZ_EPSILON
|
||||
Vec3d v2 = v1;
|
||||
v2.array() += GCodeFormatter::XYZ_EPSILON * 0.999;
|
||||
std::string result2{ writer.travel_to_xyz(v2) };
|
||||
CHECK(result2 == "");
|
||||
|
||||
Vec3d v3 = v1;
|
||||
v3.array() += GCodeFormatter::XYZ_EPSILON * 0.1;
|
||||
std::string result3{ writer.travel_to_xyz(v3) };
|
||||
CHECK(result3 == "");
|
||||
}
|
||||
}
|
||||
83
tests/fff_print/test_infill_above_bridges.cpp
Normal file
83
tests/fff_print/test_infill_above_bridges.cpp
Normal file
@@ -0,0 +1,83 @@
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <catch2/catch_approx.hpp>
|
||||
#include <libslic3r/InfillAboveBridges.hpp>
|
||||
|
||||
using namespace Slic3r;
|
||||
using Catch::Approx;
|
||||
|
||||
const ExPolygon square{
|
||||
Point::new_scale(0, 0),
|
||||
Point::new_scale(10, 0),
|
||||
Point::new_scale(10, 10),
|
||||
Point::new_scale(0, 10)
|
||||
};
|
||||
|
||||
ExPolygon translate(const ExPolygon &polygon, const Point &offset) {
|
||||
ExPolygons result{polygon};
|
||||
translate(result, offset);
|
||||
return result.front();
|
||||
}
|
||||
|
||||
constexpr bool debug_files{false};
|
||||
|
||||
void draw_surfaces(const PrepareInfill::SurfaceRefsByRegion &surfaces, std::string_view file_name) {
|
||||
using PrepareInfill::SurfaceCollectionRef;
|
||||
|
||||
SurfaceCollection to_display;
|
||||
for (const SurfaceCollectionRef &surface_collection : surfaces) {
|
||||
to_display.append(surface_collection.get());
|
||||
}
|
||||
to_display.export_to_svg(file_name.data(), false);
|
||||
}
|
||||
|
||||
TEST_CASE("Separate infill above bridges", "[PrepareInfill]") {
|
||||
ExPolygons layer_0_region_0_bridge{
|
||||
square
|
||||
};
|
||||
ExPolygons layer_0_region_0_internal{
|
||||
translate(square, Point::new_scale(10, 0))
|
||||
};
|
||||
ExPolygons layer_0_region_1_internal{
|
||||
translate(square, Point::new_scale(0, 10))
|
||||
};
|
||||
ExPolygons layer_0_region_1_bridge{
|
||||
translate(square, Point::new_scale(10, 10))
|
||||
};
|
||||
SurfaceCollection layer_0_region_0;
|
||||
layer_0_region_0.append(layer_0_region_0_bridge, stBottomBridge);
|
||||
layer_0_region_0.append(layer_0_region_0_internal, stInternal);
|
||||
SurfaceCollection layer_0_region_1;
|
||||
layer_0_region_1.append(layer_0_region_1_bridge, stBottomBridge);
|
||||
layer_0_region_1.append(layer_0_region_1_internal, stInternal);
|
||||
|
||||
PrepareInfill::SurfaceRefsByRegion layer_0{layer_0_region_0, layer_0_region_1};
|
||||
|
||||
ExPolygons layer_1_region_0_solid{
|
||||
translate(square, Point::new_scale(5, 5))
|
||||
};
|
||||
SurfaceCollection layer_1_region_0;
|
||||
layer_1_region_0.append(layer_1_region_0_solid, stInternalSolid);
|
||||
PrepareInfill::SurfaceRefsByRegion layer_1{layer_1_region_0};
|
||||
|
||||
if constexpr (debug_files) {
|
||||
draw_surfaces(layer_0, "layer_0.svg");
|
||||
}
|
||||
|
||||
PrepareInfill::separate_infill_above_bridges({layer_0, layer_1}, 0);
|
||||
|
||||
if constexpr (debug_files) {
|
||||
draw_surfaces(layer_1, "layer_1.svg");
|
||||
}
|
||||
|
||||
const Surfaces &result{layer_1.front().get().surfaces};
|
||||
REQUIRE(result.size() == 4);
|
||||
const double expected_area{scale_(5.0) * scale_(5.0)};
|
||||
CHECK(result[0].expolygon.contour.area() == Approx(expected_area));
|
||||
CHECK(result[0].surface_type == stInternalSolid);
|
||||
CHECK(result[1].expolygon.contour.area() == Approx(expected_area));
|
||||
CHECK(result[1].surface_type == stInternalSolid);
|
||||
CHECK(result[2].expolygon.contour.area() == Approx(expected_area));
|
||||
CHECK(result[2].surface_type == stSolidOverBridge);
|
||||
CHECK(result[3].expolygon.contour.area() == Approx(expected_area));
|
||||
CHECK(result[3].surface_type == stSolidOverBridge);
|
||||
}
|
||||
@@ -2,11 +2,13 @@
|
||||
* Ported from t/layers.t
|
||||
*/
|
||||
|
||||
#include <catch2/catch.hpp>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <catch2/catch_approx.hpp>
|
||||
#include "test_data.hpp"
|
||||
|
||||
using namespace Slic3r;
|
||||
using namespace Slic3r::Test;
|
||||
using namespace Catch;
|
||||
|
||||
void check_layers(const DynamicPrintConfig& config) {
|
||||
GCodeReader parser;
|
||||
@@ -27,10 +29,10 @@ void check_layers(const DynamicPrintConfig& config) {
|
||||
const double layer_height = config.opt_float("layer_height");
|
||||
INFO("Correct first layer height.");
|
||||
CHECK(z.at(0) == Approx(first_layer_height + z_offset));
|
||||
INFO("Correct second layer height")
|
||||
INFO("Correct second layer height");
|
||||
CHECK(z.at(1) == Approx(first_layer_height + layer_height + z_offset));
|
||||
|
||||
INFO("Correct layer height")
|
||||
INFO("Correct layer height");
|
||||
for (const double increment : tcb::span{increments}.subspan(1)) {
|
||||
CHECK(increment == Approx(layer_height));
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include "libslic3r/libslic3r.h"
|
||||
#include "libslic3r/Model.hpp"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include <numeric>
|
||||
#include <sstream>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include <numeric>
|
||||
#include <sstream>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include "libslic3r/libslic3r.h"
|
||||
#include "libslic3r/Print.hpp"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <catch2/catch_approx.hpp>
|
||||
|
||||
#include "libslic3r/libslic3r.h"
|
||||
#include "libslic3r/GCodeReader.hpp"
|
||||
@@ -10,6 +11,7 @@
|
||||
|
||||
using namespace Slic3r;
|
||||
using namespace Slic3r::Test;
|
||||
using namespace Catch;
|
||||
|
||||
boost::regex perimeters_regex("G1 X[-0-9.]* Y[-0-9.]* E[-0-9.]* ; perimeter");
|
||||
boost::regex infill_regex("G1 X[-0-9.]* Y[-0-9.]* E[-0-9.]* ; infill");
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <catch2/catch_approx.hpp>
|
||||
|
||||
#include "libslic3r/libslic3r.h"
|
||||
#include "libslic3r/Print.hpp"
|
||||
@@ -8,6 +9,7 @@
|
||||
|
||||
using namespace Slic3r;
|
||||
using namespace Slic3r::Test;
|
||||
using namespace Catch;
|
||||
|
||||
SCENARIO("PrintObject: object layer heights", "[PrintObject]") {
|
||||
GIVEN("20mm cube and default initial config, initial layer height of 2mm") {
|
||||
|
||||
@@ -2,10 +2,12 @@
|
||||
* Ported from t/retraction.t
|
||||
*/
|
||||
|
||||
#include <catch2/catch.hpp>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <catch2/catch_approx.hpp>
|
||||
|
||||
#include <libslic3r/GCodeReader.hpp>
|
||||
#include <libslic3r/Config.hpp>
|
||||
#include "libslic3r/GCodeReader.hpp"
|
||||
#include "libslic3r/GCode/GCodeWriter.hpp"
|
||||
#include "libslic3r/Config.hpp"
|
||||
|
||||
#include "test_data.hpp"
|
||||
#include <regex>
|
||||
@@ -13,6 +15,7 @@
|
||||
|
||||
using namespace Slic3r;
|
||||
using namespace Test;
|
||||
using namespace Catch;
|
||||
|
||||
constexpr bool debug_files {false};
|
||||
|
||||
@@ -59,6 +62,10 @@ void check_gcode(std::initializer_list<TestMesh> meshes, const DynamicPrintConfi
|
||||
const double retract_restart_extra = config.option<ConfigOptionFloats>("retract_restart_extra")->get_at(tool);
|
||||
const double retract_restart_extra_toolchange = config.option<ConfigOptionFloats>("retract_restart_extra_toolchange")->get_at(tool);
|
||||
|
||||
const double travel_speed = config.opt_float("travel_speed");
|
||||
|
||||
const double feedrate = line.has_f() ? line.f() : self.f();
|
||||
|
||||
if (line.dist_Z(self) != 0) {
|
||||
// lift move or lift + change layer
|
||||
const double retract_lift = config.option<ConfigOptionFloats>("retract_lift")->get_at(tool);
|
||||
@@ -77,7 +84,7 @@ void check_gcode(std::initializer_list<TestMesh> meshes, const DynamicPrintConfi
|
||||
lift_dist = line.dist_Z(self);
|
||||
}
|
||||
if (line.dist_Z(self) < 0) {
|
||||
INFO("Must be lifted before going down.")
|
||||
INFO("Must be lifted before going down.");
|
||||
CHECK(lifted);
|
||||
INFO("Going down by the same amount of the lift or by the amount needed to get to next layer");
|
||||
CHECK((
|
||||
@@ -87,9 +94,26 @@ void check_gcode(std::initializer_list<TestMesh> meshes, const DynamicPrintConfi
|
||||
lift_dist = 0;
|
||||
lifted = false;
|
||||
}
|
||||
const double feedrate = line.has_f() ? line.f() : self.f();
|
||||
INFO("move Z at travel speed");
|
||||
CHECK(feedrate == Approx(config.opt_float("travel_speed") * 60));
|
||||
const double travel_speed_z = config.opt_float("travel_speed_z");
|
||||
if (travel_speed_z) {
|
||||
Vec3d move{line.dist_X(self), line.dist_Y(self), line.dist_Z(self)};
|
||||
const double move_u_z = move.z() / move.norm();
|
||||
const double travel_speed_ = std::abs(travel_speed_z / move_u_z);
|
||||
INFO("move Z feedrate Z component is less than or equal to travel_speed_z");
|
||||
CHECK(feedrate * std::abs(move_u_z) <= Approx(travel_speed_z * 60).epsilon(GCodeFormatter::XYZ_EPSILON));
|
||||
if (travel_speed_ < travel_speed) {
|
||||
INFO("move Z at travel speed Z");
|
||||
CHECK(feedrate == Approx(travel_speed_ * 60).epsilon(GCodeFormatter::XYZ_EPSILON));
|
||||
INFO("move Z feedrate Z component is equal to travel_speed_z");
|
||||
CHECK(feedrate * std::abs(move_u_z) == Approx(travel_speed_z * 60).epsilon(GCodeFormatter::XYZ_EPSILON));
|
||||
} else {
|
||||
INFO("move Z at travel speed");
|
||||
CHECK(feedrate == Approx(travel_speed * 60).epsilon(GCodeFormatter::XYZ_EPSILON));
|
||||
}
|
||||
} else {
|
||||
INFO("move Z at travel speed");
|
||||
CHECK(feedrate == Approx(travel_speed * 60).epsilon(GCodeFormatter::XYZ_EPSILON));
|
||||
}
|
||||
}
|
||||
if (line.retracting(self)) {
|
||||
retracted[tool] = true;
|
||||
@@ -135,11 +159,6 @@ void test_slicing(std::initializer_list<TestMesh> meshes, DynamicPrintConfig& co
|
||||
check_gcode(meshes, config, duplicate);
|
||||
}
|
||||
|
||||
SECTION("Negative restart extra length") {
|
||||
config.set_deserialize_strict({{ "retract_restart_extra", "-1" }});
|
||||
check_gcode(meshes, config, duplicate);
|
||||
}
|
||||
|
||||
SECTION("Retract_lift") {
|
||||
config.set_deserialize_strict({{ "retract_lift", "1,2" }});
|
||||
check_gcode(meshes, config, duplicate);
|
||||
@@ -147,7 +166,7 @@ void test_slicing(std::initializer_list<TestMesh> meshes, DynamicPrintConfig& co
|
||||
|
||||
}
|
||||
|
||||
TEST_CASE("Slicing with retraction and lifing", "[retraction]") {
|
||||
TEST_CASE("Slicing with retraction and lifting", "[retraction]") {
|
||||
DynamicPrintConfig config = Slic3r::DynamicPrintConfig::full_print_config();
|
||||
config.set_deserialize_strict({
|
||||
{ "nozzle_diameter", "0.6,0.6,0.6,0.6" },
|
||||
@@ -176,6 +195,37 @@ TEST_CASE("Slicing with retraction and lifing", "[retraction]") {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Slicing with retraction and lifting with travel_speed_z=10", "[retraction]") {
|
||||
DynamicPrintConfig config = Slic3r::DynamicPrintConfig::full_print_config();
|
||||
config.set_deserialize_strict({
|
||||
{ "nozzle_diameter", "0.6,0.6,0.6,0.6" },
|
||||
{ "first_layer_height", config.opt_float("layer_height") },
|
||||
{ "first_layer_speed", "100%" },
|
||||
{ "start_gcode", "" }, // To avoid dealing with the nozzle lift in start G-code
|
||||
{ "retract_length", "1.5" },
|
||||
{ "retract_before_travel", "3" },
|
||||
{ "retract_layer_change", "1" },
|
||||
{ "only_retract_when_crossing_perimeters", 0 },
|
||||
{ "travel_speed", "600" },
|
||||
{ "travel_speed_z", "10" },
|
||||
});
|
||||
|
||||
SECTION("Standard run") {
|
||||
test_slicing({TestMesh::cube_20x20x20}, config);
|
||||
}
|
||||
SECTION("With duplicate cube") {
|
||||
test_slicing({TestMesh::cube_20x20x20}, config, 2);
|
||||
}
|
||||
SECTION("Dual extruder with multiple skirt layers") {
|
||||
config.set_deserialize_strict({
|
||||
{"infill_extruder", 2},
|
||||
{"skirts", 4},
|
||||
{"skirt_height", 3},
|
||||
});
|
||||
test_slicing({TestMesh::cube_20x20x20}, config);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Z moves", "[retraction]") {
|
||||
|
||||
DynamicPrintConfig config = Slic3r::DynamicPrintConfig::full_print_config();
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
#include <libslic3r/Point.hpp>
|
||||
#include <catch2/catch.hpp>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <catch2/catch_approx.hpp>
|
||||
#include <libslic3r/GCode/SeamAligned.hpp>
|
||||
#include "test_data.hpp"
|
||||
#include <fstream>
|
||||
|
||||
using namespace Slic3r;
|
||||
using namespace Slic3r::Seams;
|
||||
using namespace Catch;
|
||||
|
||||
constexpr bool debug_files{false};
|
||||
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
#include <libslic3r/Point.hpp>
|
||||
#include <catch2/catch.hpp>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <catch2/matchers/catch_matchers_vector.hpp>
|
||||
#include <catch2/catch_approx.hpp>
|
||||
#include <libslic3r/GCode/SeamGeometry.hpp>
|
||||
#include <libslic3r/Geometry.hpp>
|
||||
|
||||
using namespace Slic3r;
|
||||
using namespace Catch;
|
||||
|
||||
TEST_CASE("Lists mapping", "[Seams][SeamGeometry]") {
|
||||
// clang-format off
|
||||
@@ -123,50 +126,3 @@ TEST_CASE("Vertex angle is rotation agnostic", "[Seams][SeamGeometry]") {
|
||||
std::vector<double> rotated_angles = Seams::Geometry::get_vertex_angles(points, 0.1);
|
||||
CHECK(rotated_angles[1] == Approx(angles[1]));
|
||||
}
|
||||
|
||||
TEST_CASE("Calculate overhangs", "[Seams][SeamGeometry]") {
|
||||
const ExPolygon square{
|
||||
scaled(Vec2d{0.0, 0.0}),
|
||||
scaled(Vec2d{1.0, 0.0}),
|
||||
scaled(Vec2d{1.0, 1.0}),
|
||||
scaled(Vec2d{0.0, 1.0})
|
||||
};
|
||||
const std::vector<Vec2d> points{Seams::Geometry::unscaled(square.contour.points)};
|
||||
ExPolygon previous_layer{square};
|
||||
previous_layer.translate(scaled(Vec2d{-0.5, 0}));
|
||||
AABBTreeLines::LinesDistancer<Linef> previous_layer_distancer{
|
||||
to_unscaled_linesf({previous_layer})};
|
||||
const std::vector<double> overhangs{
|
||||
Seams::Geometry::get_overhangs(points, previous_layer_distancer, 0.5)};
|
||||
REQUIRE(overhangs.size() == points.size());
|
||||
CHECK_THAT(overhangs, Catch::Matchers::Approx(std::vector<double>{
|
||||
0.0, M_PI / 4.0, M_PI / 4.0, 0.0
|
||||
}));
|
||||
}
|
||||
|
||||
const Linesf lines{to_unscaled_linesf({ExPolygon{
|
||||
scaled(Vec2d{0.0, 0.0}),
|
||||
scaled(Vec2d{1.0, 0.0}),
|
||||
scaled(Vec2d{1.0, 1.0}),
|
||||
scaled(Vec2d{0.0, 1.0})
|
||||
}})};
|
||||
|
||||
TEST_CASE("Offset along loop lines forward", "[Seams][SeamGeometry]") {
|
||||
const std::optional<Seams::Geometry::PointOnLine> result{Seams::Geometry::offset_along_lines(
|
||||
{0.5, 0.0}, 0, lines, 3.9, Seams::Geometry::Direction1D::forward
|
||||
)};
|
||||
REQUIRE(result);
|
||||
const auto &[point, line_index] = *result;
|
||||
CHECK((scaled(point) - Point::new_scale(0.4, 0.0)).norm() < scaled(EPSILON));
|
||||
CHECK(line_index == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("Offset along loop lines backward", "[Seams][SeamGeometry]") {
|
||||
const std::optional<Seams::Geometry::PointOnLine> result{Seams::Geometry::offset_along_lines(
|
||||
{1.0, 0.5}, 1, lines, 1.8, Seams::Geometry::Direction1D::backward
|
||||
)};
|
||||
REQUIRE(result);
|
||||
const auto &[point, line_index] = *result;
|
||||
CHECK((scaled(point) - Point::new_scale(0.0, 0.3)).norm() < scaled(EPSILON));
|
||||
CHECK(line_index == 3);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
#include "libslic3r/GCode/SeamPerimeters.hpp"
|
||||
#include "libslic3r/Layer.hpp"
|
||||
#include "libslic3r/Point.hpp"
|
||||
#include <catch2/catch.hpp>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <catch2/catch_approx.hpp>
|
||||
#include <libslic3r/GCode/SeamGeometry.hpp>
|
||||
#include <libslic3r/Geometry.hpp>
|
||||
#include <fstream>
|
||||
@@ -11,26 +12,29 @@
|
||||
|
||||
using namespace Slic3r;
|
||||
using namespace Slic3r::Seams;
|
||||
using namespace Catch;
|
||||
|
||||
constexpr bool debug_files{false};
|
||||
|
||||
const ExPolygon square{
|
||||
scaled(Vec2d{0.0, 0.0}), scaled(Vec2d{1.0, 0.0}), scaled(Vec2d{1.0, 1.0}),
|
||||
scaled(Vec2d{0.0, 1.0})};
|
||||
|
||||
TEST_CASE("Oversample painted", "[Seams][SeamPerimeters]") {
|
||||
Perimeters::PerimeterPoints square(4);
|
||||
square[0].position = Vec2d{0.0, 0.0};
|
||||
square[1].position = Vec2d{1.0, 0.0};
|
||||
square[2].position = Vec2d{1.0, 1.0};
|
||||
square[3].position = Vec2d{0.0, 1.0};
|
||||
|
||||
auto is_painted{[](const Vec3f &position, float radius) {
|
||||
return (position - Vec3f{0.5, 0.0, 1.0}).norm() < radius;
|
||||
}};
|
||||
std::vector<Vec2d> points{Perimeters::Impl::oversample_painted(
|
||||
Seams::Geometry::unscaled(square.contour.points), is_painted, 1.0, 0.2
|
||||
Perimeters::PerimeterPoints points{Perimeters::Impl::oversample_painted(
|
||||
square, is_painted, 1.0, 0.2
|
||||
)};
|
||||
|
||||
REQUIRE(points.size() == 8);
|
||||
CHECK((points[1] - Vec2d{0.2, 0.0}).norm() == Approx(0.0));
|
||||
CHECK((points[1].position - Vec2d{0.2, 0.0}).norm() == Approx(0.0));
|
||||
|
||||
points = Perimeters::Impl::oversample_painted(
|
||||
Seams::Geometry::unscaled(square.contour.points), is_painted, 1.0, 0.199
|
||||
square, is_painted, 1.0, 0.199
|
||||
);
|
||||
CHECK(points.size() == 9);
|
||||
}
|
||||
@@ -39,24 +43,35 @@ TEST_CASE("Remove redundant points", "[Seams][SeamPerimeters]") {
|
||||
using Perimeters::PointType;
|
||||
using Perimeters::PointClassification;
|
||||
|
||||
std::vector<Vec2d> points{{0.0, 0.0}, {1.0, 0.0}, {2.0, 0.0}, {3.0, 0.0},
|
||||
{3.0, 1.0}, {3.0, 2.0}, {0.0, 2.0}};
|
||||
std::vector<PointType> point_types{PointType::common,
|
||||
PointType::enforcer, // Should keep this.
|
||||
PointType::enforcer, // Should keep this.
|
||||
PointType::blocker,
|
||||
PointType::blocker, // Should remove this.
|
||||
PointType::blocker, PointType::common};
|
||||
Perimeters::PerimeterPoints points(9);
|
||||
points[0].position = {0.0, 0.0};
|
||||
points[0].type = PointType::common;
|
||||
points[1].position = {1.0, 0.0};
|
||||
points[1].type = PointType::enforcer; // Should keep
|
||||
points[2].position = {2.0, 0.0};
|
||||
points[2].type = PointType::enforcer; // Should keep
|
||||
points[3].position = {3.0, 0.0};
|
||||
points[3].type = PointType::blocker;
|
||||
points[4].position = {3.0, 1.0};
|
||||
points[4].type = PointType::blocker; // Should remove
|
||||
points[5].position = {3.0, 1.1};
|
||||
points[5].type = PointType::blocker;
|
||||
points[6].position = {3.0, 1.2};
|
||||
points[6].type = PointType::blocker;
|
||||
points[6].classification = PointClassification::overhang; // Should keep
|
||||
points[7].position = {3.0, 2.0};
|
||||
points[7].type = PointType::blocker;
|
||||
points[8].position = {0.0, 2.0};
|
||||
points[8].type = PointType::common;
|
||||
|
||||
const auto [resulting_points, resulting_point_types]{
|
||||
Perimeters::Impl::remove_redundant_points(points, point_types, 0.1)};
|
||||
Perimeters::PerimeterPoints result{
|
||||
Perimeters::Impl::remove_redundant_points(points, 0.1)};
|
||||
|
||||
REQUIRE(resulting_points.size() == 6);
|
||||
REQUIRE(resulting_point_types.size() == 6);
|
||||
CHECK((resulting_points[3] - Vec2d{3.0, 0.0}).norm() == Approx(0.0));
|
||||
CHECK((resulting_points[4] - Vec2d{3.0, 2.0}).norm() == Approx(0.0));
|
||||
CHECK(resulting_point_types[3] == PointType::blocker);
|
||||
CHECK(resulting_point_types[4] == PointType::blocker);
|
||||
REQUIRE(result.size() == 8);
|
||||
CHECK((result[3].position - Vec2d{3.0, 0.0}).norm() == Approx(0.0));
|
||||
CHECK((result[4].position - Vec2d{3.0, 1.1}).norm() == Approx(0.0));
|
||||
CHECK(result[3].type == PointType::blocker);
|
||||
CHECK(result[4].type == PointType::blocker);
|
||||
}
|
||||
|
||||
TEST_CASE("Perimeter constructs KD trees", "[Seams][SeamPerimeters]") {
|
||||
@@ -89,8 +104,6 @@ TEST_CASE("Perimeter constructs KD trees", "[Seams][SeamPerimeters]") {
|
||||
CHECK(perimeter.common_points.embedded_points);
|
||||
}
|
||||
|
||||
using std::filesystem::path;
|
||||
|
||||
constexpr const char *to_string(Perimeters::PointType point_type) {
|
||||
using Perimeters::PointType;
|
||||
|
||||
@@ -182,3 +195,57 @@ TEST_CASE_METHOD(Test::SeamsFixture, "Create perimeters", "[Seams][SeamPerimeter
|
||||
serialize_shells(csv, shells);
|
||||
}
|
||||
}
|
||||
|
||||
using Dir = Seams::Geometry::Direction1D;
|
||||
|
||||
Perimeters::Perimeter get_perimeter(){
|
||||
Perimeters::Perimeter perimeter;
|
||||
perimeter.positions = {
|
||||
Vec2d{0.0, 0.0},
|
||||
Vec2d{1.0, 0.0},
|
||||
Vec2d{1.0, 1.0},
|
||||
Vec2d{0.0, 1.0}
|
||||
};
|
||||
return perimeter;
|
||||
}
|
||||
|
||||
TEST_CASE("Offset along perimeter forward", "[Seams][SeamPerimeters]") {
|
||||
const std::optional<Perimeters::PointOnPerimeter> result{Perimeters::offset_along_perimeter(
|
||||
{0, 1, {0.5, 0.0}}, get_perimeter(), 3.9, Dir::forward,
|
||||
[](const Perimeters::Perimeter &, const std::size_t) { return false; }
|
||||
)};
|
||||
REQUIRE(result);
|
||||
const auto &[previous_index, next_index, point] = *result;
|
||||
CHECK((scaled(point) - Point::new_scale(0.4, 0.0)).norm() < scaled(EPSILON));
|
||||
CHECK(previous_index == 0);
|
||||
CHECK(next_index == 1);
|
||||
}
|
||||
|
||||
TEST_CASE("Offset along perimeter backward", "[Seams][SeamPerimeters]") {
|
||||
const std::optional<Perimeters::PointOnPerimeter> result{Perimeters::offset_along_perimeter(
|
||||
{1, 2, {1.0, 0.5}}, get_perimeter(), 1.8, Dir::backward,
|
||||
[](const Perimeters::Perimeter &, const std::size_t) { return false; }
|
||||
)};
|
||||
REQUIRE(result);
|
||||
const auto &[previous_index, next_index, point] = *result;
|
||||
CHECK((scaled(point) - Point::new_scale(0.0, 0.3)).norm() < scaled(EPSILON));
|
||||
CHECK(previous_index == 3);
|
||||
CHECK(next_index == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("Offset along perimeter forward respects stop condition", "[Seams][SeamPerimeters]") {
|
||||
Perimeters::Perimeter perimeter{get_perimeter()};
|
||||
perimeter.point_types = std::vector<Perimeters::PointType>(perimeter.positions.size(), Perimeters::PointType::common);
|
||||
perimeter.point_types[2] = Perimeters::PointType::blocker;
|
||||
const std::optional<Perimeters::PointOnPerimeter> result{Perimeters::offset_along_perimeter(
|
||||
{0, 1, {0.5, 0.0}}, perimeter, 3.9, Dir::forward,
|
||||
[](const Perimeters::Perimeter &perimeter, const std::size_t index) {
|
||||
return perimeter.point_types[index] == Perimeters::PointType::blocker;
|
||||
}
|
||||
)};
|
||||
REQUIRE(result);
|
||||
const auto &[previous_index, next_index, point] = *result;
|
||||
CHECK((scaled(point) - Point::new_scale(1.0, 0.0)).norm() < scaled(EPSILON));
|
||||
CHECK(previous_index == 1);
|
||||
CHECK(next_index == 1);
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
#include <libslic3r/Point.hpp>
|
||||
#include <catch2/catch.hpp>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <libslic3r/GCode/SeamRandom.hpp>
|
||||
#include "test_data.hpp"
|
||||
#include <fstream>
|
||||
@@ -32,7 +32,7 @@ Perimeters::Perimeter get_perimeter() {
|
||||
}
|
||||
} // namespace RandomTest
|
||||
|
||||
double get_chi2_uniform(const std::vector<double> &data, double min, double max, const std::size_t bin_count) {
|
||||
double get_chi2_uniform(const std::vector<double> &data, const double min, const double max, const std::size_t bin_count) {
|
||||
std::vector<std::size_t> bins(bin_count);
|
||||
const double bin_size{(max - min) / bin_count};
|
||||
const double expected_frequncy{static_cast<double>(data.size()) / bin_count};
|
||||
@@ -62,7 +62,7 @@ TEST_CASE("Random is uniform", "[Seams][SeamRandom]") {
|
||||
return choice->position.x();
|
||||
});
|
||||
const std::size_t degrees_of_freedom{10};
|
||||
const double critical{18.307}; // dof 10, significance 0.05
|
||||
const double critical{29.588}; // dof 10, significance 0.001
|
||||
|
||||
CHECK(get_chi2_uniform(x_positions, 0.0, 1.0, degrees_of_freedom + 1) < critical);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include <libslic3r/Point.hpp>
|
||||
#include <catch2/catch.hpp>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <libslic3r/GCode/SeamRear.hpp>
|
||||
#include "test_data.hpp"
|
||||
#include <fstream>
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <catch2/catch_approx.hpp>
|
||||
#include <libslic3r/GCode/SeamScarf.hpp>
|
||||
#include <libslic3r/GCode/SmoothPath.hpp>
|
||||
|
||||
using namespace Slic3r;
|
||||
using Seams::Scarf::Impl::PathPoint;
|
||||
using namespace Catch;
|
||||
|
||||
TEST_CASE("Get path point", "[Seams][Scarf]") {
|
||||
using Seams::Scarf::Impl::get_path_point;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <catch2/catch_approx.hpp>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include "libslic3r/ClipperUtils.hpp"
|
||||
@@ -9,6 +10,7 @@
|
||||
|
||||
using namespace Slic3r;
|
||||
using namespace Slic3r::Seams;
|
||||
using namespace Catch;
|
||||
|
||||
struct ProjectionFixture
|
||||
{
|
||||
@@ -21,7 +23,12 @@ struct ProjectionFixture
|
||||
double extrusion_width{0.2};
|
||||
|
||||
ProjectionFixture() {
|
||||
extrusions.emplace_back(Polygon{extrusion_path}, extrusion_path.bounding_box(), extrusion_width, island_boundary);
|
||||
extrusions.emplace_back(
|
||||
Polygon{extrusion_path},
|
||||
extrusion_path.bounding_box(),
|
||||
extrusion_width, island_boundary,
|
||||
Seams::Geometry::Overhangs{}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include "libslic3r/GCodeReader.hpp"
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <catch2/catch_approx.hpp>
|
||||
|
||||
#include "libslic3r/GCodeReader.hpp"
|
||||
#include "libslic3r/Config.hpp"
|
||||
@@ -10,6 +11,7 @@
|
||||
|
||||
using namespace Slic3r::Test;
|
||||
using namespace Slic3r;
|
||||
using namespace Catch;
|
||||
|
||||
/// Helper method to find the tool used for the brim (always the first extrusion)
|
||||
static int get_brim_tool(const std::string &gcode)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include "libslic3r/GCodeReader.hpp"
|
||||
#include "libslic3r/Layer.hpp"
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include <numeric>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
|
||||
#include "test_data.hpp" // get access to init_print, etc
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include "libslic3r/TriangleMesh.hpp"
|
||||
#include "libslic3r/TriangleMeshSlicer.hpp"
|
||||
|
||||
Reference in New Issue
Block a user