Skip to content

Commit

Permalink
Fix mmu paint
Browse files Browse the repository at this point in the history
  • Loading branch information
supermerill committed Sep 12, 2022
1 parent eb80cbc commit 9d2ccf1
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 19 deletions.
5 changes: 5 additions & 0 deletions src/libslic3r/EdgeGrid.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,11 @@ class Grid
assert(m_bbox.contains(p2));
p1 -= m_bbox.min;
p2 -= m_bbox.min;
assert(std::abs(p1.x()) < coord_t(int32_t(0x7FFFFFFF)));
assert(std::abs(p1.y()) < coord_t(int32_t(0x7FFFFFFF)));
assert(std::abs(p2.x()) < coord_t(int32_t(0x7FFFFFFF)));
assert(std::abs(p2.y()) < coord_t(int32_t(0x7FFFFFFF)));
assert(p1.x() >= 0 && p1.x() < coord_t(m_cols) * m_resolution);
assert(p1.x() >= 0 && p1.x() < coord_t(m_cols) * m_resolution);
assert(p1.y() >= 0 && p1.y() < coord_t(m_rows) * m_resolution);
assert(p2.x() >= 0 && p2.x() < coord_t(m_cols) * m_resolution);
Expand Down
4 changes: 4 additions & 0 deletions src/libslic3r/Model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2093,6 +2093,10 @@ indexed_triangle_set FacetsAnnotation::get_facets(const ModelVolume& mv, Enforce
selector.deserialize(m_data, false);
return selector.get_facets(type);
}
void FacetsAnnotation::set_facets_selector(TriangleSelector& selector) const
{
selector.deserialize(m_data, false);
}

indexed_triangle_set FacetsAnnotation::get_facets_strict(const ModelVolume& mv, EnforcerBlockerType type) const
{
Expand Down
1 change: 1 addition & 0 deletions src/libslic3r/Model.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,7 @@ class FacetsAnnotation final : public ObjectWithTimestamp {
const std::pair<std::vector<std::pair<int, int>>, std::vector<bool>>& get_data() const throw() { return m_data; }
bool set(const TriangleSelector& selector);
indexed_triangle_set get_facets(const ModelVolume& mv, EnforcerBlockerType type) const;
void set_facets_selector(TriangleSelector& selector) const;
indexed_triangle_set get_facets_strict(const ModelVolume& mv, EnforcerBlockerType type) const;
bool has_facets(const ModelVolume& mv, EnforcerBlockerType type) const;
bool empty() const { return m_data.first.empty(); }
Expand Down
45 changes: 26 additions & 19 deletions src/libslic3r/MultiMaterialSegmentation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "Geometry/VoronoiVisualUtils.hpp"
#include "MutablePolygon.hpp"
#include "format.hpp"
#include "TriangleSelector.hpp"

#include <utility>
#include <cfloat>
Expand Down Expand Up @@ -98,6 +99,7 @@ struct PaintedLineVisitor
const Vec2d v1 = line_to_test.vector().cast<double>();
const double v1_sqr_norm = v1.squaredNorm();
const double heuristic_thr_part = line_to_test.length() + append_threshold;
double min_res = std::max(Slic3r::sqr(resolution), append_threshold_sqr);
for (auto it_contour_and_segment = cell_data_range.first; it_contour_and_segment != cell_data_range.second; ++it_contour_and_segment) {
Line grid_line = grid.line(*it_contour_and_segment);
const Vec2d v2 = grid_line.vector().cast<double>();
Expand All @@ -110,15 +112,14 @@ struct PaintedLineVisitor
(grid_line.a - line_to_test.b).cast<double>().squaredNorm() > heuristic_thr_sqr ||
(grid_line.b - line_to_test.b).cast<double>().squaredNorm() > heuristic_thr_sqr)
continue;

// When lines have too different length, it is necessary to normalize them
if (Slic3r::sqr(v1.dot(v2)) > cos_threshold2 * v1_sqr_norm * v2.squaredNorm()) {
// The two vectors are nearly collinear (their mutual angle is lower than 30 degrees)
if (painted_lines_set.find(*it_contour_and_segment) == painted_lines_set.end()) {
if (grid_line.distance_to_squared(line_to_test.a) < append_threshold2 ||
grid_line.distance_to_squared(line_to_test.b) < append_threshold2 ||
line_to_test.distance_to_squared(grid_line.a) < append_threshold2 ||
line_to_test.distance_to_squared(grid_line.b) < append_threshold2) {
if (grid_line.distance_to_squared(line_to_test.a) < min_res ||
grid_line.distance_to_squared(line_to_test.b) < min_res ||
line_to_test.distance_to_squared(grid_line.a) < min_res ||
line_to_test.distance_to_squared(grid_line.b) < min_res) {
Line line_to_test_projected;
project_line_on_line(grid_line, line_to_test, &line_to_test_projected);

Expand All @@ -144,10 +145,11 @@ struct PaintedLineVisitor
Line line_to_test;
std::unordered_set<std::pair<size_t, size_t>, boost::hash<std::pair<size_t, size_t>>> painted_lines_set;
int color = -1;
double resolution = 50 * SCALED_EPSILON;

static inline const double cos_threshold2 = Slic3r::sqr(cos(M_PI * 30. / 180.));
static inline const double append_threshold = 50 * SCALED_EPSILON;
static inline const double append_threshold2 = Slic3r::sqr(append_threshold);
static inline const double append_threshold_sqr = Slic3r::sqr(append_threshold);
};

static Polygon colored_points_to_polygon(const std::vector<ColoredLine> &lines)
Expand Down Expand Up @@ -1428,9 +1430,9 @@ static inline std::vector<std::vector<ExPolygons>> mmu_segmentation_top_and_bott
// Number of regions for a queried color.
int num_regions { 0 };
// Maximum perimeter extrusion width for a queried color.
float extrusion_width { 0.f };
coordf_t extrusion_width { 0.f };
// Minimum radius of a region to be printable. Used to filter regions by morphological opening.
float small_region_threshold { 0.f };
coordf_t small_region_threshold { 0.f };
// Maximum number of top layers for a queried color.
int top_solid_layers { 0 };
// Maximum number of bottom layers for a queried color.
Expand All @@ -1444,19 +1446,20 @@ static inline std::vector<std::vector<ExPolygons>> mmu_segmentation_top_and_bott
// color_idx == 0 means "don't know" extruder aka the underlying extruder.
// As this region may split existing regions, we collect statistics over all regions for color_idx == 0.
color_idx == 0 || config.perimeter_extruder == int(color_idx)) {
out.extrusion_width = std::max<float>(out.extrusion_width, float(config.perimeter_extrusion_width));
double perimeter_extrusion_width = config.get_computed_value("perimeter_extrusion_width");
out.extrusion_width = std::max<double>(out.extrusion_width, perimeter_extrusion_width);
out.top_solid_layers = std::max<int>(out.top_solid_layers, config.top_solid_layers);
out.bottom_solid_layers = std::max<int>(out.bottom_solid_layers, config.bottom_solid_layers);
out.small_region_threshold = config.gap_fill_enabled.value && config.gap_fill_speed.value > 0 ?
out.small_region_threshold = config.gap_fill_enabled.value ?
// Gap fill enabled. Enable a single line of 1/2 extrusion width.
0.5f * float(config.perimeter_extrusion_width) :
0.5f * (perimeter_extrusion_width) :
// Gap fill disabled. Enable two lines slightly overlapping.
float(config.perimeter_extrusion_width) + 0.7f * Flow::rounded_rectangle_extrusion_spacing(float(config.perimeter_extrusion_width), float(layer.height), 1.f);
out.small_region_threshold = scaled<float>(out.small_region_threshold * 0.5f);
(perimeter_extrusion_width) + 0.7f * Flow::rounded_rectangle_extrusion_spacing(perimeter_extrusion_width, float(layer.height), 1.f);
out.small_region_threshold = scale_d(out.small_region_threshold * 0.5f);
++ out.num_regions;
}
assert(out.num_regions > 0);
out.extrusion_width = scaled<float>(out.extrusion_width);
out.extrusion_width = scale_d(out.extrusion_width);
return out;
};

Expand Down Expand Up @@ -1624,7 +1627,7 @@ void export_processed_input_expolygons_to_svg(const std::string &path, const Lay
::Slic3r::SVG svg(path.c_str(), bbox);

for (LayerRegion *region : regions)
svg.draw_outline(region->slices.surfaces, "blue", "cyan", stroke_width);
svg.draw_outline(region->slices().surfaces, "blue", "cyan", stroke_width);

svg.draw_outline(processed_input_expolygons, "red", "pink", stroke_width);
}
Expand Down Expand Up @@ -1688,6 +1691,7 @@ std::vector<std::vector<ExPolygons>> multi_material_segmentation_by_painting(con
std::vector<EdgeGrid::Grid> edge_grids(num_layers);
const ConstLayerPtrsAdaptor layers = print_object.layers();
std::vector<ExPolygons> input_expolygons(num_layers);
coord_t resolution = scale_t(print_object.config().option("resolution")->getFloat());

throw_on_cancel_callback();

Expand Down Expand Up @@ -1747,15 +1751,18 @@ std::vector<std::vector<ExPolygons>> multi_material_segmentation_by_painting(con

BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - projection of painted triangles - begin";
for (const ModelVolume *mv : print_object.model_object()->volumes) {
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) {
//can reuse the TriangleSelector for each extruder_idx
TriangleSelector tri_selector(mv->mesh());
mv->mmu_segmentation_facets.set_facets_selector(tri_selector);
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, &resolution, &tri_selector , &throw_on_cancel_callback](const tbb::blocked_range<size_t> &range) {
for (size_t extruder_idx = range.begin(); extruder_idx < range.end(); ++extruder_idx) {
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 = tri_selector.get_facets(EnforcerBlockerType(extruder_idx));
if (!mv->is_model_part() || custom_facets.indices.empty())
continue;

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, &layers, &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, &resolution](const tbb::blocked_range<size_t> &range) {
for (size_t facet_idx = range.begin(); facet_idx < range.end(); ++facet_idx) {
float min_z = std::numeric_limits<float>::max();
float max_z = std::numeric_limits<float>::lowest();
Expand Down Expand Up @@ -1822,7 +1829,7 @@ std::vector<std::vector<ExPolygons>> multi_material_segmentation_by_painting(con
edge_grids[layer_idx].visit_cells_intersecting_line(line_to_test.a, line_to_test.b, visitor);
}
}
}); // end of parallel_for
}); // end of parallel_for
}
}); // end of parallel_for
}
Expand Down

0 comments on commit 9d2ccf1

Please sign in to comment.