Apply avoid crossing perimeters also for supports.
This commit is contained in:
parent
26755eb1d1
commit
0ca337ac7a
3 changed files with 65 additions and 16 deletions
|
@ -269,7 +269,7 @@ static std::vector<TravelPoint> simplify_travel(const AvoidCrossingPerimeters::B
|
|||
}
|
||||
|
||||
// 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 &end,
|
||||
std::vector<TravelPoint> &result_out)
|
||||
|
@ -372,14 +372,14 @@ static size_t avoid_perimeters_inner(const GCode &gcodegen, const AvoidCrossingP
|
|||
}
|
||||
|
||||
// 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 &end,
|
||||
Polyline &result_out)
|
||||
{
|
||||
// Travel line is completely or partially inside the bounding box.
|
||||
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);
|
||||
|
||||
#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.
|
||||
// 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))
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
//#define INCLUDE_SUPPORTS_IN_BOUNDARY
|
||||
|
||||
// called by AvoidCrossingPerimeters::travel_to()
|
||||
static ExPolygons get_boundary(const Layer &layer)
|
||||
{
|
||||
const float perimeter_spacing = get_perimeter_spacing(layer);
|
||||
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));
|
||||
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.
|
||||
size_t polygons_count = 0;
|
||||
for (const LayerRegion *layer_region : layer.regions())
|
||||
|
@ -810,20 +824,41 @@ static ExPolygons get_boundary(const Layer &layer)
|
|||
// called by AvoidCrossingPerimeters::travel_to()
|
||||
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;
|
||||
auto const *support_layer = dynamic_cast<const SupportLayer *>(&layer);
|
||||
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".
|
||||
for (const PrintObject *object : layer.object()->print()->objects()) {
|
||||
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)
|
||||
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()) {
|
||||
size_t boundary_idx = boundary.size();
|
||||
append(boundary, polygons_per_obj);
|
||||
for (; boundary_idx < boundary.size(); ++boundary_idx)
|
||||
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.
|
||||
for (Polygon &poly : boundary)
|
||||
poly.reverse();
|
||||
|
||||
#ifdef INCLUDE_SUPPORTS_IN_BOUNDARY
|
||||
append(boundary, to_polygons(inner_offset(supports_boundary, perimeter_offset)));
|
||||
#endif
|
||||
return boundary;
|
||||
}
|
||||
|
||||
|
@ -873,14 +910,17 @@ Polyline AvoidCrossingPerimeters::travel_to(const GCode &gcodegen, const Point &
|
|||
Vec2d startf = start.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.
|
||||
if (m_internal.boundaries.empty())
|
||||
init_boundary(&m_internal, to_polygons(get_boundary(*gcodegen.layer())));
|
||||
|
||||
// Trim the travel line by the bounding box.
|
||||
if (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);
|
||||
if (!m_internal.boundaries.empty() && Geometry::liang_barsky_line_clipping(startf, endf, m_internal.bbox)) {
|
||||
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.back() = end;
|
||||
}
|
||||
|
@ -891,7 +931,7 @@ Polyline AvoidCrossingPerimeters::travel_to(const GCode &gcodegen, const Point &
|
|||
|
||||
// Trim the travel line by the bounding box.
|
||||
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.back() = end;
|
||||
}
|
||||
|
|
|
@ -161,6 +161,8 @@ public:
|
|||
// Get a layer approximately at print_z.
|
||||
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);
|
||||
// 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.
|
||||
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)); }
|
||||
|
||||
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
|
||||
|
|
Loading…
Reference in a new issue