Partial store to svg

This commit is contained in:
Filip Sykala - NTB T15p 2023-07-26 11:04:24 +02:00
parent c63f9f3e11
commit 1e1caad019

View File

@ -3,6 +3,10 @@
namespace {
Slic3r::Polygons to_polygons(const NSVGshape &shape, float tessTol, int max_level, float scale, bool is_y_negative);
// see function nsvg__lineTo(NSVGparser* p, float x, float y)
bool is_line(const float *p, float precision = 1e-4);
} // namespace
namespace Slic3r {
@ -34,23 +38,102 @@ NSVGimage_ptr nsvgParseFromFile(const std::string &filename, const char *units,
bool save(const NSVGimage &image, const std::string &svg_file_path)
{
//BoundingBox bb = get_extents(to_polygons(image));
FILE * file = boost::nowide::fopen(svg_file_path.c_str(), "w");
if (file == NULL)
return false;
fprintf(file, "<svg xmlns=\"http://www.w3.org/2000/svg\">\n");
fprintf(file, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>");
Vec2f tl(std::numeric_limits<float>::max(), std::numeric_limits<float>::max());
Vec2f br(std::numeric_limits<float>::min(), std::numeric_limits<float>::min());
for (const NSVGshape *shape = image.shapes; shape != NULL; shape = shape->next)
for (const NSVGpath *path = shape->paths; path != NULL; path = path->next) {
if (tl.x() > path->bounds[0])
tl.x() = path->bounds[0];
if (tl.y() > path->bounds[1])
tl.y() = path->bounds[1];
if (br.x() < path->bounds[2])
br.x() = path->bounds[2];
if (br.y() < path->bounds[3])
br.y() = path->bounds[3];
}
tl.x() = std::floor(tl.x());
tl.y() = std::floor(tl.y());
br.x() = std::ceil(br.x());
br.y() = std::ceil(br.y());
Vec2f s = br - tl;
//// IMPROVE: use path bounds instead of BoundingBox
//BoundingBox bb = get_extents(to_polygons(image));
//// bb has opposit value of y axe
//// Values stored in point are fixed point numbers need extend
//Point s = bb.size() + Point(2, 2); // extended size
//Point tl(bb.min.x() - 1, -bb.max.y() - 1); // top left corner
//Point br(tl.x() + s.x(), tl.y() + s.y()); // bottom right
fprintf(file, "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"%dmm\" height=\"%dmm\" viewBox=\"%d %d %d %d\" >\n",
(int)s.x(), (int)s.y(), (int)tl.x(), (int)tl.y(), (int)br.x(), (int)br.y());
fprintf(file, "<!-- Created with PrusaSlicer (https://www.prusa3d.com/prusaslicer/) -->\n");
auto write_point = [](std::string &d, const float *p) {
d += std::to_string(p[0]) + "," + std::to_string(p[1]) + " ";
};
for (const NSVGshape *shape = image.shapes; shape != NULL; shape = shape->next) {
enum struct Type { move, line, curve, close }; // https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/d
Type type = Type::move;
std::string d = "M "; // move on start point
for (const NSVGpath *path = shape->paths; path != NULL; path = path->next) {
size_t path_size = (path->npts > 1) ? static_cast<size_t>(path->npts - 1) : 0;
if (path->npts <= 1)
continue;
if (type == Type::close) {
Type type = Type::move;
// NOTE: After close must be a space
d += " M "; // move on start point
}
//write_point(d, path->pts);
d += std::to_string(path->pts[0]) + "," + std::to_string(path->pts[1]) + " ";
size_t path_size = static_cast<size_t>(path->npts - 1);
if (path->closed) {
// Do not use last point in path it is duplicit
if (path->npts <= 4)
continue;
path_size = static_cast<size_t>(path->npts - 4);
}
for (size_t i = 0; i < path_size; i += 3) {
const float *p = &path->pts[i * 2];
d += std::to_string(p[0]) + "," + std::to_string(p[1]) + " ";
if (!::is_line(p)) {
if (type != Type::curve) {
type = Type::curve;
d += "C "; // start sequence of triplets defining curves
}
d += std::to_string(p[2]) + "," + std::to_string(p[3]) + " " +
std::to_string(p[4]) + "," + std::to_string(p[5]) + " " ;
} else {
if (type != Type::line) {
type = Type::line;
d += "L "; // start sequence of line points
}
}
d += std::to_string(p[6]) + "," + std::to_string(p[7]) + " ";
}
if (path->closed) {
type = Type::close;
d += "Z"; // start sequence of line points
}
}
if (type != Type::close) {
type = Type::close;
d += "Z"; // closed path
fprintf(file, " <path fill=\"#D2D2D2\" d=\"%s\" />\n", d.c_str());
}
fprintf(file, "<path fill=\"#D2D2D2\" d=\"%s\" />\n", d.c_str());
}
fprintf(file, "</svg>\n");
fclose(file);
@ -91,7 +174,7 @@ bool need_flattening(float tessTol, const Vec2f &p1, const Vec2f &p2, const Vec2
}
// see function nsvg__lineTo(NSVGparser* p, float x, float y)
bool is_line(const float *p, float precision = 1e-4){
bool is_line(const float *p, float precision){
//Vec2f p1(p[0], p[1]);
//Vec2f p2(p[2], p[3]);
//Vec2f p3(p[4], p[5]);