|
|
|
|
@@ -1240,221 +1240,6 @@ static inline std::vector<std::vector<ExPolygons>> mmu_segmentation_top_and_bott
|
|
|
|
|
const size_t num_layers = input_expolygons.size();
|
|
|
|
|
const ConstLayerPtrsAdaptor layers = print_object.layers();
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
auto get_extrusion_width = [&layers = std::as_const(layers)](const size_t layer_idx) -> float {
|
|
|
|
|
auto extrusion_width_it = std::max_element(layers[layer_idx]->regions().begin(), layers[layer_idx]->regions().end(),
|
|
|
|
|
[](const LayerRegion *l1, const LayerRegion *l2) {
|
|
|
|
|
return l1->region().config().perimeter_extrusion_width <
|
|
|
|
|
l2->region().config().perimeter_extrusion_width;
|
|
|
|
|
});
|
|
|
|
|
assert(extrusion_width_it != layers[layer_idx]->regions().end());
|
|
|
|
|
return float((*extrusion_width_it)->region().config().perimeter_extrusion_width);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
auto get_top_solid_layers = [&layers = std::as_const(layers)](const size_t layer_idx) -> int {
|
|
|
|
|
auto top_solid_layer_it = std::max_element(layers[layer_idx]->regions().begin(), layers[layer_idx]->regions().end(),
|
|
|
|
|
[](const LayerRegion *l1, const LayerRegion *l2) {
|
|
|
|
|
return l1->region().config().top_solid_layers < l2->region().config().top_solid_layers;
|
|
|
|
|
});
|
|
|
|
|
assert(top_solid_layer_it != layers[layer_idx]->regions().end());
|
|
|
|
|
return (*top_solid_layer_it)->region().config().top_solid_layers;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
auto get_bottom_solid_layers = [&layers = std::as_const(layers)](const size_t layer_idx) -> int {
|
|
|
|
|
auto top_bottom_layer_it = std::max_element(layers[layer_idx]->regions().begin(), layers[layer_idx]->regions().end(),
|
|
|
|
|
[](const LayerRegion *l1, const LayerRegion *l2) {
|
|
|
|
|
return l1->region().config().bottom_solid_layers < l2->region().config().bottom_solid_layers;
|
|
|
|
|
});
|
|
|
|
|
assert(top_bottom_layer_it != layers[layer_idx]->regions().end());
|
|
|
|
|
return (*top_bottom_layer_it)->region().config().bottom_solid_layers;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
std::vector<ExPolygons> top_layers(num_layers);
|
|
|
|
|
top_layers.back() = input_expolygons.back();
|
|
|
|
|
tbb::parallel_for(tbb::blocked_range<size_t>(1, num_layers), [&](const tbb::blocked_range<size_t> &range) {
|
|
|
|
|
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) {
|
|
|
|
|
throw_on_cancel_callback();
|
|
|
|
|
float extrusion_width = 0.1f * float(scale_(get_extrusion_width(layer_idx)));
|
|
|
|
|
top_layers[layer_idx - 1] = diff_ex(input_expolygons[layer_idx - 1], offset_ex(input_expolygons[layer_idx], extrusion_width));
|
|
|
|
|
}
|
|
|
|
|
}); // end of parallel_for
|
|
|
|
|
|
|
|
|
|
std::vector<ExPolygons> bottom_layers(num_layers);
|
|
|
|
|
bottom_layers.front() = input_expolygons.front();
|
|
|
|
|
tbb::parallel_for(tbb::blocked_range<size_t>(0, num_layers - 1), [&](const tbb::blocked_range<size_t> &range) {
|
|
|
|
|
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) {
|
|
|
|
|
throw_on_cancel_callback();
|
|
|
|
|
float extrusion_width = 0.1f * float(scale_(get_extrusion_width(layer_idx)));
|
|
|
|
|
bottom_layers[layer_idx + 1] = diff_ex(input_expolygons[layer_idx + 1], offset_ex(input_expolygons[layer_idx], extrusion_width));
|
|
|
|
|
}
|
|
|
|
|
}); // end of parallel_for
|
|
|
|
|
|
|
|
|
|
std::vector<std::vector<ClipperLib::Paths>> triangles_by_color_raw(num_extruders, std::vector<ClipperLib::Paths>(layers.size()));
|
|
|
|
|
BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - top and bottom layers - projection of painted triangles - begin";
|
|
|
|
|
{
|
|
|
|
|
auto delta = float(10 * SCALED_EPSILON);
|
|
|
|
|
std::vector<float> deltas { delta, delta, delta };
|
|
|
|
|
Points projected_facet;
|
|
|
|
|
for (const ModelVolume *mv : print_object.model_object()->volumes)
|
|
|
|
|
if (mv->is_model_part()) {
|
|
|
|
|
const Transform3f tr = print_object.trafo().cast<float>() * mv->get_matrix().cast<float>();
|
|
|
|
|
|
|
|
|
|
for (size_t extruder_idx = 0; extruder_idx < num_extruders; ++extruder_idx) {
|
|
|
|
|
const indexed_triangle_set custom_facets = mv->mmu_segmentation_facets.get_facets(*mv, EnforcerBlockerType(extruder_idx));
|
|
|
|
|
if (custom_facets.indices.empty())
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
throw_on_cancel_callback();
|
|
|
|
|
for (size_t facet_idx = 0; facet_idx < custom_facets.indices.size(); ++facet_idx) {
|
|
|
|
|
float min_z = std::numeric_limits<float>::max();
|
|
|
|
|
float max_z = std::numeric_limits<float>::lowest();
|
|
|
|
|
|
|
|
|
|
std::array<Vec3f, 3> facet;
|
|
|
|
|
for (int p_idx = 0; p_idx < 3; ++p_idx) {
|
|
|
|
|
facet[p_idx] = tr * custom_facets.vertices[custom_facets.indices[facet_idx](p_idx)];
|
|
|
|
|
max_z = std::max(max_z, facet[p_idx].z());
|
|
|
|
|
min_z = std::min(min_z, facet[p_idx].z());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Sort the vertices by z-axis for simplification of projected_facet on slices
|
|
|
|
|
std::sort(facet.begin(), facet.end(), [](const Vec3f &p1, const Vec3f &p2) { return p1.z() < p2.z(); });
|
|
|
|
|
projected_facet.clear();
|
|
|
|
|
projected_facet.reserve(3);
|
|
|
|
|
for (int p_idx = 0; p_idx < 3; ++p_idx)
|
|
|
|
|
projected_facet.emplace_back(Point(scale_(facet[p_idx].x()), scale_(facet[p_idx].y())) - print_object.center_offset());
|
|
|
|
|
if (cross2((projected_facet[1] - projected_facet[0]).cast<int64_t>(), (projected_facet[2] - projected_facet[1]).cast<int64_t>()) < 0)
|
|
|
|
|
// Make CCW.
|
|
|
|
|
std::swap(projected_facet[1], projected_facet[2]);
|
|
|
|
|
ClipperLib::Path offsetted = mittered_offset_path_scaled(projected_facet, deltas, 3.);
|
|
|
|
|
|
|
|
|
|
// Find lowest slice not below the triangle.
|
|
|
|
|
auto first_layer = std::upper_bound(layers.begin(), layers.end(), float(min_z - EPSILON),
|
|
|
|
|
[](float z, const Layer *l1) { return z < l1->slice_z + l1->height * 0.5; });
|
|
|
|
|
auto last_layer = std::upper_bound(layers.begin(), layers.end(), float(max_z - EPSILON),
|
|
|
|
|
[](float z, const Layer *l1) { return z < l1->slice_z + l1->height * 0.5; });
|
|
|
|
|
|
|
|
|
|
if (last_layer == layers.end())
|
|
|
|
|
--last_layer;
|
|
|
|
|
|
|
|
|
|
if (first_layer == layers.end() || (first_layer != layers.begin() && facet[0].z() < (*first_layer)->print_z - EPSILON))
|
|
|
|
|
--first_layer;
|
|
|
|
|
|
|
|
|
|
for (auto layer_it = first_layer; (layer_it != (last_layer + 1) && layer_it != layers.end()); ++layer_it)
|
|
|
|
|
if (size_t layer_idx = layer_it - layers.begin(); ! top_layers[layer_idx].empty() || ! bottom_layers[layer_idx].empty())
|
|
|
|
|
triangles_by_color_raw[extruder_idx][layer_idx].emplace_back(offsetted);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - top and bottom layers - projection of painted triangles - end";
|
|
|
|
|
|
|
|
|
|
std::vector<std::vector<ExPolygons>> triangles_by_color(num_extruders, std::vector<ExPolygons>(layers.size()));
|
|
|
|
|
tbb::parallel_for(tbb::blocked_range<size_t>(0, num_layers), [&](const tbb::blocked_range<size_t> &range) {
|
|
|
|
|
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) {
|
|
|
|
|
throw_on_cancel_callback();
|
|
|
|
|
float offset_factor = 0.1f * float(scale_(get_extrusion_width(layer_idx)));
|
|
|
|
|
for (size_t extruder_id = 0; extruder_id < num_extruders; ++ extruder_id)
|
|
|
|
|
if (ClipperLib::Paths &src_paths = triangles_by_color_raw[extruder_id][layer_idx]; !src_paths.empty())
|
|
|
|
|
triangles_by_color[extruder_id][layer_idx] = offset_ex(offset_ex(ClipperPaths_to_Slic3rExPolygons(src_paths), -offset_factor), offset_factor);
|
|
|
|
|
}
|
|
|
|
|
}); // end of parallel_for
|
|
|
|
|
triangles_by_color_raw.clear();
|
|
|
|
|
|
|
|
|
|
std::vector<std::vector<ExPolygons>> triangles_by_color_bottom(num_extruders);
|
|
|
|
|
std::vector<std::vector<ExPolygons>> triangles_by_color_top(num_extruders);
|
|
|
|
|
triangles_by_color_bottom.assign(num_extruders, std::vector<ExPolygons>(num_layers));
|
|
|
|
|
triangles_by_color_top.assign(num_extruders, std::vector<ExPolygons>(num_layers));
|
|
|
|
|
|
|
|
|
|
BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - segmentation of top layer - begin";
|
|
|
|
|
for (size_t layer_idx = 0; layer_idx < num_layers; ++layer_idx) {
|
|
|
|
|
float extrusion_width = scale_(get_extrusion_width(layer_idx));
|
|
|
|
|
int top_solid_layers = get_top_solid_layers(layer_idx);
|
|
|
|
|
ExPolygons top_expolygon = top_layers[layer_idx];
|
|
|
|
|
if (top_expolygon.empty())
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
for (size_t color_idx = 0; color_idx < triangles_by_color.size(); ++color_idx) {
|
|
|
|
|
throw_on_cancel_callback();
|
|
|
|
|
if (triangles_by_color[color_idx][layer_idx].empty())
|
|
|
|
|
continue;
|
|
|
|
|
ExPolygons intersection_poly = intersection_ex(triangles_by_color[color_idx][layer_idx], top_expolygon);
|
|
|
|
|
if (!intersection_poly.empty()) {
|
|
|
|
|
triangles_by_color_top[color_idx][layer_idx].insert(triangles_by_color_top[color_idx][layer_idx].end(), intersection_poly.begin(),
|
|
|
|
|
intersection_poly.end());
|
|
|
|
|
for (int last_idx = int(layer_idx) - 1; last_idx >= std::max(int(layer_idx - top_solid_layers), int(0)); --last_idx) {
|
|
|
|
|
float offset_value = float(layer_idx - last_idx) * (-1.0f) * extrusion_width;
|
|
|
|
|
if (offset_ex(top_expolygon, offset_value).empty())
|
|
|
|
|
continue;
|
|
|
|
|
ExPolygons layer_slices_trimmed = input_expolygons[last_idx];
|
|
|
|
|
|
|
|
|
|
for (int last_idx_1 = last_idx; last_idx_1 < int(layer_idx); ++last_idx_1) {
|
|
|
|
|
layer_slices_trimmed = intersection_ex(layer_slices_trimmed, input_expolygons[last_idx_1 + 1]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ExPolygons offset_e = offset_ex(layer_slices_trimmed, offset_value);
|
|
|
|
|
ExPolygons intersection_poly_2 = intersection_ex(triangles_by_color_top[color_idx][layer_idx], offset_e);
|
|
|
|
|
triangles_by_color_top[color_idx][last_idx].insert(triangles_by_color_top[color_idx][last_idx].end(), intersection_poly_2.begin(),
|
|
|
|
|
intersection_poly_2.end());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - segmentation of top layer - end";
|
|
|
|
|
|
|
|
|
|
BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - segmentation of bottom layer - begin";
|
|
|
|
|
for (size_t layer_idx = 0; layer_idx < num_layers; ++layer_idx) {
|
|
|
|
|
float extrusion_width = scale_(get_extrusion_width(layer_idx));
|
|
|
|
|
int bottom_solid_layers = get_bottom_solid_layers(layer_idx);
|
|
|
|
|
const ExPolygons &bottom_expolygon = bottom_layers[layer_idx];
|
|
|
|
|
if (bottom_expolygon.empty())
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
for (size_t color_idx = 0; color_idx < triangles_by_color.size(); ++color_idx) {
|
|
|
|
|
throw_on_cancel_callback();
|
|
|
|
|
if (triangles_by_color[color_idx][layer_idx].empty())
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
ExPolygons intersection_poly = intersection_ex(triangles_by_color[color_idx][layer_idx], bottom_expolygon);
|
|
|
|
|
if (!intersection_poly.empty()) {
|
|
|
|
|
triangles_by_color_bottom[color_idx][layer_idx].insert(triangles_by_color_bottom[color_idx][layer_idx].end(), intersection_poly.begin(),
|
|
|
|
|
intersection_poly.end());
|
|
|
|
|
for (size_t last_idx = layer_idx + 1; last_idx < std::min(layer_idx + bottom_solid_layers, num_layers); ++last_idx) {
|
|
|
|
|
float offset_value = float(last_idx - layer_idx) * (-1.0f) * extrusion_width;
|
|
|
|
|
if (offset_ex(bottom_expolygon, offset_value).empty())
|
|
|
|
|
continue;
|
|
|
|
|
ExPolygons layer_slices_trimmed = input_expolygons[last_idx];
|
|
|
|
|
for (int last_idx_1 = int(last_idx); last_idx_1 > int(layer_idx); --last_idx_1) {
|
|
|
|
|
layer_slices_trimmed = intersection_ex(layer_slices_trimmed, offset_ex(input_expolygons[last_idx_1 - 1], offset_value));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ExPolygons offset_e = offset_ex(layer_slices_trimmed, offset_value);
|
|
|
|
|
ExPolygons intersection_poly_2 = intersection_ex(triangles_by_color_bottom[color_idx][layer_idx], offset_e);
|
|
|
|
|
append(triangles_by_color_bottom[color_idx][last_idx], std::move(intersection_poly_2));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - segmentation of bottom layer - end";
|
|
|
|
|
|
|
|
|
|
std::vector<std::vector<ExPolygons>> triangles_by_color_merged(num_extruders);
|
|
|
|
|
triangles_by_color_merged.assign(num_extruders, std::vector<ExPolygons>(num_layers));
|
|
|
|
|
for (size_t layer_idx = 0; layer_idx < num_layers; ++layer_idx) {
|
|
|
|
|
throw_on_cancel_callback();
|
|
|
|
|
for (size_t color_idx = 0; color_idx < triangles_by_color_merged.size(); ++color_idx) {
|
|
|
|
|
auto &self = triangles_by_color_merged[color_idx][layer_idx];
|
|
|
|
|
append(self, std::move(triangles_by_color_bottom[color_idx][layer_idx]));
|
|
|
|
|
append(self, std::move(triangles_by_color_top[color_idx][layer_idx]));
|
|
|
|
|
self = union_ex(self);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Cut all colors for cases when two colors are overlapping
|
|
|
|
|
for (size_t color_idx = 1; color_idx < triangles_by_color_merged.size(); ++color_idx) {
|
|
|
|
|
triangles_by_color_merged[color_idx][layer_idx] = diff_ex(triangles_by_color_merged[color_idx][layer_idx],
|
|
|
|
|
triangles_by_color_merged[color_idx - 1][layer_idx]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
|
|
// Maximum number of top / bottom layers accounts for maximum overlap of one thread group into a neighbor thread group.
|
|
|
|
|
int max_top_layers = 0;
|
|
|
|
|
int max_bottom_layers = 0;
|
|
|
|
|
@@ -1470,8 +1255,7 @@ static inline std::vector<std::vector<ExPolygons>> mmu_segmentation_top_and_bott
|
|
|
|
|
// project downards pointing painted triangles over bottom surfaces.
|
|
|
|
|
std::vector<std::vector<Polygons>> top_raw(num_extruders), bottom_raw(num_extruders);
|
|
|
|
|
std::vector<float> zs = zs_from_layers(print_object.layers());
|
|
|
|
|
Transform3d object_trafo = print_object.trafo();
|
|
|
|
|
object_trafo.pretranslate(Vec3d(- unscale<double>(print_object.center_offset().x()), - unscale<double>(print_object.center_offset().y()), 0));
|
|
|
|
|
Transform3d object_trafo = print_object.trafo_centered();
|
|
|
|
|
|
|
|
|
|
#ifdef MMU_SEGMENTATION_DEBUG_TOP_BOTTOM
|
|
|
|
|
static int iRun = 0;
|
|
|
|
|
@@ -1650,7 +1434,6 @@ static inline std::vector<std::vector<ExPolygons>> mmu_segmentation_top_and_bott
|
|
|
|
|
triangles_by_color_merged[color_idx - 1][layer_idx]);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
return triangles_by_color_merged;
|
|
|
|
|
}
|
|
|
|
|
|