mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-12 01:07:57 -06:00
Fixes scars on thing walls when "avoid crossing wall" is turned on (#2659)
* Travel very close to the inner holes, could cross external perimeter when the avoid crossing perimeters was enabled. (cherry picked from commit prusa3d/PrusaSlicer@6c51e5148c) * Modified variable offset in the avoid crossing perimeters to not cause scars on thin objects (#7699). Previously, the minimum contour width was chosen too conservative and, on some thin objects, only allowed minimal (or non) offset. This could result in travels being planned along the outer perimeter. Now, the minimum contour width is chosen much smaller at the start and tested if the variable offset wasn't failed (the outer contour broke up into more parts, more or fewer holes, etc.). If any problem is detected, the variable offset is recalculated with a larger minimum contour width. (cherry picked from commit prusa3d/PrusaSlicer@dc00f0bf98) --------- Co-authored-by: Lukáš Hejl <hejl.lukas@gmail.com>
This commit is contained in:
parent
333287535b
commit
f16feff2a4
2 changed files with 168 additions and 102 deletions
|
@ -1,3 +1,7 @@
|
|||
///|/ Copyright (c) Prusa Research 2020 - 2022 Vojtěch Bubník @bubnikv, Lukáš Hejl @hejllukas
|
||||
///|/
|
||||
///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher
|
||||
///|/
|
||||
#include "../Layer.hpp"
|
||||
#include "../GCode.hpp"
|
||||
#include "../EdgeGrid.hpp"
|
||||
|
@ -13,6 +17,8 @@
|
|||
#include <unordered_set>
|
||||
#include <boost/range/adaptor/reversed.hpp>
|
||||
|
||||
//#define AVOID_CROSSING_PERIMETERS_DEBUG_OUTPUT
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
struct TravelPoint
|
||||
|
@ -20,6 +26,8 @@ struct TravelPoint
|
|||
Point point;
|
||||
// Index of the polygon containing this point. A negative value indicates that the point is not on any border.
|
||||
int border_idx;
|
||||
// simplify_travel() doesn't remove this point.
|
||||
bool do_not_remove = false;
|
||||
};
|
||||
|
||||
struct Intersection
|
||||
|
@ -32,6 +40,8 @@ struct Intersection
|
|||
Point point;
|
||||
// Distance from the first point in the corresponding boundary
|
||||
float distance;
|
||||
// simplify_travel() doesn't remove this point.
|
||||
bool do_not_remove = false;
|
||||
};
|
||||
|
||||
struct ClosestLine
|
||||
|
@ -207,8 +217,8 @@ static std::vector<Intersection> extend_for_closest_lines(const std::vector<Inte
|
|||
const ClosestLine &cl_start = start_lines[cl_indices.first];
|
||||
const ClosestLine &cl_end = end_lines[cl_indices.second];
|
||||
std::vector<Intersection> new_intersections;
|
||||
new_intersections.push_back({cl_start.border_idx, cl_start.line_idx, cl_start.point, compute_distance(cl_start)});
|
||||
new_intersections.push_back({cl_end.border_idx, cl_end.line_idx, cl_end.point, compute_distance(cl_end)});
|
||||
new_intersections.push_back({cl_start.border_idx, cl_start.line_idx, cl_start.point, compute_distance(cl_start), true});
|
||||
new_intersections.push_back({cl_end.border_idx, cl_end.line_idx, cl_end.point, compute_distance(cl_end), true});
|
||||
return new_intersections;
|
||||
}
|
||||
}
|
||||
|
@ -259,7 +269,7 @@ static std::vector<Intersection> extend_for_closest_lines(const std::vector<Inte
|
|||
if (cl_start_idx != std::numeric_limits<size_t>::max()) {
|
||||
// If there is any ClosestLine around the start point closer to the Intersection, then replace this Intersection with ClosestLine.
|
||||
const ClosestLine &cl_start = start_lines[cl_start_idx];
|
||||
new_intersections.front() = {cl_start.border_idx, cl_start.line_idx, cl_start.point, compute_distance(cl_start)};
|
||||
new_intersections.front() = {cl_start.border_idx, cl_start.line_idx, cl_start.point, compute_distance(cl_start), true};
|
||||
} else {
|
||||
// Check if there is any ClosestLine with the same boundary_idx as any Intersection. If this ClosestLine exists, then add it to the
|
||||
// vector of intersections. This allows in some cases when it is more than one around ClosestLine start point chose that one which
|
||||
|
@ -267,7 +277,7 @@ static std::vector<Intersection> extend_for_closest_lines(const std::vector<Inte
|
|||
// use the first one, which is the closest one to the start point.
|
||||
size_t start_closest_lines_idx = find_closest_line_with_same_boundary_idx(start_lines, new_intersections, true);
|
||||
const ClosestLine &cl_start = (start_closest_lines_idx != std::numeric_limits<size_t>::max()) ? start_lines[start_closest_lines_idx] : start_lines.front();
|
||||
new_intersections.insert(new_intersections.begin(),{cl_start.border_idx, cl_start.line_idx, cl_start.point, compute_distance(cl_start)});
|
||||
new_intersections.insert(new_intersections.begin(),{cl_start.border_idx, cl_start.line_idx, cl_start.point, compute_distance(cl_start), true});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -276,7 +286,7 @@ static std::vector<Intersection> extend_for_closest_lines(const std::vector<Inte
|
|||
if (cl_end_idx != std::numeric_limits<size_t>::max()) {
|
||||
// If there is any ClosestLine around the end point closer to the Intersection, then replace this Intersection with ClosestLine.
|
||||
const ClosestLine &cl_end = end_lines[cl_end_idx];
|
||||
new_intersections.back() = {cl_end.border_idx, cl_end.line_idx, cl_end.point, compute_distance(cl_end)};
|
||||
new_intersections.back() = {cl_end.border_idx, cl_end.line_idx, cl_end.point, compute_distance(cl_end), true};
|
||||
} else {
|
||||
// Check if there is any ClosestLine with the same boundary_idx as any Intersection. If this ClosestLine exists, then add it to the
|
||||
// vector of intersections. This allows in some cases when it is more than one around ClosestLine end point chose that one which
|
||||
|
@ -284,7 +294,7 @@ static std::vector<Intersection> extend_for_closest_lines(const std::vector<Inte
|
|||
// use the first one, which is the closest one to the end point.
|
||||
size_t end_closest_lines_idx = find_closest_line_with_same_boundary_idx(end_lines, new_intersections, false);
|
||||
const ClosestLine &cl_end = (end_closest_lines_idx != std::numeric_limits<size_t>::max()) ? end_lines[end_closest_lines_idx] : end_lines.front();
|
||||
new_intersections.push_back({cl_end.border_idx, cl_end.line_idx, cl_end.point, compute_distance(cl_end)});
|
||||
new_intersections.push_back({cl_end.border_idx, cl_end.line_idx, cl_end.point, compute_distance(cl_end), true});
|
||||
}
|
||||
}
|
||||
return new_intersections;
|
||||
|
@ -350,8 +360,6 @@ static Polyline to_polyline(const std::vector<TravelPoint> &travel)
|
|||
return result;
|
||||
}
|
||||
|
||||
// #define AVOID_CROSSING_PERIMETERS_DEBUG_OUTPUT
|
||||
|
||||
#ifdef AVOID_CROSSING_PERIMETERS_DEBUG_OUTPUT
|
||||
static void export_travel_to_svg(const Polygons &boundary,
|
||||
const Line &original_travel,
|
||||
|
@ -359,16 +367,17 @@ static void export_travel_to_svg(const Polygons &boundary,
|
|||
const std::vector<Intersection> &intersections,
|
||||
const std::string &path)
|
||||
{
|
||||
coordf_t stroke_width = scale_(0.05);
|
||||
BoundingBox bbox = get_extents(boundary);
|
||||
::Slic3r::SVG svg(path, bbox);
|
||||
svg.draw_outline(boundary, "green");
|
||||
svg.draw(original_travel, "blue");
|
||||
svg.draw(result_travel, "red");
|
||||
svg.draw(original_travel.a, "black");
|
||||
svg.draw(original_travel.b, "grey");
|
||||
svg.draw_outline(boundary, "green", stroke_width);
|
||||
svg.draw(original_travel, "blue", stroke_width);
|
||||
svg.draw(result_travel, "red", stroke_width);
|
||||
svg.draw(original_travel.a, "black", stroke_width);
|
||||
svg.draw(original_travel.b, "grey", stroke_width);
|
||||
|
||||
for (const Intersection &intersection : intersections)
|
||||
svg.draw(intersection.point, "lightseagreen");
|
||||
svg.draw(intersection.point, "lightseagreen", stroke_width);
|
||||
}
|
||||
|
||||
static void export_travel_to_svg(const Polygons &boundary,
|
||||
|
@ -433,7 +442,16 @@ static std::vector<TravelPoint> simplify_travel(const AvoidCrossingPerimeters::B
|
|||
|
||||
visitor.pt_current = ¤t_point;
|
||||
|
||||
if (!next.do_not_remove)
|
||||
for (size_t point_idx_2 = point_idx + 1; point_idx_2 < travel.size(); ++point_idx_2) {
|
||||
// Workaround for some issue in MSVC 19.29.30037 32-bit compiler.
|
||||
#if defined(_WIN32) && !defined(_WIN64)
|
||||
if (bool volatile do_not_remove = travel[point_idx_2].do_not_remove; do_not_remove)
|
||||
break;
|
||||
#else
|
||||
if (travel[point_idx_2].do_not_remove)
|
||||
break;
|
||||
#endif
|
||||
if (travel[point_idx_2].point == current_point) {
|
||||
next = travel[point_idx_2];
|
||||
point_idx = point_idx_2;
|
||||
|
@ -507,6 +525,25 @@ static float get_perimeter_spacing_external(const Layer &layer)
|
|||
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().
|
||||
static size_t avoid_perimeters_inner(const AvoidCrossingPerimeters::Boundary &boundary,
|
||||
const Point &start,
|
||||
|
@ -566,7 +603,7 @@ static size_t avoid_perimeters_inner(const AvoidCrossingPerimeters::Boundary &bo
|
|||
// Offset of the polygon's point using get_middle_point_offset is used to simplify the calculation of intersection between the
|
||||
// boundary and the travel. The appended point is translated in the direction of inward normal. This translation ensures that the
|
||||
// appended point will be inside the polygon and not on the polygon border.
|
||||
result.push_back({get_middle_point_offset(boundaries[intersection_first.border_idx], left_idx, right_idx, intersection_first.point, coord_t(SCALED_EPSILON)), int(intersection_first.border_idx)});
|
||||
result.push_back({get_middle_point_offset(boundaries[intersection_first.border_idx], left_idx, right_idx, intersection_first.point, coord_t(SCALED_EPSILON)), int(intersection_first.border_idx), intersection_first.do_not_remove});
|
||||
|
||||
// Check if intersection line also exit the boundary polygon
|
||||
if (it_second_r != it_last_item) {
|
||||
|
@ -590,7 +627,7 @@ static size_t avoid_perimeters_inner(const AvoidCrossingPerimeters::Boundary &bo
|
|||
// Append the farthest intersection into the path
|
||||
left_idx = intersection_second.line_idx;
|
||||
right_idx = (intersection_second.line_idx >= (boundaries[intersection_second.border_idx].points.size() - 1)) ? 0 : (intersection_second.line_idx + 1);
|
||||
result.push_back({get_middle_point_offset(boundaries[intersection_second.border_idx], left_idx, right_idx, intersection_second.point, coord_t(SCALED_EPSILON)), int(intersection_second.border_idx)});
|
||||
result.push_back({get_middle_point_offset(boundaries[intersection_second.border_idx], left_idx, right_idx, intersection_second.point, coord_t(SCALED_EPSILON)), int(intersection_second.border_idx), intersection_second.do_not_remove});
|
||||
// Skip intersections in between
|
||||
it_first = it_second;
|
||||
}
|
||||
|
@ -645,22 +682,22 @@ static size_t avoid_perimeters(const AvoidCrossingPerimeters::Boundary &boundary
|
|||
// Check if anyone of ExPolygons contains whole travel.
|
||||
// called by need_wipe() and AvoidCrossingPerimeters::travel_to()
|
||||
// FIXME Lukas H.: Maybe similar approach could also be used for ExPolygon::contains()
|
||||
static bool any_expolygon_contains(const ExPolygons &ex_polygons,
|
||||
const std::vector<BoundingBox> &ex_polygons_bboxes,
|
||||
const EdgeGrid::Grid &grid_lslice,
|
||||
static bool any_expolygon_contains(const ExPolygons &lslices_offset,
|
||||
const std::vector<BoundingBox> &lslices_offset_bboxes,
|
||||
const EdgeGrid::Grid &grid_lslices_offset,
|
||||
const Line &travel)
|
||||
{
|
||||
assert(ex_polygons.size() == ex_polygons_bboxes.size());
|
||||
if(!grid_lslice.bbox().contains(travel.a) || !grid_lslice.bbox().contains(travel.b))
|
||||
assert(lslices_offset.size() == lslices_offset_bboxes.size());
|
||||
if(!grid_lslices_offset.bbox().contains(travel.a) || !grid_lslices_offset.bbox().contains(travel.b))
|
||||
return false;
|
||||
|
||||
FirstIntersectionVisitor visitor(grid_lslice);
|
||||
FirstIntersectionVisitor visitor(grid_lslices_offset);
|
||||
visitor.pt_current = &travel.a;
|
||||
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) {
|
||||
for (const ExPolygon &ex_polygon : ex_polygons) {
|
||||
const BoundingBox &bbox = ex_polygons_bboxes[&ex_polygon - &ex_polygons.front()];
|
||||
for (const ExPolygon &ex_polygon : lslices_offset) {
|
||||
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))
|
||||
return true;
|
||||
}
|
||||
|
@ -670,18 +707,18 @@ static bool any_expolygon_contains(const ExPolygons &ex_polygons,
|
|||
|
||||
// Check if anyone of ExPolygons contains whole travel.
|
||||
// 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());
|
||||
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;
|
||||
|
||||
FirstIntersectionVisitor visitor(grid_lslice);
|
||||
FirstIntersectionVisitor visitor(grid_lslice_offset);
|
||||
bool any_intersection = false;
|
||||
for (size_t line_idx = 1; line_idx < travel.size(); ++line_idx) {
|
||||
visitor.pt_current = &travel.points[line_idx - 1];
|
||||
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;
|
||||
if (any_intersection) break;
|
||||
}
|
||||
|
@ -698,13 +735,13 @@ static bool any_expolygon_contains(const ExPolygons &ex_polygons, const std::vec
|
|||
}
|
||||
|
||||
static bool need_wipe(const GCode &gcodegen,
|
||||
const EdgeGrid::Grid &grid_lslice,
|
||||
const ExPolygons &lslices_offset,
|
||||
const std::vector<BoundingBox> &lslices_offset_bboxes,
|
||||
const EdgeGrid::Grid &grid_lslices_offset,
|
||||
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().z_hop.get_at(gcodegen.writer().extruder()->id()) > 0.;
|
||||
bool wipe_needed = false;
|
||||
|
||||
|
@ -714,16 +751,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.
|
||||
// If the z-lift is enabled, then a wipe is needed when the original travel leads above the holes.
|
||||
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.
|
||||
// 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) &&
|
||||
!any_expolygon_contains(lslices, lslices_bboxes, grid_lslice, result_travel);
|
||||
!any_expolygon_contains(lslices_offset, lslices_offset_bboxes, grid_lslices_offset, result_travel);
|
||||
} else {
|
||||
wipe_needed = true;
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -945,14 +982,22 @@ static std::vector<float> contour_distance(const EdgeGrid::Grid &grid,
|
|||
// 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 = 2. * offset + SCALED_EPSILON;
|
||||
double search_radius = 2. * (offset + min_contour_width);
|
||||
const std::vector<double> min_contour_width_values = {offset / 2., offset, 2. * offset + SCALED_EPSILON};
|
||||
ExPolygons ex_poly_result = ex_polygons;
|
||||
resample_expolygons(ex_poly_result, offset / 2, scaled<double>(0.5));
|
||||
|
||||
for (ExPolygon &ex_poly : ex_poly_result) {
|
||||
BoundingBox bbox(get_extents(ex_poly));
|
||||
bbox.offset(SCALED_EPSILON);
|
||||
|
||||
// Filter out expolygons smaller than 0.1mm^2
|
||||
if (Vec2d bbox_size = bbox.size().cast<double>(); bbox_size.x() * bbox_size.y() < Slic3r::sqr(scale_(0.1f)))
|
||||
continue;
|
||||
|
||||
for (const double &min_contour_width : min_contour_width_values) {
|
||||
const size_t min_contour_width_idx = &min_contour_width - &min_contour_width_values.front();
|
||||
const double search_radius = 2. * (offset + min_contour_width);
|
||||
|
||||
EdgeGrid::Grid grid;
|
||||
grid.set_bbox(bbox);
|
||||
grid.create(ex_poly, coord_t(0.7 * search_radius));
|
||||
|
@ -979,8 +1024,14 @@ static ExPolygons inner_offset(const ExPolygons &ex_polygons, double offset)
|
|||
|
||||
ExPolygons offset_ex_poly = variable_offset_inner_ex(ex_poly, offsets);
|
||||
// If variable_offset_inner_ex produces empty result, then original ex_polygon is used
|
||||
if (offset_ex_poly.size() == 1) {
|
||||
if (offset_ex_poly.size() == 1 && offset_ex_poly.front().holes.size() == ex_poly.holes.size()) {
|
||||
ex_poly = std::move(offset_ex_poly.front());
|
||||
break;
|
||||
} else if ((min_contour_width_idx + 1) < min_contour_width_values.size()) {
|
||||
continue; // Try the next round with bigger min_contour_width.
|
||||
} else if (offset_ex_poly.size() == 1) {
|
||||
ex_poly = std::move(offset_ex_poly.front());
|
||||
break;
|
||||
} else if (offset_ex_poly.size() > 1) {
|
||||
// fix_after_inner_offset called inside variable_offset_inner_ex sometimes produces
|
||||
// tiny artefacts polygons, so these artefacts are removed.
|
||||
|
@ -994,6 +1045,8 @@ static ExPolygons inner_offset(const ExPolygons &ex_polygons, double offset)
|
|||
}
|
||||
}
|
||||
ex_poly = std::move(offset_ex_poly[max_area_idx]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ex_poly_result;
|
||||
|
@ -1133,10 +1186,8 @@ Polyline AvoidCrossingPerimeters::travel_to(const GCode &gcodegen, const Point &
|
|||
Vec2d startf = start.cast<double>();
|
||||
Vec2d endf = end .cast<double>();
|
||||
|
||||
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)))) {
|
||||
bool is_support_layer = dynamic_cast<const SupportLayer *>(gcodegen.layer()) != nullptr;
|
||||
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)))) {
|
||||
// Initialize m_internal only when it is necessary.
|
||||
if (m_internal.boundaries.empty())
|
||||
init_boundary(&m_internal, to_polygons(get_boundary(*gcodegen.layer())));
|
||||
|
@ -1186,7 +1237,7 @@ Polyline AvoidCrossingPerimeters::travel_to(const GCode &gcodegen, const Point &
|
|||
} else if (max_detour_length_exceeded) {
|
||||
*could_be_wipe_disabled = false;
|
||||
} 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;
|
||||
}
|
||||
|
@ -1197,13 +1248,21 @@ void AvoidCrossingPerimeters::init_layer(const Layer &layer)
|
|||
{
|
||||
m_internal.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));
|
||||
bbox_slice.offset(SCALED_EPSILON);
|
||||
|
||||
m_grid_lslice.set_bbox(bbox_slice);
|
||||
//FIXME 1mm grid?
|
||||
m_grid_lslice.create(layer.lslices, coord_t(scale_(1.)));
|
||||
m_grid_lslices_offset.set_bbox(bbox_slice);
|
||||
m_grid_lslices_offset.create(m_lslices_offset, coord_t(scale_(1.)));
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
///|/ Copyright (c) Prusa Research 2020 - 2022 Lukáš Hejl @hejllukas, Vojtěch Bubník @bubnikv
|
||||
///|/
|
||||
///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher
|
||||
///|/
|
||||
#ifndef slic3r_AvoidCrossingPerimeters_hpp_
|
||||
#define slic3r_AvoidCrossingPerimeters_hpp_
|
||||
|
||||
|
@ -58,8 +62,11 @@ private:
|
|||
// we enable it by default for the first travel move in print
|
||||
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.
|
||||
EdgeGrid::Grid m_grid_lslice;
|
||||
EdgeGrid::Grid m_grid_lslices_offset;
|
||||
// Store all needed data for travels inside object
|
||||
Boundary m_internal;
|
||||
// Store all needed data for travels outside object
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue