mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-15 21:15:52 +08:00
choose seam string with lower variance weighted by visibility
This commit is contained in:
parent
feeb9b2b1b
commit
232517fe77
@ -1199,9 +1199,9 @@ std::optional<std::pair<size_t, size_t>> SeamPlacer::find_next_seam_in_layer(
|
|||||||
|
|
||||||
std::vector<std::pair<size_t, size_t>> SeamPlacer::find_seam_string(const PrintObject *po,
|
std::vector<std::pair<size_t, size_t>> SeamPlacer::find_seam_string(const PrintObject *po,
|
||||||
std::pair<size_t, size_t> start_seam, const SeamPlacerImpl::SeamComparator &comparator,
|
std::pair<size_t, size_t> start_seam, const SeamPlacerImpl::SeamComparator &comparator,
|
||||||
std::optional<std::pair<size_t, size_t>> &out_best_moved_seam, size_t &out_moved_seams_count) const {
|
std::optional<std::pair<size_t, size_t>> &out_best_moved_seam, float& seam_variance_out) const {
|
||||||
out_best_moved_seam.reset();
|
out_best_moved_seam.reset();
|
||||||
out_moved_seams_count = 0;
|
seam_variance_out = 0.0f;
|
||||||
const std::vector<PrintObjectSeamData::LayerSeams> &layers = m_seam_per_object.find(po)->second.layers;
|
const std::vector<PrintObjectSeamData::LayerSeams> &layers = m_seam_per_object.find(po)->second.layers;
|
||||||
int layer_idx = start_seam.first;
|
int layer_idx = start_seam.first;
|
||||||
int seam_index = start_seam.second;
|
int seam_index = start_seam.second;
|
||||||
@ -1210,7 +1210,7 @@ std::vector<std::pair<size_t, size_t>> SeamPlacer::find_seam_string(const PrintO
|
|||||||
int next_layer = layer_idx + 1;
|
int next_layer = layer_idx + 1;
|
||||||
std::pair<size_t, size_t> prev_point_index = start_seam;
|
std::pair<size_t, size_t> prev_point_index = start_seam;
|
||||||
std::vector<std::pair<size_t, size_t>> seam_string { start_seam };
|
std::vector<std::pair<size_t, size_t>> seam_string { start_seam };
|
||||||
Vec3f surface_line_dir { 0.0f, 0.0f, 20.0f };
|
Vec3f surface_line_dir { 0.0f, 0.0f, 1.0f };
|
||||||
Vec3f origin_position = layers[start_seam.first].points[start_seam.second].position;
|
Vec3f origin_position = layers[start_seam.first].points[start_seam.second].position;
|
||||||
|
|
||||||
//find seams or potential seams in forward direction; there is a budget of skips allowed
|
//find seams or potential seams in forward direction; there is a budget of skips allowed
|
||||||
@ -1218,9 +1218,9 @@ std::vector<std::pair<size_t, size_t>> SeamPlacer::find_seam_string(const PrintO
|
|||||||
std::optional<std::pair<size_t, size_t>> maybe_next_seam;
|
std::optional<std::pair<size_t, size_t>> maybe_next_seam;
|
||||||
float z_distance = float(po->get_layer(next_layer)->slice_z) - origin_position.z();
|
float z_distance = float(po->get_layer(next_layer)->slice_z) - origin_position.z();
|
||||||
float max_distance = SeamPlacer::seam_align_tolerable_dist;
|
float max_distance = SeamPlacer::seam_align_tolerable_dist;
|
||||||
|
Vec3f linear_position = origin_position + z_distance * (surface_line_dir / surface_line_dir.z());
|
||||||
if (fabs(next_layer - layer_idx) >= SeamPlacer::seam_align_min_seams_for_linear_projection){
|
if (fabs(next_layer - layer_idx) >= SeamPlacer::seam_align_min_seams_for_linear_projection){
|
||||||
Vec3f projected_position = origin_position + z_distance * (surface_line_dir / surface_line_dir.z());
|
maybe_next_seam = find_next_seam_in_layer(layers, linear_position, next_layer, max_distance,
|
||||||
maybe_next_seam = find_next_seam_in_layer(layers, projected_position, next_layer, max_distance,
|
|
||||||
comparator);
|
comparator);
|
||||||
}
|
}
|
||||||
if (!maybe_next_seam.has_value()) {
|
if (!maybe_next_seam.has_value()) {
|
||||||
@ -1235,7 +1235,7 @@ std::vector<std::pair<size_t, size_t>> SeamPlacer::find_seam_string(const PrintO
|
|||||||
std::pair<size_t, size_t> next_seam_coords = maybe_next_seam.operator*();
|
std::pair<size_t, size_t> next_seam_coords = maybe_next_seam.operator*();
|
||||||
const auto &next_seam = layers[next_seam_coords.first].points[next_seam_coords.second];
|
const auto &next_seam = layers[next_seam_coords.first].points[next_seam_coords.second];
|
||||||
bool is_moved = next_seam.perimeter.seam_index != next_seam_coords.second;
|
bool is_moved = next_seam.perimeter.seam_index != next_seam_coords.second;
|
||||||
out_moved_seams_count += is_moved;
|
seam_variance_out += next_seam.visibility * (linear_position - next_seam.position).squaredNorm();
|
||||||
if (is_moved && (!out_best_moved_seam.has_value() ||
|
if (is_moved && (!out_best_moved_seam.has_value() ||
|
||||||
comparator.is_first_better(next_seam,
|
comparator.is_first_better(next_seam,
|
||||||
layers[out_best_moved_seam.operator*().first].points[out_best_moved_seam.operator*().second]))) {
|
layers[out_best_moved_seam.operator*().first].points[out_best_moved_seam.operator*().second]))) {
|
||||||
@ -1259,9 +1259,9 @@ std::vector<std::pair<size_t, size_t>> SeamPlacer::find_seam_string(const PrintO
|
|||||||
std::optional<std::pair<size_t, size_t>> maybe_next_seam;
|
std::optional<std::pair<size_t, size_t>> maybe_next_seam;
|
||||||
float z_distance = float(po->get_layer(next_layer)->slice_z) - origin_position.z();
|
float z_distance = float(po->get_layer(next_layer)->slice_z) - origin_position.z();
|
||||||
float max_distance = SeamPlacer::seam_align_tolerable_dist;
|
float max_distance = SeamPlacer::seam_align_tolerable_dist;
|
||||||
|
Vec3f linear_position = origin_position + z_distance * (surface_line_dir / surface_line_dir.z());
|
||||||
if (fabs(next_layer - layer_idx) >= SeamPlacer::seam_align_min_seams_for_linear_projection){
|
if (fabs(next_layer - layer_idx) >= SeamPlacer::seam_align_min_seams_for_linear_projection){
|
||||||
Vec3f projected_position = origin_position + z_distance * (surface_line_dir / surface_line_dir.z());
|
maybe_next_seam = find_next_seam_in_layer(layers, linear_position, next_layer, max_distance,
|
||||||
maybe_next_seam = find_next_seam_in_layer(layers, projected_position, next_layer, max_distance,
|
|
||||||
comparator);
|
comparator);
|
||||||
}
|
}
|
||||||
if (!maybe_next_seam.has_value()) {
|
if (!maybe_next_seam.has_value()) {
|
||||||
@ -1272,11 +1272,10 @@ std::vector<std::pair<size_t, size_t>> SeamPlacer::find_seam_string(const PrintO
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (maybe_next_seam.has_value()) {
|
if (maybe_next_seam.has_value()) {
|
||||||
|
|
||||||
std::pair<size_t, size_t> next_seam_coords = maybe_next_seam.operator*();
|
std::pair<size_t, size_t> next_seam_coords = maybe_next_seam.operator*();
|
||||||
const auto &next_seam = layers[next_seam_coords.first].points[next_seam_coords.second];
|
const auto &next_seam = layers[next_seam_coords.first].points[next_seam_coords.second];
|
||||||
bool is_moved = next_seam.perimeter.seam_index != next_seam_coords.second;
|
bool is_moved = next_seam.perimeter.seam_index != next_seam_coords.second;
|
||||||
out_moved_seams_count += is_moved;
|
seam_variance_out += next_seam.visibility * (linear_position - next_seam.position).squaredNorm();
|
||||||
if (is_moved && (!out_best_moved_seam.has_value() ||
|
if (is_moved && (!out_best_moved_seam.has_value() ||
|
||||||
comparator.is_first_better(next_seam,
|
comparator.is_first_better(next_seam,
|
||||||
layers[out_best_moved_seam.operator*().first].points[out_best_moved_seam.operator*().second]))) {
|
layers[out_best_moved_seam.operator*().first].points[out_best_moved_seam.operator*().second]))) {
|
||||||
@ -1293,6 +1292,8 @@ std::vector<std::pair<size_t, size_t>> SeamPlacer::find_seam_string(const PrintO
|
|||||||
next_layer--;
|
next_layer--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
seam_variance_out /= float(seam_string.size());
|
||||||
|
|
||||||
return seam_string;
|
return seam_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1363,17 +1364,17 @@ void SeamPlacer::align_seam_points(const PrintObject *po, const SeamPlacerImpl::
|
|||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
std::optional<std::pair<size_t, size_t>> best_moved_seam;
|
std::optional<std::pair<size_t, size_t>> best_moved_seam;
|
||||||
size_t moved_seams_count;
|
float seam_variance;
|
||||||
seam_string = this->find_seam_string(po, { layer_idx, seam_index }, comparator, best_moved_seam,
|
seam_string = this->find_seam_string(po, { layer_idx, seam_index }, comparator, best_moved_seam,
|
||||||
moved_seams_count);
|
seam_variance);
|
||||||
if (best_moved_seam.has_value()) {
|
if (best_moved_seam.has_value()) {
|
||||||
size_t alternative_moved_seams_count;
|
float alternative_seam_variance;
|
||||||
alternative_seam_string = this->find_seam_string(po, best_moved_seam.operator*(), comparator,
|
alternative_seam_string = this->find_seam_string(po, best_moved_seam.operator*(), comparator,
|
||||||
best_moved_seam, alternative_moved_seams_count);
|
best_moved_seam, alternative_seam_variance);
|
||||||
if (alternative_seam_string.size() >= SeamPlacer::seam_align_minimum_string_seams &&
|
if (alternative_seam_string.size() >= SeamPlacer::seam_align_minimum_string_seams &&
|
||||||
alternative_moved_seams_count < moved_seams_count) {
|
alternative_seam_variance < seam_variance) {
|
||||||
seam_string = std::move(alternative_seam_string);
|
seam_string = std::move(alternative_seam_string);
|
||||||
// finish loop. but repeat the alignment for the current seam, since it could be skipped due to alternative path being aligned.
|
//repeat the alignment for the current seam, since it could be skipped due to alternative path being aligned.
|
||||||
global_index--;
|
global_index--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1414,12 +1415,16 @@ 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
|
||||||
|
auto sigmoid_angle_snapping_func = [](float angle){
|
||||||
|
float steepness = 10.0f;
|
||||||
|
float exp_val = steepness * (abs(angle) - SeamPlacer::sharp_angle_snapping_threshold);
|
||||||
|
float sig_term = exp(exp_val);
|
||||||
|
return sig_term / (sig_term + 1.0f);
|
||||||
|
};
|
||||||
|
|
||||||
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 =
|
float t = sigmoid_angle_snapping_func(layers[pair.first].points[pair.second].local_ccw_angle);
|
||||||
abs(layers[pair.first].points[pair.second].local_ccw_angle)
|
|
||||||
> SeamPlacer::sharp_angle_snapping_threshold
|
|
||||||
? 1.0 : 0.0f;
|
|
||||||
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());
|
||||||
|
|
||||||
|
@ -171,7 +171,7 @@ private:
|
|||||||
std::pair<size_t, size_t> start_seam,
|
std::pair<size_t, size_t> start_seam,
|
||||||
const SeamPlacerImpl::SeamComparator &comparator,
|
const SeamPlacerImpl::SeamComparator &comparator,
|
||||||
std::optional<std::pair<size_t, size_t>> &out_best_moved_seam,
|
std::optional<std::pair<size_t, size_t>> &out_best_moved_seam,
|
||||||
size_t& out_moved_seams_count) const;
|
float& seam_variance_out) const;
|
||||||
std::optional<std::pair<size_t, size_t>> find_next_seam_in_layer(
|
std::optional<std::pair<size_t, size_t>> find_next_seam_in_layer(
|
||||||
const std::vector<PrintObjectSeamData::LayerSeams> &layers,
|
const std::vector<PrintObjectSeamData::LayerSeams> &layers,
|
||||||
const Vec3f& projected_position,
|
const Vec3f& projected_position,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user