mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-06-02 07:50:54 +08:00
Fix of the previous Adaptive Cubic infill refactoring
plus couple of fixes of the old logic.
This commit is contained in:
parent
139b58a6f2
commit
517477f0dd
@ -47,6 +47,7 @@ public:
|
|||||||
void translate(coordf_t x, coordf_t y) { assert(this->defined); PointClass v(x, y); this->min += v; this->max += v; }
|
void translate(coordf_t x, coordf_t y) { assert(this->defined); PointClass v(x, y); this->min += v; this->max += v; }
|
||||||
void translate(const Vec2d &v) { this->min += v; this->max += v; }
|
void translate(const Vec2d &v) { this->min += v; this->max += v; }
|
||||||
void offset(coordf_t delta);
|
void offset(coordf_t delta);
|
||||||
|
BoundingBoxBase<PointClass> inflated(coordf_t delta) const throw() { BoundingBoxBase<PointClass> out(*this); out.offset(delta); return out; }
|
||||||
PointClass center() const;
|
PointClass center() const;
|
||||||
bool contains(const PointClass &point) const {
|
bool contains(const PointClass &point) const {
|
||||||
return point(0) >= this->min(0) && point(0) <= this->max(0)
|
return point(0) >= this->min(0) && point(0) <= this->max(0)
|
||||||
@ -91,6 +92,7 @@ public:
|
|||||||
void translate(coordf_t x, coordf_t y, coordf_t z) { assert(this->defined); PointClass v(x, y, z); this->min += v; this->max += v; }
|
void translate(coordf_t x, coordf_t y, coordf_t z) { assert(this->defined); PointClass v(x, y, z); this->min += v; this->max += v; }
|
||||||
void translate(const Vec3d &v) { this->min += v; this->max += v; }
|
void translate(const Vec3d &v) { this->min += v; this->max += v; }
|
||||||
void offset(coordf_t delta);
|
void offset(coordf_t delta);
|
||||||
|
BoundingBoxBase<PointClass> inflated(coordf_t delta) const throw() { BoundingBoxBase<PointClass> out(*this); out.offset(delta); return out; }
|
||||||
PointClass center() const;
|
PointClass center() const;
|
||||||
coordf_t max_size() const;
|
coordf_t max_size() const;
|
||||||
|
|
||||||
@ -159,6 +161,8 @@ public:
|
|||||||
BoundingBox(const Point &pmin, const Point &pmax) : BoundingBoxBase<Point>(pmin, pmax) {}
|
BoundingBox(const Point &pmin, const Point &pmax) : BoundingBoxBase<Point>(pmin, pmax) {}
|
||||||
BoundingBox(const Points &points) : BoundingBoxBase<Point>(points) {}
|
BoundingBox(const Points &points) : BoundingBoxBase<Point>(points) {}
|
||||||
|
|
||||||
|
BoundingBox inflated(coordf_t delta) const throw() { BoundingBox out(*this); out.offset(delta); return out; }
|
||||||
|
|
||||||
friend BoundingBox get_extents_rotated(const Points &points, double angle);
|
friend BoundingBox get_extents_rotated(const Points &points, double angle);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -231,6 +231,10 @@ public:
|
|||||||
|
|
||||||
std::pair<std::vector<std::pair<size_t, size_t>>::const_iterator, std::vector<std::pair<size_t, size_t>>::const_iterator> cell_data_range(coord_t row, coord_t col) const
|
std::pair<std::vector<std::pair<size_t, size_t>>::const_iterator, std::vector<std::pair<size_t, size_t>>::const_iterator> cell_data_range(coord_t row, coord_t col) const
|
||||||
{
|
{
|
||||||
|
assert(row >= 0);
|
||||||
|
assert(row < m_rows);
|
||||||
|
assert(col >= 0);
|
||||||
|
assert(col < m_cols);
|
||||||
const EdgeGrid::Grid::Cell &cell = m_cells[row * m_cols + col];
|
const EdgeGrid::Grid::Cell &cell = m_cells[row * m_cols + col];
|
||||||
return std::make_pair(m_cell_data.begin() + cell.begin, m_cell_data.begin() + cell.end);
|
return std::make_pair(m_cell_data.begin() + cell.begin, m_cell_data.begin() + cell.end);
|
||||||
}
|
}
|
||||||
|
@ -508,7 +508,7 @@ static void generate_infill_lines_recursive(
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ADAPTIVE_CUBIC_INFILL_DEBUG_OUTPUT
|
#ifdef ADAPTIVE_CUBIC_INFILL_DEBUG_OUTPUT
|
||||||
static void export_infill_lines_to_svg(const ExPolygon &expoly, const Polylines &polylines, const std::string &path)
|
static void export_infill_lines_to_svg(const ExPolygon &expoly, const Polylines &polylines, const std::string &path, const Points &pts = Points())
|
||||||
{
|
{
|
||||||
BoundingBox bbox = get_extents(expoly);
|
BoundingBox bbox = get_extents(expoly);
|
||||||
bbox.offset(scale_(3.));
|
bbox.offset(scale_(3.));
|
||||||
@ -518,38 +518,40 @@ static void export_infill_lines_to_svg(const ExPolygon &expoly, const Polylines
|
|||||||
svg.draw_outline(expoly, "green");
|
svg.draw_outline(expoly, "green");
|
||||||
svg.draw(polylines, "red");
|
svg.draw(polylines, "red");
|
||||||
static constexpr double trim_length = scale_(0.4);
|
static constexpr double trim_length = scale_(0.4);
|
||||||
for (Polyline polyline : polylines) {
|
for (Polyline polyline : polylines)
|
||||||
Vec2d a = polyline.points.front().cast<double>();
|
if (! polyline.empty()) {
|
||||||
Vec2d d = polyline.points.back().cast<double>();
|
Vec2d a = polyline.points.front().cast<double>();
|
||||||
if (polyline.size() == 2) {
|
Vec2d d = polyline.points.back().cast<double>();
|
||||||
Vec2d v = d - a;
|
if (polyline.size() == 2) {
|
||||||
double l = v.norm();
|
Vec2d v = d - a;
|
||||||
if (l > 2. * trim_length) {
|
double l = v.norm();
|
||||||
a += v * trim_length / l;
|
if (l > 2. * trim_length) {
|
||||||
d -= v * trim_length / l;
|
a += v * trim_length / l;
|
||||||
polyline.points.front() = a.cast<coord_t>();
|
d -= v * trim_length / l;
|
||||||
polyline.points.back() = d.cast<coord_t>();
|
polyline.points.front() = a.cast<coord_t>();
|
||||||
} else
|
polyline.points.back() = d.cast<coord_t>();
|
||||||
polyline.points.clear();
|
} else
|
||||||
} else if (polyline.size() > 2) {
|
polyline.points.clear();
|
||||||
Vec2d b = polyline.points[1].cast<double>();
|
} else if (polyline.size() > 2) {
|
||||||
Vec2d c = polyline.points[polyline.points.size() - 2].cast<double>();
|
Vec2d b = polyline.points[1].cast<double>();
|
||||||
Vec2d v = b - a;
|
Vec2d c = polyline.points[polyline.points.size() - 2].cast<double>();
|
||||||
double l = v.norm();
|
Vec2d v = b - a;
|
||||||
if (l > trim_length) {
|
double l = v.norm();
|
||||||
a += v * trim_length / l;
|
if (l > trim_length) {
|
||||||
polyline.points.front() = a.cast<coord_t>();
|
a += v * trim_length / l;
|
||||||
} else
|
polyline.points.front() = a.cast<coord_t>();
|
||||||
polyline.points.erase(polyline.points.begin());
|
} else
|
||||||
v = d - c;
|
polyline.points.erase(polyline.points.begin());
|
||||||
l = v.norm();
|
v = d - c;
|
||||||
if (l > trim_length)
|
l = v.norm();
|
||||||
polyline.points.back() = (d - v * trim_length / l).cast<coord_t>();
|
if (l > trim_length)
|
||||||
else
|
polyline.points.back() = (d - v * trim_length / l).cast<coord_t>();
|
||||||
polyline.points.pop_back();
|
else
|
||||||
|
polyline.points.pop_back();
|
||||||
|
}
|
||||||
|
svg.draw(polyline, "black");
|
||||||
}
|
}
|
||||||
svg.draw(polyline, "black");
|
svg.draw(pts, "magenta");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif /* ADAPTIVE_CUBIC_INFILL_DEBUG_OUTPUT */
|
#endif /* ADAPTIVE_CUBIC_INFILL_DEBUG_OUTPUT */
|
||||||
|
|
||||||
@ -601,11 +603,11 @@ static inline Intersection *get_nearest_intersection(std::vector<std::pair<Inter
|
|||||||
|
|
||||||
// Create a line representing the anchor aka hook extrusion based on line_to_offset
|
// Create a line representing the anchor aka hook extrusion based on line_to_offset
|
||||||
// translated in the direction of the intersection line (intersection.intersect_line).
|
// translated in the direction of the intersection line (intersection.intersect_line).
|
||||||
static Line create_offset_line(const Line &line_to_offset, const Intersection &intersection, const double scaled_spacing)
|
static Line create_offset_line(const Line &line_to_offset, const Intersection &intersection, const double scaled_offset)
|
||||||
{
|
{
|
||||||
Vec2d dir = line_to_offset.vector().cast<double>().normalized();
|
Vec2d dir = line_to_offset.vector().cast<double>().normalized();
|
||||||
// 50% overlap of the extrusion lines to achieve strong bonding.
|
// 50% overlap of the extrusion lines to achieve strong bonding.
|
||||||
Vec2d offset_vector = Vec2d(- dir.y(), dir.x()) * (scaled_spacing / 2.);
|
Vec2d offset_vector = Vec2d(- dir.y(), dir.x()) * scaled_offset;
|
||||||
const Point &furthest_point = (intersection.intersect_point == intersection.intersect_line.a ? intersection.intersect_line.b : intersection.intersect_line.a);
|
const Point &furthest_point = (intersection.intersect_point == intersection.intersect_line.a ? intersection.intersect_line.b : intersection.intersect_line.a);
|
||||||
|
|
||||||
// Move inside.
|
// Move inside.
|
||||||
@ -615,9 +617,7 @@ static Line create_offset_line(const Line &line_to_offset, const Intersection &i
|
|||||||
Line offset_line = line_to_offset;
|
Line offset_line = line_to_offset;
|
||||||
offset_line.translate(offset_vector.x(), offset_vector.y());
|
offset_line.translate(offset_vector.x(), offset_vector.y());
|
||||||
// Extend the line by a small value to guarantee a collision with adjacent lines
|
// Extend the line by a small value to guarantee a collision with adjacent lines
|
||||||
offset_line.extend(coord_t(scale_(1.)));
|
offset_line.extend(coord_t(scaled_offset * 1.16)); // / cos(PI/6)
|
||||||
//FIXME scaled_spacing * tan(PI/6)
|
|
||||||
// offset_line.extend(coord_t(scaled_spacing * 0.577));
|
|
||||||
return offset_line;
|
return offset_line;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -641,12 +641,12 @@ static inline rtree_segment_t mk_rtree_seg(const Line &l) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create a hook based on hook_line and append it to the begin or end of the polyline in the intersection
|
// Create a hook based on hook_line and append it to the begin or end of the polyline in the intersection
|
||||||
static void add_hook(const Intersection &intersection, const double scaled_spacing, const int hook_length, const rtree_t &rtree)
|
static void add_hook(const Intersection &intersection, const double scaled_offset, const int hook_length, const rtree_t &rtree)
|
||||||
{
|
{
|
||||||
// Trim the hook start by the infill line it will connect to.
|
// Trim the hook start by the infill line it will connect to.
|
||||||
Point hook_start;
|
Point hook_start;
|
||||||
bool intersection_found = intersection.intersect_line.intersection(
|
bool intersection_found = intersection.intersect_line.intersection(
|
||||||
create_offset_line(intersection.closest_line, intersection, scaled_spacing),
|
create_offset_line(intersection.closest_line, intersection, scaled_offset),
|
||||||
&hook_start);
|
&hook_start);
|
||||||
assert(intersection_found);
|
assert(intersection_found);
|
||||||
|
|
||||||
@ -729,17 +729,24 @@ static Polylines connect_lines_using_hooks(Polylines &&lines, const ExPolygon &b
|
|||||||
rtree.insert(std::make_pair(mk_rtree_seg(poly.points.front(), poly.points.back()), poly_idx++));
|
rtree.insert(std::make_pair(mk_rtree_seg(poly.points.front(), poly.points.back()), poly_idx++));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const float scaled_offset = float(scale_(spacing) * 0.7); // 30% overlap
|
||||||
|
|
||||||
std::vector<Intersection> intersections;
|
std::vector<Intersection> intersections;
|
||||||
{
|
{
|
||||||
const coord_t scaled_spacing = coord_t(scale_(spacing));
|
|
||||||
// Keeping the vector of closest points outside the loop, so the vector does not need to be reallocated.
|
// Keeping the vector of closest points outside the loop, so the vector does not need to be reallocated.
|
||||||
std::vector<std::pair<rtree_segment_t, size_t>> closest;
|
std::vector<std::pair<rtree_segment_t, size_t>> closest;
|
||||||
|
// Minimum lenght of an infill line to anchor. Very short lines cannot be trimmed from both sides,
|
||||||
|
// it does not help to anchor extremely short infill lines, it consumes too much plastic while not adding
|
||||||
|
// to the object rigidity.
|
||||||
|
const double line_len_threshold = scaled_offset * 4.;
|
||||||
|
// Minimum length of an infill line to be trimmed from both sides.
|
||||||
|
assert(line_len_threshold > scaled_offset * (2. / cos(PI / 6.)) + SCALED_EPSILON);
|
||||||
for (size_t line_idx = 0; line_idx < lines.size(); ++line_idx) {
|
for (size_t line_idx = 0; line_idx < lines.size(); ++line_idx) {
|
||||||
Polyline &line = lines[line_idx];
|
Polyline &line = lines[line_idx];
|
||||||
// Lines shorter than spacing are skipped because it is needed to shrink a line by the value of spacing.
|
// Lines shorter than spacing are skipped because it is needed to shrink a line by the value of spacing.
|
||||||
// A shorter line than spacing could produce a degenerate polyline.
|
// A shorter line than spacing could produce a degenerate polyline.
|
||||||
//FIXME we should rather remove such short infill lines earlier!
|
//FIXME we should rather remove such short infill lines earlier!
|
||||||
if (line.length() <= (scaled_spacing + SCALED_EPSILON))
|
if (line.length() < line_len_threshold)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const Point &front_point = line.points.front();
|
const Point &front_point = line.points.front();
|
||||||
@ -763,6 +770,17 @@ static Polylines connect_lines_using_hooks(Polylines &&lines, const ExPolygon &b
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ADAPTIVE_CUBIC_INFILL_DEBUG_OUTPUT
|
||||||
|
static int iRun = 0;
|
||||||
|
int iStep = 0;
|
||||||
|
{
|
||||||
|
Points pts;
|
||||||
|
for (const Intersection &i : intersections)
|
||||||
|
pts.emplace_back(i.intersect_point);
|
||||||
|
export_infill_lines_to_svg(boundary, lines, debug_out_path("FillAdaptive-Tjoints-%d.svg", iRun++), pts);
|
||||||
|
}
|
||||||
|
#endif /* ADAPTIVE_CUBIC_INFILL_DEBUG_OUTPUT */
|
||||||
|
|
||||||
std::sort(intersections.begin(), intersections.end(),
|
std::sort(intersections.begin(), intersections.end(),
|
||||||
[](const Intersection &i1, const Intersection &i2) { return i1.closest_line_idx < i2.closest_line_idx; });
|
[](const Intersection &i1, const Intersection &i2) { return i1.closest_line_idx < i2.closest_line_idx; });
|
||||||
|
|
||||||
@ -800,8 +818,11 @@ static Polylines connect_lines_using_hooks(Polylines &&lines, const ExPolygon &b
|
|||||||
|
|
||||||
intersection.intersect_pl = &lines[intersect_pl_idx];
|
intersection.intersect_pl = &lines[intersect_pl_idx];
|
||||||
// After polylines are merged, it is necessary to update "forward" based on if intersect_point is the first or the last point of intersect_pl.
|
// After polylines are merged, it is necessary to update "forward" based on if intersect_point is the first or the last point of intersect_pl.
|
||||||
if (intersection.fresh())
|
if (intersection.fresh()) {
|
||||||
|
assert(intersection.intersect_pl->points.front() == intersection.intersect_point ||
|
||||||
|
intersection.intersect_pl->points.back() == intersection.intersect_point);
|
||||||
intersection.front = intersection.intersect_pl->points.front() == intersection.intersect_point;
|
intersection.front = intersection.intersect_pl->points.front() == intersection.intersect_point;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Keep intersect_line outside the loop, so it does not get reallocated.
|
// Keep intersect_line outside the loop, so it does not get reallocated.
|
||||||
@ -811,19 +832,25 @@ static Polylines connect_lines_using_hooks(Polylines &&lines, const ExPolygon &b
|
|||||||
intersect_line.clear();
|
intersect_line.clear();
|
||||||
// All the nearest points (T-joints) ending at the same line are projected onto this line. Because of it, it can easily find the nearest point.
|
// All the nearest points (T-joints) ending at the same line are projected onto this line. Because of it, it can easily find the nearest point.
|
||||||
{
|
{
|
||||||
const Point &p0 = intersections[min_idx].intersect_point;
|
size_t max_idx = min_idx;
|
||||||
size_t max_idx = min_idx + 1;
|
for (; max_idx < intersections.size() && intersections[min_idx].closest_line_idx == intersections[max_idx].closest_line_idx; ++ max_idx)
|
||||||
intersect_line.emplace_back(&intersections[min_idx], 0.);
|
intersect_line.emplace_back(&intersections[max_idx], line_dir.dot(intersections[max_idx].intersect_point.cast<double>()));
|
||||||
for (; max_idx < intersections.size() && intersections[min_idx].closest_line_idx == intersections[max_idx].closest_line_idx; ++max_idx)
|
|
||||||
intersect_line.emplace_back(&intersections[max_idx], line_dir.dot((intersections[max_idx].intersect_point - p0).cast<double>()));
|
|
||||||
min_idx = max_idx;
|
min_idx = max_idx;
|
||||||
}
|
}
|
||||||
if (intersect_line.size() == 1) {
|
if (intersect_line.size() == 1) {
|
||||||
// Simple case: The current intersection is the only one touching its adjacent line.
|
// Simple case: The current intersection is the only one touching its adjacent line.
|
||||||
Intersection &first_i = *intersect_line.front().first;
|
Intersection &first_i = *intersect_line.front().first;
|
||||||
|
update_merged_polyline(first_i);
|
||||||
if (first_i.fresh()) {
|
if (first_i.fresh()) {
|
||||||
// Try to connect left or right. If not enough space for hook_length, take the longer side.
|
// Try to connect left or right. If not enough space for hook_length, take the longer side.
|
||||||
add_hook(first_i, scale_(spacing), hook_length, rtree);
|
#ifdef ADAPTIVE_CUBIC_INFILL_DEBUG_OUTPUT
|
||||||
|
export_infill_lines_to_svg(boundary, lines, debug_out_path("FillAdaptive-add_hook0-pre-%d-%d.svg", iRun, iStep), { first_i.intersect_point });
|
||||||
|
#endif // ADAPTIVE_CUBIC_INFILL_DEBUG_OUTPUT
|
||||||
|
add_hook(first_i, scaled_offset, hook_length, rtree);
|
||||||
|
#ifdef ADAPTIVE_CUBIC_INFILL_DEBUG_OUTPUT
|
||||||
|
export_infill_lines_to_svg(boundary, lines, debug_out_path("FillAdaptive-add_hook0-pre-%d-%d.svg", iRun, iStep), { first_i.intersect_point });
|
||||||
|
++ iStep;
|
||||||
|
#endif // ADAPTIVE_CUBIC_INFILL_DEBUG_OUTPUT
|
||||||
first_i.used = true;
|
first_i.used = true;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
@ -832,19 +859,23 @@ static Polylines connect_lines_using_hooks(Polylines &&lines, const ExPolygon &b
|
|||||||
assert(intersect_line.size() > 1);
|
assert(intersect_line.size() > 1);
|
||||||
// Sort the intersections along line_dir.
|
// Sort the intersections along line_dir.
|
||||||
std::sort(intersect_line.begin(), intersect_line.end(), [](const auto &i1, const auto &i2) { return i1.second < i2.second; });
|
std::sort(intersect_line.begin(), intersect_line.end(), [](const auto &i1, const auto &i2) { return i1.second < i2.second; });
|
||||||
|
|
||||||
for (size_t first_idx = 0; first_idx < intersect_line.size(); ++ first_idx) {
|
for (size_t first_idx = 0; first_idx < intersect_line.size(); ++ first_idx) {
|
||||||
Intersection &first_i = *intersect_line[first_idx].first;
|
Intersection &first_i = *intersect_line[first_idx].first;
|
||||||
|
update_merged_polyline(first_i);
|
||||||
if (! first_i.fresh())
|
if (! first_i.fresh())
|
||||||
// The intersection has been processed, or the polyline has been merged to another polyline.
|
// The intersection has been processed, or the polyline has been merged to another polyline.
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Get the previous or next intersection on the same line, pick the closer one.
|
// Get the previous or next intersection on the same line, pick the closer one.
|
||||||
|
if (first_idx > 0)
|
||||||
|
update_merged_polyline(*intersect_line[first_idx - 1].first);
|
||||||
|
if (first_idx + 1 < intersect_line.size())
|
||||||
|
update_merged_polyline(*intersect_line[first_idx + 1].first);
|
||||||
Intersection &nearest_i = *get_nearest_intersection(intersect_line, first_idx);
|
Intersection &nearest_i = *get_nearest_intersection(intersect_line, first_idx);
|
||||||
update_merged_polyline(first_i);
|
|
||||||
update_merged_polyline(nearest_i);
|
|
||||||
|
|
||||||
// A line between two intersections points
|
// A line between two intersections points
|
||||||
Line offset_line = create_offset_line(Line(first_i.intersect_point, nearest_i.intersect_point), first_i, scale_(spacing));
|
Line offset_line = create_offset_line(Line(first_i.intersect_point, nearest_i.intersect_point), first_i, scaled_offset);
|
||||||
// Check if both intersections lie on the offset_line and simultaneously get their points of intersecting.
|
// Check if both intersections lie on the offset_line and simultaneously get their points of intersecting.
|
||||||
// These points are used as start and end of the hook
|
// These points are used as start and end of the hook
|
||||||
Point first_i_point, nearest_i_point;
|
Point first_i_point, nearest_i_point;
|
||||||
@ -860,9 +891,13 @@ static Polylines connect_lines_using_hooks(Polylines &&lines, const ExPolygon &b
|
|||||||
bgi::satisfies([&first_i, &nearest_i](const auto &item) { return item.second != first_i.intersect_line_idx && item.second != nearest_i.intersect_line_idx; }),
|
bgi::satisfies([&first_i, &nearest_i](const auto &item) { return item.second != first_i.intersect_line_idx && item.second != nearest_i.intersect_line_idx; }),
|
||||||
std::back_inserter(hook_intersections));
|
std::back_inserter(hook_intersections));
|
||||||
if (hook_intersections.empty()) {
|
if (hook_intersections.empty()) {
|
||||||
|
#ifdef ADAPTIVE_CUBIC_INFILL_DEBUG_OUTPUT
|
||||||
|
export_infill_lines_to_svg(boundary, lines, debug_out_path("FillAdaptive-connecting-pre-%d-%d.svg", iRun, iStep), { first_i.intersect_point, nearest_i.intersect_point });
|
||||||
|
#endif // ADAPTIVE_CUBIC_INFILL_DEBUG_OUTPUT
|
||||||
// No other infill line intersects this anchor line. Extrude it as a whole.
|
// No other infill line intersects this anchor line. Extrude it as a whole.
|
||||||
if (first_i.intersect_pl == nearest_i.intersect_pl) {
|
if (first_i.intersect_pl == nearest_i.intersect_pl) {
|
||||||
// Both intersections are on the same polyline, that means a loop is being closed.
|
// Both intersections are on the same polyline, that means a loop is being closed.
|
||||||
|
assert(first_i.front != nearest_i.front);
|
||||||
if (! first_i.front)
|
if (! first_i.front)
|
||||||
std::swap(first_i_point, nearest_i_point);
|
std::swap(first_i_point, nearest_i_point);
|
||||||
first_i.intersect_pl->points.front() = first_i_point;
|
first_i.intersect_pl->points.front() = first_i_point;
|
||||||
@ -885,20 +920,33 @@ static Polylines connect_lines_using_hooks(Polylines &&lines, const ExPolygon &b
|
|||||||
// Keep the polyline at the lower index slot.
|
// Keep the polyline at the lower index slot.
|
||||||
if (first_i.intersect_pl < nearest_i.intersect_pl) {
|
if (first_i.intersect_pl < nearest_i.intersect_pl) {
|
||||||
second_points.clear();
|
second_points.clear();
|
||||||
merged_with[nearest_i.intersect_pl - lines.data()] = merged_with[first_i.intersect_pl - lines.data()];
|
merged_with[nearest_i.intersect_pl - lines.data()] = first_i.intersect_pl - lines.data();
|
||||||
} else {
|
} else {
|
||||||
second_points = std::move(first_points);
|
second_points = std::move(first_points);
|
||||||
first_points.clear();
|
first_points.clear();
|
||||||
merged_with[first_i.intersect_pl - lines.data()] = merged_with[nearest_i.intersect_pl - lines.data()];
|
merged_with[first_i.intersect_pl - lines.data()] = nearest_i.intersect_pl - lines.data();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nearest_i.used = true;
|
nearest_i.used = true;
|
||||||
connected = true;
|
connected = true;
|
||||||
|
#ifdef ADAPTIVE_CUBIC_INFILL_DEBUG_OUTPUT
|
||||||
|
export_infill_lines_to_svg(boundary, lines, debug_out_path("FillAdaptive-connecting-post-%d-%d.svg", iRun, iStep), { first_i.intersect_point, nearest_i.intersect_point });
|
||||||
|
#endif // ADAPTIVE_CUBIC_INFILL_DEBUG_OUTPUT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (! connected)
|
if (! connected) {
|
||||||
// Try to connect left or right. If not enough space for hook_length, take the longer side.
|
// Try to connect left or right. If not enough space for hook_length, take the longer side.
|
||||||
add_hook(first_i, scale_(spacing), hook_length, rtree);
|
#ifdef ADAPTIVE_CUBIC_INFILL_DEBUG_OUTPUT
|
||||||
|
export_infill_lines_to_svg(boundary, lines, debug_out_path("FillAdaptive-add_hook-pre-%d-%d.svg", iRun, iStep), { first_i.intersect_point });
|
||||||
|
#endif // ADAPTIVE_CUBIC_INFILL_DEBUG_OUTPUT
|
||||||
|
add_hook(first_i, scaled_offset, hook_length, rtree);
|
||||||
|
#ifdef ADAPTIVE_CUBIC_INFILL_DEBUG_OUTPUT
|
||||||
|
export_infill_lines_to_svg(boundary, lines, debug_out_path("FillAdaptive-add_hook-pre-%d-%d.svg", iRun, iStep), { first_i.intersect_point });
|
||||||
|
#endif // ADAPTIVE_CUBIC_INFILL_DEBUG_OUTPUT
|
||||||
|
}
|
||||||
|
#ifdef ADAPTIVE_CUBIC_INFILL_DEBUG_OUTPUT
|
||||||
|
++iStep;
|
||||||
|
#endif ADAPTIVE_CUBIC_INFILL_DEBUG_OUTPUT
|
||||||
first_i.used = true;
|
first_i.used = true;
|
||||||
} else {
|
} else {
|
||||||
// The first & last point should always be found.
|
// The first & last point should always be found.
|
||||||
|
@ -1056,7 +1056,8 @@ void mark_boundary_segments_touching_infill(
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
EdgeGrid::Grid grid;
|
EdgeGrid::Grid grid;
|
||||||
grid.set_bbox(boundary_bbox);
|
// Make sure that the the grid is big enough for queries against the thick segment.
|
||||||
|
grid.set_bbox(boundary_bbox.inflated(distance_colliding + SCALED_EPSILON));
|
||||||
// Inflate the bounding box by a thick line width.
|
// Inflate the bounding box by a thick line width.
|
||||||
grid.create(boundary, std::max(clip_distance, distance_colliding) + scale_(10.));
|
grid.create(boundary, std::max(clip_distance, distance_colliding) + scale_(10.));
|
||||||
|
|
||||||
@ -1213,15 +1214,12 @@ void mark_boundary_segments_touching_infill(
|
|||||||
void Fill::connect_infill(Polylines &&infill_ordered, const ExPolygon &boundary_src, Polylines &polylines_out, const double spacing, const FillParams ¶ms, const int hook_length)
|
void Fill::connect_infill(Polylines &&infill_ordered, const ExPolygon &boundary_src, Polylines &polylines_out, const double spacing, const FillParams ¶ms, const int hook_length)
|
||||||
{
|
{
|
||||||
assert(! boundary_src.contour.points.empty());
|
assert(! boundary_src.contour.points.empty());
|
||||||
BoundingBox bbox = get_extents(boundary_src.contour);
|
|
||||||
bbox.offset(SCALED_EPSILON);
|
|
||||||
|
|
||||||
auto polygons_src = reserve_vector<const Polygon*>(boundary_src.holes.size() + 1);
|
auto polygons_src = reserve_vector<const Polygon*>(boundary_src.holes.size() + 1);
|
||||||
polygons_src.emplace_back(&boundary_src.contour);
|
polygons_src.emplace_back(&boundary_src.contour);
|
||||||
for (const Polygon &polygon : boundary_src.holes)
|
for (const Polygon &polygon : boundary_src.holes)
|
||||||
polygons_src.emplace_back(&polygon);
|
polygons_src.emplace_back(&polygon);
|
||||||
|
|
||||||
connect_infill(std::move(infill_ordered), polygons_src, bbox, polylines_out, spacing, params, hook_length);
|
connect_infill(std::move(infill_ordered), polygons_src, get_extents(boundary_src.contour), polylines_out, spacing, params, hook_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Fill::connect_infill(Polylines &&infill_ordered, const Polygons &boundary_src, const BoundingBox &bbox, Polylines &polylines_out, const double spacing, const FillParams ¶ms, const int hook_length)
|
void Fill::connect_infill(Polylines &&infill_ordered, const Polygons &boundary_src, const BoundingBox &bbox, Polylines &polylines_out, const double spacing, const FillParams ¶ms, const int hook_length)
|
||||||
@ -1255,7 +1253,7 @@ void Fill::connect_infill(Polylines &&infill_ordered, const std::vector<const Po
|
|||||||
std::vector<std::pair<EdgeGrid::Grid::ClosestPointResult, size_t>> intersection_points;
|
std::vector<std::pair<EdgeGrid::Grid::ClosestPointResult, size_t>> intersection_points;
|
||||||
{
|
{
|
||||||
EdgeGrid::Grid grid;
|
EdgeGrid::Grid grid;
|
||||||
grid.set_bbox(bbox);
|
grid.set_bbox(bbox.inflated(SCALED_EPSILON));
|
||||||
grid.create(boundary_src, scale_(10.));
|
grid.create(boundary_src, scale_(10.));
|
||||||
intersection_points.reserve(infill_ordered.size() * 2);
|
intersection_points.reserve(infill_ordered.size() * 2);
|
||||||
for (const Polyline &pl : infill_ordered)
|
for (const Polyline &pl : infill_ordered)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user