diff --git a/xs/src/libslic3r/ClipperUtils.cpp b/xs/src/libslic3r/ClipperUtils.cpp index 3490118ee3..69c8643f37 100644 --- a/xs/src/libslic3r/ClipperUtils.cpp +++ b/xs/src/libslic3r/ClipperUtils.cpp @@ -486,6 +486,17 @@ void diff(const SubjectType &subject, const Slic3r::ExPolygons &clip, ResultType } template void diff(const Slic3r::Polygons &subject, const Slic3r::ExPolygons &clip, Slic3r::ExPolygons* retval, bool safety_offset_); +template +void diff(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, ResultType* retval, bool safety_offset_) +{ + Slic3r::Polygons pp; + for (Slic3r::ExPolygons::const_iterator ex = subject.begin(); ex != subject.end(); ++ex) { + Slic3r::Polygons ppp = *ex; + pp.insert(pp.end(), ppp.begin(), ppp.end()); + } + diff(pp, clip, retval, safety_offset_); +} + Slic3r::Polygons diff(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_) { @@ -504,6 +515,7 @@ diff_ex(const SubjectType &subject, const ClipType &clip, bool safety_offset_) } template Slic3r::ExPolygons diff_ex(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_); template Slic3r::ExPolygons diff_ex(const Slic3r::Polygons &subject, const Slic3r::ExPolygons &clip, bool safety_offset_); +template Slic3r::ExPolygons diff_ex(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, bool safety_offset_); template void intersection(const SubjectType &subject, const Slic3r::Polygons &clip, ResultType* retval, bool safety_offset_) @@ -596,6 +608,23 @@ void union_(const Slic3r::Polygons &subject1, const Slic3r::Polygons &subject2, union_(pp, retval, safety_offset); } +Slic3r::Polygons +union_(const Slic3r::ExPolygons &subject1, const Slic3r::ExPolygons &subject2, bool safety_offset) +{ + Polygons pp; + for (Slic3r::ExPolygons::const_iterator it = subject1.begin(); it != subject1.end(); ++it) { + Polygons spp = *it; + pp.insert(pp.end(), spp.begin(), spp.end()); + } + for (Slic3r::ExPolygons::const_iterator it = subject2.begin(); it != subject2.end(); ++it) { + Polygons spp = *it; + pp.insert(pp.end(), spp.begin(), spp.end()); + } + Polygons retval; + union_(pp, &retval, safety_offset); + return retval; +} + void union_pt(const Slic3r::Polygons &subject, ClipperLib::PolyTree* retval, bool safety_offset_) { Slic3r::Polygons clip; diff --git a/xs/src/libslic3r/ClipperUtils.hpp b/xs/src/libslic3r/ClipperUtils.hpp index 4bc5ceb89a..08697652c6 100644 --- a/xs/src/libslic3r/ClipperUtils.hpp +++ b/xs/src/libslic3r/ClipperUtils.hpp @@ -129,6 +129,7 @@ Slic3r::ExPolygons union_ex(const Slic3r::Polygons &subject, bool safety_offset Slic3r::ExPolygons union_ex(const Slic3r::Surfaces &subject, bool safety_offset = false); void union_(const Slic3r::Polygons &subject1, const Slic3r::Polygons &subject2, Slic3r::Polygons* retval, bool safety_offset = false); +Slic3r::Polygons union_(const Slic3r::ExPolygons &subject1, const Slic3r::ExPolygons &subject2, bool safety_offset = false); void union_pt(const Slic3r::Polygons &subject, ClipperLib::PolyTree* retval, bool safety_offset_ = false); void union_pt_chained(const Slic3r::Polygons &subject, Slic3r::Polygons* retval, bool safety_offset_ = false); diff --git a/xs/src/libslic3r/PrintConfig.hpp b/xs/src/libslic3r/PrintConfig.hpp index e943e058db..8aaebab350 100644 --- a/xs/src/libslic3r/PrintConfig.hpp +++ b/xs/src/libslic3r/PrintConfig.hpp @@ -490,6 +490,9 @@ class SVGExportConfig ConfigOptionFloat layer_height; ConfigOptionInt raft_layers; ConfigOptionFloat raft_offset; + ConfigOptionBool support_material; + ConfigOptionFloatOrPercent support_material_extrusion_width; + ConfigOptionFloat support_material_spacing; SVGExportConfig() : StaticPrintConfig() { this->set_defaults(); @@ -500,6 +503,9 @@ class SVGExportConfig OPT_PTR(layer_height); OPT_PTR(raft_layers); OPT_PTR(raft_offset); + OPT_PTR(support_material); + OPT_PTR(support_material_extrusion_width); + OPT_PTR(support_material_spacing); return NULL; }; diff --git a/xs/src/libslic3r/SVGExport.cpp b/xs/src/libslic3r/SVGExport.cpp index c34b5216ed..a209977cfc 100644 --- a/xs/src/libslic3r/SVGExport.cpp +++ b/xs/src/libslic3r/SVGExport.cpp @@ -17,6 +17,7 @@ SVGExport::writeSVG(const std::string &outputfile) bb.max.y += this->config.raft_offset.value; } this->mesh.translate(-bb.min.x, -bb.min.y, -bb.min.z); // align to origin + bb.translate(-bb.min.x, -bb.min.y, -bb.min.z); // align to origin const Sizef3 size = bb.size(); // if we are generating a raft, first_layer_height will not affect mesh slicing @@ -53,17 +54,47 @@ SVGExport::writeSVG(const std::string &outputfile) layer_z[i] += first_lh + lh * (this->config.raft_layers-1); } + // generate support material + std::vector support_material(layers.size()); + if (this->config.support_material) { + // generate a grid of points according to the configured spacing, + // covering the entire object bounding box + Points support_material_points; + for (coordf_t x = bb.min.x; x <= bb.max.x; x += this->config.support_material_spacing) { + for (coordf_t y = bb.min.y; y <= bb.max.y; y += this->config.support_material_spacing) { + support_material_points.push_back(Point(scale_(x), scale_(y))); + } + } + + // check overhangs, starting from the upper layer, and detect which points apply + // to each layer + ExPolygons overhangs; + for (int i = layer_z.size()-1; i >= 0; --i) { + overhangs = diff_ex(union_(overhangs, layers[i+1]), layers[i]); + for (Points::const_iterator it = support_material_points.begin(); it != support_material_points.end(); ++it) { + for (ExPolygons::const_iterator e = overhangs.begin(); e != overhangs.end(); ++e) { + if (e->contains(*it)) { + support_material[i].push_back(*it); + break; + } + } + } + } + } + + double support_material_radius = this->config.support_material_extrusion_width.get_abs_value(this->config.layer_height)/2; + FILE* f = fopen(outputfile.c_str(), "w"); fprintf(f, "\n" "\n" - "\n" + "\n" "\n" , size.x, size.y, SLIC3R_VERSION); 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){ + for (ExPolygons::const_iterator it = layers[i].begin(); it != layers[i].end(); ++it) { std::string pd; Polygons pp = *it; for (Polygons::const_iterator mp = pp.begin(); mp != pp.end(); ++mp) { @@ -80,6 +111,11 @@ SVGExport::writeSVG(const std::string &outputfile) pd.c_str(), "white", "black", "0", unscale(unscale(it->area())) ); } + for (Points::const_iterator it = support_material[i].begin(); it != support_material[i].end(); ++it) { + fprintf(f,"\t\t\n", + unscale(it->x), unscale(it->y), support_material_radius + ); + } fprintf(f,"\t\n"); } fprintf(f,"\n");