SeamPlacer: one more heuristic to get rid of long travels
This commit is contained in:
parent
59502e7861
commit
19eb984d72
@ -2515,7 +2515,8 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
|
|||||||
loop.split_at(last_pos, false);
|
loop.split_at(last_pos, false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
m_seam_placer.place_seam(loop, this->last_pos(), m_config.external_perimeters_first, EXTRUDER_CONFIG(nozzle_diameter));
|
m_seam_placer.place_seam(loop, this->last_pos(), m_config.external_perimeters_first,
|
||||||
|
EXTRUDER_CONFIG(nozzle_diameter), lower_layer_edge_grid ? lower_layer_edge_grid->get() : nullptr);
|
||||||
|
|
||||||
// clip the path to avoid the extruder to get exactly on the first point of the loop;
|
// clip the path to avoid the extruder to get exactly on the first point of the loop;
|
||||||
// if polyline was shorter than the clipping distance we'd get a null polyline, so
|
// if polyline was shorter than the clipping distance we'd get a null polyline, so
|
||||||
@ -2640,8 +2641,7 @@ std::string GCode::extrude_perimeters(const Print &print, const std::vector<Obje
|
|||||||
m_config.apply(print.get_print_region(®ion - &by_region.front()).config());
|
m_config.apply(print.get_print_region(®ion - &by_region.front()).config());
|
||||||
|
|
||||||
m_seam_placer.plan_perimeters(std::vector<const ExtrusionEntity*>(region.perimeters.begin(), region.perimeters.end()),
|
m_seam_placer.plan_perimeters(std::vector<const ExtrusionEntity*>(region.perimeters.begin(), region.perimeters.end()),
|
||||||
*m_layer, m_config.seam_position,
|
*m_layer, m_config.seam_position, this->last_pos(), EXTRUDER_CONFIG(nozzle_diameter),
|
||||||
m_config.external_perimeters_first, this->last_pos(), EXTRUDER_CONFIG(nozzle_diameter),
|
|
||||||
(m_layer == NULL ? nullptr : m_layer->object()),
|
(m_layer == NULL ? nullptr : m_layer->object()),
|
||||||
(lower_layer_edge_grid ? lower_layer_edge_grid.get() : nullptr));
|
(lower_layer_edge_grid ? lower_layer_edge_grid.get() : nullptr));
|
||||||
|
|
||||||
|
@ -293,7 +293,7 @@ void SeamPlacer::init(const Print& print)
|
|||||||
|
|
||||||
|
|
||||||
void SeamPlacer::plan_perimeters(const std::vector<const ExtrusionEntity*> perimeters,
|
void SeamPlacer::plan_perimeters(const std::vector<const ExtrusionEntity*> perimeters,
|
||||||
const Layer& layer, SeamPosition seam_position, bool external_first,
|
const Layer& layer, SeamPosition seam_position,
|
||||||
Point last_pos, coordf_t nozzle_dmr, const PrintObject* po,
|
Point last_pos, coordf_t nozzle_dmr, const PrintObject* po,
|
||||||
const EdgeGrid::Grid* lower_layer_edge_grid)
|
const EdgeGrid::Grid* lower_layer_edge_grid)
|
||||||
{
|
{
|
||||||
@ -315,20 +315,32 @@ void SeamPlacer::plan_perimeters(const std::vector<const ExtrusionEntity*> perim
|
|||||||
layer, seam_position, *dynamic_cast<const ExtrusionLoop*>(perimeters[i]), nozzle_dmr,
|
layer, seam_position, *dynamic_cast<const ExtrusionLoop*>(perimeters[i]), nozzle_dmr,
|
||||||
po, lower_layer_edge_grid, last_pos);
|
po, lower_layer_edge_grid, last_pos);
|
||||||
m_plan[i].external = true;
|
m_plan[i].external = true;
|
||||||
|
m_plan[i].seam_position = seam_position;
|
||||||
|
m_plan[i].layer = &layer;
|
||||||
|
m_plan[i].po = po;
|
||||||
}
|
}
|
||||||
m_plan[i].pt = last_pos;
|
m_plan[i].pt = last_pos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SeamPlacer::place_seam(ExtrusionLoop& loop, const Point& last_pos, bool external_first, double nozzle_diameter)
|
void SeamPlacer::place_seam(ExtrusionLoop& loop, const Point& last_pos, bool external_first, double nozzle_diameter,
|
||||||
|
const EdgeGrid::Grid* lower_layer_edge_grid)
|
||||||
{
|
{
|
||||||
const double seam_offset = nozzle_diameter;
|
const double seam_offset = nozzle_diameter;
|
||||||
|
|
||||||
Point seam = last_pos;
|
Point seam = last_pos;
|
||||||
if (! m_plan.empty() && m_plan_idx < m_plan.size()) {
|
if (! m_plan.empty() && m_plan_idx < m_plan.size()) {
|
||||||
if (m_plan[m_plan_idx].external)
|
if (m_plan[m_plan_idx].external) {
|
||||||
seam = m_plan[m_plan_idx].pt;
|
seam = m_plan[m_plan_idx].pt;
|
||||||
|
// One more heuristics: if the seam is too far from current nozzle position,
|
||||||
|
// try to place it again. This can happen in cases where the external perimeter
|
||||||
|
// does not belong to the preceding ones and they are ordered so they end up
|
||||||
|
// far from each other.
|
||||||
|
if ((seam.cast<double>() - last_pos.cast<double>()).squaredNorm() > std::pow(scale_(5.*nozzle_diameter), 2.))
|
||||||
|
seam = this->calculate_seam(*m_plan[m_plan_idx].layer, m_plan[m_plan_idx].seam_position, loop, nozzle_diameter,
|
||||||
|
m_plan[m_plan_idx].po, lower_layer_edge_grid, last_pos);
|
||||||
|
}
|
||||||
else if (! external_first) {
|
else if (! external_first) {
|
||||||
// Internal perimeter printed before the external.
|
// Internal perimeter printed before the external.
|
||||||
// First get list of external seams.
|
// First get list of external seams.
|
||||||
@ -342,14 +354,13 @@ void SeamPlacer::place_seam(ExtrusionLoop& loop, const Point& last_pos, bool ext
|
|||||||
// First find the line segment closest to an external seam:
|
// First find the line segment closest to an external seam:
|
||||||
int path_idx = 0;
|
int path_idx = 0;
|
||||||
int line_idx = 0;
|
int line_idx = 0;
|
||||||
size_t ext_seam_idx = -1;
|
size_t ext_seam_idx = size_t(-1);
|
||||||
double min_dist_sqr = std::numeric_limits<double>::max();
|
double min_dist_sqr = std::numeric_limits<double>::max();
|
||||||
double nozzle_diameter_sqr = std::pow(scale_(nozzle_diameter), 2.);
|
|
||||||
std::vector<Lines> lines_vect;
|
std::vector<Lines> lines_vect;
|
||||||
for (int i = 0; i < loop.paths.size(); ++i) {
|
for (int i = 0; i < int(loop.paths.size()); ++i) {
|
||||||
lines_vect.emplace_back(loop.paths[i].polyline.lines());
|
lines_vect.emplace_back(loop.paths[i].polyline.lines());
|
||||||
const Lines& lines = lines_vect.back();
|
const Lines& lines = lines_vect.back();
|
||||||
for (int j = 0; j < lines.size(); ++j) {
|
for (int j = 0; j < int(lines.size()); ++j) {
|
||||||
for (size_t k : ext_seams) {
|
for (size_t k : ext_seams) {
|
||||||
double d_sqr = lines[j].distance_to_squared(m_plan[k].pt);
|
double d_sqr = lines[j].distance_to_squared(m_plan[k].pt);
|
||||||
if (d_sqr < min_dist_sqr) {
|
if (d_sqr < min_dist_sqr) {
|
||||||
@ -364,7 +375,7 @@ void SeamPlacer::place_seam(ExtrusionLoop& loop, const Point& last_pos, bool ext
|
|||||||
|
|
||||||
// Only accept seam that is reasonably close.
|
// Only accept seam that is reasonably close.
|
||||||
double limit_dist_sqr = std::pow(double(scale_((ext_seam_idx - m_plan_idx) * nozzle_diameter * 2.)), 2.);
|
double limit_dist_sqr = std::pow(double(scale_((ext_seam_idx - m_plan_idx) * nozzle_diameter * 2.)), 2.);
|
||||||
if (ext_seam_idx != -1 && min_dist_sqr < limit_dist_sqr) {
|
if (ext_seam_idx != size_t(-1) && min_dist_sqr < limit_dist_sqr) {
|
||||||
// Now find a projection of the external seam
|
// Now find a projection of the external seam
|
||||||
const Lines& lines = lines_vect[path_idx];
|
const Lines& lines = lines_vect[path_idx];
|
||||||
Point closest = m_plan[ext_seam_idx].pt.projection_onto(lines[line_idx]);
|
Point closest = m_plan[ext_seam_idx].pt.projection_onto(lines[line_idx]);
|
||||||
@ -377,7 +388,7 @@ void SeamPlacer::place_seam(ExtrusionLoop& loop, const Point& last_pos, bool ext
|
|||||||
offset -= dist;
|
offset -= dist;
|
||||||
const Point* a = &closest;
|
const Point* a = &closest;
|
||||||
const Point* b = &lines[line_idx].b;
|
const Point* b = &lines[line_idx].b;
|
||||||
while (++line_idx < lines.size() && offset > 0.) {
|
while (++line_idx < int(lines.size()) && offset > 0.) {
|
||||||
last_offset = offset;
|
last_offset = offset;
|
||||||
offset -= lines[line_idx].length();
|
offset -= lines[line_idx].length();
|
||||||
a = &lines[line_idx].a;
|
a = &lines[line_idx].a;
|
||||||
|
@ -49,11 +49,12 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
void plan_perimeters(const std::vector<const ExtrusionEntity*> perimeters,
|
void plan_perimeters(const std::vector<const ExtrusionEntity*> perimeters,
|
||||||
const Layer& layer, SeamPosition seam_position, bool external_first,
|
const Layer& layer, SeamPosition seam_position,
|
||||||
Point last_pos, coordf_t nozzle_dmr, const PrintObject* po,
|
Point last_pos, coordf_t nozzle_dmr, const PrintObject* po,
|
||||||
const EdgeGrid::Grid* lower_layer_edge_grid);
|
const EdgeGrid::Grid* lower_layer_edge_grid);
|
||||||
|
|
||||||
void place_seam(ExtrusionLoop& loop, const Point& last_pos, bool external_first, double nozzle_diameter);
|
void place_seam(ExtrusionLoop& loop, const Point& last_pos, bool external_first, double nozzle_diameter,
|
||||||
|
const EdgeGrid::Grid* lower_layer_edge_grid);
|
||||||
|
|
||||||
|
|
||||||
using TreeType = AABBTreeIndirect::Tree<2, coord_t>;
|
using TreeType = AABBTreeIndirect::Tree<2, coord_t>;
|
||||||
@ -80,6 +81,9 @@ private:
|
|||||||
Point pt;
|
Point pt;
|
||||||
bool precalculated = false;
|
bool precalculated = false;
|
||||||
bool external = false;
|
bool external = false;
|
||||||
|
const Layer* layer = nullptr;
|
||||||
|
SeamPosition seam_position;
|
||||||
|
const PrintObject* po = nullptr;
|
||||||
};
|
};
|
||||||
std::vector<SeamPoint> m_plan;
|
std::vector<SeamPoint> m_plan;
|
||||||
size_t m_plan_idx;
|
size_t m_plan_idx;
|
||||||
|
Loading…
Reference in New Issue
Block a user