Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Port "No Unsupported Perimeters" feature from SS #3189

Merged
merged 15 commits into from
Jan 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 100 additions & 13 deletions src/libslic3r/BridgeDetector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -272,8 +272,56 @@ static void get_trapezoids2(const ExPolygon &expoly, Polygons* polygons, double
polygon.rotate(-(PI/2 - angle), Point(0,0));
}

// Coverage is currently only used by the unit tests. It is extremely slow and unreliable!
Polygons BridgeDetector::coverage(double angle) const


void get_trapezoids3_half(const ExPolygon& expoly, Polygons* polygons, float spacing)
{

// get all points of this ExPolygon
Points pp = to_points(expoly);

if (pp.empty()) return;

// build our bounding box
BoundingBox bb(pp);

// get all x coordinates
coord_t min_x = pp[0].x(), max_x = pp[0].x();
std::vector<coord_t> xx;
for (Points::const_iterator p = pp.begin(); p != pp.end(); ++p) {
if (min_x > p->x()) min_x = p->x();
if (max_x < p->x()) max_x = p->x();
}
for (coord_t x = min_x; x < max_x - (coord_t)(spacing / 2); x += (coord_t)spacing) {
xx.push_back(x);
}
xx.push_back(max_x);
//std::sort(xx.begin(), xx.end());

// find trapezoids by looping from first to next-to-last coordinate
for (std::vector<coord_t>::const_iterator x = xx.begin(); x != xx.end() - 1; ++x) {
coord_t next_x = *(x + 1);
if (*x == next_x) continue;

// build rectangle
Polygon poly;
poly.points.resize(4);
poly[0].x() = *x + (coord_t)spacing / 4;
poly[0].y() = bb.min(1);
poly[1].x() = next_x - (coord_t)spacing / 4;
poly[1].y() = bb.min(1);
poly[2].x() = next_x - (coord_t)spacing / 4;
poly[2].y() = bb.max(1);
poly[3].x() = *x + (coord_t)spacing / 4;
poly[3].y() = bb.max(1);

// intersect with this expolygon
// append results to return value
polygons_append(*polygons, intersection(Polygons{ poly }, to_polygons(expoly)));
}
}

Polygons BridgeDetector::coverage(double angle, bool precise) const
{
if (angle == -1)
angle = this->angle;
Expand All @@ -283,26 +331,65 @@ Polygons BridgeDetector::coverage(double angle) const
if (angle != -1) {
// Get anchors, convert them to Polygons and rotate them.
Polygons anchors = to_polygons(this->_anchor_regions);
polygons_rotate(anchors, PI/2.0 - angle);

polygons_rotate(anchors, PI / 2.0 - angle);
//same for region which do not need bridging
//Polygons supported_area = diff(this->lower_slices.expolygons, this->_anchor_regions, true);
//polygons_rotate(anchors, PI / 2.0 - angle);

for (ExPolygon expolygon : this->expolygons) {
// Clone our expolygon and rotate it so that we work with vertical lines.
expolygon.rotate(PI/2.0 - angle);
expolygon.rotate(PI / 2.0 - angle);
// Outset the bridge expolygon by half the amount we used for detecting anchors;
// we'll use this one to generate our trapezoids and be sure that their vertices
// are inside the anchors and not on their contours leading to false negatives.
for (ExPolygon &expoly : offset_ex(expolygon, 0.5f * float(this->spacing))) {
// Compute trapezoids according to a vertical orientation
Polygons trapezoids;
get_trapezoids2(expoly, &trapezoids, PI/2.0);
for (const Polygon &trapezoid : trapezoids) {
// not nice, we need a more robust non-numeric check
if (!precise) get_trapezoids2(expoly, &trapezoids, PI / 2);
else get_trapezoids3_half(expoly, &trapezoids, float(this->spacing));
for (Polygon &trapezoid : trapezoids) {
size_t n_supported = 0;
for (const Line &supported_line : intersection_ln(trapezoid.lines(), anchors))
if (supported_line.length() >= this->spacing)
++ n_supported;
if (n_supported >= 2)
if (!precise) {
// not nice, we need a more robust non-numeric check
// imporvment 1: take into account when we go in the supported area.
for (const Line &supported_line : intersection_ln(trapezoid.lines(), anchors))
if (supported_line.length() >= this->spacing)
++n_supported;
} else {
Polygons intersects = intersection(Polygons{trapezoid}, anchors);
n_supported = intersects.size();

if (n_supported >= 2) {
// trim it to not allow to go outside of the intersections
BoundingBox center_bound = intersects[0].bounding_box();
coord_t min_y = center_bound.center()(1), max_y = center_bound.center()(1);
for (Polygon &poly_bound : intersects) {
center_bound = poly_bound.bounding_box();
if (min_y > center_bound.center()(1)) min_y = center_bound.center()(1);
if (max_y < center_bound.center()(1)) max_y = center_bound.center()(1);
}
coord_t min_x = trapezoid[0](0), max_x = trapezoid[0](0);
for (Point &p : trapezoid.points) {
if (min_x > p(0)) min_x = p(0);
if (max_x < p(0)) max_x = p(0);
}
//add what get_trapezoids3 has removed (+EPSILON)
min_x -= (this->spacing / 4 + 1);
max_x += (this->spacing / 4 + 1);
coord_t mid_x = (min_x + max_x) / 2;
for (Point &p : trapezoid.points) {
if (p(1) < min_y) p(1) = min_y;
if (p(1) > max_y) p(1) = max_y;
if (p(0) > min_x && p(0) < mid_x) p(0) = min_x;
if (p(0) < max_x && p(0) > mid_x) p(0) = max_x;
}
}
}

if (n_supported >= 2) {
//add it
covered.push_back(std::move(trapezoid));
}
}
}
}
Expand All @@ -312,7 +399,7 @@ Polygons BridgeDetector::coverage(double angle) const
covered = union_(covered);
// Intersect trapezoids with actual bridge area to remove extra margins and append it to result.
polygons_rotate(covered, -(PI/2.0 - angle));
covered = intersection(this->expolygons, covered);
//covered = intersection(this->expolygons, covered);
#if 0
{
my @lines = map @{$_->lines}, @$trapezoids;
Expand Down
3 changes: 1 addition & 2 deletions src/libslic3r/BridgeDetector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,7 @@ class BridgeDetector {
BridgeDetector(const ExPolygons &_expolygons, const ExPolygons &_lower_slices, coord_t _extrusion_width);
// If bridge_direction_override != 0, then the angle is used instead of auto-detect.
bool detect_angle(double bridge_direction_override = 0.);
// Coverage is currently only used by the unit tests. It is extremely slow and unreliable!
Polygons coverage(double angle = -1) const;
Polygons coverage(double angle = -1, bool precise = true) const;
void unsupported_edges(double angle, Polylines* unsupported) const;
Polylines unsupported_edges(double angle = -1) const;

Expand Down
Loading
Loading