Parallelized PrintObject::detect_surfaces_type()
This commit is contained in:
parent
65c024f7cf
commit
dfba2cb6b2
1 changed files with 150 additions and 130 deletions
|
@ -365,8 +365,10 @@ void PrintObject::detect_surfaces_type()
|
||||||
{
|
{
|
||||||
BOOST_LOG_TRIVIAL(info) << "Detecting solid surfaces...";
|
BOOST_LOG_TRIVIAL(info) << "Detecting solid surfaces...";
|
||||||
|
|
||||||
|
bool interface_shells = this->config.interface_shells.value;
|
||||||
|
|
||||||
for (int idx_region = 0; idx_region < this->_print->regions.size(); ++ idx_region) {
|
for (int idx_region = 0; idx_region < this->_print->regions.size(); ++ idx_region) {
|
||||||
BOOST_LOG_TRIVIAL(debug) << "Detecting solid surfaces for region " << idx_region;
|
BOOST_LOG_TRIVIAL(debug) << "Detecting solid surfaces for region " << idx_region << " in parallel - start";
|
||||||
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
||||||
for (int idx_layer = 0; idx_layer < int(this->layer_count()); ++ idx_layer) {
|
for (int idx_layer = 0; idx_layer < int(this->layer_count()); ++ idx_layer) {
|
||||||
LayerRegion *layerm = this->layers[idx_layer]->get_region(idx_region);
|
LayerRegion *layerm = this->layers[idx_layer]->get_region(idx_region);
|
||||||
|
@ -374,140 +376,158 @@ void PrintObject::detect_surfaces_type()
|
||||||
}
|
}
|
||||||
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
|
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
|
||||||
|
|
||||||
for (int idx_layer = 0; idx_layer < int(this->layer_count()); ++ idx_layer) {
|
std::vector<Surfaces> surfaces_new;
|
||||||
Layer *layer = this->layers[idx_layer];
|
if (interface_shells)
|
||||||
LayerRegion *layerm = layer->get_region(idx_region);
|
surfaces_new.assign(this->layers.size(), Surfaces());
|
||||||
BOOST_LOG_TRIVIAL(trace) << "Detecting solid surfaces for region " << idx_region << " and layer " << layer->print_z;
|
|
||||||
// comparison happens against the *full* slices (considering all regions)
|
|
||||||
// unless internal shells are requested
|
|
||||||
Layer *upper_layer = idx_layer + 1 < this->layer_count() ? this->get_layer(idx_layer + 1) : NULL;
|
|
||||||
Layer *lower_layer = idx_layer > 0 ? this->get_layer(idx_layer - 1) : NULL;
|
|
||||||
// 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);
|
tbb::parallel_for(
|
||||||
|
tbb::blocked_range<size_t>(0, this->layers.size()),
|
||||||
|
[this, idx_region, interface_shells, &surfaces_new](const tbb::blocked_range<size_t>& range) {
|
||||||
|
for (size_t idx_layer = range.begin(); idx_layer < range.end(); ++ idx_layer) {
|
||||||
|
// BOOST_LOG_TRIVIAL(trace) << "Detecting solid surfaces for region " << idx_region << " and layer " << layer->print_z;
|
||||||
|
Layer *layer = this->layers[idx_layer];
|
||||||
|
LayerRegion *layerm = layer->get_region(idx_region);
|
||||||
|
// comparison happens against the *full* slices (considering all regions)
|
||||||
|
// unless internal shells are requested
|
||||||
|
Layer *upper_layer = idx_layer + 1 < this->layer_count() ? this->get_layer(idx_layer + 1) : NULL;
|
||||||
|
Layer *lower_layer = idx_layer > 0 ? this->get_layer(idx_layer - 1) : NULL;
|
||||||
|
// collapse very narrow parts (using the safety offset in the diff is not enough)
|
||||||
|
float offset = layerm->flow(frExternalPerimeter).scaled_width() / 10.f;
|
||||||
|
|
||||||
// find top surfaces (difference between current surfaces
|
Polygons layerm_slices_surfaces = to_polygons(layerm->slices.surfaces);
|
||||||
// of current layer and upper one)
|
|
||||||
Surfaces top;
|
// find top surfaces (difference between current surfaces
|
||||||
if (upper_layer) {
|
// of current layer and upper one)
|
||||||
// Config value $self->config->interface_shells is true, if a support is separated from the object
|
Surfaces top;
|
||||||
// by a soluble material (for example a PVA plastic).
|
if (upper_layer) {
|
||||||
Polygons upper_slices = this->config.interface_shells.value ?
|
// Config value $self->config->interface_shells is true, if a support is separated from the object
|
||||||
to_polygons(upper_layer->get_region(idx_region)->slices.surfaces) :
|
// by a soluble material (for example a PVA plastic).
|
||||||
to_polygons(upper_layer->slices);
|
Polygons upper_slices = interface_shells ?
|
||||||
surfaces_append(top,
|
to_polygons(upper_layer->get_region(idx_region)->slices.surfaces) :
|
||||||
offset2_ex(diff(layerm_slices_surfaces, upper_slices, true), -offset, offset),
|
to_polygons(upper_layer->slices);
|
||||||
stTop);
|
surfaces_append(top,
|
||||||
} else {
|
offset2_ex(diff(layerm_slices_surfaces, upper_slices, true), -offset, offset),
|
||||||
// if no upper layer, all surfaces of this one are solid
|
stTop);
|
||||||
// we clone surfaces because we're going to clear the slices collection
|
} else {
|
||||||
top = layerm->slices.surfaces;
|
// if no upper layer, all surfaces of this one are solid
|
||||||
for (Surfaces::iterator it = top.begin(); it != top.end(); ++ it)
|
// we clone surfaces because we're going to clear the slices collection
|
||||||
it->surface_type = stTop;
|
top = layerm->slices.surfaces;
|
||||||
}
|
for (Surfaces::iterator it = top.begin(); it != top.end(); ++ it)
|
||||||
|
it->surface_type = stTop;
|
||||||
// find bottom surfaces (difference between current surfaces
|
}
|
||||||
// of current layer and lower one)
|
|
||||||
Surfaces bottom;
|
// find bottom surfaces (difference between current surfaces
|
||||||
if (lower_layer) {
|
// of current layer and lower one)
|
||||||
// If we have soluble support material, don't bridge. The overhang will be squished against a soluble layer separating
|
Surfaces bottom;
|
||||||
// the support from the print.
|
if (lower_layer) {
|
||||||
SurfaceType surface_type_bottom =
|
// If we have soluble support material, don't bridge. The overhang will be squished against a soluble layer separating
|
||||||
(this->config.support_material.value && this->config.support_material_contact_distance.value == 0) ?
|
// the support from the print.
|
||||||
stBottom : stBottomBridge;
|
SurfaceType surface_type_bottom =
|
||||||
// Any surface lying on the void is a true bottom bridge (an overhang)
|
(this->config.support_material.value && this->config.support_material_contact_distance.value == 0) ?
|
||||||
surfaces_append(
|
stBottom : stBottomBridge;
|
||||||
bottom,
|
// Any surface lying on the void is a true bottom bridge (an overhang)
|
||||||
offset2_ex(
|
surfaces_append(
|
||||||
diff(layerm_slices_surfaces, to_polygons(lower_layer->slices), true),
|
bottom,
|
||||||
-offset, offset),
|
offset2_ex(
|
||||||
surface_type_bottom);
|
diff(layerm_slices_surfaces, to_polygons(lower_layer->slices), true),
|
||||||
// if user requested internal shells, we need to identify surfaces
|
-offset, offset),
|
||||||
// lying on other slices not belonging to this region
|
surface_type_bottom);
|
||||||
//FIXME Vojtech: config.internal_shells or config.interface_shells? Is it some legacy code?
|
// if user requested internal shells, we need to identify surfaces
|
||||||
// Why shall multiple regions over soluble support be treated specially?
|
// lying on other slices not belonging to this region
|
||||||
if (this->config.interface_shells.value) {
|
//FIXME Vojtech: config.internal_shells or config.interface_shells? Is it some legacy code?
|
||||||
// non-bridging bottom surfaces: any part of this layer lying
|
// Why shall multiple regions over soluble support be treated specially?
|
||||||
// on something else, excluding those lying on our own region
|
if (interface_shells) {
|
||||||
surfaces_append(
|
// non-bridging bottom surfaces: any part of this layer lying
|
||||||
bottom,
|
// on something else, excluding those lying on our own region
|
||||||
offset2_ex(
|
surfaces_append(
|
||||||
diff(
|
bottom,
|
||||||
intersection(layerm_slices_surfaces, to_polygons(lower_layer->slices)), // supported
|
offset2_ex(
|
||||||
to_polygons(lower_layer->get_region(idx_region)->slices.surfaces),
|
diff(
|
||||||
true),
|
intersection(layerm_slices_surfaces, to_polygons(lower_layer->slices)), // supported
|
||||||
-offset, offset),
|
to_polygons(lower_layer->get_region(idx_region)->slices.surfaces),
|
||||||
stBottom);
|
true),
|
||||||
|
-offset, offset),
|
||||||
|
stBottom);
|
||||||
|
}
|
||||||
|
} 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;
|
||||||
|
// if we have raft layers, consider bottom layer as a bridge
|
||||||
|
// just like any other bottom surface lying on the void
|
||||||
|
SurfaceType surface_type_bottom =
|
||||||
|
(this->config.raft_layers.value > 0 && this->config.support_material_contact_distance.value > 0) ?
|
||||||
|
stBottomBridge : stBottom;
|
||||||
|
for (Surfaces::iterator it = bottom.begin(); it != bottom.end(); ++ it)
|
||||||
|
it->surface_type = surface_type_bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
// now, if the object contained a thin membrane, we could have overlapping bottom
|
||||||
|
// and top surfaces; let's do an intersection to discover them and consider them
|
||||||
|
// as bottom surfaces (to allow for bridge detection)
|
||||||
|
if (! top.empty() && ! bottom.empty()) {
|
||||||
|
// Polygons overlapping = intersection(to_polygons(top), to_polygons(bottom));
|
||||||
|
// Slic3r::debugf " layer %d contains %d membrane(s)\n", $layerm->layer->id, scalar(@$overlapping)
|
||||||
|
// if $Slic3r::debug;
|
||||||
|
Polygons top_polygons = to_polygons(std::move(top));
|
||||||
|
top.clear();
|
||||||
|
surfaces_append(top,
|
||||||
|
#if 0
|
||||||
|
offset2_ex(diff(top_polygons, to_polygons(bottom), true), -offset, offset),
|
||||||
|
#else
|
||||||
|
diff_ex(top_polygons, to_polygons(bottom), false),
|
||||||
|
#endif
|
||||||
|
stTop);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
||||||
|
{
|
||||||
|
static int iRun = 0;
|
||||||
|
std::vector<std::pair<Slic3r::ExPolygons, SVG::ExPolygonAttributes>> expolygons_with_attributes;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
|
||||||
|
|
||||||
|
// save surfaces to layer
|
||||||
|
Surfaces &surfaces_out = interface_shells ? surfaces_new[idx_layer] : layerm->slices.surfaces;
|
||||||
|
surfaces_out.clear();
|
||||||
|
|
||||||
|
// 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,
|
||||||
|
#if 0
|
||||||
|
offset2_ex(diff(layerm_slices_surfaces, topbottom, true), -offset, offset),
|
||||||
|
#else
|
||||||
|
diff_ex(layerm_slices_surfaces, topbottom, false),
|
||||||
|
#endif
|
||||||
|
stInternal);
|
||||||
|
}
|
||||||
|
|
||||||
|
surfaces_append(surfaces_out, std::move(top));
|
||||||
|
surfaces_append(surfaces_out, std::move(bottom));
|
||||||
|
|
||||||
|
// Slic3r::debugf " layer %d has %d bottom, %d top and %d internal surfaces\n",
|
||||||
|
// $layerm->layer->id, scalar(@bottom), scalar(@top), scalar(@internal) if $Slic3r::debug;
|
||||||
|
|
||||||
|
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
||||||
|
layerm->export_region_slices_to_svg_debug("detect_surfaces_type-final");
|
||||||
|
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
|
||||||
}
|
}
|
||||||
} 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;
|
|
||||||
// if we have raft layers, consider bottom layer as a bridge
|
|
||||||
// just like any other bottom surface lying on the void
|
|
||||||
SurfaceType surface_type_bottom =
|
|
||||||
(this->config.raft_layers.value > 0 && this->config.support_material_contact_distance.value > 0) ?
|
|
||||||
stBottomBridge : stBottom;
|
|
||||||
for (Surfaces::iterator it = bottom.begin(); it != bottom.end(); ++ it)
|
|
||||||
it->surface_type = surface_type_bottom;
|
|
||||||
}
|
|
||||||
|
|
||||||
// now, if the object contained a thin membrane, we could have overlapping bottom
|
|
||||||
// and top surfaces; let's do an intersection to discover them and consider them
|
|
||||||
// as bottom surfaces (to allow for bridge detection)
|
|
||||||
if (! top.empty() && ! bottom.empty()) {
|
|
||||||
// Polygons overlapping = intersection(to_polygons(top), to_polygons(bottom));
|
|
||||||
// Slic3r::debugf " layer %d contains %d membrane(s)\n", $layerm->layer->id, scalar(@$overlapping)
|
|
||||||
// if $Slic3r::debug;
|
|
||||||
Polygons top_polygons = to_polygons(STDMOVE(top));
|
|
||||||
top.clear();
|
|
||||||
surfaces_append(top,
|
|
||||||
#if 0
|
|
||||||
offset2_ex(diff(top_polygons, to_polygons(bottom), true), -offset, offset),
|
|
||||||
#else
|
|
||||||
diff_ex(top_polygons, to_polygons(bottom), false),
|
|
||||||
#endif
|
|
||||||
stTop);
|
|
||||||
}
|
}
|
||||||
|
); // for each layer of a region
|
||||||
|
|
||||||
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
if (interface_shells) {
|
||||||
{
|
// Move surfaces_new to layerm->slices.surfaces
|
||||||
static int iRun = 0;
|
for (size_t idx_layer = 0; idx_layer < this->layers.size(); ++ idx_layer)
|
||||||
std::vector<std::pair<Slic3r::ExPolygons, SVG::ExPolygonAttributes>> expolygons_with_attributes;
|
this->layers[idx_layer]->get_region(idx_region)->slices.surfaces = std::move(surfaces_new[idx_layer]);
|
||||||
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);
|
|
||||||
}
|
|
||||||
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
|
|
||||||
|
|
||||||
// save surfaces to layer
|
|
||||||
layerm->slices.surfaces.clear();
|
|
||||||
|
|
||||||
// find internal surfaces (difference between top/bottom surfaces and others)
|
BOOST_LOG_TRIVIAL(debug) << "Detecting solid surfaces for region " << idx_region << " in parallel - end";
|
||||||
{
|
|
||||||
Polygons topbottom = to_polygons(top);
|
|
||||||
polygons_append(topbottom, to_polygons(bottom));
|
|
||||||
layerm->slices.append(
|
|
||||||
#if 0
|
|
||||||
offset2_ex(diff(layerm_slices_surfaces, topbottom, true), -offset, offset),
|
|
||||||
#else
|
|
||||||
diff_ex(layerm_slices_surfaces, topbottom, false),
|
|
||||||
#endif
|
|
||||||
stInternal);
|
|
||||||
}
|
|
||||||
|
|
||||||
layerm->slices.append(STDMOVE(top));
|
|
||||||
layerm->slices.append(STDMOVE(bottom));
|
|
||||||
|
|
||||||
// Slic3r::debugf " layer %d has %d bottom, %d top and %d internal surfaces\n",
|
|
||||||
// $layerm->layer->id, scalar(@bottom), scalar(@top), scalar(@internal) if $Slic3r::debug;
|
|
||||||
|
|
||||||
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
|
||||||
layerm->export_region_slices_to_svg_debug("detect_surfaces_type-final");
|
|
||||||
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
|
|
||||||
} // for each layer of a region
|
|
||||||
|
|
||||||
// Fill in layerm->fill_surfaces by trimming the layerm->slices by the cummulative layerm->fill_surfaces.
|
// Fill in layerm->fill_surfaces by trimming the layerm->slices by the cummulative layerm->fill_surfaces.
|
||||||
for (int idx_layer = 0; idx_layer < int(this->layer_count()); ++ idx_layer) {
|
for (int idx_layer = 0; idx_layer < int(this->layer_count()); ++ idx_layer) {
|
||||||
|
@ -642,7 +662,7 @@ PrintObject::discover_vertical_shells()
|
||||||
polygons_append(newholes, to_polygons(neighbor_layer.regions[idx_region]->fill_expolygons));
|
polygons_append(newholes, to_polygons(neighbor_layer.regions[idx_region]->fill_expolygons));
|
||||||
if (hole_first) {
|
if (hole_first) {
|
||||||
hole_first = false;
|
hole_first = false;
|
||||||
polygons_append(holes, STDMOVE(newholes));
|
polygons_append(holes, std::move(newholes));
|
||||||
}
|
}
|
||||||
else if (! holes.empty()) {
|
else if (! holes.empty()) {
|
||||||
holes = intersection(holes, newholes);
|
holes = intersection(holes, newholes);
|
||||||
|
|
Loading…
Reference in a new issue