Seam fixes:

- turned off staggering
- fixed a bug in one of the heuristics (distance between indices measured instead of actual distance)
This commit is contained in:
Lukas Matena 2022-01-11 16:35:34 +01:00
parent eb1463d46a
commit 689f923aaf

View File

@ -327,7 +327,7 @@ void SeamPlacer::plan_perimeters(const std::vector<const ExtrusionEntity*> perim
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;
if (! m_plan.empty() && m_plan_idx < m_plan.size()) {
@ -339,15 +339,18 @@ void SeamPlacer::place_seam(ExtrusionLoop& loop, const Point& last_pos, bool ext
// 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);
m_plan[m_plan_idx].po, lower_layer_edge_grid, last_pos);
}
else if (! external_first) {
// Internal perimeter printed before the external.
// First get list of external seams.
std::vector<size_t> ext_seams;
size_t external_cnt = 0;
for (size_t i = 0; i < m_plan.size(); ++i) {
if (m_plan[i].external)
if (m_plan[i].external) {
ext_seams.emplace_back(i);
++external_cnt;
}
}
if (! ext_seams.empty()) {
@ -374,32 +377,41 @@ void SeamPlacer::place_seam(ExtrusionLoop& loop, const Point& last_pos, bool ext
}
// 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.);
if (ext_seam_idx != size_t(-1) && min_dist_sqr < limit_dist_sqr) {
// Now find a projection of the external seam
const Lines& lines = lines_vect[path_idx];
Point closest = m_plan[ext_seam_idx].pt.projection_onto(lines[line_idx]);
double dist = (closest.cast<double>() - lines[line_idx].b.cast<double>()).norm();
if (ext_seam_idx != size_t(-1)) {
// How many nozzle diameters is considered "close"?
const double nozzle_d_limit = 2. * (1. + m_plan.size() / external_cnt);
const double limit_dist_sqr = double(scale_(scale_((unscale(m_plan[ext_seam_idx].pt) - unscale(m_plan[m_plan_idx].pt)).squaredNorm() * std::pow(nozzle_d_limit * nozzle_diameter, 2.))));
// And walk along the perimeter until we make enough space for
// seams of all perimeters beforethe external one.
double offset = (ext_seam_idx - m_plan_idx) * scale_(seam_offset);
double last_offset = offset;
offset -= dist;
const Point* a = &closest;
const Point* b = &lines[line_idx].b;
while (++line_idx < int(lines.size()) && offset > 0.) {
last_offset = offset;
offset -= lines[line_idx].length();
a = &lines[line_idx].a;
b = &lines[line_idx].b;
if (min_dist_sqr < limit_dist_sqr) {
// Now find a projection of the external seam
const Lines& lines = lines_vect[path_idx];
Point closest = m_plan[ext_seam_idx].pt.projection_onto(lines[line_idx]);
// This code does staggering of internal perimeters, turned off for now.
//
// double dist = (closest.cast<double>() - lines[line_idx].b.cast<double>()).norm();
//
// // And walk along the perimeter until we make enough space for
// // seams of all perimeters beforethe external one.
// double offset = (ext_seam_idx - m_plan_idx) * scale_(seam_offset);
// double last_offset = offset;
// offset -= dist;
// const Point* a = &closest;
// const Point* b = &lines[line_idx].b;
// while (++line_idx < int(lines.size()) && offset > 0.) {
// last_offset = offset;
// offset -= lines[line_idx].length();
// a = &lines[line_idx].a;
// b = &lines[line_idx].b;
// }
//
// // We have walked far enough, too far maybe. Interpolate on the
// // last segment to find the end precisely.
// offset = std::min(0., offset); // In case that offset is still positive (we may have "wrapped around")
// double ratio = last_offset / (last_offset - offset);
// seam = (a->cast<double>() + ((b->cast<double>() - a->cast<double>()) * ratio)).cast<coord_t>();
seam = closest;
}
// We have walked far enough, too far maybe. Interpolate on the
// last segment to find the end precisely.
offset = std::min(0., offset); // In case that offset is still positive (we may have "wrapped around")
double ratio = last_offset / (last_offset - offset);
seam = (a->cast<double>() + ((b->cast<double>() - a->cast<double>()) * ratio)).cast<coord_t>();
}
}
}
@ -408,6 +420,7 @@ void SeamPlacer::place_seam(ExtrusionLoop& loop, const Point& last_pos, bool ext
if (m_plan_idx > 0 && m_plan[m_plan_idx - 1].precalculated)
seam = m_plan[m_plan_idx - 1].pt;
}
m_plan[m_plan_idx].pt = seam;
}
@ -417,26 +430,29 @@ void SeamPlacer::place_seam(ExtrusionLoop& loop, const Point& last_pos, bool ext
loop.split_at(seam, true);
if (external_first && m_plan_idx+1<m_plan.size() && ! m_plan[m_plan_idx+1].external) {
// Next perimeter should start near this one.
const double dist_sqr = std::pow(double(scale_(seam_offset)), 2.);
double running_sqr = 0.;
double running_sqr_last = 0.;
if (!loop.paths.empty() && loop.paths.back().polyline.points.size() > 1) {
const ExtrusionPath& last = loop.paths.back();
auto it = last.polyline.points.crbegin() + 1;
for (; it != last.polyline.points.crend(); ++it) {
running_sqr += (it->cast<double>() - (it - 1)->cast<double>()).squaredNorm();
if (running_sqr > dist_sqr)
break;
running_sqr_last = running_sqr;
}
if (running_sqr <= dist_sqr)
it = last.polyline.points.crend() - 1;
// Now interpolate.
double ratio = (std::sqrt(dist_sqr) - std::sqrt(running_sqr_last)) / (std::sqrt(running_sqr) - std::sqrt(running_sqr_last));
m_plan[m_plan_idx + 1].pt = ((it - 1)->cast<double>() + (it->cast<double>() - (it - 1)->cast<double>()) * std::min(ratio, 1.)).cast<coord_t>();
// This code does staggering of internal perimeters, turned off for now.
// Next perimeter should start near this one.
// const double dist_sqr = std::pow(double(scale_(seam_offset)), 2.);
// double running_sqr = 0.;
// double running_sqr_last = 0.;
// if (!loop.paths.empty() && loop.paths.back().polyline.points.size() > 1) {
// const ExtrusionPath& last = loop.paths.back();
// auto it = last.polyline.points.crbegin() + 1;
// for (; it != last.polyline.points.crend(); ++it) {
// running_sqr += (it->cast<double>() - (it - 1)->cast<double>()).squaredNorm();
// if (running_sqr > dist_sqr)
// break;
// running_sqr_last = running_sqr;
// }
// if (running_sqr <= dist_sqr)
// it = last.polyline.points.crend() - 1;
// // Now interpolate.
// double ratio = (std::sqrt(dist_sqr) - std::sqrt(running_sqr_last)) / (std::sqrt(running_sqr) - std::sqrt(running_sqr_last));
// m_plan[m_plan_idx + 1].pt = ((it - 1)->cast<double>() + (it->cast<double>() - (it - 1)->cast<double>()) * std::min(ratio, 1.)).cast<coord_t>();
// m_plan[m_plan_idx + 1].precalculated = true;
m_plan[m_plan_idx + 1].pt = m_plan[m_plan_idx].pt;
m_plan[m_plan_idx + 1].precalculated = true;
}
// }
}
++m_plan_idx;