mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-13 17:49:01 +08:00
Handle special seam case of just 2 or 3 perimeters.
If there are only 2 or 3 perimeters on a layer, exactly two of them are external and just one of them is a hole, then the seams should be choosen next to each other on the external perimeters.
This commit is contained in:
parent
d158c0a4de
commit
9a1dcc4720
@ -269,6 +269,7 @@ Perimeter::PointTrees get_kd_trees(
|
||||
Perimeter::Perimeter(
|
||||
const double slice_z,
|
||||
const std::size_t layer_index,
|
||||
const bool is_hole,
|
||||
std::vector<Vec2d> &&positions,
|
||||
std::vector<double> &&angles,
|
||||
std::vector<PointType> &&point_types,
|
||||
@ -277,6 +278,7 @@ Perimeter::Perimeter(
|
||||
)
|
||||
: slice_z(slice_z)
|
||||
, layer_index(layer_index)
|
||||
, is_hole(is_hole)
|
||||
, positions(std::move(positions))
|
||||
, angles(std::move(angles))
|
||||
, index_to_coord(IndexToCoord{tcb::span{this->positions}})
|
||||
@ -304,6 +306,7 @@ Perimeter Perimeter::create_degenerate(
|
||||
Perimeter perimeter{
|
||||
slice_z,
|
||||
layer_index,
|
||||
false,
|
||||
std::move(points),
|
||||
std::move(angles),
|
||||
std::move(point_types),
|
||||
@ -368,9 +371,12 @@ Perimeter Perimeter::create(
|
||||
Impl::get_angle_types(smooth_angles, params.convex_threshold, params.concave_threshold)};
|
||||
angle_types = Impl::merge_angle_types(angle_types, smooth_angle_types, perimeter_points, params.smooth_angle_arm_length);
|
||||
|
||||
const bool is_hole{polygon.is_clockwise()};
|
||||
|
||||
return Perimeter{
|
||||
layer_info.slice_z,
|
||||
layer_info.index,
|
||||
is_hole,
|
||||
std::move(perimeter_points),
|
||||
std::move(angles),
|
||||
std::move(point_types),
|
||||
|
@ -127,6 +127,7 @@ struct Perimeter
|
||||
Perimeter(
|
||||
const double slice_z,
|
||||
const std::size_t layer_index,
|
||||
const bool is_hole,
|
||||
std::vector<Vec2d> &&positions,
|
||||
std::vector<double> &&angles,
|
||||
std::vector<PointType> &&point_types,
|
||||
@ -147,6 +148,7 @@ struct Perimeter
|
||||
|
||||
bool is_degenerate{false};
|
||||
double slice_z{};
|
||||
bool is_hole{false};
|
||||
std::size_t layer_index{};
|
||||
std::vector<Vec2d> positions{};
|
||||
std::vector<double> angles{};
|
||||
|
@ -298,6 +298,21 @@ std::pair<SeamChoice, std::size_t> place_seam_near(
|
||||
return {choice, choice_index};
|
||||
}
|
||||
|
||||
int get_perimeter_count(const Layer *layer){
|
||||
int count{0};
|
||||
for (const LayerRegion *layer_region : layer->regions()) {
|
||||
for (const ExtrusionEntity *ex_entity : layer_region->perimeters()) {
|
||||
if (ex_entity->is_collection()) { //collection of inner, outer, and overhang perimeters
|
||||
count += static_cast<const ExtrusionEntityCollection*>(ex_entity)->entities.size();
|
||||
}
|
||||
else {
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
Point Placer::place_seam(const Layer *layer, const ExtrusionLoop &loop, const Point &last_pos) const {
|
||||
const PrintObject *po = layer->object();
|
||||
// Must not be called with supprot layer.
|
||||
@ -311,12 +326,33 @@ Point Placer::place_seam(const Layer *layer, const ExtrusionLoop &loop, const Po
|
||||
const bool do_staggering{this->params.staggered_inner_seams && loop.role() == ExtrusionRole::Perimeter};
|
||||
const double loop_width{loop.paths.empty() ? 0.0 : loop.paths.front().width()};
|
||||
|
||||
|
||||
if (this->params.seam_preference == spNearest) {
|
||||
const std::vector<BoundedPerimeter> &perimeters{this->perimeters_per_layer.at(po)[layer_index]};
|
||||
const auto [seam_choice, perimeter_index] = place_seam_near(perimeters, loop, last_pos, this->params.max_nearest_detour);
|
||||
return finalize_seam_position(loop_polygon, seam_choice, perimeters[perimeter_index].perimeter, loop_width, do_staggering);
|
||||
} else {
|
||||
const SeamPerimeterChoice &seam_perimeter_choice{choose_closest_seam(this->seams_per_object.at(po)[layer_index], loop_polygon)};
|
||||
const std::vector<SeamPerimeterChoice> &seams_on_perimeters{this->seams_per_object.at(po)[layer_index]};
|
||||
|
||||
// Special case.
|
||||
// If there are only two perimeters and the current perimeter is hole (clockwise).
|
||||
const int perimeter_count{get_perimeter_count(layer)};
|
||||
const bool has_2_or_3_perimeters{perimeter_count == 2 || perimeter_count == 3};
|
||||
if (has_2_or_3_perimeters) {
|
||||
if (seams_on_perimeters.size() == 2 &&
|
||||
seams_on_perimeters[0].perimeter.is_hole !=
|
||||
seams_on_perimeters[1].perimeter.is_hole) {
|
||||
const SeamPerimeterChoice &seam_perimeter_choice{
|
||||
seams_on_perimeters[0].perimeter.is_hole ? seams_on_perimeters[1] :
|
||||
seams_on_perimeters[0]};
|
||||
return finalize_seam_position(
|
||||
loop_polygon, seam_perimeter_choice.choice, seam_perimeter_choice.perimeter,
|
||||
loop_width, do_staggering
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const SeamPerimeterChoice &seam_perimeter_choice{choose_closest_seam(seams_on_perimeters, loop_polygon)};
|
||||
return finalize_seam_position(loop_polygon, seam_perimeter_choice.choice, seam_perimeter_choice.perimeter, loop_width, do_staggering);
|
||||
}
|
||||
}
|
||||
|
@ -19,10 +19,11 @@ BoundedPolygons project_to_geometry(const Geometry::Extrusions &external_perimet
|
||||
external_perimeter.island_boundary_bounding_boxes
|
||||
)};
|
||||
|
||||
const bool is_hole{choosen_index != 0};
|
||||
const Polygon &adjacent_boundary{
|
||||
choosen_index == 0 ? external_perimeter.island_boundary.contour :
|
||||
external_perimeter.island_boundary.holes[choosen_index - 1]};
|
||||
return BoundedPolygon{adjacent_boundary, external_perimeter.island_boundary_bounding_boxes[choosen_index]};
|
||||
!is_hole ? external_perimeter.island_boundary.contour :
|
||||
external_perimeter.island_boundary.holes[choosen_index - 1]};
|
||||
return BoundedPolygon{adjacent_boundary, external_perimeter.island_boundary_bounding_boxes[choosen_index], is_hole};
|
||||
}
|
||||
);
|
||||
return result;
|
||||
|
@ -20,6 +20,7 @@ namespace Slic3r::Seams::Shells::Impl {
|
||||
struct BoundedPolygon {
|
||||
Polygon polygon;
|
||||
BoundingBox bounding_box;
|
||||
bool is_hole{false};
|
||||
};
|
||||
|
||||
using BoundedPolygons = std::vector<BoundedPolygon>;
|
||||
|
@ -25,6 +25,7 @@ Perimeters::Perimeter get_perimeter() {
|
||||
return {
|
||||
slice_z,
|
||||
layer_index,
|
||||
false,
|
||||
std::move(positions),
|
||||
std::move(angles),
|
||||
std::move(point_types),
|
||||
|
@ -76,6 +76,7 @@ TEST_CASE("Perimeter constructs KD trees", "[Seams][SeamPerimeters]") {
|
||||
Perimeters::Perimeter perimeter{
|
||||
3.0,
|
||||
2,
|
||||
false,
|
||||
std::move(positions),
|
||||
std::move(angles),
|
||||
std::move(point_types),
|
||||
|
@ -23,6 +23,7 @@ Perimeters::Perimeter get_perimeter() {
|
||||
return {
|
||||
slice_z,
|
||||
layer_index,
|
||||
false,
|
||||
std::move(positions),
|
||||
std::move(angles),
|
||||
std::move(point_types),
|
||||
|
@ -25,6 +25,7 @@ Perimeters::Perimeter get_perimeter() {
|
||||
return {
|
||||
slice_z,
|
||||
layer_index,
|
||||
false,
|
||||
std::move(positions),
|
||||
std::move(angles),
|
||||
std::move(point_types),
|
||||
|
Loading…
x
Reference in New Issue
Block a user