Merge branch 'tm_sla_export_svg_3'
This commit is contained in:
commit
3785ad3de4
@ -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)) {
|
||||
|
@ -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
|
||||
|
@ -446,8 +446,8 @@ void fill_slicerconf(ConfMap &m, const SLAPrint &print)
|
||||
|
||||
std::unique_ptr<sla::RasterBase> SL1Archive::create_raster() const
|
||||
{
|
||||
sla::RasterBase::Resolution res;
|
||||
sla::RasterBase::PixelDim pxdim;
|
||||
sla::Resolution res;
|
||||
sla::PixelDim pxdim;
|
||||
std::array<bool, 2> mirror;
|
||||
|
||||
double w = m_cfg.display_width.getFloat();
|
||||
@ -468,8 +468,8 @@ std::unique_ptr<sla::RasterBase> 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();
|
||||
|
@ -15,27 +15,16 @@ protected:
|
||||
std::unique_ptr<sla::RasterBase> 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);
|
||||
|
221
src/libslic3r/Format/SL1_SVG.cpp
Normal file
221
src/libslic3r/Format/SL1_SVG.cpp
Normal file
@ -0,0 +1,221 @@
|
||||
#include "SL1_SVG.hpp"
|
||||
#include "SLA/RasterBase.hpp"
|
||||
#include "libslic3r/LocalesUtils.hpp"
|
||||
#include "libslic3r/ClipperUtils.hpp"
|
||||
|
||||
#include <limits>
|
||||
#include <cstdint>
|
||||
#include <algorithm>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
namespace {
|
||||
|
||||
size_t constexpr coord_t_bufsize = 40;
|
||||
|
||||
char const* decimal_from(coord_t snumber, char* buffer)
|
||||
{
|
||||
std::make_unsigned_t<coord_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) {
|
||||
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)
|
||||
{
|
||||
if (poly.points.empty())
|
||||
return;
|
||||
|
||||
auto c = poly.points.front();
|
||||
|
||||
char intbuf[coord_t_bufsize];
|
||||
|
||||
buf += std::string("<path d=\"M ") + decimal_from(c.x(), intbuf);
|
||||
buf += std::string(" ") + decimal_from(c.y(), intbuf) + " m";
|
||||
|
||||
for (auto &p : poly) {
|
||||
auto d = p - c;
|
||||
if (d.squaredNorm() == 0) continue;
|
||||
buf += " ";
|
||||
buf += decimal_from(p.x() - c.x(), intbuf);
|
||||
buf += " ";
|
||||
buf += decimal_from(p.y() - c.y(), intbuf);
|
||||
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;
|
||||
sla::Resolution m_res;
|
||||
Trafo m_trafo;
|
||||
Vec2d m_sc;
|
||||
|
||||
std::string m_svg;
|
||||
|
||||
public:
|
||||
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<float>(m_bb.size().x()));
|
||||
std::string hf = float_to_string_decimal_point(unscaled<float>(m_bb.size().y()));
|
||||
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.
|
||||
|
||||
// Add svg header.
|
||||
m_svg =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n"
|
||||
"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.0//EN\" \"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\">\n"
|
||||
"<svg height=\"" + hf + "mm" + "\" width=\"" + wf + "mm" + "\" viewBox=\"0 0 " + w + " " + h +
|
||||
"\" style=\"fill: white; stroke: none; fill-rule: nonzero\" "
|
||||
"xmlns=\"http://www.w3.org/2000/svg\" xmlns:svg=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n";
|
||||
|
||||
// Add black background;
|
||||
m_svg += "<rect fill='black' stroke='none' x='0' y='0' width='" + w + "' height='" + h + "'/>\n";
|
||||
}
|
||||
|
||||
void draw(const ExPolygon& poly) override
|
||||
{
|
||||
auto cpoly = poly;
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
Trafo trafo() const override { return m_trafo; }
|
||||
|
||||
sla::EncodedRaster encode(sla::RasterEncoder /*encoder*/) const override
|
||||
{
|
||||
std::vector<uint8_t> data;
|
||||
constexpr const char finish[] = "</svg>\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<sla::RasterBase> 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<float>(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<bool, 2> 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);
|
||||
std::swap(res_x, res_y);
|
||||
}
|
||||
|
||||
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<SVGRaster>(svgarea, sla::Resolution{res_x, res_y}, tr);
|
||||
}
|
||||
|
||||
sla::RasterEncoder SL1_SVGArchive::get_encoder() const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
22
src/libslic3r/Format/SL1_SVG.hpp
Normal file
22
src/libslic3r/Format/SL1_SVG.hpp
Normal file
@ -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<sla::RasterBase> create_raster() const override;
|
||||
sla::RasterEncoder get_encoder() const override;
|
||||
|
||||
public:
|
||||
|
||||
using SL1Archive::SL1Archive;
|
||||
};
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // SL1_SVG_HPP
|
@ -573,7 +573,7 @@ static std::vector<std::string> 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", "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",
|
||||
|
@ -3800,6 +3800,19 @@ void PrintConfigDef::init_sla_params()
|
||||
def->enum_labels.push_back(L("Fast"));
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionEnum<SLAMaterialSpeed>(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"));
|
||||
|
||||
def = this->add("sla_output_precision", coFloat);
|
||||
def->label = L("SLA output precision");
|
||||
def->tooltip = L("Minimum resolution in nanometers");
|
||||
def->sidetext = L("mm");
|
||||
def->min = SCALING_FACTOR;
|
||||
def->mode = comExpert;
|
||||
def->set_default_value(new ConfigOptionFloat(0.001));
|
||||
}
|
||||
|
||||
void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &value)
|
||||
|
@ -980,6 +980,8 @@ PRINT_CONFIG_CLASS_DEFINE(
|
||||
((ConfigOptionFloat, max_exposure_time))
|
||||
((ConfigOptionFloat, min_initial_exposure_time))
|
||||
((ConfigOptionFloat, max_initial_exposure_time))
|
||||
((ConfigOptionString, sla_archive_format))
|
||||
((ConfigOptionFloat, sla_output_precision))
|
||||
)
|
||||
|
||||
PRINT_CONFIG_CLASS_DERIVED_DEFINE0(
|
||||
|
@ -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<class GammaFn>
|
||||
RasterGrayscaleAA(const RasterBase::Resolution &res,
|
||||
const RasterBase::PixelDim & pd,
|
||||
const RasterBase::Trafo & trafo,
|
||||
GammaFn && fn)
|
||||
: Base(res, pd, trafo, Colors<TColor>::White, Colors<TColor>::Black,
|
||||
RasterGrayscaleAA(const Resolution &res,
|
||||
const PixelDim &pd,
|
||||
const RasterBase::Trafo &trafo,
|
||||
GammaFn &&fn)
|
||||
: Base(res,
|
||||
pd,
|
||||
trafo,
|
||||
Colors<TColor>::White,
|
||||
Colors<TColor>::Black,
|
||||
std::forward<GammaFn>(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))
|
||||
{}
|
||||
};
|
||||
|
@ -68,10 +68,10 @@ EncodedRaster PPMRasterEncoder::operator()(const void *ptr, size_t w, size_t h,
|
||||
}
|
||||
|
||||
std::unique_ptr<RasterBase> 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<RasterBase> rst;
|
||||
|
||||
|
@ -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<EncodedRaster(const void *ptr, size_t w, size_t h, size_t num_components)>;
|
||||
|
||||
@ -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<RasterBase> 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
|
||||
|
||||
|
@ -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_archiver || !printer_diff.empty()) {
|
||||
if (m_printer_config.sla_archive_format.value == "SL1")
|
||||
m_archiver = std::make_unique<SL1Archive>(m_printer_config);
|
||||
else if (m_printer_config.sla_archive_format.value == "SL2")
|
||||
m_archiver = std::make_unique<SL1_SVGArchive>(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,9 @@ bool SLAPrint::invalidate_state_by_config_options(const std::vector<t_config_opt
|
||||
"display_pixels_y",
|
||||
"display_mirror_x",
|
||||
"display_mirror_y",
|
||||
"display_orientation"
|
||||
"display_orientation",
|
||||
"sla_archive_format",
|
||||
"sla_output_precision"
|
||||
};
|
||||
|
||||
static std::unordered_set<std::string> steps_ignore = {
|
||||
|
@ -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<class Fn, class CancelFn, class EP = ExecutionTBB>
|
||||
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<PrintLayer>& print_layers() const { return m_printer_input; }
|
||||
|
||||
void set_printer(SLAArchive *archiver);
|
||||
|
||||
void export_print(Zipper &zipper, const std::string &projectname = "")
|
||||
{
|
||||
m_archiver->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<PrintLayer> m_printer_input;
|
||||
|
||||
// The archive object which collects the raster images after slicing
|
||||
SLAArchive *m_printer = nullptr;
|
||||
std::unique_ptr<SLAArchive> m_archiver;
|
||||
|
||||
// Estimated print time, material consumed.
|
||||
SLAPrintStatistics m_print_statistics;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -190,7 +190,7 @@ void BackgroundSlicingProcess::process_sla()
|
||||
ThumbnailsParams{current_print()->full_print_config().option<ConfigOptionPoints>("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<ConfigOptionPoints>("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);
|
||||
|
@ -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.
|
||||
|
@ -2518,6 +2518,11 @@ 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");
|
||||
optgroup->append_single_option_line("sla_output_precision");
|
||||
|
||||
build_print_host_upload_group(page.get());
|
||||
|
||||
const int notes_field_height = 25; // 250
|
||||
|
@ -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<ExPolygons> 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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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.;
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user