WIP
wip
This commit is contained in:
parent
b45c6ef173
commit
72da90d28f
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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))
|
||||
{}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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