WIP: Integration of MMU painting into the slicing back-end.
This commit is contained in:
parent
9e4d483453
commit
b5aa09e5ba
6 changed files with 191 additions and 95 deletions
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 ®ion = 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 ®ion : 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))
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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 ®ion = 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];
|
||||
|
|
Loading…
Reference in a new issue