Extend sla archive tests with read-back

This commit is contained in:
tamasmeszaros 2022-04-26 10:57:49 +02:00
parent 0025a65611
commit 784105f5ad
5 changed files with 112 additions and 52 deletions

View file

@ -8,22 +8,37 @@ struct indexed_triangle_set;
namespace Slic3r {
// A generic indicator for the quality of an imported model. Obviously, the
// original cannot be fully reconstructed.
enum class SLAImportQuality { Accurate, Balanced, Fast };
class MissingProfileError : public RuntimeError { using RuntimeError::RuntimeError; };
// Raised when the needed metadata cannot be retrieved or guessed from an archive
class MissingProfileError : public RuntimeError
{
using RuntimeError::RuntimeError;
};
// A shortname for status indication function.
// The argument is the status (from <0, 100>)
// Returns false if cancel was requested.
using ProgrFn = std::function<bool(int)>;
// Abstract interface for an archive reader. This needs to be implemented for
// every supported archive format.
class SLAArchiveReader {
public:
virtual ~SLAArchiveReader() = default;
// Read the profile and reconstruct the slices
virtual ConfigSubstitutions read(std::vector<ExPolygons> &slices,
DynamicPrintConfig &profile) = 0;
// Overload for reading only the profile contained in the archive (if present)
virtual ConfigSubstitutions read(DynamicPrintConfig &profile) = 0;
// Creates a reader instance based on the provided file path.
// Currently only considers the file extension.
static std::unique_ptr<SLAArchiveReader> create(
const std::string &fname,
SLAImportQuality quality = SLAImportQuality::Balanced,
@ -32,17 +47,22 @@ public:
// Get the names of currently known archive reader implementations
static const std::vector<const char *> & registered_archives();
// Get the default file extensions belonging to an archive format
// Get the understood file extensions belonging to an archive format
static std::vector<const char *> get_extensions(const char *archtype);
// Generic description (usable in GUI) about an archive format
static const char * get_description(const char *archtype);
};
class ReaderUnimplementedError : public RuntimeError { using RuntimeError::RuntimeError; };
ConfigSubstitutions import_sla_archive(const std::string &zipfname,
DynamicPrintConfig &out);
// Raised in import_sla_archive when a nullptr reader is returned by
// SLAArchiveReader::create()
class ReaderUnimplementedError : public RuntimeError
{
using RuntimeError::RuntimeError;
};
// Helper free functions to import an archive using the above interface.
// Can throw ReaderUnimplementedError or MissingProfileError
ConfigSubstitutions import_sla_archive(
const std::string &zipfname,
indexed_triangle_set &out,
@ -50,6 +70,11 @@ ConfigSubstitutions import_sla_archive(
SLAImportQuality quality = SLAImportQuality::Balanced,
const ProgrFn &progr = [](int) { return true; });
// Only reads the profile, doesn't reconstruct the model.
ConfigSubstitutions import_sla_archive(const std::string &zipfname,
DynamicPrintConfig &out);
} // namespace Slic3r
#endif // SLAARCHIVEREADER_HPP

View file

@ -123,8 +123,8 @@ void SLAImportJob::finalize(bool canceled, std::exception_ptr &eptr)
p->plater->get_notification_manager()->push_notification(
NotificationType::CustomNotification,
NotificationManager::NotificationLevel::WarningNotificationLevel,
_L("The imported SLA archive did not contain any presets. "
"The current SLA presets were used as fallback.").ToStdString());
_u8L("The imported SLA archive did not contain any presets. "
"The current SLA presets were used as fallback."));
}
if (p->sel != Sel::modelOnly) {
@ -146,9 +146,16 @@ void SLAImportJob::finalize(bool canceled, std::exception_ptr &eptr)
config.apply(SLAFullPrintConfig::defaults());
config += std::move(p->profile);
wxGetApp().preset_bundle->load_config_model(name, std::move(config));
p->plater->check_selected_presets_visibility(ptSLA);
wxGetApp().load_current_presets();
if (Preset::printer_technology(config) == ptSLA) {
wxGetApp().preset_bundle->load_config_model(name, std::move(config));
p->plater->check_selected_presets_visibility(ptSLA);
wxGetApp().load_current_presets();
} else {
p->plater->get_notification_manager()->push_notification(
NotificationType::CustomNotification,
NotificationManager::NotificationLevel::WarningNotificationLevel,
_u8L("The profile in the imported archive is corrupt and will not be loaded."));
}
}
if (!p->mesh.empty()) {

View file

@ -4,7 +4,7 @@ add_executable(${_TEST_NAME}_tests ${_TEST_NAME}_tests_main.cpp
sla_test_utils.hpp sla_test_utils.cpp
sla_supptgen_tests.cpp
sla_raycast_tests.cpp
sla_archive_export_tests.cpp)
sla_archive_readwrite_tests.cpp)
target_link_libraries(${_TEST_NAME}_tests test_common libslic3r)
set_property(TARGET ${_TEST_NAME}_tests PROPERTY FOLDER "tests")

View file

@ -1,40 +0,0 @@
#include <catch2/catch.hpp>
#include <test_utils.hpp>
#include "libslic3r/SLAPrint.hpp"
#include "libslic3r/Format/SLAArchiveWriter.hpp"
#include <boost/filesystem.hpp>
using namespace Slic3r;
TEST_CASE("Archive export test", "[sla_archives]") {
constexpr const char *PNAME = "20mm_cube";
for (auto &archname : SLAArchiveWriter::registered_archives()) {
INFO(std::string("Testing archive type: ") + archname);
SLAPrint print;
SLAFullPrintConfig fullcfg;
auto m = Model::read_from_file(TEST_DATA_DIR PATH_SEPARATOR + std::string(PNAME) + ".obj", nullptr);
fullcfg.set("sla_archive_format", archname);
fullcfg.set("supports_enable", false);
fullcfg.set("pad_enable", false);
DynamicPrintConfig cfg;
cfg.apply(fullcfg);
print.set_status_callback([](const PrintBase::SlicingStatus&) {});
print.apply(m, cfg);
print.process();
ThumbnailsList thumbnails;
auto outputfname = std::string("output.") + SLAArchiveWriter::get_extension(archname);
print.export_print(outputfname, thumbnails, PNAME);
// Not much can be checked about the archives...
REQUIRE(boost::filesystem::exists(outputfname));
}
}

View file

@ -0,0 +1,68 @@
#include <catch2/catch.hpp>
#include <test_utils.hpp>
#include "libslic3r/SLAPrint.hpp"
#include "libslic3r/TriangleMesh.hpp"
#include "libslic3r/Format/SLAArchiveWriter.hpp"
#include "libslic3r/Format/SLAArchiveReader.hpp"
#include <boost/filesystem.hpp>
using namespace Slic3r;
TEST_CASE("Archive export test", "[sla_archives]") {
constexpr const char *PNAME = "extruder_idler";
for (auto &archname : SLAArchiveWriter::registered_archives()) {
INFO(std::string("Testing archive type: ") + archname + " -- writing...");
SLAPrint print;
SLAFullPrintConfig fullcfg;
auto m = Model::read_from_file(TEST_DATA_DIR PATH_SEPARATOR + std::string(PNAME) + ".obj", nullptr);
fullcfg.printer_technology.setInt(ptSLA); // FIXME this should be ensured
fullcfg.set("sla_archive_format", archname);
fullcfg.set("supports_enable", false);
fullcfg.set("pad_enable", false);
DynamicPrintConfig cfg;
cfg.apply(fullcfg);
print.set_status_callback([](const PrintBase::SlicingStatus&) {});
print.apply(m, cfg);
print.process();
ThumbnailsList thumbnails;
auto outputfname = std::string("output.") + SLAArchiveWriter::get_extension(archname);
print.export_print(outputfname, thumbnails, PNAME);
// Not much can be checked about the archives...
REQUIRE(boost::filesystem::exists(outputfname));
double vol_written = m.mesh().volume();
auto readable_formats = SLAArchiveReader::registered_archives();
if (std::any_of(readable_formats.begin(), readable_formats.end(),
[&archname](const std::string &a) { return a == archname; })) {
INFO(std::string("Testing archive type: ") + archname + " -- reading back...");
indexed_triangle_set its;
DynamicPrintConfig cfg;
try {
import_sla_archive(outputfname, its, cfg);
} catch (...) {
REQUIRE(false);
}
REQUIRE(!cfg.empty());
REQUIRE(!its.empty());
double vol_read = its_volume(its);
double rel_err = std::abs(vol_written - vol_read) / vol_written;
REQUIRE(rel_err < 0.1);
}
}
}