Files
OrcaSlicer/tests/fff_print/test_flow.cpp
T
HanifKoh 84657ff11e Add Missing Includes Across the Remaining Sources and Tests (#16071)
* Ignore Clipper, libpng, mcut and Boost.Polygon Internals in clang-tidy

Each only works through a wrapper or umbrella header: libslic3r/clipper.hpp or clipper_z.hpp configure Clipper before including it, png.h pulls in libpng's config headers, and Boost.Polygon's headers only compile through polygon.hpp or voronoi.hpp.

* Ignore minilzo's Config Headers in clang-tidy

lzoconf.h and lzodefs.h are internal to minilzo.h, which is what the code includes.

* Add Missing Includes Across the Remaining Sources and Tests

Covers src/slic3r/Utils, src/slic3r/plugin, src/slic3r/Config, src/libvgcode, src/dev-utils, src/OrcaSlicer.cpp and tests/, the directories left after src/slic3r/GUI and src/libslic3r. Generated with clang-tidy misc-include-cleaner. libvgcode's own headers are included by relative path as in the rest of that library, and Catch2 and pybind11 with angle brackets as elsewhere in the repo.

* Make the GUI and Test Headers Compile on Their Own

Each now includes, or forward-declares, what it uses instead of relying on what its includers happened to include first. Headers that only compile on one platform, or that nothing built includes, are left alone.

* Keep Windows and nanosvg Setup Ahead of the Added Includes

OrcaSlicer.cpp and several tests set _WIN32_WINNT, WIN32_LEAN_AND_MEAN or NOMINMAX before including Windows.h, and the profile validator defines NANOSVG_IMPLEMENTATION before any libslic3r header. The added includes had landed above those blocks, which broke the Windows build.

* Add the GUI Includes the First Pass Missed

Covers headers that only became editable once they compiled on their own, and wx symbols whose suggested header changed as the clang-tidy ignore list grew after the src/slic3r/GUI pass.

* Keep the Added Test Includes Below the NOMINMAX Guard

test_marchingsquares.cpp and test_texture_displacement.cpp had includes inside #ifndef NOMINMAX, which the tests inherit as defined on Windows from libslic3r, so those were skipped there. .clang-tidy also ignores the MSVC STL and UCRT internals, Boost.Multiprecision's fwd.hpp and CPython's Windows include directory, as in #16068.
2026-10-03 13:45:21 +08:00

100 lines
4.2 KiB
C++

#include <catch2/catch_all.hpp>
#include <cmath>
#include <numeric>
#include <sstream>
#include <catch2/catch_test_macros.hpp>
#include <catch2/catch_approx.hpp>
#include "test_helpers.hpp" // get access to init_print, etc
#include "libslic3r/Config.hpp"
#include "libslic3r/Model.hpp"
#include "libslic3r/Config.hpp"
#include "libslic3r/GCodeReader.hpp"
#include "libslic3r/Flow.hpp"
#include "libslic3r/libslic3r.h"
using namespace Slic3r::Test;
using namespace Slic3r;
/// Test the expected behavior for auto-width,
/// spacing, etc
SCENARIO("Flow math for non-bridges", "[Flow]") {
GIVEN("Nozzle Diameter of 0.4, a desired width of 1mm and layer height of 0.5") {
ConfigOptionFloatOrPercent width(1.0, false);
float nozzle_diameter = 0.4f;
float layer_height = 0.4f;
// Spacing for non-bridges is has some overlap
THEN("External perimeter flow has spacing fixed to 1.125 * nozzle_diameter") {
auto flow = Flow::new_from_config_width(frExternalPerimeter, ConfigOptionFloatOrPercent(0, false), nozzle_diameter, layer_height);
REQUIRE(flow.spacing() == Catch::Approx(1.125 * nozzle_diameter - layer_height * (1.0 - PI / 4.0)));
}
THEN("Internal perimeter flow has spacing fixed to 1.125 * nozzle_diameter") {
auto flow = Flow::new_from_config_width(frPerimeter, ConfigOptionFloatOrPercent(0, false), nozzle_diameter, layer_height);
REQUIRE(flow.spacing() == Catch::Approx(1.125 *nozzle_diameter - layer_height * (1.0 - PI / 4.0)));
}
THEN("Spacing for supplied width is 0.8927f") {
auto flow = Flow::new_from_config_width(frExternalPerimeter, width, nozzle_diameter, layer_height);
REQUIRE(flow.spacing() == Catch::Approx(width.value - layer_height * (1.0 - PI / 4.0)));
flow = Flow::new_from_config_width(frPerimeter, width, nozzle_diameter, layer_height);
REQUIRE(flow.spacing() == Catch::Approx(width.value - layer_height * (1.0 - PI / 4.0)));
}
}
/// Check the min/max
GIVEN("Nozzle Diameter of 0.25") {
float nozzle_diameter = 0.25f;
float layer_height = 0.5f;
WHEN("layer height is set to 0.2") {
layer_height = 0.15f;
THEN("Max width is set.") {
auto flow = Flow::new_from_config_width(frPerimeter, ConfigOptionFloatOrPercent(0, false), nozzle_diameter, layer_height);
REQUIRE(flow.width() == Catch::Approx(1.125 * nozzle_diameter));
}
}
WHEN("Layer height is set to 0.25") {
layer_height = 0.25f;
THEN("Min width is set.") {
auto flow = Flow::new_from_config_width(frPerimeter, ConfigOptionFloatOrPercent(0, false), nozzle_diameter, layer_height);
REQUIRE(flow.width() == Catch::Approx(1.125 * nozzle_diameter));
}
}
}
#if 0
/// Check for an edge case in the maths where the spacing could be 0; original
/// math is 0.99. Slic3r issue #4654
GIVEN("Input spacing of 0.414159 and a total width of 2") {
double in_spacing = 0.414159;
double total_width = 2.0;
auto flow = Flow::new_from_spacing(1.0, 0.4, 0.3);
WHEN("solid_spacing() is called") {
double result = flow.solid_spacing(total_width, in_spacing);
THEN("Yielded spacing is greater than 0") {
REQUIRE(result > 0);
}
}
}
#endif
}
/// Spacing, width calculation for bridge extrusions
SCENARIO("Flow math for bridges", "[Flow]") {
GIVEN("Nozzle Diameter of 0.4, a desired width of 1mm and layer height of 0.5") {
float nozzle_diameter = 0.4f;
float bridge_flow = 1.0f;
WHEN("Flow role is frExternalPerimeter") {
auto flow = Flow::bridging_flow(nozzle_diameter * sqrt(bridge_flow), nozzle_diameter);
THEN("Bridge width is same as nozzle diameter") {
REQUIRE(flow.width() == Catch::Approx(nozzle_diameter));
}
THEN("Bridge spacing is same as nozzle diameter + BRIDGE_EXTRA_SPACING") {
REQUIRE(flow.spacing() == Catch::Approx(nozzle_diameter + BRIDGE_EXTRA_SPACING));
}
}
}
}