Organic supports: Adding bridge detection using the same algorithms

as the regular supports.
Partial fix to #9493
This commit is contained in:
Vojtech Bubnik 2023-02-09 16:47:57 +01:00
parent 957572fb8a
commit f1977b07be
4 changed files with 97 additions and 81 deletions

View File

@ -361,6 +361,8 @@ inline Slic3r::Polygons expand(const Slic3r::Polygon &polygon, const float del
{ assert(delta > 0); return offset(polygon, delta, joinType, miterLimit); }
inline Slic3r::Polygons expand(const Slic3r::Polygons &polygons, const float delta, ClipperLib::JoinType joinType = DefaultJoinType, double miterLimit = DefaultMiterLimit)
{ assert(delta > 0); return offset(polygons, delta, joinType, miterLimit); }
inline Slic3r::Polygons expand(const Slic3r::ExPolygons &polygons, const float delta, ClipperLib::JoinType joinType = DefaultJoinType, double miterLimit = DefaultMiterLimit)
{ assert(delta > 0); return offset(polygons, delta, joinType, miterLimit); }
inline Slic3r::ExPolygons expand_ex(const Slic3r::Polygons &polygons, const float delta, ClipperLib::JoinType joinType = DefaultJoinType, double miterLimit = DefaultMiterLimit)
{ assert(delta > 0); return offset_ex(polygons, delta, joinType, miterLimit); }
// Input polygons for shrinking shall be "normalized": There must be no overlap / intersections between the input polygons.

View File

@ -1260,11 +1260,11 @@ namespace SupportMaterialInternal {
collect_bridging_perimeter_areas(*static_cast<const ExtrusionLoop*>(ee), expansion_scaled, out);
}
}
}
static void remove_bridges_from_contacts(
void remove_bridges_from_contacts(
const PrintConfig &print_config,
const Layer &lower_layer,
const Polygons &lower_layer_polygons,
const LayerRegion &layerm,
float fw,
Polygons &contact_polygons)
@ -1273,7 +1273,7 @@ namespace SupportMaterialInternal {
Polygons bridges;
{
// Surface supporting this layer, expanded by 0.5 * nozzle_diameter, as we consider this kind of overhang to be sufficiently supported.
Polygons lower_grown_slices = expand(lower_layer_polygons,
Polygons lower_grown_slices = expand(lower_layer.lslices,
//FIXME to mimic the decision in the perimeter generator, we should use half the external perimeter width.
0.5f * float(scale_(print_config.nozzle_diameter.get_at(layerm.region().config().perimeter_extruder-1))),
SUPPORT_SURFACES_OFFSET_PARAMETERS);
@ -1341,7 +1341,6 @@ namespace SupportMaterialInternal {
{ { union_ex(bridges) }, { "bridges", "red", "black", "", scaled<coord_t>(0.1f), 0.5f } } });
#endif /* SLIC3R_DEBUG */
}
}
std::vector<Polygons> PrintObjectSupportMaterial::buildplate_covered(const PrintObject &object) const
{
@ -1558,8 +1557,7 @@ static inline std::tuple<Polygons, Polygons, Polygons, float> detect_overhangs(
if (object_config.dont_support_bridges)
//FIXME Expensive, potentially not precise enough. Misses gap fill extrusions, which bridge.
SupportMaterialInternal::remove_bridges_from_contacts(
print_config, lower_layer, lower_layer_polygons, *layerm, fw, diff_polygons);
remove_bridges_from_contacts(print_config, lower_layer, *layerm, fw, diff_polygons);
if (diff_polygons.empty())
continue;

View File

@ -147,6 +147,15 @@ struct SupportParameters {
bool with_sheath;
};
// Remove bridges from support contact areas.
// To be called if PrintObjectConfig::dont_support_bridges.
void remove_bridges_from_contacts(
const PrintConfig &print_config,
const Layer &lower_layer,
const LayerRegion &layerm,
float fw,
Polygons &contact_polygons);
// Generate raft layers, also expand the 1st support layer
// in case there is no raft layer to improve support adhesion.
SupportGeneratorLayersPtr generate_raft_base(

View File

@ -226,6 +226,7 @@ void tree_supports_show_error(std::string_view message, bool critical)
{
std::vector<Polygons> out(print_object.layer_count(), Polygons{});
const PrintConfig &print_config = print_object.print()->config();
const PrintObjectConfig &config = print_object.config();
const bool support_auto = config.support_material.value && config.support_material_auto.value;
const int support_enforce_layers = config.support_material_enforce_layers.value;
@ -242,7 +243,8 @@ void tree_supports_show_error(std::string_view message, bool critical)
size_t num_overhang_layers = support_auto ? out.size() : std::max(size_t(support_enforce_layers), enforcers_layers.size());
tbb::parallel_for(tbb::blocked_range<LayerIndex>(1, num_overhang_layers),
[&print_object, &enforcers_layers, &blockers_layers, support_auto, support_enforce_layers, support_threshold_auto, tan_threshold, enforcer_overhang_offset, &throw_on_cancel, &out]
[&print_object, &config, &print_config, &enforcers_layers, &blockers_layers,
support_auto, support_enforce_layers, support_threshold_auto, tan_threshold, enforcer_overhang_offset, &throw_on_cancel, &out]
(const tbb::blocked_range<LayerIndex> &range) {
for (LayerIndex layer_id = range.begin(); layer_id < range.end(); ++ layer_id) {
const Layer &current_layer = *print_object.get_layer(layer_id);
@ -275,6 +277,11 @@ void tree_supports_show_error(std::string_view message, bool critical)
}
if (! (enforced_layer || blockers_layers.empty() || blockers_layers[layer_id].empty()))
overhangs = diff(overhangs, blockers_layers[layer_id], ApplySafetyOffset::Yes);
if (config.dont_support_bridges) {
for (const LayerRegion *layerm : current_layer.regions())
remove_bridges_from_contacts(print_config, lower_layer, *layerm,
float(layerm->flow(frExternalPerimeter).scaled_width()), overhangs);
}
}
//check_self_intersections(overhangs, "generate_overhangs1");
if (! enforcers_layers.empty() && ! enforcers_layers[layer_id].empty()) {