diff --git a/src/libslic3r/Format/SL1.cpp b/src/libslic3r/Format/SL1.cpp index a29dcc100..5fc273728 100644 --- a/src/libslic3r/Format/SL1.cpp +++ b/src/libslic3r/Format/SL1.cpp @@ -264,28 +264,7 @@ template<> struct _RasterTraits { namespace Slic3r { -namespace { - -ExPolygons rings_to_expolygons(const std::vector &rings, - double px_w, double px_h) -{ - auto polys = reserve_vector(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); - } - - // TODO: Is a union necessary? - return union_ex(polys); -} - -template void foreach_vertex(ExPolygon &poly, Fn &&fn) +template static void foreach_vertex(ExPolygon &poly, Fn &&fn) { for (auto &p : poly.contour.points) fn(p); for (auto &h : poly.holes) @@ -318,6 +297,27 @@ void invert_raster_trafo(ExPolygons & expolys, } } +namespace { + +ExPolygons rings_to_expolygons(const std::vector &rings, + double px_w, double px_h) +{ + auto polys = reserve_vector(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); + } + + // TODO: Is a union necessary? + return union_ex(polys); +} + struct RasterParams { sla::RasterBase::Trafo trafo; // Raster transformations coord_t width, height; // scaled raster dimensions (not resolution) diff --git a/src/libslic3r/Format/SL1.hpp b/src/libslic3r/Format/SL1.hpp index 8511ef5fd..b5d214e80 100644 --- a/src/libslic3r/Format/SL1.hpp +++ b/src/libslic3r/Format/SL1.hpp @@ -60,6 +60,11 @@ public: {} }; +void invert_raster_trafo(ExPolygons & expolys, + const sla::RasterBase::Trafo &trafo, + coord_t width, + coord_t height); + } // namespace Slic3r::sla #endif // ARCHIVETRAITS_HPP diff --git a/src/libslic3r/Format/SL1_SVG.cpp b/src/libslic3r/Format/SL1_SVG.cpp index 96cc4f213..9dd9e16fe 100644 --- a/src/libslic3r/Format/SL1_SVG.cpp +++ b/src/libslic3r/Format/SL1_SVG.cpp @@ -77,10 +77,25 @@ void transform(ExPolygon &ep, const sla::RasterBase::Trafo &tr, const BoundingBo void append_svg(std::string &buf, const Polygon &poly) { +// if (poly.points.empty()) +// return; + +// char intbuf[coord_t_bufsize]; +// buf += "\n"; - - // Add black background; - m_svg += "\n"; } void draw(const ExPolygon& poly) override @@ -193,8 +206,6 @@ std::unique_ptr SL1_SVGArchive::create_raster() const auto w = cfg().display_width.getFloat(); auto h = cfg().display_height.getFloat(); -// auto res_x = size_t(cfg().display_pixels_x.getInt()); -// auto res_y = size_t(cfg().display_pixels_y.getInt()); float precision_nm = scaled(cfg().sla_output_precision.getFloat()); size_t res_x = std::round(scaled(w) / precision_nm); size_t res_y = std::round(scaled(h) / precision_nm); @@ -238,10 +249,50 @@ void SL1_SVGArchive::export_print(const std::string fname, SL1Archive::export_print(zipper, print, thumbnails, projectname); } +struct RasterParams { + sla::RasterBase::Trafo trafo; // Raster transformations + coord_t width, height; // scaled raster dimensions (not resolution) +}; + +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 MissingProfileError("Invalid SL1 / SL1S file"); + + RasterParams rstp; + + rstp.trafo = sla::RasterBase::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 NanoSVGParser { + NSVGimage *image; + static constexpr const char *Units = "mm"; // Denotes user coordinate system + static constexpr float Dpi = 1.f; // Not needed + NanoSVGParser(char* input): image{nsvgParse(input, Units, Dpi)} {} + ~NanoSVGParser() { nsvgDelete(image); } +}; + ConfigSubstitutions SL1_SVGReader::read(std::vector &slices, DynamicPrintConfig &profile_out) { - std::vector includes = { "config.ini", "prusaslicer.ini", "svg"}; + std::vector includes = { CONFIG_FNAME, PROFILE_FNAME, "svg"}; ZipperArchive arch = read_zipper_archive(m_fname, includes, {}); DynamicPrintConfig profile_in, profile_use; @@ -271,25 +322,44 @@ ConfigSubstitutions SL1_SVGReader::read(std::vector &slices, profile_use = profile_in.empty() ? profile_out : profile_in; profile_out = profile_in; + RasterParams rstp = get_raster_params(profile_use); + + struct Status + { + double incr, val, prev; + bool stop = false; + } st{100. / arch.entries.size(), 0., 0.}; + for (const EntryBuffer &entry : arch.entries) { - NSVGimage* image; + if (st.stop) break; + + st.val += st.incr; + double curr = std::round(st.val); + if (curr > st.prev) { + st.prev = curr; + st.stop = !m_progr(int(curr)); + } + auto svgtxt = reserve_vector(entry.buf.size()); std::copy(entry.buf.begin(), entry.buf.end(), std::back_inserter(svgtxt)); - image = nsvgParse(svgtxt.data(), "px", 96); - printf("size: %f x %f\n", image->width, image->height); - // Use... - for (NSVGshape *shape = image->shapes; shape != nullptr; shape = shape->next) { - for (NSVGpath *path = shape->paths; path != nullptr; path = path->next) { + NanoSVGParser svgp(svgtxt.data()); + Polygons polys; + for (NSVGshape *shape = svgp.image->shapes; shape != nullptr; shape = shape->next) { + for (NSVGpath *path = shape->paths; path != nullptr; path = path->next) { + Polygon p; + for (int i = 0; i < path->npts; ++i) { + size_t c = 2 * i; + p.points.emplace_back(scaled(Vec2f(path->pts[c], path->pts[c + 1]))); + } + polys.emplace_back(p); } } - // Delete - nsvgDelete(image); - } -// RasterParams rstp = get_raster_params(profile_use); -// rstp.win = {windowsize.y(), windowsize.x()}; -// slices = extract_slices_from_sla_archive(arch, rstp, m_progr); + ExPolygons expolys = union_ex(polys); + invert_raster_trafo(expolys, rstp.trafo, rstp.width, rstp.height); + slices.emplace_back(expolys); + } return config_substitutions; } diff --git a/src/libslic3r/Format/ZipperArchiveImport.cpp b/src/libslic3r/Format/ZipperArchiveImport.cpp index d5d5f8272..f02de2323 100644 --- a/src/libslic3r/Format/ZipperArchiveImport.cpp +++ b/src/libslic3r/Format/ZipperArchiveImport.cpp @@ -9,9 +9,6 @@ namespace Slic3r { -static const constexpr char *CONFIG_FNAME = "config.ini"; -static const constexpr char *PROFILE_FNAME = "prusaslicer.ini"; - namespace { boost::property_tree::ptree read_ini(const mz_zip_archive_file_stat &entry, @@ -83,8 +80,8 @@ ZipperArchive read_zipper_archive(const std::string &zipfname, })) continue; - if (name == CONFIG_FNAME) arch.config = read_ini(entry, zip); - if (name == PROFILE_FNAME) arch.profile = read_ini(entry, zip); + if (name == CONFIG_FNAME) { arch.config = read_ini(entry, zip); continue; } + if (name == PROFILE_FNAME) { arch.profile = read_ini(entry, zip); continue; } auto it = std::lower_bound( arch.entries.begin(), arch.entries.end(), diff --git a/src/libslic3r/Format/ZipperArchiveImport.hpp b/src/libslic3r/Format/ZipperArchiveImport.hpp index 5802c128c..1b1273a4b 100644 --- a/src/libslic3r/Format/ZipperArchiveImport.hpp +++ b/src/libslic3r/Format/ZipperArchiveImport.hpp @@ -21,6 +21,9 @@ struct ZipperArchive std::vector entries; }; +const constexpr char *CONFIG_FNAME = "config.ini"; +const constexpr char *PROFILE_FNAME = "prusaslicer.ini"; + ZipperArchive read_zipper_archive(const std::string &zipfname, const std::vector &includes, const std::vector &excludes);