reworked and improved the find_next_seam_in_layer method:

Now uses find nearby_points with radius to save some computations
if all points are far.
From the nearby points, it finds the nearest and best point, and tries
to use them in this order (preivously only nearest was considered).
This helps to snap the alignment to nearby sharp corners if present.
This commit is contained in:
PavelMikus 2022-04-13 14:32:09 +02:00
parent 04d4a0d4f7
commit 83f3ca27dc

View File

@ -460,7 +460,7 @@ void process_perimeter_polygon(const Polygon &orig_polygon, float z_coord, const
};
size_t first_enforced_idx = perimeter.start_index;
for (int _ = 0; _ < perimeter_size; ++_) {
for (size_t _ = 0; _ < perimeter_size; ++_) {
if (result.points[first_enforced_idx].type != EnforcedBlockedSeamPoint::Enforced &&
result.points[next_index(first_enforced_idx)].type == EnforcedBlockedSeamPoint::Enforced) {
break;
@ -474,7 +474,7 @@ void process_perimeter_polygon(const Polygon &orig_polygon, float z_coord, const
std::vector<size_t> orig_large_angle_points_indices { };
std::vector<size_t> viable_points_indices { };
size_t last_enforced_idx = first_enforced_idx;
for (int _ = 0; _ < perimeter_size; ++_) {
for (size_t _ = 0; _ < perimeter_size; ++_) {
if (result.points[last_enforced_idx].type != EnforcedBlockedSeamPoint::Enforced) {
break;
}
@ -1025,35 +1025,72 @@ bool SeamPlacer::find_next_seam_in_layer(
const SeamCandidate &last_point = layers[last_point_indexes.first].points[last_point_indexes.second];
Vec3f projected_position { last_point.position.x(), last_point.position.y(), slice_z };
//find closest point in next layer
size_t closest_point_index = find_closest_point(*layers[layer_idx].points_tree, projected_position);
std::vector<size_t> nearby_points_indices = find_nearby_points(*layers[layer_idx].points_tree, projected_position,
SeamPlacer::seam_align_tolerable_dist);
const SeamCandidate &closest_point = layers[layer_idx].points[closest_point_index];
if (closest_point.perimeter.finalized) { //already finalized, skip
if (nearby_points_indices.empty()) {
return false;
}
//from the closest point, deduce index of seam in the next layer
const SeamCandidate &next_layer_seam = layers[layer_idx].points[closest_point.perimeter.seam_index];
size_t best_nearby_point_index = nearby_points_indices[0];
size_t nearest_point_index = nearby_points_indices[0];
// Now find best nearby point, nearest point, and corresponding indices
for (const size_t &nearby_point_index : nearby_points_indices) {
const SeamCandidate &point = layers[layer_idx].points[nearby_point_index];
if (point.perimeter.finalized) {
continue; // skip over finalized perimeters, try to find some that is not finalized
}
if (comparator.is_first_better(point, layers[layer_idx].points[best_nearby_point_index],
projected_position.head<2>())
|| layers[layer_idx].points[best_nearby_point_index].perimeter.finalized) {
best_nearby_point_index = nearby_point_index;
}
if ((point.position - projected_position).squaredNorm()
< (layers[layer_idx].points[nearest_point_index].position - projected_position).squaredNorm()
|| layers[layer_idx].points[nearest_point_index].perimeter.finalized) {
nearest_point_index = nearby_point_index;
}
}
const SeamCandidate &best_nearby_point = layers[layer_idx].points[best_nearby_point_index];
const SeamCandidate &nearest_point = layers[layer_idx].points[nearest_point_index];
if (nearest_point.perimeter.finalized) {
//all points are from already finalized perimeter, skip
return false;
}
//from the nearest_point, deduce index of seam in the next layer
const SeamCandidate &next_layer_seam = layers[layer_idx].points[nearest_point.perimeter.seam_index];
// First try to pick central enforcer if any present
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, closest_point.perimeter.seam_index };
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;
}
if ((closest_point.position - projected_position).squaredNorm() < sqr(SeamPlacer::seam_align_tolerable_dist)
&& comparator.is_first_not_much_worse(closest_point, next_layer_seam)
&& comparator.are_similar(last_point, closest_point)) {
last_point_indexes = std::pair<size_t, size_t> { layer_idx, closest_point_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
// We also compare it to the last point, to detect sharp changes in the scoring - that points to change in the model geometry and string should be ended.
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;
} else {
return false;
}
// 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 false;
}
// clusters already chosen seam points into strings across multiple layers, and then