mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-08 23:46:24 -06:00
Make Overhang Printable (#1615)
* First working conical overhang impl * Add settings for Make overhang printable * Added an Advanced setting to the Quality menu for Make overhang printable * Allow toggling the feature and adjusting the angle threshold * Retain recesses in the bottom of the model when "Make Overhangs Printable" is turned on * Add settings for Make overhang printable hole size * Allow disabling conical overhang per modifier * Should check upper layer instead * Skip unnecessary layers * Apply conical overhang before any size compensation which fixs the `lslices` not being updated issue and also the elephant foot compensation * 1. Fix an issue that changing make_overhang_printable related parameters won't clear caches properly. 2. Tweak the logic of make_overhang_printable parameter so that it works for per region/object/print level. Remove make_overhang_printable_disable parameter. * Change default make_overhang_printable_angle to 55 * One more missing commit * 1. Skip checking default_region_config()->make_overhang_printable 2. Handle make_overhang_printable_angle and make_overhang_printable_hole_size value change --------- Co-authored-by: David Bern <odie5533@users.noreply.github.com> Co-authored-by: SoftFever <softfeverever@gmail.com>
This commit is contained in:
parent
ab6649da8a
commit
b571318be8
11 changed files with 164 additions and 5 deletions
|
@ -777,6 +777,7 @@ void PrintObject::slice()
|
|||
m_layers = new_layers(this, generate_object_layers(m_slicing_params, layer_height_profile));
|
||||
this->slice_volumes();
|
||||
m_print->throw_if_canceled();
|
||||
|
||||
int firstLayerReplacedBy = 0;
|
||||
|
||||
#if 1
|
||||
|
@ -1028,6 +1029,8 @@ void PrintObject::slice_volumes()
|
|||
apply_mm_segmentation(*this, [print]() { print->throw_if_canceled(); });
|
||||
}
|
||||
|
||||
this->apply_conical_overhang();
|
||||
m_print->throw_if_canceled();
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << "Slicing volumes - make_slices in parallel - begin";
|
||||
{
|
||||
|
@ -1166,6 +1169,107 @@ void PrintObject::slice_volumes()
|
|||
BOOST_LOG_TRIVIAL(debug) << "Slicing volumes - make_slices in parallel - end";
|
||||
}
|
||||
|
||||
void PrintObject::apply_conical_overhang() {
|
||||
BOOST_LOG_TRIVIAL(info) << "Make overhang printable...";
|
||||
|
||||
if (m_layers.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const double conical_overhang_angle = this->config().make_overhang_printable_angle;
|
||||
if (conical_overhang_angle == 90.0) {
|
||||
return;
|
||||
}
|
||||
const double angle_radians = conical_overhang_angle * M_PI / 180.;
|
||||
const double max_hole_area = this->config().make_overhang_printable_hole_size; // in MM^2
|
||||
const double tan_angle = tan(angle_radians); // the XY-component of the angle
|
||||
BOOST_LOG_TRIVIAL(info) << "angle " << angle_radians << " maxHoleArea " << max_hole_area << " tan_angle "
|
||||
<< tan_angle;
|
||||
const coordf_t layer_thickness = m_config.layer_height.value;
|
||||
const coordf_t max_dist_from_lower_layer = tan_angle * layer_thickness; // max dist which can be bridged, in MM
|
||||
BOOST_LOG_TRIVIAL(info) << "layer_thickness " << layer_thickness << " max_dist_from_lower_layer "
|
||||
<< max_dist_from_lower_layer;
|
||||
|
||||
// Pre-scale config
|
||||
const coordf_t scaled_max_dist_from_lower_layer = -float(scale_(max_dist_from_lower_layer));
|
||||
const coordf_t scaled_max_hole_area = float(scale_(scale_(max_hole_area)));
|
||||
|
||||
|
||||
for (auto i = m_layers.rbegin() + 1; i != m_layers.rend(); ++i) {
|
||||
m_print->throw_if_canceled();
|
||||
Layer *layer = *i;
|
||||
Layer *upper_layer = layer->upper_layer;
|
||||
|
||||
if (upper_layer->empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip if entire layer has this disabled
|
||||
if (std::all_of(layer->m_regions.begin(), layer->m_regions.end(),
|
||||
[](const LayerRegion *r) { return r->slices.empty() || !r->region().config().make_overhang_printable; })) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//layer->export_region_slices_to_svg_debug("layer_before_conical_overhang");
|
||||
//upper_layer->export_region_slices_to_svg_debug("upper_layer_before_conical_overhang");
|
||||
|
||||
|
||||
// Merge the upper layer because we want to offset the entire layer uniformly, otherwise
|
||||
// the model could break at the region boundary.
|
||||
auto upper_poly = upper_layer->merged(float(SCALED_EPSILON));
|
||||
upper_poly = union_ex(upper_poly);
|
||||
|
||||
// Avoid closing up of recessed holes in the base of a model.
|
||||
// Detects when a hole is completely covered by the layer above and removes the hole from the layer above before
|
||||
// adding it in.
|
||||
// This should have no effect any time a hole in a layer interacts with any polygon in the layer above
|
||||
if (scaled_max_hole_area > 0.0) {
|
||||
// Merge layer for the same reason
|
||||
auto current_poly = layer->merged(float(SCALED_EPSILON));
|
||||
current_poly = union_ex(current_poly);
|
||||
|
||||
// Now go through all the holes in the current layer and check if they intersect anything in the layer above
|
||||
// If not, then they're the top of a hole and should be cut from the layer above before the union
|
||||
for (auto layer_polygon : current_poly) {
|
||||
for (auto hole : layer_polygon.holes) {
|
||||
if (std::abs(hole.area()) < scaled_max_hole_area) {
|
||||
ExPolygon hole_poly(hole);
|
||||
auto hole_with_above = intersection_ex(upper_poly, hole_poly);
|
||||
if (!hole_with_above.empty()) {
|
||||
// The hole had some intersection with the above layer, check if it's a complete overlap
|
||||
auto hole_difference = xor_ex(hole_with_above, hole_poly);
|
||||
if (hole_difference.empty()) {
|
||||
// The layer above completely cover it, remove it from the layer above
|
||||
upper_poly = diff_ex(upper_poly, hole_poly);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now offset the upper layer to be added into current layer
|
||||
upper_poly = offset_ex(upper_poly, scaled_max_dist_from_lower_layer);
|
||||
|
||||
for (size_t region_id = 0; region_id < this->num_printing_regions(); ++region_id) {
|
||||
// export_to_svg(debug_out_path("Surface-obj-%d-layer-%d-region-%d.svg", id().id, layer->id(), region_id).c_str(),
|
||||
// layer->m_regions[region_id]->slices.surfaces);
|
||||
|
||||
// Disable on given region
|
||||
if (!upper_layer->m_regions[region_id]->region().config().make_overhang_printable) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Calculate the scaled upper poly that belongs to current region
|
||||
auto p = intersection_ex(upper_layer->m_regions[region_id]->slices.surfaces, upper_poly);
|
||||
// And now union it
|
||||
ExPolygons layer_polygons = to_expolygons(layer->m_regions[region_id]->slices.surfaces);
|
||||
layer->m_regions[region_id]->slices.set(union_ex(layer_polygons, p), stInternal);
|
||||
}
|
||||
//layer->export_region_slices_to_svg_debug("layer_after_conical_overhang");
|
||||
}
|
||||
}
|
||||
|
||||
//BBS: this function is used to offset contour and holes of expolygons seperately by different value
|
||||
ExPolygons PrintObject::_shrink_contour_holes(double contour_delta, double hole_delta, const ExPolygons& polys) const
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue