Added basic support material to SVG export

This commit is contained in:
Alessandro Ranellucci 2016-10-19 12:35:55 +02:00
parent 56334c49ac
commit 8910b4970a
4 changed files with 74 additions and 2 deletions

View File

@ -486,6 +486,17 @@ void diff(const SubjectType &subject, const Slic3r::ExPolygons &clip, ResultType
} }
template void diff<Slic3r::Polygons, Slic3r::ExPolygons>(const Slic3r::Polygons &subject, const Slic3r::ExPolygons &clip, Slic3r::ExPolygons* retval, bool safety_offset_); template void diff<Slic3r::Polygons, Slic3r::ExPolygons>(const Slic3r::Polygons &subject, const Slic3r::ExPolygons &clip, Slic3r::ExPolygons* retval, bool safety_offset_);
template <class ResultType>
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 Slic3r::Polygons
diff(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_) 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<Slic3r::Polygons, Slic3r::Polygons>(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_); template Slic3r::ExPolygons diff_ex<Slic3r::Polygons, Slic3r::Polygons>(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_);
template Slic3r::ExPolygons diff_ex<Slic3r::Polygons, Slic3r::ExPolygons>(const Slic3r::Polygons &subject, const Slic3r::ExPolygons &clip, bool safety_offset_); template Slic3r::ExPolygons diff_ex<Slic3r::Polygons, Slic3r::ExPolygons>(const Slic3r::Polygons &subject, const Slic3r::ExPolygons &clip, bool safety_offset_);
template Slic3r::ExPolygons diff_ex<Slic3r::ExPolygons, Slic3r::ExPolygons>(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, bool safety_offset_);
template <class SubjectType, class ResultType> template <class SubjectType, class ResultType>
void intersection(const SubjectType &subject, const Slic3r::Polygons &clip, ResultType* retval, bool safety_offset_) 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); 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_) void union_pt(const Slic3r::Polygons &subject, ClipperLib::PolyTree* retval, bool safety_offset_)
{ {
Slic3r::Polygons clip; Slic3r::Polygons clip;

View File

@ -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); 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); 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(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); void union_pt_chained(const Slic3r::Polygons &subject, Slic3r::Polygons* retval, bool safety_offset_ = false);

View File

@ -490,6 +490,9 @@ class SVGExportConfig
ConfigOptionFloat layer_height; ConfigOptionFloat layer_height;
ConfigOptionInt raft_layers; ConfigOptionInt raft_layers;
ConfigOptionFloat raft_offset; ConfigOptionFloat raft_offset;
ConfigOptionBool support_material;
ConfigOptionFloatOrPercent support_material_extrusion_width;
ConfigOptionFloat support_material_spacing;
SVGExportConfig() : StaticPrintConfig() { SVGExportConfig() : StaticPrintConfig() {
this->set_defaults(); this->set_defaults();
@ -500,6 +503,9 @@ class SVGExportConfig
OPT_PTR(layer_height); OPT_PTR(layer_height);
OPT_PTR(raft_layers); OPT_PTR(raft_layers);
OPT_PTR(raft_offset); OPT_PTR(raft_offset);
OPT_PTR(support_material);
OPT_PTR(support_material_extrusion_width);
OPT_PTR(support_material_spacing);
return NULL; return NULL;
}; };

View File

@ -17,6 +17,7 @@ SVGExport::writeSVG(const std::string &outputfile)
bb.max.y += this->config.raft_offset.value; bb.max.y += this->config.raft_offset.value;
} }
this->mesh.translate(-bb.min.x, -bb.min.y, -bb.min.z); // align to origin 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(); const Sizef3 size = bb.size();
// if we are generating a raft, first_layer_height will not affect mesh slicing // 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); layer_z[i] += first_lh + lh * (this->config.raft_layers-1);
} }
// generate support material
std::vector<Points> 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"); FILE* f = fopen(outputfile.c_str(), "w");
fprintf(f, fprintf(f,
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n"
"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.0//EN\" \"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\">\n" "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.0//EN\" \"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\">\n"
"<svg width=\"%f\" height=\"%f\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:svg=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:slic3r=\"http://slic3r.org/namespaces/slic3r\">\n" "<svg width=\"%f\" height=\"%f\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:svg=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:slic3r=\"http://slic3r.org/namespaces/slic3r\" viewport-fill=\"black\">\n"
"<!-- Generated using Slic3r %s http://slic3r.org/ -->\n" "<!-- Generated using Slic3r %s http://slic3r.org/ -->\n"
, size.x, size.y, SLIC3R_VERSION); , size.x, size.y, SLIC3R_VERSION);
for (size_t i = 0; i < layer_z.size(); ++i) { for (size_t i = 0; i < layer_z.size(); ++i) {
fprintf(f, "\t<g id=\"layer%zu\" slic3r:z=\"%0.4f\">\n", i, layer_z[i]); fprintf(f, "\t<g id=\"layer%zu\" slic3r:z=\"%0.4f\">\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; std::string pd;
Polygons pp = *it; Polygons pp = *it;
for (Polygons::const_iterator mp = pp.begin(); mp != pp.end(); ++mp) { 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())) 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<circle cx=\"%f\" cy=\"%f\" r=\"%f\" stroke-width=\"0\" fill=\"white\" slic3r:type=\"support\" />\n",
unscale(it->x), unscale(it->y), support_material_radius
);
}
fprintf(f,"\t</g>\n"); fprintf(f,"\t</g>\n");
} }
fprintf(f,"</svg>\n"); fprintf(f,"</svg>\n");