mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-14 01:55:59 +08:00
New parameter "support_material_min_diameter" to filter out
support overhangs with enclosing circle diameter smaller than the new parameter.
This commit is contained in:
parent
4e9f906848
commit
e2169484a3
@ -141,6 +141,10 @@ Circle<Vector> smallest_enclosing_circle_welzl(const Points &points, const typen
|
||||
}
|
||||
|
||||
// Randomized algorithm by Emo Welzl. The returned circle radius is inflated by SCALED_EPSILON.
|
||||
inline CircleSqd smallest_enclosing_circle2_welzl(const Points &points)
|
||||
{
|
||||
return smallest_enclosing_circle2_welzl<Vec2d, Points>(points, SCALED_EPSILON);
|
||||
}
|
||||
inline Circled smallest_enclosing_circle_welzl(const Points &points)
|
||||
{
|
||||
return smallest_enclosing_circle_welzl<Vec2d, Points>(points, SCALED_EPSILON);
|
||||
|
@ -1,9 +1,13 @@
|
||||
#include "BoundingBox.hpp"
|
||||
#include "ClipperUtils.hpp"
|
||||
#include "Exception.hpp"
|
||||
#include "Geometry/Circle.hpp"
|
||||
#include "Polygon.hpp"
|
||||
#include "Polyline.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <random>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
Lines Polygon::lines() const
|
||||
@ -437,6 +441,8 @@ bool remove_degenerate(Polygons &polys)
|
||||
return modified;
|
||||
}
|
||||
|
||||
// Remove polygons with absolute area smaller then threshold.
|
||||
// Thus this function may fill holes of some polygons, which may not be what one expects.
|
||||
bool remove_small(Polygons &polys, double min_area)
|
||||
{
|
||||
bool modified = false;
|
||||
@ -454,6 +460,69 @@ bool remove_small(Polygons &polys, double min_area)
|
||||
return modified;
|
||||
}
|
||||
|
||||
// Remove polygons with minimum enclosing circle diameter smaller than min_diameter.
|
||||
// Again, this function may fill holes of some polygons, which may not be what one expects.
|
||||
void remove_with_small_diameter(Polygons &polygons, double min_diameter)
|
||||
{
|
||||
coord_t min_size = coord_t(min_diameter);
|
||||
double min_diameter2 = min_diameter * min_diameter;
|
||||
std::mt19937 g;
|
||||
Points poly_shuffled;
|
||||
size_t end = 0;
|
||||
for (size_t i = 0; i < polygons.size(); ++ i) {
|
||||
Polygon &poly = polygons[i];
|
||||
bool keep = true;
|
||||
if (poly.size() < 2) {
|
||||
keep = false;
|
||||
} else {
|
||||
Point pmin = poly.front();
|
||||
Point pmax = poly.points[1];
|
||||
for (size_t k = 2; k < poly.size(); ++k) {
|
||||
const Point& p = poly.points[k];
|
||||
pmin = pmin.cwiseMin(p);
|
||||
pmax = pmax.cwiseMax(p);
|
||||
if (pmax.x() - pmin.x() > min_size || pmax.y() - pmin.y() > min_size) {
|
||||
// Diameter of the polygon is certainly above min_diameter.
|
||||
keep = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (! keep) {
|
||||
// Measure diameter of a circumscribed circle around the polygon's bounding box.
|
||||
Vec2d size = pmax.cast<double>() - pmin.cast<double>();
|
||||
if (size.squaredNorm() > min_diameter2) {
|
||||
// There is a chance that the diameter of a polygon is above min_diameter.
|
||||
poly_shuffled = poly.points;
|
||||
std::shuffle(poly_shuffled.begin(), poly_shuffled.end(), g);
|
||||
if (Geometry::CircleSqd circle = Geometry::smallest_enclosing_circle2_welzl(poly_shuffled); circle.radius2 > 0.25 * min_diameter2)
|
||||
keep = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
//FIXME implement smarter removal of holes: Holes shall not be removed if their outer contour was not removed.
|
||||
if (!keep) {
|
||||
if (poly.is_counter_clockwise()) {
|
||||
// Remove the outer contour.
|
||||
if (i < --end) {
|
||||
std::swap(poly, polygons[end])
|
||||
--i;
|
||||
}
|
||||
}
|
||||
else
|
||||
holes.emplace_back(std::move(poly));
|
||||
}
|
||||
#else
|
||||
if (keep) {
|
||||
if (end < i)
|
||||
polygons[end] = std::move(poly);
|
||||
++ end;
|
||||
}
|
||||
#endif
|
||||
polygons.erase(polygons.begin() + end, polygons.end());
|
||||
}
|
||||
}
|
||||
|
||||
void remove_collinear(Polygon &poly)
|
||||
{
|
||||
if (poly.points.size() > 2) {
|
||||
|
@ -112,7 +112,12 @@ bool remove_sticks(Polygons &polys);
|
||||
|
||||
// Remove polygons with less than 3 edges.
|
||||
bool remove_degenerate(Polygons &polys);
|
||||
// Remove polygons with absolute area smaller then threshold.
|
||||
// Thus this function may fill holes of some polygons, which may not be what one expects.
|
||||
bool remove_small(Polygons &polys, double min_area);
|
||||
// Remove polygons with minimum enclosing circle diameter smaller than min_diameter.
|
||||
// Again, this function may fill holes of some polygons, which may not be what one expects.
|
||||
void remove_with_small_diameter(Polygons& polygons, double min_diameter);
|
||||
void remove_collinear(Polygon &poly);
|
||||
void remove_collinear(Polygons &polys);
|
||||
|
||||
|
@ -434,7 +434,7 @@ static std::vector<std::string> s_Preset_print_options {
|
||||
"raft_layers", "raft_first_layer_density", "raft_first_layer_expansion", "raft_contact_distance", "raft_expansion",
|
||||
"support_material_pattern", "support_material_with_sheath", "support_material_spacing", "support_material_closing_radius", "support_material_style",
|
||||
"support_material_synchronize_layers", "support_material_angle", "support_material_interface_layers", "support_material_bottom_interface_layers",
|
||||
"support_material_interface_pattern", "support_material_interface_spacing", "support_material_interface_contact_loops",
|
||||
"support_material_interface_pattern", "support_material_interface_spacing", "support_material_interface_contact_loops", "support_material_min_diameter",
|
||||
"support_material_contact_distance", "support_material_bottom_contact_distance",
|
||||
"support_material_buildplate_only", "dont_support_bridges", "thick_bridges", "notes", "complete_objects", "extruder_clearance_radius",
|
||||
"extruder_clearance_height", "gcode_comments", "gcode_label_objects", "output_filename_format", "post_process", "perimeter_extruder",
|
||||
|
@ -2670,6 +2670,18 @@ void PrintConfigDef::init_fff_params()
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionEnum<SupportMaterialPattern>(smpRectilinear));
|
||||
|
||||
def = this->add("support_material_min_diameter", coFloat);
|
||||
def->label = L("Minimum support size");
|
||||
def->category = L("Support material");
|
||||
def->tooltip = L("Minimum diameter of an overhang to be supported. "
|
||||
"Increasing this value will filter out likely unneccessary supports of tiny overhangs protruding from an object body. "
|
||||
"However filtering small overhangs may leave some long thin features unsupported, "
|
||||
"requiring user intervention using the paint-on supports tool.");
|
||||
def->sidetext = L("mm");
|
||||
def->min = 0;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(0));
|
||||
|
||||
def = this->add("support_material_spacing", coFloat);
|
||||
def->label = L("Pattern spacing");
|
||||
def->category = L("Support material");
|
||||
|
@ -492,6 +492,7 @@ PRINT_CONFIG_CLASS_DEFINE(
|
||||
((ConfigOptionFloat, support_material_interface_spacing))
|
||||
((ConfigOptionFloatOrPercent, support_material_interface_speed))
|
||||
((ConfigOptionEnum<SupportMaterialPattern>, support_material_pattern))
|
||||
((ConfigOptionFloat, support_material_min_diameter))
|
||||
((ConfigOptionEnum<SupportMaterialInterfacePattern>, support_material_interface_pattern))
|
||||
// Morphological closing of support areas. Only used for "sung" supports.
|
||||
((ConfigOptionFloat, support_material_closing_radius))
|
||||
|
@ -554,6 +554,7 @@ bool PrintObject::invalidate_state_by_config_options(
|
||||
|| opt_key == "support_material_interface_contact_loops"
|
||||
|| opt_key == "support_material_interface_extruder"
|
||||
|| opt_key == "support_material_interface_spacing"
|
||||
|| opt_key == "support_material_min_diameter"
|
||||
|| opt_key == "support_material_pattern"
|
||||
|| opt_key == "support_material_style"
|
||||
|| opt_key == "support_material_xy_spacing"
|
||||
|
@ -1446,7 +1446,9 @@ static inline std::tuple<Polygons, Polygons, Polygons, float> detect_overhangs(
|
||||
const PrintObjectConfig &object_config,
|
||||
SupportAnnotations &annotations,
|
||||
SlicesMarginCache &slices_margin,
|
||||
const double gap_xy
|
||||
const double gap_xy,
|
||||
// Scaled, minimum diameter of a support island to be supported.
|
||||
const double min_support_diameter
|
||||
#ifdef SLIC3R_DEBUG
|
||||
, size_t iRun
|
||||
#endif // SLIC3R_DEBUG
|
||||
@ -1601,6 +1603,10 @@ static inline std::tuple<Polygons, Polygons, Polygons, float> detect_overhangs(
|
||||
SupportMaterialInternal::remove_bridges_from_contacts(
|
||||
print_config, lower_layer, lower_layer_polygons, *layerm, fw, diff_polygons);
|
||||
|
||||
if (min_support_diameter > 0)
|
||||
// Remove polygons with their circumscribed circle radius smaller than min_diameter.
|
||||
remove_with_small_diameter(diff_polygons, min_support_diameter);
|
||||
|
||||
if (diff_polygons.empty())
|
||||
continue;
|
||||
|
||||
@ -1995,6 +2001,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(this->has_raft() ? 0 : 1, num_layers),
|
||||
[this, &object, &annotations, &layer_storage, &layer_storage_mutex, &contact_out]
|
||||
(const tbb::blocked_range<size_t>& range) {
|
||||
const double min_support_diameter = scaled<double>(object.config().support_material_min_diameter.value);
|
||||
for (size_t layer_id = range.begin(); layer_id < range.end(); ++ layer_id)
|
||||
{
|
||||
const Layer &layer = *object.layers()[layer_id];
|
||||
@ -2002,7 +2009,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
|
||||
SlicesMarginCache slices_margin;
|
||||
|
||||
auto [overhang_polygons, contact_polygons, enforcer_polygons, no_interface_offset] =
|
||||
detect_overhangs(layer, layer_id, lower_layer_polygons, *m_print_config, *m_object_config, annotations, slices_margin, m_support_params.gap_xy
|
||||
detect_overhangs(layer, layer_id, lower_layer_polygons, *m_print_config, *m_object_config, annotations, slices_margin, m_support_params.gap_xy, min_support_diameter
|
||||
#ifdef SLIC3R_DEBUG
|
||||
, iRun
|
||||
#endif // SLIC3R_DEBUG
|
||||
|
@ -282,7 +282,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config)
|
||||
bool have_support_soluble = have_support_material && config->opt_float("support_material_contact_distance") == 0;
|
||||
auto support_material_style = config->opt_enum<SupportMaterialStyle>("support_material_style");
|
||||
for (auto el : { "support_material_style", "support_material_pattern", "support_material_with_sheath",
|
||||
"support_material_spacing", "support_material_angle",
|
||||
"support_material_spacing", "support_material_angle", "support_material_min_diameter",
|
||||
"support_material_interface_pattern", "support_material_interface_layers",
|
||||
"dont_support_bridges", "support_material_extrusion_width", "support_material_contact_distance",
|
||||
"support_material_xy_spacing" })
|
||||
|
@ -1535,6 +1535,7 @@ void TabPrint::build()
|
||||
optgroup->append_single_option_line("support_material", category_path + "generate-support-material");
|
||||
optgroup->append_single_option_line("support_material_auto", category_path + "auto-generated-supports");
|
||||
optgroup->append_single_option_line("support_material_threshold", category_path + "overhang-threshold");
|
||||
optgroup->append_single_option_line("support_material_min_diameter", category_path + "support-min-diameter");
|
||||
optgroup->append_single_option_line("support_material_enforce_layers", category_path + "enforce-support-for-the-first");
|
||||
optgroup->append_single_option_line("raft_first_layer_density", category_path + "raft-first-layer-density");
|
||||
optgroup->append_single_option_line("raft_first_layer_expansion", category_path + "raft-first-layer-expansion");
|
||||
|
Loading…
x
Reference in New Issue
Block a user