Working svg import

Strange bug in export, see line 111
This commit is contained in:
tamasmeszaros 2022-04-22 18:25:03 +02:00
parent 4ef860811f
commit 885e6964ba
5 changed files with 128 additions and 53 deletions

View File

@ -264,28 +264,7 @@ template<> struct _RasterTraits<Slic3r::png::ImageGreyscale> {
namespace Slic3r {
namespace {
ExPolygons rings_to_expolygons(const std::vector<marchsq::Ring> &rings,
double px_w, double px_h)
{
auto polys = reserve_vector<ExPolygon>(rings.size());
for (const marchsq::Ring &ring : rings) {
Polygon poly; Points &pts = poly.points;
pts.reserve(ring.size());
for (const marchsq::Coord &crd : ring)
pts.emplace_back(scaled(crd.c * px_w), scaled(crd.r * px_h));
polys.emplace_back(poly);
}
// TODO: Is a union necessary?
return union_ex(polys);
}
template<class Fn> void foreach_vertex(ExPolygon &poly, Fn &&fn)
template<class Fn> static void foreach_vertex(ExPolygon &poly, Fn &&fn)
{
for (auto &p : poly.contour.points) fn(p);
for (auto &h : poly.holes)
@ -318,6 +297,27 @@ void invert_raster_trafo(ExPolygons & expolys,
}
}
namespace {
ExPolygons rings_to_expolygons(const std::vector<marchsq::Ring> &rings,
double px_w, double px_h)
{
auto polys = reserve_vector<ExPolygon>(rings.size());
for (const marchsq::Ring &ring : rings) {
Polygon poly; Points &pts = poly.points;
pts.reserve(ring.size());
for (const marchsq::Coord &crd : ring)
pts.emplace_back(scaled(crd.c * px_w), scaled(crd.r * px_h));
polys.emplace_back(poly);
}
// TODO: Is a union necessary?
return union_ex(polys);
}
struct RasterParams {
sla::RasterBase::Trafo trafo; // Raster transformations
coord_t width, height; // scaled raster dimensions (not resolution)

View File

@ -60,6 +60,11 @@ public:
{}
};
void invert_raster_trafo(ExPolygons & expolys,
const sla::RasterBase::Trafo &trafo,
coord_t width,
coord_t height);
} // namespace Slic3r::sla
#endif // ARCHIVETRAITS_HPP

View File

@ -77,10 +77,25 @@ void transform(ExPolygon &ep, const sla::RasterBase::Trafo &tr, const BoundingBo
void append_svg(std::string &buf, const Polygon &poly)
{
// if (poly.points.empty())
// return;
// char intbuf[coord_t_bufsize];
// buf += "<path d=\"M "sv;
// for (auto &p : poly) {
// buf += " "sv;
// buf += decimal_from(p.x(), intbuf);
// buf += " "sv;
// buf += decimal_from(p.y(), intbuf);
// }
// buf += " z\""sv; // mark path as closed
// buf += " />\n"sv;
if (poly.points.empty())
return;
auto c = poly.points.front();
Point c = poly.points.front();
char intbuf[coord_t_bufsize];
@ -90,14 +105,15 @@ void append_svg(std::string &buf, const Polygon &poly)
buf += decimal_from(c.y(), intbuf);
buf += " m"sv;
for (auto &p : poly) {
auto d = p - c;
if (d.squaredNorm() == 0) continue;
buf += " "sv;
buf += decimal_from(p.x() - c.x(), intbuf);
buf += " "sv;
buf += decimal_from(p.y() - c.y(), intbuf);
for (const Point &p : poly) {
Point d = p - c;
c = p;
// if (d.x() == 0 && d.y() == 0)
// continue;
buf += " "sv;
buf += decimal_from(d.x(), intbuf);
buf += " "sv;
buf += decimal_from(d.y(), intbuf);
}
buf += " z\""sv; // mark path as closed
buf += " />\n"sv;
@ -142,9 +158,6 @@ public:
"<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
@ -193,8 +206,6 @@ 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);
@ -238,10 +249,50 @@ void SL1_SVGArchive::export_print(const std::string fname,
SL1Archive::export_print(zipper, print, thumbnails, projectname);
}
struct RasterParams {
sla::RasterBase::Trafo trafo; // Raster transformations
coord_t width, height; // scaled raster dimensions (not resolution)
};
RasterParams get_raster_params(const DynamicPrintConfig &cfg)
{
auto *opt_disp_cols = cfg.option<ConfigOptionInt>("display_pixels_x");
auto *opt_disp_rows = cfg.option<ConfigOptionInt>("display_pixels_y");
auto *opt_disp_w = cfg.option<ConfigOptionFloat>("display_width");
auto *opt_disp_h = cfg.option<ConfigOptionFloat>("display_height");
auto *opt_mirror_x = cfg.option<ConfigOptionBool>("display_mirror_x");
auto *opt_mirror_y = cfg.option<ConfigOptionBool>("display_mirror_y");
auto *opt_orient = cfg.option<ConfigOptionEnum<SLADisplayOrientation>>("display_orientation");
if (!opt_disp_cols || !opt_disp_rows || !opt_disp_w || !opt_disp_h ||
!opt_mirror_x || !opt_mirror_y || !opt_orient)
throw MissingProfileError("Invalid SL1 / SL1S file");
RasterParams rstp;
rstp.trafo = sla::RasterBase::Trafo{opt_orient->value == sladoLandscape ?
sla::RasterBase::roLandscape :
sla::RasterBase::roPortrait,
{opt_mirror_x->value, opt_mirror_y->value}};
rstp.height = scaled(opt_disp_h->value);
rstp.width = scaled(opt_disp_w->value);
return rstp;
}
struct NanoSVGParser {
NSVGimage *image;
static constexpr const char *Units = "mm"; // Denotes user coordinate system
static constexpr float Dpi = 1.f; // Not needed
NanoSVGParser(char* input): image{nsvgParse(input, Units, Dpi)} {}
~NanoSVGParser() { nsvgDelete(image); }
};
ConfigSubstitutions SL1_SVGReader::read(std::vector<ExPolygons> &slices,
DynamicPrintConfig &profile_out)
{
std::vector<std::string> includes = { "config.ini", "prusaslicer.ini", "svg"};
std::vector<std::string> includes = { CONFIG_FNAME, PROFILE_FNAME, "svg"};
ZipperArchive arch = read_zipper_archive(m_fname, includes, {});
DynamicPrintConfig profile_in, profile_use;
@ -271,25 +322,44 @@ ConfigSubstitutions SL1_SVGReader::read(std::vector<ExPolygons> &slices,
profile_use = profile_in.empty() ? profile_out : profile_in;
profile_out = profile_in;
RasterParams rstp = get_raster_params(profile_use);
struct Status
{
double incr, val, prev;
bool stop = false;
} st{100. / arch.entries.size(), 0., 0.};
for (const EntryBuffer &entry : arch.entries) {
NSVGimage* image;
if (st.stop) break;
st.val += st.incr;
double curr = std::round(st.val);
if (curr > st.prev) {
st.prev = curr;
st.stop = !m_progr(int(curr));
}
auto svgtxt = reserve_vector<char>(entry.buf.size());
std::copy(entry.buf.begin(), entry.buf.end(), std::back_inserter(svgtxt));
image = nsvgParse(svgtxt.data(), "px", 96);
printf("size: %f x %f\n", image->width, image->height);
// Use...
for (NSVGshape *shape = image->shapes; shape != nullptr; shape = shape->next) {
for (NSVGpath *path = shape->paths; path != nullptr; path = path->next) {
NanoSVGParser svgp(svgtxt.data());
Polygons polys;
for (NSVGshape *shape = svgp.image->shapes; shape != nullptr; shape = shape->next) {
for (NSVGpath *path = shape->paths; path != nullptr; path = path->next) {
Polygon p;
for (int i = 0; i < path->npts; ++i) {
size_t c = 2 * i;
p.points.emplace_back(scaled(Vec2f(path->pts[c], path->pts[c + 1])));
}
polys.emplace_back(p);
}
}
// Delete
nsvgDelete(image);
}
// RasterParams rstp = get_raster_params(profile_use);
// rstp.win = {windowsize.y(), windowsize.x()};
// slices = extract_slices_from_sla_archive(arch, rstp, m_progr);
ExPolygons expolys = union_ex(polys);
invert_raster_trafo(expolys, rstp.trafo, rstp.width, rstp.height);
slices.emplace_back(expolys);
}
return config_substitutions;
}

View File

@ -9,9 +9,6 @@
namespace Slic3r {
static const constexpr char *CONFIG_FNAME = "config.ini";
static const constexpr char *PROFILE_FNAME = "prusaslicer.ini";
namespace {
boost::property_tree::ptree read_ini(const mz_zip_archive_file_stat &entry,
@ -83,8 +80,8 @@ ZipperArchive read_zipper_archive(const std::string &zipfname,
}))
continue;
if (name == CONFIG_FNAME) arch.config = read_ini(entry, zip);
if (name == PROFILE_FNAME) arch.profile = read_ini(entry, zip);
if (name == CONFIG_FNAME) { arch.config = read_ini(entry, zip); continue; }
if (name == PROFILE_FNAME) { arch.profile = read_ini(entry, zip); continue; }
auto it = std::lower_bound(
arch.entries.begin(), arch.entries.end(),

View File

@ -21,6 +21,9 @@ struct ZipperArchive
std::vector<EntryBuffer> entries;
};
const constexpr char *CONFIG_FNAME = "config.ini";
const constexpr char *PROFILE_FNAME = "prusaslicer.ini";
ZipperArchive read_zipper_archive(const std::string &zipfname,
const std::vector<std::string> &includes,
const std::vector<std::string> &excludes);