From 19e1d877aa0c9d7517a0f5e0aca03838871e962c Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Fri, 24 Apr 2020 12:46:35 +0200 Subject: Don't use sla::EncodedRaster in SLAImport, revive opencsg sandbox --- src/slic3r/Utils/SLAImport.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'src/slic3r') diff --git a/src/slic3r/Utils/SLAImport.cpp b/src/slic3r/Utils/SLAImport.cpp index 442025a77..65ec46343 100644 --- a/src/slic3r/Utils/SLAImport.cpp +++ b/src/slic3r/Utils/SLAImport.cpp @@ -43,9 +43,11 @@ namespace Slic3r { namespace { +struct PNGBuffer { std::vector buf; std::string fname; }; + struct ArchiveData { boost::property_tree::ptree profile, config; - std::vector images; + std::vector images; }; static const constexpr char *CONFIG_FNAME = "config.ini"; @@ -66,7 +68,7 @@ boost::property_tree::ptree read_ini(const mz_zip_archive_file_stat &entry, return tree; } -sla::EncodedRaster read_png(const mz_zip_archive_file_stat &entry, +PNGBuffer read_png(const mz_zip_archive_file_stat &entry, MZ_Archive & zip, const std::string & name) { @@ -75,9 +77,8 @@ sla::EncodedRaster read_png(const mz_zip_archive_file_stat &entry, if (!mz_zip_reader_extract_file_to_mem(&zip.arch, entry.m_filename, buf.data(), buf.size(), 0)) throw std::runtime_error(zip.get_errorstr()); - - return sla::EncodedRaster(std::move(buf), - name.empty() ? entry.m_filename : name); + + return {std::move(buf), (name.empty() ? entry.m_filename : name)}; } ArchiveData extract_sla_archive(const std::string &zipfname, @@ -113,9 +114,9 @@ ArchiveData extract_sla_archive(const std::string &zipfname, if (boost::filesystem::path(name).extension().string() == ".png") { auto it = std::lower_bound( - arch.images.begin(), arch.images.end(), sla::EncodedRaster({}, name), - [](const sla::EncodedRaster &r1, const sla::EncodedRaster &r2) { - return std::less()(r1.extension(), r2.extension()); + arch.images.begin(), arch.images.end(), PNGBuffer{{}, name}, + [](const PNGBuffer &r1, const PNGBuffer &r2) { + return std::less()(r1.fname, r2.fname); }); arch.images.insert(it, read_png(entry, zip, name)); @@ -258,8 +259,8 @@ std::vector extract_slices_from_sla_archive( } } - auto &buf = arch.images[i]; - wxMemoryInputStream stream{buf.data(), buf.size()}; + PNGBuffer &png = arch.images[i]; + wxMemoryInputStream stream{png.buf.data(), png.buf.size()}; wxImage img{stream}; auto rings = marchsq::execute(img, 128, rstp.win); -- cgit v1.2.3 From 2bcd36d155d0fce0041faac6a89a3fe211830041 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Mon, 27 Apr 2020 18:43:47 +0200 Subject: PNG image read with libpng --- src/slic3r/Utils/SLAImport.cpp | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) (limited to 'src/slic3r') diff --git a/src/slic3r/Utils/SLAImport.cpp b/src/slic3r/Utils/SLAImport.cpp index 65ec46343..13ea60339 100644 --- a/src/slic3r/Utils/SLAImport.cpp +++ b/src/slic3r/Utils/SLAImport.cpp @@ -9,32 +9,31 @@ #include "libslic3r/PrintConfig.hpp" #include "libslic3r/SLA/RasterBase.hpp" #include "libslic3r/miniz_extension.hpp" +#include "libslic3r/PNGRead.hpp" #include #include #include -#include #include namespace marchsq { -// Specialize this struct to register a raster type for the Marching squares alg -template<> struct _RasterTraits { - using Rst = wxImage; - +template<> struct _RasterTraits { + using Rst = Slic3r::png::ImageGreyscale; + // 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); + return rst.get(row, col); } // 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(); } + static size_t rows(const Rst &rst) { return rst.rows; } + static size_t cols(const Rst &rst) { return rst.cols; } }; } // namespace marchsq @@ -44,7 +43,6 @@ namespace Slic3r { namespace { struct PNGBuffer { std::vector buf; std::string fname; }; - struct ArchiveData { boost::property_tree::ptree profile, config; std::vector images; @@ -69,8 +67,8 @@ boost::property_tree::ptree read_ini(const mz_zip_archive_file_stat &entry, } PNGBuffer read_png(const mz_zip_archive_file_stat &entry, - MZ_Archive & zip, - const std::string & name) + MZ_Archive & zip, + const std::string & name) { std::vector buf(entry.m_uncomp_size); @@ -259,9 +257,13 @@ std::vector extract_slices_from_sla_archive( } } - PNGBuffer &png = arch.images[i]; - wxMemoryInputStream stream{png.buf.data(), png.buf.size()}; - wxImage img{stream}; +// PNGBuffer &png = arch.images[i]; +// wxMemoryInputStream stream{png.buf.data(), png.buf.size()}; +// wxImage img{stream}; + + png::ImageGreyscale img; + png::ReadBuf rb{arch.images[i].buf.data(), arch.images[i].buf.size()}; + png::decode_png(rb, img); auto rings = marchsq::execute(img, 128, rstp.win); ExPolygons expolys = rings_to_expolygons(rings, rstp.px_w, rstp.px_h); -- cgit v1.2.3 From 769ee15475a3edc10c8dd29db8e853675091677e Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Tue, 28 Apr 2020 20:21:29 +0200 Subject: Move SLA import to libslic3r with png reading using libpng Also fix flipped object issue --- src/slic3r/CMakeLists.txt | 2 - src/slic3r/GUI/GUI_ObjectList.hpp | 2 +- src/slic3r/GUI/Jobs/SLAImportJob.cpp | 3 +- src/slic3r/Utils/SLAImport.cpp | 317 ----------------------------------- src/slic3r/Utils/SLAImport.hpp | 35 ---- 5 files changed, 3 insertions(+), 356 deletions(-) delete mode 100644 src/slic3r/Utils/SLAImport.cpp delete mode 100644 src/slic3r/Utils/SLAImport.hpp (limited to 'src/slic3r') diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt index 8a2672c77..b64cfdf4f 100644 --- a/src/slic3r/CMakeLists.txt +++ b/src/slic3r/CMakeLists.txt @@ -187,8 +187,6 @@ set(SLIC3R_GUI_SOURCES Utils/HexFile.cpp Utils/HexFile.hpp Utils/Thread.hpp - Utils/SLAImport.hpp - Utils/SLAImport.cpp ) if (APPLE) diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index aa5264b07..b59631d67 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -294,7 +294,7 @@ public: void load_part(ModelObject* model_object, std::vector> &volumes_info, ModelVolumeType type); void load_generic_subobject(const std::string& type_name, const ModelVolumeType type); void load_shape_object(const std::string &type_name); - void load_mesh_object(const TriangleMesh &mesh, const wxString &name); + void load_mesh_object(const TriangleMesh &mesh, const wxString &name); void del_object(const int obj_idx); void del_subobject_item(wxDataViewItem& item); void del_settings_from_config(const wxDataViewItem& parent_item); diff --git a/src/slic3r/GUI/Jobs/SLAImportJob.cpp b/src/slic3r/GUI/Jobs/SLAImportJob.cpp index 2d5d5b072..ae92bd698 100644 --- a/src/slic3r/GUI/Jobs/SLAImportJob.cpp +++ b/src/slic3r/GUI/Jobs/SLAImportJob.cpp @@ -1,10 +1,11 @@ #include "SLAImportJob.hpp" +#include "libslic3r/Format/SL1.hpp" + #include "slic3r/GUI/GUI.hpp" #include "slic3r/GUI/GUI_App.hpp" #include "slic3r/GUI/Plater.hpp" #include "slic3r/GUI/GUI_ObjectList.hpp" -#include "slic3r/Utils/SLAImport.hpp" #include "libslic3r/Model.hpp" #include "libslic3r/PresetBundle.hpp" diff --git a/src/slic3r/Utils/SLAImport.cpp b/src/slic3r/Utils/SLAImport.cpp deleted file mode 100644 index 13ea60339..000000000 --- a/src/slic3r/Utils/SLAImport.cpp +++ /dev/null @@ -1,317 +0,0 @@ -#include "SLAImport.hpp" - -#include - -#include "libslic3r/SlicesToTriangleMesh.hpp" -#include "libslic3r/MarchingSquares.hpp" -#include "libslic3r/ClipperUtils.hpp" -#include "libslic3r/MTUtils.hpp" -#include "libslic3r/PrintConfig.hpp" -#include "libslic3r/SLA/RasterBase.hpp" -#include "libslic3r/miniz_extension.hpp" -#include "libslic3r/PNGRead.hpp" - -#include -#include -#include - -#include - -namespace marchsq { - -template<> struct _RasterTraits { - using Rst = Slic3r::png::ImageGreyscale; - - // 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.get(row, col); - } - - // Number of rows and cols of the raster - static size_t rows(const Rst &rst) { return rst.rows; } - static size_t cols(const Rst &rst) { return rst.cols; } -}; - -} // namespace marchsq - -namespace Slic3r { - -namespace { - -struct PNGBuffer { std::vector buf; std::string fname; }; -struct ArchiveData { - boost::property_tree::ptree profile, config; - std::vector images; -}; - -static const constexpr char *CONFIG_FNAME = "config.ini"; -static const constexpr char *PROFILE_FNAME = "prusaslicer.ini"; - -boost::property_tree::ptree read_ini(const mz_zip_archive_file_stat &entry, - MZ_Archive & zip) -{ - std::string buf(size_t(entry.m_uncomp_size), '\0'); - - if (!mz_zip_reader_extract_file_to_mem(&zip.arch, entry.m_filename, - buf.data(), buf.size(), 0)) - throw std::runtime_error(zip.get_errorstr()); - - boost::property_tree::ptree tree; - std::stringstream ss(buf); - boost::property_tree::read_ini(ss, tree); - return tree; -} - -PNGBuffer read_png(const mz_zip_archive_file_stat &entry, - MZ_Archive & zip, - const std::string & name) -{ - std::vector buf(entry.m_uncomp_size); - - if (!mz_zip_reader_extract_file_to_mem(&zip.arch, entry.m_filename, - buf.data(), buf.size(), 0)) - throw std::runtime_error(zip.get_errorstr()); - - return {std::move(buf), (name.empty() ? entry.m_filename : name)}; -} - -ArchiveData extract_sla_archive(const std::string &zipfname, - const std::string &exclude) -{ - ArchiveData arch; - - // Little RAII - struct Arch: public MZ_Archive { - Arch(const std::string &fname) { - if (!open_zip_reader(&arch, fname)) - throw std::runtime_error(get_errorstr()); - } - - ~Arch() { close_zip_reader(&arch); } - } zip (zipfname); - - mz_uint num_entries = mz_zip_reader_get_num_files(&zip.arch); - - for (mz_uint i = 0; i < num_entries; ++i) - { - mz_zip_archive_file_stat entry; - - if (mz_zip_reader_file_stat(&zip.arch, i, &entry)) - { - std::string name = entry.m_filename; - boost::algorithm::to_lower(name); - - if (boost::algorithm::contains(name, exclude)) continue; - - if (name == CONFIG_FNAME) arch.config = read_ini(entry, zip); - if (name == PROFILE_FNAME) arch.profile = read_ini(entry, zip); - - if (boost::filesystem::path(name).extension().string() == ".png") { - auto it = std::lower_bound( - arch.images.begin(), arch.images.end(), PNGBuffer{{}, name}, - [](const PNGBuffer &r1, const PNGBuffer &r2) { - return std::less()(r1.fname, r2.fname); - }); - - arch.images.insert(it, read_png(entry, zip, name)); - } - } - } - - return arch; -} - -ExPolygons rings_to_expolygons(const std::vector &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); -} - -template void foreach_vertex(ExPolygon &poly, Fn &&fn) -{ - for (auto &p : poly.contour.points) fn(p); - for (auto &h : poly.holes) - for (auto &p : h.points) fn(p); -} - -void invert_raster_trafo(ExPolygons & expolys, - const sla::RasterBase::Trafo &trafo, - coord_t width, - coord_t height) -{ - for (auto &expoly : expolys) { - if (trafo.mirror_y) - foreach_vertex(expoly, [height](Point &p) {p.y() = height - p.y(); }); - - if (trafo.mirror_x) - foreach_vertex(expoly, [width](Point &p) {p.x() = width - p.x(); }); - - expoly.translate(-trafo.center_x, -trafo.center_y); - - if (trafo.flipXY) - foreach_vertex(expoly, [](Point &p) { std::swap(p.x(), p.y()); }); - - if ((trafo.mirror_x + trafo.mirror_y + trafo.flipXY) % 2) { - expoly.contour.reverse(); - for (auto &h : expoly.holes) h.reverse(); - } - } -} - -struct RasterParams { - sla::RasterBase::Trafo trafo; // Raster transformations - coord_t width, height; // scaled raster dimensions (not resolution) - double px_h, px_w; // pixel dimesions - marchsq::Coord win; // marching squares window size -}; - -RasterParams get_raster_params(const DynamicPrintConfig &cfg) -{ - auto *opt_disp_cols = cfg.option("display_pixels_x"); - auto *opt_disp_rows = cfg.option("display_pixels_y"); - auto *opt_disp_w = cfg.option("display_width"); - auto *opt_disp_h = cfg.option("display_height"); - auto *opt_mirror_x = cfg.option("display_mirror_x"); - auto *opt_mirror_y = cfg.option("display_mirror_y"); - auto *opt_orient = cfg.option>("display_orientation"); - - if (!opt_disp_cols || !opt_disp_rows || !opt_disp_w || !opt_disp_h || - !opt_mirror_x || !opt_mirror_y || !opt_orient) - throw std::runtime_error("Invalid SL1 file"); - - RasterParams rstp; - - rstp.px_w = opt_disp_w->value / (opt_disp_cols->value - 1); - rstp.px_h = opt_disp_h->value / (opt_disp_rows->value - 1); - - sla::RasterBase::Trafo trafo{opt_orient->value == sladoLandscape ? - sla::RasterBase::roLandscape : - sla::RasterBase::roPortrait, - {opt_mirror_x->value, opt_mirror_y->value}}; - - rstp.height = scaled(opt_disp_h->value); - rstp.width = scaled(opt_disp_w->value); - - return rstp; -} - -struct SliceParams { double layerh = 0., initial_layerh = 0.; }; - -SliceParams get_slice_params(const DynamicPrintConfig &cfg) -{ - auto *opt_layerh = cfg.option("layer_height"); - auto *opt_init_layerh = cfg.option("initial_layer_height"); - - if (!opt_layerh || !opt_init_layerh) - throw std::runtime_error("Invalid SL1 file"); - - return SliceParams{opt_layerh->getFloat(), opt_init_layerh->getFloat()}; -} - -std::vector extract_slices_from_sla_archive( - ArchiveData & arch, - const RasterParams & rstp, - std::function progr) -{ - auto jobdir = arch.config.get("jobDir"); - for (auto &c : jobdir) c = std::tolower(c); - - std::vector slices(arch.images.size()); - - struct Status - { - double incr, val, prev; - bool stop = false; - tbb::spin_mutex mutex; - } st {100. / slices.size(), 0., 0.}; - - tbb::parallel_for(size_t(0), arch.images.size(), - [&arch, &slices, &st, &rstp, progr](size_t i) { - // Status indication guarded with the spinlock - { - std::lock_guard lck(st.mutex); - if (st.stop) return; - - st.val += st.incr; - double curr = std::round(st.val); - if (curr > st.prev) { - st.prev = curr; - st.stop = !progr(int(curr)); - } - } - -// PNGBuffer &png = arch.images[i]; -// wxMemoryInputStream stream{png.buf.data(), png.buf.size()}; -// wxImage img{stream}; - - png::ImageGreyscale img; - png::ReadBuf rb{arch.images[i].buf.data(), arch.images[i].buf.size()}; - png::decode_png(rb, img); - - auto rings = marchsq::execute(img, 128, rstp.win); - ExPolygons expolys = rings_to_expolygons(rings, rstp.px_w, rstp.px_h); - - // Invert the raster transformations indicated in - // the profile metadata - invert_raster_trafo(expolys, rstp.trafo, rstp.width, rstp.height); - - slices[i] = std::move(expolys); - }); - - if (st.stop) slices = {}; - - return slices; -} - -} // namespace - -void import_sla_archive(const std::string &zipfname, DynamicPrintConfig &out) -{ - ArchiveData arch = extract_sla_archive(zipfname, "png"); - out.load(arch.profile); -} - -void import_sla_archive( - const std::string & zipfname, - Vec2i windowsize, - TriangleMesh & out, - DynamicPrintConfig & profile, - std::function progr) -{ - // Ensure minimum window size for marching squares - windowsize.x() = std::max(2, windowsize.x()); - windowsize.y() = std::max(2, windowsize.y()); - - ArchiveData arch = extract_sla_archive(zipfname, "thumbnail"); - profile.load(arch.profile); - - RasterParams rstp = get_raster_params(profile); - rstp.win = {windowsize.y(), windowsize.x()}; - - SliceParams slicp = get_slice_params(profile); - - std::vector slices = - extract_slices_from_sla_archive(arch, rstp, progr); - - if (!slices.empty()) - out = slices_to_triangle_mesh(slices, 0, slicp.layerh, slicp.initial_layerh); -} - -} // namespace Slic3r diff --git a/src/slic3r/Utils/SLAImport.hpp b/src/slic3r/Utils/SLAImport.hpp deleted file mode 100644 index 73995014f..000000000 --- a/src/slic3r/Utils/SLAImport.hpp +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef SLAIMPORT_HPP -#define SLAIMPORT_HPP - -#include - -#include -#include - -namespace Slic3r { - -class TriangleMesh; -class DynamicPrintConfig; - -void import_sla_archive(const std::string &zipfname, DynamicPrintConfig &out); - -void import_sla_archive( - const std::string & zipfname, - Vec2i windowsize, - TriangleMesh & out, - DynamicPrintConfig & profile, - std::function progr = [](int) { return true; }); - -inline void import_sla_archive( - const std::string & zipfname, - Vec2i windowsize, - TriangleMesh & out, - std::function progr = [](int) { return true; }) -{ - DynamicPrintConfig profile; - import_sla_archive(zipfname, windowsize, out, profile, progr); -} - -} - -#endif // SLAIMPORT_HPP -- cgit v1.2.3 From 8541ce406069e2b710b22bec937d3405ed0e8316 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Wed, 29 Apr 2020 16:26:39 +0200 Subject: SLA archive import will now recover the model's original position. --- src/slic3r/GUI/GUI_ObjectList.cpp | 19 ++++++++++++------- src/slic3r/GUI/GUI_ObjectList.hpp | 2 +- src/slic3r/GUI/Jobs/SLAImportJob.cpp | 6 ++++-- 3 files changed, 17 insertions(+), 10 deletions(-) (limited to 'src/slic3r') diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index a326eea7b..44b2b6186 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -2209,7 +2209,7 @@ void ObjectList::load_shape_object(const std::string& type_name) load_mesh_object(mesh, _(L("Shape")) + "-" + _(type_name)); } -void ObjectList::load_mesh_object(const TriangleMesh &mesh, const wxString &name) +void ObjectList::load_mesh_object(const TriangleMesh &mesh, const wxString &name, bool center) { // Add mesh to model as a new object Model& model = wxGetApp().plater()->model(); @@ -2219,6 +2219,7 @@ void ObjectList::load_mesh_object(const TriangleMesh &mesh, const wxString &name #endif /* _DEBUG */ std::vector object_idxs; + auto bb = mesh.bounding_box(); ModelObject* new_object = model.add_object(); new_object->name = into_u8(name); new_object->add_instance(); // each object should have at list one instance @@ -2228,13 +2229,17 @@ void ObjectList::load_mesh_object(const TriangleMesh &mesh, const wxString &name // set a default extruder value, since user can't add it manually new_volume->config.set_key_value("extruder", new ConfigOptionInt(0)); new_object->invalidate_bounding_box(); - - new_object->center_around_origin(); + new_object->translate(-bb.center()); + + if (center) { + const BoundingBoxf bed_shape = wxGetApp().plater()->bed_shape_bb(); + new_object->instances[0]->set_offset(Slic3r::to_3d(bed_shape.center().cast(), -new_object->origin_translation(2))); + } else { + new_object->instances[0]->set_offset(bb.center()); + } + new_object->ensure_on_bed(); - - const BoundingBoxf bed_shape = wxGetApp().plater()->bed_shape_bb(); - new_object->instances[0]->set_offset(Slic3r::to_3d(bed_shape.center().cast(), -new_object->origin_translation(2))); - + object_idxs.push_back(model.objects.size() - 1); #ifdef _DEBUG check_model_ids_validity(model); diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index b59631d67..9f7dcd247 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -294,7 +294,7 @@ public: void load_part(ModelObject* model_object, std::vector> &volumes_info, ModelVolumeType type); void load_generic_subobject(const std::string& type_name, const ModelVolumeType type); void load_shape_object(const std::string &type_name); - void load_mesh_object(const TriangleMesh &mesh, const wxString &name); + void load_mesh_object(const TriangleMesh &mesh, const wxString &name, bool center = true); void del_object(const int obj_idx); void del_subobject_item(wxDataViewItem& item); void del_settings_from_config(const wxDataViewItem& parent_item); diff --git a/src/slic3r/GUI/Jobs/SLAImportJob.cpp b/src/slic3r/GUI/Jobs/SLAImportJob.cpp index ae92bd698..adecae6ac 100644 --- a/src/slic3r/GUI/Jobs/SLAImportJob.cpp +++ b/src/slic3r/GUI/Jobs/SLAImportJob.cpp @@ -219,8 +219,10 @@ void SLAImportJob::finalize() wxGetApp().load_current_presets(); } - if (!p->mesh.empty()) - p->plater->sidebar().obj_list()->load_mesh_object(p->mesh, name); + if (!p->mesh.empty()) { + bool is_centered = false; + p->plater->sidebar().obj_list()->load_mesh_object(p->mesh, name, is_centered); + } reset(); } -- cgit v1.2.3