Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorVojtech Bubnik <bubnikv@gmail.com>2021-05-27 15:29:51 +0300
committerVojtech Bubnik <bubnikv@gmail.com>2021-05-27 15:29:51 +0300
commitb5aa09e5ba88a5429bcec293b259908abba2af20 (patch)
tree0af721b2860347afd097962c2ef4e58715bb549a /src
parent9e4d483453a720591e4ae9044114c2abaa2d12d0 (diff)
WIP: Integration of MMU painting into the slicing back-end.
Diffstat (limited to 'src')
-rw-r--r--src/libslic3r/ClipperUtils.cpp2
-rw-r--r--src/libslic3r/ClipperUtils.hpp1
-rw-r--r--src/libslic3r/Model.cpp4
-rw-r--r--src/libslic3r/PrintApply.cpp69
-rw-r--r--src/libslic3r/PrintObject.cpp1
-rw-r--r--src/libslic3r/PrintObjectSlice.cpp209
6 files changed, 191 insertions, 95 deletions
diff --git a/src/libslic3r/ClipperUtils.cpp b/src/libslic3r/ClipperUtils.cpp
index a49665ae5..7216c7509 100644
--- a/src/libslic3r/ClipperUtils.cpp
+++ b/src/libslic3r/ClipperUtils.cpp
@@ -461,6 +461,8 @@ static inline Polygons _clipper(ClipperLib::ClipType clipType, TSubj &&subject,
Slic3r::Polygons diff(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, ApplySafetyOffset do_safety_offset)
{ return _clipper(ClipperLib::ctDifference, ClipperUtils::PolygonsProvider(subject), ClipperUtils::PolygonsProvider(clip), do_safety_offset); }
+Slic3r::Polygons diff(const Slic3r::Polygons &subject, const Slic3r::ExPolygons &clip, ApplySafetyOffset do_safety_offset)
+ { return _clipper(ClipperLib::ctDifference, ClipperUtils::PolygonsProvider(subject), ClipperUtils::ExPolygonsProvider(clip), do_safety_offset); }
Slic3r::Polygons diff(const Slic3r::ExPolygons &subject, const Slic3r::Polygons &clip, ApplySafetyOffset do_safety_offset)
{ return _clipper(ClipperLib::ctDifference, ClipperUtils::ExPolygonsProvider(subject), ClipperUtils::PolygonsProvider(clip), do_safety_offset); }
Slic3r::Polygons diff(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, ApplySafetyOffset do_safety_offset)
diff --git a/src/libslic3r/ClipperUtils.hpp b/src/libslic3r/ClipperUtils.hpp
index fc9677d8b..061658086 100644
--- a/src/libslic3r/ClipperUtils.hpp
+++ b/src/libslic3r/ClipperUtils.hpp
@@ -296,6 +296,7 @@ Slic3r::Lines _clipper_ln(ClipperLib::ClipType clipType, const Slic3r::Lines &su
// Safety offset is applied to the clipping polygons only.
Slic3r::Polygons diff(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No);
+Slic3r::Polygons diff(const Slic3r::Polygons &subject, const Slic3r::ExPolygons &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No);
Slic3r::Polygons diff(const Slic3r::ExPolygons &subject, const Slic3r::Polygons &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No);
Slic3r::Polygons diff(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No);
Slic3r::ExPolygons diff_ex(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No);
diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp
index 018754bc0..e68eb7b6d 100644
--- a/src/libslic3r/Model.cpp
+++ b/src/libslic3r/Model.cpp
@@ -561,7 +561,7 @@ ModelObject& ModelObject::assign_copy(const ModelObject &rhs)
this->sla_support_points = rhs.sla_support_points;
this->sla_points_status = rhs.sla_points_status;
this->sla_drain_holes = rhs.sla_drain_holes;
- this->layer_config_ranges = rhs.layer_config_ranges; // #ys_FIXME_experiment
+ this->layer_config_ranges = rhs.layer_config_ranges;
this->layer_height_profile = rhs.layer_height_profile;
this->printable = rhs.printable;
this->origin_translation = rhs.origin_translation;
@@ -602,7 +602,7 @@ ModelObject& ModelObject::assign_copy(ModelObject &&rhs)
this->sla_support_points = std::move(rhs.sla_support_points);
this->sla_points_status = std::move(rhs.sla_points_status);
this->sla_drain_holes = std::move(rhs.sla_drain_holes);
- this->layer_config_ranges = std::move(rhs.layer_config_ranges); // #ys_FIXME_experiment
+ this->layer_config_ranges = std::move(rhs.layer_config_ranges);
this->layer_height_profile = std::move(rhs.layer_height_profile);
this->origin_translation = std::move(rhs.origin_translation);
m_bounding_box = std::move(rhs.m_bounding_box);
diff --git a/src/libslic3r/PrintApply.cpp b/src/libslic3r/PrintApply.cpp
index 6b6b94f7d..46af1fee8 100644
--- a/src/libslic3r/PrintApply.cpp
+++ b/src/libslic3r/PrintApply.cpp
@@ -645,31 +645,28 @@ bool verify_update_print_object_regions(
}
// Verify and / or update PrintRegions produced by color painting.
- for (const PrintObjectRegions::LayerRangeRegions &layer_range : print_object_regions.layer_ranges) {
- size_t painted_region_idx = 0;
- for (unsigned int painted_extruder_id : painting_extruders)
- for (int parent_region_id = 0; parent_region_id < int(layer_range.volume_regions.size()); ++ parent_region_id) {
- const PrintObjectRegions::VolumeRegion &parent_region = layer_range.volume_regions[parent_region_id];
- const PrintObjectRegions::PaintedRegion &region = layer_range.painted_regions[painted_region_idx ++];
- PrintRegionConfig cfg = parent_region.region->config();
- cfg.perimeter_extruder.value = painted_extruder_id;
- cfg.infill_extruder.value = painted_extruder_id;
- if (cfg != region.region->config()) {
- // Region configuration changed.
- if (print_region_ref_cnt(*region.region) == 0) {
- // Region is referenced for the first time. Just change its parameters.
- // Stop the background process before assigning new configuration to the regions.
- t_config_option_keys diff = region.region->config().diff(cfg);
- callback_invalidate(region.region->config(), cfg, diff);
- region.region->config_apply_only(cfg, diff, false);
- } else {
- // Region is referenced multiple times, thus the region is being split. We need to reslice.
- return false;
- }
+ for (const PrintObjectRegions::LayerRangeRegions &layer_range : print_object_regions.layer_ranges)
+ for (const PrintObjectRegions::PaintedRegion &region : layer_range.painted_regions) {
+ const PrintObjectRegions::VolumeRegion &parent_region = layer_range.volume_regions[region.parent];
+ PrintRegionConfig cfg = parent_region.region->config();
+ cfg.perimeter_extruder.value = region.extruder_id;
+ cfg.solid_infill_extruder.value = region.extruder_id;
+ cfg.infill_extruder.value = region.extruder_id;
+ if (cfg != region.region->config()) {
+ // Region configuration changed.
+ if (print_region_ref_cnt(*region.region) == 0) {
+ // Region is referenced for the first time. Just change its parameters.
+ // Stop the background process before assigning new configuration to the regions.
+ t_config_option_keys diff = region.region->config().diff(cfg);
+ callback_invalidate(region.region->config(), cfg, diff);
+ region.region->config_apply_only(cfg, diff, false);
+ } else {
+ // Region is referenced multiple times, thus the region is being split. We need to reslice.
+ return false;
}
- print_region_ref_inc(*region.region);
}
- }
+ print_region_ref_inc(*region.region);
+ }
// Lastly verify, whether some regions were not merged.
{
@@ -855,16 +852,23 @@ static PrintObjectRegions* generate_print_object_regions(
}
// Finally add painting regions.
- for (PrintObjectRegions::LayerRangeRegions &layer_range : layer_ranges_regions)
+ for (PrintObjectRegions::LayerRangeRegions &layer_range : layer_ranges_regions) {
for (unsigned int painted_extruder_id : painting_extruders)
for (int parent_region_id = 0; parent_region_id < int(layer_range.volume_regions.size()); ++ parent_region_id)
if (const PrintObjectRegions::VolumeRegion &parent_region = layer_range.volume_regions[parent_region_id];
parent_region.model_volume->is_model_part() || parent_region.model_volume->is_modifier()) {
PrintRegionConfig cfg = parent_region.region->config();
- cfg.perimeter_extruder.value = painted_extruder_id;
- cfg.infill_extruder.value = painted_extruder_id;
+ cfg.perimeter_extruder.value = painted_extruder_id;
+ cfg.solid_infill_extruder.value = painted_extruder_id;
+ cfg.infill_extruder.value = painted_extruder_id;
layer_range.painted_regions.push_back({ painted_extruder_id, parent_region_id, get_create_region(std::move(cfg))});
}
+ // Sort the regions by parent region::print_object_region_id() and extruder_id to help the slicing algorithm when applying MMU segmentation.
+ std::sort(layer_range.painted_regions.begin(), layer_range.painted_regions.end(), [&layer_range](auto &l, auto &r) {
+ int lid = layer_range.volume_regions[l.parent].region->print_object_region_id();
+ int rid = layer_range.volume_regions[r.parent].region->print_object_region_id();
+ return lid < rid || (lid == rid && l.extruder_id < r.extruder_id); });
+ }
return out.release();
}
@@ -1049,6 +1053,7 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
bool solid_or_modifier_differ = model_volume_list_changed(model_object, model_object_new, solid_or_modifier_types);
bool supports_differ = model_volume_list_changed(model_object, model_object_new, ModelVolumeType::SUPPORT_BLOCKER) ||
model_volume_list_changed(model_object, model_object_new, ModelVolumeType::SUPPORT_ENFORCER);
+ bool mmu_segmentation_differ = model_mmu_segmentation_data_changed(model_object, model_object_new);
bool layer_height_ranges_differ = ! layer_height_ranges_equal(model_object.layer_config_ranges, model_object_new.layer_config_ranges, model_object_new.layer_height_profile.empty());
bool model_origin_translation_differ = model_object.origin_translation != model_object_new.origin_translation;
auto print_objects_range = print_object_status_db.get_range(model_object);
@@ -1056,7 +1061,7 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
// All PrintObjects in print_objects_range shall point to the same prints_objects_regions
model_object_status.print_object_regions = print_objects_range.begin()->print_object->m_shared_regions;
model_object_status.print_object_regions->ref_cnt_inc();
- if (solid_or_modifier_differ || model_origin_translation_differ || layer_height_ranges_differ ||
+ if (solid_or_modifier_differ || mmu_segmentation_differ || model_origin_translation_differ || layer_height_ranges_differ ||
! model_object.layer_height_profile.timestamp_matches(model_object_new.layer_height_profile)) {
// The very first step (the slicing step) is invalidated. One may freely remove all associated PrintObjects.
model_object_status.print_object_regions_status = model_origin_translation_differ || layer_height_ranges_differ ?
@@ -1075,7 +1080,7 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
model_object_status.print_object_regions->clear();
// Copy content of the ModelObject including its ID, do not change the parent.
model_object.assign_copy(model_object_new);
- } else {
+ } else {
model_object_status.print_object_regions_status = ModelObjectStatus::PrintObjectRegionsStatus::Valid;
if (supports_differ || model_custom_supports_data_changed(model_object, model_object_new)) {
// First stop background processing before shuffling or deleting the ModelVolumes in the ModelObject's list.
@@ -1229,7 +1234,6 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
// All regions now have distinct settings.
// Check whether applying the new region config defaults we would get different regions,
// update regions or create regions from scratch.
- const std::vector<unsigned int> painting_extruders;
for (auto it_print_object = m_objects.begin(); it_print_object != m_objects.end();) {
// Find the range of PrintObjects sharing the same associated ModelObject.
auto it_print_object_end = it_print_object;
@@ -1244,6 +1248,13 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
model_object_status.print_object_regions = print_object_regions;
print_object_regions->ref_cnt_inc();
}
+ std::vector<unsigned int> painting_extruders;
+ if (const auto &volumes = print_object.model_object()->volumes;
+ std::find_if(volumes.begin(), volumes.end(), [](const ModelVolume *v) { return ! v->mmu_segmentation_facets.empty(); }) != volumes.end()) {
+ //FIXME be more specific! Don't enumerate extruders that are not used for painting!
+ painting_extruders.assign(num_extruders, 0);
+ std::iota(painting_extruders.begin(), painting_extruders.end(), 1);
+ }
if (model_object_status.print_object_regions_status == ModelObjectStatus::PrintObjectRegionsStatus::Valid) {
// Verify that the trafo for regions & volume bounding boxes thus for regions is still applicable.
if (print_object_regions && ! trafos_differ_in_rotation_by_z_and_mirroring_by_xy_only(print_object_regions->trafo_bboxes, model_object_status.print_instances.front().trafo))
diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp
index df635a249..e69edd051 100644
--- a/src/libslic3r/PrintObject.cpp
+++ b/src/libslic3r/PrintObject.cpp
@@ -6,7 +6,6 @@
#include "Geometry.hpp"
#include "I18N.hpp"
#include "Layer.hpp"
-#include "MultiMaterialSegmentation.hpp"
#include "SupportMaterial.hpp"
#include "Surface.hpp"
#include "Slicing.hpp"
diff --git a/src/libslic3r/PrintObjectSlice.cpp b/src/libslic3r/PrintObjectSlice.cpp
index a64cedd03..f44d6fdbf 100644
--- a/src/libslic3r/PrintObjectSlice.cpp
+++ b/src/libslic3r/PrintObjectSlice.cpp
@@ -1,6 +1,7 @@
#include "ElephantFootCompensation.hpp"
#include "I18N.hpp"
#include "Layer.hpp"
+#include "MultiMaterialSegmentation.hpp"
#include "Print.hpp"
#include <boost/log/trivial.hpp>
@@ -221,10 +222,34 @@ static inline VolumeSlices& volume_slices_find_by_id(std::vector<VolumeSlices> &
static inline bool overlap_in_xy(const BoundingBoxf3 &l, const BoundingBoxf3 &r)
{
+ assert(l.defined && r.defined);
return ! (l.max.x() < r.min.x() || l.min.x() > r.max.x() ||
l.max.y() < r.min.y() || l.min.y() > r.max.y());
}
+static std::vector<PrintObjectRegions::LayerRangeRegions>::const_iterator layer_range_first(const std::vector<PrintObjectRegions::LayerRangeRegions> &layer_ranges, double z)
+{
+ auto it = lower_bound_by_predicate(layer_ranges.begin(), layer_ranges.end(),
+ [z](const PrintObjectRegions::LayerRangeRegions &lr) { return lr.layer_height_range.second < z; });
+ assert(it != layer_ranges.end() && it->layer_height_range.first <= z && z <= it->layer_height_range.second);
+ if (z == it->layer_height_range.second)
+ if (auto it_next = it; ++ it_next != layer_ranges.end() && it_next->layer_height_range.first == z)
+ it = it_next;
+ assert(it != layer_ranges.end() && it->layer_height_range.first <= z && z <= it->layer_height_range.second);
+ return it;
+}
+
+static std::vector<PrintObjectRegions::LayerRangeRegions>::const_iterator layer_range_next(
+ const std::vector<PrintObjectRegions::LayerRangeRegions> &layer_ranges,
+ std::vector<PrintObjectRegions::LayerRangeRegions>::const_iterator it,
+ double z)
+{
+ for (; it->layer_height_range.second <= z; ++ it)
+ assert(it != layer_ranges.end());
+ assert(it != layer_ranges.end() && it->layer_height_range.first <= z && z < it->layer_height_range.second);
+ return it;
+}
+
static std::vector<std::vector<ExPolygons>> slices_to_regions(
ModelVolumePtrs model_volumes,
const PrintObjectRegions &print_object_regions,
@@ -304,13 +329,7 @@ static std::vector<std::vector<ExPolygons>> slices_to_regions(
[&slices_by_region, &print_object_regions, &zs_complex, &layer_ranges_regions_to_slices, clip_multipart_objects, &throw_on_cancel_callback]
(const tbb::blocked_range<size_t> &range) {
float z = zs_complex[range.begin()].second;
- auto it_layer_range = lower_bound_by_predicate(print_object_regions.layer_ranges.begin(), print_object_regions.layer_ranges.end(),
- [z](const PrintObjectRegions::LayerRangeRegions &lr){ return lr.layer_height_range.second < z; });
- assert(it_layer_range != print_object_regions.layer_ranges.end() && it_layer_range->layer_height_range.first <= z && z <= it_layer_range->layer_height_range.second);
- if (z == it_layer_range->layer_height_range.second)
- if (auto it_next = it_layer_range; ++ it_next != print_object_regions.layer_ranges.end() && it_next->layer_height_range.first == z)
- it_layer_range = it_next;
- assert(it_layer_range != print_object_regions.layer_ranges.end() && it_layer_range->layer_height_range.first <= z && z <= it_layer_range->layer_height_range.second);
+ auto it_layer_range = layer_range_first(print_object_regions.layer_ranges, z);
// Per volume_regions slices at this Z height.
struct RegionSlice {
ExPolygons expolygons;
@@ -328,9 +347,7 @@ static std::vector<std::vector<ExPolygons>> slices_to_regions(
std::vector<RegionSlice> temp_slices;
for (size_t zs_complex_idx = range.begin(); zs_complex_idx < range.end(); ++ zs_complex_idx) {
auto [z_idx, z] = zs_complex[zs_complex_idx];
- for (; it_layer_range->layer_height_range.second <= z; ++ it_layer_range)
- assert(it_layer_range != print_object_regions.layer_ranges.end());
- assert(it_layer_range != print_object_regions.layer_ranges.end() && it_layer_range->layer_height_range.first <= z && z < it_layer_range->layer_height_range.second);
+ it_layer_range = layer_range_next(print_object_regions.layer_ranges, it_layer_range, z);
const PrintObjectRegions::LayerRangeRegions &layer_range = *it_layer_range;
{
std::vector<VolumeSlices*> &layer_range_regions_to_slices = layer_ranges_regions_to_slices[it_layer_range - print_object_regions.layer_ranges.begin()];
@@ -575,57 +592,6 @@ void PrintObject::slice_volumes()
}
region_slices.clear();
-#if 0
- // Second clip the volumes in the order they are presented at the user interface.
- BOOST_LOG_TRIVIAL(debug) << "Slicing volumes - parallel clipping - start";
- tbb::parallel_for(
- tbb::blocked_range<size_t>(0, slice_zs.size()),
- [this, &sliced_volumes, num_modifiers](const tbb::blocked_range<size_t>& range) {
- float delta = float(scale_(m_config.xy_size_compensation.value));
- // Only upscale together with clipping if there are no modifiers, as the modifiers shall be applied before upscaling
- // (upscaling may grow the object outside of the modifier mesh).
- bool upscale = delta > 0 && num_modifiers == 0;
- for (size_t layer_id = range.begin(); layer_id < range.end(); ++ layer_id) {
- m_print->throw_if_canceled();
- // Trim volumes in a single layer, one by the other, possibly apply upscaling.
- {
- Polygons processed;
- for (SlicedVolume &sliced_volume : sliced_volumes)
- if (! sliced_volume.expolygons_by_layer.empty()) {
- ExPolygons slices = std::move(sliced_volume.expolygons_by_layer[layer_id]);
- if (upscale)
- slices = offset_ex(std::move(slices), delta);
- if (! processed.empty())
- // Trim by the slices of already processed regions.
- slices = diff_ex(slices, processed);
- if (size_t(&sliced_volume - &sliced_volumes.front()) + 1 < sliced_volumes.size())
- // Collect the already processed regions to trim the to be processed regions.
- polygons_append(processed, slices);
- sliced_volume.expolygons_by_layer[layer_id] = std::move(slices);
- }
- }
- // Collect and union volumes of a single region.
- for (int region_id = 0; region_id < int(m_region_volumes.size()); ++ region_id) {
- ExPolygons expolygons;
- size_t num_volumes = 0;
- for (SlicedVolume &sliced_volume : sliced_volumes)
- if (sliced_volume.region_id == region_id && ! sliced_volume.expolygons_by_layer.empty() && ! sliced_volume.expolygons_by_layer[layer_id].empty()) {
- ++ num_volumes;
- append(expolygons, std::move(sliced_volume.expolygons_by_layer[layer_id]));
- }
- if (num_volumes > 1)
- // Merge the islands using a positive / negative offset.
- expolygons = offset_ex(offset_ex(expolygons, float(scale_(EPSILON))), -float(scale_(EPSILON)));
- m_layers[layer_id]->regions()[region_id]->slices.append(std::move(expolygons), stInternal);
- }
- }
- });
- BOOST_LOG_TRIVIAL(debug) << "Slicing volumes - parallel clipping - end";
- clipped = true;
- upscaled = m_config.xy_size_compensation.value > 0 && num_modifiers == 0;
- }
-#endif
-
BOOST_LOG_TRIVIAL(debug) << "Slicing volumes - removing top empty layers";
while (! m_layers.empty()) {
const Layer *layer = m_layers.back();
@@ -638,6 +604,124 @@ void PrintObject::slice_volumes()
m_layers.back()->upper_layer = nullptr;
m_print->throw_if_canceled();
+ // Is any ModelVolume MMU painted?
+ if (const auto &volumes = this->model_object()->volumes;
+ std::find_if(volumes.begin(), volumes.end(), [](const ModelVolume *v) { return ! v->mmu_segmentation_facets.empty(); }) != volumes.end()) {
+ BOOST_LOG_TRIVIAL(debug) << "Slicing volumes - MMU segmentation";
+ // 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(*this);
+ assert(segmentation.size() == m_layers.size());
+ tbb::parallel_for(
+ tbb::blocked_range<size_t>(0, segmentation.size(), std::max(segmentation.size() / 128, size_t(1))),
+ [this, &segmentation](const tbb::blocked_range<size_t> &range) {
+ const auto &layer_ranges = this->m_shared_regions->layer_ranges;
+ double z = m_layers[range.begin()]->slice_z;
+ auto it_layer_range = layer_range_first(layer_ranges, z);
+ const size_t num_extruders = this->print()->config().nozzle_diameter.size();
+ struct ByExtruder {
+ ExPolygons expolygons;
+ BoundingBox bbox;
+ };
+ std::vector<ByExtruder> by_extruder;
+ struct ByRegion {
+ ExPolygons expolygons;
+ bool needs_merge { false };
+ };
+ std::vector<ByRegion> by_region;
+ for (size_t layer_id = range.begin(); layer_id < range.end(); ++ layer_id) {
+ m_print->throw_if_canceled();
+ Layer *layer = m_layers[layer_id];
+ it_layer_range = layer_range_next(layer_ranges, it_layer_range, layer->slice_z);
+ const PrintObjectRegions::LayerRangeRegions &layer_range = *it_layer_range;
+ // Gather per extruder expolygons.
+ by_extruder.assign(num_extruders, ByExtruder());
+ by_region.assign(layer->m_regions.size(), ByRegion());
+ bool layer_split = false;
+ for (size_t extruder_id = 0; extruder_id < num_extruders; ++ extruder_id) {
+ ByExtruder &region = by_extruder[extruder_id];
+ for (const std::pair<ExPolygon, size_t> &colored_polygon : segmentation[layer_id])
+ if (colored_polygon.second == extruder_id)
+ region.expolygons.emplace_back(std::move(colored_polygon.first));
+ if (! region.expolygons.empty()) {
+ region.bbox = get_extents(region.expolygons);
+ layer_split = true;
+ }
+ }
+ if (! layer_split)
+ continue;
+ // Split LayerRegions by by_extruder regions.
+ auto it_painted_region = layer_range.painted_regions.begin();
+ for (size_t region_id = 0; region_id < layer->m_regions.size(); ++ region_id)
+ if (LayerRegion &layerm = *layer->m_regions[region_id]; ! layerm.slices.surfaces.empty()) {
+ const BoundingBox bbox = get_extents(layerm.slices.surfaces);
+ assert(it_painted_region < layer_range.painted_regions.end());
+ for (; layer_range.volume_regions[it_painted_region->parent].region->print_object_region_id() < region_id; ++ it_painted_region)
+ assert(it_painted_region < layer_range.painted_regions.end());
+ assert(&layerm.region() == it_painted_region->region && layerm.region().print_object_region_id() == region_id);
+ // 1-based extruder ID
+ bool self_trimmed = false;
+ size_t self_extruder_id;
+ for (size_t extruder_id = 1; extruder_id <= by_extruder.size(); ++ extruder_id)
+ if (ByExtruder &segmented = by_extruder[extruder_id - 1]; segmented.bbox.defined && bbox.overlap(segmented.bbox)) {
+ // Find the target region.
+ for (; it_painted_region->extruder_id < extruder_id; ++ it_painted_region)
+ assert(it_painted_region < layer_range.painted_regions.end());
+ assert(layer_range.volume_regions[it_painted_region->parent].region == &layerm.region() && it_painted_region->extruder_id == extruder_id);
+ //FIXME Don't trim by self, it is not reliable.
+ if (&layerm.region() == it_painted_region->region) {
+ self_extruder_id = extruder_id;
+ continue;
+ }
+ // Steal from this region.
+ int target_region_id = it_painted_region->region->print_object_region_id();
+ ExPolygons stolen = intersection_ex(layerm.slices.surfaces, segmented.expolygons);
+ if (! stolen.empty()) {
+ ByRegion &dst = by_region[target_region_id];
+ if (dst.expolygons.empty()) {
+ dst.expolygons = std::move(stolen);
+ } else {
+ append(dst.expolygons, std::move(stolen));
+ dst.needs_merge = true;
+ }
+ }
+#if 0
+ if (&layerm.region() == it_painted_region->region)
+ // Slices of this LayerRegion were trimmed by a MMU region of the same PrintRegion.
+ self_trimmed = true;
+#endif
+ }
+ if (! self_trimmed) {
+ // Trim slices of this LayerRegion with all the MMU regions.
+ Polygons mine = to_polygons(std::move(layerm.slices.surfaces));
+ for (auto &segmented : by_extruder)
+ if (&segmented - by_extruder.data() + 1 != self_extruder_id && segmented.bbox.defined && bbox.overlap(segmented.bbox)) {
+ mine = diff(mine, segmented.expolygons);
+ if (mine.empty())
+ break;
+ }
+ if (! mine.empty()) {
+ ByRegion &dst = by_region[layerm.region().print_object_region_id()];
+ if (dst.expolygons.empty()) {
+ dst.expolygons = union_ex(mine);
+ } else {
+ append(dst.expolygons, union_ex(mine));
+ dst.needs_merge = true;
+ }
+ }
+ }
+ }
+ // Re-create Surfaces of LayerRegions.
+ for (size_t region_id = 0; region_id < layer->m_regions.size(); ++ region_id) {
+ ByRegion &src = by_region[region_id];
+ if (src.needs_merge)
+ // Multiple regions were merged into one.
+ src.expolygons = offset2_ex(src.expolygons, float(scale_(EPSILON)), - float(scale_(EPSILON)));
+ layer->m_regions[region_id]->slices.set(std::move(src.expolygons), stInternal);
+ }
+ }
+ });
+ }
+
BOOST_LOG_TRIVIAL(debug) << "Slicing volumes - make_slices in parallel - begin";
{
// Compensation value, scaled. Only applying the negative scaling here, as the positive scaling has already been applied during slicing.
@@ -650,8 +734,7 @@ void PrintObject::slice_volumes()
ExPolygons lslices_1st_layer;
tbb::parallel_for(
tbb::blocked_range<size_t>(0, m_layers.size()),
- [this, xy_compensation_scaled, elephant_foot_compensation_scaled, &lslices_1st_layer]
- (const tbb::blocked_range<size_t>& range) {
+ [this, xy_compensation_scaled, elephant_foot_compensation_scaled, &lslices_1st_layer](const tbb::blocked_range<size_t>& range) {
for (size_t layer_id = range.begin(); layer_id < range.end(); ++ layer_id) {
m_print->throw_if_canceled();
Layer *layer = m_layers[layer_id];