Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/Ultimaker/CuraEngine.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorc.lamboo <casperlamboo@gmail.com>2022-10-25 12:18:04 +0300
committerc.lamboo <casperlamboo@gmail.com>2022-10-25 12:18:04 +0300
commit4565c7f7f0ac851e9fafb8058e3460c6739fda81 (patch)
treecbfec25b3e8a23df586b3182fae5f57b28aa7539
parent939f2a36ef7bb41196f76eba9efdd273d19f1cfb (diff)
Don't simplify polygon in FindStartLocation
But rather look at all points in a 1mm range. This provides the best of both worlds; sharp corners with lots of points are still detected and each point is a candidate seam location CURA-9486
-rw-r--r--include/PathOrderOptimizer.h104
1 files changed, 65 insertions, 39 deletions
diff --git a/include/PathOrderOptimizer.h b/include/PathOrderOptimizer.h
index d57b7ef99..cf8a75df8 100644
--- a/include/PathOrderOptimizer.h
+++ b/include/PathOrderOptimizer.h
@@ -22,7 +22,7 @@ namespace cura
/*!
* Path order optimization class.
- *
+ *
* Utility class for optimizing the order in which things are printed, by
* minimizing the distance traveled between different items to be printed. For
* each item to be printed, it also chooses a starting point as to where on the
@@ -418,36 +418,24 @@ protected:
// Don't know the path-type here, or whether it has a simplify. Also, simplification occurs in-place, which is not wanted here: Copy the polygon.
// A course simplification is needed, since Arachne has a tendency to 'smear' corners out over multiple line segments.
// Which in itself is a good thing, but will mess up the detection of sharp corners and such.
- Polygon simple_poly(*path.converted);
- if (seam_config.simplify_curvature > 0 && simple_poly.size() > 2)
- {
- // Simplify the polygons less when using USER_SPECIFIED, this will cause the seams to be much straighter
- // but "smooth" corners that are spread out over multiple points are less likely to be selected for the seam location.
- const coord_t max_simplify_dist = seam_config.type == EZSeamType::USER_SPECIFIED ? seam_config.simplify_curvature / 2 : seam_config.simplify_curvature;
-
- simple_poly = Simplify(max_simplify_dist, max_simplify_dist / 2, 0).polygon(simple_poly);
- }
- if(simple_poly.empty()) //Simplify removed everything because it's all too small.
- {
- simple_poly = Polygon(*path.converted); //Restore the original. We have to output a vertex as the seam position, so there needs to be a vertex.
- }
const Point focus_fixed_point = (seam_config.type == EZSeamType::USER_SPECIFIED)
- ? seam_config.pos
- : Point(0, std::sqrt(std::numeric_limits<coord_t>::max())); //Use sqrt, so the squared size can be used when comparing distances.
- const size_t start_from_pos = std::min_element(simple_poly.begin(), simple_poly.end(), [focus_fixed_point](const Point& a, const Point& b) {
- return vSize2(a - focus_fixed_point) < vSize2(b - focus_fixed_point);
- }) - simple_poly.begin();
- const size_t end_before_pos = simple_poly.size() + start_from_pos;
+ ? seam_config.pos
+ : Point(0, std::sqrt(std::numeric_limits<coord_t>::max())); //Use sqrt, so the squared size can be used when comparing distances.
+ const size_t start_from_pos = std::min_element(path.converted->begin(), path.converted->end(), [focus_fixed_point](const Point& a, const Point& b) {
+ return vSize2(a - focus_fixed_point) < vSize2(b - focus_fixed_point);
+ }) - path.converted->begin();
+ const size_t end_before_pos = path.converted->size() + start_from_pos;
// Find a seam position in the simple polygon:
+ size_t best_i;
Point best_point;
float best_score = std::numeric_limits<float>::infinity();
- Point previous = simple_poly[(start_from_pos - 1 + simple_poly.size()) % simple_poly.size()];
+ Point previous = (*path.converted)[(start_from_pos - 1 + path.converted->size()) % path.converted->size()];
for(size_t i = start_from_pos; i < end_before_pos; ++i)
{
- const Point& here = simple_poly[i % simple_poly.size()];
- const Point& next = simple_poly[(i + 1) % simple_poly.size()];
+ const Point& here = (*path.converted)[i % path.converted->size()];
+ const Point& next = (*path.converted)[(i + 1) % path.converted->size()];
//For most seam types, the shortest distance matters. Not for SHARPEST_CORNER though.
//For SHARPEST_CORNER, use a fixed starting score of 0.
@@ -455,7 +443,57 @@ protected:
? getDirectDistance(here, target_pos)
: getCombingDistance(here, target_pos);
const float score_distance = (seam_config.type == EZSeamType::SHARPEST_CORNER && seam_config.corner_pref != EZSeamCornerPrefType::Z_SEAM_CORNER_PREF_NONE) ? 0 : static_cast<float>(distance) / 1000000;
- const float corner_angle = LinearAlg2D::getAngleLeft(previous, here, next) / M_PI - 1; //Between -1 and 1.
+
+
+ float corner_angle = LinearAlg2D::getAngleLeft(previous, here, next) - M_PI;
+
+ // Some models have very sharp corners, but also have a high resolution. If a sharp corner
+ // consists of many points each point individual might have a shallow corner, but the
+ // collective angle of all nearby points is greater. To counter this the corner_angle is
+ // calculated from all points 1mm in front and 1mm behind there current point. Angles
+ // closer to the current point are weighted more than points further away. The formula for
+ // the angle weight is: 1 - (distance_to_query / 1mm)^3
+ const coord_t angle_query_distance = 1000;
+
+ // previous points
+ {
+ int offset_index = 1;
+ coord_t distance_to_query = vSize(here - previous);
+ while (distance_to_query < angle_query_distance)
+ {
+ const Point& previous_ = (*path.converted)[(i - offset_index - 1 + path.converted->size()) % path.converted->size()];
+ const Point& here_ = (*path.converted)[(i - offset_index + path.converted->size()) % path.converted->size()];
+ const Point& behind_next_ = (*path.converted)[(i - offset_index + 1 + path.converted->size()) % path.converted->size()];
+ // angles further away from the query point are weighted less
+ float threshold_ratio = distance_to_query / angle_query_distance;
+ float angle_weight = 1.0 - threshold_ratio * threshold_ratio * threshold_ratio;
+ corner_angle += (LinearAlg2D::getAngleLeft(previous_, here_, behind_next_) - M_PI) * angle_weight;
+ // update distance value
+ distance_to_query += vSize(here_ - previous_);
+ offset_index += 1;
+ }
+ }
+
+ // next points
+ {
+ coord_t distance_to_query = vSize(here - next);
+ int offset_index = 1;
+ while (distance_to_query < angle_query_distance)
+ {
+ const Point previous_ = (*path.converted)[(i + offset_index - 1) % path.converted->size()];
+ const Point here_ = (*path.converted)[(i + offset_index) % path.converted->size()];
+ const Point next_ = (*path.converted)[(i + offset_index + 1) % path.converted->size()];
+ // angles further away from the query point are weighted less
+ float threshold_ratio = distance_to_query / angle_query_distance;
+ float angle_weight = 1.0 - threshold_ratio * threshold_ratio * threshold_ratio;
+ corner_angle += (LinearAlg2D::getAngleLeft(previous_, here_, next_) - M_PI) * angle_weight;
+ // update distance value
+ distance_to_query += vSize(here_ - next_);
+ offset_index += 1;
+ }
+ }
+
+ corner_angle = std::max(-1.0, std::min(1.0, corner_angle / M_PI)); // Limit angle between -1 and 1.
// angles < 0 are concave (left turning)
// angles > 0 are convex (right turning)
@@ -518,31 +556,19 @@ protected:
{
best_point = here;
best_score = score;
+ best_i = i;
}
}
else if(score < best_score)
{
best_point = here;
best_score = score;
+ best_i = i;
}
previous = here;
}
- // Which point in the real deal is closest to the simple polygon version?
- size_t best_index = 0;
- coord_t closest_dist2 = std::numeric_limits<coord_t>::max();
- for (size_t i = 0; i < path.converted->size(); ++i)
- {
- const Point& here = (*path.converted)[i];
- const coord_t dist2 = vSize2(best_point - here);
- if (dist2 < closest_dist2)
- {
- closest_dist2 = dist2;
- best_index = i;
- }
- }
-
- return best_index;
+ return best_i % path.converted->size();
}
/*!