Initial version of sl1 import with sla::Raster refactor.

This commit is contained in:
tamasmeszaros 2020-04-13 12:31:37 +02:00
parent 6eb51a1cca
commit 247fca6d55
39 changed files with 2136 additions and 1094 deletions

View file

@ -182,6 +182,8 @@ set(SLIC3R_GUI_SOURCES
Utils/HexFile.cpp
Utils/HexFile.hpp
Utils/Thread.hpp
Utils/SLAZipFileImport.hpp
Utils/SLAZipFileImport.cpp
)
if (APPLE)

View file

@ -19,6 +19,7 @@
#include "libslic3r/Utils.hpp"
#include "libslic3r/GCode/PostProcessor.hpp"
#include "libslic3r/GCode/PreviewData.hpp"
#include "libslic3r/Format/SL1.hpp"
#include "libslic3r/libslic3r.h"
#include <cassert>
@ -149,7 +150,7 @@ void BackgroundSlicingProcess::process_sla()
const std::string export_path = m_sla_print->print_statistics().finalize_output_path(m_export_path);
Zipper zipper(export_path);
m_sla_print->export_raster(zipper);
m_sla_archive.export_print(zipper, *m_sla_print);
if (m_thumbnail_cb != nullptr)
{
@ -473,9 +474,9 @@ void BackgroundSlicingProcess::prepare_upload()
m_upload_job.upload_data.upload_path = m_fff_print->print_statistics().finalize_output_path(m_upload_job.upload_data.upload_path.string());
} else {
m_upload_job.upload_data.upload_path = m_sla_print->print_statistics().finalize_output_path(m_upload_job.upload_data.upload_path.string());
Zipper zipper{source_path.string()};
m_sla_print->export_raster(zipper, m_upload_job.upload_data.upload_path.string());
m_sla_archive.export_print(zipper, *m_sla_print, m_upload_job.upload_data.upload_path.string());
if (m_thumbnail_cb != nullptr)
{
ThumbnailsList thumbnails;

View file

@ -10,6 +10,7 @@
#include <wx/event.h>
#include "libslic3r/Print.hpp"
#include "libslic3r/Format/SL1.hpp"
#include "slic3r/Utils/PrintHost.hpp"
@ -19,6 +20,7 @@ class DynamicPrintConfig;
class GCodePreviewData;
class Model;
class SLAPrint;
class SL1Archive;
class SlicingStatusEvent : public wxEvent
{
@ -47,7 +49,7 @@ public:
~BackgroundSlicingProcess();
void set_fff_print(Print *print) { m_fff_print = print; }
void set_sla_print(SLAPrint *print) { m_sla_print = print; }
void set_sla_print(SLAPrint *print) { m_sla_print = print; m_sla_print->set_printer(&m_sla_archive); }
void set_gcode_preview_data(GCodePreviewData *gpd) { m_gcode_preview_data = gpd; }
void set_thumbnail_cb(ThumbnailsGeneratorCallback cb) { m_thumbnail_cb = cb; }
@ -155,6 +157,7 @@ private:
GCodePreviewData *m_gcode_preview_data = nullptr;
// Callback function, used to write thumbnails into gcode.
ThumbnailsGeneratorCallback m_thumbnail_cb = nullptr;
SL1Archive m_sla_archive;
// Temporary G-code, there is one defined for the BackgroundSlicingProcess, differentiated from the other processes by a process ID.
std::string m_temp_output_path;
// Output path provided by the user. The output path may be set even if the slicing is running,

View file

@ -589,6 +589,11 @@ void MainFrame::init_menubar()
append_menu_item(import_menu, wxID_ANY, _(L("Import STL/OBJ/AM&F/3MF")) + dots + "\tCtrl+I", _(L("Load a model")),
[this](wxCommandEvent&) { if (m_plater) m_plater->add_model(); }, "import_plater", nullptr,
[this](){return m_plater != nullptr; }, this);
append_menu_item(import_menu, wxID_ANY, _(L("Import SL1 archive")) + dots, _(L("Load an SL1 output archive")),
[this](wxCommandEvent&) { if (m_plater) m_plater->import_sl1_archive(); }, "import_plater", nullptr,
[this](){return m_plater != nullptr; }, this);
import_menu->AppendSeparator();
append_menu_item(import_menu, wxID_ANY, _(L("Import &Config")) + dots + "\tCtrl+L", _(L("Load exported configuration file")),
[this](wxCommandEvent&) { load_config_file(); }, "import_config", nullptr,

View file

@ -27,6 +27,7 @@
#include <wx/numdlg.h>
#include <wx/debug.h>
#include <wx/busyinfo.h>
#include <wx/filename.h>
#include "libslic3r/libslic3r.h"
#include "libslic3r/Format/STL.hpp"
@ -72,6 +73,7 @@
#include "../Utils/PrintHost.hpp"
#include "../Utils/FixModelByWin10.hpp"
#include "../Utils/UndoRedo.hpp"
#include "../Utils/SLAZipFileImport.hpp"
#include "RemovableDriveManager.hpp"
#if ENABLE_NON_STATIC_CANVAS_MANAGER
#ifdef __APPLE__
@ -4251,6 +4253,27 @@ void Plater::add_model()
load_files(paths, true, false);
}
void Plater::import_sl1_archive()
{
wxFileDialog dlg(this, _(L("Choose SL1 archive:")),
from_u8(wxGetApp().app_config->get_last_dir()), "",
"SL1 archive files (*.sl1)|*.sl1;*.SL1;*.zip;*.ZIP",
wxFD_OPEN | wxFD_FILE_MUST_EXIST);
if (dlg.ShowModal() == wxID_OK) {
try {
TriangleMesh mesh = import_model_from_sla_zip(dlg.GetPath());
ModelObject * obj = p->model.add_object(wxFileName(dlg.GetPath()).GetName(), "", mesh);
if (obj) {
obj->add_instance();
update();
}
} catch (std::exception &ex) {
show_error(this, ex.what());
}
}
}
void Plater::extract_config_from_project()
{
wxString input_file;

View file

@ -159,6 +159,7 @@ public:
void load_project();
void load_project(const wxString& filename);
void add_model();
void import_sl1_archive();
void extract_config_from_project();
std::vector<size_t> load_files(const std::vector<boost::filesystem::path>& input_files, bool load_model = true, bool load_config = true);

View file

@ -0,0 +1,144 @@
#include "SLAZipFileImport.hpp"
#include "libslic3r/SlicesToTriangleMesh.hpp"
#include "libslic3r/MarchingSquares.hpp"
#include "libslic3r/ClipperUtils.hpp"
#include "libslic3r/MTUtils.hpp"
#include "libslic3r/PrintConfig.hpp"
#include <wx/wfstream.h>
#include <wx/zipstrm.h>
#include <wx/mstream.h>
#include <wx/sstream.h>
#include <wx/image.h>
#include <tbb/parallel_for.h>
#include <boost/property_tree/ini_parser.hpp>
namespace marchsq {
// Specialize this struct to register a raster type for the Marching squares alg
template<> struct _RasterTraits<wxImage> {
using Rst = wxImage;
// The type of pixel cell in the raster
using ValueType = uint8_t;
// Value at a given position
static uint8_t get(const Rst &rst, size_t row, size_t col) { return rst.GetRed(col, row); }
// Number of rows and cols of the raster
static size_t rows(const Rst &rst) { return rst.GetHeight(); }
static size_t cols(const Rst &rst) { return rst.GetWidth(); }
};
} // namespace marchsq
namespace Slic3r {
ExPolygons rings_to_expolygons(const std::vector<marchsq::Ring> &rings,
double px_w, double px_h)
{
ExPolygons polys; polys.reserve(rings.size());
for (const marchsq::Ring &ring : rings) {
Polygon poly; Points &pts = poly.points;
pts.reserve(ring.size());
for (const marchsq::Coord &crd : ring)
pts.emplace_back(scaled(crd.c * px_w), scaled(crd.r * px_h));
polys.emplace_back(poly);
}
// reverse the raster transformations
return union_ex(polys);
}
TriangleMesh import_model_from_sla_zip(const wxString &zipfname)
{
wxFileInputStream in(zipfname);
wxZipInputStream zip(in, wxConvUTF8);
std::map<std::string, wxMemoryOutputStream> files;
while (auto entry = std::unique_ptr<wxZipEntry>(zip.GetNextEntry())) {
auto fname = wxFileName(entry->GetName());
wxString name_lo = fname.GetFullName().Lower();
if (fname.IsDir() || name_lo.Contains("thumbnail")) continue;
if (!zip.OpenEntry(*entry))
throw std::runtime_error("Cannot read archive");
wxMemoryOutputStream &stream = files[name_lo.ToStdString()];
zip.Read(stream);
std::cout << name_lo << " read bytes: " << zip.LastRead() << std::endl;
if (!zip.LastRead()) std::cout << zip.GetLastError() << std::endl;
}
using boost::property_tree::ptree;
auto load_ini = [&files](const std::string &key, ptree &tree) {
auto it = files.find(key);
if (it != files.end()) {
wxString str;
wxStringOutputStream oss{&str};
wxMemoryInputStream inp{it->second};
oss.Write(inp);
std::stringstream iss(str.ToStdString());
boost::property_tree::read_ini(iss, tree);
files.erase(it);
} else {
throw std::runtime_error(key + " is missing");
}
};
ptree profile_tree, config;
load_ini("prusaslicer.ini", profile_tree);
load_ini("config.ini", config);
DynamicPrintConfig profile;
profile.load(profile_tree);
size_t disp_cols = profile.opt_int("display_pixels_x");
size_t disp_rows = profile.opt_int("display_pixels_y");
double disp_w = profile.opt_float("display_width");
double disp_h = profile.opt_float("display_height");
double px_w = disp_w / disp_cols;
double px_h = disp_h / disp_rows;
auto jobdir = config.get<std::string>("jobDir");
for (auto &c : jobdir) c = std::tolower(c);
for (auto it = files.begin(); it != files.end();)
if (it->first.find(jobdir) == std::string::npos ||
wxFileName(it->first).GetExt().Lower() != "png")
it = files.erase(it);
else ++it;
std::vector<ExPolygons> slices(files.size());
size_t i = 0;
for (auto &item : files) {
wxMemoryOutputStream &imagedata = item.second;
wxMemoryInputStream stream{imagedata};
wxImage img{stream, "image/png"};
std::cout << img.GetWidth() << " " << img.GetHeight() << std::endl;
auto rings = marchsq::execute(img, 128);
slices[i++] = rings_to_expolygons(rings, px_w, px_h);
}
TriangleMesh out;
if (!slices.empty()) {
double lh = profile.opt_float("layer_height");
double ilh = profile.opt_float("initial_layer_height");
out = slices_to_triangle_mesh(slices, 0, lh, ilh);
}
return out;
}
} // namespace Slic3r

View file

@ -0,0 +1,14 @@
#ifndef SLAZIPFILEIMPORT_HPP
#define SLAZIPFILEIMPORT_HPP
#include "libslic3r/TriangleMesh.hpp"
#include <wx/string.h>
namespace Slic3r {
TriangleMesh import_model_from_sla_zip(const wxString &zipfname);
}
#endif // SLAZIPFILEIMPORT_HPP