mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-16 17:35:52 +08:00
implemented alternative aligment path search, results are compared w.r. to number of moved seams
This commit is contained in:
parent
e595194f26
commit
3ebdff165c
@ -22,7 +22,7 @@
|
||||
|
||||
#include "libslic3r/Utils.hpp"
|
||||
|
||||
//#define DEBUG_FILES
|
||||
#define DEBUG_FILES
|
||||
|
||||
#ifdef DEBUG_FILES
|
||||
#include <boost/nowide/cstdio.hpp>
|
||||
@ -295,7 +295,6 @@ struct GlobalModelInfo {
|
||||
} else {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#ifdef DEBUG_FILES
|
||||
@ -792,7 +791,8 @@ void debug_export_points(const std::vector<PrintObjectSeamData::LayerSeams> &la
|
||||
+ std::to_string(color.z()) + ")";
|
||||
visibility_svg.draw(scaled(Vec2f(point.position.head<2>())), visibility_fill);
|
||||
|
||||
Vec3i weight_color = value_to_rgbi(min_weight, max_weight, -comparator.compute_angle_penalty(point.local_ccw_angle));
|
||||
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::to_string(weight_color.z()) + ")";
|
||||
@ -1020,22 +1020,21 @@ void SeamPlacer::calculate_overhangs_and_layer_embedding(const PrintObject *po)
|
||||
// If the closest point is good enough to replace current chosen seam, it is stored in potential_string_seams, returns true and updates last_point_pos
|
||||
// Otherwise does nothing, returns false
|
||||
// Used by align_seam_points().
|
||||
bool SeamPlacer::find_next_seam_in_layer(
|
||||
std::optional<std::pair<size_t, size_t>> SeamPlacer::find_next_seam_in_layer(
|
||||
const std::vector<PrintObjectSeamData::LayerSeams> &layers,
|
||||
std::pair<size_t, size_t> &last_point_indexes,
|
||||
const std::pair<size_t, size_t> &prev_point_index,
|
||||
const size_t layer_idx, const float slice_z,
|
||||
const SeamPlacerImpl::SeamComparator &comparator,
|
||||
std::vector<std::pair<size_t, size_t>> &seam_string) const {
|
||||
const SeamPlacerImpl::SeamComparator &comparator) const {
|
||||
using namespace SeamPlacerImpl;
|
||||
|
||||
const SeamCandidate &last_point = layers[last_point_indexes.first].points[last_point_indexes.second];
|
||||
const SeamCandidate &last_point = layers[prev_point_index.first].points[prev_point_index.second];
|
||||
|
||||
Vec3f projected_position { last_point.position.x(), last_point.position.y(), slice_z };
|
||||
std::vector<size_t> nearby_points_indices = find_nearby_points(*layers[layer_idx].points_tree, projected_position,
|
||||
SeamPlacer::seam_align_tolerable_dist);
|
||||
|
||||
if (nearby_points_indices.empty()) {
|
||||
return false;
|
||||
return {};
|
||||
}
|
||||
|
||||
size_t best_nearby_point_index = nearby_points_indices[0];
|
||||
@ -1064,7 +1063,7 @@ bool SeamPlacer::find_next_seam_in_layer(
|
||||
|
||||
if (nearest_point.perimeter.finalized) {
|
||||
//all points are from already finalized perimeter, skip
|
||||
return false;
|
||||
return {};
|
||||
}
|
||||
|
||||
//from the nearest_point, deduce index of seam in the next layer
|
||||
@ -1074,9 +1073,7 @@ bool SeamPlacer::find_next_seam_in_layer(
|
||||
if (next_layer_seam.central_enforcer
|
||||
&& (next_layer_seam.position - projected_position).squaredNorm()
|
||||
< sqr(3 * SeamPlacer::seam_align_tolerable_dist)) {
|
||||
last_point_indexes = std::pair<size_t, size_t> { layer_idx, nearest_point.perimeter.seam_index };
|
||||
seam_string.push_back(last_point_indexes);
|
||||
return true;
|
||||
return {std::pair<size_t, size_t> {layer_idx, nearest_point.perimeter.seam_index}};
|
||||
}
|
||||
|
||||
// Next compare nearest and nearby point. If they are similar pick nearest, Otherwise expect curvy lines on smooth surfaces like chimney of benchy model
|
||||
@ -1084,24 +1081,22 @@ bool SeamPlacer::find_next_seam_in_layer(
|
||||
if (comparator.are_similar(nearest_point, best_nearby_point)
|
||||
&& comparator.is_first_not_much_worse(nearest_point, next_layer_seam)
|
||||
&& comparator.are_similar(last_point, nearest_point)) {
|
||||
last_point_indexes = std::pair<size_t, size_t> { layer_idx, nearest_point_index };
|
||||
seam_string.push_back(last_point_indexes);
|
||||
return true;
|
||||
return {std::pair<size_t, size_t> {layer_idx, nearest_point_index}};
|
||||
}
|
||||
// If nearest point is not good enough, try it with the best nearby point.
|
||||
if (comparator.is_first_not_much_worse(best_nearby_point, next_layer_seam)
|
||||
&& comparator.are_similar(last_point, nearest_point)) {
|
||||
last_point_indexes = std::pair<size_t, size_t> { layer_idx, best_nearby_point_index };
|
||||
seam_string.push_back(last_point_indexes);
|
||||
return true;
|
||||
return {std::pair<size_t, size_t> {layer_idx, best_nearby_point_index}};
|
||||
}
|
||||
|
||||
return false;
|
||||
return {};
|
||||
}
|
||||
|
||||
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) const {
|
||||
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 {
|
||||
out_best_moved_seam.reset();
|
||||
out_moved_seams_count = 0;
|
||||
const std::vector<PrintObjectSeamData::LayerSeams> &layers = m_seam_per_object.find(po)->second.layers;
|
||||
int layer_idx = start_seam.first;
|
||||
int seam_index = start_seam.second;
|
||||
@ -1109,14 +1104,28 @@ std::vector<std::pair<size_t, size_t>> SeamPlacer::find_seam_string(const PrintO
|
||||
//initialize searching for seam string - cluster of nearby seams on previous and next layers
|
||||
int skips = SeamPlacer::seam_align_tolerable_skips / 2;
|
||||
int next_layer = layer_idx + 1;
|
||||
std::pair<size_t, size_t> last_point_indexes = 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 };
|
||||
|
||||
//find seams or potential seams in forward direction; there is a budget of skips allowed
|
||||
while (skips >= 0 && next_layer < int(layers.size())) {
|
||||
if (find_next_seam_in_layer(layers, last_point_indexes, next_layer,
|
||||
float(po->get_layer(next_layer)->slice_z), comparator, seam_string)) {
|
||||
//String added, last_point_pos updated, nothing to be done
|
||||
auto maybe_next_seam = find_next_seam_in_layer(layers, prev_point_index, next_layer,
|
||||
float(po->get_layer(next_layer)->slice_z), comparator);
|
||||
if (maybe_next_seam.has_value()) {
|
||||
|
||||
std::pair<size_t, size_t> next_seam_coords = maybe_next_seam.value();
|
||||
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;
|
||||
out_moved_seams_count += is_moved;
|
||||
if (is_moved && (!out_best_moved_seam.has_value() ||
|
||||
comparator.is_first_better(next_seam,
|
||||
layers[out_best_moved_seam.value().first].points[out_best_moved_seam.value().second]))) {
|
||||
out_best_moved_seam = { next_seam_coords };
|
||||
}
|
||||
|
||||
seam_string.push_back(maybe_next_seam.value());
|
||||
prev_point_index = seam_string.back();
|
||||
//String added, prev_point_index updated
|
||||
} else {
|
||||
// Layer skipped, reduce number of available skips
|
||||
skips--;
|
||||
@ -1127,11 +1136,25 @@ std::vector<std::pair<size_t, size_t>> SeamPlacer::find_seam_string(const PrintO
|
||||
//do additional check in back direction
|
||||
next_layer = layer_idx - 1;
|
||||
skips = SeamPlacer::seam_align_tolerable_skips / 2;
|
||||
last_point_indexes = std::pair<size_t, size_t>(layer_idx, seam_index);
|
||||
prev_point_index = std::pair<size_t, size_t>(layer_idx, seam_index);
|
||||
while (skips >= 0 && next_layer >= 0) {
|
||||
if (find_next_seam_in_layer(layers, last_point_indexes, next_layer,
|
||||
float(po->get_layer(next_layer)->slice_z), comparator, seam_string)) {
|
||||
//String added, last_point_pos updated, nothing to be done
|
||||
auto maybe_next_seam = find_next_seam_in_layer(layers, prev_point_index, next_layer,
|
||||
float(po->get_layer(next_layer)->slice_z), comparator);
|
||||
if (maybe_next_seam.has_value()) {
|
||||
|
||||
std::pair<size_t, size_t> next_seam_coords = maybe_next_seam.value();
|
||||
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;
|
||||
out_moved_seams_count += is_moved;
|
||||
if (is_moved && (!out_best_moved_seam.has_value() ||
|
||||
comparator.is_first_better(next_seam,
|
||||
layers[out_best_moved_seam.value().first].points[out_best_moved_seam.value().second]))) {
|
||||
out_best_moved_seam = { next_seam_coords };
|
||||
}
|
||||
|
||||
seam_string.push_back(maybe_next_seam.value());
|
||||
prev_point_index = seam_string.back();
|
||||
//String added, prev_point_index updated
|
||||
} else {
|
||||
// Layer skipped, reduce number of available skips
|
||||
skips--;
|
||||
@ -1192,18 +1215,37 @@ void SeamPlacer::align_seam_points(const PrintObject *po, const SeamPlacerImpl::
|
||||
//align the seam points - start with the best, and check if they are aligned, if yes, skip, else start alignment
|
||||
// Keeping the vectors outside, so with a bit of luck they will not get reallocated after couple of for loop iterations.
|
||||
std::vector<std::pair<size_t, size_t>> seam_string;
|
||||
std::vector<std::pair<size_t, size_t>> alternative_seam_string;
|
||||
std::vector<Vec2f> observations;
|
||||
std::vector<float> observation_points;
|
||||
std::vector<float> weights;
|
||||
for (const std::pair<size_t, size_t> &seam : seams) {
|
||||
size_t layer_idx = seam.first;
|
||||
size_t seam_index = seam.second;
|
||||
|
||||
int global_index = 0;
|
||||
while (global_index < int(seams.size())) {
|
||||
size_t layer_idx = seams[global_index].first;
|
||||
size_t seam_index = seams[global_index].second;
|
||||
global_index++;
|
||||
const std::vector<SeamCandidate> &layer_perimeter_points = layers[layer_idx].points;
|
||||
if (layer_perimeter_points[seam_index].perimeter.finalized) {
|
||||
// This perimeter is already aligned, skip seam
|
||||
continue;
|
||||
} else {
|
||||
seam_string = this->find_seam_string(po, seam, comparator);
|
||||
std::optional<std::pair<size_t, size_t>> best_moved_seam;
|
||||
size_t moved_seams_count;
|
||||
seam_string = this->find_seam_string(po, { layer_idx, seam_index }, comparator, best_moved_seam,
|
||||
moved_seams_count);
|
||||
if (best_moved_seam.has_value()) {
|
||||
size_t alternative_moved_seams_count;
|
||||
alternative_seam_string = this->find_seam_string(po, best_moved_seam.value(), comparator,
|
||||
best_moved_seam, alternative_moved_seams_count);
|
||||
if (alternative_seam_string.size() >= SeamPlacer::seam_align_minimum_string_seams &&
|
||||
alternative_moved_seams_count < moved_seams_count) {
|
||||
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.
|
||||
global_index--;
|
||||
}
|
||||
}
|
||||
|
||||
if (seam_string.size() < seam_align_minimum_string_seams) {
|
||||
//string NOT long enough to be worth aligning, skip
|
||||
continue;
|
||||
@ -1355,7 +1397,7 @@ void SeamPlacer::init(const Print &print) {
|
||||
}
|
||||
|
||||
#ifdef DEBUG_FILES
|
||||
debug_export_points(layers, po->bounding_box(), std::to_string(po->id().id),
|
||||
debug_export_points(m_seam_per_object[po].layers, po->bounding_box(), std::to_string(po->id().id),
|
||||
comparator);
|
||||
#endif
|
||||
}
|
||||
|
@ -129,7 +129,7 @@ public:
|
||||
|
||||
// When searching for seam clusters for alignment:
|
||||
// following value describes, how much worse score can point have and still be picked into seam cluster instead of original seam point on the same layer
|
||||
static constexpr float seam_align_score_tolerance = 0.25f;
|
||||
static constexpr float seam_align_score_tolerance = 0.5f;
|
||||
// seam_align_tolerable_dist - if next layer closes point is too far away, break string
|
||||
static constexpr float seam_align_tolerable_dist = 1.0f;
|
||||
// if the seam of the current layer is too far away, and the closest seam candidate is not very good, layer is skipped.
|
||||
@ -156,13 +156,14 @@ private:
|
||||
void align_seam_points(const PrintObject *po, const SeamPlacerImpl::SeamComparator &comparator);
|
||||
std::vector<std::pair<size_t, size_t>> find_seam_string(const PrintObject *po,
|
||||
std::pair<size_t, size_t> start_seam,
|
||||
const SeamPlacerImpl::SeamComparator &comparator) const;
|
||||
bool find_next_seam_in_layer(
|
||||
const std::vector<PrintObjectSeamData::LayerSeams> &layers,
|
||||
std::pair<size_t, size_t> &last_point_indexes,
|
||||
const size_t layer_idx, const float slice_z,
|
||||
const SeamPlacerImpl::SeamComparator &comparator,
|
||||
std::vector<std::pair<size_t, size_t>> &seam_string) const;
|
||||
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>> find_next_seam_in_layer(
|
||||
const std::vector<PrintObjectSeamData::LayerSeams> &layers,
|
||||
const std::pair<size_t, size_t> &prev_point_index,
|
||||
const size_t layer_idx, const float slice_z,
|
||||
const SeamPlacerImpl::SeamComparator &comparator) const;
|
||||
};
|
||||
|
||||
} // namespace Slic3r
|
||||
|
Loading…
x
Reference in New Issue
Block a user