WIP Brim improvements:
Fix of connecting the brim polylines: Don't connect closed contours. Some optimizations, documentation etc.
This commit is contained in:
parent
d1dfbb31ab
commit
ab6cc7085e
3 changed files with 52 additions and 38 deletions
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue