Merge branch 'master' of https://github.com/prusa3d/PrusaSlicer into et_opengl_3

This commit is contained in:
enricoturri1966 2022-03-09 12:06:09 +01:00
commit 57ffa4d9ee
3 changed files with 62 additions and 34 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

View File

@ -13,6 +13,8 @@
#include <unordered_set> #include <unordered_set>
#include <boost/range/adaptor/reversed.hpp> #include <boost/range/adaptor/reversed.hpp>
//#define AVOID_CROSSING_PERIMETERS_DEBUG_OUTPUT
namespace Slic3r { namespace Slic3r {
struct TravelPoint struct TravelPoint
@ -354,8 +356,6 @@ static Polyline to_polyline(const std::vector<TravelPoint> &travel)
return result; return result;
} }
// #define AVOID_CROSSING_PERIMETERS_DEBUG_OUTPUT
#ifdef AVOID_CROSSING_PERIMETERS_DEBUG_OUTPUT #ifdef AVOID_CROSSING_PERIMETERS_DEBUG_OUTPUT
static void export_travel_to_svg(const Polygons &boundary, static void export_travel_to_svg(const Polygons &boundary,
const Line &original_travel, const Line &original_travel,
@ -521,6 +521,25 @@ static float get_perimeter_spacing_external(const Layer &layer)
return perimeter_spacing; return perimeter_spacing;
} }
// Returns average perimeter width calculated from all LayerRegion within the layer.
static float get_external_perimeter_width(const Layer &layer)
{
size_t regions_count = 0;
float perimeter_width = 0.f;
for (const LayerRegion *layer_region : layer.regions())
if (layer_region != nullptr && !layer_region->slices.empty()) {
perimeter_width += float(layer_region->flow(frExternalPerimeter).scaled_width());
++regions_count;
}
assert(perimeter_width >= 0.f);
if (regions_count != 0)
perimeter_width /= float(regions_count);
else
perimeter_width = get_default_perimeter_spacing(*layer.object());
return perimeter_width;
}
// 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 AvoidCrossingPerimeters::Boundary &boundary, static size_t avoid_perimeters_inner(const AvoidCrossingPerimeters::Boundary &boundary,
const Point &start, const Point &start,
@ -659,22 +678,22 @@ static size_t avoid_perimeters(const AvoidCrossingPerimeters::Boundary &boundary
// Check if anyone of ExPolygons contains whole travel. // Check if anyone of ExPolygons contains whole travel.
// called by need_wipe() and AvoidCrossingPerimeters::travel_to() // called by need_wipe() and AvoidCrossingPerimeters::travel_to()
// FIXME Lukas H.: Maybe similar approach could also be used for ExPolygon::contains() // FIXME Lukas H.: Maybe similar approach could also be used for ExPolygon::contains()
static bool any_expolygon_contains(const ExPolygons &ex_polygons, static bool any_expolygon_contains(const ExPolygons &lslices_offset,
const std::vector<BoundingBox> &ex_polygons_bboxes, const std::vector<BoundingBox> &lslices_offset_bboxes,
const EdgeGrid::Grid &grid_lslice, const EdgeGrid::Grid &grid_lslices_offset,
const Line &travel) const Line &travel)
{ {
assert(ex_polygons.size() == ex_polygons_bboxes.size()); assert(lslices_offset.size() == lslices_offset_bboxes.size());
if(!grid_lslice.bbox().contains(travel.a) || !grid_lslice.bbox().contains(travel.b)) if(!grid_lslices_offset.bbox().contains(travel.a) || !grid_lslices_offset.bbox().contains(travel.b))
return false; return false;
FirstIntersectionVisitor visitor(grid_lslice); FirstIntersectionVisitor visitor(grid_lslices_offset);
visitor.pt_current = &travel.a; visitor.pt_current = &travel.a;
visitor.pt_next = &travel.b; visitor.pt_next = &travel.b;
grid_lslice.visit_cells_intersecting_line(*visitor.pt_current, *visitor.pt_next, visitor); grid_lslices_offset.visit_cells_intersecting_line(*visitor.pt_current, *visitor.pt_next, visitor);
if (!visitor.intersect) { if (!visitor.intersect) {
for (const ExPolygon &ex_polygon : ex_polygons) { for (const ExPolygon &ex_polygon : lslices_offset) {
const BoundingBox &bbox = ex_polygons_bboxes[&ex_polygon - &ex_polygons.front()]; const BoundingBox &bbox = lslices_offset_bboxes[&ex_polygon - &lslices_offset.front()];
if (bbox.contains(travel.a) && bbox.contains(travel.b) && ex_polygon.contains(travel.a)) if (bbox.contains(travel.a) && bbox.contains(travel.b) && ex_polygon.contains(travel.a))
return true; return true;
} }
@ -684,18 +703,18 @@ static bool any_expolygon_contains(const ExPolygons &ex_polygons,
// Check if anyone of ExPolygons contains whole travel. // Check if anyone of ExPolygons contains whole travel.
// called by need_wipe() // called by need_wipe()
static bool any_expolygon_contains(const ExPolygons &ex_polygons, const std::vector<BoundingBox> &ex_polygons_bboxes, const EdgeGrid::Grid &grid_lslice, const Polyline &travel) static bool any_expolygon_contains(const ExPolygons &ex_polygons, const std::vector<BoundingBox> &ex_polygons_bboxes, const EdgeGrid::Grid &grid_lslice_offset, const Polyline &travel)
{ {
assert(ex_polygons.size() == ex_polygons_bboxes.size()); assert(ex_polygons.size() == ex_polygons_bboxes.size());
if(std::any_of(travel.points.begin(), travel.points.end(), [&grid_lslice](const Point &point) { return !grid_lslice.bbox().contains(point); })) if(std::any_of(travel.points.begin(), travel.points.end(), [&grid_lslice_offset](const Point &point) { return !grid_lslice_offset.bbox().contains(point); }))
return false; return false;
FirstIntersectionVisitor visitor(grid_lslice); FirstIntersectionVisitor visitor(grid_lslice_offset);
bool any_intersection = false; bool any_intersection = false;
for (size_t line_idx = 1; line_idx < travel.size(); ++line_idx) { for (size_t line_idx = 1; line_idx < travel.size(); ++line_idx) {
visitor.pt_current = &travel.points[line_idx - 1]; visitor.pt_current = &travel.points[line_idx - 1];
visitor.pt_next = &travel.points[line_idx]; visitor.pt_next = &travel.points[line_idx];
grid_lslice.visit_cells_intersecting_line(*visitor.pt_current, *visitor.pt_next, visitor); grid_lslice_offset.visit_cells_intersecting_line(*visitor.pt_current, *visitor.pt_next, visitor);
any_intersection = visitor.intersect; any_intersection = visitor.intersect;
if (any_intersection) break; if (any_intersection) break;
} }
@ -711,14 +730,14 @@ static bool any_expolygon_contains(const ExPolygons &ex_polygons, const std::vec
return false; return false;
} }
static bool need_wipe(const GCode &gcodegen, static bool need_wipe(const GCode &gcodegen,
const EdgeGrid::Grid &grid_lslice, const ExPolygons &lslices_offset,
const Line &original_travel, const std::vector<BoundingBox> &lslices_offset_bboxes,
const Polyline &result_travel, const EdgeGrid::Grid &grid_lslices_offset,
const size_t intersection_count) const Line &original_travel,
const Polyline &result_travel,
const size_t intersection_count)
{ {
const ExPolygons &lslices = gcodegen.layer()->lslices;
const std::vector<BoundingBox> &lslices_bboxes = gcodegen.layer()->lslices_bboxes;
bool z_lift_enabled = gcodegen.config().retract_lift.get_at(gcodegen.writer().extruder()->id()) > 0.; bool z_lift_enabled = gcodegen.config().retract_lift.get_at(gcodegen.writer().extruder()->id()) > 0.;
bool wipe_needed = false; bool wipe_needed = false;
@ -728,16 +747,16 @@ static bool need_wipe(const GCode &gcodegen,
// The original layer is intersected with defined boundaries. Then it is necessary to make a detailed test. // The original layer is intersected with defined boundaries. Then it is necessary to make a detailed test.
// If the z-lift is enabled, then a wipe is needed when the original travel leads above the holes. // If the z-lift is enabled, then a wipe is needed when the original travel leads above the holes.
if (z_lift_enabled) { if (z_lift_enabled) {
if (any_expolygon_contains(lslices, lslices_bboxes, grid_lslice, original_travel)) { if (any_expolygon_contains(lslices_offset, lslices_offset_bboxes, grid_lslices_offset, original_travel)) {
// Check if original_travel and result_travel are not same. // Check if original_travel and result_travel are not same.
// If both are the same, then it is possible to skip testing of result_travel // If both are the same, then it is possible to skip testing of result_travel
wipe_needed = !(result_travel.size() > 2 && result_travel.first_point() == original_travel.a && result_travel.last_point() == original_travel.b) && wipe_needed = !(result_travel.size() > 2 && result_travel.first_point() == original_travel.a && result_travel.last_point() == original_travel.b) &&
!any_expolygon_contains(lslices, lslices_bboxes, grid_lslice, result_travel); !any_expolygon_contains(lslices_offset, lslices_offset_bboxes, grid_lslices_offset, result_travel);
} else { } else {
wipe_needed = true; wipe_needed = true;
} }
} else { } else {
wipe_needed = !any_expolygon_contains(lslices, lslices_bboxes, grid_lslice, result_travel); wipe_needed = !any_expolygon_contains(lslices_offset, lslices_offset_bboxes, grid_lslices_offset, result_travel);
} }
} }
@ -1163,10 +1182,8 @@ 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>();
const ExPolygons &lslices = gcodegen.layer()->lslices; bool is_support_layer = dynamic_cast<const SupportLayer *>(gcodegen.layer()) != nullptr;
const std::vector<BoundingBox> &lslices_bboxes = gcodegen.layer()->lslices_bboxes; if (!use_external && (is_support_layer || (!m_lslices_offset.empty() && !any_expolygon_contains(m_lslices_offset, m_lslices_offset_bboxes, m_grid_lslices_offset, travel)))) {
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())));
@ -1216,7 +1233,7 @@ Polyline AvoidCrossingPerimeters::travel_to(const GCode &gcodegen, const Point &
} else if (max_detour_length_exceeded) { } else if (max_detour_length_exceeded) {
*could_be_wipe_disabled = false; *could_be_wipe_disabled = false;
} else } else
*could_be_wipe_disabled = !need_wipe(gcodegen, m_grid_lslice, travel, result_pl, travel_intersection_count); *could_be_wipe_disabled = !need_wipe(gcodegen, m_lslices_offset, m_lslices_offset_bboxes, m_grid_lslices_offset, travel, result_pl, travel_intersection_count);
return result_pl; return result_pl;
} }
@ -1227,13 +1244,21 @@ void AvoidCrossingPerimeters::init_layer(const Layer &layer)
{ {
m_internal.clear(); m_internal.clear();
m_external.clear(); m_external.clear();
m_lslices_offset.clear();
m_lslices_offset_bboxes.clear();
float perimeter_offset = -get_external_perimeter_width(layer) / float(2.);
m_lslices_offset = offset_ex(layer.lslices, perimeter_offset);
m_lslices_offset_bboxes.reserve(m_lslices_offset.size());
for (const ExPolygon &ex_poly : m_lslices_offset)
m_lslices_offset_bboxes.emplace_back(get_extents(ex_poly));
BoundingBox bbox_slice(get_extents(layer.lslices)); BoundingBox bbox_slice(get_extents(layer.lslices));
bbox_slice.offset(SCALED_EPSILON); bbox_slice.offset(SCALED_EPSILON);
m_grid_lslice.set_bbox(bbox_slice); m_grid_lslices_offset.set_bbox(bbox_slice);
//FIXME 1mm grid? m_grid_lslices_offset.create(m_lslices_offset, coord_t(scale_(1.)));
m_grid_lslice.create(layer.lslices, coord_t(scale_(1.)));
} }
#if 0 #if 0

View File

@ -58,8 +58,11 @@ private:
// we enable it by default for the first travel move in print // we enable it by default for the first travel move in print
bool m_disabled_once { true }; bool m_disabled_once { true };
// Lslices offseted by half an external perimeter width. Used for detection if line or polyline is inside of any polygon.
ExPolygons m_lslices_offset;
std::vector<BoundingBox> m_lslices_offset_bboxes;
// Used for detection of line or polyline is inside of any polygon. // Used for detection of line or polyline is inside of any polygon.
EdgeGrid::Grid m_grid_lslice; EdgeGrid::Grid m_grid_lslices_offset;
// Store all needed data for travels inside object // Store all needed data for travels inside object
Boundary m_internal; Boundary m_internal;
// Store all needed data for travels outside object // Store all needed data for travels outside object