Merge branch 'master' of https://github.com/prusa3d/PrusaSlicer into et_opengl_3
This commit is contained in:
commit
57ffa4d9ee
BIN
resources/profiles/Creality/ENDER3PRO_thumbnail.png
Normal file
BIN
resources/profiles/Creality/ENDER3PRO_thumbnail.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 27 KiB |
@ -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
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user