WIP: Layers split into islands, islands overlapping in Z interconnected

into a graph with links to the layer above / below.

In addition:
Members of LayerRegion were made private, public interface const only.
this->m_xxx replaced with just m_xxx
SurfacesPtr was made a vector of const pointers.
This commit is contained in:
Vojtech Bubnik 2022-10-26 18:41:39 +02:00
parent f57744ad12
commit ee626eb65a
39 changed files with 751 additions and 356 deletions
src/libslic3r

View file

@ -157,7 +157,7 @@ void PrintObject::make_perimeters()
m_print->throw_if_canceled();
LayerRegion &layerm = *m_layers[layer_idx]->get_region(region_id);
const LayerRegion &upper_layerm = *m_layers[layer_idx+1]->get_region(region_id);
const Polygons upper_layerm_polygons = to_polygons(upper_layerm.slices.surfaces);
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);
@ -166,7 +166,8 @@ void PrintObject::make_perimeters()
const coord_t ext_perimeter_width = ext_perimeter_flow.scaled_width();
const coord_t ext_perimeter_spacing = ext_perimeter_flow.scaled_spacing();
for (Surface &slice : layerm.slices.surfaces) {
// slice is not const because slice.extra_perimeters is being incremented.
for (Surface &slice : layerm.m_slices.surfaces) {
for (;;) {
// compute the total thickness of perimeters
const coord_t perimeters_thickness = ext_perimeter_width/2 + ext_perimeter_spacing/2
@ -418,7 +419,7 @@ void PrintObject::generate_support_spots()
BOOST_LOG_TRIVIAL(debug)
<< "Searching support spots - start";
m_print->set_status(75, L("Searching support spots"));
if (this->m_config.support_material && !this->m_config.support_material_auto &&
if (m_config.support_material && !m_config.support_material_auto &&
std::all_of(this->model_object()->volumes.begin(), this->model_object()->volumes.end(),
[](const ModelVolume* mv){return mv->supported_facets.empty();})
) {
@ -500,7 +501,7 @@ std::pair<FillAdaptive::OctreePtr, FillAdaptive::OctreePtr> PrintObject::prepare
m_print->throw_if_canceled();
const Layer *layer = this->layers()[idx_layer];
for (const LayerRegion *layerm : layer->regions())
for (const Surface &surface : layerm->fill_surfaces.surfaces)
for (const Surface &surface : layerm->fill_surfaces())
if (surface.surface_type == stInternalBridge)
append(out, triangulate_expolygon_3d(surface.expolygon, layer->bottom_z()));
}
@ -883,13 +884,13 @@ void PrintObject::detect_surfaces_type()
Surfaces top;
if (upper_layer) {
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);
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, opening_ex(upper_slices, 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
top = layerm->slices.surfaces;
top = layerm->slices().surfaces;
for (Surface &surface : top)
surface.surface_type = stTop;
}
@ -910,7 +911,7 @@ void PrintObject::detect_surfaces_type()
surfaces_append(
bottom,
opening_ex(
diff_ex(layerm->slices.surfaces, lower_layer->lslices, ApplySafetyOffset::Yes),
diff_ex(layerm->slices().surfaces, lower_layer->lslices, ApplySafetyOffset::Yes),
offset),
surface_type_bottom_other);
// if user requested internal shells, we need to identify surfaces
@ -922,8 +923,8 @@ void PrintObject::detect_surfaces_type()
bottom,
opening_ex(
diff_ex(
intersection(layerm->slices.surfaces, lower_layer->lslices), // supported
lower_layer->m_regions[region_id]->slices.surfaces,
intersection(layerm->slices().surfaces, lower_layer->lslices), // supported
lower_layer->m_regions[region_id]->slices().surfaces,
ApplySafetyOffset::Yes),
offset),
stBottom);
@ -932,7 +933,7 @@ void PrintObject::detect_surfaces_type()
} else {
// if no lower layer, all surfaces of this one are solid
// we clone surfaces because we're going to clear the slices collection
bottom = layerm->slices.surfaces;
bottom = layerm->slices().surfaces;
for (Surface &surface : bottom)
surface.surface_type = stBottom;
}
@ -961,13 +962,13 @@ void PrintObject::detect_surfaces_type()
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
// save surfaces to layer
Surfaces &surfaces_out = interface_shells ? surfaces_new[idx_layer] : layerm->slices.surfaces;
Surfaces &surfaces_out = interface_shells ? surfaces_new[idx_layer] : layerm->slices().surfaces;
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;
const Surfaces &surfaces_prev = interface_shells ? layerm->slices().surfaces : surfaces_backup;
// find internal surfaces (difference between top/bottom surfaces and others)
{
@ -993,15 +994,15 @@ 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[region_id]->slices.surfaces = std::move(surfaces_new[idx_layer]);
m_layers[idx_layer]->m_regions[region_id]->m_slices.set(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[region_id]->slices.set_type(stTop);
m_layers[num_layers - 1]->m_regions[region_id]->m_slices.set_type(stTop);
for (size_t i = num_layers; i < m_layers.size(); ++ i)
m_layers[i]->m_regions[region_id]->slices.set_type(stInternal);
m_layers[i]->m_regions[region_id]->m_slices.set_type(stInternal);
}
BOOST_LOG_TRIVIAL(debug) << "Detecting solid surfaces for region " << region_id << " - clipping in parallel - start";
@ -1048,7 +1049,7 @@ void PrintObject::process_external_surfaces()
bool expansions = false;
bool voids = false;
for (const LayerRegion *layerm : layer->regions()) {
for (const Surface &surface : layerm->fill_surfaces.surfaces) {
for (const Surface &surface : layerm->fill_surfaces()) {
if (surface.surface_type == stInternal)
voids = true;
else
@ -1073,7 +1074,7 @@ void PrintObject::process_external_surfaces()
Polygons voids;
for (const LayerRegion *layerm : m_layers[layer_idx]->regions()) {
if (layerm->region().config().fill_density.value == 0.)
for (const Surface &surface : layerm->fill_surfaces.surfaces)
for (const Surface &surface : layerm->fill_surfaces())
// Shrink the holes, let the layer above expand slightly inside the unsupported areas.
polygons_append(voids, offset(surface.expolygon, unsupported_width));
}
@ -1102,7 +1103,7 @@ void PrintObject::process_external_surfaces()
m_print->throw_if_canceled();
BOOST_LOG_TRIVIAL(debug) << "Processing external surfaces for region " << region_id << " in parallel - end";
}
}
} // void PrintObject::process_external_surfaces()
void PrintObject::discover_vertical_shells()
{
@ -1170,15 +1171,15 @@ void PrintObject::discover_vertical_shells()
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(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));
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(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));
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)
for (const Surface &s : layerm.slices())
perimeters = std::max<unsigned int>(perimeters, s.extra_perimeters);
perimeters += layerm.region().config().perimeters.value;
// Then calculate the infill offset.
@ -1189,7 +1190,7 @@ void PrintObject::discover_vertical_shells()
0.5f * float(extflow.scaled_width() + extflow.scaled_spacing()) + (float(perimeters) - 1.f) * flow.scaled_spacing());
perimeter_min_spacing = std::min(perimeter_min_spacing, float(std::min(extflow.scaled_spacing(), flow.scaled_spacing())));
}
polygons_append(cache.holes, to_polygons(layerm.fill_expolygons));
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);
@ -1242,15 +1243,15 @@ void PrintObject::discover_vertical_shells()
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(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));
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(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));
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 region_id = 0; region_id < layer.regions().size(); ++ region_id)
polygons_append(cache.holes, to_polygons(layer.regions()[region_id]->fill_expolygons));
polygons_append(cache.holes, to_polygons(layer.regions()[region_id]->fill_expolygons()));
}
}
});
@ -1407,14 +1408,14 @@ 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));
const Polygons polygonsInternal = to_polygons(layerm->fill_surfaces().filter_by_types(surfaceTypesInternal, 3));
shell = intersection(shell, polygonsInternal, ApplySafetyOffset::Yes);
polygons_append(shell, diff(polygonsInternal, holes));
if (shell.empty())
continue;
// Append the internal solids, so they will be merged with the new ones.
polygons_append(shell, to_polygons(layerm->fill_surfaces.filter_by_type(stInternalSolid)));
polygons_append(shell, to_polygons(layerm->fill_surfaces().filter_by_type(stInternalSolid)));
// These regions will be filled by a rectilinear full infill. Currently this type of infill
// only fills regions, which fit at least a single line. To avoid gaps in the sparse infill,
@ -1461,8 +1462,8 @@ void PrintObject::discover_vertical_shells()
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
// Trim the internal & internalvoid by the shell.
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);
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
{
@ -1474,10 +1475,10 @@ void PrintObject::discover_vertical_shells()
// Assign resulting internal surfaces to layer.
const SurfaceType surfaceTypesKeep[] = { stTop, stBottom, stBottomBridge };
layerm->fill_surfaces.keep_types(surfaceTypesKeep, sizeof(surfaceTypesKeep)/sizeof(SurfaceType));
layerm->fill_surfaces.append(new_internal, stInternal);
layerm->fill_surfaces.append(new_internal_void, stInternalVoid);
layerm->fill_surfaces.append(new_internal_solid, stInternalSolid);
layerm->m_fill_surfaces.keep_types(surfaceTypesKeep, sizeof(surfaceTypesKeep)/sizeof(SurfaceType));
layerm->m_fill_surfaces.append(new_internal, stInternal);
layerm->m_fill_surfaces.append(new_internal_void, stInternalVoid);
layerm->m_fill_surfaces.append(new_internal_solid, stInternalSolid);
} // for each layer
});
m_print->throw_if_canceled();
@ -1491,7 +1492,7 @@ void PrintObject::discover_vertical_shells()
}
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
} // for each region
}
} // void PrintObject::discover_vertical_shells()
// This method applies bridge flow to the first internal solid layer above sparse infill.
void PrintObject::bridge_over_infill()
@ -1514,7 +1515,7 @@ void PrintObject::bridge_over_infill()
for (Layer *layer : m_layers) {
Polygons sum;
for (const LayerRegion *layerm : layer->m_regions)
layerm->fill_surfaces.filter_by_type(stInternal, &sum);
layerm->fill_surfaces().filter_by_type(stInternal, &sum);
internals.emplace_back(std::move(sum));
}
@ -1531,7 +1532,7 @@ void PrintObject::bridge_over_infill()
// Extract the stInternalSolid surfaces that might be transformed into bridges.
ExPolygons internal_solid;
layerm->fill_surfaces.remove_type(stInternalSolid, &internal_solid);
layerm->m_fill_surfaces.remove_type(stInternalSolid, &internal_solid);
if (internal_solid.empty())
// No internal solid -> no new bridges for this layer region.
continue;
@ -1563,7 +1564,7 @@ void PrintObject::bridge_over_infill()
if (to_bridge_pp.empty()) {
// Restore internal_solid surfaces.
for (ExPolygon &ex : internal_solid)
layerm->fill_surfaces.surfaces.push_back(Surface(stInternalSolid, std::move(ex)));
layerm->m_fill_surfaces.surfaces.push_back(Surface(stInternalSolid, std::move(ex)));
continue;
}
// convert into ExPolygons
@ -1579,9 +1580,9 @@ void PrintObject::bridge_over_infill()
to_bridge = intersection_ex(to_bridge, internal_solid, ApplySafetyOffset::Yes);
// build the new collection of fill_surfaces
for (ExPolygon &ex : to_bridge)
layerm->fill_surfaces.surfaces.push_back(Surface(stInternalBridge, std::move(ex)));
layerm->m_fill_surfaces.surfaces.push_back(Surface(stInternalBridge, std::move(ex)));
for (ExPolygon &ex : not_to_bridge)
layerm->fill_surfaces.surfaces.push_back(Surface(stInternalSolid, std::move(ex)));
layerm->m_fill_surfaces.surfaces.push_back(Surface(stInternalSolid, std::move(ex)));
/*
# exclude infill from the layers below if needed
# see discussion at https://github.com/alexrj/Slic3r/issues/240
@ -1622,7 +1623,7 @@ void PrintObject::bridge_over_infill()
m_print->throw_if_canceled();
}
});
}
} // void PrintObject::bridge_over_infill()
static void clamp_exturder_to_default(ConfigOptionInt &opt, size_t num_extruders)
{
@ -1829,7 +1830,7 @@ void PrintObject::clip_fill_surfaces()
// Solid surfaces to be supported.
Polygons overhangs;
for (const LayerRegion *layerm : layer->m_regions)
for (const Surface &surface : layerm->fill_surfaces.surfaces) {
for (const Surface &surface : layerm->fill_surfaces()) {
Polygons polygons = to_polygons(surface.expolygon);
if (surface.is_solid())
polygons_append(overhangs, polygons);
@ -1838,7 +1839,7 @@ void PrintObject::clip_fill_surfaces()
Polygons lower_layer_fill_surfaces;
Polygons lower_layer_internal_surfaces;
for (const LayerRegion *layerm : lower_layer->m_regions)
for (const Surface &surface : layerm->fill_surfaces.surfaces) {
for (const Surface &surface : layerm->fill_surfaces()) {
Polygons polygons = to_polygons(surface.expolygon);
if (surface.surface_type == stInternal || surface.surface_type == stInternalVoid)
polygons_append(lower_layer_internal_surfaces, polygons);
@ -1873,12 +1874,12 @@ void PrintObject::clip_fill_surfaces()
continue;
SurfaceType internal_surface_types[] = { stInternal, stInternalVoid };
Polygons internal;
for (Surface &surface : layerm->fill_surfaces.surfaces)
for (Surface &surface : layerm->m_fill_surfaces.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, ApplySafetyOffset::Yes), stInternal);
layerm->fill_surfaces.append(diff_ex (internal, upper_internal, ApplySafetyOffset::Yes), stInternalVoid);
layerm->m_fill_surfaces.remove_types(internal_surface_types, 2);
layerm->m_fill_surfaces.append(intersection_ex(internal, upper_internal, ApplySafetyOffset::Yes), stInternal);
layerm->m_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.
@ -1888,7 +1889,7 @@ void PrintObject::clip_fill_surfaces()
}
m_print->throw_if_canceled();
}
}
} // void PrintObject::clip_fill_surfaces()
void PrintObject::discover_horizontal_shells()
{
@ -1904,7 +1905,7 @@ void PrintObject::discover_horizontal_shells()
(i % region_config.solid_infill_every_layers) == 0) {
// Insert a solid internal layer. Mark stInternal surfaces as stInternalSolid or stInternalBridge.
SurfaceType type = (region_config.fill_density == 100 || region_config.solid_infill_every_layers == 1) ? stInternalSolid : stInternalBridge;
for (Surface &surface : layerm->fill_surfaces.surfaces)
for (Surface &surface : layerm->m_fill_surfaces.surfaces)
if (surface.surface_type == stInternal)
surface.surface_type = type;
}
@ -1935,11 +1936,11 @@ void PrintObject::discover_horizontal_shells()
// (not covered by a layer above / below).
// This does not contain the areas covered by perimeters!
Polygons solid;
for (const Surface &surface : layerm->slices.surfaces)
for (const Surface &surface : layerm->slices())
if (surface.surface_type == type)
polygons_append(solid, to_polygons(surface.expolygon));
// Infill areas (slices without the perimeters).
for (const Surface &surface : layerm->fill_surfaces.surfaces)
for (const Surface &surface : layerm->fill_surfaces())
if (surface.surface_type == type)
polygons_append(solid, to_polygons(surface.expolygon));
if (solid.empty())
@ -1972,7 +1973,7 @@ void PrintObject::discover_horizontal_shells()
Polygons new_internal_solid;
{
Polygons internal;
for (const Surface &surface : neighbor_layerm->fill_surfaces.surfaces)
for (const Surface &surface : neighbor_layerm->fill_surfaces())
if (surface.surface_type == stInternal || surface.surface_type == stInternalSolid)
polygons_append(internal, to_polygons(surface.expolygon));
new_internal_solid = intersection(solid, internal, ApplySafetyOffset::Yes);
@ -2028,7 +2029,7 @@ void PrintObject::discover_horizontal_shells()
// additional area in the next shell too
// make sure our grown surfaces don't exceed the fill area
Polygons internal;
for (const Surface &surface : neighbor_layerm->fill_surfaces.surfaces)
for (const Surface &surface : neighbor_layerm->fill_surfaces())
if (surface.is_internal() && !surface.is_bridge())
polygons_append(internal, to_polygons(surface.expolygon));
polygons_append(new_internal_solid,
@ -2047,16 +2048,16 @@ void PrintObject::discover_horizontal_shells()
// internal-solid are the union of the existing internal-solid surfaces
// and new ones
SurfaceCollection backup = std::move(neighbor_layerm->fill_surfaces);
SurfaceCollection backup = std::move(neighbor_layerm->m_fill_surfaces);
polygons_append(new_internal_solid, to_polygons(backup.filter_by_type(stInternalSolid)));
ExPolygons internal_solid = union_ex(new_internal_solid);
// assign new internal-solid surfaces to layer
neighbor_layerm->fill_surfaces.set(internal_solid, stInternalSolid);
neighbor_layerm->m_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(backup.filter_by_type(stInternal), polygons_internal, ApplySafetyOffset::Yes);
// assign resulting internal surfaces to layer
neighbor_layerm->fill_surfaces.append(internal, stInternal);
neighbor_layerm->m_fill_surfaces.append(internal, stInternal);
polygons_append(polygons_internal, to_polygons(std::move(internal)));
// assign top and bottom surfaces to layer
SurfaceType surface_types_solid[] = { stTop, stBottom, stBottomBridge };
@ -2064,7 +2065,7 @@ void PrintObject::discover_horizontal_shells()
std::vector<SurfacesPtr> top_bottom_groups;
backup.group(&top_bottom_groups);
for (SurfacesPtr &group : top_bottom_groups)
neighbor_layerm->fill_surfaces.append(
neighbor_layerm->m_fill_surfaces.append(
diff_ex(group, polygons_internal),
// Use an existing surface as a template, it carries the bridge angle etc.
*group.front());
@ -2083,7 +2084,7 @@ void PrintObject::discover_horizontal_shells()
} // for each layer
} // for each region
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
}
} // void PrintObject::discover_horizontal_shells()
// combine fill surfaces across layers to honor the "infill every N layers" option
// Idempotence of this method is guaranteed by the fact that we don't remove things from
@ -2141,10 +2142,10 @@ void PrintObject::combine_infill()
layerms.emplace_back(m_layers[i]->regions()[region_id]);
// We need to perform a multi-layer intersection, so let's split it in pairs.
// Initialize the intersection with the candidates of the lowest layer.
ExPolygons intersection = to_expolygons(layerms.front()->fill_surfaces.filter_by_type(stInternal));
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(layerms[i]->fill_surfaces.filter_by_type(stInternal), intersection);
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(),
@ -2173,9 +2174,9 @@ void PrintObject::combine_infill()
for (ExPolygon &expoly : intersection)
polygons_append(intersection_with_clearance, offset(expoly, clearance_offset));
for (LayerRegion *layerm : layerms) {
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), stInternal);
Polygons internal = to_polygons(std::move(layerm->fill_surfaces().filter_by_type(stInternal)));
layerm->m_fill_surfaces.remove_type(stInternal);
layerm->m_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());
@ -2183,17 +2184,17 @@ void PrintObject::combine_infill()
for (LayerRegion *layerm2 : layerms)
templ.thickness += layerm2->layer()->height;
templ.thickness_layers = (unsigned short)layerms.size();
layerm->fill_surfaces.append(intersection, templ);
layerm->m_fill_surfaces.append(intersection, templ);
} else {
// Save void surfaces.
layerm->fill_surfaces.append(
layerm->m_fill_surfaces.append(
intersection_ex(internal, intersection_with_clearance),
stInternalVoid);
}
}
}
}
}
} // void PrintObject::combine_infill()
void PrintObject::_generate_support_material()
{