Add heuristics for removing unnecessary detours
This commit is contained in:
parent
9936b8e34e
commit
c702b3b71d
@ -9,6 +9,7 @@
|
||||
#include "../Polygon.hpp"
|
||||
#include "../ExPolygon.hpp"
|
||||
#include "../ClipperUtils.hpp"
|
||||
#include "../SVG.hpp"
|
||||
#include "AvoidCrossingPerimeters.hpp"
|
||||
|
||||
#include <memory>
|
||||
@ -273,6 +274,23 @@ static std::pair<Polygons, Polygons> split_expolygon(const ExPolygons &ex_polygo
|
||||
return std::make_pair(std::move(contours), std::move(holes));
|
||||
}
|
||||
|
||||
static Polyline to_polyline(const std::vector<AvoidCrossingPerimeters2::TravelPoint> &travel)
|
||||
{
|
||||
Polyline result;
|
||||
result.points.reserve(travel.size());
|
||||
for (const AvoidCrossingPerimeters2::TravelPoint &t_point : travel)
|
||||
result.append(t_point.point);
|
||||
return result;
|
||||
}
|
||||
|
||||
static double travel_length(const std::vector<AvoidCrossingPerimeters2::TravelPoint> &travel) {
|
||||
double total_length = 0;
|
||||
for (size_t idx = 1; idx < travel.size(); ++idx)
|
||||
total_length += (travel[idx].point - travel[idx - 1].point).cast<double>().norm();
|
||||
|
||||
return total_length;
|
||||
}
|
||||
|
||||
#ifdef AVOID_CROSSING_PERIMETERS_DEBUG_OUTPUT
|
||||
static void export_travel_to_svg(const Polygons &boundary,
|
||||
const Line &original_travel,
|
||||
@ -291,6 +309,15 @@ static void export_travel_to_svg(const Polygons
|
||||
for (const AvoidCrossingPerimeters2::Intersection &intersection : intersections)
|
||||
svg.draw(intersection.point, "lightseagreen");
|
||||
}
|
||||
|
||||
static void export_travel_to_svg(const Polygons &boundary,
|
||||
const Line &original_travel,
|
||||
const std::vector<AvoidCrossingPerimeters2::TravelPoint> &result_travel,
|
||||
const std::vector<AvoidCrossingPerimeters2::Intersection> &intersections,
|
||||
const std::string &path)
|
||||
{
|
||||
export_travel_to_svg(boundary, original_travel, to_polyline(result_travel), intersections, path);
|
||||
}
|
||||
#endif /* AVOID_CROSSING_PERIMETERS_DEBUG_OUTPUT */
|
||||
|
||||
ExPolygons AvoidCrossingPerimeters2::get_boundary(const Layer &layer)
|
||||
@ -420,7 +447,10 @@ AvoidCrossingPerimeters2::Direction AvoidCrossingPerimeters2::get_shortest_direc
|
||||
return (total_length_forward < total_length_backward) ? Direction::Forward : Direction::Backward;
|
||||
}
|
||||
|
||||
Polyline AvoidCrossingPerimeters2::simplify_travel(const EdgeGrid::Grid &edge_grid, const Polyline &travel)
|
||||
std::vector<AvoidCrossingPerimeters2::TravelPoint> AvoidCrossingPerimeters2::simplify_travel(const EdgeGrid::Grid &edge_grid,
|
||||
const std::vector<TravelPoint> &travel,
|
||||
const Polygons &boundaries,
|
||||
const bool use_heuristics)
|
||||
{
|
||||
struct Visitor
|
||||
{
|
||||
@ -451,44 +481,131 @@ Polyline AvoidCrossingPerimeters2::simplify_travel(const EdgeGrid::Grid &edge_gr
|
||||
bool intersect = false;
|
||||
} visitor(edge_grid);
|
||||
|
||||
Polyline simplified_path;
|
||||
simplified_path.points.reserve(travel.points.size());
|
||||
simplified_path.points.emplace_back(travel.points.front());
|
||||
std::vector<TravelPoint> simplified_path;
|
||||
simplified_path.reserve(travel.size());
|
||||
simplified_path.emplace_back(travel.front());
|
||||
|
||||
// Try to skip some points in the path.
|
||||
for (size_t point_idx = 1; point_idx < travel.size(); ++point_idx) {
|
||||
const Point ¤t_point = travel.points[point_idx - 1];
|
||||
Point next = travel.points[point_idx];
|
||||
const Point ¤t_point = travel[point_idx - 1].point;
|
||||
TravelPoint next = travel[point_idx];
|
||||
|
||||
visitor.pt_current = ¤t_point;
|
||||
|
||||
for (size_t point_idx_2 = point_idx + 1; point_idx_2 < travel.size(); ++point_idx_2) {
|
||||
if (travel.points[point_idx_2] == current_point) {
|
||||
next = travel.points[point_idx_2];
|
||||
if (travel[point_idx_2].point == current_point) {
|
||||
next = travel[point_idx_2];
|
||||
point_idx = point_idx_2;
|
||||
continue;
|
||||
}
|
||||
|
||||
visitor.pt_next = &travel.points[point_idx_2];
|
||||
visitor.pt_next = &travel[point_idx_2].point;
|
||||
edge_grid.visit_cells_intersecting_line(*visitor.pt_current, *visitor.pt_next, visitor);
|
||||
// Check if deleting point causes crossing a boundary
|
||||
if (!visitor.intersect) {
|
||||
next = travel.points[point_idx_2];
|
||||
next = travel[point_idx_2];
|
||||
point_idx = point_idx_2;
|
||||
}
|
||||
}
|
||||
|
||||
simplified_path.append(next);
|
||||
simplified_path.emplace_back(next);
|
||||
}
|
||||
|
||||
if(use_heuristics) {
|
||||
simplified_path = simplify_travel_heuristics(edge_grid, simplified_path, boundaries);
|
||||
std::reverse(simplified_path.begin(),simplified_path.end());
|
||||
simplified_path = simplify_travel_heuristics(edge_grid, simplified_path, boundaries);
|
||||
std::reverse(simplified_path.begin(),simplified_path.end());
|
||||
}
|
||||
|
||||
return simplified_path;
|
||||
}
|
||||
|
||||
size_t AvoidCrossingPerimeters2::avoid_perimeters(const Polygons &boundaries,
|
||||
const EdgeGrid::Grid &edge_grid,
|
||||
const Point &start,
|
||||
const Point &end,
|
||||
Polyline *result_out)
|
||||
std::vector<AvoidCrossingPerimeters2::TravelPoint> AvoidCrossingPerimeters2::simplify_travel_heuristics(const EdgeGrid::Grid &edge_grid,
|
||||
const std::vector<TravelPoint> &travel,
|
||||
const Polygons &boundaries)
|
||||
{
|
||||
std::vector<TravelPoint> simplified_path;
|
||||
std::vector<Intersection> intersections;
|
||||
AllIntersectionsVisitor visitor(edge_grid, intersections);
|
||||
simplified_path.reserve(travel.size());
|
||||
simplified_path.emplace_back(travel.front());
|
||||
for (size_t point_idx = 1; point_idx < travel.size(); ++point_idx) {
|
||||
// Skip all indexes on the same polygon
|
||||
while (point_idx < travel.size() && travel[point_idx - 1].border_idx == travel[point_idx].border_idx) {
|
||||
simplified_path.emplace_back(travel[point_idx]);
|
||||
point_idx++;
|
||||
}
|
||||
|
||||
if (point_idx < travel.size()) {
|
||||
const TravelPoint ¤t = travel[point_idx - 1];
|
||||
const TravelPoint &next = travel[point_idx];
|
||||
TravelPoint new_next = next;
|
||||
size_t new_point_idx = point_idx;
|
||||
double path_length = (next.point - current.point).cast<double>().norm();
|
||||
double new_path_shorter_by = 0.;
|
||||
size_t border_idx_change_count = 0;
|
||||
std::vector<TravelPoint> shortcut;
|
||||
for (size_t point_idx_2 = point_idx + 1; point_idx_2 < travel.size(); ++point_idx_2) {
|
||||
const TravelPoint &possible_new_next = travel[point_idx_2];
|
||||
if (travel[point_idx_2 - 1].border_idx != travel[point_idx_2].border_idx)
|
||||
border_idx_change_count++;
|
||||
|
||||
if (border_idx_change_count >= 2)
|
||||
break;
|
||||
|
||||
path_length += (possible_new_next.point - travel[point_idx_2 - 1].point).cast<double>().norm();
|
||||
double shortcut_length = (possible_new_next.point - current.point).cast<double>().norm();
|
||||
if ((path_length - shortcut_length) <= scale_(10.0))
|
||||
continue;
|
||||
|
||||
intersections.clear();
|
||||
visitor.reset();
|
||||
visitor.travel_line.a = current.point;
|
||||
visitor.travel_line.b = possible_new_next.point;
|
||||
visitor.transform_to_x_axis = rotation_by_direction(visitor.travel_line.vector());
|
||||
edge_grid.visit_cells_intersecting_line(visitor.travel_line.a, visitor.travel_line.b, visitor);
|
||||
if (!intersections.empty()) {
|
||||
std::sort(intersections.begin(), intersections.end());
|
||||
size_t last_border_idx_count = 0;
|
||||
for (const Intersection &intersection : intersections)
|
||||
if (intersection.border_idx == int(possible_new_next.border_idx))
|
||||
++last_border_idx_count;
|
||||
|
||||
if (last_border_idx_count > 0)
|
||||
continue;
|
||||
|
||||
std::vector<TravelPoint> possible_shortcut;
|
||||
avoid_perimeters(boundaries, edge_grid, current.point, possible_new_next.point, false, &possible_shortcut);
|
||||
double shortcut_travel = travel_length(possible_shortcut);
|
||||
if (path_length > shortcut_travel && (path_length - shortcut_travel) > new_path_shorter_by) {
|
||||
new_path_shorter_by = path_length - shortcut_travel;
|
||||
shortcut = possible_shortcut;
|
||||
new_next = possible_new_next;
|
||||
new_point_idx = point_idx_2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!shortcut.empty()) {
|
||||
assert(shortcut.size() >= 2);
|
||||
simplified_path.insert(simplified_path.end(), shortcut.begin() + 1, shortcut.end() - 1);
|
||||
point_idx = new_point_idx;
|
||||
}
|
||||
|
||||
simplified_path.emplace_back(new_next);
|
||||
}
|
||||
}
|
||||
|
||||
return simplified_path;
|
||||
}
|
||||
|
||||
size_t AvoidCrossingPerimeters2::avoid_perimeters(const Polygons &boundaries,
|
||||
const EdgeGrid::Grid &edge_grid,
|
||||
const Point &start,
|
||||
const Point &end,
|
||||
const bool use_heuristics,
|
||||
std::vector<TravelPoint> *result_out)
|
||||
{
|
||||
const Point direction = end - start;
|
||||
Matrix2d transform_to_x_axis = rotation_by_direction(direction);
|
||||
@ -499,50 +616,14 @@ size_t AvoidCrossingPerimeters2::avoid_perimeters(const Polygons &boundari
|
||||
|
||||
std::vector<Intersection> intersections;
|
||||
{
|
||||
struct Visitor
|
||||
{
|
||||
Visitor(const EdgeGrid::Grid & grid,
|
||||
std::vector<Intersection> &intersections,
|
||||
const Matrix2d & transform_to_x_axis,
|
||||
const Line & travel_line)
|
||||
: grid(grid), intersections(intersections), transform_to_x_axis(transform_to_x_axis), travel_line(travel_line)
|
||||
{}
|
||||
|
||||
bool operator()(coord_t iy, coord_t ix)
|
||||
{
|
||||
// Called with a row and colum of the grid cell, which is intersected by a line.
|
||||
auto cell_data_range = grid.cell_data_range(iy, ix);
|
||||
for (auto it_contour_and_segment = cell_data_range.first; it_contour_and_segment != cell_data_range.second;
|
||||
++it_contour_and_segment) {
|
||||
// End points of the line segment and their vector.
|
||||
auto segment = grid.segment(*it_contour_and_segment);
|
||||
|
||||
Point intersection_point;
|
||||
if (travel_line.intersection(Line(segment.first, segment.second), &intersection_point) &&
|
||||
intersection_set.find(*it_contour_and_segment) == intersection_set.end()) {
|
||||
intersections.emplace_back(it_contour_and_segment->first, it_contour_and_segment->second,
|
||||
(transform_to_x_axis * intersection_point.cast<double>()).cast<coord_t>(), intersection_point);
|
||||
intersection_set.insert(*it_contour_and_segment);
|
||||
}
|
||||
}
|
||||
// Continue traversing the grid along the edge.
|
||||
return true;
|
||||
}
|
||||
|
||||
const EdgeGrid::Grid &grid;
|
||||
std::vector<Intersection> &intersections;
|
||||
const Matrix2d &transform_to_x_axis;
|
||||
const Line &travel_line;
|
||||
std::unordered_set<std::pair<size_t, size_t>, boost::hash<std::pair<size_t, size_t>>> intersection_set;
|
||||
} visitor(edge_grid, intersections, transform_to_x_axis, travel_line_orig);
|
||||
|
||||
AllIntersectionsVisitor visitor(edge_grid, intersections, transform_to_x_axis, travel_line_orig);
|
||||
edge_grid.visit_cells_intersecting_line(start, end, visitor);
|
||||
}
|
||||
|
||||
std::sort(intersections.begin(), intersections.end());
|
||||
|
||||
Polyline result;
|
||||
result.append(start);
|
||||
std::vector<TravelPoint> result;
|
||||
result.push_back({start, -1});
|
||||
for (auto it_first = intersections.begin(); it_first != intersections.end(); ++it_first) {
|
||||
// The entry point to the boundary polygon
|
||||
const Intersection &intersection_first = *it_first;
|
||||
@ -559,7 +640,7 @@ size_t AvoidCrossingPerimeters2::avoid_perimeters(const Polygons &boundari
|
||||
// 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.append(get_middle_point_offset(boundaries[intersection_first.border_idx], left_idx, right_idx, intersection_first.point, coord_t(SCALED_EPSILON)));
|
||||
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)});
|
||||
|
||||
// Check if intersection line also exit the boundary polygon
|
||||
if (it_second_r != it_last_item) {
|
||||
@ -574,23 +655,23 @@ size_t AvoidCrossingPerimeters2::avoid_perimeters(const Polygons &boundari
|
||||
if (shortest_direction == Direction::Forward)
|
||||
for (int line_idx = int(intersection_first.line_idx); line_idx != int(intersection_second.line_idx);
|
||||
line_idx = (((line_idx + 1) < int(border_lines.size())) ? (line_idx + 1) : 0))
|
||||
result.append(get_polygon_vertex_offset(boundaries[intersection_first.border_idx],
|
||||
(line_idx + 1 == int(boundaries[intersection_first.border_idx].points.size())) ? 0 : (line_idx + 1), coord_t(SCALED_EPSILON)));
|
||||
result.push_back({get_polygon_vertex_offset(boundaries[intersection_first.border_idx],
|
||||
(line_idx + 1 == int(boundaries[intersection_first.border_idx].points.size())) ? 0 : (line_idx + 1), coord_t(SCALED_EPSILON)), int(intersection_first.border_idx)});
|
||||
else
|
||||
for (int line_idx = int(intersection_first.line_idx); line_idx != int(intersection_second.line_idx);
|
||||
line_idx = (((line_idx - 1) >= 0) ? (line_idx - 1) : (int(border_lines.size()) - 1)))
|
||||
result.append(get_polygon_vertex_offset(boundaries[intersection_second.border_idx], line_idx + 0, coord_t(SCALED_EPSILON)));
|
||||
result.push_back({get_polygon_vertex_offset(boundaries[intersection_second.border_idx], line_idx + 0, coord_t(SCALED_EPSILON)), int(intersection_first.border_idx)});
|
||||
|
||||
// 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.append(get_middle_point_offset(boundaries[intersection_second.border_idx], left_idx, right_idx, intersection_second.point, coord_t(SCALED_EPSILON)));
|
||||
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)});
|
||||
// Skip intersections in between
|
||||
it_first = it_second;
|
||||
}
|
||||
}
|
||||
|
||||
result.append(end);
|
||||
result.push_back({end, -1});
|
||||
|
||||
#ifdef AVOID_CROSSING_PERIMETERS_DEBUG_OUTPUT
|
||||
{
|
||||
@ -601,7 +682,7 @@ size_t AvoidCrossingPerimeters2::avoid_perimeters(const Polygons &boundari
|
||||
#endif /* AVOID_CROSSING_PERIMETERS_DEBUG_OUTPUT */
|
||||
|
||||
if(!intersections.empty())
|
||||
result = simplify_travel(edge_grid, result);
|
||||
result = simplify_travel(edge_grid, result, boundaries, use_heuristics);
|
||||
|
||||
#ifdef AVOID_CROSSING_PERIMETERS_DEBUG_OUTPUT
|
||||
{
|
||||
@ -611,7 +692,8 @@ size_t AvoidCrossingPerimeters2::avoid_perimeters(const Polygons &boundari
|
||||
}
|
||||
#endif /* AVOID_CROSSING_PERIMETERS_DEBUG_OUTPUT */
|
||||
|
||||
append(result_out->points, result.points);
|
||||
result_out->reserve(result_out->size() + result.size());
|
||||
result_out->insert(result_out->end(), result.begin(), result.end());
|
||||
return intersections.size();
|
||||
}
|
||||
|
||||
@ -657,34 +739,37 @@ Polyline AvoidCrossingPerimeters2::travel_to(const GCode &gcodegen, const Point
|
||||
Point scaled_origin = use_external ? Point::new_scale(gcodegen.origin()(0), gcodegen.origin()(1)) : Point(0, 0);
|
||||
Point start = gcodegen.last_pos() + scaled_origin;
|
||||
Point end = point + scaled_origin;
|
||||
Polyline result;
|
||||
Polyline result_pl;
|
||||
size_t travel_intersection_count = 0;
|
||||
if (!check_if_could_cross_perimeters(use_external ? m_bbox_external : m_bbox, start, end)) {
|
||||
result = Polyline({start, end});
|
||||
result_pl = Polyline({start, end});
|
||||
travel_intersection_count = 0;
|
||||
} else {
|
||||
std::vector<TravelPoint> result;
|
||||
auto [start_clamped, end_clamped] = clamp_endpoints_by_bounding_box(use_external ? m_bbox_external : m_bbox, start, end);
|
||||
if (use_external)
|
||||
travel_intersection_count = this->avoid_perimeters(m_boundaries_external, m_grid_external, start_clamped, end_clamped, &result);
|
||||
travel_intersection_count = this->avoid_perimeters(m_boundaries_external, m_grid_external, start_clamped, end_clamped, false, &result);
|
||||
else
|
||||
travel_intersection_count = this->avoid_perimeters(m_boundaries, m_grid, start_clamped, end_clamped, &result);
|
||||
travel_intersection_count = this->avoid_perimeters(m_boundaries, m_grid, start_clamped, end_clamped, false, &result);
|
||||
|
||||
result_pl = to_polyline(result);
|
||||
}
|
||||
|
||||
result.points.front() = start;
|
||||
result.points.back() = end;
|
||||
result_pl.points.front() = start;
|
||||
result_pl.points.back() = end;
|
||||
|
||||
Line travel(start, end);
|
||||
double max_detour_length scale_(gcodegen.config().avoid_crossing_perimeters_max_detour);
|
||||
if ((max_detour_length > 0) && ((result.length() - travel.length()) > max_detour_length)) {
|
||||
result = Polyline({start, end});
|
||||
if ((max_detour_length > 0) && ((result_pl.length() - travel.length()) > max_detour_length)) {
|
||||
result_pl = Polyline({start, end});
|
||||
}
|
||||
if (use_external) {
|
||||
result.translate(-scaled_origin);
|
||||
result_pl.translate(-scaled_origin);
|
||||
*could_be_wipe_disabled = false;
|
||||
} else
|
||||
*could_be_wipe_disabled = !need_wipe(gcodegen, travel, result, travel_intersection_count);
|
||||
*could_be_wipe_disabled = !need_wipe(gcodegen, travel, result_pl, travel_intersection_count);
|
||||
|
||||
return result;
|
||||
return result_pl;
|
||||
}
|
||||
|
||||
void AvoidCrossingPerimeters2::init_layer(const Layer &layer)
|
||||
|
@ -5,6 +5,9 @@
|
||||
#include "../ExPolygon.hpp"
|
||||
#include "../EdgeGrid.hpp"
|
||||
|
||||
#include <unordered_set>
|
||||
#include <boost/functional/hash.hpp>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
// Forward declarations.
|
||||
@ -76,6 +79,58 @@ public:
|
||||
inline bool operator<(const Intersection &other) const { return this->point_transformed.x() < other.point_transformed.x(); }
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
struct AllIntersectionsVisitor
|
||||
{
|
||||
AllIntersectionsVisitor(const EdgeGrid::Grid &grid, std::vector<AvoidCrossingPerimeters2::Intersection> &intersections)
|
||||
: grid(grid), intersections(intersections)
|
||||
{}
|
||||
|
||||
AllIntersectionsVisitor(const EdgeGrid::Grid &grid,
|
||||
std::vector<AvoidCrossingPerimeters2::Intersection> &intersections,
|
||||
const Matrix2d &transform_to_x_axis,
|
||||
const Line &travel_line)
|
||||
: grid(grid), intersections(intersections), transform_to_x_axis(transform_to_x_axis), travel_line(travel_line)
|
||||
{}
|
||||
|
||||
void reset() {
|
||||
intersection_set.clear();
|
||||
}
|
||||
|
||||
bool operator()(coord_t iy, coord_t ix)
|
||||
{
|
||||
// Called with a row and colum of the grid cell, which is intersected by a line.
|
||||
auto cell_data_range = grid.cell_data_range(iy, ix);
|
||||
for (auto it_contour_and_segment = cell_data_range.first; it_contour_and_segment != cell_data_range.second;
|
||||
++it_contour_and_segment) {
|
||||
// End points of the line segment and their vector.
|
||||
auto segment = grid.segment(*it_contour_and_segment);
|
||||
|
||||
Point intersection_point;
|
||||
if (travel_line.intersection(Line(segment.first, segment.second), &intersection_point) &&
|
||||
intersection_set.find(*it_contour_and_segment) == intersection_set.end()) {
|
||||
intersections.emplace_back(it_contour_and_segment->first, it_contour_and_segment->second,
|
||||
(transform_to_x_axis * intersection_point.cast<double>()).cast<coord_t>(), intersection_point);
|
||||
intersection_set.insert(*it_contour_and_segment);
|
||||
}
|
||||
}
|
||||
// Continue traversing the grid along the edge.
|
||||
return true;
|
||||
}
|
||||
|
||||
const EdgeGrid::Grid &grid;
|
||||
std::vector<AvoidCrossingPerimeters2::Intersection> &intersections;
|
||||
Matrix2d transform_to_x_axis;
|
||||
Line travel_line;
|
||||
std::unordered_set<std::pair<size_t, size_t>, boost::hash<std::pair<size_t, size_t>>> intersection_set;
|
||||
};
|
||||
|
||||
enum class Direction { Forward, Backward };
|
||||
|
||||
private:
|
||||
@ -86,9 +141,21 @@ private:
|
||||
static Direction get_shortest_direction(
|
||||
const Lines &lines, const size_t start_idx, const size_t end_idx, const Point &intersection_first, const Point &intersection_last);
|
||||
|
||||
static Polyline simplify_travel(const EdgeGrid::Grid &edge_grid, const Polyline &travel);
|
||||
static std::vector<AvoidCrossingPerimeters2::TravelPoint> simplify_travel(const EdgeGrid::Grid &edge_grid,
|
||||
const std::vector<TravelPoint> &travel,
|
||||
const Polygons &boundaries,
|
||||
const bool use_heuristics);
|
||||
|
||||
static size_t avoid_perimeters(const Polygons &boundaries, const EdgeGrid::Grid &grid, const Point &start, const Point &end, Polyline *result_out);
|
||||
static std::vector<AvoidCrossingPerimeters2::TravelPoint> simplify_travel_heuristics(const EdgeGrid::Grid &edge_grid,
|
||||
const std::vector<TravelPoint> &travel,
|
||||
const Polygons &boundaries);
|
||||
|
||||
static size_t avoid_perimeters(const Polygons &boundaries,
|
||||
const EdgeGrid::Grid &grid,
|
||||
const Point &start,
|
||||
const Point &end,
|
||||
const bool use_heuristics,
|
||||
std::vector<TravelPoint> *result_out);
|
||||
|
||||
bool need_wipe(const GCode &gcodegen, const Line &original_travel, const Polyline &result_travel, const size_t intersection_count);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user