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, void SeamPlacer::place_seam(ExtrusionLoop& loop, const Point& last_pos, bool external_first, double nozzle_diameter,
const EdgeGrid::Grid* lower_layer_edge_grid) 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()) {
@ -345,9 +345,12 @@ void SeamPlacer::place_seam(ExtrusionLoop& loop, const Point& last_pos, bool ext
// Internal perimeter printed before the external. // Internal perimeter printed before the external.
// First get list of external seams. // First get list of external seams.
std::vector<size_t> ext_seams; std::vector<size_t> ext_seams;
size_t external_cnt = 0;
for (size_t i = 0; i < m_plan.size(); ++i) { 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); ext_seams.emplace_back(i);
++external_cnt;
}
} }
if (! ext_seams.empty()) { 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. // 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)) {
if (ext_seam_idx != size_t(-1) && min_dist_sqr < limit_dist_sqr) { // 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.))));
if (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]);
double dist = (closest.cast<double>() - lines[line_idx].b.cast<double>()).norm();
// And walk along the perimeter until we make enough space for // This code does staggering of internal perimeters, turned off for now.
// seams of all perimeters beforethe external one. //
double offset = (ext_seam_idx - m_plan_idx) * scale_(seam_offset); // double dist = (closest.cast<double>() - lines[line_idx].b.cast<double>()).norm();
double last_offset = offset; //
offset -= dist; // // And walk along the perimeter until we make enough space for
const Point* a = &closest; // // seams of all perimeters beforethe external one.
const Point* b = &lines[line_idx].b; // double offset = (ext_seam_idx - m_plan_idx) * scale_(seam_offset);
while (++line_idx < int(lines.size()) && offset > 0.) { // double last_offset = offset;
last_offset = offset; // offset -= dist;
offset -= lines[line_idx].length(); // const Point* a = &closest;
a = &lines[line_idx].a; // const Point* b = &lines[line_idx].b;
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) if (m_plan_idx > 0 && m_plan[m_plan_idx - 1].precalculated)
seam = m_plan[m_plan_idx - 1].pt; 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); loop.split_at(seam, true);
if (external_first && m_plan_idx+1<m_plan.size() && ! m_plan[m_plan_idx+1].external) { if (external_first && m_plan_idx+1<m_plan.size() && ! m_plan[m_plan_idx+1].external) {
// This code does staggering of internal perimeters, turned off for now.
// Next perimeter should start near this one. // Next perimeter should start near this one.
const double dist_sqr = std::pow(double(scale_(seam_offset)), 2.); // const double dist_sqr = std::pow(double(scale_(seam_offset)), 2.);
double running_sqr = 0.; // double running_sqr = 0.;
double running_sqr_last = 0.; // double running_sqr_last = 0.;
if (!loop.paths.empty() && loop.paths.back().polyline.points.size() > 1) { // if (!loop.paths.empty() && loop.paths.back().polyline.points.size() > 1) {
const ExtrusionPath& last = loop.paths.back(); // const ExtrusionPath& last = loop.paths.back();
auto it = last.polyline.points.crbegin() + 1; // auto it = last.polyline.points.crbegin() + 1;
for (; it != last.polyline.points.crend(); ++it) { // for (; it != last.polyline.points.crend(); ++it) {
running_sqr += (it->cast<double>() - (it - 1)->cast<double>()).squaredNorm(); // running_sqr += (it->cast<double>() - (it - 1)->cast<double>()).squaredNorm();
if (running_sqr > dist_sqr) // if (running_sqr > dist_sqr)
break; // break;
running_sqr_last = running_sqr; // running_sqr_last = running_sqr;
} // }
if (running_sqr <= dist_sqr) // if (running_sqr <= dist_sqr)
it = last.polyline.points.crend() - 1; // it = last.polyline.points.crend() - 1;
// Now interpolate. // // Now interpolate.
double ratio = (std::sqrt(dist_sqr) - std::sqrt(running_sqr_last)) / (std::sqrt(running_sqr) - std::sqrt(running_sqr_last)); // 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].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[m_plan_idx + 1].precalculated = true;
} // }
} }
++m_plan_idx; ++m_plan_idx;