mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-15 18:55:54 +08:00
Merge branch 'lh_mm_segmentation'
This commit is contained in:
commit
80695603d6
@ -1113,7 +1113,7 @@ static inline Polygon to_polygon(const std::vector<Linef> &lines)
|
|||||||
// It iterates through all nodes on the border between two different colors, and from this point,
|
// It iterates through all nodes on the border between two different colors, and from this point,
|
||||||
// start selection always left most edges for every node to construct CCW polygons.
|
// start selection always left most edges for every node to construct CCW polygons.
|
||||||
// Assumes that graph is planar (without self-intersection edges)
|
// Assumes that graph is planar (without self-intersection edges)
|
||||||
static std::vector<std::pair<Polygon, size_t>> extract_colored_segments(const MMU_Graph &graph)
|
static std::vector<ExPolygons> extract_colored_segments(const MMU_Graph &graph, const size_t num_extruders)
|
||||||
{
|
{
|
||||||
std::vector<bool> used_arcs(graph.arcs.size(), false);
|
std::vector<bool> used_arcs(graph.arcs.size(), false);
|
||||||
// When there is no next arc, then is returned original_arc or edge with is marked as used
|
// When there is no next arc, then is returned original_arc or edge with is marked as used
|
||||||
@ -1153,7 +1153,7 @@ static std::vector<std::pair<Polygon, size_t>> extract_colored_segments(const MM
|
|||||||
return std::all_of(node.arc_idxs.cbegin(), node.arc_idxs.cend(), [&used_arcs](const size_t &arc_idx) -> bool { return used_arcs[arc_idx]; });
|
return std::all_of(node.arc_idxs.cbegin(), node.arc_idxs.cend(), [&used_arcs](const size_t &arc_idx) -> bool { return used_arcs[arc_idx]; });
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<std::pair<Polygon, size_t>> polygons_segments;
|
std::vector<ExPolygons> expolygons_segments(num_extruders + 1);
|
||||||
for (size_t node_idx = 0; node_idx < graph.all_border_points; ++node_idx) {
|
for (size_t node_idx = 0; node_idx < graph.all_border_points; ++node_idx) {
|
||||||
const MMU_Graph::Node &node = graph.nodes[node_idx];
|
const MMU_Graph::Node &node = graph.nodes[node_idx];
|
||||||
|
|
||||||
@ -1183,12 +1183,11 @@ static std::vector<std::pair<Polygon, size_t>> extract_colored_segments(const MM
|
|||||||
p_arc = &next;
|
p_arc = &next;
|
||||||
} while (graph.nodes[p_arc->to_idx].point != start_p || !all_arc_used(graph.nodes[p_arc->to_idx]));
|
} while (graph.nodes[p_arc->to_idx].point != start_p || !all_arc_used(graph.nodes[p_arc->to_idx]));
|
||||||
|
|
||||||
Polygon poly = to_polygon(face_lines);
|
if (Polygon poly = to_polygon(face_lines); poly.is_counter_clockwise() && poly.is_valid())
|
||||||
if (poly.is_counter_clockwise() && poly.is_valid())
|
expolygons_segments[arc.color].emplace_back(std::move(poly));
|
||||||
polygons_segments.emplace_back(poly, arc.color);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return polygons_segments;
|
return expolygons_segments;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used in remove_multiple_edges_in_vertices()
|
// Used in remove_multiple_edges_in_vertices()
|
||||||
@ -1269,21 +1268,20 @@ static void remove_multiple_edges_in_vertices(MMU_Graph &graph, const std::vecto
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cut_segmented_layers(const std::vector<ExPolygons> &input_expolygons,
|
static void cut_segmented_layers(const std::vector<ExPolygons> &input_expolygons,
|
||||||
std::vector<std::vector<std::pair<ExPolygon, size_t>>> &segmented_regions,
|
std::vector<std::vector<ExPolygons>> &segmented_regions,
|
||||||
const float cut_width,
|
const float cut_width,
|
||||||
const std::function<void()> &throw_on_cancel_callback)
|
const std::function<void()> &throw_on_cancel_callback)
|
||||||
{
|
{
|
||||||
BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - cutting segmented layers in parallel - begin";
|
BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - cutting segmented layers in parallel - begin";
|
||||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, segmented_regions.size()),[&segmented_regions, &input_expolygons, &cut_width, &throw_on_cancel_callback](const tbb::blocked_range<size_t>& range) {
|
tbb::parallel_for(tbb::blocked_range<size_t>(0, segmented_regions.size()),[&segmented_regions, &input_expolygons, &cut_width, &throw_on_cancel_callback](const tbb::blocked_range<size_t>& range) {
|
||||||
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) {
|
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) {
|
||||||
throw_on_cancel_callback();
|
throw_on_cancel_callback();
|
||||||
std::vector<std::pair<ExPolygon, size_t>> segmented_regions_cuts;
|
const size_t num_extruders_plus_one = segmented_regions[layer_idx].size();
|
||||||
for (const std::pair<ExPolygon, size_t> &colored_expoly : segmented_regions[layer_idx]) {
|
std::vector<ExPolygons> segmented_regions_cuts(num_extruders_plus_one); // Indexed by extruder_id
|
||||||
ExPolygons cut_colored_expoly = diff_ex(colored_expoly.first, offset_ex(input_expolygons[layer_idx], cut_width));
|
for (size_t extruder_idx = 0; extruder_idx < num_extruders_plus_one; ++extruder_idx)
|
||||||
for (ExPolygon &expoly : cut_colored_expoly)
|
if (const ExPolygons &ex_polygons = segmented_regions[layer_idx][extruder_idx]; !ex_polygons.empty())
|
||||||
segmented_regions_cuts.emplace_back(std::move(expoly), colored_expoly.second);
|
segmented_regions_cuts[extruder_idx] = diff_ex(ex_polygons, offset_ex(input_expolygons[layer_idx], cut_width));
|
||||||
}
|
|
||||||
segmented_regions[layer_idx] = std::move(segmented_regions_cuts);
|
segmented_regions[layer_idx] = std::move(segmented_regions_cuts);
|
||||||
}
|
}
|
||||||
}); // end of parallel_for
|
}); // end of parallel_for
|
||||||
@ -1323,7 +1321,7 @@ static inline std::vector<std::vector<ExPolygons>> mmu_segmentation_top_and_bott
|
|||||||
// Project upwards pointing painted triangles over top surfaces,
|
// Project upwards pointing painted triangles over top surfaces,
|
||||||
// project downards pointing painted triangles over bottom surfaces.
|
// project downards pointing painted triangles over bottom surfaces.
|
||||||
std::vector<std::vector<Polygons>> top_raw(num_extruders), bottom_raw(num_extruders);
|
std::vector<std::vector<Polygons>> top_raw(num_extruders), bottom_raw(num_extruders);
|
||||||
std::vector<float> zs = zs_from_layers(print_object.layers());
|
std::vector<float> zs = zs_from_layers(layers);
|
||||||
Transform3d object_trafo = print_object.trafo_centered();
|
Transform3d object_trafo = print_object.trafo_centered();
|
||||||
|
|
||||||
#ifdef MMU_SEGMENTATION_DEBUG_TOP_BOTTOM
|
#ifdef MMU_SEGMENTATION_DEBUG_TOP_BOTTOM
|
||||||
@ -1532,31 +1530,42 @@ static inline std::vector<std::vector<ExPolygons>> mmu_segmentation_top_and_bott
|
|||||||
return triangles_by_color_merged;
|
return triangles_by_color_merged;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<std::vector<std::pair<ExPolygon, size_t>>> merge_segmented_layers(
|
static std::vector<std::vector<ExPolygons>> merge_segmented_layers(
|
||||||
const std::vector<std::vector<std::pair<ExPolygon, size_t>>> &segmented_regions,
|
const std::vector<std::vector<ExPolygons>> &segmented_regions,
|
||||||
std::vector<std::vector<ExPolygons>> &&top_and_bottom_layers,
|
std::vector<std::vector<ExPolygons>> &&top_and_bottom_layers,
|
||||||
const std::function<void()> &throw_on_cancel_callback)
|
const size_t num_extruders,
|
||||||
|
const std::function<void()> &throw_on_cancel_callback)
|
||||||
{
|
{
|
||||||
std::vector<std::vector<std::pair<ExPolygon, size_t>>> segmented_regions_merged(segmented_regions.size());
|
const size_t num_layers = segmented_regions.size();
|
||||||
|
std::vector<std::vector<ExPolygons>> segmented_regions_merged(num_layers);
|
||||||
|
segmented_regions_merged.assign(num_layers, std::vector<ExPolygons>(num_extruders));
|
||||||
|
assert(num_extruders + 1 == top_and_bottom_layers.size());
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - merging segmented layers in parallel - begin";
|
BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - merging segmented layers in parallel - begin";
|
||||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, segmented_regions.size()), [&segmented_regions, &top_and_bottom_layers, &segmented_regions_merged, &throw_on_cancel_callback](const tbb::blocked_range<size_t> &range) {
|
tbb::parallel_for(tbb::blocked_range<size_t>(0, num_layers), [&segmented_regions, &top_and_bottom_layers, &segmented_regions_merged, &num_extruders, &throw_on_cancel_callback](const tbb::blocked_range<size_t> &range) {
|
||||||
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) {
|
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) {
|
||||||
for (const std::pair<ExPolygon, size_t> &colored_expoly : segmented_regions[layer_idx]) {
|
assert(segmented_regions[layer_idx].size() == num_extruders + 1);
|
||||||
|
// Zero is skipped because it is the default color of the volume
|
||||||
|
for (size_t extruder_id = 1; extruder_id < num_extruders + 1; ++extruder_id) {
|
||||||
throw_on_cancel_callback();
|
throw_on_cancel_callback();
|
||||||
// Zero is the default color of the volume.
|
if (!segmented_regions[layer_idx][extruder_id].empty()) {
|
||||||
if(colored_expoly.second == 0)
|
ExPolygons segmented_regions_trimmed = segmented_regions[layer_idx][extruder_id];
|
||||||
continue;
|
for (const std::vector<ExPolygons> &top_and_bottom_by_extruder : top_and_bottom_layers)
|
||||||
ExPolygons cut_colored_expoly = {colored_expoly.first};
|
if (!top_and_bottom_by_extruder[layer_idx].empty() && !segmented_regions_trimmed.empty())
|
||||||
for (const std::vector<ExPolygons> &top_and_bottom_layer : top_and_bottom_layers)
|
segmented_regions_trimmed = diff_ex(segmented_regions_trimmed, top_and_bottom_by_extruder[layer_idx]);
|
||||||
cut_colored_expoly = diff_ex(cut_colored_expoly, top_and_bottom_layer[layer_idx]);
|
|
||||||
for (ExPolygon &ex_poly : cut_colored_expoly)
|
|
||||||
segmented_regions_merged[layer_idx].emplace_back(std::move(ex_poly), colored_expoly.second - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t color_idx = 1; color_idx < top_and_bottom_layers.size(); ++color_idx)
|
segmented_regions_merged[layer_idx][extruder_id - 1] = std::move(segmented_regions_trimmed);
|
||||||
for (ExPolygon &expoly : top_and_bottom_layers[color_idx][layer_idx])
|
}
|
||||||
segmented_regions_merged[layer_idx].emplace_back(std::move(expoly), color_idx - 1);
|
|
||||||
|
if (!top_and_bottom_layers[extruder_id][layer_idx].empty()) {
|
||||||
|
bool was_top_and_bottom_empty = segmented_regions_merged[layer_idx][extruder_id - 1].empty();
|
||||||
|
append(segmented_regions_merged[layer_idx][extruder_id - 1], top_and_bottom_layers[extruder_id][layer_idx]);
|
||||||
|
|
||||||
|
// Remove dimples (#7235) appearing after merging side segmentation of the model with tops and bottoms painted layers.
|
||||||
|
if (!was_top_and_bottom_empty)
|
||||||
|
segmented_regions_merged[layer_idx][extruder_id - 1] = offset2_ex(union_ex(segmented_regions_merged[layer_idx][extruder_id - 1]), SCALED_EPSILON, -SCALED_EPSILON);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}); // end of parallel_for
|
}); // end of parallel_for
|
||||||
BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - merging segmented layers in parallel - end";
|
BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - merging segmented layers in parallel - end";
|
||||||
@ -1565,7 +1574,7 @@ static std::vector<std::vector<std::pair<ExPolygon, size_t>>> merge_segmented_la
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MMU_SEGMENTATION_DEBUG_REGIONS
|
#ifdef MMU_SEGMENTATION_DEBUG_REGIONS
|
||||||
static void export_regions_to_svg(const std::string &path, const std::vector<std::pair<ExPolygon, size_t>> ®ions, const ExPolygons &lslices)
|
static void export_regions_to_svg(const std::string &path, const std::vector<ExPolygons> ®ions, const ExPolygons &lslices)
|
||||||
{
|
{
|
||||||
const std::vector<std::string> colors = {"blue", "cyan", "red", "orange", "magenta", "pink", "purple", "yellow"};
|
const std::vector<std::string> colors = {"blue", "cyan", "red", "orange", "magenta", "pink", "purple", "yellow"};
|
||||||
coordf_t stroke_width = scale_(0.05);
|
coordf_t stroke_width = scale_(0.05);
|
||||||
@ -1574,12 +1583,12 @@ static void export_regions_to_svg(const std::string &path, const std::vector<std
|
|||||||
::Slic3r::SVG svg(path.c_str(), bbox);
|
::Slic3r::SVG svg(path.c_str(), bbox);
|
||||||
|
|
||||||
svg.draw_outline(lslices, "green", "lime", stroke_width);
|
svg.draw_outline(lslices, "green", "lime", stroke_width);
|
||||||
for (const std::pair<ExPolygon, size_t> ®ion : regions) {
|
for (const ExPolygons &by_extruder : regions) {
|
||||||
int region_color = int(region.second);
|
size_t extrude_idx = &by_extruder - ®ions.front();
|
||||||
if (region_color >= 0 && region_color < int(colors.size()))
|
if (extrude_idx >= 0 && extrude_idx < int(colors.size()))
|
||||||
svg.draw(region.first, colors[region_color]);
|
svg.draw(by_extruder, colors[extrude_idx], stroke_width);
|
||||||
else
|
else
|
||||||
svg.draw(region.first, "black");
|
svg.draw(by_extruder, "black", stroke_width);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // MMU_SEGMENTATION_DEBUG_REGIONS
|
#endif // MMU_SEGMENTATION_DEBUG_REGIONS
|
||||||
@ -1667,20 +1676,23 @@ static bool has_layer_only_one_color(const std::vector<std::vector<ColoredLine>>
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::vector<std::pair<ExPolygon, size_t>>> multi_material_segmentation_by_painting(const PrintObject &print_object, const std::function<void()> &throw_on_cancel_callback)
|
std::vector<std::vector<ExPolygons>> multi_material_segmentation_by_painting(const PrintObject &print_object, const std::function<void()> &throw_on_cancel_callback)
|
||||||
{
|
{
|
||||||
std::vector<std::vector<std::pair<ExPolygon, size_t>>> segmented_regions(print_object.layers().size());
|
const size_t num_extruders = print_object.print()->config().nozzle_diameter.size();
|
||||||
std::vector<std::vector<PaintedLine>> painted_lines(print_object.layers().size());
|
const size_t num_layers = print_object.layers().size();
|
||||||
std::array<std::mutex, 64> painted_lines_mutex;
|
std::vector<std::vector<ExPolygons>> segmented_regions(num_layers);
|
||||||
std::vector<EdgeGrid::Grid> edge_grids(print_object.layers().size());
|
segmented_regions.assign(num_layers, std::vector<ExPolygons>(num_extruders + 1));
|
||||||
const ConstLayerPtrsAdaptor layers = print_object.layers();
|
std::vector<std::vector<PaintedLine>> painted_lines(num_layers);
|
||||||
std::vector<ExPolygons> input_expolygons(layers.size());
|
std::array<std::mutex, 64> painted_lines_mutex;
|
||||||
|
std::vector<EdgeGrid::Grid> edge_grids(num_layers);
|
||||||
|
const ConstLayerPtrsAdaptor layers = print_object.layers();
|
||||||
|
std::vector<ExPolygons> input_expolygons(num_layers);
|
||||||
|
|
||||||
throw_on_cancel_callback();
|
throw_on_cancel_callback();
|
||||||
|
|
||||||
// Merge all regions and remove small holes
|
// Merge all regions and remove small holes
|
||||||
BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - slices preparation in parallel - begin";
|
BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - slices preparation in parallel - begin";
|
||||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, layers.size()), [&layers, &input_expolygons, &throw_on_cancel_callback](const tbb::blocked_range<size_t> &range) {
|
tbb::parallel_for(tbb::blocked_range<size_t>(0, num_layers), [&layers, &input_expolygons, &throw_on_cancel_callback](const tbb::blocked_range<size_t> &range) {
|
||||||
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) {
|
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) {
|
||||||
throw_on_cancel_callback();
|
throw_on_cancel_callback();
|
||||||
ExPolygons ex_polygons;
|
ExPolygons ex_polygons;
|
||||||
@ -1711,7 +1723,7 @@ std::vector<std::vector<std::pair<ExPolygon, size_t>>> multi_material_segmentati
|
|||||||
}); // end of parallel_for
|
}); // end of parallel_for
|
||||||
BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - slices preparation in parallel - end";
|
BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - slices preparation in parallel - end";
|
||||||
|
|
||||||
for (size_t layer_idx = 0; layer_idx < layers.size(); ++layer_idx) {
|
for (size_t layer_idx = 0; layer_idx < num_layers; ++layer_idx) {
|
||||||
throw_on_cancel_callback();
|
throw_on_cancel_callback();
|
||||||
BoundingBox bbox(get_extents(layers[layer_idx]->regions()));
|
BoundingBox bbox(get_extents(layers[layer_idx]->regions()));
|
||||||
bbox.merge(get_extents(input_expolygons[layer_idx]));
|
bbox.merge(get_extents(input_expolygons[layer_idx]));
|
||||||
@ -1723,8 +1735,7 @@ std::vector<std::vector<std::pair<ExPolygon, size_t>>> multi_material_segmentati
|
|||||||
|
|
||||||
BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - projection of painted triangles - begin";
|
BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - projection of painted triangles - begin";
|
||||||
for (const ModelVolume *mv : print_object.model_object()->volumes) {
|
for (const ModelVolume *mv : print_object.model_object()->volumes) {
|
||||||
const size_t num_extruders = print_object.print()->config().nozzle_diameter.size() + 1;
|
tbb::parallel_for(tbb::blocked_range<size_t>(1, num_extruders + 1), [&mv, &print_object, &layers, &edge_grids, &painted_lines, &painted_lines_mutex, &input_expolygons, &throw_on_cancel_callback](const tbb::blocked_range<size_t> &range) {
|
||||||
tbb::parallel_for(tbb::blocked_range<size_t>(1, num_extruders), [&mv, &print_object, &edge_grids, &painted_lines, &painted_lines_mutex, &input_expolygons, &throw_on_cancel_callback](const tbb::blocked_range<size_t> &range) {
|
|
||||||
for (size_t extruder_idx = range.begin(); extruder_idx < range.end(); ++extruder_idx) {
|
for (size_t extruder_idx = range.begin(); extruder_idx < range.end(); ++extruder_idx) {
|
||||||
throw_on_cancel_callback();
|
throw_on_cancel_callback();
|
||||||
const indexed_triangle_set custom_facets = mv->mmu_segmentation_facets.get_facets(*mv, EnforcerBlockerType(extruder_idx));
|
const indexed_triangle_set custom_facets = mv->mmu_segmentation_facets.get_facets(*mv, EnforcerBlockerType(extruder_idx));
|
||||||
@ -1732,7 +1743,7 @@ std::vector<std::vector<std::pair<ExPolygon, size_t>>> multi_material_segmentati
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
const Transform3f tr = print_object.trafo().cast<float>() * mv->get_matrix().cast<float>();
|
const Transform3f tr = print_object.trafo().cast<float>() * mv->get_matrix().cast<float>();
|
||||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, custom_facets.indices.size()), [&tr, &custom_facets, &print_object, &edge_grids, &input_expolygons, &painted_lines, &painted_lines_mutex, &extruder_idx](const tbb::blocked_range<size_t> &range) {
|
tbb::parallel_for(tbb::blocked_range<size_t>(0, custom_facets.indices.size()), [&tr, &custom_facets, &print_object, &layers, &edge_grids, &input_expolygons, &painted_lines, &painted_lines_mutex, &extruder_idx](const tbb::blocked_range<size_t> &range) {
|
||||||
for (size_t facet_idx = range.begin(); facet_idx < range.end(); ++facet_idx) {
|
for (size_t facet_idx = range.begin(); facet_idx < range.end(); ++facet_idx) {
|
||||||
float min_z = std::numeric_limits<float>::max();
|
float min_z = std::numeric_limits<float>::max();
|
||||||
float max_z = std::numeric_limits<float>::lowest();
|
float max_z = std::numeric_limits<float>::lowest();
|
||||||
@ -1748,15 +1759,15 @@ std::vector<std::vector<std::pair<ExPolygon, size_t>>> multi_material_segmentati
|
|||||||
std::sort(facet.begin(), facet.end(), [](const Vec3f &p1, const Vec3f &p2) { return p1.z() < p2.z(); });
|
std::sort(facet.begin(), facet.end(), [](const Vec3f &p1, const Vec3f &p2) { return p1.z() < p2.z(); });
|
||||||
|
|
||||||
// Find lowest slice not below the triangle.
|
// Find lowest slice not below the triangle.
|
||||||
auto first_layer = std::upper_bound(print_object.layers().begin(), print_object.layers().end(), float(min_z - EPSILON),
|
auto first_layer = std::upper_bound(layers.begin(), layers.end(), float(min_z - EPSILON),
|
||||||
[](float z, const Layer *l1) { return z < l1->slice_z; });
|
[](float z, const Layer *l1) { return z < l1->slice_z; });
|
||||||
auto last_layer = std::upper_bound(print_object.layers().begin(), print_object.layers().end(), float(max_z + EPSILON),
|
auto last_layer = std::upper_bound(layers.begin(), layers.end(), float(max_z + EPSILON),
|
||||||
[](float z, const Layer *l1) { return z < l1->slice_z; });
|
[](float z, const Layer *l1) { return z < l1->slice_z; });
|
||||||
--last_layer;
|
--last_layer;
|
||||||
|
|
||||||
for (auto layer_it = first_layer; layer_it != (last_layer + 1); ++layer_it) {
|
for (auto layer_it = first_layer; layer_it != (last_layer + 1); ++layer_it) {
|
||||||
const Layer *layer = *layer_it;
|
const Layer *layer = *layer_it;
|
||||||
size_t layer_idx = layer_it - print_object.layers().begin();
|
size_t layer_idx = layer_it - layers.begin();
|
||||||
if (input_expolygons[layer_idx].empty() || facet[0].z() > layer->slice_z || layer->slice_z > facet[2].z())
|
if (input_expolygons[layer_idx].empty() || facet[0].z() > layer->slice_z || layer->slice_z > facet[2].z())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -1799,7 +1810,7 @@ std::vector<std::vector<std::pair<ExPolygon, size_t>>> multi_material_segmentati
|
|||||||
<< std::count_if(painted_lines.begin(), painted_lines.end(), [](const std::vector<PaintedLine> &pl) { return !pl.empty(); });
|
<< std::count_if(painted_lines.begin(), painted_lines.end(), [](const std::vector<PaintedLine> &pl) { return !pl.empty(); });
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - layers segmentation in parallel - begin";
|
BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - layers segmentation in parallel - begin";
|
||||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, print_object.layers().size()), [&edge_grids, &input_expolygons, &painted_lines, &segmented_regions, &throw_on_cancel_callback](const tbb::blocked_range<size_t> &range) {
|
tbb::parallel_for(tbb::blocked_range<size_t>(0, num_layers), [&edge_grids, &input_expolygons, &painted_lines, &segmented_regions, &num_extruders, &throw_on_cancel_callback](const tbb::blocked_range<size_t> &range) {
|
||||||
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) {
|
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) {
|
||||||
throw_on_cancel_callback();
|
throw_on_cancel_callback();
|
||||||
if (!painted_lines[layer_idx].empty()) {
|
if (!painted_lines[layer_idx].empty()) {
|
||||||
@ -1832,8 +1843,7 @@ std::vector<std::vector<std::pair<ExPolygon, size_t>>> multi_material_segmentati
|
|||||||
assert(!color_poly.front().empty());
|
assert(!color_poly.front().empty());
|
||||||
if (has_layer_only_one_color(color_poly)) {
|
if (has_layer_only_one_color(color_poly)) {
|
||||||
// If the whole layer is painted using the same color, it is not needed to construct a Voronoi diagram for the segmentation of this layer.
|
// If the whole layer is painted using the same color, it is not needed to construct a Voronoi diagram for the segmentation of this layer.
|
||||||
for (const ExPolygon &ex_polygon : input_expolygons[layer_idx])
|
segmented_regions[layer_idx][size_t(color_poly.front().front().color)] = input_expolygons[layer_idx];
|
||||||
segmented_regions[layer_idx].emplace_back(ex_polygon, size_t(color_poly.front().front().color));
|
|
||||||
} else {
|
} else {
|
||||||
MMU_Graph graph = build_graph(layer_idx, color_poly);
|
MMU_Graph graph = build_graph(layer_idx, color_poly);
|
||||||
remove_multiple_edges_in_vertices(graph, color_poly);
|
remove_multiple_edges_in_vertices(graph, color_poly);
|
||||||
@ -1846,9 +1856,7 @@ std::vector<std::vector<std::pair<ExPolygon, size_t>>> multi_material_segmentati
|
|||||||
}
|
}
|
||||||
#endif // MMU_SEGMENTATION_DEBUG_GRAPH
|
#endif // MMU_SEGMENTATION_DEBUG_GRAPH
|
||||||
|
|
||||||
std::vector<std::pair<Polygon, size_t>> segmentation = extract_colored_segments(graph);
|
segmented_regions[layer_idx] = extract_colored_segments(graph, num_extruders);
|
||||||
for (std::pair<Polygon, size_t> ®ion : segmentation)
|
|
||||||
segmented_regions[layer_idx].emplace_back(std::move(region));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MMU_SEGMENTATION_DEBUG_REGIONS
|
#ifdef MMU_SEGMENTATION_DEBUG_REGIONS
|
||||||
@ -1868,11 +1876,11 @@ std::vector<std::vector<std::pair<ExPolygon, size_t>>> multi_material_segmentati
|
|||||||
throw_on_cancel_callback();
|
throw_on_cancel_callback();
|
||||||
}
|
}
|
||||||
|
|
||||||
// return segmented_regions;
|
// The first index is extruder number (includes default extruder), and the second one is layer number
|
||||||
std::vector<std::vector<ExPolygons>> top_and_bottom_layers = mmu_segmentation_top_and_bottom_layers(print_object, input_expolygons, throw_on_cancel_callback);
|
std::vector<std::vector<ExPolygons>> top_and_bottom_layers = mmu_segmentation_top_and_bottom_layers(print_object, input_expolygons, throw_on_cancel_callback);
|
||||||
throw_on_cancel_callback();
|
throw_on_cancel_callback();
|
||||||
|
|
||||||
std::vector<std::vector<std::pair<ExPolygon, size_t>>> segmented_regions_merged = merge_segmented_layers(segmented_regions, std::move(top_and_bottom_layers), throw_on_cancel_callback);
|
std::vector<std::vector<ExPolygons>> segmented_regions_merged = merge_segmented_layers(segmented_regions, std::move(top_and_bottom_layers), num_extruders, throw_on_cancel_callback);
|
||||||
throw_on_cancel_callback();
|
throw_on_cancel_callback();
|
||||||
|
|
||||||
#ifdef MMU_SEGMENTATION_DEBUG_REGIONS
|
#ifdef MMU_SEGMENTATION_DEBUG_REGIONS
|
||||||
|
@ -11,7 +11,7 @@ class PrintObject;
|
|||||||
class ExPolygon;
|
class ExPolygon;
|
||||||
|
|
||||||
// Returns MMU segmentation based on painting in MMU segmentation gizmo
|
// Returns MMU segmentation based on painting in MMU segmentation gizmo
|
||||||
std::vector<std::vector<std::pair<ExPolygon, size_t>>> multi_material_segmentation_by_painting(const PrintObject &print_object, const std::function<void()> &throw_on_cancel_callback);
|
std::vector<std::vector<ExPolygons>> multi_material_segmentation_by_painting(const PrintObject &print_object, const std::function<void()> &throw_on_cancel_callback);
|
||||||
|
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
|
||||||
|
@ -538,7 +538,7 @@ template<typename ThrowOnCancel>
|
|||||||
static inline void apply_mm_segmentation(PrintObject &print_object, ThrowOnCancel throw_on_cancel)
|
static inline void apply_mm_segmentation(PrintObject &print_object, ThrowOnCancel throw_on_cancel)
|
||||||
{
|
{
|
||||||
// Returns MMU segmentation based on painting in MMU segmentation gizmo
|
// Returns MMU segmentation based on painting in MMU segmentation gizmo
|
||||||
std::vector<std::vector<std::pair<ExPolygon, size_t>>> segmentation = multi_material_segmentation_by_painting(print_object, throw_on_cancel);
|
std::vector<std::vector<ExPolygons>> segmentation = multi_material_segmentation_by_painting(print_object, throw_on_cancel);
|
||||||
assert(segmentation.size() == print_object.layer_count());
|
assert(segmentation.size() == print_object.layer_count());
|
||||||
tbb::parallel_for(
|
tbb::parallel_for(
|
||||||
tbb::blocked_range<size_t>(0, segmentation.size(), std::max(segmentation.size() / 128, size_t(1))),
|
tbb::blocked_range<size_t>(0, segmentation.size(), std::max(segmentation.size() / 128, size_t(1))),
|
||||||
@ -568,9 +568,7 @@ static inline void apply_mm_segmentation(PrintObject &print_object, ThrowOnCance
|
|||||||
bool layer_split = false;
|
bool layer_split = false;
|
||||||
for (size_t extruder_id = 0; extruder_id < num_extruders; ++ extruder_id) {
|
for (size_t extruder_id = 0; extruder_id < num_extruders; ++ extruder_id) {
|
||||||
ByExtruder ®ion = by_extruder[extruder_id];
|
ByExtruder ®ion = by_extruder[extruder_id];
|
||||||
for (const std::pair<ExPolygon, size_t> &colored_polygon : segmentation[layer_id])
|
append(region.expolygons, std::move(segmentation[layer_id][extruder_id]));
|
||||||
if (colored_polygon.second == extruder_id)
|
|
||||||
region.expolygons.emplace_back(std::move(colored_polygon.first));
|
|
||||||
if (! region.expolygons.empty()) {
|
if (! region.expolygons.empty()) {
|
||||||
region.bbox = get_extents(region.expolygons);
|
region.bbox = get_extents(region.expolygons);
|
||||||
layer_split = true;
|
layer_split = true;
|
||||||
@ -632,6 +630,13 @@ static inline void apply_mm_segmentation(PrintObject &print_object, ThrowOnCance
|
|||||||
if (mine.empty())
|
if (mine.empty())
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
// Filter out unprintable polygons produced by subtraction multi-material painted regions from layerm.region().
|
||||||
|
// ExPolygon returned from multi-material segmentation does not precisely match ExPolygons in layerm.region()
|
||||||
|
// (because of preprocessing of the input regions in multi-material segmentation). Therefore, subtraction from
|
||||||
|
// layerm.region() could produce a huge number of small unprintable regions for the model's base extruder.
|
||||||
|
// This could, on some models, produce bulges with the model's base color (#7109).
|
||||||
|
if (! mine.empty())
|
||||||
|
mine = opening(union_ex(mine), float(scale_(5 * EPSILON)), float(scale_(5 * EPSILON)));
|
||||||
if (! mine.empty()) {
|
if (! mine.empty()) {
|
||||||
ByRegion &dst = by_region[layerm.region().print_object_region_id()];
|
ByRegion &dst = by_region[layerm.region().print_object_region_id()];
|
||||||
if (dst.expolygons.empty()) {
|
if (dst.expolygons.empty()) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user