mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-07-26 20:32:06 +00:00
test: stop littering the working directory with debug files (#14785)
This commit is contained in:
@@ -491,17 +491,6 @@ SCENARIO("init_print functionality", "[test_helpers]") {
|
||||
THEN("Export gcode functions outputs text.") {
|
||||
REQUIRE(! Slic3r::Test::gcode(print).empty());
|
||||
}
|
||||
#if 0
|
||||
THEN("Embedded meshes exported") {
|
||||
std::string path = "C:\\data\\temp\\embedded_meshes\\";
|
||||
for (auto kvp : Slic3r::Test::mesh_names) {
|
||||
Slic3r::TriangleMesh m = mesh(kvp.first);
|
||||
std::string name = kvp.second;
|
||||
REQUIRE(Slic3r::store_stl((path + name + ".stl").c_str(), &m, true) == true);
|
||||
REQUIRE(Slic3r::store_obj((path + name + ".obj").c_str(), &m) == true);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#include "libslic3r/MultiNozzleUtils.hpp"
|
||||
#include "libslic3r/ProjectTask.hpp"
|
||||
|
||||
#include "test_utils.hpp"
|
||||
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
|
||||
#include <catch2/catch_tostring.hpp>
|
||||
@@ -109,8 +111,8 @@ SCENARIO("Export+Import geometry to/from 3mf file cycle", "[3mf]") {
|
||||
src_object->instances.front()->set_transformation(src_instance_transform);
|
||||
|
||||
WHEN("model is saved+loaded to/from 3mf file") {
|
||||
// save the model to 3mf file
|
||||
std::string test_file = std::string(TEST_DATA_DIR) + "/test_3mf/prusa.3mf";
|
||||
ScopedTemporaryFile temp(".3mf");
|
||||
const std::string test_file = temp.string();
|
||||
store_3mf(test_file.c_str(), &src_model, nullptr, false);
|
||||
|
||||
// load back the model from the 3mf file
|
||||
@@ -120,7 +122,6 @@ SCENARIO("Export+Import geometry to/from 3mf file cycle", "[3mf]") {
|
||||
ConfigSubstitutionContext ctxt{ ForwardCompatibilitySubstitutionRule::Disable };
|
||||
load_3mf(test_file.c_str(), dst_config, ctxt, &dst_model, false);
|
||||
}
|
||||
boost::filesystem::remove(test_file);
|
||||
|
||||
// compare meshes
|
||||
TriangleMesh src_mesh = src_model.mesh();
|
||||
@@ -522,7 +523,7 @@ SCENARIO("2D convex hull of sinking object", "[3mf][.]") {
|
||||
object->center_around_origin(false);
|
||||
|
||||
// This outputs the same exact data as the Prusaslicer test
|
||||
object->volumes[0]->mesh().write_ascii("/tmp/orca.ascii");
|
||||
write_debug_stl("3mf/orca.ascii", object->volumes[0]->mesh());
|
||||
|
||||
// set instance's attitude so that it is rotated, scaled (and sinking? how is it sinking? the rotation? does it matter if it's sinking?)
|
||||
ModelInstance* instance = object->instances[0];
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
#include "libslic3r/SLA/Hollowing.hpp"
|
||||
|
||||
#include "test_utils.hpp"
|
||||
|
||||
TEST_CASE("Hollow two overlapping spheres") {
|
||||
using namespace Slic3r;
|
||||
|
||||
@@ -16,6 +18,6 @@ TEST_CASE("Hollow two overlapping spheres") {
|
||||
|
||||
sla::hollow_mesh(sphere1, sla::HollowingConfig{}, sla::HollowingFlags::hfRemoveInsideTriangles);
|
||||
|
||||
sphere1.WriteOBJFile("twospheres.obj");
|
||||
write_debug_obj("hollowing/twospheres.obj", sphere1);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
|
||||
#include "libslic3r/TriangleMesh.hpp"
|
||||
|
||||
#include "test_utils.hpp"
|
||||
|
||||
using namespace Slic3r;
|
||||
|
||||
TEST_CASE("Split empty mesh", "[its_split][its]") {
|
||||
@@ -29,13 +31,15 @@ TEST_CASE("Split simple mesh consisting of one part", "[its_split][its]") {
|
||||
REQUIRE(res.front().vertices.size() == cube.vertices.size());
|
||||
}
|
||||
|
||||
// Dump each split part as its own OBJ for eyeballing; no-op in release.
|
||||
void debug_write_obj(const std::vector<indexed_triangle_set> &res, const std::string &name)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
size_t part_idx = 0;
|
||||
for (auto &part_its : res) {
|
||||
its_write_obj(part_its, (name + std::to_string(part_idx++) + ".obj").c_str());
|
||||
}
|
||||
for (const auto &part_its : res)
|
||||
write_debug_obj("indexed_triangle_set/" + name + std::to_string(part_idx++) + ".obj", part_its);
|
||||
#else
|
||||
(void) res; (void) name;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -260,7 +264,6 @@ TEST_CASE("Reduce one edge by Quadric Edge Collapse", "[its]")
|
||||
CHECK(is_similar(its_, its, cfg));
|
||||
}
|
||||
|
||||
#include "test_utils.hpp"
|
||||
TEST_CASE("Simplify mesh by Quadric edge collapse to 5%", "[its]")
|
||||
{
|
||||
TriangleMesh mesh = load_model("frog_legs.obj");
|
||||
|
||||
@@ -191,22 +191,21 @@ static void test_expolys(Rst&& rst, const ExPolygons& ref, Vec2i32 window, const
|
||||
for (const ExPolygon& expoly : ref)
|
||||
rst.draw(expoly);
|
||||
|
||||
std::fstream out(name + ".png", std::ios::out);
|
||||
out << rst.encode(sla::PNGRasterEncoder{});
|
||||
out.close();
|
||||
write_debug_stream("marchingsquares/" + name + ".png",
|
||||
[&] { return rst.encode(sla::PNGRasterEncoder{}); });
|
||||
|
||||
const ExPolygons bmp = rstGetPolys(rst);
|
||||
const ExPolygons ext = sla::raster_to_polygons(rst, window);
|
||||
|
||||
SVG svg(name + ".svg", raster_bb);
|
||||
svg.draw(bmp, "green");
|
||||
if (pixel_size.x() >= scale_(0.5))
|
||||
svg.draw_grid(raster_bb, "grey", scale_(0.05), pixel_size.x());
|
||||
if (window_size.x() >= scale_(1.0))
|
||||
svg.draw_grid(raster_bb, "grey", scale_(0.10), window_size.x());
|
||||
svg.draw_outline(ref, "red", "red", scale_(0.3));
|
||||
svg.draw_outline(ext, "blue", "blue");
|
||||
svg.Close();
|
||||
write_debug_svg("marchingsquares/" + name + ".svg", raster_bb, [&](SVG &svg) {
|
||||
svg.draw(bmp, "green");
|
||||
if (pixel_size.x() >= scale_(0.5))
|
||||
svg.draw_grid(raster_bb, "grey", scale_(0.05), pixel_size.x());
|
||||
if (window_size.x() >= scale_(1.0))
|
||||
svg.draw_grid(raster_bb, "grey", scale_(0.10), window_size.x());
|
||||
svg.draw_outline(ref, "red", "red", scale_(0.3));
|
||||
svg.draw_outline(ext, "blue", "blue");
|
||||
});
|
||||
|
||||
// Note all these areas are unscaled back to mm^2.
|
||||
double raster_area = unscaled(unscaled(area(bmp)));
|
||||
@@ -432,9 +431,7 @@ static void recreate_object_from_rasters(const std::string& objname, float lh)
|
||||
double disp_w = 120.96;
|
||||
double disp_h = 68.04;
|
||||
|
||||
#ifndef NDEBUG
|
||||
size_t cntr = 0;
|
||||
#endif
|
||||
for (ExPolygons& layer : layers) {
|
||||
auto rst = create_raster(res, disp_w, disp_h);
|
||||
|
||||
@@ -442,11 +439,8 @@ static void recreate_object_from_rasters(const std::string& objname, float lh)
|
||||
rst.draw(island);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
std::fstream out(objname + std::to_string(cntr) + ".png", std::ios::out);
|
||||
out << rst.encode(sla::PNGRasterEncoder{});
|
||||
out.close();
|
||||
#endif
|
||||
write_debug_stream("marchingsquares/" + objname + std::to_string(cntr) + ".png",
|
||||
[&] { return rst.encode(sla::PNGRasterEncoder{}); });
|
||||
|
||||
ExPolygons layer_ = sla::raster_to_polygons(rst);
|
||||
// float delta = scaled(std::min(rst.pixel_dimensions().h_mm,
|
||||
@@ -454,21 +448,19 @@ static void recreate_object_from_rasters(const std::string& objname, float lh)
|
||||
|
||||
// layer_ = expolygons_simplify(layer_, delta);
|
||||
|
||||
#ifndef NDEBUG
|
||||
SVG svg(objname + std::to_string(cntr) + ".svg", rstBBox(rst));
|
||||
svg.draw(layer_);
|
||||
svg.draw(layer, "green");
|
||||
svg.Close();
|
||||
#endif
|
||||
write_debug_svg("marchingsquares/" + objname + std::to_string(cntr) + ".svg", rstBBox(rst),
|
||||
[&](SVG &svg) {
|
||||
svg.draw(layer_);
|
||||
svg.draw(layer, "green");
|
||||
});
|
||||
|
||||
double layera = 0., layera_ = 0.;
|
||||
for (auto& p : layer)
|
||||
layera += p.area();
|
||||
for (auto& p : layer_)
|
||||
layera_ += p.area();
|
||||
#ifndef NDEBUG
|
||||
std::cout << cntr++ << std::endl;
|
||||
#endif
|
||||
++cntr;
|
||||
|
||||
double diff = std::abs(layera_ - layera);
|
||||
REQUIRE((diff <= 0.1 * layera || diff < scaled<double>(1.) * scaled<double>(1.)));
|
||||
|
||||
@@ -477,7 +469,7 @@ static void recreate_object_from_rasters(const std::string& objname, float lh)
|
||||
|
||||
indexed_triangle_set out = slices_to_mesh(layers, bb.min.z(), double(lh), double(lh));
|
||||
|
||||
its_write_obj(out, "out_from_rasters.obj");
|
||||
write_debug_obj("marchingsquares/out_from_rasters.obj", out);
|
||||
}
|
||||
|
||||
TEST_CASE("Recreate object from rasters", "[SL1Import]") { recreate_object_from_rasters("frog_legs.obj", 0.05f); }
|
||||
|
||||
@@ -229,7 +229,7 @@ TEST_CASE("halfcone test", "[halfcone]") {
|
||||
indexed_triangle_set m = sla::get_mesh(br, 45);
|
||||
|
||||
its_merge_vertices(m);
|
||||
its_write_obj(m, "Halfcone.obj");
|
||||
write_debug_obj("sla_print/Halfcone.obj", m);
|
||||
}
|
||||
|
||||
TEST_CASE("Test concurrency")
|
||||
|
||||
@@ -13,7 +13,7 @@ TEST_CASE("Overhanging point should be supported", "[SupGen]") {
|
||||
// Pyramid with 45 deg slope
|
||||
TriangleMesh mesh = make_pyramid(10.f, 10.f);
|
||||
mesh.rotate_y(float(PI));
|
||||
mesh.WriteOBJFile("Pyramid.obj");
|
||||
write_debug_obj("sla_supptgen/Pyramid.obj", mesh);
|
||||
|
||||
sla::SupportPoints pts = calc_support_pts(mesh);
|
||||
|
||||
@@ -55,7 +55,7 @@ TEST_CASE("Overhanging horizontal surface should be supported", "[SupGen]") {
|
||||
|
||||
TriangleMesh mesh = make_cube(width, depth, height);
|
||||
mesh.translate(0., 0., 5.); // lift up
|
||||
mesh.WriteOBJFile("Cuboid.obj");
|
||||
write_debug_obj("sla_supptgen/Cuboid.obj", mesh);
|
||||
|
||||
sla::SupportPointGenerator::Config cfg;
|
||||
sla::SupportPoints pts = calc_support_pts(mesh, cfg);
|
||||
@@ -81,7 +81,7 @@ TEST_CASE("Overhanging edge should be supported", "[SupGen]") {
|
||||
TriangleMesh mesh = make_prism(width, depth, height);
|
||||
mesh.rotate_y(float(PI)); // rotate on its back
|
||||
mesh.translate(0., 0., height);
|
||||
mesh.WriteOBJFile("Prism.obj");
|
||||
write_debug_obj("sla_supptgen/Prism.obj", mesh);
|
||||
|
||||
sla::SupportPointGenerator::Config cfg;
|
||||
sla::SupportPoints pts = calc_support_pts(mesh, cfg);
|
||||
@@ -106,7 +106,7 @@ TEST_CASE("Hollowed cube should be supported from the inside", "[SupGen][Hollowe
|
||||
|
||||
hollow_mesh(mesh, HollowingConfig{});
|
||||
|
||||
mesh.WriteOBJFile("cube_hollowed.obj");
|
||||
write_debug_obj("sla_supptgen/cube_hollowed.obj", mesh);
|
||||
|
||||
auto bb = mesh.bounding_box();
|
||||
auto h = float(bb.max.z() - bb.min.z());
|
||||
@@ -129,7 +129,7 @@ TEST_CASE("Two parallel plates should be supported", "[SupGen][Hollowed]")
|
||||
mesh_high.translate(0., 0., 10.); // lift up
|
||||
mesh.merge(mesh_high);
|
||||
|
||||
mesh.WriteOBJFile("parallel_plates.obj");
|
||||
write_debug_obj("sla_supptgen/parallel_plates.obj", mesh);
|
||||
|
||||
sla::SupportPointGenerator::Config cfg;
|
||||
sla::SupportPoints pts = calc_support_pts(mesh, cfg);
|
||||
|
||||
@@ -47,8 +47,9 @@ void test_support_model_collision(const std::string &obj_filename,
|
||||
notouch = notouch && area(intersections) < PI * pinhead_r * pinhead_r;
|
||||
}
|
||||
|
||||
/*if (!notouch) */export_failed_case(support_slices, byproducts);
|
||||
|
||||
if (!notouch)
|
||||
export_failed_case(support_slices, byproducts);
|
||||
|
||||
REQUIRE(notouch);
|
||||
}
|
||||
|
||||
@@ -62,11 +63,11 @@ void export_failed_case(const std::vector<ExPolygons> &support_slices, const Sup
|
||||
std::stringstream ss;
|
||||
if (!intersections.empty()) {
|
||||
ss << byproducts.obj_fname << std::setprecision(4) << n << ".svg";
|
||||
SVG svg(ss.str());
|
||||
svg.draw(sup_slice, "green");
|
||||
svg.draw(mod_slice, "blue");
|
||||
svg.draw(intersections, "red");
|
||||
svg.Close();
|
||||
write_debug_svg("sla/" + ss.str(), [&](SVG &svg) {
|
||||
svg.draw(sup_slice, "green");
|
||||
svg.draw(mod_slice, "blue");
|
||||
svg.draw(intersections, "red");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,8 +75,8 @@ void export_failed_case(const std::vector<ExPolygons> &support_slices, const Sup
|
||||
byproducts.supporttree.retrieve_full_mesh(its);
|
||||
TriangleMesh m{its};
|
||||
m.merge(byproducts.input_mesh);
|
||||
m.WriteOBJFile((Catch::getResultCapture().getCurrentTestName() + "_" +
|
||||
byproducts.obj_fname).c_str());
|
||||
write_debug_obj("sla/" + Catch::getResultCapture().getCurrentTestName() +
|
||||
"_" + byproducts.obj_fname, m);
|
||||
}
|
||||
|
||||
void test_supports(const std::string &obj_filename,
|
||||
@@ -350,13 +351,11 @@ void check_raster_transformations(sla::RasterBase::Orientation o, sla::RasterBas
|
||||
REQUIRE((w < res.width_px && h < res.height_px));
|
||||
|
||||
auto px = raster.read_pixel(w, h);
|
||||
|
||||
if (px != FullWhite) {
|
||||
std::fstream outf("out.png", std::ios::out);
|
||||
|
||||
outf << raster.encode(sla::PNGRasterEncoder());
|
||||
}
|
||||
|
||||
|
||||
if (px != FullWhite)
|
||||
write_debug_stream("sla/raster_transform_mismatch.png",
|
||||
[&] { return raster.encode(sla::PNGRasterEncoder()); });
|
||||
|
||||
REQUIRE(px == FullWhite);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,9 +3,14 @@
|
||||
|
||||
#include <libslic3r/TriangleMesh.hpp>
|
||||
#include <libslic3r/Format/OBJ.hpp>
|
||||
#include <libslic3r/SVG.hpp>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include <cstdio>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
#if defined(WIN32) || defined(_WIN32)
|
||||
#define PATH_SEPARATOR R"(\)"
|
||||
#else
|
||||
@@ -44,4 +49,98 @@ private:
|
||||
boost::filesystem::path m_path;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Debug-only test artifacts
|
||||
//
|
||||
// Files a test dumps for inspection: a mesh, an SVG, or any streamable blob such
|
||||
// as a PNG. In debug builds each run writes to a fresh temp folder (path printed
|
||||
// once); the name may include a subfolder (e.g. "marchingsquares/foo.svg").
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// Maps name to a path under the run's temp folder, creating any parent dirs
|
||||
// (forward slashes work on Windows). Not gated, so only call it from a
|
||||
// write_debug_* helper or inside an #ifndef NDEBUG block.
|
||||
inline std::string debug_artifact_path(const std::string &name)
|
||||
{
|
||||
static const boost::filesystem::path root = [] {
|
||||
boost::filesystem::path dir = boost::filesystem::temp_directory_path()
|
||||
/ boost::filesystem::unique_path("orca-test-artifacts-%%%%-%%%%");
|
||||
boost::filesystem::create_directories(dir);
|
||||
std::printf("Debug test artifacts will be written to %s\n", dir.string().c_str());
|
||||
return dir;
|
||||
}();
|
||||
boost::filesystem::path full = root / name;
|
||||
boost::filesystem::create_directories(full.parent_path());
|
||||
return full.string();
|
||||
}
|
||||
|
||||
// Dump a mesh as OBJ.
|
||||
inline void write_debug_obj(const std::string &name, const Slic3r::TriangleMesh &mesh)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
mesh.WriteOBJFile(debug_artifact_path(name).c_str());
|
||||
#else
|
||||
(void) name; (void) mesh;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void write_debug_obj(const std::string &name, const indexed_triangle_set &its)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
its_write_obj(its, debug_artifact_path(name).c_str());
|
||||
#else
|
||||
(void) name; (void) its;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Dump a mesh as ASCII STL.
|
||||
inline void write_debug_stl(const std::string &name, const Slic3r::TriangleMesh &mesh)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
mesh.write_ascii(debug_artifact_path(name).c_str());
|
||||
#else
|
||||
(void) name; (void) mesh;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Draw an SVG artifact through a callback that receives the open SVG. Second
|
||||
// overload takes a BoundingBox when the drawing needs one.
|
||||
template<class Draw>
|
||||
inline void write_debug_svg(const std::string &name, Draw &&draw)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
Slic3r::SVG svg(debug_artifact_path(name));
|
||||
draw(svg);
|
||||
svg.Close();
|
||||
#else
|
||||
(void) name; (void) draw;
|
||||
#endif
|
||||
}
|
||||
|
||||
template<class Draw>
|
||||
inline void write_debug_svg(const std::string &name, const Slic3r::BoundingBox &bbox, Draw &&draw)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
Slic3r::SVG svg(debug_artifact_path(name), bbox);
|
||||
draw(svg);
|
||||
svg.Close();
|
||||
#else
|
||||
(void) name; (void) bbox; (void) draw;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Write a callback's result (e.g. raster.encode(sla::PNGRasterEncoder{})) to an
|
||||
// artifact. operator<< is resolved by ADL at the call site, so this header needn't
|
||||
// include the producer's headers.
|
||||
template<class Produce>
|
||||
inline void write_debug_stream(const std::string &name, Produce &&produce)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
std::ofstream out(debug_artifact_path(name), std::ios::out | std::ios::binary);
|
||||
out << produce();
|
||||
#else
|
||||
(void) name; (void) produce;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // SLIC3R_TEST_UTILS
|
||||
|
||||
Reference in New Issue
Block a user