Connect infill with perimeters using hooks

This commit is contained in:
Lukáš Hejl 2020-10-02 11:15:55 +02:00
parent 1a8a5984ad
commit 7a9aec2b0b
3 changed files with 125 additions and 4 deletions

View file

@ -843,7 +843,7 @@ void Filler::_fill_surface_single(
if (params.dont_connect || all_polylines_with_hooks.size() <= 1) if (params.dont_connect || all_polylines_with_hooks.size() <= 1)
append(polylines_out, std::move(all_polylines_with_hooks)); append(polylines_out, std::move(all_polylines_with_hooks));
else else
connect_infill(chain_polylines(std::move(all_polylines_with_hooks)), expolygon, polylines_out, this->spacing, params); connect_infill(chain_polylines(std::move(all_polylines_with_hooks)), expolygon, polylines_out, this->spacing, params, int(scale_(2.)));
#ifdef ADAPTIVE_CUBIC_INFILL_DEBUG_OUTPUT #ifdef ADAPTIVE_CUBIC_INFILL_DEBUG_OUTPUT
{ {

View file

@ -833,7 +833,67 @@ 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 &params) static double compute_distance_to_consumed_point(const std::vector<Points> & boundary,
const std::vector<std::vector<ContourPointData>> &boundary_data,
size_t contour_idx,
size_t point_index,
bool forward)
{
Point predecessor = boundary[contour_idx][point_index];
double total_distance = 0;
do {
if (forward)
point_index = (point_index == (boundary[contour_idx].size() - 1)) ? 0 : (point_index + 1);
else
point_index = (point_index > 0) ? (point_index - 1) : (boundary[contour_idx].size() - 1);
Point successor = boundary[contour_idx][point_index];
total_distance += (successor - predecessor).cast<double>().norm();
predecessor = successor;
} while (!boundary_data[contour_idx][point_index].point_consumed);
return total_distance;
}
static std::pair<Points, double> get_hook_path(const std::vector<Points> & boundary,
const std::vector<std::vector<ContourPointData>> &boundary_data,
size_t contour_idx,
size_t point_index,
bool forward,
int hook_length,
std::vector<Point> & not_connected)
{
double total_distance = 0;
Points points;
points.emplace_back(boundary[contour_idx][point_index]);
do {
if (forward)
point_index = (point_index == (boundary[contour_idx].size() - 1)) ? 0 : (point_index + 1);
else
point_index = (point_index > 0) ? (point_index - 1) : (boundary[contour_idx].size() - 1);
Point successor = boundary[contour_idx][point_index];
total_distance += (successor - points.back()).cast<double>().norm();
points.emplace_back(successor);
} while (!boundary_data[contour_idx][point_index].point_consumed && total_distance < hook_length &&
std::find(not_connected.begin(), not_connected.end(), points.back()) == not_connected.end());
if (total_distance > hook_length) {
Vec2d vector = (points.back() - points[points.size() - 2]).cast<double>();
double vector_length = vector.norm();
double shrink_vec_length = vector_length - (total_distance - hook_length);
points.back() = ((vector / vector_length) * shrink_vec_length).cast<coord_t>() + points[points.size() - 2];
// total_distance += (shrink_vec_length - vector_length);
}
return std::make_pair(points, total_distance);
}
void Fill::connect_infill(Polylines &&infill_ordered, const ExPolygon &boundary_src, Polylines &polylines_out, const double spacing, const FillParams &params, const int hook_length)
{ {
assert(! infill_ordered.empty()); assert(! infill_ordered.empty());
assert(! boundary_src.contour.points.empty()); assert(! boundary_src.contour.points.empty());
@ -1005,7 +1065,68 @@ void Fill::connect_infill(Polylines &&infill_ordered, const ExPolygon &boundary_
if (next_marked) if (next_marked)
contour_data[cp2next->second].point_consumed = false; contour_data[cp2next->second].point_consumed = false;
} }
polylines_out.reserve(polylines_out.size() + std::count_if(infill_ordered.begin(), infill_ordered.end(), [](const Polyline &pl) { return ! pl.empty(); }));
auto get_merged_index = [&merged_with](size_t polyline_idx) {
for (size_t last = polyline_idx;;) {
size_t lower = merged_with[last];
if (lower == last) {
merged_with[polyline_idx] = lower;
polyline_idx = lower;
break;
}
last = lower;
}
return polyline_idx;
};
if (hook_length != 0) {
std::vector<Point> not_connect_points;
for (const std::pair<size_t, size_t> &contour_point : map_infill_end_point_to_boundary)
if (contour_point.first != boundary_idx_unconnected && !boundary_data[contour_point.first][contour_point.second].point_consumed)
not_connect_points.emplace_back(boundary[contour_point.first][contour_point.second]);
for (size_t endpoint_idx = 0; endpoint_idx < map_infill_end_point_to_boundary.size(); ++endpoint_idx) {
Polyline & polyline = infill_ordered[get_merged_index(endpoint_idx / 2)];
const std::pair<size_t, size_t> &contour_point = map_infill_end_point_to_boundary[endpoint_idx];
if (contour_point.first != boundary_idx_unconnected &&
!boundary_data[contour_point.first][contour_point.second].point_consumed) {
Point boundary_point = boundary[contour_point.first][contour_point.second];
auto [points_forward, total_length_forward] = get_hook_path(boundary, boundary_data, contour_point.first,
contour_point.second, true, hook_length, not_connect_points);
auto [points_backward, total_length_backward] = get_hook_path(boundary, boundary_data, contour_point.first,
contour_point.second, false, hook_length, not_connect_points);
Points points;
if (total_length_forward < hook_length && total_length_backward < hook_length) {
continue;
} else if (total_length_forward < total_length_backward && total_length_forward >= hook_length) {
points = std::move(points_forward);
} else if (total_length_backward < total_length_forward && total_length_backward >= hook_length) {
points = std::move(points_backward);
} else if (total_length_forward > total_length_backward) {
points = std::move(points_forward);
} else {
points = std::move(points_backward);
}
if ((boundary_point - polyline.points.front()).cast<double>().squaredNorm() <= (SCALED_EPSILON * SCALED_EPSILON)) {
Points merge_points;
merge_points.reserve(polyline.points.size() + points.size() - 1);
for (auto it = points.rbegin(); it != points.rend() - 1; ++it) merge_points.emplace_back(*it);
append(merge_points, std::move(polyline.points));
polyline.points = std::move(merge_points);
} else {
for (auto it = points.begin() + 1; it != points.end(); ++it) polyline.points.emplace_back(*it);
}
}
}
}
polylines_out.reserve(polylines_out.size() + std::count_if(infill_ordered.begin(), infill_ordered.end(), [](const Polyline &pl) { return ! pl.empty(); }));
for (Polyline &pl : infill_ordered) for (Polyline &pl : infill_ordered)
if (! pl.empty()) if (! pl.empty())
polylines_out.emplace_back(std::move(pl)); polylines_out.emplace_back(std::move(pl));

View file

@ -124,7 +124,7 @@ protected:
virtual std::pair<float, Point> _infill_direction(const Surface *surface) const; virtual std::pair<float, Point> _infill_direction(const Surface *surface) const;
public: public:
static void connect_infill(Polylines &&infill_ordered, const ExPolygon &boundary, Polylines &polylines_out, double spacing, const FillParams &params); static void connect_infill(Polylines &&infill_ordered, const ExPolygon &boundary, Polylines &polylines_out, double spacing, const FillParams &params, const int hook_length = 0);
static coord_t _adjust_solid_spacing(const coord_t width, const coord_t distance); static coord_t _adjust_solid_spacing(const coord_t width, const coord_t distance);