Updated weights for curve fitting, ensured snapping to sharp corners

Fixed debug exports after refactorings.
This commit is contained in:
PavelMikus 2022-04-14 11:53:00 +02:00
parent 43d9166382
commit e377e58cd2

View File

@ -722,16 +722,6 @@ struct SeamComparator {
return is_first_not_much_worse(a, b) && is_first_not_much_worse(b, a); return is_first_not_much_worse(a, b) && is_first_not_much_worse(b, a);
} }
//always nonzero, positive
float get_penalty(const SeamCandidate &a) const {
if (setup == SeamPosition::spRear) {
return a.position.y();
}
return (a.visibility + SeamPlacer::additional_angle_importance) * compute_angle_penalty(a.local_ccw_angle);
}
private:
float compute_angle_penalty(float ccw_angle) const { float compute_angle_penalty(float ccw_angle) const {
// This function is used: // This function is used:
// ((^(((1)/(x^(2)*3+1)))-1)/(-1))*1+((1)/(2+^(-x))) // ((^(((1)/(x^(2)*3+1)))-1)/(-1))*1+((1)/(2+^(-x)))
@ -757,15 +747,15 @@ void debug_export_points(const std::vector<PrintObjectSeamData::LayerSeams> &la
float max_weight = min_weight; float max_weight = min_weight;
for (const SeamCandidate &point : layers[layer_idx].points) { for (const SeamCandidate &point : layers[layer_idx].points) {
Vec3i color = value_rgbi(-PI, PI, point.local_ccw_angle); Vec3i color = value_to_rgbi(-PI, PI, point.local_ccw_angle);
std::string fill = "rgb(" + std::to_string(color.x()) + "," + std::to_string(color.y()) + "," std::string fill = "rgb(" + std::to_string(color.x()) + "," + std::to_string(color.y()) + ","
+ std::to_string(color.z()) + ")"; + std::to_string(color.z()) + ")";
angles_svg.draw(scaled(Vec2f(point.position.head<2>())), fill); angles_svg.draw(scaled(Vec2f(point.position.head<2>())), fill);
min_vis = std::min(min_vis, point.visibility); min_vis = std::min(min_vis, point.visibility);
max_vis = std::max(max_vis, point.visibility); max_vis = std::max(max_vis, point.visibility);
min_weight = std::min(min_weight, -comparator.get_penalty(point)); min_weight = std::min(min_weight, -comparator.compute_angle_penalty(point.local_ccw_angle));
max_weight = std::max(max_weight, -comparator.get_penalty(point)); max_weight = std::max(max_weight, -comparator.compute_angle_penalty(point.local_ccw_angle));
} }
@ -780,18 +770,18 @@ void debug_export_points(const std::vector<PrintObjectSeamData::LayerSeams> &la
SVG overhangs_svg {overhangs_file_name, bounding_box}; SVG overhangs_svg {overhangs_file_name, bounding_box};
for (const SeamCandidate &point : layers[layer_idx].points) { for (const SeamCandidate &point : layers[layer_idx].points) {
Vec3i color = value_rgbi(min_vis, max_vis, point.visibility); Vec3i color = value_to_rgbi(min_vis, max_vis, point.visibility);
std::string visibility_fill = "rgb(" + std::to_string(color.x()) + "," + std::to_string(color.y()) + "," std::string visibility_fill = "rgb(" + std::to_string(color.x()) + "," + std::to_string(color.y()) + ","
+ std::to_string(color.z()) + ")"; + std::to_string(color.z()) + ")";
visibility_svg.draw(scaled(Vec2f(point.position.head<2>())), visibility_fill); visibility_svg.draw(scaled(Vec2f(point.position.head<2>())), visibility_fill);
Vec3i weight_color = value_rgbi(min_weight, max_weight, -comparator.get_penalty(point)); Vec3i weight_color = value_to_rgbi(min_weight, max_weight, -comparator.compute_angle_penalty(point.local_ccw_angle));
std::string weight_fill = "rgb(" + std::to_string(weight_color.x()) + "," + std::to_string(weight_color.y()) std::string weight_fill = "rgb(" + std::to_string(weight_color.x()) + "," + std::to_string(weight_color.y())
+ "," + ","
+ std::to_string(weight_color.z()) + ")"; + std::to_string(weight_color.z()) + ")";
weight_svg.draw(scaled(Vec2f(point.position.head<2>())), weight_fill); weight_svg.draw(scaled(Vec2f(point.position.head<2>())), weight_fill);
Vec3i overhang_color = value_rgbi(-0.5, 0.5, std::clamp(point.overhang, -0.5f, 0.5f)); Vec3i overhang_color = value_to_rgbi(-0.5, 0.5, std::clamp(point.overhang, -0.5f, 0.5f));
std::string overhang_fill = "rgb(" + std::to_string(overhang_color.x()) + "," std::string overhang_fill = "rgb(" + std::to_string(overhang_color.x()) + ","
+ std::to_string(overhang_color.y()) + std::to_string(overhang_color.y())
+ "," + ","
@ -1205,22 +1195,18 @@ void SeamPlacer::align_seam_points(const PrintObject *po, const SeamPlacerImpl::
observation_points.resize(seam_string.size()); observation_points.resize(seam_string.size());
weights.resize(seam_string.size()); weights.resize(seam_string.size());
auto min_weight = std::numeric_limits<float>::max(); //gather points positions and weights
auto max_weight = -std::numeric_limits<float>::max(); // The algorithm uses only angle to compute penalty, to enforce snapping to sharp corners, if they are present
//gather points positions and weights (negative value of penalty), update min_weight in each step // after several experiments approach that gives best results is to snap the weight to one for sharp corners, and
// leave it small for others. However, this can result in non-smooth line over area with a lot of unaligned sharp corners.
for (size_t index = 0; index < seam_string.size(); ++index) { for (size_t index = 0; index < seam_string.size(); ++index) {
Vec3f pos = layers[seam_string[index].first].points[seam_string[index].second].position; Vec3f pos = layers[seam_string[index].first].points[seam_string[index].second].position;
observations[index] = pos.head<2>(); observations[index] = pos.head<2>();
observation_points[index] = pos.z(); observation_points[index] = pos.z();
weights[index] = -comparator.get_penalty( weights[index] =
layers[seam_string[index].first].points[seam_string[index].second]); (comparator.compute_angle_penalty(
min_weight = std::min(min_weight, weights[index]); layers[seam_string[index].first].points[seam_string[index].second].local_ccw_angle)
max_weight = std::max(max_weight, weights[index]); < comparator.compute_angle_penalty(0.4f * PI)) ? 1.0f : 0.1f;
}
//normalize weights (ensure nonzero)
for (float &w : weights) {
w = 0.01 + (w - min_weight) / (max_weight - min_weight);
} }
// Curve Fitting // Curve Fitting
@ -1231,13 +1217,13 @@ void SeamPlacer::align_seam_points(const PrintObject *po, const SeamPlacerImpl::
// Do alignment - compute fitted point for each point in the string from its Z coord, and store the position into // Do alignment - compute fitted point for each point in the string from its Z coord, and store the position into
// Perimeter structure of the point; also set flag aligned to true // Perimeter structure of the point; also set flag aligned to true
for (size_t index = 0; index < seam_string.size(); ++index) { for (size_t index = 0; index < seam_string.size(); ++index) {
const auto& pair = seam_string[index]; const auto &pair = seam_string[index];
const float t = weights[index]; const float t = weights[index];
Vec3f current_pos = layers[pair.first].points[pair.second].position; Vec3f current_pos = layers[pair.first].points[pair.second].position;
Vec2f fitted_pos = curve.get_fitted_value(current_pos.z()); Vec2f fitted_pos = curve.get_fitted_value(current_pos.z());
//interpolate between current and fitted position, prefer current pos for large weights. //interpolate between current and fitted position, prefer current pos for large weights.
Vec3f final_position = t*current_pos + (1-t)*to_3d(fitted_pos, current_pos.z()); Vec3f final_position = t * current_pos + (1 - t) * to_3d(fitted_pos, current_pos.z());
Perimeter &perimeter = layers[pair.first].points[pair.second].perimeter; Perimeter &perimeter = layers[pair.first].points[pair.second].perimeter;
perimeter.final_seam_position = final_position; perimeter.final_seam_position = final_position;