Avoid placement of seams on bridging perimeters, if random seam is enabled.

https://github.com/alexrj/Slic3r/issues/3526#issuecomment-263125049
This commit is contained in:
bubnikv 2017-02-02 18:49:33 +01:00
parent 4256af22ff
commit 7e6390c4b6
4 changed files with 35 additions and 19 deletions

View file

@ -204,22 +204,38 @@ ExtrusionLoop::split_at_vertex(const Point &point)
return false;
}
void
ExtrusionLoop::split_at(const Point &point)
// Splitting an extrusion loop, possibly made of multiple segments, some of the segments may be bridging.
void ExtrusionLoop::split_at(const Point &point, bool prefer_non_overhang)
{
if (this->paths.empty()) return;
if (this->paths.empty())
return;
// find the closest path and closest point belonging to that path
// Find the closest path and closest point belonging to that path. Avoid overhangs, if asked for.
size_t path_idx = 0;
Point p = this->paths.front().first_point();
double min = point.distance_to(p);
for (ExtrusionPaths::const_iterator path = this->paths.begin(); path != this->paths.end(); ++path) {
Point p_tmp = point.projection_onto(path->polyline);
double dist = point.distance_to(p_tmp);
if (dist < min) {
p = p_tmp;
min = dist;
path_idx = path - this->paths.begin();
Point p;
{
double min = std::numeric_limits<double>::max();
Point p_non_overhang;
size_t path_idx_non_overhang = 0;
double min_non_overhang = std::numeric_limits<double>::max();
for (ExtrusionPaths::const_iterator path = this->paths.begin(); path != this->paths.end(); ++path) {
Point p_tmp = point.projection_onto(path->polyline);
double dist = point.distance_to(p_tmp);
if (dist < min) {
p = p_tmp;
min = dist;
path_idx = path - this->paths.begin();
}
if (prefer_non_overhang && ! path->is_bridge() && dist < min_non_overhang) {
p_non_overhang = p_tmp;
min_non_overhang = dist;
path_idx_non_overhang = path - this->paths.begin();
}
}
if (prefer_non_overhang && min_non_overhang != std::numeric_limits<double>::max()) {
// Only apply the non-overhang point if there is one.
path_idx = path_idx_non_overhang;
p = p_non_overhang;
}
}

View file

@ -218,7 +218,7 @@ class ExtrusionLoop : public ExtrusionEntity
Polygon polygon() const;
virtual double length() const;
bool split_at_vertex(const Point &point);
void split_at(const Point &point);
void split_at(const Point &point, bool prefer_non_overhang);
void clip_end(double distance, ExtrusionPaths* paths) const;
// Test, whether the point is extruded by a bridging flow.
// This used to be used to avoid placing seams on overhangs, but now the EdgeGrid is used instead.

View file

@ -571,7 +571,7 @@ GCode::extrude(ExtrusionLoop loop, std::string description, double speed)
// or randomize if requested
Point last_pos = this->last_pos();
if (this->config.spiral_vase) {
loop.split_at(last_pos);
loop.split_at(last_pos, false);
} else if (seam_position == spNearest || seam_position == spAligned) {
Polygon polygon = loop.polygon();
const coordf_t nozzle_dmr = EXTRUDER_CONFIG(nozzle_diameter);
@ -682,7 +682,7 @@ GCode::extrude(ExtrusionLoop loop, std::string description, double speed)
// Split the loop at the point with a minium penalty.
if (!loop.split_at_vertex(polygon.points[idx_min]))
// The point is not in the original loop. Insert it.
loop.split_at(polygon.points[idx_min]);
loop.split_at(polygon.points[idx_min], true);
} else if (seam_position == spRandom) {
if (loop.role == elrContourInternalPerimeter) {
@ -696,7 +696,7 @@ GCode::extrude(ExtrusionLoop loop, std::string description, double speed)
last_pos = Point(polygon.bounding_box().max.x, centroid.y);
last_pos.rotate(fmod((float)rand()/16.0, 2.0*PI), centroid);
}
loop.split_at(last_pos);
loop.split_at(last_pos, true);
}
// clip the path to avoid the extruder to get exactly on the first point of the loop;

View file

@ -21,8 +21,8 @@
double length();
bool split_at_vertex(Point* point)
%code{% RETVAL = THIS->split_at_vertex(*point); %};
void split_at(Point* point)
%code{% THIS->split_at(*point); %};
void split_at(Point* point, int prefer_non_overhang = 0)
%code{% THIS->split_at(*point, prefer_non_overhang != 0); %};
ExtrusionPaths clip_end(double distance)
%code{% THIS->clip_end(distance, &RETVAL); %};
bool has_overhang_point(Point* point)