New support settings: "support_material_auto" controls, whether
the supports shall be generated automatically. If not, only supports inside support enforcers are generated.
This commit is contained in:
parent
2a81408e8b
commit
6de8e21131
8 changed files with 63 additions and 43 deletions
|
@ -1225,7 +1225,7 @@ bool EdgeGrid::Grid::signed_distance(const Point &pt, coord_t search_radius, coo
|
|||
return true;
|
||||
}
|
||||
|
||||
Polygons EdgeGrid::Grid::contours_simplified(coord_t offset) const
|
||||
Polygons EdgeGrid::Grid::contours_simplified(coord_t offset, bool fill_holes) const
|
||||
{
|
||||
assert(std::abs(2 * offset) < m_resolution);
|
||||
|
||||
|
@ -1239,7 +1239,7 @@ Polygons EdgeGrid::Grid::contours_simplified(coord_t offset) const
|
|||
cell_inside[r * cell_cols + c] = cell_inside_or_crossing(r - 1, c - 1);
|
||||
// Fill in empty cells, which have a left / right neighbor filled.
|
||||
// Fill in empty cells, which have the top / bottom neighbor filled.
|
||||
{
|
||||
if (fill_holes) {
|
||||
std::vector<char> cell_inside2(cell_inside);
|
||||
for (int r = 1; r + 1 < int(cell_rows); ++ r) {
|
||||
for (int c = 1; c + 1 < int(cell_cols); ++ c) {
|
||||
|
|
|
@ -58,7 +58,7 @@ public:
|
|||
const size_t cols() const { return m_cols; }
|
||||
|
||||
// For supports: Contours enclosing the rasterized edges.
|
||||
Polygons contours_simplified(coord_t offset) const;
|
||||
Polygons contours_simplified(coord_t offset, bool fill_holes) const;
|
||||
|
||||
protected:
|
||||
struct Cell {
|
||||
|
|
|
@ -1696,6 +1696,14 @@ PrintConfigDef::PrintConfigDef()
|
|||
def->cli = "support-material!";
|
||||
def->default_value = new ConfigOptionBool(false);
|
||||
|
||||
def = this->add("support_material_auto", coBool);
|
||||
def->label = L("Auto generated supports");
|
||||
def->category = L("Support material");
|
||||
def->tooltip = L("If checked, supports will be generated automatically based on the overhang threshold value."\
|
||||
" If unchecked, supports will be generated inside the \"Support Enforcer\" volumes only.");
|
||||
def->cli = "support-material-auto!";
|
||||
def->default_value = new ConfigOptionBool(true);
|
||||
|
||||
def = this->add("support_material_xy_spacing", coFloatOrPercent);
|
||||
def->label = L("XY separation between an object and its support");
|
||||
def->category = L("Support material");
|
||||
|
|
|
@ -331,6 +331,8 @@ public:
|
|||
// ConfigOptionFloat seam_preferred_direction;
|
||||
// ConfigOptionFloat seam_preferred_direction_jitter;
|
||||
ConfigOptionBool support_material;
|
||||
// Automatic supports (generated based on support_material_threshold).
|
||||
ConfigOptionBool support_material_auto;
|
||||
// Direction of the support pattern (in XY plane).
|
||||
ConfigOptionFloat support_material_angle;
|
||||
ConfigOptionBool support_material_buildplate_only;
|
||||
|
@ -372,6 +374,7 @@ protected:
|
|||
// OPT_PTR(seam_preferred_direction);
|
||||
// OPT_PTR(seam_preferred_direction_jitter);
|
||||
OPT_PTR(support_material);
|
||||
OPT_PTR(support_material_auto);
|
||||
OPT_PTR(support_material_angle);
|
||||
OPT_PTR(support_material_buildplate_only);
|
||||
OPT_PTR(support_material_contact_distance);
|
||||
|
|
|
@ -172,6 +172,7 @@ bool PrintObject::invalidate_state_by_config_options(const std::vector<t_config_
|
|||
steps.emplace_back(posSlice);
|
||||
} else if (
|
||||
opt_key == "support_material"
|
||||
|| opt_key == "support_material_auto"
|
||||
|| opt_key == "support_material_angle"
|
||||
|| opt_key == "support_material_buildplate_only"
|
||||
|| opt_key == "support_material_enforce_layers"
|
||||
|
|
|
@ -495,12 +495,12 @@ public:
|
|||
// and trim the extracted polygons by trimming_polygons.
|
||||
// Trimming by the trimming_polygons may split the extracted polygons into pieces.
|
||||
// Remove all the pieces, which do not contain any of the island_samples.
|
||||
Polygons extract_support(const coord_t offset_in_grid)
|
||||
Polygons extract_support(const coord_t offset_in_grid, bool fill_holes)
|
||||
{
|
||||
// Generate islands, so each island may be tested for overlap with m_island_samples.
|
||||
assert(std::abs(2 * offset_in_grid) < m_grid.resolution());
|
||||
ExPolygons islands = diff_ex(
|
||||
m_grid.contours_simplified(offset_in_grid),
|
||||
m_grid.contours_simplified(offset_in_grid, fill_holes),
|
||||
*m_trimming_polygons, false);
|
||||
|
||||
// Extract polygons, which contain some of the m_island_samples.
|
||||
|
@ -812,6 +812,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
|
|||
// Output layers, sorted by top Z.
|
||||
MyLayersPtr contact_out;
|
||||
|
||||
const bool support_auto = m_object_config->support_material_auto.value;
|
||||
// If user specified a custom angle threshold, convert it to radians.
|
||||
// Zero means automatic overhang detection.
|
||||
const double threshold_rad = (m_object_config->support_material_threshold.value > 0) ?
|
||||
|
@ -851,7 +852,8 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
|
|||
contact_out.assign(num_layers * 2, nullptr);
|
||||
tbb::spin_mutex layer_storage_mutex;
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(this->has_raft() ? 0 : 1, num_layers),
|
||||
[this, &object, &buildplate_covered, &enforcers, &blockers, threshold_rad, &layer_storage, &layer_storage_mutex, &contact_out](const tbb::blocked_range<size_t>& range) {
|
||||
[this, &object, &buildplate_covered, &enforcers, &blockers, support_auto, threshold_rad, &layer_storage, &layer_storage_mutex, &contact_out]
|
||||
(const tbb::blocked_range<size_t>& range) {
|
||||
for (size_t layer_id = range.begin(); layer_id < range.end(); ++ layer_id)
|
||||
{
|
||||
const Layer &layer = *object.layers[layer_id];
|
||||
|
@ -901,34 +903,35 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
|
|||
diff_polygons = diff(diff_polygons, buildplate_covered[layer_id]);
|
||||
}
|
||||
} else {
|
||||
// Get the regions needing a suport, collapse very tiny spots.
|
||||
//FIXME cache the lower layer offset if this layer has multiple regions.
|
||||
#if 1
|
||||
diff_polygons = offset2(
|
||||
diff(layerm_polygons,
|
||||
offset2(lower_layer_polygons, - 0.5f * fw, lower_layer_offset + 0.5f * fw, SUPPORT_SURFACES_OFFSET_PARAMETERS)),
|
||||
//FIXME This offset2 is targeted to reduce very thin regions to support, but it may lead to
|
||||
// no support at all for not so steep overhangs.
|
||||
- 0.1f * fw, 0.1f * fw);
|
||||
#else
|
||||
diff_polygons =
|
||||
diff(layerm_polygons,
|
||||
offset(lower_layer_polygons, lower_layer_offset, SUPPORT_SURFACES_OFFSET_PARAMETERS));
|
||||
#endif
|
||||
if (! buildplate_covered.empty()) {
|
||||
// Don't support overhangs above the top surfaces.
|
||||
// This step is done before the contact surface is calculated by growing the overhang region.
|
||||
diff_polygons = diff(diff_polygons, buildplate_covered[layer_id]);
|
||||
if (support_auto) {
|
||||
// Get the regions needing a suport, collapse very tiny spots.
|
||||
//FIXME cache the lower layer offset if this layer has multiple regions.
|
||||
#if 1
|
||||
diff_polygons = offset2(
|
||||
diff(layerm_polygons,
|
||||
offset2(lower_layer_polygons, - 0.5f * fw, lower_layer_offset + 0.5f * fw, SUPPORT_SURFACES_OFFSET_PARAMETERS)),
|
||||
//FIXME This offset2 is targeted to reduce very thin regions to support, but it may lead to
|
||||
// no support at all for not so steep overhangs.
|
||||
- 0.1f * fw, 0.1f * fw);
|
||||
#else
|
||||
diff_polygons =
|
||||
diff(layerm_polygons,
|
||||
offset(lower_layer_polygons, lower_layer_offset, SUPPORT_SURFACES_OFFSET_PARAMETERS));
|
||||
#endif
|
||||
if (! buildplate_covered.empty()) {
|
||||
// Don't support overhangs above the top surfaces.
|
||||
// This step is done before the contact surface is calculated by growing the overhang region.
|
||||
diff_polygons = diff(diff_polygons, buildplate_covered[layer_id]);
|
||||
}
|
||||
if (! diff_polygons.empty()) {
|
||||
// Offset the support regions back to a full overhang, restrict them to the full overhang.
|
||||
// This is done to increase size of the supporting columns below, as they are calculated by
|
||||
// propagating these contact surfaces downwards.
|
||||
diff_polygons = diff(
|
||||
intersection(offset(diff_polygons, lower_layer_offset, SUPPORT_SURFACES_OFFSET_PARAMETERS), layerm_polygons),
|
||||
lower_layer_polygons);
|
||||
}
|
||||
}
|
||||
if (! diff_polygons.empty()) {
|
||||
// Offset the support regions back to a full overhang, restrict them to the full overhang.
|
||||
// This is done to increase size of the supporting columns below, as they are calculated by
|
||||
// propagating these contact surfaces downwards.
|
||||
diff_polygons = diff(
|
||||
intersection(offset(diff_polygons, lower_layer_offset, SUPPORT_SURFACES_OFFSET_PARAMETERS), layerm_polygons),
|
||||
lower_layer_polygons);
|
||||
}
|
||||
|
||||
if (! enforcers.empty()) {
|
||||
// Apply the "support enforcers".
|
||||
//FIXME add the "enforcers" to the sparse support regions only.
|
||||
|
@ -1000,7 +1003,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
|
|||
slices_margin_cached_offset = slices_margin_offset;
|
||||
slices_margin_cached = (slices_margin_offset == 0.f) ?
|
||||
lower_layer_polygons :
|
||||
offset2(to_polygons(lower_layer.slices.expolygons), - scale_(- no_interface_offset * 0.5f), slices_margin_offset + scale_(- no_interface_offset * 0.5f), SUPPORT_SURFACES_OFFSET_PARAMETERS);
|
||||
offset2(to_polygons(lower_layer.slices.expolygons), - no_interface_offset * 0.5f, slices_margin_offset + no_interface_offset * 0.5f, SUPPORT_SURFACES_OFFSET_PARAMETERS);
|
||||
if (! buildplate_covered.empty()) {
|
||||
// Trim the inflated contact surfaces by the top surfaces as well.
|
||||
polygons_append(slices_margin_cached, buildplate_covered[layer_id]);
|
||||
|
@ -1102,16 +1105,18 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
|
|||
m_object_config->support_material_spacing.value + m_support_material_flow.spacing(),
|
||||
Geometry::deg2rad(m_object_config->support_material_angle.value));
|
||||
// 1) Contact polygons will be projected down. To keep the interface and base layers from growing, return a contour a tiny bit smaller than the grid cells.
|
||||
new_layer.contact_polygons = new Polygons(support_grid_pattern.extract_support(-3));
|
||||
new_layer.contact_polygons = new Polygons(support_grid_pattern.extract_support(-3, true));
|
||||
// 2) infill polygons, expand them by half the extrusion width + a tiny bit of extra.
|
||||
if (layer_id == 0) {
|
||||
// if (no_interface_offset == 0.f) {
|
||||
new_layer.polygons = support_grid_pattern.extract_support(m_support_material_flow.scaled_spacing()/2 + 5);
|
||||
new_layer.polygons = support_grid_pattern.extract_support(m_support_material_flow.scaled_spacing()/2 + 5, true);
|
||||
} else {
|
||||
//Polygons dense_interface_polygons = diff(overhang_polygons, offset(lower_layer_polygons, scale_(no_interface_offset * 0.7f)));
|
||||
Polygons dense_interface_polygons = diff(overhang_polygons,
|
||||
offset2(lower_layer_polygons, scale_(- no_interface_offset * 0.5f), scale_(no_interface_offset * (0.7f + 0.5f)), SUPPORT_SURFACES_OFFSET_PARAMETERS));
|
||||
offset2(lower_layer_polygons, - no_interface_offset * 0.5f, no_interface_offset * (0.6f + 0.5f), SUPPORT_SURFACES_OFFSET_PARAMETERS));
|
||||
// offset(lower_layer_polygons, no_interface_offset * 0.6f, SUPPORT_SURFACES_OFFSET_PARAMETERS));
|
||||
if (! dense_interface_polygons.empty()) {
|
||||
//FIXME do it for non-soluble support interfaces only.
|
||||
//FIXME do it for the bridges only?
|
||||
SupportGridPattern support_grid_pattern(
|
||||
// Support islands, to be stretched into a grid.
|
||||
dense_interface_polygons,
|
||||
|
@ -1120,7 +1125,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
|
|||
// Grid resolution.
|
||||
m_object_config->support_material_spacing.value + m_support_material_flow.spacing(),
|
||||
Geometry::deg2rad(m_object_config->support_material_angle.value));
|
||||
new_layer.polygons = support_grid_pattern.extract_support(m_support_material_flow.scaled_spacing()/2 + 5);
|
||||
new_layer.polygons = support_grid_pattern.extract_support(m_support_material_flow.scaled_spacing()/2 + 5, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1407,7 +1412,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::bottom_conta
|
|||
, &layer
|
||||
#endif /* SLIC3R_DEBUG */
|
||||
] {
|
||||
layer_support_area = support_grid_pattern.extract_support(m_support_material_flow.scaled_spacing()/2 + 25);
|
||||
layer_support_area = support_grid_pattern.extract_support(m_support_material_flow.scaled_spacing()/2 + 25, true);
|
||||
#ifdef SLIC3R_DEBUG
|
||||
Slic3r::SVG::export_expolygons(
|
||||
debug_out_path("support-layer_support_area-gridded-%d-%lf.svg", iRun, layer.print_z),
|
||||
|
@ -1421,7 +1426,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::bottom_conta
|
|||
, &layer
|
||||
#endif /* SLIC3R_DEBUG */
|
||||
] {
|
||||
projection_new = support_grid_pattern.extract_support(-5);
|
||||
projection_new = support_grid_pattern.extract_support(-5, true);
|
||||
#ifdef SLIC3R_DEBUG
|
||||
Slic3r::SVG::export_expolygons(
|
||||
debug_out_path("support-projection_new-gridded-%d-%lf.svg", iRun, layer.print_z),
|
||||
|
|
|
@ -292,7 +292,7 @@ const std::vector<std::string>& Preset::print_options()
|
|||
"top_solid_infill_speed", "support_material_speed", "support_material_xy_spacing", "support_material_interface_speed",
|
||||
"bridge_speed", "gap_fill_speed", "travel_speed", "first_layer_speed", "perimeter_acceleration", "infill_acceleration",
|
||||
"bridge_acceleration", "first_layer_acceleration", "default_acceleration", "skirts", "skirt_distance", "skirt_height",
|
||||
"min_skirt_length", "brim_width", "support_material", "support_material_threshold", "support_material_enforce_layers",
|
||||
"min_skirt_length", "brim_width", "support_material", "support_material_auto", "support_material_threshold", "support_material_enforce_layers",
|
||||
"raft_layers", "support_material_pattern", "support_material_with_sheath", "support_material_spacing",
|
||||
"support_material_synchronize_layers", "support_material_angle", "support_material_interface_layers",
|
||||
"support_material_interface_spacing", "support_material_interface_contact_loops", "support_material_contact_distance",
|
||||
|
|
|
@ -847,6 +847,7 @@ void TabPrint::build()
|
|||
page = add_options_page(_(L("Support material")), "building.png");
|
||||
optgroup = page->new_optgroup(_(L("Support material")));
|
||||
optgroup->append_single_option_line("support_material");
|
||||
optgroup->append_single_option_line("support_material_auto");
|
||||
optgroup->append_single_option_line("support_material_threshold");
|
||||
optgroup->append_single_option_line("support_material_enforce_layers");
|
||||
|
||||
|
@ -1183,13 +1184,15 @@ void TabPrint::update()
|
|||
|
||||
bool have_raft = m_config->opt_int("raft_layers") > 0;
|
||||
bool have_support_material = m_config->opt_bool("support_material") || have_raft;
|
||||
bool have_support_material_auto = have_support_material && m_config->opt_bool("support_material_auto");
|
||||
bool have_support_interface = m_config->opt_int("support_material_interface_layers") > 0;
|
||||
bool have_support_soluble = have_support_material && m_config->opt_float("support_material_contact_distance") == 0;
|
||||
for (auto el : {"support_material_threshold", "support_material_pattern", "support_material_with_sheath",
|
||||
for (auto el : {"support_material_pattern", "support_material_with_sheath",
|
||||
"support_material_spacing", "support_material_angle", "support_material_interface_layers",
|
||||
"dont_support_bridges", "support_material_extrusion_width", "support_material_contact_distance",
|
||||
"support_material_xy_spacing" })
|
||||
get_field(el)->toggle(have_support_material);
|
||||
get_field("support_material_threshold")->toggle(have_support_material_auto);
|
||||
|
||||
for (auto el : {"support_material_interface_spacing", "support_material_interface_extruder",
|
||||
"support_material_interface_speed", "support_material_interface_contact_loops" })
|
||||
|
|
Loading…
Reference in a new issue