mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-05-24 23:27:46 +08:00
Apply avoid crossing perimeters also for supports.
This commit is contained in:
parent
26755eb1d1
commit
0ca337ac7a
@ -269,10 +269,10 @@ static std::vector<TravelPoint> simplify_travel(const AvoidCrossingPerimeters::B
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Called by avoid_perimeters() and by simplify_travel_heuristics().
|
// Called by avoid_perimeters() and by simplify_travel_heuristics().
|
||||||
static size_t avoid_perimeters_inner(const GCode &gcodegen, const AvoidCrossingPerimeters::Boundary &boundary,
|
static size_t avoid_perimeters_inner(const AvoidCrossingPerimeters::Boundary &boundary,
|
||||||
const Point &start,
|
const Point &start,
|
||||||
const Point &end,
|
const Point &end,
|
||||||
std::vector<TravelPoint> &result_out)
|
std::vector<TravelPoint> &result_out)
|
||||||
{
|
{
|
||||||
const Polygons &boundaries = boundary.boundaries;
|
const Polygons &boundaries = boundary.boundaries;
|
||||||
const EdgeGrid::Grid &edge_grid = boundary.grid;
|
const EdgeGrid::Grid &edge_grid = boundary.grid;
|
||||||
@ -372,14 +372,14 @@ static size_t avoid_perimeters_inner(const GCode &gcodegen, const AvoidCrossingP
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Called by AvoidCrossingPerimeters::travel_to()
|
// Called by AvoidCrossingPerimeters::travel_to()
|
||||||
static size_t avoid_perimeters(const GCode &gcodegen, const AvoidCrossingPerimeters::Boundary &boundary,
|
static size_t avoid_perimeters(const AvoidCrossingPerimeters::Boundary &boundary,
|
||||||
const Point &start,
|
const Point &start,
|
||||||
const Point &end,
|
const Point &end,
|
||||||
Polyline &result_out)
|
Polyline &result_out)
|
||||||
{
|
{
|
||||||
// Travel line is completely or partially inside the bounding box.
|
// Travel line is completely or partially inside the bounding box.
|
||||||
std::vector<TravelPoint> path;
|
std::vector<TravelPoint> path;
|
||||||
size_t num_intersections = avoid_perimeters_inner(gcodegen, boundary, start, end, path);
|
size_t num_intersections = avoid_perimeters_inner(boundary, start, end, path);
|
||||||
result_out = to_polyline(path);
|
result_out = to_polyline(path);
|
||||||
|
|
||||||
#ifdef AVOID_CROSSING_PERIMETERS_DEBUG_OUTPUT
|
#ifdef AVOID_CROSSING_PERIMETERS_DEBUG_OUTPUT
|
||||||
@ -726,6 +726,7 @@ static std::vector<float> contour_distance(const EdgeGrid::Grid &grid,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Polygon offset which ensures that if a polygon breaks up into several separate parts, the original polygon will be used in these places.
|
// Polygon offset which ensures that if a polygon breaks up into several separate parts, the original polygon will be used in these places.
|
||||||
|
// ExPolygons are handled one by one so returned ExPolygons could intersect.
|
||||||
static ExPolygons inner_offset(const ExPolygons &ex_polygons, double offset, double min_contour_width = scale_(0.001))
|
static ExPolygons inner_offset(const ExPolygons &ex_polygons, double offset, double min_contour_width = scale_(0.001))
|
||||||
{
|
{
|
||||||
double search_radius = 2. * (offset + min_contour_width);
|
double search_radius = 2. * (offset + min_contour_width);
|
||||||
@ -781,12 +782,25 @@ static ExPolygons inner_offset(const ExPolygons &ex_polygons, double offset, dou
|
|||||||
return ex_poly_result;
|
return ex_poly_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//#define INCLUDE_SUPPORTS_IN_BOUNDARY
|
||||||
|
|
||||||
// called by AvoidCrossingPerimeters::travel_to()
|
// called by AvoidCrossingPerimeters::travel_to()
|
||||||
static ExPolygons get_boundary(const Layer &layer)
|
static ExPolygons get_boundary(const Layer &layer)
|
||||||
{
|
{
|
||||||
const float perimeter_spacing = get_perimeter_spacing(layer);
|
const float perimeter_spacing = get_perimeter_spacing(layer);
|
||||||
const float perimeter_offset = perimeter_spacing / 2.f;
|
const float perimeter_offset = perimeter_spacing / 2.f;
|
||||||
|
auto const *support_layer = dynamic_cast<const SupportLayer *>(&layer);
|
||||||
ExPolygons boundary = union_ex(inner_offset(layer.lslices, perimeter_offset));
|
ExPolygons boundary = union_ex(inner_offset(layer.lslices, perimeter_offset));
|
||||||
|
if(support_layer) {
|
||||||
|
#ifdef INCLUDE_SUPPORTS_IN_BOUNDARY
|
||||||
|
append(boundary, inner_offset(support_layer->support_islands.expolygons, perimeter_offset));
|
||||||
|
#endif
|
||||||
|
auto *layer_below = layer.object()->get_first_layer_bellow_printz(layer.print_z, EPSILON);
|
||||||
|
if (layer_below)
|
||||||
|
append(boundary, inner_offset(layer_below->lslices, perimeter_offset));
|
||||||
|
// After calling inner_offset it is necessary to call union_ex because of the possibility of intersection ExPolygons
|
||||||
|
boundary = union_ex(boundary);
|
||||||
|
}
|
||||||
// Collect all top layers that will not be crossed.
|
// Collect all top layers that will not be crossed.
|
||||||
size_t polygons_count = 0;
|
size_t polygons_count = 0;
|
||||||
for (const LayerRegion *layer_region : layer.regions())
|
for (const LayerRegion *layer_region : layer.regions())
|
||||||
@ -810,20 +824,41 @@ static ExPolygons get_boundary(const Layer &layer)
|
|||||||
// called by AvoidCrossingPerimeters::travel_to()
|
// called by AvoidCrossingPerimeters::travel_to()
|
||||||
static Polygons get_boundary_external(const Layer &layer)
|
static Polygons get_boundary_external(const Layer &layer)
|
||||||
{
|
{
|
||||||
const float perimeter_spacing = get_perimeter_spacing(layer);
|
const float perimeter_spacing = get_perimeter_spacing_external(layer);
|
||||||
const float perimeter_offset = perimeter_spacing / 2.f;
|
const float perimeter_offset = perimeter_spacing / 2.f;
|
||||||
|
auto const *support_layer = dynamic_cast<const SupportLayer *>(&layer);
|
||||||
Polygons boundary;
|
Polygons boundary;
|
||||||
|
#ifdef INCLUDE_SUPPORTS_IN_BOUNDARY
|
||||||
|
ExPolygons supports_boundary;
|
||||||
|
#endif
|
||||||
// Collect all holes for all printed objects and their instances, which will be printed at the same time as passed "layer".
|
// Collect all holes for all printed objects and their instances, which will be printed at the same time as passed "layer".
|
||||||
for (const PrintObject *object : layer.object()->print()->objects()) {
|
for (const PrintObject *object : layer.object()->print()->objects()) {
|
||||||
Polygons polygons_per_obj;
|
Polygons polygons_per_obj;
|
||||||
|
#ifdef INCLUDE_SUPPORTS_IN_BOUNDARY
|
||||||
|
ExPolygons supports_per_obj;
|
||||||
|
#endif
|
||||||
if (const Layer *l = object->get_layer_at_printz(layer.print_z, EPSILON); l)
|
if (const Layer *l = object->get_layer_at_printz(layer.print_z, EPSILON); l)
|
||||||
for (const ExPolygon &island : l->lslices) append(polygons_per_obj, island.holes);
|
for (const ExPolygon &island : l->lslices) append(polygons_per_obj, island.holes);
|
||||||
|
if (support_layer) {
|
||||||
|
auto *layer_below = object->get_first_layer_bellow_printz(layer.print_z, EPSILON);
|
||||||
|
if (layer_below)
|
||||||
|
for (const ExPolygon &island : layer_below->lslices) append(polygons_per_obj, island.holes);
|
||||||
|
#ifdef INCLUDE_SUPPORTS_IN_BOUNDARY
|
||||||
|
append(supports_per_obj, support_layer->support_islands.expolygons);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
for (const PrintInstance &instance : object->instances()) {
|
for (const PrintInstance &instance : object->instances()) {
|
||||||
size_t boundary_idx = boundary.size();
|
size_t boundary_idx = boundary.size();
|
||||||
append(boundary, polygons_per_obj);
|
append(boundary, polygons_per_obj);
|
||||||
for (; boundary_idx < boundary.size(); ++boundary_idx)
|
for (; boundary_idx < boundary.size(); ++boundary_idx)
|
||||||
boundary[boundary_idx].translate(instance.shift);
|
boundary[boundary_idx].translate(instance.shift);
|
||||||
|
#ifdef INCLUDE_SUPPORTS_IN_BOUNDARY
|
||||||
|
size_t support_idx = supports_boundary.size();
|
||||||
|
append(supports_boundary, supports_per_obj);
|
||||||
|
for (; support_idx < supports_boundary.size(); ++support_idx)
|
||||||
|
supports_boundary[support_idx].translate(instance.shift);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -832,7 +867,9 @@ static Polygons get_boundary_external(const Layer &layer)
|
|||||||
// Reverse all polygons for making normals point from the polygon out.
|
// Reverse all polygons for making normals point from the polygon out.
|
||||||
for (Polygon &poly : boundary)
|
for (Polygon &poly : boundary)
|
||||||
poly.reverse();
|
poly.reverse();
|
||||||
|
#ifdef INCLUDE_SUPPORTS_IN_BOUNDARY
|
||||||
|
append(boundary, to_polygons(inner_offset(supports_boundary, perimeter_offset)));
|
||||||
|
#endif
|
||||||
return boundary;
|
return boundary;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -873,14 +910,17 @@ Polyline AvoidCrossingPerimeters::travel_to(const GCode &gcodegen, const Point &
|
|||||||
Vec2d startf = start.cast<double>();
|
Vec2d startf = start.cast<double>();
|
||||||
Vec2d endf = end .cast<double>();
|
Vec2d endf = end .cast<double>();
|
||||||
|
|
||||||
if (!use_external && !gcodegen.layer()->lslices.empty() && !any_expolygon_contains(gcodegen.layer()->lslices, gcodegen.layer()->lslices_bboxes, m_grid_lslice, travel)) {
|
const ExPolygons &lslices = gcodegen.layer()->lslices;
|
||||||
|
const std::vector<BoundingBox> &lslices_bboxes = gcodegen.layer()->lslices_bboxes;
|
||||||
|
bool is_support_layer = dynamic_cast<const SupportLayer *>(gcodegen.layer()) != nullptr;
|
||||||
|
if (!use_external && (is_support_layer || (!lslices.empty() && !any_expolygon_contains(lslices, lslices_bboxes, m_grid_lslice, travel)))) {
|
||||||
// Initialize m_internal only when it is necessary.
|
// Initialize m_internal only when it is necessary.
|
||||||
if (m_internal.boundaries.empty())
|
if (m_internal.boundaries.empty())
|
||||||
init_boundary(&m_internal, to_polygons(get_boundary(*gcodegen.layer())));
|
init_boundary(&m_internal, to_polygons(get_boundary(*gcodegen.layer())));
|
||||||
|
|
||||||
// Trim the travel line by the bounding box.
|
// Trim the travel line by the bounding box.
|
||||||
if (Geometry::liang_barsky_line_clipping(startf, endf, m_internal.bbox)) {
|
if (!m_internal.boundaries.empty() && Geometry::liang_barsky_line_clipping(startf, endf, m_internal.bbox)) {
|
||||||
travel_intersection_count = avoid_perimeters(gcodegen, m_internal, startf.cast<coord_t>(), endf.cast<coord_t>(), result_pl);
|
travel_intersection_count = avoid_perimeters(m_internal, startf.cast<coord_t>(), endf.cast<coord_t>(), result_pl);
|
||||||
result_pl.points.front() = start;
|
result_pl.points.front() = start;
|
||||||
result_pl.points.back() = end;
|
result_pl.points.back() = end;
|
||||||
}
|
}
|
||||||
@ -891,7 +931,7 @@ Polyline AvoidCrossingPerimeters::travel_to(const GCode &gcodegen, const Point &
|
|||||||
|
|
||||||
// Trim the travel line by the bounding box.
|
// Trim the travel line by the bounding box.
|
||||||
if (!m_external.boundaries.empty() && Geometry::liang_barsky_line_clipping(startf, endf, m_external.bbox)) {
|
if (!m_external.boundaries.empty() && Geometry::liang_barsky_line_clipping(startf, endf, m_external.bbox)) {
|
||||||
travel_intersection_count = avoid_perimeters(gcodegen, m_external, startf.cast<coord_t>(), endf.cast<coord_t>(), result_pl);
|
travel_intersection_count = avoid_perimeters(m_external, startf.cast<coord_t>(), endf.cast<coord_t>(), result_pl);
|
||||||
result_pl.points.front() = start;
|
result_pl.points.front() = start;
|
||||||
result_pl.points.back() = end;
|
result_pl.points.back() = end;
|
||||||
}
|
}
|
||||||
|
@ -161,6 +161,8 @@ public:
|
|||||||
// Get a layer approximately at print_z.
|
// Get a layer approximately at print_z.
|
||||||
const Layer* get_layer_at_printz(coordf_t print_z, coordf_t epsilon) const;
|
const Layer* get_layer_at_printz(coordf_t print_z, coordf_t epsilon) const;
|
||||||
Layer* get_layer_at_printz(coordf_t print_z, coordf_t epsilon);
|
Layer* get_layer_at_printz(coordf_t print_z, coordf_t epsilon);
|
||||||
|
// Get the first layer approximately bellow print_z.
|
||||||
|
const Layer* get_first_layer_bellow_printz(coordf_t print_z, coordf_t epsilon) const;
|
||||||
|
|
||||||
// print_z: top of the layer; slice_z: center of the layer.
|
// print_z: top of the layer; slice_z: center of the layer.
|
||||||
Layer* add_layer(int id, coordf_t height, coordf_t print_z, coordf_t slice_z);
|
Layer* add_layer(int id, coordf_t height, coordf_t print_z, coordf_t slice_z);
|
||||||
|
@ -2943,4 +2943,11 @@ const Layer* PrintObject::get_layer_at_printz(coordf_t print_z, coordf_t epsilon
|
|||||||
|
|
||||||
Layer* PrintObject::get_layer_at_printz(coordf_t print_z, coordf_t epsilon) { return const_cast<Layer*>(std::as_const(*this).get_layer_at_printz(print_z, epsilon)); }
|
Layer* PrintObject::get_layer_at_printz(coordf_t print_z, coordf_t epsilon) { return const_cast<Layer*>(std::as_const(*this).get_layer_at_printz(print_z, epsilon)); }
|
||||||
|
|
||||||
|
const Layer *PrintObject::get_first_layer_bellow_printz(coordf_t print_z, coordf_t epsilon) const
|
||||||
|
{
|
||||||
|
coordf_t limit = print_z + epsilon;
|
||||||
|
auto it = Slic3r::lower_bound_by_predicate(m_layers.begin(), m_layers.end(), [limit](const Layer *layer) { return layer->print_z < limit; });
|
||||||
|
return (it == m_layers.begin()) ? nullptr : *(--it);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
Loading…
x
Reference in New Issue
Block a user