mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-07-31 13:42:01 +08:00
Little refactoring, make the fill modifiable
This commit is contained in:
parent
801a41a352
commit
0a7c48f5fd
@ -147,9 +147,9 @@ protected:
|
||||
|
||||
virtual float _layer_angle(size_t idx) const { return (idx & 1) ? float(M_PI/2.) : 0; }
|
||||
|
||||
virtual std::pair<float, Point> _infill_direction(const Surface *surface) const;
|
||||
|
||||
public:
|
||||
virtual std::pair<float, Point> _infill_direction(const Surface *surface) const;
|
||||
static void connect_infill(Polylines &&infill_ordered, const ExPolygon &boundary, Polylines &polylines_out, const double spacing, const FillParams ¶ms);
|
||||
static void connect_infill(Polylines &&infill_ordered, const Polygons &boundary, const BoundingBox& bbox, Polylines &polylines_out, const double spacing, const FillParams ¶ms);
|
||||
static void connect_infill(Polylines &&infill_ordered, const std::vector<const Polygon*> &boundary, const BoundingBox &bbox, Polylines &polylines_out, double spacing, const FillParams ¶ms);
|
||||
|
@ -25,10 +25,9 @@
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
ThickPolylines FillEnsuring::fill_surface_arachne(const Surface *surface, const FillParams ¶ms)
|
||||
ThickPolylines make_fill_polylines(const Fill *fill, const Surface *surface, const FillParams ¶ms, bool stop_vibrations, bool fill_gaps)
|
||||
{
|
||||
assert(params.use_arachne);
|
||||
assert(this->print_config != nullptr && this->print_object_config != nullptr && this->print_region_config != nullptr);
|
||||
assert(fill->print_config != nullptr && fill->print_object_config != nullptr && fill->print_region_config != nullptr);
|
||||
|
||||
auto rotate_thick_polylines = [](ThickPolylines &tpolylines, double cos_angle, double sin_angle) {
|
||||
for (ThickPolyline &tp : tpolylines) {
|
||||
@ -46,14 +45,13 @@ ThickPolylines FillEnsuring::fill_surface_arachne(const Surface *surface, const
|
||||
(bhigh >= alow && bhigh <= ahigh);
|
||||
};
|
||||
|
||||
const coord_t scaled_spacing = scaled<coord_t>(this->spacing);
|
||||
const coord_t scaled_spacing = scaled<coord_t>(fill->spacing);
|
||||
double distance_limit_reconnection = double(scaled_spacing);
|
||||
double squared_distance_limit_reconnection = distance_limit_reconnection * distance_limit_reconnection;
|
||||
Polygons filled_area = to_polygons(surface->expolygon);
|
||||
std::pair<float, Point> rotate_vector = this->_infill_direction(surface);
|
||||
std::pair<float, Point> rotate_vector = fill->_infill_direction(surface);
|
||||
double aligning_angle = -rotate_vector.first + PI;
|
||||
polygons_rotate(filled_area, aligning_angle);
|
||||
Polygons internal_area = shrink(filled_area, 0.5 * scaled_spacing - scale_(this->overlap));
|
||||
BoundingBox bb = get_extents(filled_area);
|
||||
|
||||
const size_t n_vlines = (bb.max.x() - bb.min.x() + scaled_spacing - 1) / scaled_spacing;
|
||||
@ -65,11 +63,18 @@ ThickPolylines FillEnsuring::fill_surface_arachne(const Surface *surface, const
|
||||
vertical_lines[i].a = Point{x, y_min};
|
||||
vertical_lines[i].b = Point{x, y_max};
|
||||
}
|
||||
vertical_lines.push_back(vertical_lines.back());
|
||||
vertical_lines.back().a = Point{coord_t(bb.min.x() + n_vlines * double(scaled_spacing) + scaled_spacing * 0.5), y_min};
|
||||
vertical_lines.back().b = Point{vertical_lines.back().a.x(), y_max};
|
||||
|
||||
auto area_walls = AABBTreeLines::LinesDistancer<Line>{
|
||||
to_lines(intersection(filled_area, opening(filled_area, 2 * scaled_spacing, 3 * scaled_spacing)))};
|
||||
AABBTreeLines::LinesDistancer<Line> area_walls;
|
||||
if (stop_vibrations) {
|
||||
area_walls = AABBTreeLines::LinesDistancer<Line>{
|
||||
to_lines(intersection(filled_area, opening(filled_area, 2 * scaled_spacing, 3 * scaled_spacing)))};
|
||||
} else {
|
||||
area_walls = AABBTreeLines::LinesDistancer<Line>{to_lines(filled_area)};
|
||||
}
|
||||
|
||||
std::vector<std::vector<Line>> polygon_sections(n_vlines);
|
||||
|
||||
for (size_t i = 0; i < n_vlines; i++) {
|
||||
@ -86,75 +91,77 @@ ThickPolylines FillEnsuring::fill_surface_arachne(const Surface *surface, const
|
||||
}
|
||||
}
|
||||
|
||||
struct Node
|
||||
{
|
||||
int section_idx;
|
||||
int line_idx;
|
||||
int skips_taken = 0;
|
||||
bool neighbours_explored = false;
|
||||
std::vector<std::pair<int,int>> neighbours{};
|
||||
};
|
||||
if (stop_vibrations) {
|
||||
struct Node
|
||||
{
|
||||
int section_idx;
|
||||
int line_idx;
|
||||
int skips_taken = 0;
|
||||
bool neighbours_explored = false;
|
||||
std::vector<std::pair<int, int>> neighbours{};
|
||||
};
|
||||
|
||||
coord_t length_filter = scale_(4);
|
||||
size_t skips_allowed = 2;
|
||||
size_t min_removal_conut = 5;
|
||||
for (int section_idx = 0; section_idx < polygon_sections.size(); section_idx++) {
|
||||
for (int line_idx = 0; line_idx < polygon_sections[section_idx].size(); line_idx++) {
|
||||
if (const Line &line = polygon_sections[section_idx][line_idx]; line.a != line.b && line.length() < length_filter) {
|
||||
std::set<std::pair<int, int>> to_remove{{section_idx, line_idx}};
|
||||
std::vector<Node> to_visit{{section_idx, line_idx}};
|
||||
coord_t length_filter = scale_(4);
|
||||
size_t skips_allowed = 2;
|
||||
size_t min_removal_conut = 5;
|
||||
for (int section_idx = 0; section_idx < polygon_sections.size(); section_idx++) {
|
||||
for (int line_idx = 0; line_idx < polygon_sections[section_idx].size(); line_idx++) {
|
||||
if (const Line &line = polygon_sections[section_idx][line_idx]; line.a != line.b && line.length() < length_filter) {
|
||||
std::set<std::pair<int, int>> to_remove{{section_idx, line_idx}};
|
||||
std::vector<Node> to_visit{{section_idx, line_idx}};
|
||||
|
||||
bool initial_touches_long_lines = false;
|
||||
if (section_idx > 0) {
|
||||
for (int prev_line_idx = 0; prev_line_idx < polygon_sections[section_idx - 1].size(); prev_line_idx++) {
|
||||
if (const Line &nl = polygon_sections[section_idx - 1][prev_line_idx];
|
||||
nl.a != nl.b && segments_overlap(line.a.y(), line.b.y(), nl.a.y(), nl.b.y())) {
|
||||
initial_touches_long_lines = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (!to_visit.empty()) {
|
||||
Node curr = to_visit.back();
|
||||
const Line &curr_l = polygon_sections[curr.section_idx][curr.line_idx];
|
||||
if (curr.neighbours_explored) {
|
||||
bool is_valid_for_removal = (curr_l.length() < length_filter) &&
|
||||
((int(to_remove.size()) - curr.skips_taken > min_removal_conut) ||
|
||||
(curr.neighbours.empty() && !initial_touches_long_lines));
|
||||
if (!is_valid_for_removal) {
|
||||
for (const auto &n : curr.neighbours) {
|
||||
if (to_remove.find(n) != to_remove.end()) {
|
||||
is_valid_for_removal = true;
|
||||
break;
|
||||
}
|
||||
bool initial_touches_long_lines = false;
|
||||
if (section_idx > 0) {
|
||||
for (int prev_line_idx = 0; prev_line_idx < polygon_sections[section_idx - 1].size(); prev_line_idx++) {
|
||||
if (const Line &nl = polygon_sections[section_idx - 1][prev_line_idx];
|
||||
nl.a != nl.b && segments_overlap(line.a.y(), line.b.y(), nl.a.y(), nl.b.y())) {
|
||||
initial_touches_long_lines = true;
|
||||
}
|
||||
}
|
||||
if (!is_valid_for_removal) {
|
||||
to_remove.erase({curr.section_idx, curr.line_idx});
|
||||
}
|
||||
to_visit.pop_back();
|
||||
} else {
|
||||
to_visit.back().neighbours_explored = true;
|
||||
int curr_index = to_visit.size() - 1;
|
||||
bool can_use_skip = curr_l.length() <= length_filter && curr.skips_taken < skips_allowed;
|
||||
if (curr.section_idx + 1 < polygon_sections.size()) {
|
||||
for (int lidx = 0; lidx < polygon_sections[curr.section_idx + 1].size(); lidx++) {
|
||||
if (const Line &nl = polygon_sections[curr.section_idx + 1][lidx];
|
||||
nl.a != nl.b && segments_overlap(curr_l.a.y(), curr_l.b.y(), nl.a.y(), nl.b.y()) &&
|
||||
(nl.length() < length_filter || can_use_skip)) {
|
||||
to_visit[curr_index].neighbours.push_back({curr.section_idx + 1, lidx});
|
||||
to_remove.insert({curr.section_idx + 1, lidx});
|
||||
Node next_node{curr.section_idx + 1, lidx, curr.skips_taken + (nl.length() >= length_filter)};
|
||||
to_visit.push_back(next_node);
|
||||
}
|
||||
|
||||
while (!to_visit.empty()) {
|
||||
Node curr = to_visit.back();
|
||||
const Line &curr_l = polygon_sections[curr.section_idx][curr.line_idx];
|
||||
if (curr.neighbours_explored) {
|
||||
bool is_valid_for_removal = (curr_l.length() < length_filter) &&
|
||||
((int(to_remove.size()) - curr.skips_taken > min_removal_conut) ||
|
||||
(curr.neighbours.empty() && !initial_touches_long_lines));
|
||||
if (!is_valid_for_removal) {
|
||||
for (const auto &n : curr.neighbours) {
|
||||
if (to_remove.find(n) != to_remove.end()) {
|
||||
is_valid_for_removal = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!is_valid_for_removal) {
|
||||
to_remove.erase({curr.section_idx, curr.line_idx});
|
||||
}
|
||||
to_visit.pop_back();
|
||||
} else {
|
||||
to_visit.back().neighbours_explored = true;
|
||||
int curr_index = to_visit.size() - 1;
|
||||
bool can_use_skip = curr_l.length() <= length_filter && curr.skips_taken < skips_allowed;
|
||||
if (curr.section_idx + 1 < polygon_sections.size()) {
|
||||
for (int lidx = 0; lidx < polygon_sections[curr.section_idx + 1].size(); lidx++) {
|
||||
if (const Line &nl = polygon_sections[curr.section_idx + 1][lidx];
|
||||
nl.a != nl.b && segments_overlap(curr_l.a.y(), curr_l.b.y(), nl.a.y(), nl.b.y()) &&
|
||||
(nl.length() < length_filter || can_use_skip)) {
|
||||
to_visit[curr_index].neighbours.push_back({curr.section_idx + 1, lidx});
|
||||
to_remove.insert({curr.section_idx + 1, lidx});
|
||||
Node next_node{curr.section_idx + 1, lidx, curr.skips_taken + (nl.length() >= length_filter)};
|
||||
to_visit.push_back(next_node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &pair : to_remove) {
|
||||
Line &l = polygon_sections[pair.first][pair.second];
|
||||
l.a = l.b;
|
||||
for (const auto &pair : to_remove) {
|
||||
Line &l = polygon_sections[pair.first][pair.second];
|
||||
l.a = l.b;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -182,9 +189,9 @@ ThickPolylines FillEnsuring::fill_surface_arachne(const Surface *surface, const
|
||||
std::unordered_set<const Line *> used_segments;
|
||||
for (TracedPoly &traced_poly : current_traced_polys) {
|
||||
auto candidates_begin = std::upper_bound(polygon_slice.begin(), polygon_slice.end(), traced_poly.lows.back(),
|
||||
[](const Point &low, const Line &seg) { return seg.b.y() > low.y(); });
|
||||
auto candidates_end = std::upper_bound(polygon_slice.begin(), polygon_slice.end(), traced_poly.highs.back(),
|
||||
[](const Point &high, const Line &seg) { return seg.a.y() > high.y(); });
|
||||
[](const Point &low, const Line &seg) { return seg.b.y() > low.y(); });
|
||||
auto candidates_end = std::upper_bound(polygon_slice.begin(), polygon_slice.end(), traced_poly.highs.back(),
|
||||
[](const Point &high, const Line &seg) { return seg.a.y() > high.y(); });
|
||||
|
||||
bool segment_added = false;
|
||||
for (auto candidate = candidates_begin; candidate != candidates_end && !segment_added; candidate++) {
|
||||
@ -247,8 +254,8 @@ ThickPolylines FillEnsuring::fill_surface_arachne(const Surface *surface, const
|
||||
|
||||
reconstructed_area = closing(reconstructed_area, float(SCALED_EPSILON), float(SCALED_EPSILON));
|
||||
ExPolygons gaps_for_additional_filling = diff_ex(filled_area, reconstructed_area);
|
||||
if (this->overlap != 0) {
|
||||
gaps_for_additional_filling = offset_ex(gaps_for_additional_filling, scaled<float>(this->overlap));
|
||||
if (fill->overlap != 0) {
|
||||
gaps_for_additional_filling = offset_ex(gaps_for_additional_filling, scaled<float>(fill->overlap));
|
||||
}
|
||||
|
||||
// BoundingBox bbox = get_extents(filled_area);
|
||||
@ -274,129 +281,132 @@ ThickPolylines FillEnsuring::fill_surface_arachne(const Surface *surface, const
|
||||
}
|
||||
}
|
||||
|
||||
for (ExPolygon &ex_poly : gaps_for_additional_filling) {
|
||||
BoundingBox ex_bb = ex_poly.contour.bounding_box();
|
||||
coord_t loops_count = (std::max(ex_bb.size().x(), ex_bb.size().y()) + scaled_spacing - 1) / scaled_spacing;
|
||||
Polygons polygons = to_polygons(ex_poly);
|
||||
Arachne::WallToolPaths wall_tool_paths(polygons, scaled_spacing, scaled_spacing, loops_count, 0, params.layer_height,
|
||||
*this->print_object_config, *this->print_config);
|
||||
if (std::vector<Arachne::VariableWidthLines> loops = wall_tool_paths.getToolPaths(); !loops.empty()) {
|
||||
std::vector<const Arachne::ExtrusionLine *> all_extrusions;
|
||||
for (Arachne::VariableWidthLines &loop : loops) {
|
||||
if (loop.empty())
|
||||
continue;
|
||||
for (const Arachne::ExtrusionLine &wall : loop)
|
||||
all_extrusions.emplace_back(&wall);
|
||||
}
|
||||
if (fill_gaps) {
|
||||
for (ExPolygon &ex_poly : gaps_for_additional_filling) {
|
||||
BoundingBox ex_bb = ex_poly.contour.bounding_box();
|
||||
coord_t loops_count = (std::max(ex_bb.size().x(), ex_bb.size().y()) + scaled_spacing - 1) / scaled_spacing;
|
||||
Polygons polygons = to_polygons(ex_poly);
|
||||
Arachne::WallToolPaths wall_tool_paths(polygons, scaled_spacing, scaled_spacing, loops_count, 0, params.layer_height,
|
||||
*fill->print_object_config, *fill->print_config);
|
||||
if (std::vector<Arachne::VariableWidthLines> loops = wall_tool_paths.getToolPaths(); !loops.empty()) {
|
||||
std::vector<const Arachne::ExtrusionLine *> all_extrusions;
|
||||
for (Arachne::VariableWidthLines &loop : loops) {
|
||||
if (loop.empty())
|
||||
continue;
|
||||
for (const Arachne::ExtrusionLine &wall : loop)
|
||||
all_extrusions.emplace_back(&wall);
|
||||
}
|
||||
|
||||
for (const Arachne::ExtrusionLine *extrusion : all_extrusions) {
|
||||
if (extrusion->junctions.size() < 2) {
|
||||
continue;
|
||||
for (const Arachne::ExtrusionLine *extrusion : all_extrusions) {
|
||||
if (extrusion->junctions.size() < 2) {
|
||||
continue;
|
||||
}
|
||||
ThickPolyline thick_polyline = Arachne::to_thick_polyline(*extrusion);
|
||||
if (extrusion->is_closed) {
|
||||
thick_polyline.start_at_index(nearest_point_index(thick_polyline.points, ex_bb.min));
|
||||
thick_polyline.clip_end(scaled_spacing * 0.5);
|
||||
}
|
||||
if (thick_polyline.is_valid() && thick_polyline.length() > 0 && thick_polyline.points.size() > 1) {
|
||||
thick_polylines.push_back(thick_polyline);
|
||||
}
|
||||
}
|
||||
ThickPolyline thick_polyline = Arachne::to_thick_polyline(*extrusion);
|
||||
if (extrusion->is_closed) {
|
||||
thick_polyline.start_at_index(nearest_point_index(thick_polyline.points, ex_bb.min));
|
||||
thick_polyline.clip_end(scaled_spacing * 0.5);
|
||||
}
|
||||
thick_polylines.push_back(thick_polyline);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// connect tiny gap fills to close colinear line
|
||||
struct EndPoint
|
||||
{
|
||||
Vec2d position;
|
||||
size_t polyline_idx;
|
||||
size_t other_end_point_idx;
|
||||
bool is_first;
|
||||
bool used = false;
|
||||
};
|
||||
std::vector<EndPoint> connection_endpoints;
|
||||
connection_endpoints.reserve(thick_polylines.size() * 2);
|
||||
for (size_t pl_idx = 0; pl_idx < thick_polylines.size(); pl_idx++) {
|
||||
size_t current_idx = connection_endpoints.size();
|
||||
connection_endpoints.push_back({thick_polylines[pl_idx].first_point().cast<double>(), pl_idx, current_idx + 1, true});
|
||||
connection_endpoints.push_back({thick_polylines[pl_idx].last_point().cast<double>(), pl_idx, current_idx, false});
|
||||
}
|
||||
std::sort(thick_polylines.begin(), thick_polylines.end(), [](const ThickPolyline &left, const ThickPolyline &right) {
|
||||
BoundingBox lbb(left.points);
|
||||
BoundingBox rbb(right.points);
|
||||
if (lbb.min.x() == rbb.min.x())
|
||||
return lbb.min.y() < rbb.min.y();
|
||||
else
|
||||
return lbb.min.x() < rbb.min.x();
|
||||
});
|
||||
|
||||
auto coord_fn = [&connection_endpoints](size_t idx, size_t dim) { return connection_endpoints[idx].position[dim]; };
|
||||
KDTreeIndirect<2, double, decltype(coord_fn)> endpoints_tree{coord_fn, connection_endpoints.size()};
|
||||
for (size_t ep_idx = 0; ep_idx < connection_endpoints.size(); ep_idx++) {
|
||||
EndPoint &ep1 = connection_endpoints[ep_idx];
|
||||
if (!ep1.used) {
|
||||
std::vector<size_t> close_endpoints = find_nearby_points(endpoints_tree, ep1.position, double(scaled_spacing));
|
||||
for (size_t close_endpoint_idx : close_endpoints) {
|
||||
EndPoint &ep2 = connection_endpoints[close_endpoint_idx];
|
||||
if (ep2.used || ep2.polyline_idx == ep1.polyline_idx) {
|
||||
continue;
|
||||
// connect tiny gap fills to close colinear line
|
||||
struct EndPoint
|
||||
{
|
||||
Vec2d position;
|
||||
size_t polyline_idx;
|
||||
size_t other_end_point_idx;
|
||||
bool is_first;
|
||||
bool used = false;
|
||||
};
|
||||
std::vector<EndPoint> connection_endpoints;
|
||||
connection_endpoints.reserve(thick_polylines.size() * 2);
|
||||
for (size_t pl_idx = 0; pl_idx < thick_polylines.size(); pl_idx++) {
|
||||
size_t current_idx = connection_endpoints.size();
|
||||
connection_endpoints.push_back({thick_polylines[pl_idx].first_point().cast<double>(), pl_idx, current_idx + 1, true});
|
||||
connection_endpoints.push_back({thick_polylines[pl_idx].last_point().cast<double>(), pl_idx, current_idx, false});
|
||||
}
|
||||
|
||||
auto coord_fn = [&connection_endpoints](size_t idx, size_t dim) { return connection_endpoints[idx].position[dim]; };
|
||||
KDTreeIndirect<2, double, decltype(coord_fn)> endpoints_tree{coord_fn, connection_endpoints.size()};
|
||||
for (size_t ep_idx = 0; ep_idx < connection_endpoints.size(); ep_idx++) {
|
||||
EndPoint &ep1 = connection_endpoints[ep_idx];
|
||||
if (!ep1.used) {
|
||||
std::vector<size_t> close_endpoints = find_nearby_points(endpoints_tree, ep1.position, double(scaled_spacing));
|
||||
for (size_t close_endpoint_idx : close_endpoints) {
|
||||
EndPoint &ep2 = connection_endpoints[close_endpoint_idx];
|
||||
if (ep2.used || ep2.polyline_idx == ep1.polyline_idx) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ThickPolyline &tp1 = thick_polylines[ep1.polyline_idx];
|
||||
ThickPolyline &tp2 = thick_polylines[ep2.polyline_idx];
|
||||
|
||||
Vec2d v1 = ep1.is_first ? (tp1.points[0] - tp1.points[1]).cast<double>() :
|
||||
(tp1.points.back() - tp1.points[tp1.points.size() - 1]).cast<double>();
|
||||
Vec2d v2 = ep2.is_first ? (tp2.points[1] - tp2.points[0]).cast<double>() :
|
||||
(tp2.points[tp2.points.size() - 1] - tp2.points.back()).cast<double>();
|
||||
|
||||
if (std::abs(Slic3r::angle(v1, v2)) > PI / 6.0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// connect ep and ep2;
|
||||
if (ep1.is_first) {
|
||||
tp1.reverse();
|
||||
ep1.is_first = false;
|
||||
connection_endpoints[ep1.other_end_point_idx].is_first = true;
|
||||
}
|
||||
|
||||
size_t new_start_idx = ep1.other_end_point_idx;
|
||||
|
||||
if (!ep2.is_first) {
|
||||
tp2.reverse();
|
||||
ep2.is_first = true;
|
||||
connection_endpoints[ep2.other_end_point_idx].is_first = false;
|
||||
}
|
||||
|
||||
size_t new_end_idx = ep2.other_end_point_idx;
|
||||
|
||||
tp1.points.insert(tp1.points.end(), tp2.points.begin(), tp2.points.end());
|
||||
tp1.width.push_back(tp1.width.back());
|
||||
tp1.width.push_back(tp2.width.front());
|
||||
tp1.width.insert(tp1.width.end(), tp2.width.begin(), tp2.width.end());
|
||||
ep1.used = true;
|
||||
ep2.used = true;
|
||||
|
||||
connection_endpoints[new_start_idx].polyline_idx = ep1.polyline_idx;
|
||||
connection_endpoints[new_end_idx].polyline_idx = ep1.polyline_idx;
|
||||
connection_endpoints[new_start_idx].other_end_point_idx = new_end_idx;
|
||||
connection_endpoints[new_end_idx].other_end_point_idx = new_start_idx;
|
||||
tp2.clear();
|
||||
break;
|
||||
}
|
||||
|
||||
ThickPolyline &tp1 = thick_polylines[ep1.polyline_idx];
|
||||
ThickPolyline &tp2 = thick_polylines[ep2.polyline_idx];
|
||||
|
||||
Vec2d v1 = ep1.is_first ? (tp1.points[0] - tp1.points[1]).cast<double>() :
|
||||
(tp1.points.back() - tp1.points[tp1.points.size() - 1]).cast<double>();
|
||||
Vec2d v2 = ep2.is_first ? (tp2.points[1] - tp2.points[0]).cast<double>() :
|
||||
(tp2.points[tp2.points.size() - 1] - tp2.points.back()).cast<double>();
|
||||
|
||||
if (std::abs(Slic3r::angle(v1, v2)) > PI / 6.0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// connect ep and ep2;
|
||||
if (ep1.is_first) {
|
||||
tp1.reverse();
|
||||
ep1.is_first = false;
|
||||
connection_endpoints[ep1.other_end_point_idx].is_first = true;
|
||||
}
|
||||
|
||||
size_t new_start_idx = ep1.other_end_point_idx;
|
||||
|
||||
if (!ep2.is_first) {
|
||||
tp2.reverse();
|
||||
ep2.is_first = true;
|
||||
connection_endpoints[ep2.other_end_point_idx].is_first = false;
|
||||
}
|
||||
|
||||
size_t new_end_idx = ep2.other_end_point_idx;
|
||||
|
||||
tp1.points.insert(tp1.points.end(), tp2.points.begin(), tp2.points.end());
|
||||
tp1.width.push_back(tp1.width.back());
|
||||
tp1.width.push_back(tp2.width.front());
|
||||
tp1.width.insert(tp1.width.end(), tp2.width.begin(), tp2.width.end());
|
||||
ep1.used = true;
|
||||
ep2.used = true;
|
||||
|
||||
connection_endpoints[new_start_idx].polyline_idx = ep1.polyline_idx;
|
||||
connection_endpoints[new_end_idx].polyline_idx = ep1.polyline_idx;
|
||||
connection_endpoints[new_start_idx].other_end_point_idx = new_end_idx;
|
||||
connection_endpoints[new_end_idx].other_end_point_idx = new_start_idx;
|
||||
tp2.clear();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
thick_polylines.erase(std::remove_if(thick_polylines.begin(), thick_polylines.end(),
|
||||
thick_polylines.erase(std::remove_if(thick_polylines.begin(), thick_polylines.end(),
|
||||
[scaled_spacing](const ThickPolyline &tp) {
|
||||
return tp.length() < scaled_spacing &&
|
||||
std::all_of(tp.width.begin(), tp.width.end(),
|
||||
[scaled_spacing](double w) { return w < scaled_spacing; });
|
||||
}),
|
||||
thick_polylines.end());
|
||||
}
|
||||
|
||||
std::sort(thick_polylines.begin(), thick_polylines.end(), [](const ThickPolyline &left, const ThickPolyline &right) {
|
||||
BoundingBox lbb(left.points);
|
||||
BoundingBox rbb(right.points);
|
||||
if (lbb.min.x() == rbb.min.x())
|
||||
return lbb.max.y() < rbb.max.y();
|
||||
else
|
||||
return lbb.max.x() < rbb.max.x();
|
||||
});
|
||||
|
||||
Algorithm::sort_paths(thick_polylines.begin(), thick_polylines.end(), bb.min, double(scaled_spacing) * 1.2, [](const ThickPolyline
|
||||
&tp) {
|
||||
Algorithm::sort_paths(thick_polylines.begin(), thick_polylines.end(), bb.min, double(scaled_spacing) * 1.2, [](const ThickPolyline &tp) {
|
||||
Lines ls;
|
||||
Point prev = tp.first_point();
|
||||
for (size_t i = 1; i < tp.points.size(); i++) {
|
||||
|
@ -6,13 +6,18 @@
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class FillEnsuring : public FillRectilinear
|
||||
ThickPolylines make_fill_polylines(const Fill *fill, const Surface *surface, const FillParams ¶ms, bool stop_vibrations, bool fill_gaps);
|
||||
|
||||
class FillEnsuring : public Fill
|
||||
{
|
||||
public:
|
||||
Fill *clone() const override { return new FillEnsuring(*this); }
|
||||
~FillEnsuring() override = default;
|
||||
Polylines fill_surface(const Surface *surface, const FillParams ¶ms) override { return {}; };
|
||||
ThickPolylines fill_surface_arachne(const Surface *surface, const FillParams ¶ms) override;
|
||||
ThickPolylines fill_surface_arachne(const Surface *surface, const FillParams ¶ms) override
|
||||
{
|
||||
return make_fill_polylines(this, surface, params, true, true);
|
||||
};
|
||||
|
||||
protected:
|
||||
void fill_surface_single_arachne(const Surface &surface, const FillParams ¶ms, ThickPolylines &thick_polylines_out);
|
||||
|
Loading…
x
Reference in New Issue
Block a user