Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authortamasmeszaros <meszaros.q@gmail.com>2020-04-23 20:12:07 +0300
committertamasmeszaros <meszaros.q@gmail.com>2020-04-23 20:12:07 +0300
commit217477a9ff62e084f6b616943705d84578417170 (patch)
treeee1a686ff26040aaa6a7b1eff1b55adc2fdacf69 /src
parent247fca6d55318fbaa5c7424bf7605db7fb02e342 (diff)
SLA archive import with miniz, marching square bugfixes
Fix compilation on Windows Fix array subscript out of range error in MarchingSquares Fix normals of mesh constructed from slices Improve performance of mesh construction from slices
Diffstat (limited to 'src')
-rw-r--r--src/libslic3r/MarchingSquares.hpp104
-rw-r--r--src/libslic3r/SLA/RasterToPolygons.cpp9
-rw-r--r--src/libslic3r/SLA/RasterToPolygons.hpp4
-rw-r--r--src/libslic3r/SlicesToTriangleMesh.cpp103
-rw-r--r--src/libslic3r/Zipper.cpp80
-rw-r--r--src/libslic3r/Zipper.hpp2
-rw-r--r--src/libslic3r/miniz_extension.cpp88
-rw-r--r--src/libslic3r/miniz_extension.hpp21
-rw-r--r--src/slic3r/CMakeLists.txt4
-rw-r--r--src/slic3r/GUI/GUI_ObjectList.cpp17
-rw-r--r--src/slic3r/GUI/GUI_ObjectList.hpp2
-rw-r--r--src/slic3r/GUI/Plater.cpp8
-rw-r--r--src/slic3r/Utils/SLAImport.cpp314
-rw-r--r--src/slic3r/Utils/SLAImport.hpp36
-rw-r--r--src/slic3r/Utils/SLAZipFileImport.cpp144
-rw-r--r--src/slic3r/Utils/SLAZipFileImport.hpp14
16 files changed, 619 insertions, 331 deletions
diff --git a/src/libslic3r/MarchingSquares.hpp b/src/libslic3r/MarchingSquares.hpp
index a5aeb0953..d5f07fbde 100644
--- a/src/libslic3r/MarchingSquares.hpp
+++ b/src/libslic3r/MarchingSquares.hpp
@@ -11,11 +11,11 @@ namespace marchsq {
// Marks a square in the grid
struct Coord {
- size_t r = 0, c = 0;
+ long r = 0, c = 0;
Coord() = default;
- explicit Coord(size_t s) : r(s), c(s) {}
- Coord(size_t _r, size_t _c): r(_r), c(_c) {}
+ explicit Coord(long s) : r(s), c(s) {}
+ Coord(long _r, long _c): r(_r), c(_c) {}
size_t seq(const Coord &res) const { return r * res.c + c; }
Coord& operator+=(const Coord& b) { r += b.r; c += b.c; return *this; }
@@ -52,11 +52,6 @@ namespace __impl {
template<class T> using RasterTraits = _RasterTraits<std::decay_t<T>>;
template<class T> using TRasterValue = typename RasterTraits<T>::ValueType;
-template<class T> TRasterValue<T> isoval(const T &raster, const Coord &crd)
-{
- return RasterTraits<T>::get(raster, crd.r, crd.c);
-}
-
template<class T> size_t rows(const T &raster)
{
return RasterTraits<T>::rows(raster);
@@ -67,6 +62,11 @@ template<class T> size_t cols(const T &raster)
return RasterTraits<T>::cols(raster);
}
+template<class T> TRasterValue<T> isoval(const T &rst, const Coord &crd)
+{
+ return RasterTraits<T>::get(rst, crd.r, crd.c);
+}
+
template<class ExecutionPolicy, class It, class Fn>
void for_each(ExecutionPolicy&& policy, It from, It to, Fn &&fn)
{
@@ -142,55 +142,46 @@ inline Coord step(const Coord &crd, Dir d)
template<class Rst> class Grid {
const Rst * m_rst = nullptr;
- Coord m_cellsize, m_res_1, m_window, m_gridsize;
+ Coord m_cellsize, m_res_1, m_window, m_gridsize, m_grid_1;
std::vector<uint8_t> m_tags; // Assign tags to each square
Coord rastercoord(const Coord &crd) const
{
- return {crd.r * m_window.r, crd.c * m_window.c};
+ return {(crd.r - 1) * m_window.r, (crd.c - 1) * m_window.c};
}
Coord bl(const Coord &crd) const { return tl(crd) + Coord{m_res_1.r, 0}; }
Coord br(const Coord &crd) const { return tl(crd) + Coord{m_res_1.r, m_res_1.c}; }
Coord tr(const Coord &crd) const { return tl(crd) + Coord{0, m_res_1.c}; }
Coord tl(const Coord &crd) const { return rastercoord(crd); }
-
- TRasterValue<Rst> bottomleft(const Coord &cell) const
- {
- return isoval(*m_rst, bl(cell));
- }
-
- TRasterValue<Rst> bottomright(const Coord &cell) const
- {
- return isoval(*m_rst, br(cell));
- }
- TRasterValue<Rst> topright(const Coord &cell) const
+ bool is_within(const Coord &crd)
{
- return isoval(*m_rst, tr(cell));
- }
-
- TRasterValue<Rst> topleft(const Coord &cell) const
- {
- return isoval(*m_rst, tl(cell));
- }
+ long R = rows(*m_rst), C = cols(*m_rst);
+ return crd.r >= 0 && crd.r < R && crd.c >= 0 && crd.c < C;
+ };
// Calculate the tag for a cell (or square). The cell coordinates mark the
// top left vertex of a square in the raster. v is the isovalue
uint8_t get_tag_for_cell(const Coord &cell, TRasterValue<Rst> v)
- {
- uint8_t t = (bottomleft(cell) >= v) +
- ((bottomright(cell) >= v) << 1) +
- ((topright(cell) >= v) << 2) +
- ((topleft(cell) >= v) << 3);
+ {
+ Coord sqr[] = {bl(cell), br(cell), tr(cell), tl(cell)};
+
+ uint8_t t = ((is_within(sqr[0]) && isoval(*m_rst, sqr[0]) >= v)) +
+ ((is_within(sqr[1]) && isoval(*m_rst, sqr[1]) >= v) << 1) +
+ ((is_within(sqr[2]) && isoval(*m_rst, sqr[2]) >= v) << 2) +
+ ((is_within(sqr[3]) && isoval(*m_rst, sqr[3]) >= v) << 3);
assert(t < 16);
return t;
}
// Get a cell coordinate from a sequential index
- Coord coord(size_t i) const { return {i / m_gridsize.c, i % m_gridsize.c}; }
-
+ Coord coord(size_t i) const
+ {
+ return {long(i) / m_gridsize.c, long(i) % m_gridsize.c};
+ }
+
size_t seq(const Coord &crd) const { return crd.seq(m_gridsize); }
bool is_visited(size_t idx, Dir d = Dir::none) const
@@ -217,7 +208,7 @@ template<class Rst> class Grid {
{
// Skip ambiguous tags as starting tags due to unknown previous
// direction.
- while ((i < m_tags.size() && is_visited(i)) || is_ambiguous(i)) ++i;
+ while ((i < m_tags.size()) && (is_visited(i) || is_ambiguous(i))) ++i;
return i;
}
@@ -248,8 +239,9 @@ template<class Rst> class Grid {
}
struct CellIt {
- Coord crd; Dir dir= Dir::none; const Rst *rst = nullptr;
- TRasterValue<Rst> operator*() const { return isoval(*rst, crd); }
+ Coord crd; Dir dir= Dir::none; const Rst *grid = nullptr;
+
+ TRasterValue<Rst> operator*() const { return isoval(*grid, crd); }
CellIt& operator++() { crd = step(crd, dir); return *this; }
CellIt operator++(int) { CellIt it = *this; ++(*this); return it; }
bool operator!=(const CellIt &it) { return crd.r != it.crd.r || crd.c != it.crd.c; }
@@ -265,7 +257,7 @@ template<class Rst> class Grid {
// used for binary search for the first active pixel on the edge.
struct Edge { CellIt from, to; };
- Edge edge(const Coord &ringvertex)
+ Edge _edge(const Coord &ringvertex) const
{
size_t idx = ringvertex.r;
Coord cell = coord(idx);
@@ -312,6 +304,28 @@ template<class Rst> class Grid {
return {};
}
+ Edge edge(const Coord &ringvertex) const
+ {
+ const long R = rows(*m_rst), C = cols(*m_rst);
+ const long R_1 = R - 1, C_1 = C - 1;
+
+ Edge e = _edge(ringvertex);
+ e.to.dir = e.from.dir;
+ ++e.to;
+
+ e.from.crd.r = std::min(e.from.crd.r, R_1);
+ e.from.crd.r = std::max(e.from.crd.r, 0l);
+ e.from.crd.c = std::min(e.from.crd.c, C_1);
+ e.from.crd.c = std::max(e.from.crd.c, 0l);
+
+ e.to.crd.r = std::min(e.to.crd.r, R);
+ e.to.crd.r = std::max(e.to.crd.r, 0l);
+ e.to.crd.c = std::min(e.to.crd.c, C);
+ e.to.crd.c = std::max(e.to.crd.c, 0l);
+
+ return e;
+ }
+
public:
explicit Grid(const Rst &rst, const Coord &cellsz, const Coord &overlap)
: m_rst{&rst}
@@ -319,8 +333,8 @@ public:
, m_res_1{m_cellsize.r - 1, m_cellsize.c - 1}
, m_window{overlap.r < cellsz.r ? cellsz.r - overlap.r : cellsz.r,
overlap.c < cellsz.c ? cellsz.c - overlap.c : cellsz.c}
- , m_gridsize{(rows(rst) - overlap.r) / m_window.r,
- (cols(rst) - overlap.c) / m_window.c}
+ , m_gridsize{2 + (long(rows(rst)) - overlap.r) / m_window.r,
+ 2 + (long(cols(rst)) - overlap.c) / m_window.c}
, m_tags(m_gridsize.r * m_gridsize.c, 0)
{}
@@ -350,7 +364,7 @@ public:
Dir prev = Dir::none, next = next_dir(prev, get_tag(idx));
while (next != Dir::none && !is_visited(idx, prev)) {
- Coord ringvertex{idx, size_t(next)};
+ Coord ringvertex{long(idx), long(next)};
ring.emplace_back(ringvertex);
set_visited(idx, prev);
@@ -379,9 +393,11 @@ public:
TRasterValue<Rst> isov)
{
for_each(std::forward<ExecutionPolicy>(policy),
- rings.begin(), rings.end(), [this, isov] (Ring &ring, size_t) {
+ rings.begin(), rings.end(), [this, isov] (Ring &ring, size_t)
+ {
for (Coord &ringvertex : ring) {
Edge e = edge(ringvertex);
+
CellIt found = std::lower_bound(e.from, e.to, isov);
ringvertex = found.crd;
}
@@ -401,7 +417,7 @@ std::vector<marchsq::Ring> execute_with_policy(ExecutionPolicy && policy,
if (!windowsize.r) windowsize.r = 2;
if (!windowsize.c)
- windowsize.c = std::max(size_t(2), windowsize.r * ratio);
+ windowsize.c = std::max(2l, long(windowsize.r * ratio));
Coord overlap{1};
diff --git a/src/libslic3r/SLA/RasterToPolygons.cpp b/src/libslic3r/SLA/RasterToPolygons.cpp
index 6b1d8992c..cd84a3cb4 100644
--- a/src/libslic3r/SLA/RasterToPolygons.cpp
+++ b/src/libslic3r/SLA/RasterToPolygons.cpp
@@ -33,15 +33,15 @@ template<class Fn> void foreach_vertex(ExPolygon &poly, Fn &&fn)
for (auto &p : h.points) fn(p);
}
-ExPolygons raster_to_polygons(const RasterGrayscaleAA &rst, float accuracy)
+ExPolygons raster_to_polygons(const RasterGrayscaleAA &rst, Vec2i windowsize)
{
size_t rows = rst.resolution().height_px, cols = rst.resolution().width_px;
if (rows < 2 || cols < 2) return {};
Polygons polys;
- size_t w_rows = (2 + rows / 8) - size_t(accuracy * rows / 8);
- size_t w_cols = std::max(size_t(2), w_rows * cols / rows);
+ long w_rows = std::max(2l, long(windowsize.y()));
+ long w_cols = std::max(2l, long(windowsize.x()));
std::vector<marchsq::Ring> rings =
marchsq::execute(rst, 128, {w_rows, w_cols});
@@ -49,6 +49,9 @@ ExPolygons raster_to_polygons(const RasterGrayscaleAA &rst, float accuracy)
polys.reserve(rings.size());
auto pxd = rst.pixel_dimensions();
+ pxd.w_mm = (rst.resolution().width_px * pxd.w_mm) / (rst.resolution().width_px - 1);
+ pxd.h_mm = (rst.resolution().height_px * pxd.h_mm) / (rst.resolution().height_px - 1);
+
for (const marchsq::Ring &ring : rings) {
Polygon poly; Points &pts = poly.points;
pts.reserve(ring.size());
diff --git a/src/libslic3r/SLA/RasterToPolygons.hpp b/src/libslic3r/SLA/RasterToPolygons.hpp
index 131fe518e..c0e1f4114 100644
--- a/src/libslic3r/SLA/RasterToPolygons.hpp
+++ b/src/libslic3r/SLA/RasterToPolygons.hpp
@@ -8,8 +8,8 @@ namespace sla {
class RasterGrayscaleAA;
-ExPolygons raster_to_polygons(const RasterGrayscaleAA &rst, float accuracy = 1.f);
+ExPolygons raster_to_polygons(const RasterGrayscaleAA &rst, Vec2i windowsize = {2, 2});
-}}
+}} // namespace Slic3r::sla
#endif // RASTERTOPOLYGONS_HPP
diff --git a/src/libslic3r/SlicesToTriangleMesh.cpp b/src/libslic3r/SlicesToTriangleMesh.cpp
index bd0961d04..d6a546961 100644
--- a/src/libslic3r/SlicesToTriangleMesh.cpp
+++ b/src/libslic3r/SlicesToTriangleMesh.cpp
@@ -1,23 +1,40 @@
#include "SlicesToTriangleMesh.hpp"
-#include "libslic3r/TriangulateWall.hpp"
+#include "libslic3r/MTUtils.hpp"
#include "libslic3r/SLA/Contour3D.hpp"
#include "libslic3r/ClipperUtils.hpp"
#include "libslic3r/Tesselate.hpp"
+#include <tbb/parallel_for.h>
+#include <tbb/parallel_reduce.h>
+
namespace Slic3r {
-inline sla::Contour3D walls(const Polygon &lower,
- const Polygon &upper,
- double lower_z_mm,
- double upper_z_mm)
+inline sla::Contour3D wall_strip(const Polygon &poly,
+ double lower_z_mm,
+ double upper_z_mm)
{
- Wall w = triangulate_wall(lower, upper, lower_z_mm, upper_z_mm);
-
sla::Contour3D ret;
- ret.points = std::move(w.first);
- ret.faces3 = std::move(w.second);
+
+ size_t startidx = ret.points.size();
+ size_t offs = poly.points.size();
+
+ ret.points.reserve(ret.points.size() + 2 *offs);
+
+ for (const Point &p : poly.points)
+ ret.points.emplace_back(to_3d(unscaled(p), lower_z_mm));
+
+ for (const Point &p : poly.points)
+ ret.points.emplace_back(to_3d(unscaled(p), upper_z_mm));
+
+ for (size_t i = startidx + 1; i < startidx + offs; ++i) {
+ ret.faces3.emplace_back(i - 1, i, i + offs - 1);
+ ret.faces3.emplace_back(i, i + offs, i + offs - 1);
+ }
+
+ ret.faces3.emplace_back(startidx + offs - 1, startidx, startidx + 2 * offs - 1);
+ ret.faces3.emplace_back(startidx, startidx + offs, startidx + 2 * offs - 1);
return ret;
}
@@ -27,7 +44,7 @@ sla::Contour3D inline straight_walls(const Polygon &plate,
double lo_z,
double hi_z)
{
- return walls(plate, plate, lo_z, hi_z);
+ return wall_strip(plate, lo_z, hi_z);
}
sla::Contour3D inline straight_walls(const ExPolygon &plate,
@@ -43,7 +60,7 @@ sla::Contour3D inline straight_walls(const ExPolygon &plate,
sla::Contour3D inline straight_walls(const ExPolygons &slice,
double lo_z,
double hi_z)
-{
+{
sla::Contour3D ret;
for (const ExPolygon &poly : slice)
ret.merge(straight_walls(poly, lo_z, hi_z));
@@ -51,32 +68,60 @@ sla::Contour3D inline straight_walls(const ExPolygons &slice,
return ret;
}
+sla::Contour3D slices_to_triangle_mesh(const std::vector<ExPolygons> &slices,
+ double zmin,
+ const std::vector<float> & grid)
+{
+ assert(slices.size() == grid.size());
+
+ using Layers = std::vector<sla::Contour3D>;
+ std::vector<sla::Contour3D> layers(slices.size());
+ size_t len = slices.size() - 1;
+
+ tbb::parallel_for(size_t(0), len, [&slices, &layers, &grid](size_t i) {
+ const ExPolygons &upper = slices[i + 1];
+ const ExPolygons &lower = slices[i];
+
+ ExPolygons dff1 = diff_ex(lower, upper);
+ ExPolygons dff2 = diff_ex(upper, lower);
+ layers[i].merge(triangulate_expolygons_3d(dff1, grid[i], NORMALS_UP));
+ layers[i].merge(triangulate_expolygons_3d(dff2, grid[i], NORMALS_DOWN));
+ layers[i].merge(straight_walls(upper, grid[i], grid[i + 1]));
+
+ });
+
+ sla::Contour3D ret = tbb::parallel_reduce(
+ tbb::blocked_range(layers.begin(), layers.end()),
+ sla::Contour3D{},
+ [](const tbb::blocked_range<Layers::iterator>& r, sla::Contour3D init) {
+ for(auto it = r.begin(); it != r.end(); ++it ) init.merge(*it);
+ return init;
+ },
+ []( const sla::Contour3D &a, const sla::Contour3D &b ) {
+ sla::Contour3D res{a}; res.merge(b); return res;
+ });
+
+ ret.merge(triangulate_expolygons_3d(slices.front(), zmin, NORMALS_DOWN));
+ ret.merge(straight_walls(slices.front(), zmin, grid.front()));
+ ret.merge(triangulate_expolygons_3d(slices.back(), grid.back(), NORMALS_UP));
+
+ return ret;
+}
+
void slices_to_triangle_mesh(TriangleMesh & mesh,
const std::vector<ExPolygons> &slices,
double zmin,
double lh,
double ilh)
{
- sla::Contour3D cntr3d;
- double h = zmin;
-
- auto it = slices.begin(), xt = std::next(it);
- cntr3d.merge(triangulate_expolygons_3d(*it, h, NORMALS_DOWN));
- cntr3d.merge(straight_walls(*it, h, h + ilh));
- h += ilh;
- while (xt != slices.end()) {
- ExPolygons dff1 = diff_ex(*it, *xt);
- ExPolygons dff2 = diff_ex(*xt, *it);
- cntr3d.merge(triangulate_expolygons_3d(dff1, h, NORMALS_UP));
- cntr3d.merge(triangulate_expolygons_3d(dff2, h, NORMALS_UP));
- cntr3d.merge(straight_walls(*xt, h, h + lh));
- h += lh;
- ++it; ++xt;
- }
+ std::vector<sla::Contour3D> wall_meshes(slices.size());
+ std::vector<float> grid(slices.size(), zmin + ilh);
- cntr3d.merge(triangulate_expolygons_3d(*it, h, NORMALS_UP));
+ for (size_t i = 1; i < grid.size(); ++i) grid[i] = grid[i - 1] + lh;
- mesh.merge(sla::to_triangle_mesh(cntr3d));
+ sla::Contour3D cntr = slices_to_triangle_mesh(slices, zmin, grid);
+ mesh.merge(sla::to_triangle_mesh(cntr));
+ mesh.repaired = true;
mesh.require_shared_vertices();
}
diff --git a/src/libslic3r/Zipper.cpp b/src/libslic3r/Zipper.cpp
index ec9d3aa16..02f022083 100644
--- a/src/libslic3r/Zipper.cpp
+++ b/src/libslic3r/Zipper.cpp
@@ -17,90 +17,14 @@
namespace Slic3r {
-class Zipper::Impl {
+class Zipper::Impl: public MZ_Archive {
public:
- mz_zip_archive arch;
std::string m_zipname;
- static std::string get_errorstr(mz_zip_error mz_err)
- {
- switch (mz_err)
- {
- case MZ_ZIP_NO_ERROR:
- return "no error";
- case MZ_ZIP_UNDEFINED_ERROR:
- return L("undefined error");
- case MZ_ZIP_TOO_MANY_FILES:
- return L("too many files");
- case MZ_ZIP_FILE_TOO_LARGE:
- return L("file too large");
- case MZ_ZIP_UNSUPPORTED_METHOD:
- return L("unsupported method");
- case MZ_ZIP_UNSUPPORTED_ENCRYPTION:
- return L("unsupported encryption");
- case MZ_ZIP_UNSUPPORTED_FEATURE:
- return L("unsupported feature");
- case MZ_ZIP_FAILED_FINDING_CENTRAL_DIR:
- return L("failed finding central directory");
- case MZ_ZIP_NOT_AN_ARCHIVE:
- return L("not a ZIP archive");
- case MZ_ZIP_INVALID_HEADER_OR_CORRUPTED:
- return L("invalid header or archive is corrupted");
- case MZ_ZIP_UNSUPPORTED_MULTIDISK:
- return L("unsupported multidisk archive");
- case MZ_ZIP_DECOMPRESSION_FAILED:
- return L("decompression failed or archive is corrupted");
- case MZ_ZIP_COMPRESSION_FAILED:
- return L("compression failed");
- case MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE:
- return L("unexpected decompressed size");
- case MZ_ZIP_CRC_CHECK_FAILED:
- return L("CRC-32 check failed");
- case MZ_ZIP_UNSUPPORTED_CDIR_SIZE:
- return L("unsupported central directory size");
- case MZ_ZIP_ALLOC_FAILED:
- return L("allocation failed");
- case MZ_ZIP_FILE_OPEN_FAILED:
- return L("file open failed");
- case MZ_ZIP_FILE_CREATE_FAILED:
- return L("file create failed");
- case MZ_ZIP_FILE_WRITE_FAILED:
- return L("file write failed");
- case MZ_ZIP_FILE_READ_FAILED:
- return L("file read failed");
- case MZ_ZIP_FILE_CLOSE_FAILED:
- return L("file close failed");
- case MZ_ZIP_FILE_SEEK_FAILED:
- return L("file seek failed");
- case MZ_ZIP_FILE_STAT_FAILED:
- return L("file stat failed");
- case MZ_ZIP_INVALID_PARAMETER:
- return L("invalid parameter");
- case MZ_ZIP_INVALID_FILENAME:
- return L("invalid filename");
- case MZ_ZIP_BUF_TOO_SMALL:
- return L("buffer too small");
- case MZ_ZIP_INTERNAL_ERROR:
- return L("internal error");
- case MZ_ZIP_FILE_NOT_FOUND:
- return L("file not found");
- case MZ_ZIP_ARCHIVE_TOO_LARGE:
- return L("archive is too large");
- case MZ_ZIP_VALIDATION_FAILED:
- return L("validation failed");
- case MZ_ZIP_WRITE_CALLBACK_FAILED:
- return L("write calledback failed");
- default:
- break;
- }
-
- return "unknown error";
- }
-
std::string formatted_errorstr() const
{
return L("Error with zip archive") + " " + m_zipname + ": " +
- get_errorstr(arch.m_last_error) + "!";
+ get_errorstr() + "!";
}
SLIC3R_NORETURN void blow_up() const
diff --git a/src/libslic3r/Zipper.hpp b/src/libslic3r/Zipper.hpp
index d203ea7b2..bbaf2f05e 100644
--- a/src/libslic3r/Zipper.hpp
+++ b/src/libslic3r/Zipper.hpp
@@ -28,7 +28,7 @@ public:
// Will blow up in a runtime exception if the file cannot be created.
explicit Zipper(const std::string& zipfname,
- e_compression level = NO_COMPRESSION);
+ e_compression level = FAST_COMPRESSION);
~Zipper();
// No copies allwed, this is a file resource...
diff --git a/src/libslic3r/miniz_extension.cpp b/src/libslic3r/miniz_extension.cpp
index 17cc136fc..76b4cb4e5 100644
--- a/src/libslic3r/miniz_extension.cpp
+++ b/src/libslic3r/miniz_extension.cpp
@@ -1,9 +1,17 @@
+#include <exception>
+
#include "miniz_extension.hpp"
#if defined(_MSC_VER) || defined(__MINGW64__)
#include "boost/nowide/cstdio.hpp"
#endif
+#include "I18N.hpp"
+
+//! macro used to mark string used at localization,
+//! return same string
+#define L(s) Slic3r::I18N::translate(s)
+
namespace Slic3r {
namespace {
@@ -68,4 +76,84 @@ bool open_zip_writer(mz_zip_archive *zip, const std::string &fname)
bool close_zip_reader(mz_zip_archive *zip) { return close_zip(zip, true); }
bool close_zip_writer(mz_zip_archive *zip) { return close_zip(zip, false); }
+MZ_Archive::MZ_Archive()
+{
+ mz_zip_zero_struct(&arch);
}
+
+std::string MZ_Archive::get_errorstr(mz_zip_error mz_err)
+{
+ switch (mz_err)
+ {
+ case MZ_ZIP_NO_ERROR:
+ return "no error";
+ case MZ_ZIP_UNDEFINED_ERROR:
+ return L("undefined error");
+ case MZ_ZIP_TOO_MANY_FILES:
+ return L("too many files");
+ case MZ_ZIP_FILE_TOO_LARGE:
+ return L("file too large");
+ case MZ_ZIP_UNSUPPORTED_METHOD:
+ return L("unsupported method");
+ case MZ_ZIP_UNSUPPORTED_ENCRYPTION:
+ return L("unsupported encryption");
+ case MZ_ZIP_UNSUPPORTED_FEATURE:
+ return L("unsupported feature");
+ case MZ_ZIP_FAILED_FINDING_CENTRAL_DIR:
+ return L("failed finding central directory");
+ case MZ_ZIP_NOT_AN_ARCHIVE:
+ return L("not a ZIP archive");
+ case MZ_ZIP_INVALID_HEADER_OR_CORRUPTED:
+ return L("invalid header or archive is corrupted");
+ case MZ_ZIP_UNSUPPORTED_MULTIDISK:
+ return L("unsupported multidisk archive");
+ case MZ_ZIP_DECOMPRESSION_FAILED:
+ return L("decompression failed or archive is corrupted");
+ case MZ_ZIP_COMPRESSION_FAILED:
+ return L("compression failed");
+ case MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE:
+ return L("unexpected decompressed size");
+ case MZ_ZIP_CRC_CHECK_FAILED:
+ return L("CRC-32 check failed");
+ case MZ_ZIP_UNSUPPORTED_CDIR_SIZE:
+ return L("unsupported central directory size");
+ case MZ_ZIP_ALLOC_FAILED:
+ return L("allocation failed");
+ case MZ_ZIP_FILE_OPEN_FAILED:
+ return L("file open failed");
+ case MZ_ZIP_FILE_CREATE_FAILED:
+ return L("file create failed");
+ case MZ_ZIP_FILE_WRITE_FAILED:
+ return L("file write failed");
+ case MZ_ZIP_FILE_READ_FAILED:
+ return L("file read failed");
+ case MZ_ZIP_FILE_CLOSE_FAILED:
+ return L("file close failed");
+ case MZ_ZIP_FILE_SEEK_FAILED:
+ return L("file seek failed");
+ case MZ_ZIP_FILE_STAT_FAILED:
+ return L("file stat failed");
+ case MZ_ZIP_INVALID_PARAMETER:
+ return L("invalid parameter");
+ case MZ_ZIP_INVALID_FILENAME:
+ return L("invalid filename");
+ case MZ_ZIP_BUF_TOO_SMALL:
+ return L("buffer too small");
+ case MZ_ZIP_INTERNAL_ERROR:
+ return L("internal error");
+ case MZ_ZIP_FILE_NOT_FOUND:
+ return L("file not found");
+ case MZ_ZIP_ARCHIVE_TOO_LARGE:
+ return L("archive is too large");
+ case MZ_ZIP_VALIDATION_FAILED:
+ return L("validation failed");
+ case MZ_ZIP_WRITE_CALLBACK_FAILED:
+ return L("write calledback failed");
+ default:
+ break;
+ }
+
+ return "unknown error";
+}
+
+} // namespace Slic3r
diff --git a/src/libslic3r/miniz_extension.hpp b/src/libslic3r/miniz_extension.hpp
index 8d0967cbc..006226bf2 100644
--- a/src/libslic3r/miniz_extension.hpp
+++ b/src/libslic3r/miniz_extension.hpp
@@ -11,6 +11,25 @@ bool open_zip_writer(mz_zip_archive *zip, const std::string &fname_utf8);
bool close_zip_reader(mz_zip_archive *zip);
bool close_zip_writer(mz_zip_archive *zip);
-}
+class MZ_Archive {
+public:
+ mz_zip_archive arch;
+
+ MZ_Archive();
+
+ static std::string get_errorstr(mz_zip_error mz_err);
+
+ std::string get_errorstr() const
+ {
+ return get_errorstr(arch.m_last_error) + "!";
+ }
+
+ bool is_alive() const
+ {
+ return arch.m_zip_mode != MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED;
+ }
+};
+
+} // namespace Slic3r
#endif // MINIZ_EXTENSION_HPP
diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt
index c0853fb65..1f1284a9e 100644
--- a/src/slic3r/CMakeLists.txt
+++ b/src/slic3r/CMakeLists.txt
@@ -182,8 +182,8 @@ set(SLIC3R_GUI_SOURCES
Utils/HexFile.cpp
Utils/HexFile.hpp
Utils/Thread.hpp
- Utils/SLAZipFileImport.hpp
- Utils/SLAZipFileImport.cpp
+ Utils/SLAImport.hpp
+ Utils/SLAImport.cpp
)
if (APPLE)
diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp
index 6297cace3..1f2ce0221 100644
--- a/src/slic3r/GUI/GUI_ObjectList.cpp
+++ b/src/slic3r/GUI/GUI_ObjectList.cpp
@@ -2071,37 +2071,40 @@ void ObjectList::load_shape_object(const std::string& type_name)
// Create mesh
BoundingBoxf3 bb;
TriangleMesh mesh = create_mesh(type_name, bb);
+ load_mesh_object(mesh, _(L("Shape")) + "-" + _(type_name));
+}
+void ObjectList::load_mesh_object(const TriangleMesh &mesh, const wxString &name)
+{
// Add mesh to model as a new object
Model& model = wxGetApp().plater()->model();
- const wxString name = _(L("Shape")) + "-" + _(type_name);
#ifdef _DEBUG
check_model_ids_validity(model);
#endif /* _DEBUG */
-
+
std::vector<size_t> object_idxs;
ModelObject* new_object = model.add_object();
new_object->name = into_u8(name);
new_object->add_instance(); // each object should have at list one instance
-
+
ModelVolume* new_volume = new_object->add_volume(mesh);
new_volume->name = into_u8(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->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<double>(), -new_object->origin_translation(2)));
-
+
object_idxs.push_back(model.objects.size() - 1);
#ifdef _DEBUG
check_model_ids_validity(model);
#endif /* _DEBUG */
-
+
paste_objects_into_list(object_idxs);
#ifdef _DEBUG
diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp
index 609411cd5..72e130737 100644
--- a/src/slic3r/GUI/GUI_ObjectList.hpp
+++ b/src/slic3r/GUI/GUI_ObjectList.hpp
@@ -24,6 +24,7 @@ class ConfigOptionsGroup;
class DynamicPrintConfig;
class ModelObject;
class ModelVolume;
+class TriangleMesh;
enum class ModelVolumeType : int;
// FIXME: broken build on mac os because of this is missing:
@@ -265,6 +266,7 @@ public:
void load_part(ModelObject* model_object, std::vector<std::pair<wxString, bool>> &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 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/Plater.cpp b/src/slic3r/GUI/Plater.cpp
index 75ef32762..f9fe06a85 100644
--- a/src/slic3r/GUI/Plater.cpp
+++ b/src/slic3r/GUI/Plater.cpp
@@ -73,7 +73,7 @@
#include "../Utils/PrintHost.hpp"
#include "../Utils/FixModelByWin10.hpp"
#include "../Utils/UndoRedo.hpp"
-#include "../Utils/SLAZipFileImport.hpp"
+#include "../Utils/SLAImport.hpp"
#include "RemovableDriveManager.hpp"
#if ENABLE_NON_STATIC_CANVAS_MANAGER
#ifdef __APPLE__
@@ -4263,11 +4263,7 @@ void Plater::import_sl1_archive()
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();
- }
+ p->sidebar->obj_list()->load_mesh_object(mesh, wxFileName(dlg.GetPath()).GetName());
} catch (std::exception &ex) {
show_error(this, ex.what());
}
diff --git a/src/slic3r/Utils/SLAImport.cpp b/src/slic3r/Utils/SLAImport.cpp
new file mode 100644
index 000000000..442025a77
--- /dev/null
+++ b/src/slic3r/Utils/SLAImport.cpp
@@ -0,0 +1,314 @@
+#include "SLAImport.hpp"
+
+#include <sstream>
+
+#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 <boost/property_tree/ini_parser.hpp>
+#include <boost/filesystem/path.hpp>
+#include <boost/algorithm/string.hpp>
+
+#include <wx/image.h>
+#include <wx/mstream.h>
+
+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 {
+
+namespace {
+
+struct ArchiveData {
+ boost::property_tree::ptree profile, config;
+ std::vector<sla::EncodedRaster> 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;
+}
+
+sla::EncodedRaster read_png(const mz_zip_archive_file_stat &entry,
+ MZ_Archive & zip,
+ const std::string & name)
+{
+ std::vector<uint8_t> 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 sla::EncodedRaster(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(), sla::EncodedRaster({}, name),
+ [](const sla::EncodedRaster &r1, const sla::EncodedRaster &r2) {
+ return std::less<std::string>()(r1.extension(), r2.extension());
+ });
+
+ arch.images.insert(it, read_png(entry, zip, name));
+ }
+ }
+ }
+
+ return arch;
+}
+
+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);
+}
+
+template<class Fn> 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<ConfigOptionInt>("display_pixels_x");
+ auto *opt_disp_rows = cfg.option<ConfigOptionInt>("display_pixels_y");
+ auto *opt_disp_w = cfg.option<ConfigOptionFloat>("display_width");
+ auto *opt_disp_h = cfg.option<ConfigOptionFloat>("display_height");
+ auto *opt_mirror_x = cfg.option<ConfigOptionBool>("display_mirror_x");
+ auto *opt_mirror_y = cfg.option<ConfigOptionBool>("display_mirror_y");
+ auto *opt_orient = cfg.option<ConfigOptionEnum<SLADisplayOrientation>>("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<ConfigOptionFloat>("layer_height");
+ auto *opt_init_layerh = cfg.option<ConfigOptionFloat>("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<ExPolygons> extract_slices_from_sla_archive(
+ ArchiveData & arch,
+ const RasterParams & rstp,
+ std::function<bool(int)> progr)
+{
+ auto jobdir = arch.config.get<std::string>("jobDir");
+ for (auto &c : jobdir) c = std::tolower(c);
+
+ std::vector<ExPolygons> 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<tbb::spin_mutex> 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));
+ }
+ }
+
+ auto &buf = arch.images[i];
+ wxMemoryInputStream stream{buf.data(), buf.size()};
+ wxImage img{stream};
+
+ 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<bool(int)> 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<ExPolygons> 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
new file mode 100644
index 000000000..a819bd7e7
--- /dev/null
+++ b/src/slic3r/Utils/SLAImport.hpp
@@ -0,0 +1,36 @@
+#ifndef SLAIMPORT_HPP
+#define SLAIMPORT_HPP
+
+#include <functional>
+
+#include <libslic3r/Point.hpp>
+#include <libslic3r/TriangleMesh.hpp>
+#include <libslic3r/PrintConfig.hpp>
+
+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<bool(int)> progr = [](int) { return true; });
+
+inline void import_sla_archive(
+ const std::string & zipfname,
+ Vec2i windowsize,
+ TriangleMesh & out,
+ std::function<bool(int)> progr = [](int) { return true; })
+{
+ DynamicPrintConfig profile;
+ import_sla_archive(zipfname, windowsize, out, profile, progr);
+}
+
+}
+
+#endif // SLAIMPORT_HPP
diff --git a/src/slic3r/Utils/SLAZipFileImport.cpp b/src/slic3r/Utils/SLAZipFileImport.cpp
deleted file mode 100644
index 6543e8674..000000000
--- a/src/slic3r/Utils/SLAZipFileImport.cpp
+++ /dev/null
@@ -1,144 +0,0 @@
-#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
diff --git a/src/slic3r/Utils/SLAZipFileImport.hpp b/src/slic3r/Utils/SLAZipFileImport.hpp
deleted file mode 100644
index 4e36f86f4..000000000
--- a/src/slic3r/Utils/SLAZipFileImport.hpp
+++ /dev/null
@@ -1,14 +0,0 @@
-#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