mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-04 14:20:58 +00:00
* 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.
222 lines
8.1 KiB
C++
222 lines
8.1 KiB
C++
#include <catch2/catch_all.hpp>
|
|
|
|
#include <cmath>
|
|
#include <iostream>
|
|
#include <boost/filesystem.hpp>
|
|
#include "libslic3r/libslic3r.h"
|
|
#include <vector>
|
|
#include "libslic3r/Polygon.hpp"
|
|
#include <math.h>
|
|
|
|
#include <catch2/catch_test_macros.hpp>
|
|
#include <catch2/catch_approx.hpp>
|
|
#include "libslic3r/ClipperUtils.hpp"
|
|
#include "libslic3r/ExPolygon.hpp"
|
|
#include "libslic3r/SVG.hpp"
|
|
|
|
using namespace Slic3r;
|
|
|
|
// #define TESTS_EXPORT_SVGS
|
|
|
|
SCENARIO("Constant offset", "[ClipperUtils]") {
|
|
coord_t s = 1000000;
|
|
GIVEN("20mm box") {
|
|
ExPolygon box20mm;
|
|
box20mm.contour.points = { Vec2crd{ 0, 0 }, Vec2crd{ 20 * s, 0 }, Vec2crd{ 20 * s, 20 * s}, Vec2crd{ 0, 20 * s} };
|
|
std::vector<float> deltas_plus(box20mm.contour.points.size(), 1. * s);
|
|
std::vector<float> deltas_minus(box20mm.contour.points.size(), - 1. * s);
|
|
Polygons output;
|
|
WHEN("Slic3r::offset()") {
|
|
for (double miter : { 2.0, 1.5, 1.2 }) {
|
|
DYNAMIC_SECTION("plus 1mm, miter " << miter << "x") {
|
|
output = Slic3r::offset(box20mm, 1. * s, jtMiter, miter);
|
|
#ifdef TESTS_EXPORT_SVGS
|
|
{
|
|
SVG svg(debug_out_path("constant_offset_box20mm_plus1mm_miter%lf.svg", miter).c_str(), get_extents(output));
|
|
svg.draw(box20mm, "blue");
|
|
svg.draw_outline(output, "black", coord_t(scale_(0.01)));
|
|
}
|
|
#endif
|
|
THEN("Area is 22^2mm2") {
|
|
REQUIRE(output.size() == 1);
|
|
REQUIRE(output.front().area() == Catch::Approx(22. * 22. * s * s));
|
|
}
|
|
}
|
|
DYNAMIC_SECTION("minus 1mm, miter " << miter << "x") {
|
|
output = Slic3r::offset(box20mm, - 1. * s, jtMiter, miter);
|
|
#ifdef TESTS_EXPORT_SVGS
|
|
{
|
|
SVG svg(debug_out_path("constant_offset_box20mm_minus1mm_miter%lf.svg", miter).c_str(), get_extents(output));
|
|
svg.draw(box20mm, "blue");
|
|
svg.draw_outline(output, "black", coord_t(scale_(0.01)));
|
|
}
|
|
#endif
|
|
THEN("Area is 18^2mm2") {
|
|
REQUIRE(output.size() == 1);
|
|
REQUIRE(output.front().area() == Catch::Approx(18. * 18. * s * s));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
WHEN("Slic3r::variable_offset_outer/inner") {
|
|
for (double miter : { 2.0, 1.5, 1.2 }) {
|
|
DYNAMIC_SECTION("plus 1mm, miter " << miter << "x") {
|
|
output = Slic3r::variable_offset_outer(box20mm, { deltas_plus }, miter);
|
|
#ifdef TESTS_EXPORT_SVGS
|
|
{
|
|
SVG svg(debug_out_path("variable_offset_box20mm_plus1mm_miter%lf.svg", miter).c_str(), get_extents(output));
|
|
svg.draw(box20mm, "blue");
|
|
svg.draw_outline(output, "black", coord_t(scale_(0.01)));
|
|
}
|
|
#endif
|
|
THEN("Area is 22^2mm2") {
|
|
REQUIRE(output.size() == 1);
|
|
REQUIRE(output.front().area() == Catch::Approx(22. * 22. * s * s));
|
|
}
|
|
}
|
|
DYNAMIC_SECTION("minus 1mm, miter " << miter << "x") {
|
|
output = Slic3r::variable_offset_inner(box20mm, { deltas_minus }, miter);
|
|
#ifdef TESTS_EXPORT_SVGS
|
|
{
|
|
SVG svg(debug_out_path("variable_offset_box20mm_minus1mm_miter%lf.svg", miter).c_str(), get_extents(output));
|
|
svg.draw(box20mm, "blue");
|
|
svg.draw_outline(output, "black", coord_t(scale_(0.01)));
|
|
}
|
|
#endif
|
|
THEN("Area is 18^2mm2") {
|
|
REQUIRE(output.size() == 1);
|
|
REQUIRE(output.front().area() == Catch::Approx(18. * 18. * s * s));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
GIVEN("20mm box with 10mm hole") {
|
|
ExPolygon box20mm;
|
|
box20mm.contour.points = { Vec2crd{ 0, 0 }, Vec2crd{ 20 * s, 0 }, Vec2crd{ 20 * s, 20 * s}, Vec2crd{ 0, 20 * s} };
|
|
box20mm.holes.emplace_back(Slic3r::Polygon({ Vec2crd{ 5 * s, 5 * s }, Vec2crd{ 5 * s, 15 * s}, Vec2crd{ 15 * s, 15 * s}, Vec2crd{ 15 * s, 5 * s } }));
|
|
std::vector<float> deltas_plus(box20mm.contour.points.size(), 1. * s);
|
|
std::vector<float> deltas_minus(box20mm.contour.points.size(), -1. * s);
|
|
ExPolygons output;
|
|
SECTION("Slic3r::offset()") {
|
|
for (double miter : { 2.0, 1.5, 1.2 }) {
|
|
DYNAMIC_SECTION("miter " << miter << "x") {
|
|
WHEN("plus 1mm") {
|
|
output = Slic3r::offset_ex(box20mm, 1. * s, jtMiter, miter);
|
|
#ifdef TESTS_EXPORT_SVGS
|
|
{
|
|
SVG svg(debug_out_path("constant_offset_box20mm_10mm_hole_plus1mm_miter%lf.svg", miter).c_str(), get_extents(output));
|
|
svg.draw(box20mm, "blue");
|
|
svg.draw_outline(to_polygons(output), "black", coord_t(scale_(0.01)));
|
|
}
|
|
#endif
|
|
THEN("Area is 22^2-8^2 mm2") {
|
|
REQUIRE(output.size() == 1);
|
|
REQUIRE(output.front().area() == Catch::Approx((22. * 22. - 8. * 8.) * s * s));
|
|
}
|
|
}
|
|
WHEN("minus 1mm") {
|
|
output = Slic3r::offset_ex(box20mm, - 1. * s, jtMiter, miter);
|
|
#ifdef TESTS_EXPORT_SVGS
|
|
{
|
|
SVG svg(debug_out_path("constant_offset_box20mm_10mm_hole_minus1mm_miter%lf.svg", miter).c_str(), get_extents(output));
|
|
svg.draw(box20mm, "blue");
|
|
svg.draw_outline(to_polygons(output), "black", coord_t(scale_(0.01)));
|
|
}
|
|
#endif
|
|
THEN("Area is 18^2-12^2 mm2") {
|
|
REQUIRE(output.size() == 1);
|
|
REQUIRE(output.front().area() == Catch::Approx((18. * 18. - 12. * 12.) * s * s));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
SECTION("Slic3r::variable_offset_outer()") {
|
|
for (double miter : { 2.0, 1.5, 1.2 }) {
|
|
DYNAMIC_SECTION("miter " << miter << "x") {
|
|
WHEN("plus 1mm") {
|
|
output = Slic3r::variable_offset_outer_ex(box20mm, { deltas_plus, deltas_plus }, miter);
|
|
#ifdef TESTS_EXPORT_SVGS
|
|
{
|
|
SVG svg(debug_out_path("variable_offset_box20mm_10mm_hole_plus1mm_miter%lf.svg", miter).c_str(), get_extents(output));
|
|
svg.draw(box20mm, "blue");
|
|
svg.draw_outline(to_polygons(output), "black", coord_t(scale_(0.01)));
|
|
}
|
|
#endif
|
|
THEN("Area is 22^2-8^2 mm2") {
|
|
REQUIRE(output.size() == 1);
|
|
REQUIRE(output.front().area() == Catch::Approx((22. * 22. - 8. * 8.) * s * s));
|
|
}
|
|
}
|
|
WHEN("minus 1mm") {
|
|
output = Slic3r::variable_offset_inner_ex(box20mm, { deltas_minus, deltas_minus }, miter);
|
|
#ifdef TESTS_EXPORT_SVGS
|
|
{
|
|
SVG svg(debug_out_path("variable_offset_box20mm_10mm_hole_minus1mm_miter%lf.svg", miter).c_str(), get_extents(output));
|
|
svg.draw(box20mm, "blue");
|
|
svg.draw_outline(to_polygons(output), "black", coord_t(scale_(0.01)));
|
|
}
|
|
#endif
|
|
THEN("Area is 18^2-12^2 mm2") {
|
|
REQUIRE(output.size() == 1);
|
|
REQUIRE(output.front().area() == Catch::Approx((18. * 18. - 12. * 12.) * s * s));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
GIVEN("20mm right angle triangle") {
|
|
ExPolygon triangle20mm;
|
|
triangle20mm.contour.points = { Vec2crd{ 0, 0 }, Vec2crd{ 20 * s, 0 }, Vec2crd{ 0, 20 * s } };
|
|
Polygons output;
|
|
double offset = 1.;
|
|
// Angle of the sharp corner bisector.
|
|
double angle_bisector = M_PI / 8.;
|
|
// Area tapered by mitering one sharp corner.
|
|
double area_tapered = pow(offset * (1. / sin(angle_bisector) - 1.), 2.) * tan(angle_bisector);
|
|
double l_triangle_side_offsetted = 20. + offset * (1. + 1. / tan(angle_bisector));
|
|
double area_offsetted = (0.5 * l_triangle_side_offsetted * l_triangle_side_offsetted - 2. * area_tapered) * s * s;
|
|
SECTION("Slic3r::offset()") {
|
|
for (double miter : { 2.0, 1.5, 1.2 }) {
|
|
DYNAMIC_SECTION("Outer offset 1mm, miter " << miter << "x") {
|
|
output = Slic3r::offset(triangle20mm, offset * s, jtMiter, 2.0);
|
|
#ifdef TESTS_EXPORT_SVGS
|
|
{
|
|
SVG svg(debug_out_path("constant_offset_triangle20mm_plus1mm_miter%lf.svg", miter).c_str(), get_extents(output));
|
|
svg.draw(triangle20mm, "blue");
|
|
svg.draw_outline(output, "black", coord_t(scale_(0.01)));
|
|
}
|
|
#endif
|
|
THEN("Area matches") {
|
|
REQUIRE(output.size() == 1);
|
|
REQUIRE(output.front().area() == Catch::Approx(area_offsetted));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
SECTION("Slic3r::variable_offset_outer()") {
|
|
std::vector<float> deltas(triangle20mm.contour.points.size(), 1. * s);
|
|
for (double miter : { 2.0, 1.5, 1.2 }) {
|
|
DYNAMIC_SECTION("Outer offset 1mm, miter " << miter << "x") {
|
|
output = Slic3r::variable_offset_outer(triangle20mm, { deltas }, 2.0);
|
|
#ifdef TESTS_EXPORT_SVGS
|
|
{
|
|
SVG svg(debug_out_path("variable_offset_triangle20mm_plus1mm_miter%lf.svg", miter).c_str(), get_extents(output));
|
|
svg.draw(triangle20mm, "blue");
|
|
svg.draw_outline(output, "black", coord_t(scale_(0.01)));
|
|
}
|
|
#endif
|
|
THEN("Area matches") {
|
|
REQUIRE(output.size() == 1);
|
|
REQUIRE(output.front().area() == Catch::Approx(area_offsetted));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|