This commit is contained in:
YuSanka 2019-08-25 09:44:46 +02:00
commit 55b2b0737c
6 changed files with 87 additions and 21 deletions

View file

@ -290,9 +290,10 @@ void EdgeGrid::Grid::create_from_m_contours(coord_t resolution)
size_t j;
} visitor(m_cell_data, m_cells, m_cols);
assert(visitor.i == 0);
for (; visitor.i < m_contours.size(); ++ visitor.i) {
const Slic3r::Points &pts = *m_contours[visitor.i];
for (; visitor.j < pts.size(); ++ visitor.j)
for (visitor.j = 0; visitor.j < pts.size(); ++ visitor.j)
this->visit_cells_intersecting_line(pts[visitor.j], pts[(visitor.j + 1 == pts.size()) ? 0 : visitor.j + 1], visitor);
}
}

View file

@ -24,6 +24,8 @@
#include "SVG.hpp"
#include <tbb/parallel_for.h>
#include <Shiny/Shiny.h>
#if 0
@ -48,7 +50,12 @@ static inline void check_add_eol(std::string &gcode)
if (! gcode.empty() && gcode.back() != '\n')
gcode += '\n';
}
void AvoidCrossingPerimeters::init_external_mp(const Print &print)
{
m_external_mp = Slic3r::make_unique<MotionPlanner>(union_ex(this->collect_contours_all_layers(print.objects())));
}
// Plan a travel move while minimizing the number of perimeter crossings.
// point is in unscaled coordinates, in the coordinate system of the current active object
// (set by gcodegen.set_origin()).
@ -65,6 +72,72 @@ Polyline AvoidCrossingPerimeters::travel_to(const GCode &gcodegen, const Point &
return result;
}
// Collect outer contours of all objects over all layers.
// Discard objects only containing thin walls (offset would fail on an empty polygon).
// Used by avoid crossing perimeters feature.
Polygons AvoidCrossingPerimeters::collect_contours_all_layers(const PrintObjectPtrs& objects)
{
Polygons islands;
for (const PrintObject *object : objects) {
// Reducing all the object slices into the Z projection in a logarithimc fashion.
// First reduce to half the number of layers.
std::vector<Polygons> polygons_per_layer((object->layers().size() + 1) / 2);
tbb::parallel_for(tbb::blocked_range<size_t>(0, object->layers().size() / 2),
[&object, &polygons_per_layer](const tbb::blocked_range<size_t> &range) {
for (size_t i = range.begin(); i < range.end(); ++ i) {
const Layer* layer1 = object->layers()[i * 2];
const Layer* layer2 = object->layers()[i * 2 + 1];
Polygons polys;
polys.reserve(layer1->slices.expolygons.size() + layer2->slices.expolygons.size());
for (const ExPolygon &expoly : layer1->slices.expolygons)
//FIXME no holes?
polys.emplace_back(expoly.contour);
for (const ExPolygon &expoly : layer2->slices.expolygons)
//FIXME no holes?
polys.emplace_back(expoly.contour);
polygons_per_layer[i] = union_(polys);
}
});
if (object->layers().size() & 1) {
const Layer *layer = object->layers().back();
Polygons polys;
polys.reserve(layer->slices.expolygons.size());
for (const ExPolygon &expoly : layer->slices.expolygons)
//FIXME no holes?
polys.emplace_back(expoly.contour);
polygons_per_layer.back() = union_(polys);
}
// Now reduce down to a single layer.
size_t cnt = polygons_per_layer.size();
while (cnt > 1) {
tbb::parallel_for(tbb::blocked_range<size_t>(0, cnt / 2),
[&polygons_per_layer](const tbb::blocked_range<size_t> &range) {
for (size_t i = range.begin(); i < range.end(); ++ i) {
Polygons polys;
polys.reserve(polygons_per_layer[i * 2].size() + polygons_per_layer[i * 2 + 1].size());
polygons_append(polys, polygons_per_layer[i * 2]);
polygons_append(polys, polygons_per_layer[i * 2 + 1]);
polygons_per_layer[i * 2] = union_(polys);
}
});
for (size_t i = 0; i < cnt / 2; ++ i)
polygons_per_layer[i] = std::move(polygons_per_layer[i * 2]);
if (cnt & 1)
polygons_per_layer[cnt / 2] = std::move(polygons_per_layer[cnt - 1]);
cnt = (cnt + 1) / 2;
}
// And collect copies of the objects.
for (const Point &copy : object->copies()) {
// All the layers were reduced to the 1st item of polygons_per_layer.
size_t i = islands.size();
polygons_append(islands, polygons_per_layer.front());
for (; i < islands.size(); ++ i)
islands[i].translate(copy);
}
}
return islands;
}
std::string OozePrevention::pre_toolchange(GCode &gcodegen)
{
std::string gcode;
@ -940,21 +1013,10 @@ void GCode::_do_export(Print &print, FILE *file)
// Initialize a motion planner for object-to-object travel moves.
if (print.config().avoid_crossing_perimeters.value) {
// Collect outer contours of all objects over all layers.
// Discard objects only containing thin walls (offset would fail on an empty polygon).
Polygons islands;
for (const PrintObject *object : print.objects())
for (const Layer *layer : object->layers())
for (const ExPolygon &expoly : layer->slices.expolygons)
for (const Point &copy : object->copies()) {
islands.emplace_back(expoly.contour);
islands.back().translate(copy);
}
//FIXME Mege the islands in parallel.
m_avoid_crossing_perimeters.init_external_mp(union_ex(islands));
m_avoid_crossing_perimeters.init_external_mp(print);
print.throw_if_canceled();
}
// Calculate wiping points if needed
if (print.config().ooze_prevention.value && ! print.config().single_extruder_multi_material) {
Points skirt_points;

View file

@ -45,12 +45,15 @@ public:
AvoidCrossingPerimeters() : use_external_mp(false), use_external_mp_once(false), disable_once(true) {}
~AvoidCrossingPerimeters() {}
void init_external_mp(const ExPolygons &islands) { m_external_mp = Slic3r::make_unique<MotionPlanner>(islands); }
void init_external_mp(const Print &print);
void init_layer_mp(const ExPolygons &islands) { m_layer_mp = Slic3r::make_unique<MotionPlanner>(islands); }
Polyline travel_to(const GCode &gcodegen, const Point &point);
private:
// For initializing the regions to avoid.
static Polygons collect_contours_all_layers(const PrintObjectPtrs& objects);
std::unique_ptr<MotionPlanner> m_external_mp;
std::unique_ptr<MotionPlanner> m_layer_mp;
};