mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-16 21:45:58 +08:00
Better bridge direction when only one anchor area
This commit is contained in:
parent
d4fe1e573d
commit
703e26bc6d
@ -97,22 +97,21 @@ bool BridgeDetector::detect_angle(double bridge_direction_override)
|
|||||||
for (size_t i_angle = 0; i_angle < candidates.size(); ++ i_angle)
|
for (size_t i_angle = 0; i_angle < candidates.size(); ++ i_angle)
|
||||||
{
|
{
|
||||||
const double angle = candidates[i_angle].angle;
|
const double angle = candidates[i_angle].angle;
|
||||||
|
|
||||||
Lines lines;
|
Lines lines;
|
||||||
{
|
{
|
||||||
// Get an oriented bounding box around _anchor_regions.
|
// Get an oriented bounding box around _anchor_regions.
|
||||||
BoundingBox bbox = get_extents_rotated(this->_anchor_regions, - angle);
|
BoundingBox bbox = get_extents_rotated(this->_anchor_regions, - angle);
|
||||||
// Cover the region with line segments.
|
// Cover the region with line segments.
|
||||||
lines.reserve((bbox.max(1) - bbox.min(1) + this->spacing) / this->spacing);
|
lines.reserve((bbox.max.y() - bbox.min.y() + this->spacing - SCALED_EPSILON) / this->spacing);
|
||||||
double s = sin(angle);
|
double s = sin(angle);
|
||||||
double c = cos(angle);
|
double c = cos(angle);
|
||||||
//FIXME Vojtech: The lines shall be spaced half the line width from the edge, but then
|
// As The lines be spaced half the line width from the edge
|
||||||
// some of the test cases fail. Need to adjust the test cases then?
|
// FIXME: some of the test cases may fail. Need to adjust the test cases
|
||||||
// for (coord_t y = bbox.min(1) + this->spacing / 2; y <= bbox.max(1); y += this->spacing)
|
for (coord_t y = bbox.min.y() + this->spacing / 2; y <= bbox.max.y(); y += this->spacing)
|
||||||
for (coord_t y = bbox.min(1); y <= bbox.max(1); y += this->spacing)
|
//for (coord_t y = bbox.min.y(); y <= bbox.max.y(); y += this->spacing) //this is the old version
|
||||||
lines.push_back(Line(
|
lines.push_back(Line(
|
||||||
Point((coord_t)round(c * bbox.min(0) - s * y), (coord_t)round(c * y + s * bbox.min(0))),
|
Point((coord_t)round(c * bbox.min.x() - s * y), (coord_t)round(c * y + s * bbox.min.x())),
|
||||||
Point((coord_t)round(c * bbox.max(0) - s * y), (coord_t)round(c * y + s * bbox.max(0)))));
|
Point((coord_t)round(c * bbox.max.x() - s * y), (coord_t)round(c * y + s * bbox.max.x()))));
|
||||||
}
|
}
|
||||||
|
|
||||||
//compute stat on line with anchors, and their lengths.
|
//compute stat on line with anchors, and their lengths.
|
||||||
@ -122,7 +121,13 @@ bool BridgeDetector::detect_angle(double bridge_direction_override)
|
|||||||
Lines clipped_lines = intersection_ln(lines, clip_area);
|
Lines clipped_lines = intersection_ln(lines, clip_area);
|
||||||
for (size_t i = 0; i < clipped_lines.size(); ++i) {
|
for (size_t i = 0; i < clipped_lines.size(); ++i) {
|
||||||
const Line &line = clipped_lines[i];
|
const Line &line = clipped_lines[i];
|
||||||
|
bool good_line = false;
|
||||||
if (expolygons_contain(this->_anchor_regions, line.a) && expolygons_contain(this->_anchor_regions, line.b)) {
|
if (expolygons_contain(this->_anchor_regions, line.a) && expolygons_contain(this->_anchor_regions, line.b)) {
|
||||||
|
//check that it isn't always inside
|
||||||
|
Lines lines = intersection_ln(line, to_polygons(this->_anchor_regions));
|
||||||
|
good_line = lines.size() > 1;
|
||||||
|
}
|
||||||
|
if(good_line) {
|
||||||
// This line could be anchored.
|
// This line could be anchored.
|
||||||
coordf_t len = line.length();
|
coordf_t len = line.length();
|
||||||
//store stats
|
//store stats
|
||||||
@ -154,11 +159,76 @@ bool BridgeDetector::detect_angle(double bridge_direction_override)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if no direction produced coverage, then there's no bridge direction
|
// if no direction produced coverage, then there's no bridge direction ?
|
||||||
if (! have_coverage)
|
if (!have_coverage) {
|
||||||
return false;
|
//try again to choose the least worse
|
||||||
|
// use only poly contour angles
|
||||||
|
if (bridge_direction_override == 0.) {
|
||||||
|
candidates = bridge_direction_candidates(true);
|
||||||
|
} else
|
||||||
|
candidates.emplace_back(BridgeDirection(bridge_direction_override));
|
||||||
|
for (size_t i_angle = 0; i_angle < candidates.size(); ++i_angle)
|
||||||
|
{
|
||||||
|
const double angle = candidates[i_angle].angle;
|
||||||
|
//use the whole polygon
|
||||||
|
Lines lines;
|
||||||
|
{
|
||||||
|
// Get an oriented bounding box around _anchor_regions.
|
||||||
|
BoundingBox bbox = get_extents_rotated(clip_area, -angle);
|
||||||
|
// Cover the region with line segments.
|
||||||
|
lines.reserve((bbox.max.y() - bbox.min.y() + this->spacing - SCALED_EPSILON) / this->spacing);
|
||||||
|
double s = sin(angle);
|
||||||
|
double c = cos(angle);
|
||||||
|
// The lines be spaced half the line width from the edge
|
||||||
|
for (coord_t y = bbox.min.y() + this->spacing / 2; y <= bbox.max.y(); y += this->spacing)
|
||||||
|
lines.push_back(Line(
|
||||||
|
Point((coord_t)round(c * bbox.min.x() - s * y), (coord_t)round(c * y + s * bbox.min.x())),
|
||||||
|
Point((coord_t)round(c * bbox.max.x() - s * y), (coord_t)round(c * y + s * bbox.max.x()))));
|
||||||
|
}
|
||||||
|
//compute stat on line with anchors, and their lengths.
|
||||||
|
BridgeDirection& c = candidates[i_angle];
|
||||||
|
std::vector<coordf_t> dist_anchored;
|
||||||
|
{
|
||||||
|
Lines clipped_lines = intersection_ln(lines, clip_area);
|
||||||
|
for (size_t i = 0; i < clipped_lines.size(); ++i) {
|
||||||
|
const Line& line = clipped_lines[i];
|
||||||
|
if (expolygons_contain(this->_anchor_regions, line.a) || expolygons_contain(this->_anchor_regions, line.b)) {
|
||||||
|
// This line has one anchor
|
||||||
|
coordf_t len = line.length();
|
||||||
|
//store stats
|
||||||
|
c.total_length_anchored += len;
|
||||||
|
c.max_length_anchored = std::max(c.max_length_anchored, len);
|
||||||
|
c.nb_lines_anchored++;
|
||||||
|
dist_anchored.push_back(len);
|
||||||
|
} else {
|
||||||
|
// this line could NOT be anchored.
|
||||||
|
coordf_t len = line.length();
|
||||||
|
c.total_length_free += len;
|
||||||
|
c.max_length_free = std::max(c.max_length_free, len);
|
||||||
|
c.nb_lines_free++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (c.total_length_anchored == 0. || c.nb_lines_anchored == 0) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
have_coverage = true;
|
||||||
|
// compute median
|
||||||
|
if (!dist_anchored.empty()) {
|
||||||
|
std::sort(dist_anchored.begin(), dist_anchored.end());
|
||||||
|
c.median_length_anchor = dist_anchored[dist_anchored.size() / 2];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// size is 20%
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if no direction produced coverage, then there's no bridge direction
|
||||||
|
if (!have_coverage)
|
||||||
|
return false;
|
||||||
|
|
||||||
//compute global stat (max & min median & max length)
|
//compute global stat (max & min median & max length)
|
||||||
std::vector<coordf_t> all_median_length;
|
std::vector<coordf_t> all_median_length;
|
||||||
std::vector<coordf_t> all_max_length;
|
std::vector<coordf_t> all_max_length;
|
||||||
@ -189,7 +259,7 @@ bool BridgeDetector::detect_angle(double bridge_direction_override)
|
|||||||
c.coverage += 15 * ratio_max;
|
c.coverage += 15 * ratio_max;
|
||||||
//bonus for perimeter dir
|
//bonus for perimeter dir
|
||||||
if (c.along_perimeter)
|
if (c.along_perimeter)
|
||||||
c.coverage += 0.05;
|
c.coverage += 5;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,12 +282,13 @@ bool BridgeDetector::detect_angle(double bridge_direction_override)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<BridgeDetector::BridgeDirection> BridgeDetector::bridge_direction_candidates() const
|
std::vector<BridgeDetector::BridgeDirection> BridgeDetector::bridge_direction_candidates(bool only_from_polygon) const
|
||||||
{
|
{
|
||||||
// we test angles according to configured resolution
|
|
||||||
std::vector<BridgeDirection> angles;
|
std::vector<BridgeDirection> angles;
|
||||||
for (int i = 0; i <= PI/this->resolution; ++i)
|
// we test angles according to configured resolution
|
||||||
angles.emplace_back(i * this->resolution);
|
if (!only_from_polygon)
|
||||||
|
for (int i = 0; i <= PI/this->resolution; ++i)
|
||||||
|
angles.emplace_back(i * this->resolution);
|
||||||
|
|
||||||
// we also test angles of each bridge contour
|
// we also test angles of each bridge contour
|
||||||
{
|
{
|
||||||
|
@ -63,7 +63,7 @@ private:
|
|||||||
};
|
};
|
||||||
public:
|
public:
|
||||||
// Get possible briging direction candidates.
|
// Get possible briging direction candidates.
|
||||||
std::vector<BridgeDirection> bridge_direction_candidates() const;
|
std::vector<BridgeDirection> bridge_direction_candidates(bool only_from_polygon = false) const;
|
||||||
|
|
||||||
// Open lines representing the supporting edges.
|
// Open lines representing the supporting edges.
|
||||||
Polylines _edges;
|
Polylines _edges;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user