Trimming support base layer with brim.

Fixes Brim destroyed by support aka. Enable supports on top of brim #1156
Fixes Brim Priority/Support on Brim #713
Fixes Phantom Support columns interfere with brim #3396
Fixes false generation of brim when supports are used #3395

This is a work in progress, as the brim generator currently produces
different brim areas from what the support generator expects.
This commit is contained in:
Vojtech Bubnik 2021-02-23 14:43:47 +01:00
parent 8ba230db9f
commit 055d2321e7
5 changed files with 60 additions and 19 deletions

View File

@ -171,12 +171,6 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|| opt_key == "wipe_tower_y"
|| opt_key == "wipe_tower_rotation_angle") {
steps.emplace_back(psSkirt);
} else if (
opt_key == "brim_width"
|| opt_key == "brim_offset"
|| opt_key == "brim_type") {
steps.emplace_back(psBrim);
steps.emplace_back(psSkirt);
} else if (
opt_key == "nozzle_diameter"
|| opt_key == "resolution"
@ -1191,8 +1185,7 @@ bool Print::has_skirt() const
bool Print::has_brim() const
{
return std::any_of(m_objects.begin(), m_objects.end(),
[](PrintObject *object) { return object->config().brim_type != btNoBrim && object->config().brim_width.value > 0.; });
return std::any_of(m_objects.begin(), m_objects.end(), [](PrintObject *object) { return object->has_brim(); });
}
static inline bool sequential_print_horizontal_clearance_valid(const Print &print)

View File

@ -168,12 +168,15 @@ public:
// Bounding box is used to align the object infill patterns, and to calculate attractor for the rear seam.
// The bounding box may not be quite snug.
BoundingBox bounding_box() const { return BoundingBox(Point(- m_size.x() / 2, - m_size.y() / 2), Point(m_size.x() / 2, m_size.y() / 2)); }
BoundingBox bounding_box() const { return BoundingBox(Point(- m_size.x() / 2, - m_size.y() / 2), Point(m_size.x() / 2, m_size.y() / 2)); }
// Height is used for slicing, for sorting the objects by height for sequential printing and for checking vertical clearence in sequential print mode.
// The height is snug.
coord_t height() const { return m_size.z(); }
coord_t height() const { return m_size.z(); }
// Centering offset of the sliced mesh from the scaled and rotated mesh of the model.
const Point& center_offset() const { return m_center_offset; }
const Point& center_offset() const { return m_center_offset; }
bool has_brim() const { return this->config().brim_type != btNoBrim && this->config().brim_width.value > 0.; }
// adds region_id, too, if necessary
void add_region_volume(unsigned int region_id, int volume_id, const t_layer_height_range &layer_range) {
@ -199,14 +202,14 @@ public:
const Layer* get_first_layer_bellow_printz(coordf_t print_z, coordf_t epsilon) const;
// print_z: top of the layer; slice_z: center of the layer.
Layer* add_layer(int id, coordf_t height, coordf_t print_z, coordf_t slice_z);
Layer* add_layer(int id, coordf_t height, coordf_t print_z, coordf_t slice_z);
size_t support_layer_count() const { return m_support_layers.size(); }
void clear_support_layers();
SupportLayer* get_support_layer(int idx) { return m_support_layers[idx]; }
SupportLayer* add_support_layer(int id, coordf_t height, coordf_t print_z);
size_t support_layer_count() const { return m_support_layers.size(); }
void clear_support_layers();
SupportLayer* get_support_layer(int idx) { return m_support_layers[idx]; }
SupportLayer* add_support_layer(int id, coordf_t height, coordf_t print_z);
SupportLayerPtrs::iterator insert_support_layer(SupportLayerPtrs::iterator pos, size_t id, coordf_t height, coordf_t print_z, coordf_t slice_z);
void delete_support_layer(int idx);
void delete_support_layer(int idx);
// Initialize the layer_height_profile from the model_object's layer_height_profile, from model_object's layer height table, or from slicing parameters.
// Returns true, if the layer_height_profile was changed.

View File

@ -518,7 +518,13 @@ bool PrintObject::invalidate_state_by_config_options(
std::vector<PrintObjectStep> steps;
bool invalidated = false;
for (const t_config_option_key &opt_key : opt_keys) {
if ( opt_key == "perimeters"
if ( opt_key == "brim_width"
|| opt_key == "brim_offset"
|| opt_key == "brim_type") {
// Brim is printed below supports, support invalidates brim and skirt.
steps.emplace_back(posSupportMaterial);
} else if (
opt_key == "perimeters"
|| opt_key == "extra_perimeters"
|| opt_key == "gap_fill_enabled"
|| opt_key == "gap_fill_speed"

View File

@ -5,6 +5,7 @@
#include "SupportMaterial.hpp"
#include "Fill/FillBase.hpp"
#include "Geometry.hpp"
#include "Point.hpp"
#include <cmath>
#include <memory>
@ -496,7 +497,7 @@ void PrintObjectSupportMaterial::generate(PrintObject &object)
// 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(top_contacts, interface_layers, intermediate_layers, layer_storage);
MyLayersPtr raft_layers = this->generate_raft_base(object, top_contacts, interface_layers, intermediate_layers, layer_storage);
#ifdef SLIC3R_DEBUG
for (const MyLayer *l : interface_layers)
@ -2498,11 +2499,41 @@ void PrintObjectSupportMaterial::trim_support_layers_by_object(
}
PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::generate_raft_base(
const PrintObject &object,
const MyLayersPtr &top_contacts,
const MyLayersPtr &interface_layers,
const MyLayersPtr &base_layers,
MyLayerStorage &layer_storage) const
{
// If there is brim to be generated, calculate the trimming regions.
Polygons brim;
if (object.has_brim()) {
// Calculate the area covered by the brim.
const BrimType brim_type = object.config().brim_type;
const bool brim_outer = brim_type == btOuterOnly || brim_type == btOuterAndInner;
const bool brim_inner = brim_type == btInnerOnly || brim_type == btOuterAndInner;
const auto brim_offset = scaled<float>(object.config().brim_offset.value + object.config().brim_width.value);
for (const ExPolygon &ex : object.layers().front()->lslices) {
if (brim_outer && brim_inner)
polygons_append(brim, offset(ex, brim_offset));
else {
if (brim_outer)
polygons_append(brim, offset(ex.contour, brim_offset, ClipperLib::jtRound, float(scale_(0.1))));
else
brim.emplace_back(ex.contour);
if (brim_inner) {
Polygons holes = ex.holes;
polygons_reverse(holes);
holes = offset(holes, - brim_offset, ClipperLib::jtRound, float(scale_(0.1)));
polygons_reverse(holes);
polygons_append(brim, std::move(holes));
} else
polygons_append(brim, ex.holes);
}
}
brim = union_(brim);
}
// 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_fine = float(scale_((m_slicing_params.raft_layers() > 1) ? 0.5 : EPSILON));
const float inflate_factor_1st_layer = float(scale_(3.)) - inflate_factor_fine;
@ -2581,6 +2612,13 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::generate_raf
offset(m_object->layers().front()->lslices, (float)scale_(m_gap_xy), SUPPORT_SURFACES_OFFSET_PARAMETERS));
if (contacts != nullptr)
columns_base->polygons = diff(columns_base->polygons, interface_polygons);
if (! brim.empty()) {
columns_base->polygons = diff(columns_base->polygons, brim);
if (contacts)
contacts->polygons = diff(contacts->polygons, brim);
if (interfaces)
interfaces->polygons = diff(interfaces->polygons, brim);
}
}
return raft_layers;

View File

@ -196,6 +196,7 @@ private:
// Generate raft layers, also expand the 1st support layer
// in case there is no raft layer to improve support adhesion.
MyLayersPtr generate_raft_base(
const PrintObject &object,
const MyLayersPtr &top_contacts,
const MyLayersPtr &interface_layers,
const MyLayersPtr &base_layers,