add max_bridge_length

This commit is contained in:
Wang YB
2024-04-25 09:57:55 +08:00
parent cc68470ac8
commit b9452a91a2
12 changed files with 189 additions and 3 deletions

View File

@@ -120,6 +120,104 @@ void remove_bridges_from_contacts(
#endif /* SLIC3R_DEBUG */
}
//w28
void remove_bridges_from_contacts_select_area(
const PrintConfig &print_config, const Layer &lower_layer, const LayerRegion &layerm, float fw, Polygons &contact_polygons,const double max_bridge_length)
{
Polygons bridges;
{
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);
#if 0
Polylines overhang_perimeters = layerm.perimeters.as_polylines();
for (Polyline &polyline : overhang_perimeters)
polyline.points[0].x += 1;
overhang_perimeters = diff_pl(overhang_perimeters, lower_grown_slices);
#else
Polylines overhang_perimeters = diff_pl(layerm.perimeters().as_polylines(), lower_grown_slices);
#endif
Flow perimeter_bridge_flow = layerm.bridging_flow(frPerimeter);
const float w = float(std::max(perimeter_bridge_flow.scaled_width(), perimeter_bridge_flow.scaled_spacing())) ;
for (Polyline &polyline : overhang_perimeters)
if (polyline.is_straight()) {
polyline.extend_start(fw);
polyline.extend_end(fw);
Point pts[2] = {polyline.first_point(), polyline.last_point()};
bool supported[2] = {false, false};
for (size_t i = 0; i < lower_layer.lslices.size() && !(supported[0] && supported[1]); ++i)
for (int j = 0; j < 2; ++j)
if (!supported[j] && lower_layer.lslices_ex[i].bbox.contains(pts[j]) && lower_layer.lslices[i].contains(pts[j]))
supported[j] = true;
if (supported[0] && supported[1]) {
Polylines lines;
if (polyline.length() > max_bridge_length + 10) {
// equally divide the polyline
float len = polyline.length() / ceil(polyline.length() / max_bridge_length);
lines = polyline.equally_spaced_lines(len);
for (auto &line : lines) {
line.clip_start(fw);
line.clip_end(fw);
}
} else
lines.push_back(polyline);
polygons_append(bridges, offset(lines, 0.5f * w + 10.f));
}
}
bridges = union_(bridges);
for (const Surface &surface : layerm.fill_surfaces().surfaces)
if (surface.surface_type == stBottomBridge && surface.bridge_angle != -1) {
auto bbox = get_extents(surface.expolygon);
auto bbox_size = bbox.size();
if (bbox_size[0] < max_bridge_length && bbox_size[1] < max_bridge_length)
polygons_append(bridges, surface.expolygon);
else {
Polygons holes;
coord_t x0 = bbox.min.x();
coord_t x1 = bbox.max.x();
coord_t y0 = bbox.min.y();
coord_t y1 = bbox.max.y();
const int grid_lw = int(w );
Vec2f bridge_direction{cos(surface.bridge_angle), sin(surface.bridge_angle)};
if (fabs(bridge_direction(0)) >
fabs(bridge_direction(1))) {
int step = bbox_size(0) / ceil(bbox_size(0) / max_bridge_length);
for (int x = x0 + step; x < x1; x += step) {
Polygon poly;
poly.points = {Point(x - grid_lw, y0), Point(x + grid_lw, y0), Point(x + grid_lw, y1), Point(x - grid_lw, y1)};
holes.emplace_back(poly);
}
} else {
int step = bbox_size(1) / ceil(bbox_size(1) / max_bridge_length);
for (int y = y0 + step; y < y1; y += step) {
Polygon poly;
poly.points = {Point(x0, y - grid_lw), Point(x0, y + grid_lw), Point(x1, y + grid_lw), Point(x1, y - grid_lw)};
holes.emplace_back(poly);
}
}
auto expoly = diff_ex(surface.expolygon, holes);
polygons_append(bridges, expoly);
}
}
}
bridges = diff(bridges,
offset(layerm.unsupported_bridge_edges(), scale_(SUPPORT_MATERIAL_MARGIN), SUPPORT_SURFACES_OFFSET_PARAMETERS));
contact_polygons = diff(contact_polygons, bridges, ApplySafetyOffset::Yes);
#ifdef SLIC3R_DEBUG
static int iRun = 0;
SVG::export_expolygons(debug_out_path("support-top-contacts-remove-bridges-run%d.svg", iRun++),
{{{union_ex(offset(layerm.unsupported_bridge_edges(), scale_(SUPPORT_MATERIAL_MARGIN),
SUPPORT_SURFACES_OFFSET_PARAMETERS))},
{"unsupported_bridge_edges", "orange", 0.5f}},
{{union_ex(contact_polygons)}, {"contact_polygons", "blue", 0.5f}},
{{union_ex(bridges)}, {"bridges", "red", "black", "", scaled<coord_t>(0.1f), 0.5f}}});
#endif /* SLIC3R_DEBUG */
}
// Convert some of the intermediate layers into top/bottom interface layers as well as base interface layers.
std::pair<SupportGeneratorLayersPtr, SupportGeneratorLayersPtr> generate_interface_layers(
const PrintObjectConfig &config,

View File

@@ -22,6 +22,14 @@ void remove_bridges_from_contacts(
const LayerRegion &layerm,
float fw,
Polygons &contact_polygons);
//w28
void remove_bridges_from_contacts_select_area(
const PrintConfig &print_config,
const Layer &lower_layer,
const LayerRegion &layerm,
float fw,
Polygons &contact_polygons,
const double max_bridge_length = 0);
// Turn some of the base layers into base interface layers.
// For soluble interfaces with non-soluble bases, print maximum two first interface layers with the base

View File

@@ -1143,6 +1143,9 @@ static inline std::tuple<Polygons, Polygons, Polygons, float> detect_overhangs(
M_PI * double(object_config.support_material_threshold.value + 1) / 180. : // +1 makes the threshold inclusive
0.;
float no_interface_offset = 0.f;
//w28
double max_bridge_length = scale_(object_config.max_bridge_length.value);
bool bridge_break = object_config.max_bridge_length.value > 0;
if (layer_id == 0)
{
@@ -1275,7 +1278,9 @@ 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.
remove_bridges_from_contacts(print_config, lower_layer, *layerm, fw, diff_polygons);
//w28
if (!object_config.dont_support_bridges && bridge_break)
remove_bridges_from_contacts_select_area(print_config, lower_layer, *layerm, fw, diff_polygons, max_bridge_length);
if (diff_polygons.empty())
continue;

View File

@@ -203,11 +203,15 @@ static std::vector<std::pair<TreeSupportSettings, std::vector<size_t>>> group_me
double tan_threshold = support_threshold_auto ? 0. : tan(M_PI * double(support_threshold + 1) / 180.);
//FIXME this is a fudge constant!
auto enforcer_overhang_offset = scaled<double>(config.support_tree_tip_diameter.value);
//w28
double max_bridge_length = scale_(config.max_bridge_length.value);
bool bridge_break = config.max_bridge_length.value > 0;
//w28
size_t num_overhang_layers = support_auto ? num_object_layers : std::min(num_object_layers, std::max(size_t(support_enforce_layers), enforcers_layers.size()));
tbb::parallel_for(tbb::blocked_range<LayerIndex>(1, num_overhang_layers),
[&print_object, &config, &print_config, &enforcers_layers, &blockers_layers,
support_auto, support_enforce_layers, support_threshold_auto, tan_threshold, enforcer_overhang_offset, num_raft_layers, &throw_on_cancel, &out]
support_auto, support_enforce_layers, support_threshold_auto, tan_threshold, enforcer_overhang_offset, num_raft_layers, &throw_on_cancel, &out,bridge_break,max_bridge_length]
(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);
@@ -244,6 +248,12 @@ static std::vector<std::pair<TreeSupportSettings, std::vector<size_t>>> group_me
for (const LayerRegion *layerm : current_layer.regions())
remove_bridges_from_contacts(print_config, lower_layer, *layerm,
float(layerm->flow(frExternalPerimeter).scaled_width()), overhangs);
}
//w28
else if (!config.dont_support_bridges && bridge_break) {
for (const LayerRegion *layerm : current_layer.regions())
remove_bridges_from_contacts_select_area(print_config, lower_layer, *layerm, float(scale_(config.extrusion_width)),
overhangs, max_bridge_length);
}
}
//check_self_intersections(overhangs, "generate_overhangs1");