Fixed some of the raft issues introduced in the new C++ supports.
This commit is contained in:
parent
420e387055
commit
f5e4026aee
@ -290,20 +290,6 @@ void PrintObjectSupportMaterial::generate(PrintObject &object)
|
|||||||
// top contacts over the bottom contacts.
|
// top contacts over the bottom contacts.
|
||||||
this->trim_top_contacts_by_bottom_contacts(object, bottom_contacts, top_contacts);
|
this->trim_top_contacts_by_bottom_contacts(object, bottom_contacts, top_contacts);
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(info) << "Support generator - Creating raft";
|
|
||||||
|
|
||||||
// If raft is to be generated, the 1st top_contact layer will contain the 1st object layer silhouette with holes filled.
|
|
||||||
// There is also a 1st intermediate layer containing bases of support columns.
|
|
||||||
// Inflate the bases of the support columns and create the raft base under the object.
|
|
||||||
MyLayersPtr raft_layers = this->generate_raft_base(object, top_contacts, intermediate_layers, layer_storage);
|
|
||||||
|
|
||||||
/*
|
|
||||||
// If we wanted to apply some special logic to the first support layers lying on
|
|
||||||
// object's top surfaces this is the place to detect them
|
|
||||||
LayersSet shape;
|
|
||||||
if (m_objectconfig->support_material_pattern.value == smpPillars)
|
|
||||||
shape = this->generate_pillars_shape(contact, support_z);
|
|
||||||
*/
|
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(info) << "Support generator - Creating interfaces";
|
BOOST_LOG_TRIVIAL(info) << "Support generator - Creating interfaces";
|
||||||
|
|
||||||
@ -311,6 +297,13 @@ void PrintObjectSupportMaterial::generate(PrintObject &object)
|
|||||||
MyLayersPtr interface_layers = this->generate_interface_layers(
|
MyLayersPtr interface_layers = this->generate_interface_layers(
|
||||||
object, bottom_contacts, top_contacts, intermediate_layers, layer_storage);
|
object, bottom_contacts, top_contacts, intermediate_layers, layer_storage);
|
||||||
|
|
||||||
|
BOOST_LOG_TRIVIAL(info) << "Support generator - Creating raft";
|
||||||
|
|
||||||
|
// If raft is to be generated, the 1st top_contact layer will contain the 1st object layer silhouette with holes filled.
|
||||||
|
// There is also a 1st intermediate layer containing bases of support columns.
|
||||||
|
// Inflate the bases of the support columns and create the raft base under the object.
|
||||||
|
MyLayersPtr raft_layers = this->generate_raft_base(object, top_contacts, interface_layers, intermediate_layers, layer_storage);
|
||||||
|
|
||||||
#ifdef SLIC3R_DEBUG
|
#ifdef SLIC3R_DEBUG
|
||||||
for (MyLayersPtr::const_iterator it = interface_layers.begin(); it != interface_layers.end(); ++ it)
|
for (MyLayersPtr::const_iterator it = interface_layers.begin(); it != interface_layers.end(); ++ it)
|
||||||
Slic3r::SVG::export_expolygons(
|
Slic3r::SVG::export_expolygons(
|
||||||
@ -697,7 +690,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
|
|||||||
0.;
|
0.;
|
||||||
new_layer.print_z = layer.print_z - layer.height;
|
new_layer.print_z = layer.print_z - layer.height;
|
||||||
new_layer.bottom_z = new_layer.print_z - new_layer.height;
|
new_layer.bottom_z = new_layer.print_z - new_layer.height;
|
||||||
} else {
|
} else {
|
||||||
// Contact layer will be printed with a normal flow, but
|
// Contact layer will be printed with a normal flow, but
|
||||||
// it will support layers printed with a bridging flow.
|
// it will support layers printed with a bridging flow.
|
||||||
//FIXME Probably printing with the bridge flow? How about the unsupported perimeters? Are they printed with the bridging flow?
|
//FIXME Probably printing with the bridge flow? How about the unsupported perimeters? Are they printed with the bridging flow?
|
||||||
@ -716,7 +709,11 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
|
|||||||
new_layer.print_z = layer.print_z - nozzle_dmr - m_object_config->support_material_contact_distance;
|
new_layer.print_z = layer.print_z - nozzle_dmr - m_object_config->support_material_contact_distance;
|
||||||
new_layer.bottom_z = new_layer.print_z;
|
new_layer.bottom_z = new_layer.print_z;
|
||||||
new_layer.height = 0.;
|
new_layer.height = 0.;
|
||||||
if (this->synchronize_layers()) {
|
if (layer_id == 0) {
|
||||||
|
// This is a raft contact layer sitting directly on the print bed.
|
||||||
|
new_layer.bottom_z = m_slicing_params.raft_interface_top_z;
|
||||||
|
new_layer.height = m_slicing_params.contact_raft_layer_height;
|
||||||
|
} else if (this->synchronize_layers()) {
|
||||||
// Align bottom of this layer with a top of the closest object layer
|
// Align bottom of this layer with a top of the closest object layer
|
||||||
// while not trespassing into the 1st layer and keeping the support layer thickness bounded.
|
// while not trespassing into the 1st layer and keeping the support layer thickness bounded.
|
||||||
int layer_id_below = int(layer_id) - 1;
|
int layer_id_below = int(layer_id) - 1;
|
||||||
@ -749,7 +746,8 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
|
|||||||
// Don't want to print a layer below the first layer height as it may not stick well.
|
// Don't want to print a layer below the first layer height as it may not stick well.
|
||||||
//FIXME there may be a need for a single layer support, then one may decide to print it either as a bottom contact or a top contact
|
//FIXME there may be a need for a single layer support, then one may decide to print it either as a bottom contact or a top contact
|
||||||
// and it may actually make sense to do it with a thinner layer than the first layer height.
|
// and it may actually make sense to do it with a thinner layer than the first layer height.
|
||||||
if (new_layer.print_z < m_slicing_params.first_print_layer_height + m_support_layer_height_min)
|
if (new_layer.print_z < m_slicing_params.first_print_layer_height - EPSILON)
|
||||||
|
// This contact layer is below the first layer height, therefore not printable. Don't support this surface.
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
@ -1027,7 +1025,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::raft_and_int
|
|||||||
return intermediate_layers;
|
return intermediate_layers;
|
||||||
std::sort(extremes.begin(), extremes.end());
|
std::sort(extremes.begin(), extremes.end());
|
||||||
|
|
||||||
assert(extremes.front().z() > m_slicing_params.raft_interface_top_z && extremes.front().z() >= m_slicing_params.first_print_layer_height);
|
assert(extremes.front().z() > m_slicing_params.raft_interface_top_z - EPSILON && (m_slicing_params.raft_layers() == 1 || extremes.front().z() > m_slicing_params.first_print_layer_height - EPSILON));
|
||||||
|
|
||||||
// bool synchronize = m_slicing_params.soluble_interface || this->synchronize_layers();
|
// bool synchronize = m_slicing_params.soluble_interface || this->synchronize_layers();
|
||||||
bool synchronize = this->synchronize_layers();
|
bool synchronize = this->synchronize_layers();
|
||||||
@ -1038,10 +1036,15 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::raft_and_int
|
|||||||
// Intermediate layers are always printed with a normal etrusion flow (non-bridging).
|
// Intermediate layers are always printed with a normal etrusion flow (non-bridging).
|
||||||
size_t idx_layer_object = 0;
|
size_t idx_layer_object = 0;
|
||||||
for (size_t idx_extreme = 0; idx_extreme < extremes.size(); ++ idx_extreme) {
|
for (size_t idx_extreme = 0; idx_extreme < extremes.size(); ++ idx_extreme) {
|
||||||
LayerExtreme *extr1 = (idx_extreme == 0) ? NULL : &extremes[idx_extreme-1];
|
LayerExtreme &extr2 = extremes[idx_extreme];
|
||||||
|
coordf_t extr2z = extr2.z();
|
||||||
|
if (std::abs(extr2z - m_slicing_params.raft_interface_top_z) < EPSILON)
|
||||||
|
// This is a raft contact layer.
|
||||||
|
continue;
|
||||||
|
LayerExtreme *extr1 = (idx_extreme == 0) ? NULL : &extremes[idx_extreme - 1];
|
||||||
coordf_t extr1z = (extr1 == NULL) ? m_slicing_params.raft_interface_top_z : extr1->z();
|
coordf_t extr1z = (extr1 == NULL) ? m_slicing_params.raft_interface_top_z : extr1->z();
|
||||||
assert(extremes[idx_extreme].z() > extr1z);
|
assert(extr2z > extr1z + EPSILON);
|
||||||
if (extr1z == 0.) {
|
if (std::abs(extr1z) < EPSILON) {
|
||||||
// This layer interval starts with the 1st layer. Print the 1st layer using the prescribed 1st layer thickness.
|
// This layer interval starts with the 1st layer. Print the 1st layer using the prescribed 1st layer thickness.
|
||||||
assert(intermediate_layers.empty());
|
assert(intermediate_layers.empty());
|
||||||
MyLayer &layer_new = layer_allocate(layer_storage, sltIntermediate);
|
MyLayer &layer_new = layer_allocate(layer_storage, sltIntermediate);
|
||||||
@ -1051,8 +1054,6 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::raft_and_int
|
|||||||
intermediate_layers.push_back(&layer_new);
|
intermediate_layers.push_back(&layer_new);
|
||||||
// Continue printing the other layers up to extr2z.
|
// Continue printing the other layers up to extr2z.
|
||||||
}
|
}
|
||||||
LayerExtreme &extr2 = extremes[idx_extreme];
|
|
||||||
coordf_t extr2z = extr2.z();
|
|
||||||
coordf_t dist = extr2z - extr1z;
|
coordf_t dist = extr2z - extr1z;
|
||||||
assert(dist >= 0.);
|
assert(dist >= 0.);
|
||||||
if (dist == 0.)
|
if (dist == 0.)
|
||||||
@ -1316,38 +1317,49 @@ void PrintObjectSupportMaterial::trim_support_layers_by_object(
|
|||||||
PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::generate_raft_base(
|
PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::generate_raft_base(
|
||||||
const PrintObject &object,
|
const PrintObject &object,
|
||||||
const MyLayersPtr &top_contacts,
|
const MyLayersPtr &top_contacts,
|
||||||
MyLayersPtr &intermediate_layers,
|
const MyLayersPtr &interface_layers,
|
||||||
|
const MyLayersPtr &base_layers,
|
||||||
MyLayerStorage &layer_storage) const
|
MyLayerStorage &layer_storage) const
|
||||||
{
|
{
|
||||||
// Areas covered by the raft, supporting the raft interface and the support columns.
|
|
||||||
Polygons raft_polygons;
|
|
||||||
// How much to inflate the support columns to be stable. This also applies to the 1st layer, if no raft layers are to be printed.
|
// How much to inflate the support columns to be stable. This also applies to the 1st layer, if no raft layers are to be printed.
|
||||||
const float inflate_factor = scale_(3.);
|
const float inflate_factor_fine = float(scale_(0.5));
|
||||||
MyLayer *contacts = top_contacts.empty() ? nullptr : top_contacts.front();
|
const float inflate_factor_1st_layer = float(scale_(3.)) - inflate_factor_fine;
|
||||||
MyLayer *columns_base = intermediate_layers.empty() ? nullptr : intermediate_layers.front();
|
MyLayer *contacts = top_contacts .empty() ? nullptr : top_contacts .front();
|
||||||
|
MyLayer *interfaces = interface_layers.empty() ? nullptr : interface_layers.front();
|
||||||
|
MyLayer *columns_base = base_layers .empty() ? nullptr : base_layers .front();
|
||||||
if (contacts != nullptr && contacts->print_z > m_slicing_params.raft_contact_top_z + EPSILON)
|
if (contacts != nullptr && contacts->print_z > m_slicing_params.raft_contact_top_z + EPSILON)
|
||||||
// This is not the raft contact layer.
|
// This is not the raft contact layer.
|
||||||
contacts = nullptr;
|
contacts = nullptr;
|
||||||
|
if (interfaces != nullptr && interfaces->bottom_print_z() > m_slicing_params.raft_interface_top_z + EPSILON)
|
||||||
|
// This is not the raft column base layer.
|
||||||
|
interfaces = nullptr;
|
||||||
|
if (columns_base != nullptr && columns_base->bottom_print_z() > m_slicing_params.raft_interface_top_z + EPSILON)
|
||||||
|
// This is not the raft interface layer.
|
||||||
|
columns_base = nullptr;
|
||||||
|
|
||||||
|
Polygons interface_polygons;
|
||||||
|
if (contacts != nullptr && ! contacts->polygons.empty())
|
||||||
|
polygons_append(interface_polygons, offset(contacts->polygons, inflate_factor_fine, SUPPORT_SURFACES_OFFSET_PARAMETERS));
|
||||||
|
if (interfaces != nullptr && ! interfaces->polygons.empty())
|
||||||
|
polygons_append(interface_polygons, offset(interfaces->polygons, inflate_factor_fine, SUPPORT_SURFACES_OFFSET_PARAMETERS));
|
||||||
|
|
||||||
// Output vector.
|
// Output vector.
|
||||||
MyLayersPtr raft_layers;
|
MyLayersPtr raft_layers;
|
||||||
|
|
||||||
// Expand the 1st intermediate layer, which contains the bases of the support columns.
|
if (m_slicing_params.raft_layers() > 1) {
|
||||||
Polygons base;
|
Polygons base;
|
||||||
if (columns_base != nullptr) {
|
Polygons columns;
|
||||||
base = offset(columns_base->polygons, inflate_factor);
|
if (columns_base != nullptr) {
|
||||||
// Modify the 1st intermediate layer with the expanded support columns.
|
base = columns_base->polygons;
|
||||||
columns_base->polygons = diff(
|
columns = base;
|
||||||
base,
|
if (! interface_polygons.empty())
|
||||||
offset(m_object->layers.front()->slices.expolygons, scale_(m_gap_xy), SUPPORT_SURFACES_OFFSET_PARAMETERS));
|
// Trim the 1st layer columns with the inflated interface polygons.
|
||||||
if (contacts != nullptr)
|
columns = diff(columns, interface_polygons);
|
||||||
columns_base->polygons = diff(columns_base->polygons, contacts->polygons);
|
}
|
||||||
}
|
if (! interface_polygons.empty()) {
|
||||||
if (m_slicing_params.has_raft() && contacts != nullptr) {
|
// Merge the untrimmed columns base with the expanded raft interface, to be used for the support base and interface.
|
||||||
// Merge the untrimmed columns base with the expanded raft interface, to be used for the support base and interface.
|
base = union_(base, interface_polygons);
|
||||||
base = union_(base, offset(contacts->polygons, inflate_factor, SUPPORT_SURFACES_OFFSET_PARAMETERS));
|
}
|
||||||
}
|
|
||||||
if (m_slicing_params.has_raft() && m_slicing_params.raft_layers() > 1 && ! base.empty()) {
|
|
||||||
// Do not add the raft contact layer, only add the raft layers below the contact layer.
|
// Do not add the raft contact layer, only add the raft layers below the contact layer.
|
||||||
// Insert the 1st layer.
|
// Insert the 1st layer.
|
||||||
{
|
{
|
||||||
@ -1356,7 +1368,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::generate_raf
|
|||||||
new_layer.print_z = m_slicing_params.first_print_layer_height;
|
new_layer.print_z = m_slicing_params.first_print_layer_height;
|
||||||
new_layer.height = m_slicing_params.first_print_layer_height;
|
new_layer.height = m_slicing_params.first_print_layer_height;
|
||||||
new_layer.bottom_z = 0.;
|
new_layer.bottom_z = 0.;
|
||||||
new_layer.polygons = base;
|
new_layer.polygons = offset(base, inflate_factor_1st_layer);
|
||||||
}
|
}
|
||||||
// Insert the base layers.
|
// Insert the base layers.
|
||||||
for (size_t i = 1; i < m_slicing_params.base_raft_layers; ++ i) {
|
for (size_t i = 1; i < m_slicing_params.base_raft_layers; ++ i) {
|
||||||
@ -1376,8 +1388,17 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::generate_raf
|
|||||||
new_layer.print_z = print_z + m_slicing_params.interface_raft_layer_height;
|
new_layer.print_z = print_z + m_slicing_params.interface_raft_layer_height;
|
||||||
new_layer.height = m_slicing_params.interface_raft_layer_height;
|
new_layer.height = m_slicing_params.interface_raft_layer_height;
|
||||||
new_layer.bottom_z = print_z;
|
new_layer.bottom_z = print_z;
|
||||||
new_layer.polygons = base;
|
new_layer.polygons = interface_polygons;
|
||||||
|
//FIXME misusing contact_polygons for support columns.
|
||||||
|
new_layer.contact_polygons = new Polygons(columns);
|
||||||
}
|
}
|
||||||
|
} else if (columns_base != nullptr) {
|
||||||
|
// Expand the bases of the support columns in the 1st layer.
|
||||||
|
columns_base->polygons = diff(
|
||||||
|
offset(columns_base->polygons, inflate_factor_1st_layer),
|
||||||
|
offset(m_object->layers.front()->slices.expolygons, scale_(m_gap_xy), SUPPORT_SURFACES_OFFSET_PARAMETERS));
|
||||||
|
if (contacts != nullptr)
|
||||||
|
columns_base->polygons = diff(columns_base->polygons, interface_polygons);
|
||||||
}
|
}
|
||||||
|
|
||||||
return raft_layers;
|
return raft_layers;
|
||||||
@ -2079,15 +2100,27 @@ void PrintObjectSupportMaterial::generate_toolpaths(
|
|||||||
LoopInterfaceProcessor loop_interface_processor(1.5 * m_support_material_interface_flow.scaled_width());
|
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;
|
loop_interface_processor.n_contact_loops = this->has_contact_loops() ? 1 : 0;
|
||||||
|
|
||||||
|
float base_angle = float(Geometry::deg2rad(m_object_config->support_material_angle));
|
||||||
|
float interface_angle = float(Geometry::deg2rad(m_object_config->support_material_angle + 90.));
|
||||||
|
coordf_t interface_spacing = m_object_config->support_material_interface_spacing.value + m_support_material_interface_flow.spacing();
|
||||||
|
coordf_t interface_density = std::min(1., m_support_material_interface_flow.spacing() / interface_spacing);
|
||||||
|
coordf_t support_spacing = m_object_config->support_material_spacing.value + m_support_material_flow.spacing();
|
||||||
|
coordf_t support_density = std::min(1., m_support_material_flow.spacing() / support_spacing);
|
||||||
|
if (m_object_config->support_material_interface_layers.value == 0) {
|
||||||
|
// No interface layers allowed, print everything with the base support pattern.
|
||||||
|
interface_spacing = support_spacing;
|
||||||
|
interface_density = support_density;
|
||||||
|
}
|
||||||
|
|
||||||
// Prepare fillers.
|
// Prepare fillers.
|
||||||
SupportMaterialPattern support_pattern = m_object_config->support_material_pattern;
|
SupportMaterialPattern support_pattern = m_object_config->support_material_pattern;
|
||||||
bool with_sheath = m_object_config->support_material_with_sheath;
|
bool with_sheath = m_object_config->support_material_with_sheath;
|
||||||
InfillPattern infill_pattern;
|
InfillPattern infill_pattern;
|
||||||
std::vector<double> angles;
|
std::vector<float> angles;
|
||||||
angles.push_back(Geometry::deg2rad(m_object_config->support_material_angle));
|
angles.push_back(base_angle);
|
||||||
switch (support_pattern) {
|
switch (support_pattern) {
|
||||||
case smpRectilinearGrid:
|
case smpRectilinearGrid:
|
||||||
angles.push_back(angles[0] + Geometry::deg2rad(90.));
|
angles.push_back(interface_angle);
|
||||||
// fall through
|
// fall through
|
||||||
case smpRectilinear:
|
case smpRectilinear:
|
||||||
infill_pattern = ipRectilinear;
|
infill_pattern = ipRectilinear;
|
||||||
@ -2106,20 +2139,36 @@ void PrintObjectSupportMaterial::generate_toolpaths(
|
|||||||
filler_support->set_bounding_box(bbox_object);
|
filler_support->set_bounding_box(bbox_object);
|
||||||
}
|
}
|
||||||
|
|
||||||
coordf_t interface_angle = Geometry::deg2rad(m_object_config->support_material_angle + 90.);
|
|
||||||
coordf_t interface_spacing = m_object_config->support_material_interface_spacing.value + m_support_material_interface_flow.spacing();
|
|
||||||
coordf_t interface_density = std::min(1., m_support_material_interface_flow.spacing() / interface_spacing);
|
|
||||||
coordf_t support_spacing = m_object_config->support_material_spacing.value + m_support_material_flow.spacing();
|
|
||||||
coordf_t support_density = std::min(1., m_support_material_flow.spacing() / support_spacing);
|
|
||||||
if (m_object_config->support_material_interface_layers.value == 0) {
|
|
||||||
// No interface layers allowed, print everything with the base support pattern.
|
|
||||||
interface_spacing = support_spacing;
|
|
||||||
interface_density = support_density;
|
|
||||||
}
|
|
||||||
|
|
||||||
// const coordf_t link_max_length_factor = 3.;
|
// const coordf_t link_max_length_factor = 3.;
|
||||||
const coordf_t link_max_length_factor = 0.;
|
const coordf_t link_max_length_factor = 0.;
|
||||||
|
|
||||||
|
float raft_angle_1st_layer = 0.f;
|
||||||
|
float raft_angle_base = 0.f;
|
||||||
|
float raft_angle_interface = 0.f;
|
||||||
|
if (m_slicing_params.base_raft_layers > 1) {
|
||||||
|
// There are all raft layer types (1st layer, base, interface & contact layers) available.
|
||||||
|
raft_angle_1st_layer = interface_angle;
|
||||||
|
raft_angle_base = base_angle;
|
||||||
|
raft_angle_interface = interface_angle;
|
||||||
|
} else if (m_slicing_params.base_raft_layers == 1 || m_slicing_params.interface_raft_layers > 1) {
|
||||||
|
// 1st layer, interface & contact layers available.
|
||||||
|
raft_angle_1st_layer = base_angle;
|
||||||
|
if (this->has_support())
|
||||||
|
// Print 1st layer at 45 degrees from both the interface and base angles as both can land on the 1st layer.
|
||||||
|
raft_angle_1st_layer += 0.7854f;
|
||||||
|
raft_angle_interface = interface_angle;
|
||||||
|
} else if (m_slicing_params.interface_raft_layers == 1) {
|
||||||
|
// Only the contact raft layer is non-empty, which will be printed as the 1st layer.
|
||||||
|
assert(m_slicing_params.base_raft_layers == 0);
|
||||||
|
assert(m_slicing_params.interface_raft_layers == 1);
|
||||||
|
assert(m_slicing_params.raft_layers() == 1 && raft_layers.size() == 0);
|
||||||
|
} else {
|
||||||
|
// No raft.
|
||||||
|
assert(m_slicing_params.base_raft_layers == 0);
|
||||||
|
assert(m_slicing_params.interface_raft_layers == 0);
|
||||||
|
assert(m_slicing_params.raft_layers() == 0 && raft_layers.size() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
//FIXME Parallelize the support generator.
|
//FIXME Parallelize the support generator.
|
||||||
// Insert the raft base layers.
|
// Insert the raft base layers.
|
||||||
size_t support_layer_id = 0;
|
size_t support_layer_id = 0;
|
||||||
@ -2130,52 +2179,79 @@ void PrintObjectSupportMaterial::generate_toolpaths(
|
|||||||
assert(support_layer.support_interface_fills.entities.empty());
|
assert(support_layer.support_interface_fills.entities.empty());
|
||||||
assert(support_layer.support_islands.expolygons.empty());
|
assert(support_layer.support_islands.expolygons.empty());
|
||||||
MyLayer &raft_layer = *raft_layers[support_layer_id];
|
MyLayer &raft_layer = *raft_layers[support_layer_id];
|
||||||
|
|
||||||
|
// Print the support base below the support columns, or the support base for the support columns plus the contacts.
|
||||||
|
if (support_layer_id > 0) {
|
||||||
|
Polygons to_infill_polygons = (support_layer_id < m_slicing_params.base_raft_layers) ?
|
||||||
|
raft_layer.polygons :
|
||||||
|
//FIXME misusing contact_polygons for support columns.
|
||||||
|
((raft_layer.contact_polygons == nullptr) ? Polygons() : *raft_layer.contact_polygons);
|
||||||
|
if (! to_infill_polygons.empty()) {
|
||||||
|
Flow flow(m_support_material_flow.width, raft_layer.height, m_support_material_flow.nozzle_diameter, raft_layer.bridging);
|
||||||
|
// find centerline of the external loop/extrusions
|
||||||
|
ExPolygons to_infill = (support_layer_id == 0 || ! with_sheath) ?
|
||||||
|
// union_ex(base_polygons, true) :
|
||||||
|
offset2_ex(to_infill_polygons, SCALED_EPSILON, - SCALED_EPSILON) :
|
||||||
|
offset2_ex(to_infill_polygons, SCALED_EPSILON, - SCALED_EPSILON - 0.5*flow.scaled_width());
|
||||||
|
if (! to_infill.empty() && with_sheath) {
|
||||||
|
// Draw a perimeter all around the support infill. This makes the support stable, but difficult to remove.
|
||||||
|
// TODO: use brim ordering algorithm
|
||||||
|
to_infill_polygons = to_polygons(to_infill);
|
||||||
|
// TODO: use offset2_ex()
|
||||||
|
to_infill = offset_ex(to_infill, - flow.scaled_spacing());
|
||||||
|
extrusion_entities_append_paths(
|
||||||
|
support_layer.support_fills.entities,
|
||||||
|
to_polylines(STDMOVE(to_infill_polygons)),
|
||||||
|
erSupportMaterial, flow.mm3_per_mm(), flow.width, flow.height);
|
||||||
|
}
|
||||||
|
if (! to_infill.empty()) {
|
||||||
|
// We don't use $base_flow->spacing because we need a constant spacing
|
||||||
|
// value that guarantees that all layers are correctly aligned.
|
||||||
|
Fill *filler = filler_support.get();
|
||||||
|
filler->angle = raft_angle_base;
|
||||||
|
filler->spacing = m_support_material_flow.spacing();
|
||||||
|
filler->link_max_length = scale_(filler->spacing * link_max_length_factor / support_density);
|
||||||
|
fill_expolygons_generate_paths(
|
||||||
|
// Destination
|
||||||
|
support_layer.support_fills.entities,
|
||||||
|
// Regions to fill
|
||||||
|
STDMOVE(to_infill),
|
||||||
|
// Filler and its parameters
|
||||||
|
filler, support_density,
|
||||||
|
// Extrusion parameters
|
||||||
|
erSupportMaterial, flow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//FIXME When paralellizing, each thread shall have its own copy of the fillers.
|
//FIXME When paralellizing, each thread shall have its own copy of the fillers.
|
||||||
Fill *filler = filler_support.get();
|
Fill *filler = filler_interface.get();
|
||||||
filler->angle = 0.;
|
Flow flow = m_first_layer_flow;
|
||||||
// We don't use $base_flow->spacing because we need a constant spacing
|
float density = 0.f;
|
||||||
// value that guarantees that all layers are correctly aligned.
|
|
||||||
Flow flow(m_support_material_flow.width, raft_layer.height, m_support_material_flow.nozzle_diameter, raft_layer.bridging);
|
|
||||||
filler->spacing = m_support_material_flow.spacing();
|
|
||||||
filler->link_max_length = scale_(filler->spacing * link_max_length_factor / support_density);
|
|
||||||
float density = support_density;
|
|
||||||
// find centerline of the external loop/extrusions
|
|
||||||
ExPolygons to_infill = (support_layer_id == 0 || ! with_sheath) ?
|
|
||||||
// union_ex(base_polygons, true) :
|
|
||||||
offset2_ex(raft_layer.polygons, SCALED_EPSILON, - SCALED_EPSILON) :
|
|
||||||
offset2_ex(raft_layer.polygons, SCALED_EPSILON, - SCALED_EPSILON - 0.5*flow.scaled_width());
|
|
||||||
if (support_layer_id == 0) {
|
if (support_layer_id == 0) {
|
||||||
// Base flange.
|
// Base flange.
|
||||||
filler = filler_interface.get();
|
filler->angle = raft_angle_1st_layer;
|
||||||
filler->angle = Geometry::deg2rad(m_object_config->support_material_angle + 90.);
|
filler->spacing = m_first_layer_flow.spacing();
|
||||||
density = 0.5f;
|
density = 0.5f;
|
||||||
flow = m_first_layer_flow;
|
} else if (support_layer_id >= m_slicing_params.base_raft_layers) {
|
||||||
// use the proper spacing for first layer as we don't need to align
|
filler->angle = raft_angle_interface;
|
||||||
// its pattern to the other layers
|
// We don't use $base_flow->spacing because we need a constant spacing
|
||||||
//FIXME When paralellizing, each thread shall have its own copy of the fillers.
|
// value that guarantees that all layers are correctly aligned.
|
||||||
filler->spacing = flow.spacing();
|
filler->spacing = m_support_material_flow.spacing();
|
||||||
filler->link_max_length = scale_(filler->spacing * link_max_length_factor / density);
|
flow = Flow(m_support_material_interface_flow.width, raft_layer.height, m_support_material_flow.nozzle_diameter, raft_layer.bridging);
|
||||||
} else if (with_sheath) {
|
density = interface_density;
|
||||||
// Draw a perimeter all around the support infill. This makes the support stable, but difficult to remove.
|
} else
|
||||||
// TODO: use brim ordering algorithm
|
continue;
|
||||||
Polygons to_infill_polygons = to_polygons(to_infill);
|
filler->link_max_length = scale_(filler->spacing * link_max_length_factor / density);
|
||||||
// TODO: use offset2_ex()
|
|
||||||
to_infill = offset_ex(to_infill, - flow.scaled_spacing());
|
|
||||||
extrusion_entities_append_paths(
|
|
||||||
support_layer.support_fills.entities,
|
|
||||||
to_polylines(STDMOVE(to_infill_polygons)),
|
|
||||||
erSupportMaterial, flow.mm3_per_mm(), flow.width, flow.height);
|
|
||||||
}
|
|
||||||
fill_expolygons_generate_paths(
|
fill_expolygons_generate_paths(
|
||||||
// Destination
|
// Destination
|
||||||
support_layer.support_fills.entities,
|
support_layer.support_fills.entities,
|
||||||
// Regions to fill
|
// Regions to fill
|
||||||
STDMOVE(to_infill),
|
offset2_ex(raft_layer.polygons, SCALED_EPSILON, - SCALED_EPSILON),
|
||||||
// Filler and its parameters
|
// Filler and its parameters
|
||||||
filler, density,
|
filler, density,
|
||||||
// Extrusion parameters
|
// Extrusion parameters
|
||||||
erSupportMaterial, flow);
|
(support_layer_id < m_slicing_params.base_raft_layers) ? erSupportMaterial : erSupportMaterialInterface, flow);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Indices of the 1st layer in their respective container at the support layer height.
|
// Indices of the 1st layer in their respective container at the support layer height.
|
||||||
@ -2237,16 +2313,17 @@ void PrintObjectSupportMaterial::generate_toolpaths(
|
|||||||
|
|
||||||
// Top and bottom contacts, interface layers.
|
// Top and bottom contacts, interface layers.
|
||||||
for (size_t i = 0; i < 3; ++ i) {
|
for (size_t i = 0; i < 3; ++ i) {
|
||||||
MyLayerExtruded &layer_ex = (i == 0) ? top_contact_layer : (i == 1 ? interface_layer : bottom_contact_layer);
|
MyLayerExtruded &layer_ex = (i == 0) ? top_contact_layer : (i == 1 ? bottom_contact_layer : interface_layer);
|
||||||
if (layer_ex.empty() || layer_ex.polygons_to_extrude().empty())
|
if (layer_ex.empty() || layer_ex.polygons_to_extrude().empty())
|
||||||
continue;
|
continue;
|
||||||
//FIXME When paralellizing, each thread shall have its own copy of the fillers.
|
//FIXME When paralellizing, each thread shall have its own copy of the fillers.
|
||||||
|
bool interface_as_base = (&layer_ex == &interface_layer) && m_object_config->support_material_interface_layers.value == 0;
|
||||||
Flow interface_flow(
|
Flow interface_flow(
|
||||||
layer_ex.layer->bridging ? layer_ex.layer->height : m_support_material_interface_flow.width,
|
layer_ex.layer->bridging ? layer_ex.layer->height : (interface_as_base ? m_support_material_flow.width : m_support_material_interface_flow.width),
|
||||||
layer_ex.layer->height,
|
layer_ex.layer->height,
|
||||||
m_support_material_interface_flow.nozzle_diameter,
|
m_support_material_interface_flow.nozzle_diameter,
|
||||||
layer_ex.layer->bridging);
|
layer_ex.layer->bridging);
|
||||||
filler_interface->angle = (i == 2 && m_object_config->support_material_interface_layers.value == 0) ?
|
filler_interface->angle = interface_as_base ?
|
||||||
// If zero interface layers are configured, use the same angle as for the base layers.
|
// If zero interface layers are configured, use the same angle as for the base layers.
|
||||||
angles[support_layer_id % angles.size()] :
|
angles[support_layer_id % angles.size()] :
|
||||||
// Use interface angle for the interface layers.
|
// Use interface angle for the interface layers.
|
||||||
@ -2281,7 +2358,7 @@ void PrintObjectSupportMaterial::generate_toolpaths(
|
|||||||
offset2_ex(base_layer.polygons_to_extrude(), SCALED_EPSILON, - SCALED_EPSILON) :
|
offset2_ex(base_layer.polygons_to_extrude(), SCALED_EPSILON, - SCALED_EPSILON) :
|
||||||
offset2_ex(base_layer.polygons_to_extrude(), SCALED_EPSILON, - SCALED_EPSILON - 0.5*flow.scaled_width());
|
offset2_ex(base_layer.polygons_to_extrude(), SCALED_EPSILON, - SCALED_EPSILON - 0.5*flow.scaled_width());
|
||||||
if (base_layer.layer->bottom_z < EPSILON) {
|
if (base_layer.layer->bottom_z < EPSILON) {
|
||||||
// Base flange.
|
// Base flange (the 1st layer).
|
||||||
filler = filler_interface.get();
|
filler = filler_interface.get();
|
||||||
filler->angle = Geometry::deg2rad(m_object_config->support_material_angle + 90.);
|
filler->angle = Geometry::deg2rad(m_object_config->support_material_angle + 90.);
|
||||||
density = 0.5f;
|
density = 0.5f;
|
||||||
|
@ -178,8 +178,9 @@ private:
|
|||||||
MyLayersPtr generate_raft_base(
|
MyLayersPtr generate_raft_base(
|
||||||
const PrintObject &object,
|
const PrintObject &object,
|
||||||
const MyLayersPtr &top_contacts,
|
const MyLayersPtr &top_contacts,
|
||||||
MyLayersPtr &intermediate_layers,
|
const MyLayersPtr &interface_layers,
|
||||||
MyLayerStorage &layer_storage) const;
|
const MyLayersPtr &base_layers,
|
||||||
|
MyLayerStorage &layer_storage) const;
|
||||||
|
|
||||||
// Turn some of the base layers into interface layers.
|
// Turn some of the base layers into interface layers.
|
||||||
MyLayersPtr generate_interface_layers(
|
MyLayersPtr generate_interface_layers(
|
||||||
|
Loading…
Reference in New Issue
Block a user