Skip to content

Commit

Permalink
G2/G3 from bambu
Browse files Browse the repository at this point in the history
  • Loading branch information
supermerill committed Feb 24, 2023
2 parents 759db2d + dd43846 commit 96bc1c0
Show file tree
Hide file tree
Showing 41 changed files with 2,423 additions and 547 deletions.
4 changes: 4 additions & 0 deletions resources/ui_layout/default/printer_fff.ui
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ group:silent_mode_event:Firmware
setting:max_gcode_per_second
setting:min_length
end_line
line:G2/G3 generation
setting:arc_fitting
setting:arc_fitting_tolerance
end_line
setting:gcode_filename_illegal_char
group:Cooling fan
line:Speedup time
Expand Down
4 changes: 4 additions & 0 deletions resources/ui_layout/example/printer_fff.ui
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ group:silent_mode_event:Firmware
setting:max_gcode_per_second
setting:min_length
end_line
line:G2/G3 generation
setting:arc_fitting
setting:arc_fitting_tolerance
end_line
setting:gcode_filename_illegal_char
group:Cooling fan
line:Speedup time
Expand Down
2 changes: 1 addition & 1 deletion src/libslic3r/Arachne/WallToolPaths.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,7 @@ const std::vector<VariableWidthLines> &WallToolPaths::generate()
const double wall_add_middle_threshold = std::clamp(unscaled(this->min_bead_width) / unscaled(this->perimeter_width_x), 0.01, 0.99); // For an even nr. of lines: When to add a new middle in between the innermost two walls.

const int wall_distribution_count = this->print_object_config.wall_distribution_count.value;
const size_t max_bead_count = (inset_count < std::numeric_limits<coord_t>::max() / 2) ? 2 * inset_count : std::numeric_limits<coord_t>::max();
const size_t max_bead_count = (inset_count < size_t(std::numeric_limits<coord_t>::max() / 2)) ? 2 * inset_count : size_t(std::numeric_limits<coord_t>::max());
const auto beading_strat = BeadingStrategyFactory::makeStrategy
(
bead_spacing_0,
Expand Down
37 changes: 20 additions & 17 deletions src/libslic3r/Brim.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -817,16 +817,16 @@ void extrude_brim_from_tree(const Print& print, std::vector<std::vector<BrimLoop
//nothing
} else if (i_have_line && to_cut.children.empty()) {
ExtrusionEntitiesPtr to_add;
for (Polyline& line : to_cut.lines) {
assert(line.size() > 0);
if (line.points.back() == line.points.front()) {
for (Polyline& pline : to_cut.lines) {
assert(pline.size() > 0);
if (pline.back() == pline.front()) {
ExtrusionPath path(erSkirt, mm3_per_mm, width, height);
path.polyline.points = line.points;
path.polyline = pline;
to_add.push_back(new ExtrusionLoop(std::move(path), elrSkirt));
} else {
ExtrusionPath* extrusion_path = new ExtrusionPath(erSkirt, mm3_per_mm, width, height);
to_add.push_back(extrusion_path);
extrusion_path->polyline = line;
extrusion_path->polyline = pline;
}
}
parent->append(std::move(to_add));
Expand All @@ -853,16 +853,16 @@ void extrude_brim_from_tree(const Print& print, std::vector<std::vector<BrimLoop
print_me_first->set_can_sort_reverse(false, false);
parent->append({ print_me_first });
ExtrusionEntitiesPtr to_add;
for (Polyline& line : to_cut.lines) {
assert(line.size() > 0);
if (line.points.back() == line.points.front()) {
for (Polyline& pline : to_cut.lines) {
assert(pline.size() > 0);
if (pline.back() == pline.front()) {
ExtrusionPath path(erSkirt, mm3_per_mm, width, height);
path.polyline.points = line.points;
path.polyline = pline;
to_add.push_back(new ExtrusionLoop(std::move(path), elrSkirt));
} else {
ExtrusionPath* extrusion_path = new ExtrusionPath(erSkirt, mm3_per_mm, width, height);
to_add.push_back(extrusion_path);
extrusion_path->polyline = line;
extrusion_path->polyline = pline;
}
}
print_me_first->append(std::move(to_add));
Expand Down Expand Up @@ -1024,10 +1024,11 @@ void make_brim(const Print& print, const Flow& flow, const PrintObjectPtrs& obje
print.throw_if_canceled();

//simplify & merge
coordf_t scaled_resolution = scale_d(brim_config.get_computed_value("resolution_internal"));
//get brim resolution (lower resolution if no arc fitting)
coordf_t scaled_resolution_brim = (print.config().arc_fitting.value)? scale_d(print.config().resolution) : scale_d(print.config().resolution_internal) / 10;
ExPolygons unbrimmable_areas;
for (ExPolygon& expoly : islands)
for (ExPolygon& expoly : expoly.simplify(scaled_resolution/10))
for (ExPolygon& expoly : expoly.simplify(scaled_resolution_brim))
unbrimmable_areas.emplace_back(std::move(expoly));
islands = union_safety_offset_ex(unbrimmable_areas);
unbrimmable_areas = islands;
Expand Down Expand Up @@ -1077,7 +1078,7 @@ void make_brim(const Print& print, const Flow& flow, const PrintObjectPtrs& obje
for (ExPolygon& expoly : last_islands) {
for (ExPolygon& big_contour : offset_ex(expoly, double(scaled_spacing), jtSquare)) {
bigger_islands.push_back(big_contour);
Polygons simplifiesd_big_contour = big_contour.contour.simplify(scaled_resolution / 10);
Polygons simplifiesd_big_contour = big_contour.contour.simplify(scaled_resolution_brim);
if (simplifiesd_big_contour.size() == 1) {
bigger_islands.back().contour = simplifiesd_big_contour.front();
}
Expand Down Expand Up @@ -1210,7 +1211,8 @@ void make_brim_ears(const Print& print, const Flow& flow, const PrintObjectPtrs&

print.throw_if_canceled();

const coordf_t scaled_resolution = scale_d(brim_config.get_computed_value("resolution_internal"));
//get brim resolution (low resolution if no arc fitting)
coordf_t scaled_resolution_brim = (print.config().arc_fitting.value) ? scale_d(print.config().resolution) : scale_d(print.config().resolution_internal) / 10;
if (brim_config.brim_ears_pattern.value == InfillPattern::ipConcentric) {

//create loops (same as standard brim)
Expand All @@ -1222,7 +1224,7 @@ void make_brim_ears(const Print& print, const Flow& flow, const PrintObjectPtrs&
for (ExPolygon& expoly : islands) {
Polygon poly = expoly.contour;
poly.points.push_back(poly.points.front());
Points p = MultiPoint::_douglas_peucker(poly.points, scaled_resolution/10);
Points p = MultiPoint::_douglas_peucker(poly.points, scaled_resolution_brim);
p.pop_back();
poly.points = std::move(p);
loops.push_back(poly);
Expand Down Expand Up @@ -1368,7 +1370,8 @@ void make_brim_interior(const Print& print, const Flow& flow, const PrintObjectP
brimmable_areas = diff_ex(brimmable_areas, unbrimmable_areas, ApplySafetyOffset::Yes);

//now get all holes, use them to create loops
const coordf_t scaled_resolution = scale_d(brim_config.get_computed_value("resolution_internal"));
//get brim resolution (low resolution if no arc fitting)
coordf_t scaled_resolution_brim = (print.config().arc_fitting.value) ? scale_d(print.config().resolution) : scale_d(print.config().resolution_internal) / 10;
std::vector<std::vector<BrimLoop>> loops;
for (size_t i = 0; i < num_loops; ++i) {
print.throw_if_canceled();
Expand All @@ -1378,7 +1381,7 @@ void make_brim_interior(const Print& print, const Flow& flow, const PrintObjectP
Polygons temp = offset(poly, double(-flow.scaled_spacing()), jtSquare);
for (Polygon& poly : temp) {
poly.points.push_back(poly.points.front());
Points p = MultiPoint::_douglas_peucker(poly.points, scaled_resolution/10);
Points p = MultiPoint::_douglas_peucker(poly.points, scaled_resolution_brim);
p.pop_back();
poly.points = std::move(p);
}
Expand Down
2 changes: 2 additions & 0 deletions src/libslic3r/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@ add_library(libslic3r STATIC
GCodeWriter.hpp
Geometry.cpp
Geometry.hpp
Geometry/ArcFitter.cpp
Geometry/ArcFitter.hpp
Geometry/Bicubic.hpp
Geometry/Circle.cpp
Geometry/Circle.hpp
Expand Down
8 changes: 4 additions & 4 deletions src/libslic3r/ExPolygon.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,9 @@ inline ExPolygons to_expolygon(const Polygons &other)

inline Lines to_lines(const ExPolygon &src)
{
size_t n_lines = src.contour.points.size();
size_t n_lines = src.contour.size();
for (size_t i = 0; i < src.holes.size(); ++ i)
n_lines += src.holes[i].points.size();
n_lines += src.holes[i].size();
Lines lines;
lines.reserve(n_lines);
for (size_t i = 0; i <= src.holes.size(); ++ i) {
Expand All @@ -130,9 +130,9 @@ inline Lines to_lines(const ExPolygons &src)
{
size_t n_lines = 0;
for (ExPolygons::const_iterator it_expoly = src.begin(); it_expoly != src.end(); ++ it_expoly) {
n_lines += it_expoly->contour.points.size();
n_lines += it_expoly->contour.size();
for (size_t i = 0; i < it_expoly->holes.size(); ++ i)
n_lines += it_expoly->holes[i].points.size();
n_lines += it_expoly->holes[i].size();
}
Lines lines;
lines.reserve(n_lines);
Expand Down
94 changes: 58 additions & 36 deletions src/libslic3r/ExtrusionEntity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,22 +30,30 @@ void ExtrusionVisitorConst::use(const ExtrusionEntityCollection &collection) { d
void
ExtrusionPath::intersect_expolygons(const ExPolygonCollection &collection, ExtrusionEntityCollection* retval) const
{
this->_inflate_collection(intersection_pl(Polylines{ polyline }, collection.expolygons), retval);
this->_inflate_collection(intersection_pl(Polylines{ this->polyline.as_polyline() }, collection.expolygons), retval);
}

void ExtrusionPath::subtract_expolygons(const ExPolygonCollection &collection, ExtrusionEntityCollection* retval) const
{
this->_inflate_collection(diff_pl(Polylines{ this->polyline }, collection.expolygons), retval);
this->_inflate_collection(diff_pl(Polylines{ this->polyline.as_polyline() }, collection.expolygons), retval);
}

void ExtrusionPath::clip_end(coordf_t distance)
{
this->polyline.clip_end(distance);
}

void ExtrusionPath::simplify(coordf_t tolerance)
void ExtrusionPath::simplify(coordf_t tolerance, bool with_fitting_arc, double fitting_arc_tolerance)
{
this->polyline.simplify(tolerance);
this->polyline.simplify(tolerance, with_fitting_arc, fitting_arc_tolerance);
}

void ExtrusionPath3D::simplify(coordf_t tolerance, bool with_fitting_arc, double fitting_arc_tolerance)
{
//TODO: simplify but only for sub-path with same zheight.
//if (with_fitting_arc) {
// this->polyline.simplify(tolerance, with_fitting_arc, fitting_arc_tolerance);
//}
}

double ExtrusionPath::length() const
Expand All @@ -57,13 +65,13 @@ void ExtrusionPath::_inflate_collection(const Polylines &polylines, ExtrusionEnt
{
ExtrusionEntitiesPtr to_add;
for (const Polyline &polyline : polylines)
to_add.emplace_back(new ExtrusionPath(polyline, *this));
to_add.emplace_back(new ExtrusionPath(PolylineOrArc{ polyline }, *this));
collection->append(std::move(to_add));
}

void ExtrusionPath::polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const
{
polygons_append(out, offset(this->polyline, double(scale_(this->width/2)) + scaled_epsilon));
polygons_append(out, offset(this->polyline.as_polyline(), double(scale_(this->width/2)) + scaled_epsilon));
}

void ExtrusionPath::polygons_covered_by_spacing(Polygons &out, const float spacing_ratio, const float scaled_epsilon) const
Expand All @@ -76,7 +84,7 @@ void ExtrusionPath::polygons_covered_by_spacing(Polygons &out, const float spaci
auto flow = bridge
? Flow::bridging_flow(this->width, 0.f)
: Flow::new_from_width(this->width, 0.f, this->height, spacing_ratio);
polygons_append(out, offset(this->polyline, 0.5f * float(flow.scaled_spacing()) + scaled_epsilon));
polygons_append(out, offset(this->polyline.as_polyline(), 0.5f * float(flow.scaled_spacing()) + scaled_epsilon));
}

bool ExtrusionLoop::make_clockwise()
Expand Down Expand Up @@ -105,11 +113,19 @@ Polygon ExtrusionLoop::polygon() const
Polygon polygon;
for (const ExtrusionPath &path : this->paths) {
// for each polyline, append all points except the last one (because it coincides with the first one of the next polyline)
polygon.points.insert(polygon.points.end(), path.polyline.points.begin(), path.polyline.points.end()-1);
polygon.points.insert(polygon.points.end(), path.polyline.get_points().begin(), path.polyline.get_points().end()-1);
}
return polygon;
}

PolylineOrArc ExtrusionLoop::as_polyline() const {
PolylineOrArc polyline;
for (const ExtrusionPath& path : this->paths) {
polyline.append(path.as_polyline());
}
return polyline;
}

double ExtrusionLoop::length() const
{
double len = 0;
Expand All @@ -124,31 +140,35 @@ bool ExtrusionLoop::split_at_vertex(const Point &point, const double scaled_epsi
if (int idx = path->polyline.find_point(point, scaled_epsilon); idx != -1) {
if (this->paths.size() == 1) {
// just change the order of points
path->polyline.points.insert(path->polyline.points.end(), path->polyline.points.begin() + 1, path->polyline.points.begin() + idx + 1);
path->polyline.points.erase(path->polyline.points.begin(), path->polyline.points.begin() + idx);
PolylineOrArc p1, p2;
path->polyline.split_at_index(idx, &p1, &p2);
if (p1.is_valid() && p2.is_valid()) {
p2.append(std::move(p1));
path->polyline.swap(p2); // swap points & fitting result
}
} else {
// new paths list starts with the second half of current path
ExtrusionPaths new_paths;
PolylineOrArc p1, p2;
path->polyline.split_at_index(idx, &p1, &p2);
new_paths.reserve(this->paths.size() + 1);
{
ExtrusionPath p = *path;
p.polyline.points.erase(p.polyline.points.begin(), p.polyline.points.begin() + idx);
if (p.polyline.is_valid())
new_paths.push_back(std::move(p));
p.polyline.swap(p2);
if (p.polyline.is_valid()) new_paths.push_back(p);
}

// then we add all paths until the end of current path list
std::move(path + 1, this->paths.end(), std::back_inserter(new_paths)); // not including this path
new_paths.insert(new_paths.end(), path + 1, this->paths.end()); // not including this path

// then we add all paths since the beginning of current list up to the previous one
std::move(this->paths.begin(), path, std::back_inserter(new_paths)); // not including this path
new_paths.insert(new_paths.end(), this->paths.begin(), path); // not including this path

// finally we add the first half of current path
{
ExtrusionPath p = *path;
p.polyline.points.erase(p.polyline.points.begin() + idx + 1, p.polyline.points.end());
if (p.polyline.is_valid())
new_paths.push_back(std::move(p));
p.polyline.swap(p1);
if (p.polyline.is_valid()) new_paths.push_back(p);
}
// we can now override the old path list with the new one and stop looping
this->paths = std::move(new_paths);
Expand All @@ -168,7 +188,7 @@ ExtrusionLoop::ClosestPathPoint ExtrusionLoop::get_closest_path_and_point(const
ClosestPathPoint best_non_overhang { 0, 0 };
double min2_non_overhang = std::numeric_limits<double>::max();
for (const ExtrusionPath& path : this->paths) {
std::pair<int, Point> foot_pt_ = foot_pt(path.polyline.points, point);
std::pair<int, Point> foot_pt_ = foot_pt(path.polyline.get_points(), point);
double d2 = (foot_pt_.second - point).cast<double>().squaredNorm();
if (d2 < min2) {
out.foot_pt = foot_pt_.second;
Expand Down Expand Up @@ -200,7 +220,7 @@ void ExtrusionLoop::split_at(const Point &point, bool prefer_non_overhang, const

// Snap p to start or end of segment_idx if closer than scaled_epsilon.
{
const Point *p1 = this->paths[path_idx].polyline.points.data() + segment_idx;
const Point *p1 = this->paths[path_idx].polyline.get_points().data() + segment_idx;
const Point *p2 = p1;
++ p2;
double d2_1 = (point - *p1).cast<double>().squaredNorm();
Expand All @@ -222,12 +242,14 @@ void ExtrusionLoop::split_at(const Point &point, bool prefer_non_overhang, const
path.polyline.split_at(p, &p1.polyline, &p2.polyline);

if (this->paths.size() == 1) {
if (p2.polyline.is_valid() && p2.polyline.length() > 0) {
if (p1.polyline.is_valid() && p1.polyline.length() > 0)
p2.polyline.points.insert(p2.polyline.points.end(), p1.polyline.points.begin() + 1, p1.polyline.points.end());
this->paths.front().polyline.points = std::move(p2.polyline.points);
} else
this->paths.front().polyline.points = std::move(p1.polyline.points);
if (!p1.polyline.is_valid()) {
this->paths.front().polyline.swap(p2.polyline);
} else if (!p2.polyline.is_valid()) {
this->paths.front().polyline.swap(p1.polyline);
} else {
p2.polyline.append(std::move(p1.polyline));
this->paths.front().polyline.swap(p2.polyline);
}
} else {
// install the two paths
this->paths.erase(this->paths.begin() + path_idx);
Expand Down Expand Up @@ -267,7 +289,7 @@ bool ExtrusionLoop::has_overhang_point(const Point &point) const
if (pos != -1) {
// point belongs to this path
// we consider it overhang only if it's not an endpoint
return (is_bridge(path.role()) && pos > 0 && pos != (int)(path.polyline.points.size())-1);
return (is_bridge(path.role()) && pos > 0 && pos != (int)(path.polyline.size())-1);
}
}
return false;
Expand Down Expand Up @@ -357,20 +379,20 @@ ExtrusionRole ExtrusionEntity::string_to_role(const std::string_view role)
}
void ExtrusionPrinter::use(const ExtrusionPath &path) {
ss << "ExtrusionPath:" << (uint16_t)path.role() << "{";
for (int i = 0; i < path.polyline.points.size(); i++) {
for (int i = 0; i < path.polyline.size(); i++) {
if (i != 0) ss << ",";
double x = (mult * (path.polyline.points[i].x()));
double y = (mult * (path.polyline.points[i].y()));
double x = (mult * (path.polyline.get_points()[i].x()));
double y = (mult * (path.polyline.get_points()[i].y()));
ss << std::fixed << "{"<<(trunc?(int)x:x) << "," << (trunc ? (int)y : y) <<"}";
}
ss << "}";
}
void ExtrusionPrinter::use(const ExtrusionPath3D &path3D) {
ss << "ExtrusionPath3D:" << (uint16_t)path3D.role() << "{";
for (int i = 0; i < path3D.polyline.points.size();i++){
for (int i = 0; i < path3D.polyline.size();i++){
if (i != 0) ss << ",";
double x = (mult * (path3D.polyline.points[i].x()));
double y = (mult * (path3D.polyline.points[i].y()));
double x = (mult * (path3D.polyline.get_points()[i].x()));
double y = (mult * (path3D.polyline.get_points()[i].y()));
double z = (path3D.z_offsets.size() > i ? mult * (path3D.z_offsets[i]) : -1);
ss << std::fixed << "{" << (trunc ? (int)x : x) << "," << (trunc ? (int)y : y) << "," << (trunc ? (int)z : z) << "}";
}
Expand Down
Loading

0 comments on commit 96bc1c0

Please sign in to comment.