wip
This commit is contained in:
tamasmeszaros 2022-01-12 13:54:18 +01:00
parent b45c6ef173
commit 72da90d28f
10 changed files with 147 additions and 93 deletions

View File

@ -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();

View File

@ -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 += "<path d=\"M";
if (poly.points.empty())
return;
auto c = poly.points.front();
buf += "<path d=\"M " + std::to_string(c.x()) + " " + std::to_string(c.y()) + " m";
for (auto &p : poly) {
auto d = p - c;
if (d.squaredNorm() == 0) continue;
buf += " ";
buf += std::to_string(p.x());
buf += std::to_string(p.x() - c.x());
buf += " ";
buf += std::to_string(p.y());
buf += std::to_string(p.y() - c.y());
c = p;
}
buf += " z\""; // mark path as closed
buf += " />\n";
}
//static constexpr int precision = -1;
//void append_svg_fp(std::string &buf, const Polygon &poly)
//{
// if (poly.points.empty())
// return;
// auto c = poly.points.front();
// buf += "<path d=\"M " + float_to_string_decimal_point(unscaled<float>(c.x()), precision) +
// " " + float_to_string_decimal_point(unscaled<float>(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<float>(p.x() - c.x()), precision);
// buf += " ";
// buf += float_to_string_decimal_point(unscaled<float>(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;
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<float>(res.width_px));
std::string hf = float_to_string_decimal_point(unscaled<float>(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<float>(m_bb.size().x()));
std::string hf = float_to_string_decimal_point(unscaled<float>(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,20 +123,27 @@ public:
{
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 / 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; }
sla::EncodedRaster encode(sla::RasterEncoder /*encoder*/) const override
@ -116,8 +162,11 @@ public:
std::unique_ptr<sla::RasterBase> SL1_SVGArchive::create_raster() const
{
auto w = scaled<size_t>(cfg().display_width.getFloat());
auto h = scaled<size_t>(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<bool, 2> mirror;
@ -133,13 +182,14 @@ std::unique_ptr<sla::RasterBase> 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<SVGRaster>(res, tr);
return std::make_unique<SVGRaster>(svgarea, sla::Resolution{res_x * 4, res_y * 4}, tr);
}
sla::RasterEncoder SL1_SVGArchive::get_encoder() const

View File

@ -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,9 +212,9 @@ public:
class RasterGrayscaleAAGammaPower: public RasterGrayscaleAA {
public:
RasterGrayscaleAAGammaPower(const RasterBase::Resolution &res,
const RasterBase::PixelDim & pd,
const RasterBase::Trafo & trafo,
RasterGrayscaleAAGammaPower(const Resolution &res,
const PixelDim &pd,
const RasterBase::Trafo &trafo,
double gamma = 1.)
: RasterGrayscaleAA(res, pd, trafo, agg::gamma_power(gamma))
{}

View File

@ -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,
const Resolution &res,
const PixelDim &pxdim,
double gamma,
const RasterBase::Trafo & tr)
const RasterBase::Trafo &tr)
{
std::unique_ptr<RasterBase> rst;

View File

@ -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,
const Resolution &res,
const PixelDim &pxdim,
double gamma = 1.0,
const RasterBase::Trafo & tr = {});
const RasterBase::Trafo &tr = {});
}} // namespace Slic3r::sla

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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.;

View File

@ -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,