From af9c7c967f08fcf22ffa628c324c90eda65230f1 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Tue, 23 Mar 2021 11:06:31 +0100 Subject: [PATCH] Implementing a new switch for the shape of support towers: expanded to a grid (the old way) vs. snug (like the upstream Slic3r, Cura or Ideamaker). Snug supports suffered from the degeneracies when merging overhang islands over a large number of layers when projecting the support towers down. We borrowed the idea & a bit of code from Cura by simplifying the support polygons by closing the concave cracks, see the smooth_outward() function and the MutablePolygon class. Fixes Support problems with models with hole in the walls. #555 Fixes Support in the Air #740 Fixes [Bug] Supports generated beyond bed edges (X<0 and X>250) and where none are needed. #902 Fixes Unable to remove support material/can't change support "inflation distance" #2708 Fixes FR: support inflation and support conform to boundary #4783 Fixes Support blocker not working on this model #1346 Fixes Unnecessary support material #1993 Fixes support blocker enforcer issue #6240 --- src/libslic3r/Preset.cpp | 2 +- src/libslic3r/PrintConfig.cpp | 14 ++ src/libslic3r/PrintConfig.hpp | 15 ++ src/libslic3r/PrintObject.cpp | 1 + src/libslic3r/SupportMaterial.cpp | 318 ++++++++++++++------------ src/slic3r/GUI/ConfigManipulation.cpp | 2 +- src/slic3r/GUI/Field.cpp | 2 + src/slic3r/GUI/GUI.cpp | 2 + src/slic3r/GUI/GUI_Factories.cpp | 2 +- src/slic3r/GUI/Tab.cpp | 1 + 10 files changed, 208 insertions(+), 151 deletions(-) diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 7dac34342..ecb20a18e 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -427,7 +427,7 @@ const std::vector& Preset::print_options() "bridge_acceleration", "first_layer_acceleration", "default_acceleration", "skirts", "skirt_distance", "skirt_height", "draft_shield", "min_skirt_length", "brim_width", "brim_offset", "brim_type", "support_material", "support_material_auto", "support_material_threshold", "support_material_enforce_layers", "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_pattern", "support_material_with_sheath", "support_material_spacing", "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_contact_distance", "support_material_bottom_contact_distance", diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 692b4c47a..2c6918acf 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -2419,6 +2419,20 @@ void PrintConfigDef::init_fff_params() def->mode = comAdvanced; def->set_default_value(new ConfigOptionFloat(60)); + def = this->add("support_material_style", coEnum); + def->label = L("Style"); + def->category = L("Support material"); + def->tooltip = L("Style and shape of the support towers. Projecting the supports into a regular grid " + "will create more stable supports, while snug support towers will save material and reduce " + "object scarring."); + def->enum_keys_map = &ConfigOptionEnum::get_enum_values(); + def->enum_values.push_back("grid"); + def->enum_values.push_back("snug"); + def->enum_labels.push_back(L("Grid")); + def->enum_labels.push_back(L("Snug")); + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionEnum(smsGrid)); + def = this->add("support_material_synchronize_layers", coBool); def->label = L("Synchronize with object layers"); def->category = L("Support material"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index abeb29d4b..10f3b11d5 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -65,6 +65,10 @@ enum SupportMaterialPattern { smpRectilinear, smpRectilinearGrid, smpHoneycomb, }; +enum SupportMaterialStyle { + smsGrid, smsSnug, +}; + enum SupportMaterialInterfacePattern { smipAuto, smipRectilinear, smipConcentric, }; @@ -211,6 +215,15 @@ template<> inline const t_config_enum_values& ConfigOptionEnum inline const t_config_enum_values& ConfigOptionEnum::get_enum_values() { + static t_config_enum_values keys_map; + if (keys_map.empty()) { + keys_map["grid"] = smsGrid; + keys_map["snug"] = smsSnug; + } + return keys_map; +} + template<> inline const t_config_enum_values& ConfigOptionEnum::get_enum_values() { static t_config_enum_values keys_map; if (keys_map.empty()) { @@ -519,6 +532,7 @@ public: // Spacing between support material lines (the hatching distance). ConfigOptionFloat support_material_spacing; ConfigOptionFloat support_material_speed; + ConfigOptionEnum support_material_style; ConfigOptionBool support_material_synchronize_layers; // Overhang angle threshold. ConfigOptionInt support_material_threshold; @@ -570,6 +584,7 @@ protected: OPT_PTR(support_material_interface_pattern); OPT_PTR(support_material_spacing); OPT_PTR(support_material_speed); + OPT_PTR(support_material_style); OPT_PTR(support_material_synchronize_layers); OPT_PTR(support_material_xy_spacing); OPT_PTR(support_material_threshold); diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index e86eb2c9c..1989b1884 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -588,6 +588,7 @@ bool PrintObject::invalidate_state_by_config_options( || opt_key == "support_material_interface_extruder" || opt_key == "support_material_interface_spacing" || opt_key == "support_material_pattern" + || opt_key == "support_material_style" || opt_key == "support_material_xy_spacing" || opt_key == "support_material_spacing" || opt_key == "support_material_synchronize_layers" diff --git a/src/libslic3r/SupportMaterial.cpp b/src/libslic3r/SupportMaterial.cpp index c01da8f91..56ae04bce 100644 --- a/src/libslic3r/SupportMaterial.cpp +++ b/src/libslic3r/SupportMaterial.cpp @@ -6,6 +6,7 @@ #include "Fill/FillBase.hpp" #include "Geometry.hpp" #include "Point.hpp" +#include "MutablePolygon.hpp" #include #include @@ -667,17 +668,19 @@ Polygons collect_slices_outer(const Layer &layer) struct SupportGridParams { SupportGridParams(const PrintObjectConfig &object_config, const Flow &support_material_flow) : + style(object_config.support_material_style.value), grid_resolution(object_config.support_material_spacing.value + support_material_flow.spacing()), support_angle(Geometry::deg2rad(object_config.support_material_angle.value)), extrusion_width(support_material_flow.spacing()), expansion_to_slice(coord_t(support_material_flow.scaled_spacing() / 2 + 5)), expansion_to_propagate(-3) {} - double grid_resolution; - double support_angle; - double extrusion_width; - coord_t expansion_to_slice; - coord_t expansion_to_propagate; + SupportMaterialStyle style; + double grid_resolution; + double support_angle; + double extrusion_width; + coord_t expansion_to_slice; + coord_t expansion_to_propagate; }; class SupportGridPattern @@ -689,75 +692,88 @@ public: // Trimming polygons, to trim the stretched support islands. support_polygons were already trimmed with trimming_polygons. const Polygons *trimming_polygons, const SupportGridParams ¶ms) : + m_style(params.style), m_support_polygons(support_polygons), m_trimming_polygons(trimming_polygons), m_support_spacing(params.grid_resolution), m_support_angle(params.support_angle) { - if (m_support_angle != 0.) { - // Create a copy of the rotated contours. - m_support_polygons_rotated = *support_polygons; - m_trimming_polygons_rotated = *trimming_polygons; - m_support_polygons = &m_support_polygons_rotated; - m_trimming_polygons = &m_trimming_polygons_rotated; - polygons_rotate(m_support_polygons_rotated, - params.support_angle); - polygons_rotate(m_trimming_polygons_rotated, - params.support_angle); - } - - // Resolution of the sparse support grid. - coord_t grid_resolution = coord_t(scale_(m_support_spacing)); - BoundingBox bbox = get_extents(*m_support_polygons); - bbox.offset(20); - // Align the bounding box with the sparse support grid. - bbox.align_to_grid(grid_resolution); - -#ifdef SUPPORT_USE_AGG_RASTERIZER - m_bbox = bbox; - // Oversample the grid to avoid leaking of supports through or around the object walls. - int oversampling = std::min(8, int(scale_(m_support_spacing) / (scale_(params.extrusion_width) + 100))); - m_pixel_size = scale_(m_support_spacing / oversampling); - assert(scale_(params.extrusion_width) + 20 < m_pixel_size); - // Add one empty column / row boundaries. - m_bbox.offset(m_pixel_size); - // Grid size fitting the support polygons plus one pixel boundary around the polygons. - Vec2i grid_size_raw(int(ceil((m_bbox.max.x() - m_bbox.min.x()) / m_pixel_size)), - int(ceil((m_bbox.max.y() - m_bbox.min.y()) / m_pixel_size))); - // Overlay macro blocks of (oversampling x oversampling) over the grid. - Vec2i grid_blocks((grid_size_raw.x() + oversampling - 1 - 2) / oversampling, - (grid_size_raw.y() + oversampling - 1 - 2) / oversampling); - // and resize the grid to fit the macro blocks + one pixel boundary. - m_grid_size = grid_blocks * oversampling + Vec2i(2, 2); - assert(m_grid_size.x() >= grid_size_raw.x()); - assert(m_grid_size.y() >= grid_size_raw.y()); - m_grid2 = rasterize_polygons(m_grid_size, m_pixel_size, m_bbox.min, *m_support_polygons); - - seed_fill_block(m_grid2, m_grid_size, - dilate_trimming_region(rasterize_polygons(m_grid_size, m_pixel_size, m_bbox.min, *m_trimming_polygons), m_grid_size), - grid_blocks, oversampling); - -#ifdef SLIC3R_DEBUG + switch (m_style) { + case smsGrid: { - static int irun; - Slic3r::png::write_gray_to_file_scaled(debug_out_path("support-rasterizer-%d.png", irun++), m_grid_size.x(), m_grid_size.y(), m_grid2.data(), 4); - } -#endif // SLIC3R_DEBUG + // Prepare the grid data, it will be reused when extracting support structures. + if (m_support_angle != 0.) { + // Create a copy of the rotated contours. + m_support_polygons_rotated = *support_polygons; + m_trimming_polygons_rotated = *trimming_polygons; + m_support_polygons = &m_support_polygons_rotated; + m_trimming_polygons = &m_trimming_polygons_rotated; + polygons_rotate(m_support_polygons_rotated, - params.support_angle); + polygons_rotate(m_trimming_polygons_rotated, - params.support_angle); + } -#else // SUPPORT_USE_AGG_RASTERIZER - // Create an EdgeGrid, initialize it with projection, initialize signed distance field. - m_grid.set_bbox(bbox); - m_grid.create(*m_support_polygons, grid_resolution); -#if 0 - if (m_grid.has_intersecting_edges()) { - // EdgeGrid fails to produce valid signed distance function for self-intersecting polygons. - m_support_polygons_rotated = simplify_polygons(*m_support_polygons); - m_support_polygons = &m_support_polygons_rotated; + // Resolution of the sparse support grid. + coord_t grid_resolution = coord_t(scale_(m_support_spacing)); + BoundingBox bbox = get_extents(*m_support_polygons); + bbox.offset(20); + // Align the bounding box with the sparse support grid. + bbox.align_to_grid(grid_resolution); + + #ifdef SUPPORT_USE_AGG_RASTERIZER + m_bbox = bbox; + // Oversample the grid to avoid leaking of supports through or around the object walls. + int oversampling = std::min(8, int(scale_(m_support_spacing) / (scale_(params.extrusion_width) + 100))); + m_pixel_size = scale_(m_support_spacing / oversampling); + assert(scale_(params.extrusion_width) + 20 < m_pixel_size); + // Add one empty column / row boundaries. + m_bbox.offset(m_pixel_size); + // Grid size fitting the support polygons plus one pixel boundary around the polygons. + Vec2i grid_size_raw(int(ceil((m_bbox.max.x() - m_bbox.min.x()) / m_pixel_size)), + int(ceil((m_bbox.max.y() - m_bbox.min.y()) / m_pixel_size))); + // Overlay macro blocks of (oversampling x oversampling) over the grid. + Vec2i grid_blocks((grid_size_raw.x() + oversampling - 1 - 2) / oversampling, + (grid_size_raw.y() + oversampling - 1 - 2) / oversampling); + // and resize the grid to fit the macro blocks + one pixel boundary. + m_grid_size = grid_blocks * oversampling + Vec2i(2, 2); + assert(m_grid_size.x() >= grid_size_raw.x()); + assert(m_grid_size.y() >= grid_size_raw.y()); + m_grid2 = rasterize_polygons(m_grid_size, m_pixel_size, m_bbox.min, *m_support_polygons); + + seed_fill_block(m_grid2, m_grid_size, + dilate_trimming_region(rasterize_polygons(m_grid_size, m_pixel_size, m_bbox.min, *m_trimming_polygons), m_grid_size), + grid_blocks, oversampling); + + #ifdef SLIC3R_DEBUG + { + static int irun; + Slic3r::png::write_gray_to_file_scaled(debug_out_path("support-rasterizer-%d.png", irun++), m_grid_size.x(), m_grid_size.y(), m_grid2.data(), 4); + } + #endif // SLIC3R_DEBUG + + #else // SUPPORT_USE_AGG_RASTERIZER + // Create an EdgeGrid, initialize it with projection, initialize signed distance field. m_grid.set_bbox(bbox); m_grid.create(*m_support_polygons, grid_resolution); -// assert(! m_grid.has_intersecting_edges()); - printf("SupportGridPattern: fixing polygons with intersection %s\n", - m_grid.has_intersecting_edges() ? "FAILED" : "SUCCEEDED"); + #if 0 + if (m_grid.has_intersecting_edges()) { + // EdgeGrid fails to produce valid signed distance function for self-intersecting polygons. + m_support_polygons_rotated = simplify_polygons(*m_support_polygons); + m_support_polygons = &m_support_polygons_rotated; + m_grid.set_bbox(bbox); + m_grid.create(*m_support_polygons, grid_resolution); + // assert(! m_grid.has_intersecting_edges()); + printf("SupportGridPattern: fixing polygons with intersection %s\n", + m_grid.has_intersecting_edges() ? "FAILED" : "SUCCEEDED"); + } + #endif + m_grid.calculate_sdf(); + #endif // SUPPORT_USE_AGG_RASTERIZER + break; + } + + case smsSnug: + default: + // nothing to prepare + break; } -#endif - m_grid.calculate_sdf(); -#endif // SUPPORT_USE_AGG_RASTERIZER } // Extract polygons from the grid, offsetted by offset_in_grid, @@ -770,97 +786,102 @@ public: #endif ) { -#ifdef SUPPORT_USE_AGG_RASTERIZER - Polygons support_polygons_simplified = contours_simplified(m_grid_size, m_pixel_size, m_bbox.min, m_grid2, offset_in_grid, fill_holes); -#else // SUPPORT_USE_AGG_RASTERIZER - // Generate islands, so each island may be tested for overlap with island_samples. - assert(std::abs(2 * offset_in_grid) < m_grid.resolution()); - Polygons support_polygons_simplified = m_grid.contours_simplified(offset_in_grid, fill_holes); -#endif // SUPPORT_USE_AGG_RASTERIZER + switch (m_style) { + case smsGrid: + { + #ifdef SUPPORT_USE_AGG_RASTERIZER + Polygons support_polygons_simplified = contours_simplified(m_grid_size, m_pixel_size, m_bbox.min, m_grid2, offset_in_grid, fill_holes); + #else // SUPPORT_USE_AGG_RASTERIZER + // Generate islands, so each island may be tested for overlap with island_samples. + assert(std::abs(2 * offset_in_grid) < m_grid.resolution()); + Polygons support_polygons_simplified = m_grid.contours_simplified(offset_in_grid, fill_holes); + #endif // SUPPORT_USE_AGG_RASTERIZER - ExPolygons islands = diff_ex(support_polygons_simplified, *m_trimming_polygons, false); + ExPolygons islands = diff_ex(support_polygons_simplified, *m_trimming_polygons, false); - // Extract polygons, which contain some of the island_samples. - Polygons out; -#if 0 - out = to_polygons(std::move(islands)); -#else + // Extract polygons, which contain some of the island_samples. + Polygons out; - // Sample a single point per input support polygon, keep it as a reference to maintain corresponding - // polygons if ever these polygons get split into parts by the trimming polygons. - // As offset_in_grid may be negative, m_support_polygons may stick slightly outside of islands. - // Trim ti with islands. - Points samples = island_samples( - offset_in_grid > 0 ? - // Expanding, thus m_support_polygons are all inside islands. - union_ex(*m_support_polygons) : - // Shrinking, thus m_support_polygons may be trimmed a tiny bit by islands. - intersection_ex(*m_support_polygons, to_polygons(islands))); + // Sample a single point per input support polygon, keep it as a reference to maintain corresponding + // polygons if ever these polygons get split into parts by the trimming polygons. + // As offset_in_grid may be negative, m_support_polygons may stick slightly outside of islands. + // Trim ti with islands. + Points samples = island_samples( + offset_in_grid > 0 ? + // Expanding, thus m_support_polygons are all inside islands. + union_ex(*m_support_polygons) : + // Shrinking, thus m_support_polygons may be trimmed a tiny bit by islands. + intersection_ex(*m_support_polygons, to_polygons(islands))); - std::vector> samples_inside; - for (ExPolygon &island : islands) { - BoundingBox bbox = get_extents(island.contour); - // Samples are sorted lexicographically. - auto it_lower = std::lower_bound(samples.begin(), samples.end(), Point(bbox.min - Point(1, 1))); - auto it_upper = std::upper_bound(samples.begin(), samples.end(), Point(bbox.max + Point(1, 1))); - samples_inside.clear(); - for (auto it = it_lower; it != it_upper; ++ it) - if (bbox.contains(*it)) - samples_inside.push_back(std::make_pair(*it, false)); - if (! samples_inside.empty()) { - // For all samples_inside count the boundary crossing. - for (size_t i_contour = 0; i_contour <= island.holes.size(); ++ i_contour) { - Polygon &contour = (i_contour == 0) ? island.contour : island.holes[i_contour - 1]; - Points::const_iterator i = contour.points.begin(); - Points::const_iterator j = contour.points.end() - 1; - for (; i != contour.points.end(); j = i ++) { - //FIXME this test is not numerically robust. Particularly, it does not handle horizontal segments at y == point(1) well. - // Does the ray with y == point(1) intersect this line segment? - for (auto &sample_inside : samples_inside) { - if (((*i)(1) > sample_inside.first(1)) != ((*j)(1) > sample_inside.first(1))) { - double x1 = (double)sample_inside.first(0); - double x2 = (double)(*i)(0) + (double)((*j)(0) - (*i)(0)) * (double)(sample_inside.first(1) - (*i)(1)) / (double)((*j)(1) - (*i)(1)); - if (x1 < x2) - sample_inside.second = !sample_inside.second; + std::vector> samples_inside; + for (ExPolygon &island : islands) { + BoundingBox bbox = get_extents(island.contour); + // Samples are sorted lexicographically. + auto it_lower = std::lower_bound(samples.begin(), samples.end(), Point(bbox.min - Point(1, 1))); + auto it_upper = std::upper_bound(samples.begin(), samples.end(), Point(bbox.max + Point(1, 1))); + samples_inside.clear(); + for (auto it = it_lower; it != it_upper; ++ it) + if (bbox.contains(*it)) + samples_inside.push_back(std::make_pair(*it, false)); + if (! samples_inside.empty()) { + // For all samples_inside count the boundary crossing. + for (size_t i_contour = 0; i_contour <= island.holes.size(); ++ i_contour) { + Polygon &contour = (i_contour == 0) ? island.contour : island.holes[i_contour - 1]; + Points::const_iterator i = contour.points.begin(); + Points::const_iterator j = contour.points.end() - 1; + for (; i != contour.points.end(); j = i ++) { + //FIXME this test is not numerically robust. Particularly, it does not handle horizontal segments at y == point(1) well. + // Does the ray with y == point(1) intersect this line segment? + for (auto &sample_inside : samples_inside) { + if (((*i)(1) > sample_inside.first(1)) != ((*j)(1) > sample_inside.first(1))) { + double x1 = (double)sample_inside.first(0); + double x2 = (double)(*i)(0) + (double)((*j)(0) - (*i)(0)) * (double)(sample_inside.first(1) - (*i)(1)) / (double)((*j)(1) - (*i)(1)); + if (x1 < x2) + sample_inside.second = !sample_inside.second; + } } } } + // If any of the sample is inside this island, add this island to the output. + for (auto &sample_inside : samples_inside) + if (sample_inside.second) { + polygons_append(out, std::move(island)); + island.clear(); + break; + } } - // If any of the sample is inside this island, add this island to the output. - for (auto &sample_inside : samples_inside) - if (sample_inside.second) { - polygons_append(out, std::move(island)); - island.clear(); - break; - } } + + #ifdef SLIC3R_DEBUG + BoundingBox bbox = get_extents(*m_trimming_polygons); + if (! islands.empty()) + bbox.merge(get_extents(islands)); + if (!out.empty()) + bbox.merge(get_extents(out)); + if (!support_polygons_simplified.empty()) + bbox.merge(get_extents(support_polygons_simplified)); + SVG svg(debug_out_path("extract_support_from_grid_trimmed-%s-%d-%d-%lf.svg", step_name, iRun, layer_id, print_z).c_str(), bbox); + svg.draw(union_ex(support_polygons_simplified), "gray", 0.25f); + svg.draw(islands, "red", 0.5f); + svg.draw(union_ex(out), "green", 0.5f); + svg.draw(union_ex(*m_support_polygons), "blue", 0.5f); + svg.draw_outline(islands, "red", "red", scale_(0.05)); + svg.draw_outline(union_ex(out), "green", "green", scale_(0.05)); + svg.draw_outline(union_ex(*m_support_polygons), "blue", "blue", scale_(0.05)); + for (const Point &pt : samples) + svg.draw(pt, "black", coord_t(scale_(0.15))); + svg.Close(); + #endif /* SLIC3R_DEBUG */ + + if (m_support_angle != 0.) + polygons_rotate(out, m_support_angle); + return out; + } + case smsSnug: + // Just close the gaps. + float thr = scaled(0.5); + return smooth_outward(offset(offset_ex(*m_support_polygons, thr), - thr), thr); } -#endif - -#ifdef SLIC3R_DEBUG - BoundingBox bbox = get_extents(*m_trimming_polygons); - if (! islands.empty()) - bbox.merge(get_extents(islands)); - if (!out.empty()) - bbox.merge(get_extents(out)); - if (!support_polygons_simplified.empty()) - bbox.merge(get_extents(support_polygons_simplified)); - SVG svg(debug_out_path("extract_support_from_grid_trimmed-%s-%d-%d-%lf.svg", step_name, iRun, layer_id, print_z).c_str(), bbox); - svg.draw(union_ex(support_polygons_simplified), "gray", 0.25f); - svg.draw(islands, "red", 0.5f); - svg.draw(union_ex(out), "green", 0.5f); - svg.draw(union_ex(*m_support_polygons), "blue", 0.5f); - svg.draw_outline(islands, "red", "red", scale_(0.05)); - svg.draw_outline(union_ex(out), "green", "green", scale_(0.05)); - svg.draw_outline(union_ex(*m_support_polygons), "blue", "blue", scale_(0.05)); - for (const Point &pt : samples) - svg.draw(pt, "black", coord_t(scale_(0.15))); - svg.Close(); -#endif /* SLIC3R_DEBUG */ - - if (m_support_angle != 0.) - polygons_rotate(out, m_support_angle); - return out; } #if defined(SLIC3R_DEBUG) && ! defined(SUPPORT_USE_AGG_RASTERIZER) @@ -1096,6 +1117,7 @@ private: return pts; } + SupportMaterialStyle m_style; const Polygons *m_support_polygons; const Polygons *m_trimming_polygons; Polygons m_support_polygons_rotated; @@ -1525,7 +1547,7 @@ static inline std::tuple detect_overhangs( ClipperLib::jtRound, // round mitter limit scale_(0.05)), - slices_margin_cached); + slices_margin.polygons); } #else diff_polygons = diff(diff_polygons, slices_margin.polygons); diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index 6e0f13528..9334eea47 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -278,7 +278,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config) bool have_support_material_auto = have_support_material && config->opt_bool("support_material_auto"); bool have_support_interface = config->opt_int("support_material_interface_layers") > 0; bool have_support_soluble = have_support_material && config->opt_float("support_material_contact_distance") == 0; - for (auto el : { "support_material_pattern", "support_material_with_sheath", + for (auto el : { "support_material_style", "support_material_pattern", "support_material_with_sheath", "support_material_spacing", "support_material_angle", "support_material_interface_pattern", "support_material_interface_layers", "dont_support_bridges", "support_material_extrusion_width", "support_material_contact_distance", diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index cbbe7f381..8e3fff06d 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -1224,6 +1224,8 @@ boost::any& Choice::get_value() m_value = static_cast(ret_enum); else if (m_opt_id.compare("support_material_interface_pattern") == 0) m_value = static_cast(ret_enum); + else if (m_opt_id.compare("support_material_style") == 0) + m_value = static_cast(ret_enum); else if (m_opt_id.compare("seam_position") == 0) m_value = static_cast(ret_enum); else if (m_opt_id.compare("host_type") == 0) diff --git a/src/slic3r/GUI/GUI.cpp b/src/slic3r/GUI/GUI.cpp index 61ec4d233..1d3a85dc0 100644 --- a/src/slic3r/GUI/GUI.cpp +++ b/src/slic3r/GUI/GUI.cpp @@ -198,6 +198,8 @@ void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt config.set_key_value(opt_key, new ConfigOptionEnum(boost::any_cast(value))); else if (opt_key.compare("support_material_interface_pattern") == 0) config.set_key_value(opt_key, new ConfigOptionEnum(boost::any_cast(value))); + else if (opt_key.compare("support_material_style") == 0) + config.set_key_value(opt_key, new ConfigOptionEnum(boost::any_cast(value))); else if (opt_key.compare("seam_position") == 0) config.set_key_value(opt_key, new ConfigOptionEnum(boost::any_cast(value))); else if (opt_key.compare("host_type") == 0) diff --git a/src/slic3r/GUI/GUI_Factories.cpp b/src/slic3r/GUI/GUI_Factories.cpp index d8518a6c8..5ca8f8e2a 100644 --- a/src/slic3r/GUI/GUI_Factories.cpp +++ b/src/slic3r/GUI/GUI_Factories.cpp @@ -50,7 +50,7 @@ static SettingsFactory::Bundle FREQ_SETTINGS_BUNDLE_FFF = { L("Layers and Perimeters"), { "layer_height" , "perimeters", "top_solid_layers", "bottom_solid_layers" } }, { L("Infill") , { "fill_density", "fill_pattern" } }, { L("Support material") , { "support_material", "support_material_auto", "support_material_threshold", - "support_material_pattern", "support_material_interface_pattern", "support_material_buildplate_only", + "support_material_pattern", "support_material_pattern", "support_material_interface_pattern", "support_material_buildplate_only", "support_material_spacing" } }, { L("Wipe options") , { "wipe_into_infill", "wipe_into_objects" } } }; diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index c68de4984..de2e84515 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1506,6 +1506,7 @@ void TabPrint::build() optgroup->append_single_option_line("raft_expansion"); optgroup = page->new_optgroup(L("Options for support material and raft")); + optgroup->append_single_option_line("support_material_style", category_path + "style"); optgroup->append_single_option_line("support_material_contact_distance", category_path + "contact-z-distance"); optgroup->append_single_option_line("support_material_bottom_contact_distance", category_path + "contact-z-distance"); optgroup->append_single_option_line("support_material_pattern", category_path + "pattern");