From 7f153a55b36561ba53ab6ded7533debd416feaf8 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Fri, 7 Jan 2022 10:15:16 +0100 Subject: [PATCH 1/6] SLA archiver implemented for svg output, switchable in config. new config is sla_archive_format as a string. WIP Get rid of SVG class, use manual svg creation Revert changes in SVG.hpp and SVG.cpp --- src/PrusaSlicer.cpp | 4 +- src/libslic3r/CMakeLists.txt | 2 + src/libslic3r/Format/SL1.hpp | 19 +-- src/libslic3r/Format/SL1_SVG.cpp | 139 ++++++++++++++++++++ src/libslic3r/Format/SL1_SVG.hpp | 22 ++++ src/libslic3r/Preset.cpp | 2 +- src/libslic3r/PrintConfig.cpp | 5 + src/libslic3r/PrintConfig.hpp | 1 + src/libslic3r/SLAPrint.cpp | 21 +-- src/libslic3r/SLAPrint.hpp | 25 +++- src/slic3r/GUI/BackgroundSlicingProcess.cpp | 4 +- src/slic3r/GUI/BackgroundSlicingProcess.hpp | 9 +- src/slic3r/GUI/Tab.cpp | 4 + 13 files changed, 217 insertions(+), 40 deletions(-) create mode 100644 src/libslic3r/Format/SL1_SVG.cpp create mode 100644 src/libslic3r/Format/SL1_SVG.hpp diff --git a/src/PrusaSlicer.cpp b/src/PrusaSlicer.cpp index 2648fba9e..5bde6c128 100644 --- a/src/PrusaSlicer.cpp +++ b/src/PrusaSlicer.cpp @@ -498,8 +498,6 @@ int CLI::run(int argc, char **argv) std::string outfile = m_config.opt_string("output"); Print fff_print; SLAPrint sla_print; - SL1Archive sla_archive(sla_print.printer_config()); - sla_print.set_printer(&sla_archive); sla_print.set_status_callback( [](const PrintBase::SlicingStatus& s) { @@ -539,7 +537,7 @@ int CLI::run(int argc, char **argv) outfile = sla_print.output_filepath(outfile); // We need to finalize the filename beforehand because the export function sets the filename inside the zip metadata outfile_final = sla_print.print_statistics().finalize_output_path(outfile); - sla_archive.export_print(outfile_final, sla_print); + sla_print.export_print(outfile_final); } if (outfile != outfile_final) { if (Slic3r::rename_file(outfile, outfile_final)) { diff --git a/src/libslic3r/CMakeLists.txt b/src/libslic3r/CMakeLists.txt index 6961432c1..fff000da9 100644 --- a/src/libslic3r/CMakeLists.txt +++ b/src/libslic3r/CMakeLists.txt @@ -96,6 +96,8 @@ set(SLIC3R_SOURCES Format/STL.hpp Format/SL1.hpp Format/SL1.cpp + Format/SL1_SVG.hpp + Format/SL1_SVG.cpp GCode/ThumbnailData.cpp GCode/ThumbnailData.hpp GCode/Thumbnails.cpp diff --git a/src/libslic3r/Format/SL1.hpp b/src/libslic3r/Format/SL1.hpp index 46a82e1b8..e6c0ff089 100644 --- a/src/libslic3r/Format/SL1.hpp +++ b/src/libslic3r/Format/SL1.hpp @@ -15,27 +15,16 @@ protected: std::unique_ptr create_raster() const override; sla::RasterEncoder get_encoder() const override; + SLAPrinterConfig & cfg() { return m_cfg; } + const SLAPrinterConfig & cfg() const { return m_cfg; } + public: SL1Archive() = default; explicit SL1Archive(const SLAPrinterConfig &cfg): m_cfg(cfg) {} explicit SL1Archive(SLAPrinterConfig &&cfg): m_cfg(std::move(cfg)) {} - void export_print(Zipper &zipper, const SLAPrint &print, const std::string &projectname = ""); - void export_print(const std::string &fname, const SLAPrint &print, const std::string &projectname = "") - { - Zipper zipper(fname); - export_print(zipper, print, projectname); - } - - void apply(const SLAPrinterConfig &cfg) override - { - auto diff = m_cfg.diff(cfg); - if (!diff.empty()) { - m_cfg.apply_only(cfg, diff); - m_layers = {}; - } - } + void export_print(Zipper &zipper, const SLAPrint &print, const std::string &projectname = "") override; }; ConfigSubstitutions import_sla_archive(const std::string &zipfname, DynamicPrintConfig &out); diff --git a/src/libslic3r/Format/SL1_SVG.cpp b/src/libslic3r/Format/SL1_SVG.cpp new file mode 100644 index 000000000..bb2f94a68 --- /dev/null +++ b/src/libslic3r/Format/SL1_SVG.cpp @@ -0,0 +1,139 @@ +#include "SL1_SVG.hpp" +#include "SLA/RasterBase.hpp" +#include "libslic3r/LocalesUtils.hpp" + +namespace Slic3r { + +namespace { + +void transform(ExPolygon &ep, const sla::RasterBase::Trafo &tr, const BoundingBox &bb) +{ + if (tr.flipXY) { + for (auto &p : ep.contour.points) std::swap(p.x(), p.y()); + for (auto &h : ep.holes) + for (auto &p : h.points) std::swap(p.x(), p.y()); + } + + if (tr.mirror_x){ + for (auto &p : ep.contour.points) p.x() = bb.max.x() - p.x() + bb.min.x(); + for (auto &h : ep.holes) + for (auto &p : h.points) p.x() = bb.max.x() - p.x() + bb.min.x(); + } + + if (tr.mirror_y){ + for (auto &p : ep.contour.points) p.y() = bb.max.y() - p.y() + bb.min.y(); + for (auto &h : ep.holes) + for (auto &p : h.points) p.y() = bb.max.y() - p.y() + bb.min.y(); + } +} + +void append_svg(std::string &buf, const Polygon &poly) +{ + buf += "(p.x())); + buf += " "; + buf += float_to_string_decimal_point(unscaled(p.y())); + } + buf += " z\""; // mark path as closed + buf += " />\n"; +} + +} // namespace + +// A fake raster from SVG +class SVGRaster : public sla::RasterBase { + // Resolution here will be used for svg boundaries + BoundingBox m_bb; + Trafo m_trafo; + + std::string m_svg; + +public: + SVGRaster(Resolution res = {}, Trafo tr = {}) + : m_bb{BoundingBox{{0, 0}, Vec2crd{res.width_px, res.height_px}}} + , m_trafo{tr} + { + std::string w = float_to_string_decimal_point(unscaled(res.width_px)); + std::string h = float_to_string_decimal_point(unscaled(res.height_px)); + // Add svg header. + m_svg = + "\n" + "\n" + "\n"; + + // Add black background; + m_svg += "\n"; + } + + void draw(const ExPolygon& poly) override + { + auto cpoly = poly; + + transform(cpoly, m_trafo, m_bb); + append_svg(m_svg, cpoly.contour); + for (auto &h : cpoly.holes) + append_svg(m_svg, h); + } + + Resolution resolution() const override + { + return {size_t(m_bb.size().x()), size_t(m_bb.size().y())}; + } + + // Pixel dimension is undefined in this case. + PixelDim pixel_dimensions() const override { return {0, 0}; } + + Trafo trafo() const override { return m_trafo; } + + sla::EncodedRaster encode(sla::RasterEncoder /*encoder*/) const override + { + std::vector data; + constexpr const char finish[] = "\n"; + + data.reserve(m_svg.size() + std::size(finish)); + + std::copy(m_svg.begin(), m_svg.end(), std::back_inserter(data)); + std::copy(finish, finish + std::size(finish) - 1, std::back_inserter(data)); + + return sla::EncodedRaster{std::move(data), "svg"}; + } +}; + +std::unique_ptr SL1_SVGArchive::create_raster() const +{ + auto w = scaled(cfg().display_width.getFloat()); + auto h = scaled(cfg().display_height.getFloat()); + + std::array mirror; + + mirror[X] = cfg().display_mirror_x.getBool(); + mirror[Y] = cfg().display_mirror_y.getBool(); + + auto ro = cfg().display_orientation.getInt(); + sla::RasterBase::Orientation orientation = + ro == sla::RasterBase::roPortrait ? sla::RasterBase::roPortrait : + sla::RasterBase::roLandscape; + + if (orientation == sla::RasterBase::roPortrait) { + std::swap(w, h); + } + + sla::RasterBase::Resolution res{w, h}; + sla::RasterBase::Trafo tr{orientation, mirror}; + + // Gamma does not really make sense in an svg, right? + // double gamma = cfg().gamma_correction.getFloat(); + + return std::make_unique(SVGRaster::Resolution{w, h}, tr); +} + +sla::RasterEncoder SL1_SVGArchive::get_encoder() const +{ + return nullptr; +} + +} // namespace Slic3r diff --git a/src/libslic3r/Format/SL1_SVG.hpp b/src/libslic3r/Format/SL1_SVG.hpp new file mode 100644 index 000000000..a3afbcdff --- /dev/null +++ b/src/libslic3r/Format/SL1_SVG.hpp @@ -0,0 +1,22 @@ +#ifndef SL1_SVG_HPP +#define SL1_SVG_HPP + +#include "SL1.hpp" + +namespace Slic3r { + +class SL1_SVGArchive: public SL1Archive { +protected: + + // Override the factory methods to produce svg instead of a real raster. + std::unique_ptr create_raster() const override; + sla::RasterEncoder get_encoder() const override; + +public: + + using SL1Archive::SL1Archive; +}; + +} // namespace Slic3r + +#endif // SL1_SVG_HPP diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index f8361f1fd..44995cce3 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -573,7 +573,7 @@ static std::vector s_Preset_sla_printer_options { "elefant_foot_min_width", "gamma_correction", "min_exposure_time", "max_exposure_time", - "min_initial_exposure_time", "max_initial_exposure_time", + "min_initial_exposure_time", "max_initial_exposure_time", "sla_archive_format", //FIXME the print host keys are left here just for conversion from the Printer preset to Physical Printer preset. "print_host", "printhost_apikey", "printhost_cafile", "printer_notes", diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 173aa4cee..f0926b0a4 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -3800,6 +3800,11 @@ void PrintConfigDef::init_sla_params() def->enum_labels.push_back(L("Fast")); def->mode = comAdvanced; def->set_default_value(new ConfigOptionEnum(slamsFast)); + + def = this->add("sla_archive_format", coString); + def->label = L("Format of the output SLA archive"); + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionString("SL1")); } void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &value) diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 077969d61..07b024536 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -980,6 +980,7 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionFloat, max_exposure_time)) ((ConfigOptionFloat, min_initial_exposure_time)) ((ConfigOptionFloat, max_initial_exposure_time)) + ((ConfigOptionString, sla_archive_format)) ) PRINT_CONFIG_CLASS_DERIVED_DEFINE0( diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index 55acd3846..ddf3d1419 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -1,6 +1,9 @@ #include "SLAPrint.hpp" #include "SLAPrintSteps.hpp" +#include "Format/SL1.hpp" +#include "Format/SL1_SVG.hpp" + #include "ClipperUtils.hpp" #include "Geometry.hpp" #include "MTUtils.hpp" @@ -240,8 +243,13 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, DynamicPrintConfig con m_material_config.apply_only(config, material_diff, true); // Handle changes to object config defaults m_default_object_config.apply_only(config, object_diff, true); - - if (m_printer) m_printer->apply(m_printer_config); + + if (!m_printer || std::find(printer_diff.begin(), printer_diff.end(), "sla_archive_format") != printer_diff.end()) { + if (m_printer_config.sla_archive_format.value == "SL1") + m_printer = std::make_unique(m_printer_config); + else if (m_printer_config.sla_archive_format.value == "SL2") + m_printer = std::make_unique(m_printer_config); + } struct ModelObjectStatus { enum Status { @@ -670,12 +678,6 @@ std::string SLAPrint::validate(std::string*) const return ""; } -void SLAPrint::set_printer(SLAArchive *arch) -{ - invalidate_step(slapsRasterize); - m_printer = arch; -} - bool SLAPrint::invalidate_step(SLAPrintStep step) { bool invalidated = Inherited::invalidate_step(step); @@ -835,7 +837,8 @@ bool SLAPrint::invalidate_state_by_config_options(const std::vector steps_ignore = { diff --git a/src/libslic3r/SLAPrint.hpp b/src/libslic3r/SLAPrint.hpp index 0622bec4e..58e090c4b 100644 --- a/src/libslic3r/SLAPrint.hpp +++ b/src/libslic3r/SLAPrint.hpp @@ -399,8 +399,6 @@ protected: public: virtual ~SLAArchive() = default; - virtual void apply(const SLAPrinterConfig &cfg) = 0; - // Fn have to be thread safe: void(sla::RasterBase& raster, size_t lyrid); template void draw_layers( @@ -422,6 +420,14 @@ public: }, execution::max_concurrency(ep)); } + + // Export the print into an archive using the provided zipper. + // TODO: Use an archive writer interface instead of Zipper. + // This is quite limiting as the Zipper is a complete class, not an interface. + // The output can only be a zip archive. + virtual void export_print(Zipper &zipper, + const SLAPrint &print, + const std::string &projectname = "") = 0; }; /** @@ -527,8 +533,17 @@ public: // The aggregated and leveled print records from various objects. // TODO: use this structure for the preview in the future. const std::vector& print_layers() const { return m_printer_input; } - - void set_printer(SLAArchive *archiver); + + void export_print(Zipper &zipper, const std::string &projectname = "") + { + m_printer->export_print(zipper, *this, projectname); + } + + void export_print(const std::string &fname, const std::string &projectname = "") + { + Zipper zipper(fname); + export_print(zipper, projectname); + } private: @@ -550,7 +565,7 @@ private: std::vector m_printer_input; // The archive object which collects the raster images after slicing - SLAArchive *m_printer = nullptr; + std::unique_ptr m_printer; // Estimated print time, material consumed. SLAPrintStatistics m_print_statistics; diff --git a/src/slic3r/GUI/BackgroundSlicingProcess.cpp b/src/slic3r/GUI/BackgroundSlicingProcess.cpp index 5f7b4e8d3..5d3d47c20 100644 --- a/src/slic3r/GUI/BackgroundSlicingProcess.cpp +++ b/src/slic3r/GUI/BackgroundSlicingProcess.cpp @@ -190,7 +190,7 @@ void BackgroundSlicingProcess::process_sla() ThumbnailsParams{current_print()->full_print_config().option("thumbnails")->values, true, true, true, true}); Zipper zipper(export_path); - m_sla_archive.export_print(zipper, *m_sla_print); // true, false, true, true); // renders also supports and pad + m_sla_print->export_print(zipper); for (const ThumbnailData& data : thumbnails) if (data.is_valid()) write_thumbnail(zipper, data); @@ -741,7 +741,7 @@ void BackgroundSlicingProcess::prepare_upload() ThumbnailsParams{current_print()->full_print_config().option("thumbnails")->values, true, true, true, true}); // true, false, true, true); // renders also supports and pad Zipper zipper{source_path.string()}; - m_sla_archive.export_print(zipper, *m_sla_print, m_upload_job.upload_data.upload_path.string()); + m_sla_print->export_print(zipper, m_upload_job.upload_data.upload_path.string()); for (const ThumbnailData& data : thumbnails) if (data.is_valid()) write_thumbnail(zipper, data); diff --git a/src/slic3r/GUI/BackgroundSlicingProcess.hpp b/src/slic3r/GUI/BackgroundSlicingProcess.hpp index 5fba237e3..00a3ab6d0 100644 --- a/src/slic3r/GUI/BackgroundSlicingProcess.hpp +++ b/src/slic3r/GUI/BackgroundSlicingProcess.hpp @@ -11,7 +11,6 @@ #include "libslic3r/PrintBase.hpp" #include "libslic3r/GCode/ThumbnailData.hpp" -#include "libslic3r/Format/SL1.hpp" #include "slic3r/Utils/PrintHost.hpp" #include "libslic3r/GCode/GCodeProcessor.hpp" @@ -84,7 +83,7 @@ public: ~BackgroundSlicingProcess(); void set_fff_print(Print *print) { m_fff_print = print; } - void set_sla_print(SLAPrint *print) { m_sla_print = print; m_sla_print->set_printer(&m_sla_archive); } + void set_sla_print(SLAPrint *print) { m_sla_print = print; } void set_thumbnail_cb(ThumbnailsGeneratorCallback cb) { m_thumbnail_cb = cb; } void set_gcode_result(GCodeProcessorResult* result) { m_gcode_result = result; } @@ -218,9 +217,9 @@ private: // Data structure, to which the G-code export writes its annotations. GCodeProcessorResult *m_gcode_result = 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. + ThumbnailsGeneratorCallback m_thumbnail_cb = nullptr; + // 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, // but once set, it cannot be re-set. diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 7d9277dd9..b4354c30e 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -2518,6 +2518,10 @@ void TabPrinter::build_sla() optgroup->append_single_option_line("min_initial_exposure_time"); optgroup->append_single_option_line("max_initial_exposure_time"); + + optgroup = page->new_optgroup(L("Output")); + optgroup->append_single_option_line("sla_archive_format"); + build_print_host_upload_group(page.get()); const int notes_field_height = 25; // 250 From 00764ceadec5094ea0c85f3c8b49d8b49de6fc0d Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Fri, 7 Jan 2022 13:12:40 +0100 Subject: [PATCH 2/6] Fix ignoring of changed sla printer params --- src/libslic3r/SLAPrint.cpp | 6 +++--- src/libslic3r/SLAPrint.hpp | 4 ++-- src/libslic3r/SLAPrintSteps.cpp | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index ddf3d1419..746def7c4 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -244,11 +244,11 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, DynamicPrintConfig con // Handle changes to object config defaults m_default_object_config.apply_only(config, object_diff, true); - if (!m_printer || std::find(printer_diff.begin(), printer_diff.end(), "sla_archive_format") != printer_diff.end()) { + if (!m_archiver || !printer_diff.empty()) { if (m_printer_config.sla_archive_format.value == "SL1") - m_printer = std::make_unique(m_printer_config); + m_archiver = std::make_unique(m_printer_config); else if (m_printer_config.sla_archive_format.value == "SL2") - m_printer = std::make_unique(m_printer_config); + m_archiver = std::make_unique(m_printer_config); } struct ModelObjectStatus { diff --git a/src/libslic3r/SLAPrint.hpp b/src/libslic3r/SLAPrint.hpp index 58e090c4b..b2df0c4e9 100644 --- a/src/libslic3r/SLAPrint.hpp +++ b/src/libslic3r/SLAPrint.hpp @@ -536,7 +536,7 @@ public: void export_print(Zipper &zipper, const std::string &projectname = "") { - m_printer->export_print(zipper, *this, projectname); + m_archiver->export_print(zipper, *this, projectname); } void export_print(const std::string &fname, const std::string &projectname = "") @@ -565,7 +565,7 @@ private: std::vector m_printer_input; // The archive object which collects the raster images after slicing - std::unique_ptr m_printer; + std::unique_ptr m_archiver; // Estimated print time, material consumed. SLAPrintStatistics m_print_statistics; diff --git a/src/libslic3r/SLAPrintSteps.cpp b/src/libslic3r/SLAPrintSteps.cpp index fa7348781..435e8c8e3 100644 --- a/src/libslic3r/SLAPrintSteps.cpp +++ b/src/libslic3r/SLAPrintSteps.cpp @@ -1044,7 +1044,7 @@ void SLAPrint::Steps::merge_slices_and_eval_stats() { // Rasterizing the model objects, and their supports void SLAPrint::Steps::rasterize() { - if(canceled() || !m_print->m_printer) return; + if(canceled() || !m_print->m_archiver) return; // coefficient to map the rasterization state (0-99) to the allocated // portion (slot) of the process state @@ -1089,7 +1089,7 @@ void SLAPrint::Steps::rasterize() if(canceled()) return; // Print all the layers in parallel - m_print->m_printer->draw_layers(m_print->m_printer_input.size(), lvlfn, + m_print->m_archiver->draw_layers(m_print->m_printer_input.size(), lvlfn, [this]() { return canceled(); }, ex_tbb); } From b45c6ef173b6709b9215f82c59218728f43bfe6a Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Fri, 7 Jan 2022 13:18:40 +0100 Subject: [PATCH 3/6] Export scaled integer coordinates into svg This is faster and lossless --- src/libslic3r/Format/SL1_SVG.cpp | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/libslic3r/Format/SL1_SVG.cpp b/src/libslic3r/Format/SL1_SVG.cpp index bb2f94a68..70e3a444f 100644 --- a/src/libslic3r/Format/SL1_SVG.cpp +++ b/src/libslic3r/Format/SL1_SVG.cpp @@ -32,9 +32,9 @@ void append_svg(std::string &buf, const Polygon &poly) buf += "(p.x())); + buf += std::to_string(p.x()); buf += " "; - buf += float_to_string_decimal_point(unscaled(p.y())); + buf += std::to_string(p.y()); } buf += " z\""; // mark path as closed buf += " />\n"; @@ -55,13 +55,24 @@ public: : m_bb{BoundingBox{{0, 0}, Vec2crd{res.width_px, res.height_px}}} , m_trafo{tr} { - std::string w = float_to_string_decimal_point(unscaled(res.width_px)); - std::string h = float_to_string_decimal_point(unscaled(res.height_px)); + // Inside the svg header, the boundaries will be defined in mm to + // the actual bed size. The viewport is then defined to work with our + // scaled coordinates. All the exported polygons will be in these scaled + // coordinates but svg rendering software will interpret them correctly + // in mm due to the header's definition. + std::string wf = float_to_string_decimal_point(unscaled(res.width_px)); + std::string hf = float_to_string_decimal_point(unscaled(res.height_px)); + std::string w = std::to_string(res.width_px); + std::string h = std::to_string(res.height_px); + + // Notice the header also defines the fill-rule as nonzero which should + // generate correct results for our ExPolygons. + // Add svg header. m_svg = "\n" "\n" - "\n"; @@ -128,7 +139,7 @@ std::unique_ptr SL1_SVGArchive::create_raster() const // Gamma does not really make sense in an svg, right? // double gamma = cfg().gamma_correction.getFloat(); - return std::make_unique(SVGRaster::Resolution{w, h}, tr); + return std::make_unique(res, tr); } sla::RasterEncoder SL1_SVGArchive::get_encoder() const From 72da90d28f1d63e84bd23f13a32edf9049489ec0 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Wed, 12 Jan 2022 13:54:18 +0100 Subject: [PATCH 4/6] WIP wip --- src/libslic3r/Format/SL1.cpp | 8 +- src/libslic3r/Format/SL1_SVG.cpp | 106 +++++++++++++++++------ src/libslic3r/SLA/AGGRaster.hpp | 28 +++--- src/libslic3r/SLA/RasterBase.cpp | 8 +- src/libslic3r/SLA/RasterBase.hpp | 54 ++++++------ tests/libslic3r/test_marchingsquares.cpp | 14 +-- tests/libslic3r/test_png_io.cpp | 4 +- tests/sla_print/sla_print_tests.cpp | 8 +- tests/sla_print/sla_test_utils.cpp | 6 +- tests/sla_print/sla_test_utils.hpp | 4 +- 10 files changed, 147 insertions(+), 93 deletions(-) diff --git a/src/libslic3r/Format/SL1.cpp b/src/libslic3r/Format/SL1.cpp index 6ed8c5ebe..6f1e95528 100644 --- a/src/libslic3r/Format/SL1.cpp +++ b/src/libslic3r/Format/SL1.cpp @@ -446,8 +446,8 @@ void fill_slicerconf(ConfMap &m, const SLAPrint &print) std::unique_ptr SL1Archive::create_raster() const { - sla::RasterBase::Resolution res; - sla::RasterBase::PixelDim pxdim; + sla::Resolution res; + sla::PixelDim pxdim; std::array mirror; double w = m_cfg.display_width.getFloat(); @@ -468,8 +468,8 @@ std::unique_ptr SL1Archive::create_raster() const std::swap(pw, ph); } - res = sla::RasterBase::Resolution{pw, ph}; - pxdim = sla::RasterBase::PixelDim{w / pw, h / ph}; + res = sla::Resolution{pw, ph}; + pxdim = sla::PixelDim{w / pw, h / ph}; sla::RasterBase::Trafo tr{orientation, mirror}; double gamma = m_cfg.gamma_correction.getFloat(); diff --git a/src/libslic3r/Format/SL1_SVG.cpp b/src/libslic3r/Format/SL1_SVG.cpp index 70e3a444f..8788577d3 100644 --- a/src/libslic3r/Format/SL1_SVG.cpp +++ b/src/libslic3r/Format/SL1_SVG.cpp @@ -1,6 +1,7 @@ #include "SL1_SVG.hpp" #include "SLA/RasterBase.hpp" #include "libslic3r/LocalesUtils.hpp" +#include "libslic3r/ClipperUtils.hpp" namespace Slic3r { @@ -29,41 +30,79 @@ void transform(ExPolygon &ep, const sla::RasterBase::Trafo &tr, const BoundingBo void append_svg(std::string &buf, const Polygon &poly) { - buf += "(c.x()), precision) + +// " " + float_to_string_decimal_point(unscaled(c.y()), precision) + " m"; + +// for (auto &p : poly) { +// auto d = p - c; +// if (d.squaredNorm() == 0) continue; +// buf += " "; +// buf += float_to_string_decimal_point(unscaled(p.x() - c.x()), precision); +// buf += " "; +// buf += float_to_string_decimal_point(unscaled(p.y() - c.y()), precision); +// c = p; +// } +// buf += " z\""; // mark path as closed +// buf += " />\n"; +//} + } // namespace // A fake raster from SVG class SVGRaster : public sla::RasterBase { // Resolution here will be used for svg boundaries - BoundingBox m_bb; - Trafo m_trafo; + BoundingBox m_bb; + sla::Resolution m_res; + Trafo m_trafo; + Vec2d m_sc; std::string m_svg; public: - SVGRaster(Resolution res = {}, Trafo tr = {}) - : m_bb{BoundingBox{{0, 0}, Vec2crd{res.width_px, res.height_px}}} + SVGRaster(const BoundingBox &svgarea, sla::Resolution res, Trafo tr = {}) + : m_bb{svgarea} + , m_res{res} , m_trafo{tr} + , m_sc{double(m_res.width_px) / m_bb.size().x(), double(m_res.height_px) / m_bb.size().y()} { // Inside the svg header, the boundaries will be defined in mm to // the actual bed size. The viewport is then defined to work with our // scaled coordinates. All the exported polygons will be in these scaled // coordinates but svg rendering software will interpret them correctly // in mm due to the header's definition. - std::string wf = float_to_string_decimal_point(unscaled(res.width_px)); - std::string hf = float_to_string_decimal_point(unscaled(res.height_px)); - std::string w = std::to_string(res.width_px); - std::string h = std::to_string(res.height_px); + std::string wf = float_to_string_decimal_point(unscaled(m_bb.size().x())); + std::string hf = float_to_string_decimal_point(unscaled(m_bb.size().y())); + std::string w = std::to_string(coord_t(m_res.width_px)); + std::string h = std::to_string(coord_t(m_res.height_px)); // Notice the header also defines the fill-rule as nonzero which should // generate correct results for our ExPolygons. @@ -84,21 +123,28 @@ public: { auto cpoly = poly; - transform(cpoly, m_trafo, m_bb); - append_svg(m_svg, cpoly.contour); - for (auto &h : cpoly.holes) - append_svg(m_svg, h); + double tol = std::min(m_bb.size().x() / double(m_res.width_px), + m_bb.size().y() / double(m_res.height_px)); + + ExPolygons cpolys = poly.simplify(tol / 4.); + + for (auto &cpoly : cpolys) { + transform(cpoly, m_trafo, m_bb); + + for (auto &p : cpoly.contour.points) + p = {std::round(p.x() * m_sc.x()), std::round(p.y() * m_sc.y())}; + + for (auto &h : cpoly.holes) + for (auto &p : h) + p = {std::round(p.x() * m_sc.x()), std::round(p.y() * m_sc.y())}; + + append_svg(m_svg, cpoly.contour); + for (auto &h : cpoly.holes) + append_svg(m_svg, h); + } } - Resolution resolution() const override - { - return {size_t(m_bb.size().x()), size_t(m_bb.size().y())}; - } - - // Pixel dimension is undefined in this case. - PixelDim pixel_dimensions() const override { return {0, 0}; } - - Trafo trafo() const override { return m_trafo; } + Trafo trafo() const override { return m_trafo; } sla::EncodedRaster encode(sla::RasterEncoder /*encoder*/) const override { @@ -116,8 +162,11 @@ public: std::unique_ptr SL1_SVGArchive::create_raster() const { - auto w = scaled(cfg().display_width.getFloat()); - auto h = scaled(cfg().display_height.getFloat()); + 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()); std::array mirror; @@ -133,13 +182,14 @@ std::unique_ptr SL1_SVGArchive::create_raster() const std::swap(w, h); } - sla::RasterBase::Resolution res{w, h}; + BoundingBox svgarea{{0, 0}, {scaled(w), scaled(h)}}; + sla::RasterBase::Trafo tr{orientation, mirror}; // Gamma does not really make sense in an svg, right? // double gamma = cfg().gamma_correction.getFloat(); - return std::make_unique(res, tr); + return std::make_unique(svgarea, sla::Resolution{res_x * 4, res_y * 4}, tr); } sla::RasterEncoder SL1_SVGArchive::get_encoder() const diff --git a/src/libslic3r/SLA/AGGRaster.hpp b/src/libslic3r/SLA/AGGRaster.hpp index bc68cd377..7c8e71c2a 100644 --- a/src/libslic3r/SLA/AGGRaster.hpp +++ b/src/libslic3r/SLA/AGGRaster.hpp @@ -41,7 +41,7 @@ public: using TValue = typename TColor::value_type; using TPixel = typename PixelRenderer::pixel_type; using TRawBuffer = agg::rendering_buffer; - + protected: Resolution m_resolution; @@ -153,8 +153,8 @@ public: } Trafo trafo() const override { return m_trafo; } - Resolution resolution() const override { return m_resolution; } - PixelDim pixel_dimensions() const override + Resolution resolution() const { return m_resolution; } + PixelDim pixel_dimensions() const { return {SCALING_FACTOR / m_pxdim_scaled.w_mm, SCALING_FACTOR / m_pxdim_scaled.h_mm}; @@ -186,11 +186,15 @@ class RasterGrayscaleAA : public _RasterGrayscaleAA { using typename Base::TValue; public: template - RasterGrayscaleAA(const RasterBase::Resolution &res, - const RasterBase::PixelDim & pd, - const RasterBase::Trafo & trafo, - GammaFn && fn) - : Base(res, pd, trafo, Colors::White, Colors::Black, + RasterGrayscaleAA(const Resolution &res, + const PixelDim &pd, + const RasterBase::Trafo &trafo, + GammaFn &&fn) + : Base(res, + pd, + trafo, + Colors::White, + Colors::Black, std::forward(fn)) {} @@ -208,10 +212,10 @@ public: class RasterGrayscaleAAGammaPower: public RasterGrayscaleAA { public: - RasterGrayscaleAAGammaPower(const RasterBase::Resolution &res, - const RasterBase::PixelDim & pd, - const RasterBase::Trafo & trafo, - double gamma = 1.) + RasterGrayscaleAAGammaPower(const Resolution &res, + const PixelDim &pd, + const RasterBase::Trafo &trafo, + double gamma = 1.) : RasterGrayscaleAA(res, pd, trafo, agg::gamma_power(gamma)) {} }; diff --git a/src/libslic3r/SLA/RasterBase.cpp b/src/libslic3r/SLA/RasterBase.cpp index cc9aca027..0b6c45eff 100644 --- a/src/libslic3r/SLA/RasterBase.cpp +++ b/src/libslic3r/SLA/RasterBase.cpp @@ -68,10 +68,10 @@ EncodedRaster PPMRasterEncoder::operator()(const void *ptr, size_t w, size_t h, } std::unique_ptr create_raster_grayscale_aa( - const RasterBase::Resolution &res, - const RasterBase::PixelDim & pxdim, - double gamma, - const RasterBase::Trafo & tr) + const Resolution &res, + const PixelDim &pxdim, + double gamma, + const RasterBase::Trafo &tr) { std::unique_ptr rst; diff --git a/src/libslic3r/SLA/RasterBase.hpp b/src/libslic3r/SLA/RasterBase.hpp index 6439830fe..657fc865c 100644 --- a/src/libslic3r/SLA/RasterBase.hpp +++ b/src/libslic3r/SLA/RasterBase.hpp @@ -31,6 +31,27 @@ public: const char * extension() const { return m_ext.c_str(); } }; +/// Type that represents a resolution in pixels. +struct Resolution { + size_t width_px = 0; + size_t height_px = 0; + + Resolution() = default; + Resolution(size_t w, size_t h) : width_px(w), height_px(h) {} + size_t pixels() const { return width_px * height_px; } +}; + +/// Types that represents the dimension of a pixel in millimeters. +struct PixelDim { + double w_mm = 1.; + double h_mm = 1.; + + PixelDim() = default; + PixelDim(double px_width_mm, double px_height_mm) + : w_mm(px_width_mm), h_mm(px_height_mm) + {} +}; + using RasterEncoder = std::function; @@ -63,35 +84,14 @@ public: Point get_center() const { return {center_x, center_y}; } }; - /// Type that represents a resolution in pixels. - struct Resolution { - size_t width_px = 0; - size_t height_px = 0; - - Resolution() = default; - Resolution(size_t w, size_t h) : width_px(w), height_px(h) {} - size_t pixels() const { return width_px * height_px; } - }; - - /// Types that represents the dimension of a pixel in millimeters. - struct PixelDim { - double w_mm = 1.; - double h_mm = 1.; - - PixelDim() = default; - PixelDim(double px_width_mm, double px_height_mm) - : w_mm(px_width_mm), h_mm(px_height_mm) - {} - }; - virtual ~RasterBase() = default; /// Draw a polygon with holes. virtual void draw(const ExPolygon& poly) = 0; /// Get the resolution of the raster. - virtual Resolution resolution() const = 0; - virtual PixelDim pixel_dimensions() const = 0; +// virtual Resolution resolution() const = 0; +// virtual PixelDim pixel_dimensions() const = 0; virtual Trafo trafo() const = 0; virtual EncodedRaster encode(RasterEncoder encoder) const = 0; @@ -109,10 +109,10 @@ std::ostream& operator<<(std::ostream &stream, const EncodedRaster &bytes); // If gamma is zero, thresholding will be performed which disables AA. std::unique_ptr create_raster_grayscale_aa( - const RasterBase::Resolution &res, - const RasterBase::PixelDim & pxdim, - double gamma = 1.0, - const RasterBase::Trafo & tr = {}); + const Resolution &res, + const PixelDim &pxdim, + double gamma = 1.0, + const RasterBase::Trafo &tr = {}); }} // namespace Slic3r::sla diff --git a/tests/libslic3r/test_marchingsquares.cpp b/tests/libslic3r/test_marchingsquares.cpp index 3553697ac..32b137175 100644 --- a/tests/libslic3r/test_marchingsquares.cpp +++ b/tests/libslic3r/test_marchingsquares.cpp @@ -20,17 +20,17 @@ using namespace Slic3r; -static double area(const sla::RasterBase::PixelDim &pxd) +static double area(const sla::PixelDim &pxd) { return pxd.w_mm * pxd.h_mm; } static Slic3r::sla::RasterGrayscaleAA create_raster( - const sla::RasterBase::Resolution &res, + const sla::Resolution &res, double disp_w = 100., double disp_h = 100.) { - sla::RasterBase::PixelDim pixdim{disp_w / res.width_px, disp_h / res.height_px}; + sla::PixelDim pixdim{disp_w / res.width_px, disp_h / res.height_px}; auto bb = BoundingBox({0, 0}, {scaled(disp_w), scaled(disp_h)}); sla::RasterBase::Trafo trafo; @@ -107,7 +107,7 @@ static void test_expolys(Rst && rst, svg.Close(); double max_rel_err = 0.1; - sla::RasterBase::PixelDim pxd = rst.pixel_dimensions(); + sla::PixelDim pxd = rst.pixel_dimensions(); double max_abs_err = area(pxd) * scaled(1.) * scaled(1.); BoundingBox ref_bb; @@ -175,7 +175,7 @@ TEST_CASE("Fully covered raster should result in a rectangle", "[MarchingSquares TEST_CASE("4x4 raster with one ring", "[MarchingSquares]") { - sla::RasterBase::PixelDim pixdim{1, 1}; + sla::PixelDim pixdim{1, 1}; // We need one additional row and column to detect edges sla::RasterGrayscaleAA rst{{4, 4}, pixdim, {}, agg::gamma_threshold(.5)}; @@ -205,7 +205,7 @@ TEST_CASE("4x4 raster with one ring", "[MarchingSquares]") { TEST_CASE("4x4 raster with two rings", "[MarchingSquares]") { - sla::RasterBase::PixelDim pixdim{1, 1}; + sla::PixelDim pixdim{1, 1}; // We need one additional row and column to detect edges sla::RasterGrayscaleAA rst{{5, 5}, pixdim, {}, agg::gamma_threshold(.5)}; @@ -321,7 +321,7 @@ static void recreate_object_from_rasters(const std::string &objname, float lh) { std::vector layers = slice_mesh_ex(mesh.its, grid(float(bb.min.z()) + lh, float(bb.max.z()), lh)); - sla::RasterBase::Resolution res{2560, 1440}; + sla::Resolution res{2560, 1440}; double disp_w = 120.96; double disp_h = 68.04; diff --git a/tests/libslic3r/test_png_io.cpp b/tests/libslic3r/test_png_io.cpp index b4fcd6255..e8229b716 100644 --- a/tests/libslic3r/test_png_io.cpp +++ b/tests/libslic3r/test_png_io.cpp @@ -9,9 +9,9 @@ using namespace Slic3r; -static sla::RasterGrayscaleAA create_raster(const sla::RasterBase::Resolution &res) +static sla::RasterGrayscaleAA create_raster(const sla::Resolution &res) { - sla::RasterBase::PixelDim pixdim{1., 1.}; + sla::PixelDim pixdim{1., 1.}; auto bb = BoundingBox({0, 0}, {scaled(1.), scaled(1.)}); sla::RasterBase::Trafo trafo; diff --git a/tests/sla_print/sla_print_tests.cpp b/tests/sla_print/sla_print_tests.cpp index db8c5e93e..f7b0df339 100644 --- a/tests/sla_print/sla_print_tests.cpp +++ b/tests/sla_print/sla_print_tests.cpp @@ -159,8 +159,8 @@ TEST_CASE("FloorSupportsDoNotPierceModel", "[SLASupportGeneration]") { TEST_CASE("InitializedRasterShouldBeNONEmpty", "[SLARasterOutput]") { // Default Prusa SL1 display parameters - sla::RasterBase::Resolution res{2560, 1440}; - sla::RasterBase::PixelDim pixdim{120. / res.width_px, 68. / res.height_px}; + sla::Resolution res{2560, 1440}; + sla::PixelDim pixdim{120. / res.width_px, 68. / res.height_px}; sla::RasterGrayscaleAAGammaPower raster(res, pixdim, {}, 1.); REQUIRE(raster.resolution().width_px == res.width_px); @@ -186,8 +186,8 @@ TEST_CASE("MirroringShouldBeCorrect", "[SLARasterOutput]") { TEST_CASE("RasterizedPolygonAreaShouldMatch", "[SLARasterOutput]") { double disp_w = 120., disp_h = 68.; - sla::RasterBase::Resolution res{2560, 1440}; - sla::RasterBase::PixelDim pixdim{disp_w / res.width_px, disp_h / res.height_px}; + sla::Resolution res{2560, 1440}; + sla::PixelDim pixdim{disp_w / res.width_px, disp_h / res.height_px}; double gamma = 1.; sla::RasterGrayscaleAAGammaPower raster(res, pixdim, {}, gamma); diff --git a/tests/sla_print/sla_test_utils.cpp b/tests/sla_print/sla_test_utils.cpp index 1082df200..d98a92037 100644 --- a/tests/sla_print/sla_test_utils.cpp +++ b/tests/sla_print/sla_test_utils.cpp @@ -307,8 +307,8 @@ void check_validity(const TriangleMesh &input_mesh, int flags) void check_raster_transformations(sla::RasterBase::Orientation o, sla::RasterBase::TMirroring mirroring) { double disp_w = 120., disp_h = 68.; - sla::RasterBase::Resolution res{2560, 1440}; - sla::RasterBase::PixelDim pixdim{disp_w / res.width_px, disp_h / res.height_px}; + sla::Resolution res{2560, 1440}; + sla::PixelDim pixdim{disp_w / res.width_px, disp_h / res.height_px}; auto bb = BoundingBox({0, 0}, {scaled(disp_w), scaled(disp_h)}); sla::RasterBase::Trafo trafo{o, mirroring}; @@ -400,7 +400,7 @@ double raster_white_area(const sla::RasterGrayscaleAA &raster) return a; } -double predict_error(const ExPolygon &p, const sla::RasterBase::PixelDim &pd) +double predict_error(const ExPolygon &p, const sla::PixelDim &pd) { auto lines = p.lines(); double pix_err = pixel_area(FullWhite, pd) / 2.; diff --git a/tests/sla_print/sla_test_utils.hpp b/tests/sla_print/sla_test_utils.hpp index 2264ad856..7171914d4 100644 --- a/tests/sla_print/sla_test_utils.hpp +++ b/tests/sla_print/sla_test_utils.hpp @@ -175,7 +175,7 @@ void check_raster_transformations(sla::RasterBase::Orientation o, ExPolygon square_with_hole(double v); -inline double pixel_area(TPixel px, const sla::RasterBase::PixelDim &pxdim) +inline double pixel_area(TPixel px, const sla::PixelDim &pxdim) { return (pxdim.h_mm * pxdim.w_mm) * px * 1. / (FullWhite - FullBlack); } @@ -183,7 +183,7 @@ inline double pixel_area(TPixel px, const sla::RasterBase::PixelDim &pxdim) double raster_white_area(const sla::RasterGrayscaleAA &raster); long raster_pxsum(const sla::RasterGrayscaleAA &raster); -double predict_error(const ExPolygon &p, const sla::RasterBase::PixelDim &pd); +double predict_error(const ExPolygon &p, const sla::PixelDim &pd); sla::SupportPoints calc_support_pts( const TriangleMesh & mesh, From 5e97778528464f431097407964ab476b76c8a566 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Wed, 12 Jan 2022 15:30:08 +0100 Subject: [PATCH 5/6] Added new param sla_output_precision in nanometers Adopted a fast and easy integer to string conversion --- src/libslic3r/Format/SL1_SVG.cpp | 88 +++++++++++++++++++------------- src/libslic3r/Preset.cpp | 2 +- src/libslic3r/PrintConfig.cpp | 8 +++ src/libslic3r/PrintConfig.hpp | 1 + src/libslic3r/SLAPrint.cpp | 3 +- src/slic3r/GUI/Tab.cpp | 1 + 6 files changed, 66 insertions(+), 37 deletions(-) diff --git a/src/libslic3r/Format/SL1_SVG.cpp b/src/libslic3r/Format/SL1_SVG.cpp index 8788577d3..52fad1473 100644 --- a/src/libslic3r/Format/SL1_SVG.cpp +++ b/src/libslic3r/Format/SL1_SVG.cpp @@ -3,10 +3,50 @@ #include "libslic3r/LocalesUtils.hpp" #include "libslic3r/ClipperUtils.hpp" +#include +#include +#include + namespace Slic3r { namespace { +size_t constexpr coord_t_bufsize = 40; + +inline char const* decimal_from(coord_t snumber, char* buffer) +{ + std::make_unsigned_t number = 0; + + char* ret = buffer; + + if( snumber < 0 ) { + *buffer++ = '-'; + number = -snumber; + } else + number = snumber; + + if( number == 0 ) { + *buffer++ = '0'; + } else { + char* p_first = buffer; + while( number != 0 ) { + *buffer++ = '0' + number % 10; + number /= 10; + } + std::reverse( p_first, buffer ); + } + + *buffer = '\0'; + + return ret; +} + +inline std::string coord2str(coord_t crd) +{ + char buf[coord_t_bufsize]; + return decimal_from(crd, buf); +} + void transform(ExPolygon &ep, const sla::RasterBase::Trafo &tr, const BoundingBox &bb) { if (tr.flipXY) { @@ -35,46 +75,23 @@ void append_svg(std::string &buf, const Polygon &poly) auto c = poly.points.front(); - buf += "(c.x()), precision) + -// " " + float_to_string_decimal_point(unscaled(c.y()), precision) + " m"; - -// for (auto &p : poly) { -// auto d = p - c; -// if (d.squaredNorm() == 0) continue; -// buf += " "; -// buf += float_to_string_decimal_point(unscaled(p.x() - c.x()), precision); -// buf += " "; -// buf += float_to_string_decimal_point(unscaled(p.y() - c.y()), precision); -// c = p; -// } -// buf += " z\""; // mark path as closed -// buf += " />\n"; -//} - } // namespace // A fake raster from SVG @@ -101,8 +118,8 @@ public: // in mm due to the header's definition. std::string wf = float_to_string_decimal_point(unscaled(m_bb.size().x())); std::string hf = float_to_string_decimal_point(unscaled(m_bb.size().y())); - std::string w = std::to_string(coord_t(m_res.width_px)); - std::string h = std::to_string(coord_t(m_res.height_px)); + std::string w = coord2str(coord_t(m_res.width_px)); + std::string h = coord2str(coord_t(m_res.height_px)); // Notice the header also defines the fill-rule as nonzero which should // generate correct results for our ExPolygons. @@ -126,7 +143,7 @@ public: double tol = std::min(m_bb.size().x() / double(m_res.width_px), m_bb.size().y() / double(m_res.height_px)); - ExPolygons cpolys = poly.simplify(tol / 4.); + ExPolygons cpolys = poly.simplify(tol); for (auto &cpoly : cpolys) { transform(cpoly, m_trafo, m_bb); @@ -165,8 +182,10 @@ 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()); +// auto res_x = size_t(cfg().display_pixels_x.getInt()); +// auto res_y = size_t(cfg().display_pixels_y.getInt()); + size_t res_x = std::round(scaled(w) / cfg().sla_output_precision.getFloat()); + size_t res_y = std::round(scaled(h) / cfg().sla_output_precision.getFloat()); std::array mirror; @@ -188,8 +207,7 @@ std::unique_ptr SL1_SVGArchive::create_raster() const // Gamma does not really make sense in an svg, right? // double gamma = cfg().gamma_correction.getFloat(); - - return std::make_unique(svgarea, sla::Resolution{res_x * 4, res_y * 4}, tr); + return std::make_unique(svgarea, sla::Resolution{res_x, res_y}, tr); } sla::RasterEncoder SL1_SVGArchive::get_encoder() const diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 44995cce3..ca1363da2 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -573,7 +573,7 @@ static std::vector s_Preset_sla_printer_options { "elefant_foot_min_width", "gamma_correction", "min_exposure_time", "max_exposure_time", - "min_initial_exposure_time", "max_initial_exposure_time", "sla_archive_format", + "min_initial_exposure_time", "max_initial_exposure_time", "sla_archive_format", "sla_output_precision", //FIXME the print host keys are left here just for conversion from the Printer preset to Physical Printer preset. "print_host", "printhost_apikey", "printhost_cafile", "printer_notes", diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index f0926b0a4..3070f865b 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -3805,6 +3805,14 @@ void PrintConfigDef::init_sla_params() def->label = L("Format of the output SLA archive"); def->mode = comAdvanced; def->set_default_value(new ConfigOptionString("SL1")); + + def = this->add("sla_output_precision", coFloat); + def->label = L("SLA output precision"); + def->tooltip = L("Minimum resolution in nanometers"); + def->sidetext = L("nm"); + def->min = 1; + def->mode = comExpert; + def->set_default_value(new ConfigOptionFloat(1000)); } void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &value) diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 07b024536..75079ee71 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -981,6 +981,7 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionFloat, min_initial_exposure_time)) ((ConfigOptionFloat, max_initial_exposure_time)) ((ConfigOptionString, sla_archive_format)) + ((ConfigOptionFloat, sla_output_precision)) ) PRINT_CONFIG_CLASS_DERIVED_DEFINE0( diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index 746def7c4..7b78dfea2 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -838,7 +838,8 @@ bool SLAPrint::invalidate_state_by_config_options(const std::vector steps_ignore = { diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index b4354c30e..a20bdb831 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -2521,6 +2521,7 @@ void TabPrinter::build_sla() optgroup = page->new_optgroup(L("Output")); optgroup->append_single_option_line("sla_archive_format"); + optgroup->append_single_option_line("sla_output_precision"); build_print_host_upload_group(page.get()); From ca7668d858ddbf731456c78ea2dcae51731ce6ce Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Thu, 13 Jan 2022 09:59:29 +0100 Subject: [PATCH 6/6] Change precision units to mm Add some perf optimization for svg output writing --- src/libslic3r/Format/SL1_SVG.cpp | 17 ++++++++++------- src/libslic3r/PrintConfig.cpp | 6 +++--- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/libslic3r/Format/SL1_SVG.cpp b/src/libslic3r/Format/SL1_SVG.cpp index 52fad1473..0ea230611 100644 --- a/src/libslic3r/Format/SL1_SVG.cpp +++ b/src/libslic3r/Format/SL1_SVG.cpp @@ -13,7 +13,7 @@ namespace { size_t constexpr coord_t_bufsize = 40; -inline char const* decimal_from(coord_t snumber, char* buffer) +char const* decimal_from(coord_t snumber, char* buffer) { std::make_unsigned_t number = 0; @@ -75,17 +75,18 @@ void append_svg(std::string &buf, const Polygon &poly) auto c = poly.points.front(); -// char intbuf[coord_t_bufsize]; + char intbuf[coord_t_bufsize]; - buf += std::string(" SL1_SVGArchive::create_raster() const // auto res_x = size_t(cfg().display_pixels_x.getInt()); // auto res_y = size_t(cfg().display_pixels_y.getInt()); - size_t res_x = std::round(scaled(w) / cfg().sla_output_precision.getFloat()); - size_t res_y = std::round(scaled(h) / cfg().sla_output_precision.getFloat()); + 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); std::array mirror; @@ -199,6 +201,7 @@ std::unique_ptr SL1_SVGArchive::create_raster() const if (orientation == sla::RasterBase::roPortrait) { std::swap(w, h); + std::swap(res_x, res_y); } BoundingBox svgarea{{0, 0}, {scaled(w), scaled(h)}}; diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 3070f865b..5a674da84 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -3809,10 +3809,10 @@ void PrintConfigDef::init_sla_params() def = this->add("sla_output_precision", coFloat); def->label = L("SLA output precision"); def->tooltip = L("Minimum resolution in nanometers"); - def->sidetext = L("nm"); - def->min = 1; + def->sidetext = L("mm"); + def->min = SCALING_FACTOR; def->mode = comExpert; - def->set_default_value(new ConfigOptionFloat(1000)); + def->set_default_value(new ConfigOptionFloat(0.001)); } void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &value)