Fixing overlaps of organic supports: Base vs. interface layers.

This commit is contained in:
Vojtech Bubnik 2023-02-08 14:40:41 +01:00
parent 56c4cfb202
commit 9ab88d75e0
2 changed files with 54 additions and 44 deletions

View File

@ -2936,7 +2936,11 @@ static void finalize_interface_and_support_areas(
std::function<void()> throw_on_cancel) std::function<void()> throw_on_cancel)
{ {
InterfacePreference interface_pref = config.interface_preference; // InterfacePreference::SupportLinesOverwriteInterface; assert(std::all_of(bottom_contacts.begin(), bottom_contacts.end(), [](auto *p) { return p == nullptr; }));
// assert(std::all_of(top_contacts.begin(), top_contacts.end(), [](auto* p) { return p == nullptr; }));
assert(std::all_of(intermediate_layers.begin(), intermediate_layers.end(), [](auto* p) { return p == nullptr; }));
InterfacePreference interface_pref = config.interface_preference; // InterfacePreference::InterfaceAreaOverwritesSupport;
#ifdef SLIC3R_TREESUPPORTS_PROGRESS #ifdef SLIC3R_TREESUPPORTS_PROGRESS
double progress_total = TREE_PROGRESS_PRECALC_AVO + TREE_PROGRESS_PRECALC_COLL + TREE_PROGRESS_GENERATE_NODES + TREE_PROGRESS_AREA_CALC + TREE_PROGRESS_GENERATE_BRANCH_AREAS + TREE_PROGRESS_SMOOTH_BRANCH_AREAS; double progress_total = TREE_PROGRESS_PRECALC_AVO + TREE_PROGRESS_PRECALC_COLL + TREE_PROGRESS_GENERATE_NODES + TREE_PROGRESS_AREA_CALC + TREE_PROGRESS_GENERATE_BRANCH_AREAS + TREE_PROGRESS_SMOOTH_BRANCH_AREAS;
@ -2947,29 +2951,41 @@ static void finalize_interface_and_support_areas(
tbb::parallel_for(tbb::blocked_range<size_t>(0, support_layer_storage.size()), tbb::parallel_for(tbb::blocked_range<size_t>(0, support_layer_storage.size()),
[&](const tbb::blocked_range<size_t> &range) { [&](const tbb::blocked_range<size_t> &range) {
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) { for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) {
// Most of the time in this function is this union call. Can take 300+ ms when a lot of areas are to be unioned.
support_layer_storage[layer_idx] = smooth_outward(union_(support_layer_storage[layer_idx]), config.support_line_width); //FIXME was .smooth(50);
//smooth_outward(closing(std::move(bottom), closing_distance + minimum_island_radius, closing_distance, SUPPORT_SURFACES_OFFSET_PARAMETERS), smoothing_distance) :
// simplify a bit, to ensure the output does not contain outrageous amounts of vertices. Should not be necessary, just a precaution.
support_layer_storage[layer_idx] = polygons_simplify(support_layer_storage[layer_idx], std::min(scaled<double>(0.03), double(config.resolution)));
// Subtract support lines of the branches from the roof // Subtract support lines of the branches from the roof
SupportGeneratorLayer*& support_roof = top_contacts[layer_idx]; SupportGeneratorLayer *support_roof = top_contacts[layer_idx];
if (! support_roof_storage[layer_idx].empty() || support_roof != nullptr) { Polygons support_roof_polygons;
if (support_roof == nullptr) {
support_roof = &layer_allocate(layer_storage, layer_storage_mutex, SupporLayerType::TopContact, print_object.slicing_parameters(), layer_idx);
support_roof->polygons = union_(support_roof_storage[layer_idx]);
} else
support_roof->polygons = union_(support_roof->polygons, support_roof_storage[layer_idx]);
if (! support_roof->polygons.empty() && if (Polygons &src = support_roof_storage[layer_idx]; ! src.empty()) {
area(intersection(support_layer_storage[layer_idx], support_roof->polygons)) > tiny_area_threshold) { if (support_roof != nullptr && ! support_roof->polygons.empty()) {
support_roof_polygons = union_(src, support_roof->polygons);
support_roof->polygons.clear();
} else
support_roof_polygons = std::move(src);
} else if (support_roof != nullptr) {
support_roof_polygons = std::move(support_roof->polygons);
support_roof->polygons.clear();
}
assert(intermediate_layers[layer_idx] == nullptr);
Polygons base_layer_polygons = std::move(support_layer_storage[layer_idx]);
if (! base_layer_polygons.empty()) {
// Most of the time in this function is this union call. Can take 300+ ms when a lot of areas are to be unioned.
base_layer_polygons = smooth_outward(union_(base_layer_polygons), config.support_line_width); //FIXME was .smooth(50);
//smooth_outward(closing(std::move(bottom), closing_distance + minimum_island_radius, closing_distance, SUPPORT_SURFACES_OFFSET_PARAMETERS), smoothing_distance) :
// simplify a bit, to ensure the output does not contain outrageous amounts of vertices. Should not be necessary, just a precaution.
base_layer_polygons = polygons_simplify(base_layer_polygons, std::min(scaled<double>(0.03), double(config.resolution)));
}
if (! support_roof_polygons.empty() && ! base_layer_polygons.empty()) {
// if (area(intersection(base_layer_polygons, support_roof_polygons)) > tiny_area_threshold)
{
switch (interface_pref) { switch (interface_pref) {
case InterfacePreference::InterfaceAreaOverwritesSupport: case InterfacePreference::InterfaceAreaOverwritesSupport:
support_layer_storage[layer_idx] = diff(support_layer_storage[layer_idx], support_roof->polygons); base_layer_polygons = diff(base_layer_polygons, support_roof_polygons);
break; break;
case InterfacePreference::SupportAreaOverwritesInterface: case InterfacePreference::SupportAreaOverwritesInterface:
support_roof->polygons = diff(support_roof->polygons, support_layer_storage[layer_idx]); support_roof_polygons = diff(support_roof_polygons, base_layer_polygons);
break; break;
//FIXME //FIXME
#if 1 #if 1
@ -2984,14 +3000,14 @@ static void finalize_interface_and_support_areas(
Polygons interface_lines = offset(to_polylines( Polygons interface_lines = offset(to_polylines(
generate_support_infill_lines(support_roof->polygons, true, layer_idx, config.support_roof_line_distance)), generate_support_infill_lines(support_roof->polygons, true, layer_idx, config.support_roof_line_distance)),
config.support_roof_line_width / 2); config.support_roof_line_width / 2);
support_layer_storage[layer_idx] = diff(support_layer_storage[layer_idx], interface_lines); base_layer_polygons = diff(base_layer_polygons, interface_lines);
break; break;
} }
case InterfacePreference::SupportLinesOverwriteInterface: case InterfacePreference::SupportLinesOverwriteInterface:
{ {
// Hatch the support roof interfaces, offset them by their line width and subtract them from support base. // Hatch the support roof interfaces, offset them by their line width and subtract them from support base.
Polygons tree_lines = union_(offset(to_polylines( Polygons tree_lines = union_(offset(to_polylines(
generate_support_infill_lines(support_layer_storage[layer_idx], false, layer_idx, config.support_line_distance, true)), generate_support_infill_lines(base_layer_polygons, false, layer_idx, config.support_line_distance, true)),
config.support_line_width / 2)); config.support_line_width / 2));
// do not draw roof where the tree is. I prefer it this way as otherwise the roof may cut of a branch from its support below. // do not draw roof where the tree is. I prefer it this way as otherwise the roof may cut of a branch from its support below.
support_roof->polygons = diff(support_roof->polygons, tree_lines); support_roof->polygons = diff(support_roof->polygons, tree_lines);
@ -3005,10 +3021,10 @@ static void finalize_interface_and_support_areas(
} }
// Subtract support floors from the support area and add them to the support floor instead. // Subtract support floors from the support area and add them to the support floor instead.
if (config.support_bottom_layers > 0 && !support_layer_storage[layer_idx].empty()) { if (config.support_bottom_layers > 0 && ! base_layer_polygons.empty()) {
SupportGeneratorLayer*& support_bottom = bottom_contacts[layer_idx]; SupportGeneratorLayer*& support_bottom = bottom_contacts[layer_idx];
Polygons layer_outset = diff_clipped( Polygons layer_outset = diff_clipped(
config.support_bottom_offset > 0 ? offset(support_layer_storage[layer_idx], config.support_bottom_offset, jtMiter, 1.2) : support_layer_storage[layer_idx], config.support_bottom_offset > 0 ? offset(base_layer_polygons, config.support_bottom_offset, jtMiter, 1.2) : base_layer_polygons,
volumes.getCollision(0, layer_idx, false)); volumes.getCollision(0, layer_idx, false));
Polygons floor_layer; Polygons floor_layer;
size_t layers_below = 0; size_t layers_below = 0;
@ -3026,15 +3042,18 @@ static void finalize_interface_and_support_areas(
if (support_bottom == nullptr) if (support_bottom == nullptr)
support_bottom = &layer_allocate(layer_storage, layer_storage_mutex, SupporLayerType::BottomContact, print_object.slicing_parameters(), layer_idx); support_bottom = &layer_allocate(layer_storage, layer_storage_mutex, SupporLayerType::BottomContact, print_object.slicing_parameters(), layer_idx);
support_bottom->polygons = union_(floor_layer, support_bottom->polygons); support_bottom->polygons = union_(floor_layer, support_bottom->polygons);
support_layer_storage[layer_idx] = diff_clipped(support_layer_storage[layer_idx], offset(support_bottom->polygons, scaled<float>(0.01), jtMiter, 1.2)); // Subtract the support floor from the normal support. base_layer_polygons = diff_clipped(base_layer_polygons, offset(support_bottom->polygons, scaled<float>(0.01), jtMiter, 1.2)); // Subtract the support floor from the normal support.
} }
} }
if (! support_layer_storage[layer_idx].empty()) { if (! support_roof_polygons.empty()) {
SupportGeneratorLayer *&l = intermediate_layers[layer_idx]; if (support_roof == nullptr)
if (l == nullptr) support_roof = top_contacts[layer_idx] = &layer_allocate(layer_storage, layer_storage_mutex, SupporLayerType::TopContact, print_object.slicing_parameters(), layer_idx);
l = &layer_allocate(layer_storage, layer_storage_mutex, SupporLayerType::Base, print_object.slicing_parameters(), layer_idx); support_roof->polygons = union_(support_roof_polygons);
append(l->polygons, union_(support_layer_storage[layer_idx])); }
if (! base_layer_polygons.empty()) {
SupportGeneratorLayer *base_layer = intermediate_layers[layer_idx] = &layer_allocate(layer_storage, layer_storage_mutex, SupporLayerType::Base, print_object.slicing_parameters(), layer_idx);
base_layer->polygons = union_(base_layer_polygons);
} }
#ifdef SLIC3R_TREESUPPORTS_PROGRESS #ifdef SLIC3R_TREESUPPORTS_PROGRESS
@ -3911,25 +3930,15 @@ static void slice_branches(
params.closing_radius = float(print_object.config().slice_closing_radius.value); params.closing_radius = float(print_object.config().slice_closing_radius.value);
params.mode = MeshSlicingParams::SlicingMode::Positive; params.mode = MeshSlicingParams::SlicingMode::Positive;
std::vector<ExPolygons> slices = slice_mesh_ex(cummulative_mesh, slice_z, params, throw_on_cancel); std::vector<ExPolygons> slices = slice_mesh_ex(cummulative_mesh, slice_z, params, throw_on_cancel);
for (size_t layer_idx = 0; layer_idx < slice_z.size(); ++ layer_idx)
if (! slices[layer_idx].empty()) {
SupportGeneratorLayer *&l = intermediate_layers[layer_idx];
if (l == nullptr)
l = &layer_allocate(layer_storage, SupporLayerType::Base, slicing_params, layer_idx);
append(l->polygons, to_polygons(std::move(slices[layer_idx])));
}
// Trim the slices. // Trim the slices.
tbb::parallel_for(tbb::blocked_range<size_t>(0, intermediate_layers.size()), std::vector<Polygons> support_layer_storage(move_bounds.size());
tbb::parallel_for(tbb::blocked_range<size_t>(0, slices.size()),
[&](const tbb::blocked_range<size_t> &range) { [&](const tbb::blocked_range<size_t> &range) {
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx)
if (SupportGeneratorLayer *layer = intermediate_layers[layer_idx]; layer) { if (ExPolygons &src = slices[layer_idx]; ! src.empty())
Polygons &poly = intermediate_layers[layer_idx]->polygons; support_layer_storage[layer_idx] = diff_clipped(to_polygons(std::move(src)), volumes.getCollision(0, layer_idx, true));
poly = diff_clipped(poly, volumes.getCollision(0, layer_idx, true));
}
}); });
std::vector<Polygons> support_layer_storage(move_bounds.size());
std::vector<Polygons> support_roof_storage(move_bounds.size()); std::vector<Polygons> support_roof_storage(move_bounds.size());
finalize_interface_and_support_areas(print_object, volumes, config, overhangs, support_layer_storage, support_roof_storage, finalize_interface_and_support_areas(print_object, volumes, config, overhangs, support_layer_storage, support_roof_storage,
bottom_contacts, top_contacts, intermediate_layers, layer_storage, throw_on_cancel); bottom_contacts, top_contacts, intermediate_layers, layer_storage, throw_on_cancel);

View File

@ -310,7 +310,8 @@ struct TreeSupportSettings
// interface_preference = interface_map.at(mesh_group_settings.get<std::string>("support_interface_priority")); // interface_preference = interface_map.at(mesh_group_settings.get<std::string>("support_interface_priority"));
//FIXME this was the default //FIXME this was the default
// interface_preference = InterfacePreference::SupportLinesOverwriteInterface; // interface_preference = InterfacePreference::SupportLinesOverwriteInterface;
interface_preference = InterfacePreference::SupportAreaOverwritesInterface; //interface_preference = InterfacePreference::SupportAreaOverwritesInterface;
interface_preference = InterfacePreference::InterfaceAreaOverwritesSupport;
} }
private: private: