mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-17 08:35:53 +08:00
Fix #13870: Prefer a corner if there is one clearly rearest corner to be picked when placing rear seam
This commit is contained in:
parent
6176dcc540
commit
6494a3badd
@ -24,13 +24,48 @@ BoundingBoxf get_bounding_box(const Shells::Shell<> &shell) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<SeamChoice> get_clear_max_y_corner(
|
||||||
|
const std::vector<PerimeterLine> &possible_lines,
|
||||||
|
const Perimeters::Perimeter &perimeter,
|
||||||
|
const SeamChoice &max_y_choice,
|
||||||
|
const double rear_tolerance
|
||||||
|
) {
|
||||||
|
if (perimeter.angle_types[max_y_choice.previous_index] != Perimeters::AngleType::concave) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
const double epsilon{1e-2};
|
||||||
|
|
||||||
|
// Check if there are two max y corners (e.g. on a cube).
|
||||||
|
for (const PerimeterLine &line : possible_lines) {
|
||||||
|
if (
|
||||||
|
line.previous_index != max_y_choice.previous_index
|
||||||
|
&& perimeter.angle_types[line.previous_index] == Perimeters::AngleType::concave
|
||||||
|
&& max_y_choice.position.y() < line.a.y() + epsilon
|
||||||
|
&& (max_y_choice.position - line.a).norm() > epsilon
|
||||||
|
) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
line.next_index != max_y_choice.next_index
|
||||||
|
&& perimeter.angle_types[line.next_index] == Perimeters::AngleType::concave
|
||||||
|
&& max_y_choice.position.y() < line.b.y() + epsilon
|
||||||
|
&& (max_y_choice.position - line.b).norm() > epsilon
|
||||||
|
) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return max_y_choice;
|
||||||
|
}
|
||||||
|
|
||||||
SeamChoice get_max_y_choice(const std::vector<PerimeterLine> &possible_lines) {
|
SeamChoice get_max_y_choice(const std::vector<PerimeterLine> &possible_lines) {
|
||||||
if (possible_lines.empty()) {
|
if (possible_lines.empty()) {
|
||||||
throw std::runtime_error{"No possible lines!"};
|
throw std::runtime_error{"No possible lines!"};
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec2d point{possible_lines.front().a};
|
Vec2d point{possible_lines.front().a};
|
||||||
std::size_t point_index{0};
|
std::size_t point_index{possible_lines.front().previous_index};
|
||||||
|
|
||||||
for (const PerimeterLine &line : possible_lines) {
|
for (const PerimeterLine &line : possible_lines) {
|
||||||
if (line.a.y() > point.y()) {
|
if (line.a.y() > point.y()) {
|
||||||
@ -69,24 +104,37 @@ struct RearestPointCalculator {
|
|||||||
const PointClassification point_classification
|
const PointClassification point_classification
|
||||||
) {
|
) {
|
||||||
std::vector<PerimeterLine> possible_lines;
|
std::vector<PerimeterLine> possible_lines;
|
||||||
for (std::size_t i{0}; i < perimeter.positions.size() - 1; ++i) {
|
for (std::size_t i{0}; i < perimeter.positions.size(); ++i) {
|
||||||
|
const std::size_t next_index{i == perimeter.positions.size() - 1 ? 0 : i + 1};
|
||||||
if (perimeter.point_types[i] != point_type) {
|
if (perimeter.point_types[i] != point_type) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (perimeter.point_classifications[i] != point_classification) {
|
if (perimeter.point_classifications[i] != point_classification) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (perimeter.point_types[i + 1] != point_type) {
|
if (perimeter.point_types[next_index] != point_type) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (perimeter.point_classifications[i + 1] != point_classification) {
|
if (perimeter.point_classifications[next_index] != point_classification) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
possible_lines.push_back(PerimeterLine{perimeter.positions[i], perimeter.positions[i+1], i, i + 1});
|
possible_lines.push_back(PerimeterLine{perimeter.positions[i], perimeter.positions[next_index], i, next_index});
|
||||||
}
|
}
|
||||||
if (possible_lines.empty()) {
|
if (possible_lines.empty()) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const SeamChoice max_y_choice{get_max_y_choice(possible_lines)};
|
||||||
|
|
||||||
|
if (const auto clear_max_y_corner{get_clear_max_y_corner(
|
||||||
|
possible_lines,
|
||||||
|
perimeter,
|
||||||
|
max_y_choice,
|
||||||
|
rear_tolerance
|
||||||
|
)}) {
|
||||||
|
return *clear_max_y_corner;
|
||||||
|
}
|
||||||
|
|
||||||
const BoundingBoxf bounding_box{perimeter.positions};
|
const BoundingBoxf bounding_box{perimeter.positions};
|
||||||
const AABBTreeLines::LinesDistancer<PerimeterLine> possible_distancer{possible_lines};
|
const AABBTreeLines::LinesDistancer<PerimeterLine> possible_distancer{possible_lines};
|
||||||
const double center_x{(bounding_box.max.x() + bounding_box.min.x()) / 2.0};
|
const double center_x{(bounding_box.max.x() + bounding_box.min.x()) / 2.0};
|
||||||
@ -112,7 +160,7 @@ struct RearestPointCalculator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (bounding_box.max.y() - result.position.y() > rear_tolerance) {
|
if (bounding_box.max.y() - result.position.y() > rear_tolerance) {
|
||||||
return get_max_y_choice(possible_lines);
|
return max_y_choice;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user