Connect infill with perimeters using hooks
This commit is contained in:
parent
1a8a5984ad
commit
7a9aec2b0b
3 changed files with 125 additions and 4 deletions
|
@ -843,7 +843,7 @@ void Filler::_fill_surface_single(
|
|||
if (params.dont_connect || all_polylines_with_hooks.size() <= 1)
|
||||
append(polylines_out, std::move(all_polylines_with_hooks));
|
||||
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
|
||||
{
|
||||
|
|
|
@ -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 ¶ms)
|
||||
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 ¶ms, const int hook_length)
|
||||
{
|
||||
assert(! infill_ordered.empty());
|
||||
assert(! boundary_src.contour.points.empty());
|
||||
|
@ -1005,6 +1065,67 @@ void Fill::connect_infill(Polylines &&infill_ordered, const ExPolygon &boundary_
|
|||
if (next_marked)
|
||||
contour_data[cp2next->second].point_consumed = false;
|
||||
}
|
||||
|
||||
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)
|
||||
if (! pl.empty())
|
||||
|
|
|
@ -124,7 +124,7 @@ protected:
|
|||
virtual std::pair<float, Point> _infill_direction(const Surface *surface) const;
|
||||
|
||||
public:
|
||||
static void connect_infill(Polylines &&infill_ordered, const ExPolygon &boundary, Polylines &polylines_out, double spacing, const FillParams ¶ms);
|
||||
static void connect_infill(Polylines &&infill_ordered, const ExPolygon &boundary, Polylines &polylines_out, double spacing, const FillParams ¶ms, const int hook_length = 0);
|
||||
|
||||
static coord_t _adjust_solid_spacing(const coord_t width, const coord_t distance);
|
||||
|
||||
|
|
Loading…
Reference in a new issue