mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-14 01:15:52 +08:00
Better support material in SVG export with conic tips
This commit is contained in:
parent
bca95a98c8
commit
0a15af5488
@ -42,41 +42,83 @@ SVGExport::writeSVG(const std::string &outputfile)
|
|||||||
TriangleMeshSlicer(&this->mesh).slice(slice_z, &layers);
|
TriangleMeshSlicer(&this->mesh).slice(slice_z, &layers);
|
||||||
|
|
||||||
// generate support material
|
// generate support material
|
||||||
std::vector<Points> support_material(layers.size());
|
std::vector<SupportPillar> sm_pillars;
|
||||||
|
ExPolygons overhangs;
|
||||||
if (this->config.support_material) {
|
if (this->config.support_material) {
|
||||||
// generate a grid of points according to the configured spacing,
|
// flatten and merge all the overhangs
|
||||||
// covering the entire object bounding box
|
{
|
||||||
Points support_material_points;
|
Polygons pp;
|
||||||
for (coordf_t x = bb.min.x; x <= bb.max.x; x += this->config.support_material_spacing) {
|
for (std::vector<ExPolygons>::const_iterator it = layers.begin()+1; it != layers.end(); ++it) {
|
||||||
for (coordf_t y = bb.min.y; y <= bb.max.y; y += this->config.support_material_spacing) {
|
Polygons oh = diff(*it, *(it - 1));
|
||||||
support_material_points.push_back(Point(scale_(x), scale_(y)));
|
pp.insert(pp.end(), oh.begin(), oh.end());
|
||||||
|
}
|
||||||
|
overhangs = union_ex(pp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate points following the shape of each island
|
||||||
|
Points pillars_pos;
|
||||||
|
const float spacing = scale_(this->config.support_material_spacing);
|
||||||
|
for (ExPolygons::const_iterator it = overhangs.begin(); it != overhangs.end(); ++it) {
|
||||||
|
for (float inset = -spacing/2; inset += spacing; ) {
|
||||||
|
// inset according to the configured spacing
|
||||||
|
Polygons curr = offset(*it, -inset);
|
||||||
|
if (curr.empty()) break;
|
||||||
|
|
||||||
|
// generate points along the contours
|
||||||
|
for (Polygons::const_iterator pg = curr.begin(); pg != curr.end(); ++pg) {
|
||||||
|
Points pp = pg->equally_spaced_points(spacing);
|
||||||
|
for (Points::const_iterator p = pp.begin(); p != pp.end(); ++p)
|
||||||
|
pillars_pos.push_back(*p);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check overhangs, starting from the upper layer, and detect which points apply
|
// for each pillar, check which layers it applies to
|
||||||
// to each layer
|
for (Points::const_iterator p = pillars_pos.begin(); p != pillars_pos.end(); ++p) {
|
||||||
ExPolygons overhangs;
|
SupportPillar pillar(*p);
|
||||||
for (int i = layer_z.size()-1; i >= 0; --i) {
|
bool object_hit = false;
|
||||||
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) {
|
// check layers top-down
|
||||||
for (ExPolygons::const_iterator e = overhangs.begin(); e != overhangs.end(); ++e) {
|
for (int i = layer_z.size()-1; i >= 0; --i) {
|
||||||
if (e->contains(*it)) {
|
// check whether point is void in this layer
|
||||||
support_material[i].push_back(*it);
|
bool is_void = true;
|
||||||
|
for (ExPolygons::const_iterator it = layers[i].begin(); it != layers[i].end(); ++it) {
|
||||||
|
if (it->contains(*p)) {
|
||||||
|
is_void = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_void) {
|
||||||
|
if (pillar.top_layer > 0) {
|
||||||
|
// we have a pillar, so extend it
|
||||||
|
pillar.bottom_layer = i + this->config.raft_layers;
|
||||||
|
} else if (object_hit) {
|
||||||
|
// we don't have a pillar and we're below the object, so create one
|
||||||
|
pillar.top_layer = i + this->config.raft_layers;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (pillar.top_layer > 0) {
|
||||||
|
// we have a pillar which is not needed anymore, so store it and initialize a new potential pillar
|
||||||
|
sm_pillars.push_back(pillar);
|
||||||
|
pillar = SupportPillar(*p);
|
||||||
|
}
|
||||||
|
object_hit = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (pillar.top_layer > 0) sm_pillars.push_back(pillar);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate a solid raft if requested
|
// generate a solid raft if requested
|
||||||
// (do this after support material because we take support material shape into account)
|
// (do this after support material because we take support material shape into account)
|
||||||
if (this->config.raft_layers > 0) {
|
if (this->config.raft_layers > 0) {
|
||||||
ExPolygons raft = offset_ex(layers.front(), scale_(this->config.raft_offset));
|
ExPolygons raft = layers.front();
|
||||||
|
raft.insert(raft.end(), overhangs.begin(), overhangs.end()); // take support material into account
|
||||||
|
raft = offset_ex(raft, scale_(this->config.raft_offset));
|
||||||
for (int i = this->config.raft_layers; i >= 1; --i) {
|
for (int i = this->config.raft_layers; i >= 1; --i) {
|
||||||
layer_z.insert(layer_z.begin(), first_lh + lh * (i-1));
|
layer_z.insert(layer_z.begin(), first_lh + lh * (i-1));
|
||||||
layers.insert(layers.begin(), raft);
|
layers.insert(layers.begin(), raft);
|
||||||
support_material.insert(support_material.begin(), Points()); // no support on this layer, we have raft
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// prepend total raft height to all sliced layers
|
// prepend total raft height to all sliced layers
|
||||||
@ -113,11 +155,25 @@ 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",
|
// don't print support material in raft layers
|
||||||
unscale(it->x), unscale(it->y), support_material_radius
|
if (i >= this->config.raft_layers) {
|
||||||
);
|
// look for support material pillars belonging to this layer
|
||||||
|
for (std::vector<SupportPillar>::const_iterator it = sm_pillars.begin(); it != sm_pillars.end(); ++it) {
|
||||||
|
if (!(it->top_layer >= i && it->bottom_layer <= i)) continue;
|
||||||
|
|
||||||
|
// generate a conic tip
|
||||||
|
float radius = fminf(
|
||||||
|
support_material_radius,
|
||||||
|
(it->top_layer - i + 1) * lh
|
||||||
|
);
|
||||||
|
|
||||||
|
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), radius
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(f,"\t</g>\n");
|
fprintf(f,"\t</g>\n");
|
||||||
}
|
}
|
||||||
fprintf(f,"</svg>\n");
|
fprintf(f,"</svg>\n");
|
||||||
|
@ -19,6 +19,13 @@ class SVGExport
|
|||||||
this->mesh.mirror_x();
|
this->mesh.mirror_x();
|
||||||
};
|
};
|
||||||
void writeSVG(const std::string &outputfile);
|
void writeSVG(const std::string &outputfile);
|
||||||
|
|
||||||
|
private:
|
||||||
|
class SupportPillar : public Point {
|
||||||
|
public:
|
||||||
|
size_t top_layer, bottom_layer;
|
||||||
|
SupportPillar(const Point &p) : Point(p), top_layer(0), bottom_layer(0) {};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user