WIP Brim improvements:

Fix of connecting the brim polylines: Don't connect closed contours.
Some optimizations, documentation etc.
This commit is contained in:
Vojtech Bubnik 2021-02-04 15:48:36 +01:00
parent d1dfbb31ab
commit ab6cc7085e
3 changed files with 52 additions and 38 deletions

View file

@ -34,9 +34,9 @@ static void append_and_translate(Polygons &dst, const Polygons &src, const Print
static float max_brim_width(const ConstPrintObjectPtrsAdaptor &objects) static float max_brim_width(const ConstPrintObjectPtrsAdaptor &objects)
{ {
assert(!objects.empty()); assert(!objects.empty());
return float(std::accumulate(objects.begin() + 1, objects.end(), objects.front()->config().brim_width.value, return float(std::accumulate(objects.begin(), objects.end(), 0.,
[](double partial_result, const PrintObject *object) { [](double partial_result, const PrintObject *object) {
return std::max(partial_result, object->config().brim_width.value); return std::max(partial_result, object->config().brim_type == btNoBrim ? 0. : object->config().brim_width.value);
})); }));
} }
@ -46,6 +46,7 @@ static ConstPrintObjectPtrs get_top_level_objects_with_brim(const Print &print)
ConstPrintObjectPtrs island_to_object; ConstPrintObjectPtrs island_to_object;
for (const PrintObject *object : print.objects()) { for (const PrintObject *object : print.objects()) {
Polygons islands_object; Polygons islands_object;
islands_object.reserve(object->layers().front()->lslices.size());
for (const ExPolygon &ex_poly : object->layers().front()->lslices) for (const ExPolygon &ex_poly : object->layers().front()->lslices)
islands_object.emplace_back(ex_poly.contour); islands_object.emplace_back(ex_poly.contour);
@ -101,6 +102,7 @@ static Polygons top_level_outer_brim_islands(const ConstPrintObjectPtrs &top_lev
{ {
Polygons islands; Polygons islands;
for (const PrintObject *object : top_level_objects_with_brim) { for (const PrintObject *object : top_level_objects_with_brim) {
//FIXME how about the brim type?
float brim_offset = float(scale_(object->config().brim_offset.value)); float brim_offset = float(scale_(object->config().brim_offset.value));
Polygons islands_object; Polygons islands_object;
for (const ExPolygon &ex_poly : object->layers().front()->lslices) { for (const ExPolygon &ex_poly : object->layers().front()->lslices) {
@ -206,6 +208,7 @@ static ExPolygons inner_brim_area(const Print &print, const ConstPrintObjectPtrs
return diff_ex(intersection_ex(to_polygons(std::move(brim_area)), holes), no_brim_area); return diff_ex(intersection_ex(to_polygons(std::move(brim_area)), holes), no_brim_area);
} }
// Flip orientation of open polylines to minimize travel distance.
static void optimize_polylines_by_reversing(Polylines *polylines) static void optimize_polylines_by_reversing(Polylines *polylines)
{ {
for (size_t poly_idx = 1; poly_idx < polylines->size(); ++poly_idx) { for (size_t poly_idx = 1; poly_idx < polylines->size(); ++poly_idx) {
@ -216,23 +219,24 @@ static void optimize_polylines_by_reversing(Polylines *polylines)
double dist_to_start = (next.first_point() - prev.last_point()).cast<double>().norm(); double dist_to_start = (next.first_point() - prev.last_point()).cast<double>().norm();
double dist_to_end = (next.last_point() - prev.last_point()).cast<double>().norm(); double dist_to_end = (next.last_point() - prev.last_point()).cast<double>().norm();
if (dist_to_end < dist_to_start) next.reverse(); if (dist_to_end < dist_to_start)
next.reverse();
} }
} }
} }
static Polylines connect_brim_lines(Polylines &&polylines, const Polygons &brim_area, float max_connection_length) static Polylines connect_brim_lines(Polylines &&polylines, const Polygons &brim_area, float max_connection_length)
{ {
EdgeGrid::Grid grid; if (polylines.empty())
BoundingBox bbox(get_extents(polylines)); return Polylines();
bbox.offset(SCALED_EPSILON);
grid.set_bbox(bbox);
std::vector<Points> polylines_points(polylines.size() + brim_area.size()); std::vector<Points> polylines_points(polylines.size() + brim_area.size());
for (const Polyline &poly : polylines) for (const Polyline &poly : polylines)
polylines_points[&poly - &polylines.front()] = poly.points; polylines_points[&poly - &polylines.front()] = poly.points;
for (const Polygon &poly : brim_area) for (const Polygon &poly : brim_area)
polylines_points.emplace_back(poly.points); polylines_points.emplace_back(poly.points);
EdgeGrid::Grid grid(get_extents(polylines).inflated(SCALED_EPSILON));
grid.create(polylines_points, coord_t(scale_(10.))); grid.create(polylines_points, coord_t(scale_(10.)));
struct Visitor struct Visitor
@ -262,30 +266,44 @@ static Polylines connect_brim_lines(Polylines &&polylines, const Polygons &brim_
} visitor(grid); } visitor(grid);
Polyline *prev = &polylines.front(); // Connect successive polylines if they are open, their ends are closer than max_connection_length.
for (size_t poly_idx = 1; poly_idx < polylines.size(); ++poly_idx) { // Remove empty polylines.
Polyline &next = polylines[poly_idx]; {
// Skip initial empty lines.
double dist = Line(prev->last_point(), next.first_point()).length(); size_t poly_idx = 0;
if (dist <= max_connection_length) { for (; poly_idx < polylines.size() && polylines[poly_idx].empty(); ++ poly_idx) ;
visitor.brim_line.a = prev->last_point(); size_t end = ++ poly_idx;
visitor.brim_line.b = next.first_point(); double max_connection_length2 = Slic3r::sqr(max_connection_length);
visitor.brim_line.extend(-SCALED_EPSILON); for (; poly_idx < polylines.size(); ++poly_idx) {
grid.visit_cells_intersecting_line(visitor.brim_line.a, visitor.brim_line.b, visitor); Polyline &next = polylines[poly_idx];
if (!visitor.intersect) if (! next.empty()) {
append(prev->points, std::move(next.points)); Polyline &prev = polylines[end - 1];
else bool connect = false;
prev = &next; if (! prev.is_closed() && ! next.is_closed()) {
double dist2 = (prev.last_point() - next.first_point()).cast<double>().squaredNorm();
if (dist2 <= max_connection_length2) {
visitor.brim_line.a = prev.last_point();
visitor.brim_line.b = next.first_point();
// Shrink the connection line to avoid collisions with the brim centerlines.
visitor.brim_line.extend(-SCALED_EPSILON);
grid.visit_cells_intersecting_line(visitor.brim_line.a, visitor.brim_line.b, visitor);
connect = ! visitor.intersect;
}
}
if (connect) {
append(prev.points, std::move(next.points));
} else {
if (end < poly_idx)
polylines[end] = std::move(next);
++ end;
}
}
} }
if (end < polylines.size())
polylines.erase(polylines.begin() + end, polylines.end());
} }
Polylines polylines_out; return polylines;
polylines_out.reserve(std::count_if(polylines.begin(), polylines.end(), [](const Polyline &pl) { return !pl.empty(); }));
for (Polyline &pl : polylines)
if (!pl.empty())
polylines_out.emplace_back(std::move(pl));
return polylines_out;
} }
static void make_inner_brim(const Print &print, const ConstPrintObjectPtrs &top_level_objects_with_brim, ExtrusionEntityCollection &brim) static void make_inner_brim(const Print &print, const ConstPrintObjectPtrs &top_level_objects_with_brim, ExtrusionEntityCollection &brim)
@ -349,6 +367,7 @@ ExtrusionEntityCollection make_brim(const Print &print, PrintTryCancel try_cance
append(all_loops, std::move(polylines)); append(all_loops, std::move(polylines));
loops_pl_by_levels.clear(); loops_pl_by_levels.clear();
// Flip orientation of open polylines to minimize travel distance.
optimize_polylines_by_reversing(&all_loops); optimize_polylines_by_reversing(&all_loops);
#ifdef BRIM_DEBUG_TO_SVG #ifdef BRIM_DEBUG_TO_SVG
@ -363,8 +382,7 @@ ExtrusionEntityCollection make_brim(const Print &print, PrintTryCancel try_cance
} }
#endif // BRIM_DEBUG_TO_SVG #endif // BRIM_DEBUG_TO_SVG
//FIXME WIP this breaks unit tests. all_loops = connect_brim_lines(std::move(all_loops), offset(islands_area_ex,SCALED_EPSILON), flow.scaled_spacing() * 2);
// all_loops = connect_brim_lines(std::move(all_loops), offset(islands_area_ex,SCALED_EPSILON), flow.scaled_spacing() * 2);
#ifdef BRIM_DEBUG_TO_SVG #ifdef BRIM_DEBUG_TO_SVG
{ {

View file

@ -25,11 +25,6 @@
namespace Slic3r { namespace Slic3r {
EdgeGrid::Grid::Grid() :
m_rows(0), m_cols(0)
{
}
EdgeGrid::Grid::~Grid() EdgeGrid::Grid::~Grid()
{ {
m_contours.clear(); m_contours.clear();

View file

@ -15,7 +15,8 @@ namespace EdgeGrid {
class Grid class Grid
{ {
public: public:
Grid(); Grid() = default;
Grid(const BoundingBox &bbox) : m_bbox(bbox) {}
~Grid(); ~Grid();
void set_bbox(const BoundingBox &bbox) { m_bbox = bbox; } void set_bbox(const BoundingBox &bbox) { m_bbox = bbox; }
@ -295,8 +296,8 @@ protected:
BoundingBox m_bbox; BoundingBox m_bbox;
// Grid dimensions. // Grid dimensions.
coord_t m_resolution; coord_t m_resolution;
size_t m_rows; size_t m_rows = 0;
size_t m_cols; size_t m_cols = 0;
// Referencing the source contours. // Referencing the source contours.
// This format allows one to work with any Slic3r fixed point contour format // This format allows one to work with any Slic3r fixed point contour format