#351 reworked brim ordering, now similar as perimeter algo.

This commit is contained in:
supermerill 2020-07-31 04:35:37 +02:00
parent 4359c2a4f8
commit 65f97a9092
3 changed files with 165 additions and 58 deletions

View File

@ -2382,9 +2382,7 @@ void GCode::process_layer(
this->set_origin(0., 0.);
m_avoid_crossing_perimeters.use_external_mp = true;
for (const ExtrusionEntity *ee : print.brim().entities) {
gcode += this->extrude_entity(*ee, "brim", m_config.support_material_speed.value);
}
gcode += this->extrude_entity(print.brim(), "brim", m_config.support_material_speed.value);
m_brim_done = true;
m_avoid_crossing_perimeters.use_external_mp = false;
// Allow a straight travel move to the first object point.
@ -3528,11 +3526,15 @@ std::string GCode::extrude_entity(const ExtrusionEntity &entity, const std::stri
}
void GCode::use(const ExtrusionEntityCollection &collection) {
ExtrusionEntityCollection chained;
if (collection.no_sort) chained = collection;
else chained = collection.chained_path_from(m_last_pos);
for (const ExtrusionEntity *next_entity : chained.entities) {
next_entity->visit(*this);
if (collection.no_sort || collection.role() == erMixed) {
for (const ExtrusionEntity* next_entity : collection.entities) {
next_entity->visit(*this);
}
} else {
ExtrusionEntityCollection chained = collection.chained_path_from(m_last_pos);
for (const ExtrusionEntity* next_entity : chained.entities) {
next_entity->visit(*this);
}
}
}

View File

@ -1982,6 +1982,126 @@ void Print::_make_skirt(const PrintObjectPtrs &objects, ExtrusionEntityCollectio
out.reverse();
}
void Print::_extrude_brim_from_tree(std::vector<std::vector< BrimLoop>>& loops, const Polygons& frontiers, const Flow& flow, ExtrusionEntityCollection& out, bool reversed/*= false*/) {
// nest contour loops (same as in perimetergenerator)
for (int d = loops.size() - 1; d >= 1; --d) {
std::vector<BrimLoop>& contours_d = loops[d];
// loop through all contours having depth == d
for (int i = 0; i < (int)contours_d.size(); ++i) {
const BrimLoop& loop = contours_d[i];
// find the contour loop that contains it
for (int t = d - 1; t >= 0; --t) {
for (size_t j = 0; j < loops[t].size(); ++j) {
BrimLoop& candidate_parent = loops[t][j];
bool test = reversed
? loop.polygon().contains(candidate_parent.line.first_point())
: candidate_parent.polygon().contains(loop.line.first_point());
if (test) {
candidate_parent.children.push_back(loop);
contours_d.erase(contours_d.begin() + i);
--i;
goto NEXT_CONTOUR;
}
}
}
//didn't find a contour: add it as a root loop
loops[0].push_back(loop);
contours_d.erase(contours_d.begin() + i);
--i;
NEXT_CONTOUR:;
}
}
//def
//cut loops if they go inside a forbidden region
std::function<void(BrimLoop&)> cut_loop = [&frontiers](BrimLoop& to_cut) {
Polylines result;
if (to_cut.is_loop)
result = intersection_pl(to_cut.polygon(), frontiers, true);
else
result = intersection_pl(to_cut.line, frontiers, true);
if (result.empty())
to_cut.line.points.clear();
else {
if (to_cut.line.points != result[0].points) {
to_cut.line.points = result[0].points;
to_cut.is_loop = false;
}
for (int i = 1; i < result.size(); i++)
to_cut.children.insert(to_cut.children.begin() + i - 1, BrimLoop(std::move(result[i])));
}
};
//calls
for (std::vector<BrimLoop>& loops : loops)
for (BrimLoop& loop : loops)
cut_loop(loop);
this->throw_if_canceled();
//def: push into extrusions, in the right order
float mm3_per_mm = float(flow.mm3_per_mm());
float width = float(flow.width);
float height = float(this->skirt_first_layer_height());
int nextIdx = 0;
std::function<void(BrimLoop&, ExtrusionEntityCollection*)>* extrude_ptr;
std::function<void(BrimLoop&, ExtrusionEntityCollection*) > extrude = [&mm3_per_mm, &width, &height, &extrude_ptr, &nextIdx](BrimLoop& to_cut, ExtrusionEntityCollection* parent) {
int idx = nextIdx++;
bool i_have_line = !to_cut.line.points.empty() && to_cut.line.is_valid();
if (!i_have_line && to_cut.children.empty()) {
//nothing
} else if (i_have_line && to_cut.children.empty()) {
if (to_cut.line.points.back() == to_cut.line.points.front()) {
ExtrusionPath path(erSkirt, mm3_per_mm, width, height);
path.polyline.points = to_cut.line.points;
parent->entities.emplace_back(new ExtrusionLoop(std::move(path), elrSkirt));
} else {
ExtrusionPath* extrusion_path = new ExtrusionPath(erSkirt, mm3_per_mm, width, height);
parent->entities.push_back(extrusion_path);
extrusion_path->polyline = to_cut.line;
}
} else if (!i_have_line && !to_cut.children.empty()) {
if (to_cut.children.size() == 1) {
(*extrude_ptr)(to_cut.children[0], parent);
} else {
ExtrusionEntityCollection* mycoll = new ExtrusionEntityCollection();
parent->entities.push_back(mycoll);
for (BrimLoop& child : to_cut.children)
(*extrude_ptr)(child, mycoll);
}
} else {
ExtrusionEntityCollection* print_me_first = new ExtrusionEntityCollection();
parent->entities.push_back(print_me_first);
print_me_first->no_sort = true;
if (to_cut.line.points.back() == to_cut.line.points.front()) {
ExtrusionPath path(erSkirt, mm3_per_mm, width, height);
path.polyline.points = to_cut.line.points;
print_me_first->entities.emplace_back(new ExtrusionLoop(std::move(path), elrSkirt));
} else {
ExtrusionPath* extrusion_path = new ExtrusionPath(erSkirt, mm3_per_mm, width, height);
print_me_first->entities.push_back(extrusion_path);
extrusion_path->polyline = to_cut.line;
}
if (to_cut.children.size() == 1) {
(*extrude_ptr)(to_cut.children[0], print_me_first);
} else {
ExtrusionEntityCollection* children = new ExtrusionEntityCollection();
print_me_first->entities.push_back(children);
for (BrimLoop& child : to_cut.children)
(*extrude_ptr)(child, children);
}
}
};
extrude_ptr = &extrude;
//launch extrude
for (BrimLoop& loop : loops[0]) {
extrude(loop, &out);
}
}
//TODO: test if no regression vs old _make_brim.
// this new one can extrude brim for an object inside an other object.
void Print::_make_brim(const Flow &flow, const PrintObjectPtrs &objects, ExPolygons &unbrimmable, ExtrusionEntityCollection &out) {
@ -2027,7 +2147,7 @@ void Print::_make_brim(const Flow &flow, const PrintObjectPtrs &objects, ExPolyg
const size_t num_loops = size_t(floor((brim_config.brim_width.value - brim_config.brim_offset.value) / flow.spacing()));
ExPolygons brimmable_areas;
for (ExPolygon &expoly : islands) {
for (Polygon poly : offset(expoly.contour, num_loops * flow.scaled_width(), jtSquare)) {
for (Polygon poly : offset(expoly.contour, num_loops * flow.scaled_spacing(), jtSquare)) {
brimmable_areas.emplace_back();
brimmable_areas.back().contour = poly;
brimmable_areas.back().contour.make_counter_clockwise();
@ -2043,8 +2163,9 @@ void Print::_make_brim(const Flow &flow, const PrintObjectPtrs &objects, ExPolyg
brimmable_areas = diff_ex(brimmable_areas, unbrimmable, true);
this->throw_if_canceled();
//now get all holes, use them to create loops
Polylines loops;
std::vector<std::vector<BrimLoop>> loops;
ExPolygons bigger_islands;
//grow a half of spacing, to go to the first extrusion polyline.
Polygons unbrimmable_polygons;
@ -2058,6 +2179,7 @@ void Print::_make_brim(const Flow &flow, const PrintObjectPtrs &objects, ExPolyg
}
islands = bigger_islands;
for (size_t i = 0; i < num_loops; ++i) {
loops.emplace_back();
this->throw_if_canceled();
// only grow the contour, not holes
bigger_islands.clear();
@ -2068,19 +2190,20 @@ void Print::_make_brim(const Flow &flow, const PrintObjectPtrs &objects, ExPolyg
bigger_islands.back().contour = big_contour;
}
}
}
else bigger_islands = islands;
} else bigger_islands = islands;
bigger_islands = union_ex(bigger_islands);
for (ExPolygon &expoly : bigger_islands) {
loops.push_back(expoly.contour);
//also add hole, in case of it's merged with a contour.
loops[i].emplace_back(expoly.contour);
//also add hole, in case of it's merged with a contour. <= HOW? if there's an island inside a hole! (in the same object)
for (Polygon &hole : expoly.holes)
//but remove the points that are inside the holes of islands
for(Polyline &pl : diff_pl(hole, unbrimmable_polygons, true))
loops.emplace_back(pl);
loops[i].emplace_back(pl);
}
}
std::reverse(loops.begin(), loops.end());
//intersection
Polygons frontiers;
//use contour from brimmable_areas (external frontier)
@ -2091,33 +2214,8 @@ void Print::_make_brim(const Flow &flow, const PrintObjectPtrs &objects, ExPolyg
// add internal frontier
frontiers.insert(frontiers.begin(), unbrimmable_polygons.begin(), unbrimmable_polygons.end());
Polylines lines = intersection_pl(loops, frontiers, true);
//{
// std::stringstream stri;
// stri << "exter_brim_test_" << ".svg";
// SVG svg(stri.str());
// svg.draw(unbrimmable_areas, "red");
// svg.draw(brimmable_areas, "green");
// svg.draw(to_polylines(frontiers), "blue");
// svg.draw((loops), "pink");
// svg.draw(lines, "yellow");
// svg.Close();
//}
this->throw_if_canceled();
//TODO: reorder when it will work with loops (ie do not overextrude)
//push into extrusions
extrusion_entities_append_paths(
out.entities,
lines,
erSkirt,
float(flow.mm3_per_mm()),
float(flow.width),
float(this->skirt_first_layer_height())
);
_extrude_brim_from_tree(loops, frontiers, flow, out);
unbrimmable.insert(unbrimmable.end(), brimmable_areas.begin(), brimmable_areas.end());
}
@ -2187,6 +2285,7 @@ void Print::_make_brim_ears(const Flow &flow, const PrintObjectPtrs &objects, Ex
loops.push_back(poly);
}
}
//order path with least travel possible
loops = union_pt_chained(loops, false);
//create ear pattern
@ -2275,9 +2374,10 @@ void Print::_make_brim_interior(const Flow &flow, const PrintObjectPtrs &objects
brimmable_areas = diff_ex(brimmable_areas, unbrimmable_areas, true);
//now get all holes, use them to create loops
Polygons loops;
std::vector<std::vector<BrimLoop>> loops;
for (size_t i = 0; i < num_loops; ++i) {
this->throw_if_canceled();
loops.emplace_back();
islands_to_loops = offset(islands_to_loops, double(-flow.scaled_spacing()), jtSquare);
for (Polygon &poly : islands_to_loops) {
poly.points.push_back(poly.points.front());
@ -2285,9 +2385,10 @@ void Print::_make_brim_interior(const Flow &flow, const PrintObjectPtrs &objects
p.pop_back();
poly.points = std::move(p);
}
polygons_append(loops, offset(islands_to_loops, 0.5f * double(flow.scaled_spacing())));
for (Polygon& poly : offset(islands_to_loops, 0.5f * double(flow.scaled_spacing())))
loops[i].emplace_back(poly);
}
loops = union_pt_chained(loops, false);
std::reverse(loops.begin(), loops.end());
//intersection
Polygons frontiers;
@ -2302,19 +2403,7 @@ void Print::_make_brim_interior(const Flow &flow, const PrintObjectPtrs &objects
}
}
Polylines lines = intersection_pl(loops, frontiers);
//TODO: reorder when it can work with loops
//push into extrusions
extrusion_entities_append_paths(
out.entities,
lines,
erSkirt,
float(flow.mm3_per_mm()),
float(flow.width),
float(this->skirt_first_layer_height())
);
_extrude_brim_from_tree(loops, frontiers, flow, out, true);
unbrimmable_areas.insert(unbrimmable_areas.end(), brimmable_areas.begin(), brimmable_areas.end());
}

View File

@ -355,6 +355,21 @@ struct PrintStatistics
}
};
class BrimLoop {
public:
BrimLoop(const Polygon& p) : line(p.split_at_first_point()), is_loop(true) {}
BrimLoop(const Polyline& l) : line(l), is_loop(false) {}
Polyline line;
std::vector<BrimLoop> children;
bool is_loop;
Polygon polygon() const{
Polygon poly = Polygon(line.points);
if (poly.points.front() == poly.points.back())
poly.points.resize(poly.points.size() - 1);
return poly;
}
};
typedef std::vector<PrintObject*> PrintObjectPtrs;
typedef std::vector<PrintRegion*> PrintRegionPtrs;
@ -468,6 +483,7 @@ private:
void _make_brim(const Flow &flow, const PrintObjectPtrs &objects, ExPolygons &unbrimmable, ExtrusionEntityCollection &out);
void _make_brim_ears(const Flow &flow, const PrintObjectPtrs &objects, ExPolygons &unbrimmable, ExtrusionEntityCollection &out);
void _make_brim_interior(const Flow &flow, const PrintObjectPtrs &objects, ExPolygons &unbrimmable, ExtrusionEntityCollection &out);
void _extrude_brim_from_tree(std::vector<std::vector<BrimLoop>> &loops, const Polygons &frontiers, const Flow &flow, ExtrusionEntityCollection &out, bool reversed = false);
Polylines _reorder_brim_polyline(Polylines lines, ExtrusionEntityCollection &out, const Flow &flow);
void _make_wipe_tower();