Count seam string weight and try mutiple strings; choose highest weight

This commit is contained in:
PavelMikus 2022-07-07 13:54:21 +02:00 committed by Pavel Mikus
parent f31865a627
commit 4d8e8afb10
2 changed files with 32 additions and 42 deletions

View file

@ -1202,9 +1202,8 @@ 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, float& seam_variance_out) const { float& string_weight) const {
out_best_moved_seam.reset(); string_weight = 0.0f;
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;
@ -1213,7 +1212,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, 3.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
@ -1222,13 +1221,14 @@ std::vector<std::pair<size_t, size_t>> SeamPlacer::find_seam_string(const PrintO
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()); 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){ Vec3f prev_position = layers[prev_point_index.first].points[prev_point_index.second].position;
Vec3f projected_position(prev_position.x(), prev_position.y(), float(po->get_layer(next_layer)->slice_z));
if ((projected_position - linear_position).squaredNorm() < max_distance*max_distance){
maybe_next_seam = find_next_seam_in_layer(layers, linear_position, next_layer, max_distance, maybe_next_seam = find_next_seam_in_layer(layers, linear_position, next_layer, max_distance,
comparator); comparator);
} }
if (!maybe_next_seam.has_value()) { if (!maybe_next_seam.has_value()) {
Vec3f prev_position = layers[prev_point_index.first].points[prev_point_index.second].position;
Vec3f projected_position(prev_position.x(), prev_position.y(), float(po->get_layer(next_layer)->slice_z));
maybe_next_seam = find_next_seam_in_layer(layers, projected_position, next_layer, maybe_next_seam = find_next_seam_in_layer(layers, projected_position, next_layer,
max_distance, comparator); max_distance, comparator);
} }
@ -1238,13 +1238,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;
seam_variance_out += (linear_position - next_seam.position).squaredNorm() * next_seam.visibility; string_weight += comparator.weight(next_seam) - (linear_position - next_seam.position).squaredNorm();
if (is_moved && (!out_best_moved_seam.has_value() ||
comparator.is_first_better(next_seam,
layers[out_best_moved_seam.operator*().first].points[out_best_moved_seam.operator*().second]))) {
out_best_moved_seam = { next_seam_coords };
}
seam_string.push_back(maybe_next_seam.operator*()); seam_string.push_back(maybe_next_seam.operator*());
prev_point_index = seam_string.back(); prev_point_index = seam_string.back();
//String added, prev_point_index updated //String added, prev_point_index updated
@ -1263,7 +1257,10 @@ std::vector<std::pair<size_t, size_t>> SeamPlacer::find_seam_string(const PrintO
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()); 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){ Vec3f prev_position = layers[prev_point_index.first].points[prev_point_index.second].position;
Vec3f projected_position(prev_position.x(), prev_position.y(), float(po->get_layer(next_layer)->slice_z));
if ((projected_position - linear_position).squaredNorm() < max_distance*max_distance){
maybe_next_seam = find_next_seam_in_layer(layers, linear_position, next_layer, max_distance, maybe_next_seam = find_next_seam_in_layer(layers, linear_position, next_layer, max_distance,
comparator); comparator);
} }
@ -1278,13 +1275,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;
seam_variance_out += (linear_position - next_seam.position).squaredNorm() * next_seam.visibility; string_weight += comparator.weight(next_seam) - (linear_position - next_seam.position).squaredNorm();
if (is_moved && (!out_best_moved_seam.has_value() ||
comparator.is_first_better(next_seam,
layers[out_best_moved_seam.operator*().first].points[out_best_moved_seam.operator*().second]))) {
out_best_moved_seam = { next_seam_coords };
}
seam_string.push_back(maybe_next_seam.operator*()); seam_string.push_back(maybe_next_seam.operator*());
prev_point_index = seam_string.back(); prev_point_index = seam_string.back();
//String added, prev_point_index updated //String added, prev_point_index updated
@ -1295,8 +1286,6 @@ 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;
} }
@ -1366,22 +1355,21 @@ void SeamPlacer::align_seam_points(const PrintObject *po, const SeamPlacerImpl::
// This perimeter is already aligned, skip seam // This perimeter is already aligned, skip seam
continue; continue;
} else { } else {
std::optional<std::pair<size_t, size_t>> best_moved_seam; float seam_string_weight;
float seam_variance; seam_string = this->find_seam_string(po, { layer_idx, seam_index }, comparator, seam_string_weight);
seam_string = this->find_seam_string(po, { layer_idx, seam_index }, comparator, best_moved_seam, size_t step_size = 1 + seam_string.size() / 20;
seam_variance); for (size_t alternative_start = 0; alternative_start < seam_string.size(); alternative_start+=step_size) {
if (best_moved_seam.has_value()) { float alternative_seam_string_weight = 0;
float alternative_seam_variance; size_t start_layer_idx = seam_string[alternative_start].first;
alternative_seam_string = this->find_seam_string(po, best_moved_seam.operator*(), comparator, size_t seam_idx = layers[start_layer_idx].points[seam_string[alternative_start].second].perimeter.seam_index;
best_moved_seam, alternative_seam_variance); alternative_seam_string = this->find_seam_string(po, std::pair<size_t,size_t>(start_layer_idx, seam_idx), comparator,
alternative_seam_string_weight);
if (alternative_seam_string.size() >= SeamPlacer::seam_align_minimum_string_seams && if (alternative_seam_string.size() >= SeamPlacer::seam_align_minimum_string_seams &&
alternative_seam_variance < seam_variance) { alternative_seam_string_weight > seam_string_weight) {
seam_string_weight = alternative_seam_string_weight;
seam_string = std::move(alternative_seam_string); seam_string = std::move(alternative_seam_string);
//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) { if (seam_string.size() < seam_align_minimum_string_seams) {
//string NOT long enough to be worth aligning, skip //string NOT long enough to be worth aligning, skip
continue; continue;
@ -1394,6 +1382,9 @@ void SeamPlacer::align_seam_points(const PrintObject *po, const SeamPlacerImpl::
return left.first < right.first; return left.first < right.first;
}); });
//repeat the alignment for the current seam, since it could be skipped due to alternative path being aligned.
global_index--;
// gather all positions of seams and their weights (weights are derived as negative penalty, they are made positive in next step) // gather all positions of seams and their weights (weights are derived as negative penalty, they are made positive in next step)
observations.resize(seam_string.size()); observations.resize(seam_string.size());
observation_points.resize(seam_string.size()); observation_points.resize(seam_string.size());
@ -1408,7 +1399,8 @@ void SeamPlacer::align_seam_points(const PrintObject *po, const SeamPlacerImpl::
last_point_pos = pos; last_point_pos = pos;
observations[index] = pos.head<2>(); observations[index] = pos.head<2>();
observation_points[index] = pos.z(); observation_points[index] = pos.z();
weights[index] = comparator.weight(layers[seam_string[index].first].points[seam_string[index].second]); weights[index] = std::min(1.0f,
comparator.weight(layers[seam_string[index].first].points[seam_string[index].second]));
} }
// Curve Fitting // Curve Fitting

View file

@ -143,15 +143,14 @@ public:
static constexpr float enforcer_oversampling_distance = 0.2f; static constexpr float enforcer_oversampling_distance = 0.2f;
// When searching for seam clusters for alignment: // When searching for seam clusters for alignment:
static constexpr size_t seam_align_min_seams_for_linear_projection = 1;
// 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 // 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.3f; static constexpr float seam_align_score_tolerance = 0.3f;
// seam_align_tolerable_dist - if next layer closest point is too far away, break aligned string // seam_align_tolerable_dist - if next layer closest point is too far away, break aligned string
static constexpr float seam_align_tolerable_dist = 1.5f; static constexpr float seam_align_tolerable_dist = 1.0f;
// minimum number of seams needed in cluster to make alignment happen // minimum number of seams needed in cluster to make alignment happen
static constexpr size_t seam_align_minimum_string_seams = 6; static constexpr size_t seam_align_minimum_string_seams = 6;
// millimeters covered by spline; determines number of splines for the given string // millimeters covered by spline; determines number of splines for the given string
static constexpr size_t seam_align_mm_per_segment = 8.0f; static constexpr size_t seam_align_mm_per_segment = 3.0f;
//The following data structures hold all perimeter points for all PrintObject. //The following data structures hold all perimeter points for all PrintObject.
std::unordered_map<const PrintObject*, PrintObjectSeamData> m_seam_per_object; std::unordered_map<const PrintObject*, PrintObjectSeamData> m_seam_per_object;
@ -170,8 +169,7 @@ private:
std::vector<std::pair<size_t, size_t>> find_seam_string(const PrintObject *po, std::vector<std::pair<size_t, size_t>> find_seam_string(const PrintObject *po,
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, float& string_weight) 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,