mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-20 21:27:52 -06:00
Fixed conflicts after merge with master
This commit is contained in:
commit
f786d9c96e
174 changed files with 9811 additions and 5525 deletions
|
@ -97,6 +97,15 @@ PrintBase::ApplyStatus PrintObject::set_instances(PrintInstances &&instances)
|
|||
return status;
|
||||
}
|
||||
|
||||
std::vector<std::reference_wrapper<const PrintRegion>> PrintObject::all_regions() const
|
||||
{
|
||||
std::vector<std::reference_wrapper<const PrintRegion>> out;
|
||||
out.reserve(m_all_regions.size());
|
||||
for (size_t i = 0; i < m_all_regions.size(); ++ i)
|
||||
out.emplace_back(*m_all_regions[i]);
|
||||
return out;
|
||||
}
|
||||
|
||||
// Called by make_perimeters()
|
||||
// 1) Decides Z positions of the layers,
|
||||
// 2) Initializes layers and their regions
|
||||
|
@ -173,8 +182,8 @@ void PrintObject::make_perimeters()
|
|||
// but we don't generate any extra perimeter if fill density is zero, as they would be floating
|
||||
// inside the object - infill_only_where_needed should be the method of choice for printing
|
||||
// hollow objects
|
||||
for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) {
|
||||
const PrintRegion ®ion = *m_print->regions()[region_id];
|
||||
for (size_t region_id = 0; region_id < this->num_printing_regions(); ++ region_id) {
|
||||
const PrintRegion ®ion = this->printing_region(region_id);
|
||||
if (! region.config().extra_perimeters || region.config().perimeters == 0 || region.config().fill_density == 0 || this->layer_count() < 2)
|
||||
continue;
|
||||
|
||||
|
@ -186,7 +195,7 @@ void PrintObject::make_perimeters()
|
|||
m_print->throw_if_canceled();
|
||||
LayerRegion &layerm = *m_layers[layer_idx]->m_regions[region_id];
|
||||
const LayerRegion &upper_layerm = *m_layers[layer_idx+1]->m_regions[region_id];
|
||||
const Polygons upper_layerm_polygons = upper_layerm.slices;
|
||||
const Polygons upper_layerm_polygons = to_polygons(upper_layerm.slices.surfaces);
|
||||
// Filter upper layer polygons in intersection_ppl by their bounding boxes?
|
||||
// my $upper_layerm_poly_bboxes= [ map $_->bounding_box, @{$upper_layerm_polygons} ];
|
||||
const double total_loop_length = total_length(upper_layerm_polygons);
|
||||
|
@ -294,7 +303,7 @@ void PrintObject::prepare_infill()
|
|||
|
||||
// Debugging output.
|
||||
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
||||
for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) {
|
||||
for (size_t region_id = 0; region_id < this->num_printing_regions(); ++ region_id) {
|
||||
for (const Layer *layer : m_layers) {
|
||||
LayerRegion *layerm = layer->m_regions[region_id];
|
||||
layerm->export_region_slices_to_svg_debug("6_discover_vertical_shells-final");
|
||||
|
@ -313,7 +322,7 @@ void PrintObject::prepare_infill()
|
|||
m_print->throw_if_canceled();
|
||||
|
||||
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
||||
for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) {
|
||||
for (size_t region_id = 0; region_id < this->num_printing_regions(); ++ region_id) {
|
||||
for (const Layer *layer : m_layers) {
|
||||
LayerRegion *layerm = layer->m_regions[region_id];
|
||||
layerm->export_region_slices_to_svg_debug("7_discover_horizontal_shells-final");
|
||||
|
@ -332,7 +341,7 @@ void PrintObject::prepare_infill()
|
|||
m_print->throw_if_canceled();
|
||||
|
||||
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
||||
for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) {
|
||||
for (size_t region_id = 0; region_id < this->num_printing_regions(); ++ region_id) {
|
||||
for (const Layer *layer : m_layers) {
|
||||
LayerRegion *layerm = layer->m_regions[region_id];
|
||||
layerm->export_region_slices_to_svg_debug("8_clip_surfaces-final");
|
||||
|
@ -351,7 +360,7 @@ void PrintObject::prepare_infill()
|
|||
m_print->throw_if_canceled();
|
||||
|
||||
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
||||
for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) {
|
||||
for (size_t region_id = 0; region_id < this->num_printing_regions(); ++ region_id) {
|
||||
for (const Layer *layer : m_layers) {
|
||||
LayerRegion *layerm = layer->m_regions[region_id];
|
||||
layerm->export_region_slices_to_svg_debug("9_prepare_infill-final");
|
||||
|
@ -716,10 +725,10 @@ bool PrintObject::invalidate_step(PrintObjectStep step)
|
|||
} else if (step == posSlice) {
|
||||
invalidated |= this->invalidate_steps({ posPerimeters, posPrepareInfill, posInfill, posIroning, posSupportMaterial });
|
||||
invalidated |= m_print->invalidate_steps({ psSkirt, psBrim });
|
||||
this->m_slicing_params.valid = false;
|
||||
m_slicing_params.valid = false;
|
||||
} else if (step == posSupportMaterial) {
|
||||
invalidated |= m_print->invalidate_steps({ psSkirt, psBrim });
|
||||
this->m_slicing_params.valid = false;
|
||||
m_slicing_params.valid = false;
|
||||
}
|
||||
|
||||
// Wipe tower depends on the ordering of extruders, which in turn depends on everything.
|
||||
|
@ -736,19 +745,11 @@ bool PrintObject::invalidate_all_steps()
|
|||
// First call the "invalidate" functions, which may cancel background processing.
|
||||
bool result = Inherited::invalidate_all_steps() | m_print->invalidate_all_steps();
|
||||
// Then reset some of the depending values.
|
||||
this->m_slicing_params.valid = false;
|
||||
this->region_volumes.clear();
|
||||
m_slicing_params.valid = false;
|
||||
m_region_volumes.clear();
|
||||
return result;
|
||||
}
|
||||
|
||||
static const PrintRegion* first_printing_region(const PrintObject &print_object)
|
||||
{
|
||||
for (size_t idx_region = 0; idx_region < print_object.region_volumes.size(); ++ idx_region)
|
||||
if (!print_object.region_volumes.empty())
|
||||
return print_object.print()->regions()[idx_region];
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// This function analyzes slices of a region (SurfaceCollection slices).
|
||||
// Each region slice (instance of Surface) is analyzed, whether it is supported or whether it is the top surface.
|
||||
// Initially all slices are of type stInternal.
|
||||
|
@ -769,13 +770,13 @@ void PrintObject::detect_surfaces_type()
|
|||
// should be visible.
|
||||
bool spiral_vase = this->print()->config().spiral_vase.value;
|
||||
bool interface_shells = ! spiral_vase && m_config.interface_shells.value;
|
||||
size_t num_layers = spiral_vase ? std::min(size_t(first_printing_region(*this)->config().bottom_solid_layers), m_layers.size()) : m_layers.size();
|
||||
size_t num_layers = spiral_vase ? std::min(size_t(this->printing_region(0).config().bottom_solid_layers), m_layers.size()) : m_layers.size();
|
||||
|
||||
for (size_t idx_region = 0; idx_region < this->region_volumes.size(); ++ idx_region) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "Detecting solid surfaces for region " << idx_region << " in parallel - start";
|
||||
for (size_t region_id = 0; region_id < this->num_printing_regions(); ++ region_id) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "Detecting solid surfaces for region " << region_id << " in parallel - start";
|
||||
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
||||
for (Layer *layer : m_layers)
|
||||
layer->m_regions[idx_region]->export_region_fill_surfaces_to_svg_debug("1_detect_surfaces_type-initial");
|
||||
layer->m_regions[region_id]->export_region_fill_surfaces_to_svg_debug("1_detect_surfaces_type-initial");
|
||||
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
|
||||
|
||||
// If interface shells are allowed, the region->surfaces cannot be overwritten as they may be used by other threads.
|
||||
|
@ -791,7 +792,7 @@ void PrintObject::detect_surfaces_type()
|
|||
((num_layers > 1) ? num_layers - 1 : num_layers) :
|
||||
// In non-spiral vase mode, go over all layers.
|
||||
m_layers.size()),
|
||||
[this, idx_region, interface_shells, &surfaces_new](const tbb::blocked_range<size_t>& range) {
|
||||
[this, region_id, interface_shells, &surfaces_new](const tbb::blocked_range<size_t>& range) {
|
||||
// If we have soluble support material, don't bridge. The overhang will be squished against a soluble layer separating
|
||||
// the support from the print.
|
||||
SurfaceType surface_type_bottom_other =
|
||||
|
@ -799,9 +800,9 @@ void PrintObject::detect_surfaces_type()
|
|||
stBottom : stBottomBridge;
|
||||
for (size_t idx_layer = range.begin(); idx_layer < range.end(); ++ idx_layer) {
|
||||
m_print->throw_if_canceled();
|
||||
// BOOST_LOG_TRIVIAL(trace) << "Detecting solid surfaces for region " << idx_region << " and layer " << layer->print_z;
|
||||
// BOOST_LOG_TRIVIAL(trace) << "Detecting solid surfaces for region " << region_id << " and layer " << layer->print_z;
|
||||
Layer *layer = m_layers[idx_layer];
|
||||
LayerRegion *layerm = layer->m_regions[idx_region];
|
||||
LayerRegion *layerm = layer->m_regions[region_id];
|
||||
// comparison happens against the *full* slices (considering all regions)
|
||||
// unless internal shells are requested
|
||||
Layer *upper_layer = (idx_layer + 1 < this->layer_count()) ? m_layers[idx_layer + 1] : nullptr;
|
||||
|
@ -809,19 +810,14 @@ void PrintObject::detect_surfaces_type()
|
|||
// collapse very narrow parts (using the safety offset in the diff is not enough)
|
||||
float offset = layerm->flow(frExternalPerimeter).scaled_width() / 10.f;
|
||||
|
||||
Polygons layerm_slices_surfaces = to_polygons(layerm->slices.surfaces);
|
||||
|
||||
// find top surfaces (difference between current surfaces
|
||||
// of current layer and upper one)
|
||||
Surfaces top;
|
||||
if (upper_layer) {
|
||||
Polygons upper_slices = interface_shells ?
|
||||
to_polygons(upper_layer->m_regions[idx_region]->slices.surfaces) :
|
||||
to_polygons(upper_layer->lslices);
|
||||
surfaces_append(top,
|
||||
//FIXME implement offset2_ex working over ExPolygons, that should be a bit more efficient than calling offset_ex twice.
|
||||
offset_ex(offset_ex(diff_ex(layerm_slices_surfaces, upper_slices, true), -offset), offset),
|
||||
stTop);
|
||||
ExPolygons upper_slices = interface_shells ?
|
||||
diff_ex(layerm->slices.surfaces, upper_layer->m_regions[region_id]->slices.surfaces, ApplySafetyOffset::Yes) :
|
||||
diff_ex(layerm->slices.surfaces, upper_layer->lslices, ApplySafetyOffset::Yes);
|
||||
surfaces_append(top, offset2_ex(upper_slices, -offset, offset), stTop);
|
||||
} else {
|
||||
// if no upper layer, all surfaces of this one are solid
|
||||
// we clone surfaces because we're going to clear the slices collection
|
||||
|
@ -836,17 +832,17 @@ void PrintObject::detect_surfaces_type()
|
|||
#if 0
|
||||
//FIXME Why is this branch failing t\multi.t ?
|
||||
Polygons lower_slices = interface_shells ?
|
||||
to_polygons(lower_layer->get_region(idx_region)->slices.surfaces) :
|
||||
to_polygons(lower_layer->get_region(region_id)->slices.surfaces) :
|
||||
to_polygons(lower_layer->slices);
|
||||
surfaces_append(bottom,
|
||||
offset2_ex(diff(layerm_slices_surfaces, lower_slices, true), -offset, offset),
|
||||
offset2_ex(diff(layerm->slices.surfaces, lower_slices, true), -offset, offset),
|
||||
surface_type_bottom_other);
|
||||
#else
|
||||
// Any surface lying on the void is a true bottom bridge (an overhang)
|
||||
surfaces_append(
|
||||
bottom,
|
||||
offset2_ex(
|
||||
diff(layerm_slices_surfaces, to_polygons(lower_layer->lslices), true),
|
||||
diff_ex(layerm->slices.surfaces, lower_layer->lslices, ApplySafetyOffset::Yes),
|
||||
-offset, offset),
|
||||
surface_type_bottom_other);
|
||||
// if user requested internal shells, we need to identify surfaces
|
||||
|
@ -857,10 +853,10 @@ void PrintObject::detect_surfaces_type()
|
|||
surfaces_append(
|
||||
bottom,
|
||||
offset2_ex(
|
||||
diff(
|
||||
intersection(layerm_slices_surfaces, to_polygons(lower_layer->lslices)), // supported
|
||||
to_polygons(lower_layer->m_regions[idx_region]->slices.surfaces),
|
||||
true),
|
||||
diff_ex(
|
||||
intersection(layerm->slices.surfaces, lower_layer->lslices), // supported
|
||||
lower_layer->m_regions[region_id]->slices.surfaces,
|
||||
ApplySafetyOffset::Yes),
|
||||
-offset, offset),
|
||||
stBottom);
|
||||
}
|
||||
|
@ -882,9 +878,7 @@ void PrintObject::detect_surfaces_type()
|
|||
// if $Slic3r::debug;
|
||||
Polygons top_polygons = to_polygons(std::move(top));
|
||||
top.clear();
|
||||
surfaces_append(top,
|
||||
diff_ex(top_polygons, to_polygons(bottom), false),
|
||||
stTop);
|
||||
surfaces_append(top, diff_ex(top_polygons, bottom), stTop);
|
||||
}
|
||||
|
||||
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
||||
|
@ -894,21 +888,24 @@ void PrintObject::detect_surfaces_type()
|
|||
expolygons_with_attributes.emplace_back(std::make_pair(union_ex(top), SVG::ExPolygonAttributes("green")));
|
||||
expolygons_with_attributes.emplace_back(std::make_pair(union_ex(bottom), SVG::ExPolygonAttributes("brown")));
|
||||
expolygons_with_attributes.emplace_back(std::make_pair(to_expolygons(layerm->slices.surfaces), SVG::ExPolygonAttributes("black")));
|
||||
SVG::export_expolygons(debug_out_path("1_detect_surfaces_type_%d_region%d-layer_%f.svg", iRun ++, idx_region, layer->print_z).c_str(), expolygons_with_attributes);
|
||||
SVG::export_expolygons(debug_out_path("1_detect_surfaces_type_%d_region%d-layer_%f.svg", iRun ++, region_id, layer->print_z).c_str(), expolygons_with_attributes);
|
||||
}
|
||||
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
|
||||
|
||||
// save surfaces to layer
|
||||
Surfaces &surfaces_out = interface_shells ? surfaces_new[idx_layer] : layerm->slices.surfaces;
|
||||
surfaces_out.clear();
|
||||
Surfaces surfaces_backup;
|
||||
if (! interface_shells) {
|
||||
surfaces_backup = std::move(surfaces_out);
|
||||
surfaces_out.clear();
|
||||
}
|
||||
const Surfaces &surfaces_prev = interface_shells ? layerm->slices.surfaces : surfaces_backup;
|
||||
|
||||
// find internal surfaces (difference between top/bottom surfaces and others)
|
||||
{
|
||||
Polygons topbottom = to_polygons(top);
|
||||
polygons_append(topbottom, to_polygons(bottom));
|
||||
surfaces_append(surfaces_out,
|
||||
diff_ex(layerm_slices_surfaces, topbottom, false),
|
||||
stInternal);
|
||||
surfaces_append(surfaces_out, diff_ex(surfaces_prev, topbottom), stInternal);
|
||||
}
|
||||
|
||||
surfaces_append(surfaces_out, std::move(top));
|
||||
|
@ -928,25 +925,25 @@ void PrintObject::detect_surfaces_type()
|
|||
if (interface_shells) {
|
||||
// Move surfaces_new to layerm->slices.surfaces
|
||||
for (size_t idx_layer = 0; idx_layer < num_layers; ++ idx_layer)
|
||||
m_layers[idx_layer]->m_regions[idx_region]->slices.surfaces = std::move(surfaces_new[idx_layer]);
|
||||
m_layers[idx_layer]->m_regions[region_id]->slices.surfaces = std::move(surfaces_new[idx_layer]);
|
||||
}
|
||||
|
||||
if (spiral_vase) {
|
||||
if (num_layers > 1)
|
||||
// Turn the last bottom layer infill to a top infill, so it will be extruded with a proper pattern.
|
||||
m_layers[num_layers - 1]->m_regions[idx_region]->slices.set_type(stTop);
|
||||
m_layers[num_layers - 1]->m_regions[region_id]->slices.set_type(stTop);
|
||||
for (size_t i = num_layers; i < m_layers.size(); ++ i)
|
||||
m_layers[i]->m_regions[idx_region]->slices.set_type(stInternal);
|
||||
m_layers[i]->m_regions[region_id]->slices.set_type(stInternal);
|
||||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << "Detecting solid surfaces for region " << idx_region << " - clipping in parallel - start";
|
||||
BOOST_LOG_TRIVIAL(debug) << "Detecting solid surfaces for region " << region_id << " - clipping in parallel - start";
|
||||
// Fill in layerm->fill_surfaces by trimming the layerm->slices by the cummulative layerm->fill_surfaces.
|
||||
tbb::parallel_for(
|
||||
tbb::blocked_range<size_t>(0, m_layers.size()),
|
||||
[this, idx_region](const tbb::blocked_range<size_t>& range) {
|
||||
[this, region_id](const tbb::blocked_range<size_t>& range) {
|
||||
for (size_t idx_layer = range.begin(); idx_layer < range.end(); ++ idx_layer) {
|
||||
m_print->throw_if_canceled();
|
||||
LayerRegion *layerm = m_layers[idx_layer]->m_regions[idx_region];
|
||||
LayerRegion *layerm = m_layers[idx_layer]->m_regions[region_id];
|
||||
layerm->slices_to_fill_surfaces_clipped();
|
||||
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
||||
layerm->export_region_fill_surfaces_to_svg_debug("1_detect_surfaces_type-final");
|
||||
|
@ -954,7 +951,7 @@ void PrintObject::detect_surfaces_type()
|
|||
} // for each layer of a region
|
||||
});
|
||||
m_print->throw_if_canceled();
|
||||
BOOST_LOG_TRIVIAL(debug) << "Detecting solid surfaces for region " << idx_region << " - clipping in parallel - end";
|
||||
BOOST_LOG_TRIVIAL(debug) << "Detecting solid surfaces for region " << region_id << " - clipping in parallel - end";
|
||||
} // for each this->print->region_count
|
||||
|
||||
// Mark the object to have the region slices classified (typed, which also means they are split based on whether they are supported, bridging, top layers etc.)
|
||||
|
@ -970,8 +967,8 @@ void PrintObject::process_external_surfaces()
|
|||
// Is there any printing region, that has zero infill? If so, then we don't want the expansion to be performed over the complete voids, but only
|
||||
// over voids, which are supported by the layer below.
|
||||
bool has_voids = false;
|
||||
for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id)
|
||||
if (! this->region_volumes.empty() && this->print()->regions()[region_id]->config().fill_density == 0) {
|
||||
for (size_t region_id = 0; region_id < this->num_printing_regions(); ++ region_id)
|
||||
if (this->printing_region(region_id).config().fill_density == 0) {
|
||||
has_voids = true;
|
||||
break;
|
||||
}
|
||||
|
@ -1007,12 +1004,12 @@ void PrintObject::process_external_surfaces()
|
|||
m_print->throw_if_canceled();
|
||||
Polygons voids;
|
||||
for (const LayerRegion *layerm : m_layers[layer_idx]->regions()) {
|
||||
if (layerm->region()->config().fill_density.value == 0.)
|
||||
if (layerm->region().config().fill_density.value == 0.)
|
||||
for (const Surface &surface : layerm->fill_surfaces.surfaces)
|
||||
// Shrink the holes, let the layer above expand slightly inside the unsupported areas.
|
||||
polygons_append(voids, offset(surface.expolygon, unsupported_width));
|
||||
}
|
||||
surfaces_covered[layer_idx] = diff(to_polygons(this->m_layers[layer_idx]->lslices), voids);
|
||||
surfaces_covered[layer_idx] = diff(m_layers[layer_idx]->lslices, voids);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
@ -1020,7 +1017,7 @@ void PrintObject::process_external_surfaces()
|
|||
BOOST_LOG_TRIVIAL(debug) << "Collecting surfaces covered with extrusions in parallel - end";
|
||||
}
|
||||
|
||||
for (size_t region_id = 0; region_id < this->region_volumes.size(); ++region_id) {
|
||||
for (size_t region_id = 0; region_id < this->num_printing_regions(); ++region_id) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "Processing external surfaces for region " << region_id << " in parallel - start";
|
||||
tbb::parallel_for(
|
||||
tbb::blocked_range<size_t>(0, m_layers.size()),
|
||||
|
@ -1028,7 +1025,7 @@ void PrintObject::process_external_surfaces()
|
|||
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) {
|
||||
m_print->throw_if_canceled();
|
||||
// BOOST_LOG_TRIVIAL(trace) << "Processing external surface, layer" << m_layers[layer_idx]->print_z;
|
||||
m_layers[layer_idx]->get_region((int)region_id)->process_external_surfaces(
|
||||
m_layers[layer_idx]->get_region(int(region_id))->process_external_surfaces(
|
||||
(layer_idx == 0) ? nullptr : m_layers[layer_idx - 1],
|
||||
(layer_idx == 0 || surfaces_covered.empty() || surfaces_covered[layer_idx - 1].empty()) ? nullptr : &surfaces_covered[layer_idx - 1]);
|
||||
}
|
||||
|
@ -1053,7 +1050,7 @@ void PrintObject::discover_vertical_shells()
|
|||
Polygons holes;
|
||||
};
|
||||
bool spiral_vase = this->print()->config().spiral_vase.value;
|
||||
size_t num_layers = spiral_vase ? std::min(size_t(first_printing_region(*this)->config().bottom_solid_layers), m_layers.size()) : m_layers.size();
|
||||
size_t num_layers = spiral_vase ? std::min(size_t(this->printing_region(0).config().bottom_solid_layers), m_layers.size()) : m_layers.size();
|
||||
coordf_t min_layer_height = this->slicing_parameters().min_layer_height;
|
||||
// Does this region possibly produce more than 1 top or bottom layer?
|
||||
auto has_extra_layers_fn = [min_layer_height](const PrintRegionConfig &config) {
|
||||
|
@ -1068,14 +1065,14 @@ void PrintObject::discover_vertical_shells()
|
|||
num_extra_layers(config.bottom_solid_layers, config.bottom_solid_min_thickness) > 0;
|
||||
};
|
||||
std::vector<DiscoverVerticalShellsCacheEntry> cache_top_botom_regions(num_layers, DiscoverVerticalShellsCacheEntry());
|
||||
bool top_bottom_surfaces_all_regions = this->region_volumes.size() > 1 && ! m_config.interface_shells.value;
|
||||
bool top_bottom_surfaces_all_regions = this->num_printing_regions() > 1 && ! m_config.interface_shells.value;
|
||||
if (top_bottom_surfaces_all_regions) {
|
||||
// This is a multi-material print and interface_shells are disabled, meaning that the vertical shell thickness
|
||||
// is calculated over all materials.
|
||||
// Is the "ensure vertical wall thickness" applicable to any region?
|
||||
bool has_extra_layers = false;
|
||||
for (size_t idx_region = 0; idx_region < this->region_volumes.size(); ++idx_region) {
|
||||
const PrintRegionConfig &config = m_print->get_region(idx_region)->config();
|
||||
for (size_t region_id = 0; region_id < this->num_printing_regions(); ++region_id) {
|
||||
const PrintRegionConfig &config = this->printing_region(region_id).config();
|
||||
if (config.ensure_vertical_shell_thickness.value && has_extra_layers_fn(config)) {
|
||||
has_extra_layers = true;
|
||||
break;
|
||||
|
@ -1091,7 +1088,7 @@ void PrintObject::discover_vertical_shells()
|
|||
tbb::blocked_range<size_t>(0, num_layers, grain_size),
|
||||
[this, &cache_top_botom_regions](const tbb::blocked_range<size_t>& range) {
|
||||
const SurfaceType surfaces_bottom[2] = { stBottom, stBottomBridge };
|
||||
const size_t num_regions = this->region_volumes.size();
|
||||
const size_t num_regions = this->num_printing_regions();
|
||||
for (size_t idx_layer = range.begin(); idx_layer < range.end(); ++ idx_layer) {
|
||||
m_print->throw_if_canceled();
|
||||
const Layer &layer = *m_layers[idx_layer];
|
||||
|
@ -1103,21 +1100,21 @@ void PrintObject::discover_vertical_shells()
|
|||
static size_t debug_idx = 0;
|
||||
++ debug_idx;
|
||||
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
|
||||
for (size_t idx_region = 0; idx_region < num_regions; ++ idx_region) {
|
||||
LayerRegion &layerm = *layer.m_regions[idx_region];
|
||||
for (size_t region_id = 0; region_id < num_regions; ++ region_id) {
|
||||
LayerRegion &layerm = *layer.m_regions[region_id];
|
||||
float min_perimeter_infill_spacing = float(layerm.flow(frSolidInfill).scaled_spacing()) * 1.05f;
|
||||
// Top surfaces.
|
||||
append(cache.top_surfaces, offset(to_expolygons(layerm.slices.filter_by_type(stTop)), min_perimeter_infill_spacing));
|
||||
append(cache.top_surfaces, offset(to_expolygons(layerm.fill_surfaces.filter_by_type(stTop)), min_perimeter_infill_spacing));
|
||||
append(cache.top_surfaces, offset(layerm.slices.filter_by_type(stTop), min_perimeter_infill_spacing));
|
||||
append(cache.top_surfaces, offset(layerm.fill_surfaces.filter_by_type(stTop), min_perimeter_infill_spacing));
|
||||
// Bottom surfaces.
|
||||
append(cache.bottom_surfaces, offset(to_expolygons(layerm.slices.filter_by_types(surfaces_bottom, 2)), min_perimeter_infill_spacing));
|
||||
append(cache.bottom_surfaces, offset(to_expolygons(layerm.fill_surfaces.filter_by_types(surfaces_bottom, 2)), min_perimeter_infill_spacing));
|
||||
append(cache.bottom_surfaces, offset(layerm.slices.filter_by_types(surfaces_bottom, 2), min_perimeter_infill_spacing));
|
||||
append(cache.bottom_surfaces, offset(layerm.fill_surfaces.filter_by_types(surfaces_bottom, 2), min_perimeter_infill_spacing));
|
||||
// Calculate the maximum perimeter offset as if the slice was extruded with a single extruder only.
|
||||
// First find the maxium number of perimeters per region slice.
|
||||
unsigned int perimeters = 0;
|
||||
for (Surface &s : layerm.slices.surfaces)
|
||||
perimeters = std::max<unsigned int>(perimeters, s.extra_perimeters);
|
||||
perimeters += layerm.region()->config().perimeters.value;
|
||||
perimeters += layerm.region().config().perimeters.value;
|
||||
// Then calculate the infill offset.
|
||||
if (perimeters > 0) {
|
||||
Flow extflow = layerm.flow(frExternalPerimeter);
|
||||
|
@ -1129,8 +1126,8 @@ void PrintObject::discover_vertical_shells()
|
|||
polygons_append(cache.holes, to_polygons(layerm.fill_expolygons));
|
||||
}
|
||||
// Save some computing time by reducing the number of polygons.
|
||||
cache.top_surfaces = union_(cache.top_surfaces, false);
|
||||
cache.bottom_surfaces = union_(cache.bottom_surfaces, false);
|
||||
cache.top_surfaces = union_(cache.top_surfaces);
|
||||
cache.bottom_surfaces = union_(cache.bottom_surfaces);
|
||||
// For a multi-material print, simulate perimeter / infill split as if only a single extruder has been used for the whole print.
|
||||
if (perimeter_offset > 0.) {
|
||||
// The layer.lslices are forced to merge by expanding them first.
|
||||
|
@ -1145,17 +1142,17 @@ void PrintObject::discover_vertical_shells()
|
|||
}
|
||||
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
|
||||
}
|
||||
cache.holes = union_(cache.holes, false);
|
||||
cache.holes = union_(cache.holes);
|
||||
}
|
||||
});
|
||||
m_print->throw_if_canceled();
|
||||
BOOST_LOG_TRIVIAL(debug) << "Discovering vertical shells in parallel - end : cache top / bottom";
|
||||
}
|
||||
|
||||
for (size_t idx_region = 0; idx_region < this->region_volumes.size(); ++ idx_region) {
|
||||
for (size_t region_id = 0; region_id < this->num_printing_regions(); ++ region_id) {
|
||||
PROFILE_BLOCK(discover_vertical_shells_region);
|
||||
|
||||
const PrintRegion ®ion = *m_print->get_region(idx_region);
|
||||
const PrintRegion ®ion = this->printing_region(region_id);
|
||||
if (! region.config().ensure_vertical_shell_thickness.value)
|
||||
// This region will be handled by discover_horizontal_shells().
|
||||
continue;
|
||||
|
@ -1169,38 +1166,38 @@ void PrintObject::discover_vertical_shells()
|
|||
if (! top_bottom_surfaces_all_regions) {
|
||||
// This is either a single material print, or a multi-material print and interface_shells are enabled, meaning that the vertical shell thickness
|
||||
// is calculated over a single material.
|
||||
BOOST_LOG_TRIVIAL(debug) << "Discovering vertical shells for region " << idx_region << " in parallel - start : cache top / bottom";
|
||||
BOOST_LOG_TRIVIAL(debug) << "Discovering vertical shells for region " << region_id << " in parallel - start : cache top / bottom";
|
||||
tbb::parallel_for(
|
||||
tbb::blocked_range<size_t>(0, num_layers, grain_size),
|
||||
[this, idx_region, &cache_top_botom_regions](const tbb::blocked_range<size_t>& range) {
|
||||
[this, region_id, &cache_top_botom_regions](const tbb::blocked_range<size_t>& range) {
|
||||
const SurfaceType surfaces_bottom[2] = { stBottom, stBottomBridge };
|
||||
for (size_t idx_layer = range.begin(); idx_layer < range.end(); ++ idx_layer) {
|
||||
m_print->throw_if_canceled();
|
||||
Layer &layer = *m_layers[idx_layer];
|
||||
LayerRegion &layerm = *layer.m_regions[idx_region];
|
||||
LayerRegion &layerm = *layer.m_regions[region_id];
|
||||
float min_perimeter_infill_spacing = float(layerm.flow(frSolidInfill).scaled_spacing()) * 1.05f;
|
||||
// Top surfaces.
|
||||
auto &cache = cache_top_botom_regions[idx_layer];
|
||||
cache.top_surfaces = offset(to_expolygons(layerm.slices.filter_by_type(stTop)), min_perimeter_infill_spacing);
|
||||
append(cache.top_surfaces, offset(to_expolygons(layerm.fill_surfaces.filter_by_type(stTop)), min_perimeter_infill_spacing));
|
||||
cache.top_surfaces = offset(layerm.slices.filter_by_type(stTop), min_perimeter_infill_spacing);
|
||||
append(cache.top_surfaces, offset(layerm.fill_surfaces.filter_by_type(stTop), min_perimeter_infill_spacing));
|
||||
// Bottom surfaces.
|
||||
cache.bottom_surfaces = offset(to_expolygons(layerm.slices.filter_by_types(surfaces_bottom, 2)), min_perimeter_infill_spacing);
|
||||
append(cache.bottom_surfaces, offset(to_expolygons(layerm.fill_surfaces.filter_by_types(surfaces_bottom, 2)), min_perimeter_infill_spacing));
|
||||
// Holes over all regions. Only collect them once, they are valid for all idx_region iterations.
|
||||
cache.bottom_surfaces = offset(layerm.slices.filter_by_types(surfaces_bottom, 2), min_perimeter_infill_spacing);
|
||||
append(cache.bottom_surfaces, offset(layerm.fill_surfaces.filter_by_types(surfaces_bottom, 2), min_perimeter_infill_spacing));
|
||||
// Holes over all regions. Only collect them once, they are valid for all region_id iterations.
|
||||
if (cache.holes.empty()) {
|
||||
for (size_t idx_region = 0; idx_region < layer.regions().size(); ++ idx_region)
|
||||
polygons_append(cache.holes, to_polygons(layer.regions()[idx_region]->fill_expolygons));
|
||||
for (size_t region_id = 0; region_id < layer.regions().size(); ++ region_id)
|
||||
polygons_append(cache.holes, to_polygons(layer.regions()[region_id]->fill_expolygons));
|
||||
}
|
||||
}
|
||||
});
|
||||
m_print->throw_if_canceled();
|
||||
BOOST_LOG_TRIVIAL(debug) << "Discovering vertical shells for region " << idx_region << " in parallel - end : cache top / bottom";
|
||||
BOOST_LOG_TRIVIAL(debug) << "Discovering vertical shells for region " << region_id << " in parallel - end : cache top / bottom";
|
||||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << "Discovering vertical shells for region " << idx_region << " in parallel - start : ensure vertical wall thickness";
|
||||
BOOST_LOG_TRIVIAL(debug) << "Discovering vertical shells for region " << region_id << " in parallel - start : ensure vertical wall thickness";
|
||||
tbb::parallel_for(
|
||||
tbb::blocked_range<size_t>(0, num_layers, grain_size),
|
||||
[this, idx_region, &cache_top_botom_regions]
|
||||
[this, region_id, &cache_top_botom_regions]
|
||||
(const tbb::blocked_range<size_t>& range) {
|
||||
// printf("discover_vertical_shells from %d to %d\n", range.begin(), range.end());
|
||||
for (size_t idx_layer = range.begin(); idx_layer < range.end(); ++ idx_layer) {
|
||||
|
@ -1212,8 +1209,8 @@ void PrintObject::discover_vertical_shells()
|
|||
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
|
||||
|
||||
Layer *layer = m_layers[idx_layer];
|
||||
LayerRegion *layerm = layer->m_regions[idx_region];
|
||||
const PrintRegionConfig ®ion_config = layerm->region()->config();
|
||||
LayerRegion *layerm = layer->m_regions[region_id];
|
||||
const PrintRegionConfig ®ion_config = layerm->region().config();
|
||||
|
||||
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
||||
layerm->export_region_slices_to_svg_debug("4_discover_vertical_shells-initial");
|
||||
|
@ -1269,7 +1266,7 @@ void PrintObject::discover_vertical_shells()
|
|||
polygons_append(shell, cache.top_surfaces);
|
||||
// Running the union_ using the Clipper library piece by piece is cheaper
|
||||
// than running the union_ all at once.
|
||||
shell = union_(shell, false);
|
||||
shell = union_(shell);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1288,7 +1285,7 @@ void PrintObject::discover_vertical_shells()
|
|||
polygons_append(shell, cache.bottom_surfaces);
|
||||
// Running the union_ using the Clipper library piece by piece is cheaper
|
||||
// than running the union_ all at once.
|
||||
shell = union_(shell, false);
|
||||
shell = union_(shell);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1308,7 +1305,7 @@ void PrintObject::discover_vertical_shells()
|
|||
}
|
||||
#endif
|
||||
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
||||
shell_ex = union_ex(shell, true);
|
||||
shell_ex = union_safety_offset_ex(shell);
|
||||
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
|
||||
}
|
||||
|
||||
|
@ -1354,7 +1351,7 @@ void PrintObject::discover_vertical_shells()
|
|||
// Trim the shells region by the internal & internal void surfaces.
|
||||
const SurfaceType surfaceTypesInternal[] = { stInternal, stInternalVoid, stInternalSolid };
|
||||
const Polygons polygonsInternal = to_polygons(layerm->fill_surfaces.filter_by_types(surfaceTypesInternal, 3));
|
||||
shell = intersection(shell, polygonsInternal, true);
|
||||
shell = intersection(shell, polygonsInternal, ApplySafetyOffset::Yes);
|
||||
polygons_append(shell, diff(polygonsInternal, holes));
|
||||
if (shell.empty())
|
||||
continue;
|
||||
|
@ -1392,14 +1389,14 @@ void PrintObject::discover_vertical_shells()
|
|||
polygons_append(shell, intersection(offset(too_narrow, margin), polygonsInternal));
|
||||
}
|
||||
#endif
|
||||
ExPolygons new_internal_solid = intersection_ex(polygonsInternal, shell, false);
|
||||
ExPolygons new_internal_solid = intersection_ex(polygonsInternal, shell);
|
||||
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
||||
{
|
||||
Slic3r::SVG svg(debug_out_path("discover_vertical_shells-regularized-%d.svg", debug_idx), get_extents(shell_before));
|
||||
// Source shell.
|
||||
svg.draw(union_ex(shell_before, true));
|
||||
svg.draw(union_safety_offset_ex(shell_before));
|
||||
// Shell trimmed to the internal surfaces.
|
||||
svg.draw_outline(union_ex(shell, true), "black", "blue", scale_(0.05));
|
||||
svg.draw_outline(union_safety_offset_ex(shell), "black", "blue", scale_(0.05));
|
||||
// Regularized infill region.
|
||||
svg.draw_outline(new_internal_solid, "red", "magenta", scale_(0.05));
|
||||
svg.Close();
|
||||
|
@ -1407,16 +1404,8 @@ void PrintObject::discover_vertical_shells()
|
|||
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
|
||||
|
||||
// Trim the internal & internalvoid by the shell.
|
||||
Slic3r::ExPolygons new_internal = diff_ex(
|
||||
to_polygons(layerm->fill_surfaces.filter_by_type(stInternal)),
|
||||
shell,
|
||||
false
|
||||
);
|
||||
Slic3r::ExPolygons new_internal_void = diff_ex(
|
||||
to_polygons(layerm->fill_surfaces.filter_by_type(stInternalVoid)),
|
||||
shell,
|
||||
false
|
||||
);
|
||||
Slic3r::ExPolygons new_internal = diff_ex(layerm->fill_surfaces.filter_by_type(stInternal), shell);
|
||||
Slic3r::ExPolygons new_internal_void = diff_ex(layerm->fill_surfaces.filter_by_type(stInternalVoid), shell);
|
||||
|
||||
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
||||
{
|
||||
|
@ -1435,11 +1424,11 @@ void PrintObject::discover_vertical_shells()
|
|||
} // for each layer
|
||||
});
|
||||
m_print->throw_if_canceled();
|
||||
BOOST_LOG_TRIVIAL(debug) << "Discovering vertical shells for region " << idx_region << " in parallel - end";
|
||||
BOOST_LOG_TRIVIAL(debug) << "Discovering vertical shells for region " << region_id << " in parallel - end";
|
||||
|
||||
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
||||
for (size_t idx_layer = 0; idx_layer < m_layers.size(); ++idx_layer) {
|
||||
LayerRegion *layerm = m_layers[idx_layer]->get_region(idx_region);
|
||||
LayerRegion *layerm = m_layers[idx_layer]->get_region(region_id);
|
||||
layerm->export_region_slices_to_svg_debug("4_discover_vertical_shells-final");
|
||||
layerm->export_region_fill_surfaces_to_svg_debug("4_discover_vertical_shells-final");
|
||||
}
|
||||
|
@ -1457,8 +1446,8 @@ void PrintObject::bridge_over_infill()
|
|||
{
|
||||
BOOST_LOG_TRIVIAL(info) << "Bridge over infill..." << log_memory_info();
|
||||
|
||||
for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) {
|
||||
const PrintRegion ®ion = *m_print->regions()[region_id];
|
||||
for (size_t region_id = 0; region_id < this->num_printing_regions(); ++ region_id) {
|
||||
const PrintRegion ®ion = this->printing_region(region_id);
|
||||
|
||||
// skip bridging in case there are no voids
|
||||
if (region.config().fill_density.value == 100)
|
||||
|
@ -1521,8 +1510,8 @@ void PrintObject::bridge_over_infill()
|
|||
#endif
|
||||
|
||||
// compute the remaning internal solid surfaces as difference
|
||||
ExPolygons not_to_bridge = diff_ex(internal_solid, to_polygons(to_bridge), true);
|
||||
to_bridge = intersection_ex(to_polygons(to_bridge), internal_solid, true);
|
||||
ExPolygons not_to_bridge = diff_ex(internal_solid, to_bridge, ApplySafetyOffset::Yes);
|
||||
to_bridge = intersection_ex(to_bridge, internal_solid, ApplySafetyOffset::Yes);
|
||||
// build the new collection of fill_surfaces
|
||||
layerm->fill_surfaces.remove_type(stInternalSolid);
|
||||
for (ExPolygon &ex : to_bridge)
|
||||
|
@ -1680,6 +1669,7 @@ SlicingParameters PrintObject::slicing_parameters(const DynamicPrintConfig& full
|
|||
object_extruders);
|
||||
}
|
||||
sort_remove_duplicates(object_extruders);
|
||||
//FIXME add painting extruders
|
||||
|
||||
if (object_max_z <= 0.f)
|
||||
object_max_z = (float)model_object.raw_bounding_box().size().z();
|
||||
|
@ -1690,10 +1680,9 @@ SlicingParameters PrintObject::slicing_parameters(const DynamicPrintConfig& full
|
|||
std::vector<unsigned int> PrintObject::object_extruders() const
|
||||
{
|
||||
std::vector<unsigned int> extruders;
|
||||
extruders.reserve(this->region_volumes.size() * 3);
|
||||
for (size_t idx_region = 0; idx_region < this->region_volumes.size(); ++ idx_region)
|
||||
if (! this->region_volumes[idx_region].empty())
|
||||
m_print->get_region(idx_region)->collect_object_printing_extruders(extruders);
|
||||
extruders.reserve(this->all_regions().size() * 3);
|
||||
for (const PrintRegion ®ion : this->all_regions())
|
||||
region.collect_object_printing_extruders(*this->print(), extruders);
|
||||
sort_remove_duplicates(extruders);
|
||||
return extruders;
|
||||
}
|
||||
|
@ -1771,8 +1760,8 @@ void PrintObject::_slice(const std::vector<coordf_t> &layer_height_profile)
|
|||
layer->lower_layer = prev;
|
||||
}
|
||||
// Make sure all layers contain layer region objects for all regions.
|
||||
for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id)
|
||||
layer->add_region(this->print()->get_region(region_id));
|
||||
for (size_t region_id = 0; region_id < m_region_volumes.size(); ++ region_id)
|
||||
layer->add_region(&this->printing_region(region_id));
|
||||
prev = layer;
|
||||
}
|
||||
}
|
||||
|
@ -1782,16 +1771,15 @@ void PrintObject::_slice(const std::vector<coordf_t> &layer_height_profile)
|
|||
bool has_z_ranges = false;
|
||||
size_t num_volumes = 0;
|
||||
size_t num_modifiers = 0;
|
||||
for (int region_id = 0; region_id < (int)this->region_volumes.size(); ++ region_id) {
|
||||
for (int region_id = 0; region_id < int(m_region_volumes.size()); ++ region_id) {
|
||||
int last_volume_id = -1;
|
||||
for (const std::pair<t_layer_height_range, int> &volume_and_range : this->region_volumes[region_id]) {
|
||||
const int volume_id = volume_and_range.second;
|
||||
const ModelVolume *model_volume = this->model_object()->volumes[volume_id];
|
||||
for (const PrintRegionVolumes::VolumeWithZRange &volume_w_zrange : m_region_volumes[region_id].volumes) {
|
||||
const ModelVolume *model_volume = this->model_object()->volumes[volume_w_zrange.volume_idx];
|
||||
if (model_volume->is_model_part()) {
|
||||
if (last_volume_id == volume_id) {
|
||||
if (last_volume_id == volume_w_zrange.volume_idx) {
|
||||
has_z_ranges = true;
|
||||
} else {
|
||||
last_volume_id = volume_id;
|
||||
last_volume_id = volume_w_zrange.volume_idx;
|
||||
if (all_volumes_single_region == -2)
|
||||
// first model volume met
|
||||
all_volumes_single_region = region_id;
|
||||
|
@ -1814,14 +1802,14 @@ void PrintObject::_slice(const std::vector<coordf_t> &layer_height_profile)
|
|||
if (! has_z_ranges && (! m_config.clip_multipart_objects.value || all_volumes_single_region >= 0)) {
|
||||
// Cheap path: Slice regions without mutual clipping.
|
||||
// The cheap path is possible if no clipping is allowed or if slicing volumes of just a single region.
|
||||
for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) {
|
||||
for (size_t region_id = 0; region_id < m_region_volumes.size(); ++ region_id) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - region " << region_id;
|
||||
// slicing in parallel
|
||||
size_t slicing_mode_normal_below_layer = 0;
|
||||
if (spiral_vase) {
|
||||
// Slice the bottom layers with SlicingMode::Regular.
|
||||
// This needs to be in sync with LayerRegion::make_perimeters() spiral_vase!
|
||||
const PrintRegionConfig &config = this->print()->regions()[region_id]->config();
|
||||
const PrintRegionConfig &config = this->printing_region(region_id).config();
|
||||
slicing_mode_normal_below_layer = size_t(config.bottom_solid_layers.value);
|
||||
for (; slicing_mode_normal_below_layer < slice_zs.size() && slice_zs[slicing_mode_normal_below_layer] < config.bottom_solid_min_thickness - EPSILON;
|
||||
++ slicing_mode_normal_below_layer);
|
||||
|
@ -1847,22 +1835,22 @@ void PrintObject::_slice(const std::vector<coordf_t> &layer_height_profile)
|
|||
};
|
||||
std::vector<SlicedVolume> sliced_volumes;
|
||||
sliced_volumes.reserve(num_volumes);
|
||||
for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) {
|
||||
const std::vector<std::pair<t_layer_height_range, int>> &volumes_and_ranges = this->region_volumes[region_id];
|
||||
for (size_t i = 0; i < volumes_and_ranges.size(); ) {
|
||||
int volume_id = volumes_and_ranges[i].second;
|
||||
for (size_t region_id = 0; region_id < m_region_volumes.size(); ++ region_id) {
|
||||
const PrintRegionVolumes &volumes_and_ranges = m_region_volumes[region_id];
|
||||
for (size_t i = 0; i < volumes_and_ranges.volumes.size(); ) {
|
||||
int volume_id = volumes_and_ranges.volumes[i].volume_idx;
|
||||
const ModelVolume *model_volume = this->model_object()->volumes[volume_id];
|
||||
if (model_volume->is_model_part()) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - volume " << volume_id;
|
||||
// Find the ranges of this volume. Ranges in volumes_and_ranges must not overlap for a single volume.
|
||||
std::vector<t_layer_height_range> ranges;
|
||||
ranges.emplace_back(volumes_and_ranges[i].first);
|
||||
ranges.emplace_back(volumes_and_ranges.volumes[i].layer_height_range);
|
||||
size_t j = i + 1;
|
||||
for (; j < volumes_and_ranges.size() && volume_id == volumes_and_ranges[j].second; ++ j)
|
||||
if (! ranges.empty() && std::abs(ranges.back().second - volumes_and_ranges[j].first.first) < EPSILON)
|
||||
ranges.back().second = volumes_and_ranges[j].first.second;
|
||||
for (; j < volumes_and_ranges.volumes.size() && volume_id == volumes_and_ranges.volumes[j].volume_idx; ++ j)
|
||||
if (! ranges.empty() && std::abs(ranges.back().second - volumes_and_ranges.volumes[j].layer_height_range.first) < EPSILON)
|
||||
ranges.back().second = volumes_and_ranges.volumes[j].layer_height_range.second;
|
||||
else
|
||||
ranges.emplace_back(volumes_and_ranges[j].first);
|
||||
ranges.emplace_back(volumes_and_ranges.volumes[j].layer_height_range);
|
||||
// slicing in parallel
|
||||
sliced_volumes.emplace_back(volume_id, (int)region_id, this->slice_volume(slice_zs, ranges, slicing_mode, *model_volume));
|
||||
i = j;
|
||||
|
@ -1891,7 +1879,7 @@ void PrintObject::_slice(const std::vector<coordf_t> &layer_height_profile)
|
|||
slices = offset_ex(std::move(slices), delta);
|
||||
if (! processed.empty())
|
||||
// Trim by the slices of already processed regions.
|
||||
slices = diff_ex(to_polygons(std::move(slices)), processed);
|
||||
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);
|
||||
|
@ -1899,7 +1887,7 @@ void PrintObject::_slice(const std::vector<coordf_t> &layer_height_profile)
|
|||
}
|
||||
}
|
||||
// Collect and union volumes of a single region.
|
||||
for (int region_id = 0; region_id < (int)this->region_volumes.size(); ++ region_id) {
|
||||
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)
|
||||
|
@ -1920,8 +1908,8 @@ void PrintObject::_slice(const std::vector<coordf_t> &layer_height_profile)
|
|||
}
|
||||
|
||||
// Slice all modifier volumes.
|
||||
if (this->region_volumes.size() > 1) {
|
||||
for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) {
|
||||
if (m_region_volumes.size() > 1) {
|
||||
for (size_t region_id = 0; region_id < m_region_volumes.size(); ++ region_id) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "Slicing modifier volumes - region " << region_id;
|
||||
// slicing in parallel
|
||||
std::vector<ExPolygons> expolygons_by_layer = this->slice_modifiers(region_id, slice_zs);
|
||||
|
@ -1934,7 +1922,7 @@ void PrintObject::_slice(const std::vector<coordf_t> &layer_height_profile)
|
|||
tbb::blocked_range<size_t>(0, m_layers.size()),
|
||||
[this, &expolygons_by_layer, region_id](const tbb::blocked_range<size_t>& range) {
|
||||
for (size_t layer_id = range.begin(); layer_id < range.end(); ++ layer_id) {
|
||||
for (size_t other_region_id = 0; other_region_id < this->region_volumes.size(); ++ other_region_id) {
|
||||
for (size_t other_region_id = 0; other_region_id < m_region_volumes.size(); ++ other_region_id) {
|
||||
if (region_id == other_region_id)
|
||||
continue;
|
||||
Layer *layer = m_layers[layer_id];
|
||||
|
@ -1942,12 +1930,11 @@ void PrintObject::_slice(const std::vector<coordf_t> &layer_height_profile)
|
|||
LayerRegion *other_layerm = layer->m_regions[other_region_id];
|
||||
if (layerm == nullptr || other_layerm == nullptr || other_layerm->slices.empty() || expolygons_by_layer[layer_id].empty())
|
||||
continue;
|
||||
Polygons other_slices = to_polygons(other_layerm->slices);
|
||||
ExPolygons my_parts = intersection_ex(other_slices, to_polygons(expolygons_by_layer[layer_id]));
|
||||
ExPolygons my_parts = intersection_ex(other_layerm->slices.surfaces, expolygons_by_layer[layer_id]);
|
||||
if (my_parts.empty())
|
||||
continue;
|
||||
// Remove such parts from original region.
|
||||
other_layerm->slices.set(diff_ex(other_slices, to_polygons(my_parts)), stInternal);
|
||||
other_layerm->slices.set(diff_ex(other_layerm->slices.surfaces, my_parts), stInternal);
|
||||
// Append new parts to our region.
|
||||
layerm->slices.append(std::move(my_parts), stInternal);
|
||||
}
|
||||
|
@ -2034,7 +2021,7 @@ end:
|
|||
slices = offset_ex(std::move(slices), xy_compensation_scaled);
|
||||
if (region_id > 0 && clip)
|
||||
// Trim by the slices of already processed regions.
|
||||
slices = diff_ex(to_polygons(std::move(slices)), processed);
|
||||
slices = diff_ex(slices, processed);
|
||||
if (clip && (region_id + 1 < layer->m_regions.size()))
|
||||
// Collect the already processed regions to trim the to be processed regions.
|
||||
polygons_append(processed, slices);
|
||||
|
@ -2075,9 +2062,9 @@ end:
|
|||
std::vector<ExPolygons> PrintObject::slice_region(size_t region_id, const std::vector<float> &z, SlicingMode mode, size_t slicing_mode_normal_below_layer, SlicingMode mode_below) const
|
||||
{
|
||||
std::vector<const ModelVolume*> volumes;
|
||||
if (region_id < this->region_volumes.size()) {
|
||||
for (const std::pair<t_layer_height_range, int> &volume_and_range : this->region_volumes[region_id]) {
|
||||
const ModelVolume *volume = this->model_object()->volumes[volume_and_range.second];
|
||||
if (region_id < m_region_volumes.size()) {
|
||||
for (const PrintRegionVolumes::VolumeWithZRange &volume_w_zrange : m_region_volumes[region_id].volumes) {
|
||||
const ModelVolume *volume = this->model_object()->volumes[volume_w_zrange.volume_idx];
|
||||
if (volume->is_model_part())
|
||||
volumes.emplace_back(volume);
|
||||
}
|
||||
|
@ -2085,27 +2072,27 @@ std::vector<ExPolygons> PrintObject::slice_region(size_t region_id, const std::v
|
|||
return this->slice_volumes(z, mode, slicing_mode_normal_below_layer, mode_below, volumes);
|
||||
}
|
||||
|
||||
// Z ranges are not applicable to modifier meshes, therefore a single volume will be found in volume_and_range at most once.
|
||||
// Z ranges are not applicable to modifier meshes, therefore a single volume will be found in volume_w_zrange at most once.
|
||||
std::vector<ExPolygons> PrintObject::slice_modifiers(size_t region_id, const std::vector<float> &slice_zs) const
|
||||
{
|
||||
std::vector<ExPolygons> out;
|
||||
if (region_id < this->region_volumes.size())
|
||||
if (region_id < m_region_volumes.size())
|
||||
{
|
||||
std::vector<std::vector<t_layer_height_range>> volume_ranges;
|
||||
const std::vector<std::pair<t_layer_height_range, int>> &volumes_and_ranges = this->region_volumes[region_id];
|
||||
volume_ranges.reserve(volumes_and_ranges.size());
|
||||
for (size_t i = 0; i < volumes_and_ranges.size(); ) {
|
||||
int volume_id = volumes_and_ranges[i].second;
|
||||
const PrintRegionVolumes &volumes_and_ranges = m_region_volumes[region_id];
|
||||
volume_ranges.reserve(volumes_and_ranges.volumes.size());
|
||||
for (size_t i = 0; i < volumes_and_ranges.volumes.size(); ) {
|
||||
int volume_id = volumes_and_ranges.volumes[i].volume_idx;
|
||||
const ModelVolume *model_volume = this->model_object()->volumes[volume_id];
|
||||
if (model_volume->is_modifier()) {
|
||||
std::vector<t_layer_height_range> ranges;
|
||||
ranges.emplace_back(volumes_and_ranges[i].first);
|
||||
ranges.emplace_back(volumes_and_ranges.volumes[i].layer_height_range);
|
||||
size_t j = i + 1;
|
||||
for (; j < volumes_and_ranges.size() && volume_id == volumes_and_ranges[j].second; ++ j) {
|
||||
if (! ranges.empty() && std::abs(ranges.back().second - volumes_and_ranges[j].first.first) < EPSILON)
|
||||
ranges.back().second = volumes_and_ranges[j].first.second;
|
||||
for (; j < volumes_and_ranges.volumes.size() && volume_id == volumes_and_ranges.volumes[j].volume_idx; ++ j) {
|
||||
if (! ranges.empty() && std::abs(ranges.back().second - volumes_and_ranges.volumes[j].layer_height_range.first) < EPSILON)
|
||||
ranges.back().second = volumes_and_ranges.volumes[j].layer_height_range.second;
|
||||
else
|
||||
ranges.emplace_back(volumes_and_ranges[j].first);
|
||||
ranges.emplace_back(volumes_and_ranges.volumes[j].layer_height_range);
|
||||
}
|
||||
volume_ranges.emplace_back(std::move(ranges));
|
||||
i = j;
|
||||
|
@ -2127,8 +2114,8 @@ std::vector<ExPolygons> PrintObject::slice_modifiers(size_t region_id, const std
|
|||
if (equal_ranges && volume_ranges.front().size() == 1 && volume_ranges.front().front() == t_layer_height_range(0, DBL_MAX)) {
|
||||
// No modifier in this region was split to layer spans.
|
||||
std::vector<const ModelVolume*> volumes;
|
||||
for (const std::pair<t_layer_height_range, int> &volume_and_range : this->region_volumes[region_id]) {
|
||||
const ModelVolume *volume = this->model_object()->volumes[volume_and_range.second];
|
||||
for (const PrintRegionVolumes::VolumeWithZRange &volume_w_zrange : m_region_volumes[region_id].volumes) {
|
||||
const ModelVolume *volume = this->model_object()->volumes[volume_w_zrange.volume_idx];
|
||||
if (volume->is_modifier())
|
||||
volumes.emplace_back(volume);
|
||||
}
|
||||
|
@ -2136,19 +2123,19 @@ std::vector<ExPolygons> PrintObject::slice_modifiers(size_t region_id, const std
|
|||
} else {
|
||||
// Some modifier in this region was split to layer spans.
|
||||
std::vector<char> merge;
|
||||
for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) {
|
||||
const std::vector<std::pair<t_layer_height_range, int>> &volumes_and_ranges = this->region_volumes[region_id];
|
||||
for (size_t i = 0; i < volumes_and_ranges.size(); ) {
|
||||
int volume_id = volumes_and_ranges[i].second;
|
||||
for (size_t region_id = 0; region_id < m_region_volumes.size(); ++ region_id) {
|
||||
const PrintRegionVolumes &volumes_and_ranges = m_region_volumes[region_id];
|
||||
for (size_t i = 0; i < volumes_and_ranges.volumes.size(); ) {
|
||||
int volume_id = volumes_and_ranges.volumes[i].volume_idx;
|
||||
const ModelVolume *model_volume = this->model_object()->volumes[volume_id];
|
||||
if (model_volume->is_modifier()) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "Slicing modifiers - volume " << volume_id;
|
||||
// Find the ranges of this volume. Ranges in volumes_and_ranges must not overlap for a single volume.
|
||||
std::vector<t_layer_height_range> ranges;
|
||||
ranges.emplace_back(volumes_and_ranges[i].first);
|
||||
ranges.emplace_back(volumes_and_ranges.volumes[i].layer_height_range);
|
||||
size_t j = i + 1;
|
||||
for (; j < volumes_and_ranges.size() && volume_id == volumes_and_ranges[j].second; ++ j)
|
||||
ranges.emplace_back(volumes_and_ranges[j].first);
|
||||
for (; j < volumes_and_ranges.volumes.size() && volume_id == volumes_and_ranges.volumes[j].volume_idx; ++ j)
|
||||
ranges.emplace_back(volumes_and_ranges.volumes[j].layer_height_range);
|
||||
// slicing in parallel
|
||||
std::vector<ExPolygons> this_slices = this->slice_volume(slice_zs, ranges, SlicingMode::Regular, *model_volume);
|
||||
// Variable this_slices could be empty if no value of slice_zs is within any of the ranges of this volume.
|
||||
|
@ -2223,6 +2210,7 @@ std::vector<ExPolygons> PrintObject::slice_volumes(
|
|||
TriangleMesh vol_mesh(model_volume.mesh());
|
||||
vol_mesh.transform(model_volume.get_matrix(), true);
|
||||
mesh.merge(vol_mesh);
|
||||
mesh.repair(false);
|
||||
}
|
||||
if (mesh.stl.stats.number_of_facets > 0) {
|
||||
mesh.transform(m_trafo, true);
|
||||
|
@ -2365,7 +2353,7 @@ std::string PrintObject::_fix_slicing_errors()
|
|||
if (lower_surfaces)
|
||||
for (const auto &surface : *lower_surfaces)
|
||||
polygons_append(holes, surface.expolygon.holes);
|
||||
layerm->slices.set(diff_ex(union_(outer), holes, false), stInternal);
|
||||
layerm->slices.set(diff_ex(union_(outer), holes), stInternal);
|
||||
}
|
||||
// Update layer slices after repairing the single regions.
|
||||
layer->make_slices();
|
||||
|
@ -2423,9 +2411,15 @@ void PrintObject::simplify_slices(double distance)
|
|||
// fill_surfaces but we only turn them into VOID surfaces, thus preserving the boundaries.
|
||||
void PrintObject::clip_fill_surfaces()
|
||||
{
|
||||
if (! m_config.infill_only_where_needed.value ||
|
||||
! std::any_of(this->print()->regions().begin(), this->print()->regions().end(),
|
||||
[](const PrintRegion *region) { return region->config().fill_density > 0; }))
|
||||
if (! m_config.infill_only_where_needed.value)
|
||||
return;
|
||||
bool has_infill = false;
|
||||
for (size_t i = 0; i < this->num_printing_regions(); ++ i)
|
||||
if (this->printing_region(i).config().fill_density > 0) {
|
||||
has_infill = true;
|
||||
break;
|
||||
}
|
||||
if (! has_infill)
|
||||
return;
|
||||
|
||||
// We only want infill under ceilings; this is almost like an
|
||||
|
@ -2478,7 +2472,7 @@ void PrintObject::clip_fill_surfaces()
|
|||
upper_internal = intersection(overhangs, lower_layer_internal_surfaces);
|
||||
// Apply new internal infill to regions.
|
||||
for (LayerRegion *layerm : lower_layer->m_regions) {
|
||||
if (layerm->region()->config().fill_density.value == 0)
|
||||
if (layerm->region().config().fill_density.value == 0)
|
||||
continue;
|
||||
SurfaceType internal_surface_types[] = { stInternal, stInternalVoid };
|
||||
Polygons internal;
|
||||
|
@ -2486,8 +2480,8 @@ void PrintObject::clip_fill_surfaces()
|
|||
if (surface.surface_type == stInternal || surface.surface_type == stInternalVoid)
|
||||
polygons_append(internal, std::move(surface.expolygon));
|
||||
layerm->fill_surfaces.remove_types(internal_surface_types, 2);
|
||||
layerm->fill_surfaces.append(intersection_ex(internal, upper_internal, true), stInternal);
|
||||
layerm->fill_surfaces.append(diff_ex (internal, upper_internal, true), stInternalVoid);
|
||||
layerm->fill_surfaces.append(intersection_ex(internal, upper_internal, ApplySafetyOffset::Yes), stInternal);
|
||||
layerm->fill_surfaces.append(diff_ex (internal, upper_internal, ApplySafetyOffset::Yes), stInternalVoid);
|
||||
// If there are voids it means that our internal infill is not adjacent to
|
||||
// perimeters. In this case it would be nice to add a loop around infill to
|
||||
// make it more robust and nicer. TODO.
|
||||
|
@ -2503,12 +2497,12 @@ void PrintObject::discover_horizontal_shells()
|
|||
{
|
||||
BOOST_LOG_TRIVIAL(trace) << "discover_horizontal_shells()";
|
||||
|
||||
for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) {
|
||||
for (size_t region_id = 0; region_id < this->num_printing_regions(); ++ region_id) {
|
||||
for (size_t i = 0; i < m_layers.size(); ++ i) {
|
||||
m_print->throw_if_canceled();
|
||||
Layer *layer = m_layers[i];
|
||||
LayerRegion *layerm = layer->regions()[region_id];
|
||||
const PrintRegionConfig ®ion_config = layerm->region()->config();
|
||||
const PrintRegionConfig ®ion_config = layerm->region().config();
|
||||
if (region_config.solid_infill_every_layers.value > 0 && region_config.fill_density.value > 0 &&
|
||||
(i % region_config.solid_infill_every_layers) == 0) {
|
||||
// Insert a solid internal layer. Mark stInternal surfaces as stInternalSolid or stInternalBridge.
|
||||
|
@ -2584,7 +2578,7 @@ void PrintObject::discover_horizontal_shells()
|
|||
for (const Surface &surface : neighbor_layerm->fill_surfaces.surfaces)
|
||||
if (surface.surface_type == stInternal || surface.surface_type == stInternalSolid)
|
||||
polygons_append(internal, to_polygons(surface.expolygon));
|
||||
new_internal_solid = intersection(solid, internal, true);
|
||||
new_internal_solid = intersection(solid, internal, ApplySafetyOffset::Yes);
|
||||
}
|
||||
if (new_internal_solid.empty()) {
|
||||
// No internal solid needed on this layer. In order to decide whether to continue
|
||||
|
@ -2611,8 +2605,7 @@ void PrintObject::discover_horizontal_shells()
|
|||
float margin = float(neighbor_layerm->flow(frExternalPerimeter).scaled_width());
|
||||
Polygons too_narrow = diff(
|
||||
new_internal_solid,
|
||||
offset2(new_internal_solid, -margin, +margin, jtMiter, 5),
|
||||
true);
|
||||
offset2(new_internal_solid, -margin, +margin + ClipperSafetyOffset, jtMiter, 5));
|
||||
// Trim the regularized region by the original region.
|
||||
if (! too_narrow.empty())
|
||||
new_internal_solid = solid = diff(new_internal_solid, too_narrow);
|
||||
|
@ -2631,8 +2624,7 @@ void PrintObject::discover_horizontal_shells()
|
|||
// have the same angle, so the next shell would be grown even more and so on.
|
||||
Polygons too_narrow = diff(
|
||||
new_internal_solid,
|
||||
offset2(new_internal_solid, -margin, +margin, ClipperLib::jtMiter, 5),
|
||||
true);
|
||||
offset2(new_internal_solid, -margin, +margin + ClipperSafetyOffset, ClipperLib::jtMiter, 5));
|
||||
if (! too_narrow.empty()) {
|
||||
// grow the collapsing parts and add the extra area to the neighbor layer
|
||||
// as well as to our original surfaces so that we support this
|
||||
|
@ -2660,15 +2652,12 @@ void PrintObject::discover_horizontal_shells()
|
|||
// and new ones
|
||||
SurfaceCollection backup = std::move(neighbor_layerm->fill_surfaces);
|
||||
polygons_append(new_internal_solid, to_polygons(backup.filter_by_type(stInternalSolid)));
|
||||
ExPolygons internal_solid = union_ex(new_internal_solid, false);
|
||||
ExPolygons internal_solid = union_ex(new_internal_solid);
|
||||
// assign new internal-solid surfaces to layer
|
||||
neighbor_layerm->fill_surfaces.set(internal_solid, stInternalSolid);
|
||||
// subtract intersections from layer surfaces to get resulting internal surfaces
|
||||
Polygons polygons_internal = to_polygons(std::move(internal_solid));
|
||||
ExPolygons internal = diff_ex(
|
||||
to_polygons(backup.filter_by_type(stInternal)),
|
||||
polygons_internal,
|
||||
true);
|
||||
ExPolygons internal = diff_ex(backup.filter_by_type(stInternal), polygons_internal, ApplySafetyOffset::Yes);
|
||||
// assign resulting internal surfaces to layer
|
||||
neighbor_layerm->fill_surfaces.append(internal, stInternal);
|
||||
polygons_append(polygons_internal, to_polygons(std::move(internal)));
|
||||
|
@ -2679,7 +2668,7 @@ void PrintObject::discover_horizontal_shells()
|
|||
backup.group(&top_bottom_groups);
|
||||
for (SurfacesPtr &group : top_bottom_groups)
|
||||
neighbor_layerm->fill_surfaces.append(
|
||||
diff_ex(to_polygons(group), polygons_internal),
|
||||
diff_ex(group, polygons_internal),
|
||||
// Use an existing surface as a template, it carries the bridge angle etc.
|
||||
*group.front());
|
||||
}
|
||||
|
@ -2689,7 +2678,7 @@ void PrintObject::discover_horizontal_shells()
|
|||
} // for each region
|
||||
|
||||
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
||||
for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) {
|
||||
for (size_t region_id = 0; region_id < this->num_printing_regions(); ++ region_id) {
|
||||
for (const Layer *layer : m_layers) {
|
||||
const LayerRegion *layerm = layer->m_regions[region_id];
|
||||
layerm->export_region_slices_to_svg_debug("5_discover_horizontal_shells");
|
||||
|
@ -2705,16 +2694,16 @@ void PrintObject::discover_horizontal_shells()
|
|||
void PrintObject::combine_infill()
|
||||
{
|
||||
// Work on each region separately.
|
||||
for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) {
|
||||
const PrintRegion *region = this->print()->regions()[region_id];
|
||||
const size_t every = region->config().infill_every_layers.value;
|
||||
if (every < 2 || region->config().fill_density == 0.)
|
||||
for (size_t region_id = 0; region_id < this->num_printing_regions(); ++ region_id) {
|
||||
const PrintRegion ®ion = this->printing_region(region_id);
|
||||
const size_t every = region.config().infill_every_layers.value;
|
||||
if (every < 2 || region.config().fill_density == 0.)
|
||||
continue;
|
||||
// Limit the number of combined layers to the maximum height allowed by this regions' nozzle.
|
||||
//FIXME limit the layer height to max_layer_height
|
||||
double nozzle_diameter = std::min(
|
||||
this->print()->config().nozzle_diameter.get_at(region->config().infill_extruder.value - 1),
|
||||
this->print()->config().nozzle_diameter.get_at(region->config().solid_infill_extruder.value - 1));
|
||||
this->print()->config().nozzle_diameter.get_at(region.config().infill_extruder.value - 1),
|
||||
this->print()->config().nozzle_diameter.get_at(region.config().solid_infill_extruder.value - 1));
|
||||
// define the combinations
|
||||
std::vector<size_t> combine(m_layers.size(), 0);
|
||||
{
|
||||
|
@ -2758,10 +2747,7 @@ void PrintObject::combine_infill()
|
|||
ExPolygons intersection = to_expolygons(layerms.front()->fill_surfaces.filter_by_type(stInternal));
|
||||
// Start looping from the second layer and intersect the current intersection with it.
|
||||
for (size_t i = 1; i < layerms.size(); ++ i)
|
||||
intersection = intersection_ex(
|
||||
to_polygons(intersection),
|
||||
to_polygons(layerms[i]->fill_surfaces.filter_by_type(stInternal)),
|
||||
false);
|
||||
intersection = intersection_ex(layerms[i]->fill_surfaces.filter_by_type(stInternal), intersection);
|
||||
double area_threshold = layerms.front()->infill_area_threshold();
|
||||
if (! intersection.empty() && area_threshold > 0.)
|
||||
intersection.erase(std::remove_if(intersection.begin(), intersection.end(),
|
||||
|
@ -2781,18 +2767,18 @@ void PrintObject::combine_infill()
|
|||
0.5f * layerms.back()->flow(frPerimeter).scaled_width() +
|
||||
// Because fill areas for rectilinear and honeycomb are grown
|
||||
// later to overlap perimeters, we need to counteract that too.
|
||||
((region->config().fill_pattern == ipRectilinear ||
|
||||
region->config().fill_pattern == ipMonotonic ||
|
||||
region->config().fill_pattern == ipGrid ||
|
||||
region->config().fill_pattern == ipLine ||
|
||||
region->config().fill_pattern == ipHoneycomb) ? 1.5f : 0.5f) *
|
||||
((region.config().fill_pattern == ipRectilinear ||
|
||||
region.config().fill_pattern == ipMonotonic ||
|
||||
region.config().fill_pattern == ipGrid ||
|
||||
region.config().fill_pattern == ipLine ||
|
||||
region.config().fill_pattern == ipHoneycomb) ? 1.5f : 0.5f) *
|
||||
layerms.back()->flow(frSolidInfill).scaled_width();
|
||||
for (ExPolygon &expoly : intersection)
|
||||
polygons_append(intersection_with_clearance, offset(expoly, clearance_offset));
|
||||
for (LayerRegion *layerm : layerms) {
|
||||
Polygons internal = to_polygons(layerm->fill_surfaces.filter_by_type(stInternal));
|
||||
Polygons internal = to_polygons(std::move(layerm->fill_surfaces.filter_by_type(stInternal)));
|
||||
layerm->fill_surfaces.remove_type(stInternal);
|
||||
layerm->fill_surfaces.append(diff_ex(internal, intersection_with_clearance, false), stInternal);
|
||||
layerm->fill_surfaces.append(diff_ex(internal, intersection_with_clearance), stInternal);
|
||||
if (layerm == layerms.back()) {
|
||||
// Apply surfaces back with adjusted depth to the uppermost layer.
|
||||
Surface templ(stInternal, ExPolygon());
|
||||
|
@ -2804,7 +2790,7 @@ void PrintObject::combine_infill()
|
|||
} else {
|
||||
// Save void surfaces.
|
||||
layerm->fill_surfaces.append(
|
||||
intersection_ex(internal, intersection_with_clearance, false),
|
||||
intersection_ex(internal, intersection_with_clearance),
|
||||
stInternalVoid);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue