Splitting FDM support gap to top / bottom, introducing
support_material_bottom_contact_distance
Fixing Crash in support generation after fcb714c
(repro attached) #6195
This commit is contained in:
parent
f3f10ff002
commit
73b88e6ce0
11 changed files with 144 additions and 118 deletions
|
@ -429,7 +429,8 @@ const std::vector<std::string>& 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_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_interface_pattern", "support_material_interface_spacing", "support_material_interface_contact_loops",
|
||||
"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",
|
||||
"infill_extruder", "solid_infill_extruder", "support_material_extruder", "support_material_interface_extruder",
|
||||
|
|
|
@ -1326,7 +1326,8 @@ std::string Print::validate(std::string* warning) const
|
|||
return L("The Wipe Tower is only supported for multiple objects if they have equal layer heights");
|
||||
if (slicing_params.raft_layers() != slicing_params0.raft_layers())
|
||||
return L("The Wipe Tower is only supported for multiple objects if they are printed over an equal number of raft layers");
|
||||
if (object->config().support_material_contact_distance != m_objects.front()->config().support_material_contact_distance)
|
||||
if (slicing_params0.gap_object_support != slicing_params.gap_object_support ||
|
||||
slicing_params0.gap_support_object != slicing_params.gap_support_object)
|
||||
return L("The Wipe Tower is only supported for multiple objects if they are printed with the same support_material_contact_distance");
|
||||
if (! equal_layering(slicing_params, slicing_params0))
|
||||
return L("The Wipe Tower is only supported for multiple objects if they are sliced equally.");
|
||||
|
|
|
@ -2235,7 +2235,7 @@ void PrintConfigDef::init_fff_params()
|
|||
|
||||
def = this->add("support_material_contact_distance", coFloat);
|
||||
def->gui_type = "f_enum_open";
|
||||
def->label = L("Contact Z distance");
|
||||
def->label = L("Top contact Z distance");
|
||||
def->category = L("Support material");
|
||||
def->tooltip = L("The vertical distance between object and support material interface. "
|
||||
"Setting this to 0 will also prevent Slic3r from using bridge flow and speed "
|
||||
|
@ -2243,12 +2243,31 @@ void PrintConfigDef::init_fff_params()
|
|||
def->sidetext = L("mm");
|
||||
// def->min = 0;
|
||||
def->enum_values.push_back("0");
|
||||
def->enum_values.push_back("0.1");
|
||||
def->enum_values.push_back("0.2");
|
||||
def->enum_labels.push_back(L("0 (soluble)"));
|
||||
def->enum_labels.push_back(L("0.1 (detachable)"));
|
||||
def->enum_labels.push_back(L("0.2 (detachable)"));
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(0.2));
|
||||
|
||||
def = this->add("support_material_bottom_contact_distance", coFloat);
|
||||
def->gui_type = "f_enum_open";
|
||||
def->label = L("Bottom contact Z distance");
|
||||
def->category = L("Support material");
|
||||
def->tooltip = L("The vertical distance between the object top surface and the support material interface. "
|
||||
"If set to zero, support_material_contact_distance will be used for both top and bottom contact Z distances.");
|
||||
def->sidetext = L("mm");
|
||||
// def->min = 0;
|
||||
def->enum_values.push_back("0");
|
||||
def->enum_values.push_back("0.1");
|
||||
def->enum_values.push_back("0.2");
|
||||
def->enum_labels.push_back(L("same as top"));
|
||||
def->enum_labels.push_back(L("0.1"));
|
||||
def->enum_labels.push_back(L("0.2"));
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(0));
|
||||
|
||||
def = this->add("support_material_enforce_layers", coInt);
|
||||
def->label = L("Enforce support for the first");
|
||||
def->category = L("Support material");
|
||||
|
@ -2298,22 +2317,36 @@ void PrintConfigDef::init_fff_params()
|
|||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionInt(1));
|
||||
|
||||
def = this->add("support_material_interface_layers", coInt);
|
||||
auto support_material_interface_layers = def = this->add("support_material_interface_layers", coInt);
|
||||
def->gui_type = "f_enum_open";
|
||||
def->label = L("Top interface layers");
|
||||
def->category = L("Support material");
|
||||
def->tooltip = L("Number of interface layers to insert between the object(s) and support material.");
|
||||
def->sidetext = L("layers");
|
||||
def->min = 0;
|
||||
def->enum_values.push_back("0");
|
||||
def->enum_values.push_back("1");
|
||||
def->enum_values.push_back("2");
|
||||
def->enum_values.push_back("3");
|
||||
def->enum_labels.push_back(L("0 (off)"));
|
||||
def->enum_labels.push_back(L("1 (light)"));
|
||||
def->enum_labels.push_back(L("2 (default)"));
|
||||
def->enum_labels.push_back(L("3 (heavy)"));
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionInt(3));
|
||||
|
||||
def = this->add("support_material_bottom_interface_layers", coInt);
|
||||
def->gui_type = "f_enum_open";
|
||||
def->label = L("Bottom interface layers");
|
||||
def->category = L("Support material");
|
||||
def->tooltip = L("Number of interface layers to insert between the object(s) and support material. "
|
||||
"Set to -1 to use support_material_interface_layers");
|
||||
def->sidetext = L("layers");
|
||||
def->min = -1;
|
||||
def->enum_values.push_back("-1");
|
||||
append(def->enum_values, support_material_interface_layers->enum_values);
|
||||
def->enum_labels.push_back(L("same as top"));
|
||||
append(def->enum_labels, support_material_interface_layers->enum_labels);
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionInt(-1));
|
||||
|
||||
|
|
|
@ -503,6 +503,7 @@ public:
|
|||
ConfigOptionFloat support_material_angle;
|
||||
ConfigOptionBool support_material_buildplate_only;
|
||||
ConfigOptionFloat support_material_contact_distance;
|
||||
ConfigOptionFloat support_material_bottom_contact_distance;
|
||||
ConfigOptionInt support_material_enforce_layers;
|
||||
ConfigOptionInt support_material_extruder;
|
||||
ConfigOptionFloatOrPercent support_material_extrusion_width;
|
||||
|
@ -555,6 +556,7 @@ protected:
|
|||
OPT_PTR(support_material_angle);
|
||||
OPT_PTR(support_material_buildplate_only);
|
||||
OPT_PTR(support_material_contact_distance);
|
||||
OPT_PTR(support_material_bottom_contact_distance);
|
||||
OPT_PTR(support_material_enforce_layers);
|
||||
OPT_PTR(support_material_interface_contact_loops);
|
||||
OPT_PTR(support_material_extruder);
|
||||
|
|
|
@ -546,15 +546,9 @@ bool PrintObject::invalidate_state_by_config_options(
|
|||
|| opt_key == "extra_perimeters"
|
||||
|| opt_key == "gap_fill_enabled"
|
||||
|| opt_key == "gap_fill_speed"
|
||||
|| opt_key == "overhangs"
|
||||
|| opt_key == "first_layer_extrusion_width"
|
||||
|| opt_key == "fuzzy_skin"
|
||||
|| opt_key == "fuzzy_skin_thickness"
|
||||
|| opt_key == "fuzzy_skin_point_dist"
|
||||
|| opt_key == "perimeter_extrusion_width"
|
||||
|| opt_key == "infill_overlap"
|
||||
|| opt_key == "thin_walls"
|
||||
|| opt_key == "thick_bridges"
|
||||
|| opt_key == "external_perimeters_first") {
|
||||
steps.emplace_back(posPerimeters);
|
||||
} else if (
|
||||
|
@ -586,6 +580,7 @@ bool PrintObject::invalidate_state_by_config_options(
|
|||
|| opt_key == "support_material_enforce_layers"
|
||||
|| opt_key == "support_material_extruder"
|
||||
|| opt_key == "support_material_extrusion_width"
|
||||
|| opt_key == "support_material_bottom_contact_distance"
|
||||
|| opt_key == "support_material_interface_layers"
|
||||
|| opt_key == "support_material_bottom_interface_layers"
|
||||
|| opt_key == "support_material_interface_pattern"
|
||||
|
@ -654,7 +649,13 @@ bool PrintObject::invalidate_state_by_config_options(
|
|||
steps.emplace_back(posPrepareInfill);
|
||||
} else if (
|
||||
opt_key == "external_perimeter_extrusion_width"
|
||||
|| opt_key == "perimeter_extruder") {
|
||||
|| opt_key == "perimeter_extruder"
|
||||
|| opt_key == "fuzzy_skin"
|
||||
|| opt_key == "fuzzy_skin_thickness"
|
||||
|| opt_key == "fuzzy_skin_point_dist"
|
||||
|| opt_key == "overhangs"
|
||||
|| opt_key == "thin_walls"
|
||||
|| opt_key == "thick_bridges") {
|
||||
steps.emplace_back(posPerimeters);
|
||||
steps.emplace_back(posSupportMaterial);
|
||||
} else if (opt_key == "bridge_flow_ratio") {
|
||||
|
|
|
@ -112,8 +112,10 @@ SlicingParameters SlicingParameters::create_from_config(
|
|||
|
||||
if (! soluble_interface) {
|
||||
params.gap_raft_object = object_config.raft_contact_distance.value;
|
||||
params.gap_object_support = object_config.support_material_contact_distance.value;
|
||||
params.gap_object_support = object_config.support_material_bottom_contact_distance.value;
|
||||
params.gap_support_object = object_config.support_material_contact_distance.value;
|
||||
if (params.gap_object_support <= 0)
|
||||
params.gap_object_support = params.gap_support_object;
|
||||
}
|
||||
|
||||
if (params.base_raft_layers > 0) {
|
||||
|
|
|
@ -26,7 +26,7 @@ class DynamicPrintConfig;
|
|||
// (using a normal flow over a soluble support, using a bridging flow over a non-soluble support).
|
||||
struct SlicingParameters
|
||||
{
|
||||
SlicingParameters() { memset(this, 0, sizeof(SlicingParameters)); }
|
||||
SlicingParameters() = default;
|
||||
|
||||
static SlicingParameters create_from_config(
|
||||
const PrintConfig &print_config,
|
||||
|
@ -44,58 +44,58 @@ struct SlicingParameters
|
|||
// Height of the object to be printed. This value does not contain the raft height.
|
||||
coordf_t object_print_z_height() const { return object_print_z_max - object_print_z_min; }
|
||||
|
||||
bool valid;
|
||||
bool valid { false };
|
||||
|
||||
// Number of raft layers.
|
||||
size_t base_raft_layers;
|
||||
size_t base_raft_layers { 0 };
|
||||
// Number of interface layers including the contact layer.
|
||||
size_t interface_raft_layers;
|
||||
size_t interface_raft_layers { 0 };
|
||||
|
||||
// Layer heights of the raft (base, interface and a contact layer).
|
||||
coordf_t base_raft_layer_height;
|
||||
coordf_t interface_raft_layer_height;
|
||||
coordf_t contact_raft_layer_height;
|
||||
coordf_t base_raft_layer_height { 0 };
|
||||
coordf_t interface_raft_layer_height { 0 };
|
||||
coordf_t contact_raft_layer_height { 0 };
|
||||
|
||||
// The regular layer height, applied for all but the first layer, if not overridden by layer ranges
|
||||
// or by the variable layer thickness table.
|
||||
coordf_t layer_height;
|
||||
coordf_t layer_height { 0 };
|
||||
// Minimum / maximum layer height, to be used for the automatic adaptive layer height algorithm,
|
||||
// or by an interactive layer height editor.
|
||||
coordf_t min_layer_height;
|
||||
coordf_t max_layer_height;
|
||||
coordf_t max_suport_layer_height;
|
||||
coordf_t min_layer_height { 0 };
|
||||
coordf_t max_layer_height { 0 };
|
||||
coordf_t max_suport_layer_height { 0 };
|
||||
|
||||
// First layer height of the print, this may be used for the first layer of the raft
|
||||
// or for the first layer of the print.
|
||||
coordf_t first_print_layer_height;
|
||||
coordf_t first_print_layer_height { 0 };
|
||||
|
||||
// Thickness of the first layer. This is either the first print layer thickness if printed without a raft,
|
||||
// or a bridging flow thickness if printed over a non-soluble raft,
|
||||
// or a normal layer height if printed over a soluble raft.
|
||||
coordf_t first_object_layer_height;
|
||||
coordf_t first_object_layer_height { 0 };
|
||||
|
||||
// If the object is printed over a non-soluble raft, the first layer may be printed with a briding flow.
|
||||
bool first_object_layer_bridging;
|
||||
bool first_object_layer_bridging { false };
|
||||
|
||||
// Soluble interface? (PLA soluble in water, HIPS soluble in lemonen)
|
||||
// otherwise the interface must be broken off.
|
||||
bool soluble_interface;
|
||||
bool soluble_interface { false };
|
||||
// Gap when placing object over raft.
|
||||
coordf_t gap_raft_object;
|
||||
coordf_t gap_raft_object { 0 };
|
||||
// Gap when placing support over object.
|
||||
coordf_t gap_object_support;
|
||||
coordf_t gap_object_support { 0 };
|
||||
// Gap when placing object over support.
|
||||
coordf_t gap_support_object;
|
||||
coordf_t gap_support_object { 0 };
|
||||
|
||||
// Bottom and top of the printed object.
|
||||
// If printed without a raft, object_print_z_min = 0 and object_print_z_max = object height.
|
||||
// Otherwise object_print_z_min is equal to the raft height.
|
||||
coordf_t raft_base_top_z;
|
||||
coordf_t raft_interface_top_z;
|
||||
coordf_t raft_contact_top_z;
|
||||
coordf_t raft_base_top_z { 0 };
|
||||
coordf_t raft_interface_top_z { 0 };
|
||||
coordf_t raft_contact_top_z { 0 };
|
||||
// In case of a soluble interface, object_print_z_min == raft_contact_top_z, otherwise there is a gap between the raft and the 1st object layer.
|
||||
coordf_t object_print_z_min;
|
||||
coordf_t object_print_z_max;
|
||||
coordf_t object_print_z_min { 0 };
|
||||
coordf_t object_print_z_max { 0 };
|
||||
};
|
||||
static_assert(IsTriviallyCopyable<SlicingParameters>::value, "SlicingParameters class is not POD (and it should be - see constructor).");
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <cmath>
|
||||
#include <memory>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/container/static_vector.hpp>
|
||||
|
||||
#include <tbb/parallel_for.h>
|
||||
#include <tbb/atomic.h>
|
||||
|
@ -397,14 +398,6 @@ inline void layers_append(PrintObjectSupportMaterial::MyLayersPtr &dst, const Pr
|
|||
dst.insert(dst.end(), src.begin(), src.end());
|
||||
}
|
||||
|
||||
// Compare layers lexicographically.
|
||||
struct MyLayersPtrCompare
|
||||
{
|
||||
bool operator()(const PrintObjectSupportMaterial::MyLayer* layer1, const PrintObjectSupportMaterial::MyLayer* layer2) const {
|
||||
return *layer1 < *layer2;
|
||||
}
|
||||
};
|
||||
|
||||
void PrintObjectSupportMaterial::generate(PrintObject &object)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(info) << "Support generator - Start";
|
||||
|
@ -467,10 +460,7 @@ void PrintObjectSupportMaterial::generate(PrintObject &object)
|
|||
MyLayersPtr intermediate_layers = this->raft_and_intermediate_support_layers(
|
||||
object, bottom_contacts, top_contacts, layer_storage);
|
||||
|
||||
// this->trim_support_layers_by_object(object, top_contacts, m_slicing_params.soluble_interface ? 0. : m_support_layer_height_min, 0., m_gap_xy);
|
||||
this->trim_support_layers_by_object(object, top_contacts,
|
||||
m_slicing_params.soluble_interface ? 0. : m_object_config->support_material_contact_distance.value,
|
||||
m_slicing_params.soluble_interface ? 0. : m_object_config->support_material_contact_distance.value, m_gap_xy);
|
||||
this->trim_support_layers_by_object(object, top_contacts, m_slicing_params.gap_support_object, m_slicing_params.gap_object_support, m_gap_xy);
|
||||
|
||||
#ifdef SLIC3R_DEBUG
|
||||
for (const MyLayer *layer : top_contacts)
|
||||
|
@ -552,7 +542,7 @@ void PrintObjectSupportMaterial::generate(PrintObject &object)
|
|||
layers_append(layers_sorted, interface_layers);
|
||||
layers_append(layers_sorted, base_interface_layers);
|
||||
// Sort the layers lexicographically by a raising print_z and a decreasing height.
|
||||
std::sort(layers_sorted.begin(), layers_sorted.end(), MyLayersPtrCompare());
|
||||
std::sort(layers_sorted.begin(), layers_sorted.end(), [](auto *l1, auto *l2) { return *l1 < *l2; });
|
||||
int layer_id = 0;
|
||||
assert(object.support_layers().empty());
|
||||
for (size_t i = 0; i < layers_sorted.size();) {
|
||||
|
@ -1585,11 +1575,11 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
|
|||
} else if (m_slicing_params.soluble_interface) {
|
||||
// Align the contact surface height with a layer immediately below the supported layer.
|
||||
// Interface layer will be synchronized with the object.
|
||||
new_layer.print_z = layer.print_z - layer.height;
|
||||
new_layer.print_z = layer.bottom_z();
|
||||
new_layer.height = object.layers()[layer_id - 1]->height;
|
||||
new_layer.bottom_z = (layer_id == 1) ? m_slicing_params.object_print_z_min : object.layers()[layer_id - 2]->print_z;
|
||||
} else {
|
||||
new_layer.print_z = layer.print_z - layer.height - m_object_config->support_material_contact_distance;
|
||||
new_layer.print_z = layer.bottom_z() - m_slicing_params.gap_object_support;
|
||||
new_layer.bottom_z = new_layer.print_z;
|
||||
new_layer.height = 0.;
|
||||
// Ignore this contact area if it's too low.
|
||||
|
@ -1616,7 +1606,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
|
|||
for (const LayerRegion *region : layer.regions())
|
||||
bridging_height += region->region()->bridging_height_avg(*m_print_config);
|
||||
bridging_height /= coordf_t(layer.regions().size());
|
||||
coordf_t bridging_print_z = layer.print_z - bridging_height - m_object_config->support_material_contact_distance;
|
||||
coordf_t bridging_print_z = layer.print_z - bridging_height - m_slicing_params.gap_support_object;
|
||||
if (bridging_print_z >= m_slicing_params.first_print_layer_height - EPSILON) {
|
||||
// Not below the first layer height means this layer is printable.
|
||||
if (new_layer.print_z < m_slicing_params.first_print_layer_height + EPSILON) {
|
||||
|
@ -1892,7 +1882,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::bottom_conta
|
|||
// Place a bridge flow interface layer or the normal flow interface layer over the top surface.
|
||||
m_support_material_bottom_interface_flow.height();
|
||||
layer_new.print_z = m_slicing_params.soluble_interface ? object.layers()[layer_id + 1]->print_z :
|
||||
layer.print_z + layer_new.height + m_object_config->support_material_contact_distance.value;
|
||||
layer.print_z + layer_new.height + m_slicing_params.gap_object_support;
|
||||
layer_new.bottom_z = layer.print_z;
|
||||
layer_new.idx_object_layer_below = layer_id;
|
||||
layer_new.bridging = ! m_slicing_params.soluble_interface && m_object_config->thick_bridges;
|
||||
|
@ -2039,11 +2029,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::bottom_conta
|
|||
task_group.wait();
|
||||
}
|
||||
std::reverse(bottom_contacts.begin(), bottom_contacts.end());
|
||||
// trim_support_layers_by_object(object, bottom_contacts, 0., 0., m_gap_xy);
|
||||
trim_support_layers_by_object(object, bottom_contacts,
|
||||
m_slicing_params.soluble_interface ? 0. : m_object_config->support_material_contact_distance.value,
|
||||
m_slicing_params.soluble_interface ? 0. : m_object_config->support_material_contact_distance.value, m_gap_xy);
|
||||
|
||||
trim_support_layers_by_object(object, bottom_contacts, m_slicing_params.gap_support_object, m_slicing_params.gap_object_support, m_gap_xy);
|
||||
} // ! top_contacts.empty()
|
||||
|
||||
return bottom_contacts;
|
||||
|
@ -2473,10 +2459,7 @@ void PrintObjectSupportMaterial::generate_base_layers(
|
|||
++ iRun;
|
||||
#endif /* SLIC3R_DEBUG */
|
||||
|
||||
// trim_support_layers_by_object(object, intermediate_layers, 0., 0., m_gap_xy);
|
||||
this->trim_support_layers_by_object(object, intermediate_layers,
|
||||
m_slicing_params.soluble_interface ? 0. : m_object_config->support_material_contact_distance.value,
|
||||
m_slicing_params.soluble_interface ? 0. : m_object_config->support_material_contact_distance.value, m_gap_xy);
|
||||
this->trim_support_layers_by_object(object, intermediate_layers, m_slicing_params.gap_support_object, m_slicing_params.gap_object_support, m_gap_xy);
|
||||
}
|
||||
|
||||
void PrintObjectSupportMaterial::trim_support_layers_by_object(
|
||||
|
@ -2510,7 +2493,7 @@ void PrintObjectSupportMaterial::trim_support_layers_by_object(
|
|||
// BOOST_LOG_TRIVIAL(trace) << "Support generator - trim_support_layers_by_object - trimmming non-empty layer " << idx_layer << " of " << nonempty_layers.size();
|
||||
assert(! support_layer.polygons.empty() && support_layer.print_z >= m_slicing_params.raft_contact_top_z + EPSILON);
|
||||
// Find the overlapping object layers including the extra above / below gap.
|
||||
coordf_t z_threshold = support_layer.print_z - support_layer.height - gap_extra_below + EPSILON;
|
||||
coordf_t z_threshold = support_layer.bottom_print_z() - gap_extra_below + EPSILON;
|
||||
idx_object_layer_overlapping = idx_higher_or_equal(
|
||||
object.layers().begin(), object.layers().end(), idx_object_layer_overlapping,
|
||||
[z_threshold](const Layer *layer){ return layer->print_z >= z_threshold; });
|
||||
|
@ -2519,7 +2502,7 @@ void PrintObjectSupportMaterial::trim_support_layers_by_object(
|
|||
size_t i = idx_object_layer_overlapping;
|
||||
for (; i < object.layers().size(); ++ i) {
|
||||
const Layer &object_layer = *object.layers()[i];
|
||||
if (object_layer.print_z - object_layer.height > support_layer.print_z + gap_extra_above - EPSILON)
|
||||
if (object_layer.bottom_z() > support_layer.print_z + gap_extra_above - EPSILON)
|
||||
break;
|
||||
polygons_append(polygons_trimming, offset(object_layer.lslices, gap_xy_scaled, SUPPORT_SURFACES_OFFSET_PARAMETERS));
|
||||
}
|
||||
|
@ -2537,6 +2520,7 @@ void PrintObjectSupportMaterial::trim_support_layers_by_object(
|
|||
offset(to_expolygons(region->fill_surfaces.filter_by_type(stBottomBridge)),
|
||||
gap_xy_scaled, SUPPORT_SURFACES_OFFSET_PARAMETERS));
|
||||
if (region->region()->config().overhangs.value)
|
||||
// Add bridging perimeters.
|
||||
SupportMaterialInternal::collect_bridging_perimeter_areas(region->perimeters, gap_xy_scaled, polygons_trimming);
|
||||
}
|
||||
if (! some_region_overlaps)
|
||||
|
@ -2896,7 +2880,8 @@ static inline void fill_expolygons_with_sheath_generate_paths(
|
|||
float density,
|
||||
ExtrusionRole role,
|
||||
const Flow &flow,
|
||||
bool with_sheath)
|
||||
bool with_sheath,
|
||||
bool no_sort)
|
||||
{
|
||||
if (polygons.empty())
|
||||
return;
|
||||
|
@ -2916,8 +2901,12 @@ static inline void fill_expolygons_with_sheath_generate_paths(
|
|||
|
||||
for (ExPolygon &expoly : offset2_ex(polygons, float(SCALED_EPSILON), float(- SCALED_EPSILON - 0.5*flow.scaled_width()))) {
|
||||
// Don't reorder the skirt and its infills.
|
||||
auto eec = std::make_unique<ExtrusionEntityCollection>();
|
||||
eec->no_sort = true;
|
||||
std::unique_ptr<ExtrusionEntityCollection> eec;
|
||||
if (no_sort) {
|
||||
eec = std::make_unique<ExtrusionEntityCollection>();
|
||||
eec->no_sort = true;
|
||||
}
|
||||
ExtrusionEntitiesPtr &out = no_sort ? eec->entities : dst;
|
||||
// Draw the perimeters.
|
||||
Polylines polylines;
|
||||
polylines.reserve(expoly.holes.size() + 1);
|
||||
|
@ -2927,10 +2916,11 @@ static inline void fill_expolygons_with_sheath_generate_paths(
|
|||
pl.clip_end(clip_length);
|
||||
polylines.emplace_back(std::move(pl));
|
||||
}
|
||||
extrusion_entities_append_paths(eec->entities, polylines, erSupportMaterial, flow.mm3_per_mm(), flow.width(), flow.height());
|
||||
extrusion_entities_append_paths(out, polylines, erSupportMaterial, flow.mm3_per_mm(), flow.width(), flow.height());
|
||||
// Fill in the rest.
|
||||
fill_expolygons_generate_paths(eec->entities, offset_ex(expoly, float(-0.4 * spacing)), filler, fill_params, density, role, flow);
|
||||
dst.emplace_back(eec.release());
|
||||
fill_expolygons_generate_paths(out, offset_ex(expoly, float(-0.4 * spacing)), filler, fill_params, density, role, flow);
|
||||
if (no_sort)
|
||||
dst.emplace_back(eec.release());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3255,6 +3245,9 @@ static std::string dbg_index_to_color(int idx)
|
|||
// Therefore the bottom interface spots are expanded a bit. The expanded regions may overlap with another bottom interface layers,
|
||||
// leading to over extrusion, where they overlap. The over extrusion is better avoided as it often makes the interface layers
|
||||
// to stick too firmly to the object.
|
||||
//
|
||||
// Modulate thickness (increase bottom_z) of extrusions_in_out generated for this_layer
|
||||
// if they overlap with overlapping_layers, whose print_z is above this_layer.bottom_z() and below this_layer.print_z.
|
||||
void modulate_extrusion_by_overlapping_layers(
|
||||
// Extrusions generated for this_layer.
|
||||
ExtrusionEntitiesPtr &extrusions_in_out,
|
||||
|
@ -3343,8 +3336,8 @@ void modulate_extrusion_by_overlapping_layers(
|
|||
// Collect the paths of this_layer.
|
||||
{
|
||||
Polylines &polylines = path_fragments.back().polylines;
|
||||
for (ExtrusionEntitiesPtr::const_iterator it = extrusions_in_out.begin(); it != extrusions_in_out.end(); ++ it) {
|
||||
ExtrusionPath *path = dynamic_cast<ExtrusionPath*>(*it);
|
||||
for (ExtrusionEntity *ee : extrusions_in_out) {
|
||||
ExtrusionPath *path = dynamic_cast<ExtrusionPath*>(ee);
|
||||
assert(path != nullptr);
|
||||
polylines.emplace_back(Polyline(std::move(path->polyline)));
|
||||
path_ends.emplace_back(std::pair<Point, Point>(polylines.back().points.front(), polylines.back().points.back()));
|
||||
|
@ -3504,7 +3497,6 @@ void PrintObjectSupportMaterial::generate_toolpaths(
|
|||
const MyLayersPtr &interface_layers,
|
||||
const MyLayersPtr &base_interface_layers) const
|
||||
{
|
||||
// Slic3r::debugf "Generating patterns\n";
|
||||
// loop_interface_processor with a given circle radius.
|
||||
LoopInterfaceProcessor loop_interface_processor(1.5 * m_support_material_interface_flow.scaled_width());
|
||||
loop_interface_processor.n_contact_loops = this->has_contact_loops() ? 1 : 0;
|
||||
|
@ -3603,7 +3595,7 @@ void PrintObjectSupportMaterial::generate_toolpaths(
|
|||
filler, float(support_density),
|
||||
// Extrusion parameters
|
||||
erSupportMaterial, flow,
|
||||
with_sheath);
|
||||
with_sheath, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3636,7 +3628,7 @@ void PrintObjectSupportMaterial::generate_toolpaths(
|
|||
// Extrusion parameters
|
||||
(support_layer_id < m_slicing_params.base_raft_layers) ? erSupportMaterial : erSupportMaterialInterface, flow,
|
||||
// sheath at first layer
|
||||
support_layer_id == 0);
|
||||
support_layer_id == 0, support_layer_id == 0);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -3646,12 +3638,20 @@ void PrintObjectSupportMaterial::generate_toolpaths(
|
|||
std::vector<MyLayer*> overlapping;
|
||||
};
|
||||
struct LayerCache {
|
||||
MyLayerExtruded bottom_contact_layer;
|
||||
MyLayerExtruded top_contact_layer;
|
||||
MyLayerExtruded base_layer;
|
||||
MyLayerExtruded interface_layer;
|
||||
MyLayerExtruded base_interface_layer;
|
||||
std::vector<LayerCacheItem> overlaps;
|
||||
MyLayerExtruded bottom_contact_layer;
|
||||
MyLayerExtruded top_contact_layer;
|
||||
MyLayerExtruded base_layer;
|
||||
MyLayerExtruded interface_layer;
|
||||
MyLayerExtruded base_interface_layer;
|
||||
boost::container::static_vector<LayerCacheItem, 5> nonempty;
|
||||
|
||||
void add_nonempty_and_sort() {
|
||||
for (MyLayerExtruded *item : { &bottom_contact_layer, &top_contact_layer, &interface_layer, &base_interface_layer, &base_layer })
|
||||
if (! item->empty())
|
||||
this->nonempty.emplace_back(item);
|
||||
// Sort the layers with the same print_z coordinate by their heights, thickest first.
|
||||
std::stable_sort(this->nonempty.begin(), this->nonempty.end(), [](const LayerCacheItem &lc1, const LayerCacheItem &lc2) { return lc1.layer_extruded->layer->height > lc2.layer_extruded->layer->height; });
|
||||
}
|
||||
};
|
||||
std::vector<LayerCache> layer_caches(support_layers.size(), LayerCache());
|
||||
|
||||
|
@ -3816,6 +3816,7 @@ void PrintObjectSupportMaterial::generate_toolpaths(
|
|||
filler->link_max_length = coord_t(scale_(filler->spacing * link_max_length_factor / support_density));
|
||||
float density = float(support_density);
|
||||
bool sheath = with_sheath;
|
||||
bool no_sort = false;
|
||||
if (base_layer.layer->bottom_z < EPSILON) {
|
||||
// Base flange (the 1st layer).
|
||||
filler = filler_first_layer;
|
||||
|
@ -3827,7 +3828,8 @@ void PrintObjectSupportMaterial::generate_toolpaths(
|
|||
//FIXME When paralellizing, each thread shall have its own copy of the fillers.
|
||||
filler->spacing = flow.spacing();
|
||||
filler->link_max_length = coord_t(scale_(filler->spacing * link_max_length_factor / density));
|
||||
sheath = true;
|
||||
sheath = true;
|
||||
no_sort = true;
|
||||
}
|
||||
fill_expolygons_with_sheath_generate_paths(
|
||||
// Destination
|
||||
|
@ -3838,7 +3840,7 @@ void PrintObjectSupportMaterial::generate_toolpaths(
|
|||
filler, density,
|
||||
// Extrusion parameters
|
||||
erSupportMaterial, flow,
|
||||
sheath);
|
||||
sheath, no_sort);
|
||||
|
||||
}
|
||||
|
||||
|
@ -3847,24 +3849,13 @@ void PrintObjectSupportMaterial::generate_toolpaths(
|
|||
base_layer.could_merge(base_interface_layer))
|
||||
base_layer.merge(std::move(base_interface_layer));
|
||||
|
||||
layer_cache.overlaps.reserve(5);
|
||||
if (! bottom_contact_layer.empty())
|
||||
layer_cache.overlaps.push_back(&bottom_contact_layer);
|
||||
if (! top_contact_layer.empty())
|
||||
layer_cache.overlaps.push_back(&top_contact_layer);
|
||||
if (! interface_layer.empty())
|
||||
layer_cache.overlaps.push_back(&interface_layer);
|
||||
if (! base_interface_layer.empty())
|
||||
layer_cache.overlaps.push_back(&base_interface_layer);
|
||||
if (! base_layer.empty())
|
||||
layer_cache.overlaps.push_back(&base_layer);
|
||||
// Sort the layers with the same print_z coordinate by their heights, thickest first.
|
||||
std::sort(layer_cache.overlaps.begin(), layer_cache.overlaps.end(), [](const LayerCacheItem &lc1, const LayerCacheItem &lc2) { return lc1.layer_extruded->layer->height > lc2.layer_extruded->layer->height; });
|
||||
layer_cache.add_nonempty_and_sort();
|
||||
|
||||
// Collect the support areas with this print_z into islands, as there is no need
|
||||
// for retraction over these islands.
|
||||
Polygons polys;
|
||||
// Collect the extrusions, sorted by the bottom extrusion height.
|
||||
for (LayerCacheItem &layer_cache_item : layer_cache.overlaps) {
|
||||
for (LayerCacheItem &layer_cache_item : layer_cache.nonempty) {
|
||||
// Collect islands to polys.
|
||||
layer_cache_item.layer_extruded->polygons_append(polys);
|
||||
// The print_z of the top contact surfaces and bottom_z of the bottom contact surfaces are "free"
|
||||
|
@ -3878,32 +3869,22 @@ void PrintObjectSupportMaterial::generate_toolpaths(
|
|||
// Collect overlapping top/bottom surfaces.
|
||||
layer_cache_item.overlapping.reserve(20);
|
||||
coordf_t bottom_z = layer_cache_item.layer_extruded->layer->bottom_print_z() + EPSILON;
|
||||
for (int i = int(idx_layer_bottom_contact) - 1; i >= 0 && bottom_contacts[i]->print_z > bottom_z; -- i)
|
||||
layer_cache_item.overlapping.push_back(bottom_contacts[i]);
|
||||
for (int i = int(idx_layer_top_contact) - 1; i >= 0 && top_contacts[i]->print_z > bottom_z; -- i)
|
||||
layer_cache_item.overlapping.push_back(top_contacts[i]);
|
||||
auto add_overlapping = [&layer_cache_item, bottom_z](const MyLayersPtr &layers, size_t idx_top) {
|
||||
for (int i = int(idx_top) - 1; i >= 0 && layers[i]->print_z > bottom_z; -- i)
|
||||
layer_cache_item.overlapping.push_back(layers[i]);
|
||||
};
|
||||
add_overlapping(top_contacts, idx_layer_top_contact);
|
||||
if (layer_cache_item.layer_extruded->layer->layer_type == sltBottomContact) {
|
||||
// Bottom contact layer may overlap with a base layer, which may be changed to interface layer.
|
||||
for (int i = int(idx_layer_intermediate) - 1; i >= 0 && intermediate_layers[i]->print_z > bottom_z; -- i)
|
||||
layer_cache_item.overlapping.push_back(intermediate_layers[i]);
|
||||
for (int i = int(idx_layer_interface) - 1; i >= 0 && interface_layers[i]->print_z > bottom_z; -- i)
|
||||
layer_cache_item.overlapping.push_back(interface_layers[i]);
|
||||
for (int i = int(idx_layer_base_interface) - 1; i >= 0 && base_interface_layers[i]->print_z > bottom_z; -- i)
|
||||
layer_cache_item.overlapping.push_back(base_interface_layers[i]);
|
||||
add_overlapping(intermediate_layers, idx_layer_intermediate);
|
||||
add_overlapping(interface_layers, idx_layer_interface);
|
||||
add_overlapping(base_interface_layers, idx_layer_base_interface);
|
||||
}
|
||||
std::sort(layer_cache_item.overlapping.begin(), layer_cache_item.overlapping.end(), MyLayersPtrCompare());
|
||||
// Order the layers by lexicographically by an increasing print_z and a decreasing layer height.
|
||||
std::stable_sort(layer_cache_item.overlapping.begin(), layer_cache_item.overlapping.end(), [](auto *l1, auto *l2) { return *l1 < *l2; });
|
||||
}
|
||||
if (! polys.empty())
|
||||
expolygons_append(support_layer.support_islands.expolygons, union_ex(polys));
|
||||
/* {
|
||||
require "Slic3r/SVG.pm";
|
||||
Slic3r::SVG::output("islands_" . $z . ".svg",
|
||||
red_expolygons => union_ex($contact),
|
||||
green_expolygons => union_ex($interface),
|
||||
green_polylines => [ map $_->unpack->polyline, @{$layer->support_contact_fills} ],
|
||||
polylines => [ map $_->unpack->polyline, @{$layer->support_fills} ],
|
||||
);
|
||||
} */
|
||||
} // for each support_layer_id
|
||||
});
|
||||
|
||||
|
@ -3914,7 +3895,9 @@ void PrintObjectSupportMaterial::generate_toolpaths(
|
|||
for (size_t support_layer_id = range.begin(); support_layer_id < range.end(); ++ support_layer_id) {
|
||||
SupportLayer &support_layer = *support_layers[support_layer_id];
|
||||
LayerCache &layer_cache = layer_caches[support_layer_id];
|
||||
for (LayerCacheItem &layer_cache_item : layer_cache.overlaps) {
|
||||
// For all extrusion types at this print_z, ordered by decreasing layer height:
|
||||
for (LayerCacheItem &layer_cache_item : layer_cache.nonempty) {
|
||||
// Trim the extrusion height from the bottom by the overlapping layers.
|
||||
modulate_extrusion_by_overlapping_layers(layer_cache_item.layer_extruded->extrusions, *layer_cache_item.layer_extruded->layer, layer_cache_item.overlapping);
|
||||
support_layer.support_fills.append(std::move(layer_cache_item.layer_extruded->extrusions));
|
||||
}
|
||||
|
|
|
@ -285,6 +285,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config)
|
|||
"support_material_xy_spacing" })
|
||||
toggle_field(el, have_support_material);
|
||||
toggle_field("support_material_threshold", have_support_material_auto);
|
||||
toggle_field("support_material_bottom_contact_distance", have_support_material && ! have_support_soluble);
|
||||
|
||||
for (auto el : { "support_material_bottom_interface_layers", "support_material_interface_spacing", "support_material_interface_extruder",
|
||||
"support_material_interface_speed", "support_material_interface_contact_loops" })
|
||||
|
|
|
@ -1762,7 +1762,8 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
|
|||
// These values are necessary to construct SlicingParameters by the Canvas3D variable layer height editor.
|
||||
"layer_height", "first_layer_height", "min_layer_height", "max_layer_height",
|
||||
"brim_width", "perimeters", "perimeter_extruder", "fill_density", "infill_extruder", "top_solid_layers",
|
||||
"support_material", "support_material_extruder", "support_material_interface_extruder", "support_material_contact_distance", "raft_layers"
|
||||
"support_material", "support_material_extruder", "support_material_interface_extruder",
|
||||
"support_material_contact_distance", "support_material_bottom_contact_distance", "raft_layers"
|
||||
}))
|
||||
, sidebar(new Sidebar(q))
|
||||
, m_ui_jobs(this)
|
||||
|
|
|
@ -1507,6 +1507,7 @@ void TabPrint::build()
|
|||
|
||||
optgroup = page->new_optgroup(L("Options for support material and raft"));
|
||||
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");
|
||||
optgroup->append_single_option_line("support_material_with_sheath", category_path + "with-sheath-around-the-support");
|
||||
optgroup->append_single_option_line("support_material_spacing", category_path + "pattern-spacing-0-inf");
|
||||
|
|
Loading…
Reference in a new issue