mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-05 16:10:44 +08:00
Partial store to svg
This commit is contained in:
parent
c63f9f3e11
commit
1e1caad019
@ -3,6 +3,10 @@
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
Slic3r::Polygons to_polygons(const NSVGshape &shape, float tessTol, int max_level, float scale, bool is_y_negative);
|
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
|
||||||
|
|
||||||
namespace Slic3r {
|
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)
|
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");
|
FILE * file = boost::nowide::fopen(svg_file_path.c_str(), "w");
|
||||||
if (file == NULL)
|
if (file == NULL)
|
||||||
return false;
|
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) {
|
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
|
std::string d = "M "; // move on start point
|
||||||
for (const NSVGpath *path = shape->paths; path != NULL; path = path->next) {
|
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) {
|
for (size_t i = 0; i < path_size; i += 3) {
|
||||||
const float *p = &path->pts[i * 2];
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
d += "Z"; // closed path
|
if (type != Type::close) {
|
||||||
fprintf(file, " <path fill=\"#D2D2D2\" d=\"%s\" />\n", d.c_str());
|
type = Type::close;
|
||||||
|
d += "Z"; // closed path
|
||||||
|
}
|
||||||
|
fprintf(file, "<path fill=\"#D2D2D2\" d=\"%s\" />\n", d.c_str());
|
||||||
}
|
}
|
||||||
fprintf(file, "</svg>\n");
|
fprintf(file, "</svg>\n");
|
||||||
fclose(file);
|
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)
|
// 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 p1(p[0], p[1]);
|
||||||
//Vec2f p2(p[2], p[3]);
|
//Vec2f p2(p[2], p[3]);
|
||||||
//Vec2f p3(p[4], p[5]);
|
//Vec2f p3(p[4], p[5]);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user