From 1ecf1c805f203a9a1df35dce0ba80f7f65896ad5 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Sat, 9 Jul 2016 11:44:45 +0200 Subject: [PATCH] Raft for SVG export --- xs/src/libslic3r/ClipperUtils.cpp | 12 ++++++++ xs/src/libslic3r/ClipperUtils.hpp | 3 ++ xs/src/libslic3r/MotionPlanner.cpp | 2 +- xs/src/libslic3r/PrintConfig.cpp | 9 ++++++ xs/src/libslic3r/PrintConfig.hpp | 4 +++ xs/src/libslic3r/SVGExport.cpp | 44 ++++++++++++++++++++++++------ 6 files changed, 64 insertions(+), 10 deletions(-) diff --git a/xs/src/libslic3r/ClipperUtils.cpp b/xs/src/libslic3r/ClipperUtils.cpp index aea0ef5959..3490118ee3 100644 --- a/xs/src/libslic3r/ClipperUtils.cpp +++ b/xs/src/libslic3r/ClipperUtils.cpp @@ -222,6 +222,18 @@ offset_ex(const Slic3r::Polygons &polygons, const float delta, return expp; } +Slic3r::ExPolygons +offset_ex(const Slic3r::ExPolygons &expolygons, const float delta, + double scale, ClipperLib::JoinType joinType, double miterLimit) +{ + Slic3r::Polygons pp; + for (Slic3r::ExPolygons::const_iterator ex = expolygons.begin(); ex != expolygons.end(); ++ex) { + Slic3r::Polygons pp2 = *ex; + pp.insert(pp.end(), pp2.begin(), pp2.end()); + } + return offset_ex(pp, delta, scale, joinType, miterLimit); +} + void offset2(const Slic3r::Polygons &polygons, ClipperLib::Paths* retval, const float delta1, const float delta2, const double scale, const ClipperLib::JoinType joinType, const double miterLimit) diff --git a/xs/src/libslic3r/ClipperUtils.hpp b/xs/src/libslic3r/ClipperUtils.hpp index f3ab6158e4..4bc5ceb89a 100644 --- a/xs/src/libslic3r/ClipperUtils.hpp +++ b/xs/src/libslic3r/ClipperUtils.hpp @@ -61,6 +61,9 @@ void offset(const Slic3r::Polygons &polygons, Slic3r::ExPolygons* retval, const Slic3r::ExPolygons offset_ex(const Slic3r::Polygons &polygons, const float delta, double scale = 100000, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3); +Slic3r::ExPolygons offset_ex(const Slic3r::ExPolygons &expolygons, const float delta, + double scale = 100000, ClipperLib::JoinType joinType = ClipperLib::jtMiter, + double miterLimit = 3); void offset2(const Slic3r::Polygons &polygons, ClipperLib::Paths* retval, const float delta1, const float delta2, double scale = 100000, ClipperLib::JoinType joinType = ClipperLib::jtMiter, diff --git a/xs/src/libslic3r/MotionPlanner.cpp b/xs/src/libslic3r/MotionPlanner.cpp index 21afb37c41..a1df679cfd 100644 --- a/xs/src/libslic3r/MotionPlanner.cpp +++ b/xs/src/libslic3r/MotionPlanner.cpp @@ -142,7 +142,7 @@ MotionPlanner::shortest_path(const Point &from, const Point &to) { // grow our environment slightly in order for simplify_by_visibility() // to work best by considering moves on boundaries valid as well - ExPolygonCollection grown_env(offset_ex(env.env, +SCALED_EPSILON)); + ExPolygonCollection grown_env(offset_ex((Polygons)env.env, +SCALED_EPSILON)); if (island_idx == -1) { /* If 'from' or 'to' are not inside our env, they were connected using the diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp index 58d9437e75..1438bb2967 100644 --- a/xs/src/libslic3r/PrintConfig.cpp +++ b/xs/src/libslic3r/PrintConfig.cpp @@ -754,6 +754,15 @@ PrintConfigDef::PrintConfigDef() def->min = 0; def->default_value = new ConfigOptionInt(0); + def = this->add("raft_offset", coFloat); + def->label = "Raft offset"; + def->category = "Support material"; + def->tooltip = "Horizontal margin between object base layer and raft contour."; + def->sidetext = "mm"; + def->cli = "raft-offset=f"; + def->min = 0; + def->default_value = new ConfigOptionFloat(4); + def = this->add("resolution", coFloat); def->label = "Resolution"; def->tooltip = "Minimum detail resolution, used to simplify the input file for speeding up the slicing job and reducing memory usage. High-resolution models often carry more detail than printers can render. Set to zero to disable any simplification and use full resolution from input."; diff --git a/xs/src/libslic3r/PrintConfig.hpp b/xs/src/libslic3r/PrintConfig.hpp index 9cae88b65a..345406a6d5 100644 --- a/xs/src/libslic3r/PrintConfig.hpp +++ b/xs/src/libslic3r/PrintConfig.hpp @@ -472,6 +472,8 @@ class SVGExportConfig public: ConfigOptionFloatOrPercent first_layer_height; ConfigOptionFloat layer_height; + ConfigOptionInt raft_layers; + ConfigOptionFloat raft_offset; SVGExportConfig() : StaticPrintConfig() { this->set_defaults(); @@ -480,6 +482,8 @@ class SVGExportConfig virtual ConfigOption* optptr(const t_config_option_key &opt_key, bool create = false) { OPT_PTR(first_layer_height); OPT_PTR(layer_height); + OPT_PTR(raft_layers); + OPT_PTR(raft_offset); return NULL; }; diff --git a/xs/src/libslic3r/SVGExport.cpp b/xs/src/libslic3r/SVGExport.cpp index cd83e5ccab..d27a1cede2 100644 --- a/xs/src/libslic3r/SVGExport.cpp +++ b/xs/src/libslic3r/SVGExport.cpp @@ -1,5 +1,5 @@ #include "SVGExport.hpp" -#include "SVG.hpp" +#include "ClipperUtils.hpp" #include #include #define COORD(x) ((float)unscale(x)*10) @@ -9,13 +9,39 @@ namespace Slic3r { void SVGExport::writeSVG(const std::string &outputfile) { - std::vector heights; - for (float z = this->config.first_layer_height.value; z <= this->mesh->stl.stats.max.z; - z += this->config.layer_height.value) - heights.push_back(z); - + // if we are generating a raft, first_layer_height will not affect mesh slicing + const float lh = this->config.layer_height.value; + const float first_lh = this->config.first_layer_height.value; + + // generate the list of Z coordinates for mesh slicing + // (we slice each layer at half of its thickness) + std::vector slice_z, layer_z; + { + const float first_slice_lh = (this->config.raft_layers > 0) ? lh : first_lh; + slice_z.push_back(first_slice_lh/2); + layer_z.push_back(first_slice_lh); + } + while (layer_z.back() + lh/2 <= this->mesh->stl.stats.max.z) { + slice_z.push_back(layer_z.back() + lh/2); + layer_z.push_back(layer_z.back() + lh); + } + + // perform the slicing std::vector layers; - TriangleMeshSlicer(this->mesh).slice(heights, &layers); + TriangleMeshSlicer(this->mesh).slice(slice_z, &layers); + + // generate a solid raft if requested + if (this->config.raft_layers > 0) { + ExPolygons raft = offset_ex(layers.front(), scale_(this->config.raft_offset)); + for (int i = this->config.raft_layers; i >= 1; --i) { + layer_z.insert(layer_z.begin(), first_lh + lh * (i-1)); + layers.insert(layers.begin(), raft); + } + + // prepend total raft height to all sliced layers + for (int i = this->config.raft_layers; i < layer_z.size(); ++i) + layer_z[i] += first_lh + lh * (this->config.raft_layers-1); + } FILE* f = fopen(outputfile.c_str(), "w"); fprintf(f, @@ -27,8 +53,8 @@ SVGExport::writeSVG(const std::string &outputfile) // - for (size_t i = 0; i < heights.size(); ++i) { - fprintf(f, "\t\n", i, heights[i]); + for (size_t i = 0; i < layer_z.size(); ++i) { + fprintf(f, "\t\n", i, layer_z[i]); for (ExPolygons::const_iterator it = layers[i].begin(); it != layers[i].end(); ++it){ std::string pd; Polygons pp = *it;