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)
|
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); }
|
{ 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)
|
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); }
|
{ 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)
|
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.
|
// 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::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::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::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);
|
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_support_points = rhs.sla_support_points;
|
||||||
this->sla_points_status = rhs.sla_points_status;
|
this->sla_points_status = rhs.sla_points_status;
|
||||||
this->sla_drain_holes = rhs.sla_drain_holes;
|
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->layer_height_profile = rhs.layer_height_profile;
|
||||||
this->printable = rhs.printable;
|
this->printable = rhs.printable;
|
||||||
this->origin_translation = rhs.origin_translation;
|
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_support_points = std::move(rhs.sla_support_points);
|
||||||
this->sla_points_status = std::move(rhs.sla_points_status);
|
this->sla_points_status = std::move(rhs.sla_points_status);
|
||||||
this->sla_drain_holes = std::move(rhs.sla_drain_holes);
|
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->layer_height_profile = std::move(rhs.layer_height_profile);
|
||||||
this->origin_translation = std::move(rhs.origin_translation);
|
this->origin_translation = std::move(rhs.origin_translation);
|
||||||
m_bounding_box = std::move(rhs.m_bounding_box);
|
m_bounding_box = std::move(rhs.m_bounding_box);
|
||||||
|
|
|
@ -645,15 +645,13 @@ bool verify_update_print_object_regions(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify and / or update PrintRegions produced by color painting.
|
// Verify and / or update PrintRegions produced by color painting.
|
||||||
for (const PrintObjectRegions::LayerRangeRegions &layer_range : print_object_regions.layer_ranges) {
|
for (const PrintObjectRegions::LayerRangeRegions &layer_range : print_object_regions.layer_ranges)
|
||||||
size_t painted_region_idx = 0;
|
for (const PrintObjectRegions::PaintedRegion ®ion : layer_range.painted_regions) {
|
||||||
for (unsigned int painted_extruder_id : painting_extruders)
|
const PrintObjectRegions::VolumeRegion &parent_region = layer_range.volume_regions[region.parent];
|
||||||
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();
|
PrintRegionConfig cfg = parent_region.region->config();
|
||||||
cfg.perimeter_extruder.value = painted_extruder_id;
|
cfg.perimeter_extruder.value = region.extruder_id;
|
||||||
cfg.infill_extruder.value = painted_extruder_id;
|
cfg.solid_infill_extruder.value = region.extruder_id;
|
||||||
|
cfg.infill_extruder.value = region.extruder_id;
|
||||||
if (cfg != region.region->config()) {
|
if (cfg != region.region->config()) {
|
||||||
// Region configuration changed.
|
// Region configuration changed.
|
||||||
if (print_region_ref_cnt(*region.region) == 0) {
|
if (print_region_ref_cnt(*region.region) == 0) {
|
||||||
|
@ -669,7 +667,6 @@ bool verify_update_print_object_regions(
|
||||||
}
|
}
|
||||||
print_region_ref_inc(*region.region);
|
print_region_ref_inc(*region.region);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Lastly verify, whether some regions were not merged.
|
// Lastly verify, whether some regions were not merged.
|
||||||
{
|
{
|
||||||
|
@ -855,16 +852,23 @@ static PrintObjectRegions* generate_print_object_regions(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally add painting 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 (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)
|
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];
|
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()) {
|
parent_region.model_volume->is_model_part() || parent_region.model_volume->is_modifier()) {
|
||||||
PrintRegionConfig cfg = parent_region.region->config();
|
PrintRegionConfig cfg = parent_region.region->config();
|
||||||
cfg.perimeter_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;
|
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))});
|
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();
|
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 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) ||
|
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);
|
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 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;
|
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);
|
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
|
// 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 = print_objects_range.begin()->print_object->m_shared_regions;
|
||||||
model_object_status.print_object_regions->ref_cnt_inc();
|
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)) {
|
! 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.
|
// 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 ?
|
model_object_status.print_object_regions_status = model_origin_translation_differ || layer_height_ranges_differ ?
|
||||||
|
@ -1229,7 +1234,6 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
||||||
// All regions now have distinct settings.
|
// All regions now have distinct settings.
|
||||||
// Check whether applying the new region config defaults we would get different regions,
|
// Check whether applying the new region config defaults we would get different regions,
|
||||||
// update regions or create regions from scratch.
|
// 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();) {
|
for (auto it_print_object = m_objects.begin(); it_print_object != m_objects.end();) {
|
||||||
// Find the range of PrintObjects sharing the same associated ModelObject.
|
// Find the range of PrintObjects sharing the same associated ModelObject.
|
||||||
auto it_print_object_end = it_print_object;
|
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;
|
model_object_status.print_object_regions = print_object_regions;
|
||||||
print_object_regions->ref_cnt_inc();
|
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) {
|
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.
|
// 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))
|
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 "Geometry.hpp"
|
||||||
#include "I18N.hpp"
|
#include "I18N.hpp"
|
||||||
#include "Layer.hpp"
|
#include "Layer.hpp"
|
||||||
#include "MultiMaterialSegmentation.hpp"
|
|
||||||
#include "SupportMaterial.hpp"
|
#include "SupportMaterial.hpp"
|
||||||
#include "Surface.hpp"
|
#include "Surface.hpp"
|
||||||
#include "Slicing.hpp"
|
#include "Slicing.hpp"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "ElephantFootCompensation.hpp"
|
#include "ElephantFootCompensation.hpp"
|
||||||
#include "I18N.hpp"
|
#include "I18N.hpp"
|
||||||
#include "Layer.hpp"
|
#include "Layer.hpp"
|
||||||
|
#include "MultiMaterialSegmentation.hpp"
|
||||||
#include "Print.hpp"
|
#include "Print.hpp"
|
||||||
|
|
||||||
#include <boost/log/trivial.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)
|
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() ||
|
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());
|
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(
|
static std::vector<std::vector<ExPolygons>> slices_to_regions(
|
||||||
ModelVolumePtrs model_volumes,
|
ModelVolumePtrs model_volumes,
|
||||||
const PrintObjectRegions &print_object_regions,
|
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]
|
[&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) {
|
(const tbb::blocked_range<size_t> &range) {
|
||||||
float z = zs_complex[range.begin()].second;
|
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(),
|
auto it_layer_range = layer_range_first(print_object_regions.layer_ranges, z);
|
||||||
[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);
|
|
||||||
// Per volume_regions slices at this Z height.
|
// Per volume_regions slices at this Z height.
|
||||||
struct RegionSlice {
|
struct RegionSlice {
|
||||||
ExPolygons expolygons;
|
ExPolygons expolygons;
|
||||||
|
@ -328,9 +347,7 @@ static std::vector<std::vector<ExPolygons>> slices_to_regions(
|
||||||
std::vector<RegionSlice> temp_slices;
|
std::vector<RegionSlice> temp_slices;
|
||||||
for (size_t zs_complex_idx = range.begin(); zs_complex_idx < range.end(); ++ zs_complex_idx) {
|
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];
|
auto [z_idx, z] = zs_complex[zs_complex_idx];
|
||||||
for (; it_layer_range->layer_height_range.second <= z; ++ it_layer_range)
|
it_layer_range = layer_range_next(print_object_regions.layer_ranges, it_layer_range, z);
|
||||||
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);
|
|
||||||
const PrintObjectRegions::LayerRangeRegions &layer_range = *it_layer_range;
|
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()];
|
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();
|
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";
|
BOOST_LOG_TRIVIAL(debug) << "Slicing volumes - removing top empty layers";
|
||||||
while (! m_layers.empty()) {
|
while (! m_layers.empty()) {
|
||||||
const Layer *layer = m_layers.back();
|
const Layer *layer = m_layers.back();
|
||||||
|
@ -638,6 +604,124 @@ void PrintObject::slice_volumes()
|
||||||
m_layers.back()->upper_layer = nullptr;
|
m_layers.back()->upper_layer = nullptr;
|
||||||
m_print->throw_if_canceled();
|
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";
|
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.
|
// 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;
|
ExPolygons lslices_1st_layer;
|
||||||
tbb::parallel_for(
|
tbb::parallel_for(
|
||||||
tbb::blocked_range<size_t>(0, m_layers.size()),
|
tbb::blocked_range<size_t>(0, m_layers.size()),
|
||||||
[this, xy_compensation_scaled, elephant_foot_compensation_scaled, &lslices_1st_layer]
|
[this, xy_compensation_scaled, elephant_foot_compensation_scaled, &lslices_1st_layer](const tbb::blocked_range<size_t>& range) {
|
||||||
(const tbb::blocked_range<size_t>& range) {
|
|
||||||
for (size_t layer_id = range.begin(); layer_id < range.end(); ++ layer_id) {
|
for (size_t layer_id = range.begin(); layer_id < range.end(); ++ layer_id) {
|
||||||
m_print->throw_if_canceled();
|
m_print->throw_if_canceled();
|
||||||
Layer *layer = m_layers[layer_id];
|
Layer *layer = m_layers[layer_id];
|
||||||
|
|
Loading…
Reference in a new issue