mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-07-31 06:42:05 +08:00
SPE-2186: Add shrinkage compensation into filament settings.
There is a limitation that on multi-tool printers, all used filaments must have the same shrinkage compression values.
This commit is contained in:
parent
e14ba9d431
commit
4b8fe98443
@ -637,6 +637,21 @@ Transform3d Transformation::get_matrix_no_scaling_factor() const
|
||||
return copy.get_matrix();
|
||||
}
|
||||
|
||||
Transform3d Transformation::get_matrix_with_applied_shrinkage_compensation(const Vec3d &shrinkage_compensation) const {
|
||||
const Transform3d shrinkage_trafo = Geometry::scale_transform(shrinkage_compensation);
|
||||
const Vec3d trafo_offset = this->get_offset();
|
||||
const Vec3d trafo_offset_xy = Vec3d(trafo_offset.x(), trafo_offset.y(), 0.);
|
||||
|
||||
Transformation copy(*this);
|
||||
copy.set_offset(Axis::X, 0.);
|
||||
copy.set_offset(Axis::Y, 0.);
|
||||
|
||||
Transform3d trafo_after_shrinkage = (shrinkage_trafo * copy.get_matrix());
|
||||
trafo_after_shrinkage.translation() += trafo_offset_xy;
|
||||
|
||||
return trafo_after_shrinkage;
|
||||
}
|
||||
|
||||
Transformation Transformation::operator * (const Transformation& other) const
|
||||
{
|
||||
return Transformation(get_matrix() * other.get_matrix());
|
||||
|
@ -460,6 +460,8 @@ public:
|
||||
Transform3d get_matrix_no_offset() const;
|
||||
Transform3d get_matrix_no_scaling_factor() const;
|
||||
|
||||
Transform3d get_matrix_with_applied_shrinkage_compensation(const Vec3d &shrinkage_compensation) const;
|
||||
|
||||
void set_matrix(const Transform3d& transform) { m_matrix = transform; }
|
||||
|
||||
Transformation operator * (const Transformation& other) const;
|
||||
|
@ -1998,6 +1998,22 @@ void ModelVolume::convert_from_meters()
|
||||
this->source.is_converted_from_meters = true;
|
||||
}
|
||||
|
||||
std::vector<size_t> ModelVolume::get_extruders_from_multi_material_painting() const {
|
||||
if (!this->is_mm_painted())
|
||||
return {};
|
||||
|
||||
assert(static_cast<size_t>(TriangleStateType::Extruder1) - 1 == 0);
|
||||
const TriangleSelector::TriangleSplittingData &data = this->mm_segmentation_facets.get_data();
|
||||
|
||||
std::vector<size_t> extruders;
|
||||
for (size_t state_idx = static_cast<size_t>(TriangleStateType::Extruder1); state_idx < data.used_states.size(); ++state_idx) {
|
||||
if (data.used_states[state_idx])
|
||||
extruders.emplace_back(state_idx - 1);
|
||||
}
|
||||
|
||||
return extruders;
|
||||
}
|
||||
|
||||
void ModelInstance::transform_mesh(TriangleMesh* mesh, bool dont_translate) const
|
||||
{
|
||||
mesh->transform(dont_translate ? get_matrix_no_offset() : get_matrix());
|
||||
|
@ -910,6 +910,9 @@ public:
|
||||
bool is_seam_painted() const { return !this->seam_facets.empty(); }
|
||||
bool is_mm_painted() const { return !this->mm_segmentation_facets.empty(); }
|
||||
|
||||
// Returns 0-based indices of extruders painted by multi-material painting gizmo.
|
||||
std::vector<size_t> get_extruders_from_multi_material_painting() const;
|
||||
|
||||
protected:
|
||||
friend class Print;
|
||||
friend class SLAPrint;
|
||||
|
@ -490,7 +490,9 @@ static std::vector<std::string> s_Preset_filament_options {
|
||||
"filament_retract_layer_change", "filament_wipe", "filament_retract_before_wipe", "filament_retract_length_toolchange", "filament_retract_restart_extra_toolchange", "filament_travel_ramping_lift",
|
||||
"filament_travel_slope", "filament_travel_max_lift", "filament_travel_lift_before_obstacle",
|
||||
// Profile compatibility
|
||||
"filament_vendor", "compatible_prints", "compatible_prints_condition", "compatible_printers", "compatible_printers_condition", "inherits"
|
||||
"filament_vendor", "compatible_prints", "compatible_prints_condition", "compatible_printers", "compatible_printers_condition", "inherits",
|
||||
// Shrinkage compensation
|
||||
"filament_shrinkage_compensation_xy", "filament_shrinkage_compensation_z",
|
||||
};
|
||||
|
||||
static std::vector<std::string> s_Preset_machine_limits_options {
|
||||
|
@ -209,7 +209,9 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|
||||
// Spiral Vase forces different kind of slicing than the normal model:
|
||||
// In Spiral Vase mode, holes are closed and only the largest area contour is kept at each layer.
|
||||
// Therefore toggling the Spiral Vase on / off requires complete reslicing.
|
||||
|| opt_key == "spiral_vase") {
|
||||
|| opt_key == "spiral_vase"
|
||||
|| opt_key == "filament_shrinkage_compensation_xy"
|
||||
|| opt_key == "filament_shrinkage_compensation_z") {
|
||||
osteps.emplace_back(posSlice);
|
||||
} else if (
|
||||
opt_key == "complete_objects"
|
||||
@ -525,6 +527,9 @@ std::string Print::validate(std::vector<std::string>* warnings) const
|
||||
goto DONE;
|
||||
}
|
||||
DONE:;
|
||||
|
||||
if (!this->has_same_shrinkage_compensations())
|
||||
warnings->emplace_back("_FILAMENT_SHRINKAGE_DIFFER");
|
||||
}
|
||||
|
||||
if (m_objects.empty())
|
||||
@ -584,12 +589,19 @@ std::string Print::validate(std::vector<std::string>* warnings) const
|
||||
//FIXME It is quite expensive to generate object layers just to get the print height!
|
||||
if (auto layers = generate_object_layers(print_object.slicing_parameters(), layer_height_profile(print_object_idx));
|
||||
! layers.empty() && layers.back() > this->config().max_print_height + EPSILON) {
|
||||
return
|
||||
// Test whether the last slicing plane is below or above the print volume.
|
||||
0.5 * (layers[layers.size() - 2] + layers.back()) > this->config().max_print_height + EPSILON ?
|
||||
format(_u8L("The object %1% exceeds the maximum build volume height."), print_object.model_object()->name) :
|
||||
format(_u8L("While the object %1% itself fits the build volume, its last layer exceeds the maximum build volume height."), print_object.model_object()->name) +
|
||||
" " + _u8L("You might want to reduce the size of your model or change current print settings and retry.");
|
||||
|
||||
const double shrinkage_compensation_z = this->shrinkage_compensation().z();
|
||||
if (shrinkage_compensation_z != 1. && layers.back() > (this->config().max_print_height / shrinkage_compensation_z + EPSILON)) {
|
||||
// The object exceeds the maximum build volume height because of shrinkage compensation.
|
||||
return format(_u8L("While the object %1% itself fits the build volume, it exceeds the maximum build volume height because of material shrinkage compensation."), print_object.model_object()->name);
|
||||
} else if (0.5 * (layers[layers.size() - 2] + layers.back()) > this->config().max_print_height + EPSILON) {
|
||||
// The last slicing plane is below the print volume.
|
||||
return format(_u8L("The object %1% exceeds the maximum build volume height."), print_object.model_object()->name);
|
||||
} else {
|
||||
// The last slicing plane is above the print volume.
|
||||
return format(_u8L("While the object %1% itself fits the build volume, its last layer exceeds the maximum build volume height."), print_object.model_object()->name) +
|
||||
" " + _u8L("You might want to reduce the size of your model or change current print settings and retry.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1618,6 +1630,40 @@ std::string Print::output_filename(const std::string &filename_base) const
|
||||
return this->PrintBase::output_filename(output_filename_format, ".gcode", filename_base, &config);
|
||||
}
|
||||
|
||||
// Returns if all used filaments have same shrinkage compensations.
|
||||
bool Print::has_same_shrinkage_compensations() const {
|
||||
const std::vector<unsigned int> extruders = this->extruders();
|
||||
if (extruders.empty())
|
||||
return false;
|
||||
|
||||
const double filament_shrinkage_compensation_xy = m_config.filament_shrinkage_compensation_xy.get_at(extruders.front());
|
||||
const double filament_shrinkage_compensation_z = m_config.filament_shrinkage_compensation_z.get_at(extruders.front());
|
||||
|
||||
for (unsigned int extruder : extruders) {
|
||||
if (filament_shrinkage_compensation_xy != m_config.filament_shrinkage_compensation_xy.get_at(extruder) ||
|
||||
filament_shrinkage_compensation_z != m_config.filament_shrinkage_compensation_z.get_at(extruder)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Returns scaling for each axis representing shrinkage compensations in each axis.
|
||||
Vec3d Print::shrinkage_compensation() const
|
||||
{
|
||||
if (!this->has_same_shrinkage_compensations())
|
||||
return Vec3d::Ones();
|
||||
|
||||
const unsigned int first_extruder = this->extruders().front();
|
||||
const double xy_compensation_percent = std::clamp(m_config.filament_shrinkage_compensation_xy.get_at(first_extruder), -99., 99.);
|
||||
const double z_compensation_percent = std::clamp(m_config.filament_shrinkage_compensation_z.get_at(first_extruder), -99., 99.);
|
||||
const double xy_compensation = 100. / (100. - xy_compensation_percent);
|
||||
const double z_compensation = 100. / (100. - z_compensation_percent);
|
||||
|
||||
return { xy_compensation, xy_compensation, z_compensation };
|
||||
}
|
||||
|
||||
const std::string PrintStatistics::FilamentUsedG = "filament used [g]";
|
||||
const std::string PrintStatistics::FilamentUsedGMask = "; filament used [g] =";
|
||||
|
||||
|
@ -327,7 +327,7 @@ public:
|
||||
// The slicing parameters are dependent on various configuration values
|
||||
// (layer height, first layer height, raft settings, print nozzle diameter etc).
|
||||
const SlicingParameters& slicing_parameters() const { return m_slicing_params; }
|
||||
static SlicingParameters slicing_parameters(const DynamicPrintConfig &full_config, const ModelObject &model_object, float object_max_z);
|
||||
static SlicingParameters slicing_parameters(const DynamicPrintConfig &full_config, const ModelObject &model_object, float object_max_z, const Vec3d &object_shrinkage_compensation);
|
||||
|
||||
size_t num_printing_regions() const throw() { return m_shared_regions->all_regions.size(); }
|
||||
const PrintRegion& printing_region(size_t idx) const throw() { return *m_shared_regions->all_regions[idx].get(); }
|
||||
@ -665,6 +665,12 @@ public:
|
||||
const Polygons& get_sequential_print_clearance_contours() const { return m_sequential_print_clearance_contours; }
|
||||
static bool sequential_print_horizontal_clearance_valid(const Print& print, Polygons* polygons = nullptr);
|
||||
|
||||
// Returns if all used filaments have same shrinkage compensations.
|
||||
bool has_same_shrinkage_compensations() const;
|
||||
|
||||
// Returns scaling for each axis representing shrinkage compensations in each axis.
|
||||
Vec3d shrinkage_compensation() const;
|
||||
|
||||
protected:
|
||||
// Invalidates the step, and its depending steps in Print.
|
||||
bool invalidate_step(PrintStep step);
|
||||
|
@ -134,13 +134,14 @@ struct PrintObjectTrafoAndInstances
|
||||
};
|
||||
|
||||
// Generate a list of trafos and XY offsets for instances of a ModelObject
|
||||
static std::vector<PrintObjectTrafoAndInstances> print_objects_from_model_object(const ModelObject &model_object)
|
||||
static std::vector<PrintObjectTrafoAndInstances> print_objects_from_model_object(const ModelObject &model_object, const Vec3d &shrinkage_compensation)
|
||||
{
|
||||
std::set<PrintObjectTrafoAndInstances> trafos;
|
||||
PrintObjectTrafoAndInstances trafo;
|
||||
for (ModelInstance *model_instance : model_object.instances)
|
||||
if (model_instance->is_printable()) {
|
||||
trafo.trafo = model_instance->get_matrix();
|
||||
Geometry::Transformation model_instance_transformation = model_instance->get_transformation();
|
||||
trafo.trafo = model_instance_transformation.get_matrix_with_applied_shrinkage_compensation(shrinkage_compensation);
|
||||
auto shift = Point::new_scale(trafo.trafo.data()[12], trafo.trafo.data()[13]);
|
||||
// Reset the XY axes of the transformation.
|
||||
trafo.trafo.data()[12] = 0;
|
||||
@ -1281,7 +1282,7 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
||||
// Walk over all new model objects and check, whether there are matching PrintObjects.
|
||||
for (ModelObject *model_object : m_model.objects) {
|
||||
ModelObjectStatus &model_object_status = const_cast<ModelObjectStatus&>(model_object_status_db.reuse(*model_object));
|
||||
model_object_status.print_instances = print_objects_from_model_object(*model_object);
|
||||
model_object_status.print_instances = print_objects_from_model_object(*model_object, this->shrinkage_compensation());
|
||||
std::vector<const PrintObjectStatus*> old;
|
||||
old.reserve(print_object_status_db.count(*model_object));
|
||||
for (const PrintObjectStatus &print_object_status : print_object_status_db.get_range(*model_object))
|
||||
|
@ -1332,6 +1332,28 @@ void PrintConfigDef::init_fff_params()
|
||||
def->set_default_value(new ConfigOptionString(L("(Unknown)")));
|
||||
def->cli = ConfigOptionDef::nocli;
|
||||
|
||||
def = this->add("filament_shrinkage_compensation_xy", coPercents);
|
||||
def->label = L("Shrinkage XY");
|
||||
def->tooltip = L("Enter your filament shrinkage percentages for the X and Y axes here to apply scaling of the object to "
|
||||
"compensate for shrinkage in the X and Y axes. For example, if you measured 99mm instead of 100mm, "
|
||||
"then you should put here 1%.");
|
||||
def->sidetext = L("%");
|
||||
def->mode = comAdvanced;
|
||||
def->min = -10.;
|
||||
def->max = 10.;
|
||||
def->set_default_value(new ConfigOptionPercents { 0 });
|
||||
|
||||
def = this->add("filament_shrinkage_compensation_z", coPercents);
|
||||
def->label = L("Shrinkage Z");
|
||||
def->tooltip = L("Enter your filament shrinkage percentages for the Z axis here to apply scaling of the object to "
|
||||
"compensate for shrinkage in the Z axis. For example, if you measured 99mm instead of 100mm, "
|
||||
"then you should put here 1%.");
|
||||
def->sidetext = L("%");
|
||||
def->mode = comAdvanced;
|
||||
def->min = -10.;
|
||||
def->max = 10.;
|
||||
def->set_default_value(new ConfigOptionPercents { 0. });
|
||||
|
||||
def = this->add("fill_angle", coFloat);
|
||||
def->label = L("Fill angle");
|
||||
def->category = L("Infill");
|
||||
|
@ -745,6 +745,8 @@ PRINT_CONFIG_CLASS_DEFINE(
|
||||
((ConfigOptionFloats, filament_multitool_ramming_flow))
|
||||
((ConfigOptionFloats, filament_stamping_loading_speed))
|
||||
((ConfigOptionFloats, filament_stamping_distance))
|
||||
((ConfigOptionPercents, filament_shrinkage_compensation_xy))
|
||||
((ConfigOptionPercents, filament_shrinkage_compensation_z))
|
||||
((ConfigOptionBool, gcode_comments))
|
||||
((ConfigOptionEnum<GCodeFlavor>, gcode_flavor))
|
||||
((ConfigOptionEnum<LabelObjectsStyle>, gcode_label_objects))
|
||||
|
@ -2620,15 +2620,14 @@ PrintRegionConfig region_config_from_model_volume(const PrintRegionConfig &defau
|
||||
return config;
|
||||
}
|
||||
|
||||
void PrintObject::update_slicing_parameters()
|
||||
{
|
||||
if (!m_slicing_params.valid)
|
||||
m_slicing_params = SlicingParameters::create_from_config(
|
||||
this->print()->config(), m_config, this->model_object()->max_z(), this->object_extruders());
|
||||
void PrintObject::update_slicing_parameters() {
|
||||
if (!m_slicing_params.valid) {
|
||||
m_slicing_params = SlicingParameters::create_from_config(this->print()->config(), m_config, this->model_object()->max_z(),
|
||||
this->object_extruders(), this->print()->shrinkage_compensation());
|
||||
}
|
||||
}
|
||||
|
||||
SlicingParameters PrintObject::slicing_parameters(const DynamicPrintConfig& full_config, const ModelObject& model_object, float object_max_z)
|
||||
{
|
||||
SlicingParameters PrintObject::slicing_parameters(const DynamicPrintConfig &full_config, const ModelObject &model_object, float object_max_z, const Vec3d &object_shrinkage_compensation) {
|
||||
PrintConfig print_config;
|
||||
PrintObjectConfig object_config;
|
||||
PrintRegionConfig default_region_config;
|
||||
@ -2661,7 +2660,8 @@ SlicingParameters PrintObject::slicing_parameters(const DynamicPrintConfig& full
|
||||
|
||||
if (object_max_z <= 0.f)
|
||||
object_max_z = (float)model_object.raw_bounding_box().size().z();
|
||||
return SlicingParameters::create_from_config(print_config, object_config, object_max_z, object_extruders);
|
||||
|
||||
return SlicingParameters::create_from_config(print_config, object_config, object_max_z, object_extruders, object_shrinkage_compensation);
|
||||
}
|
||||
|
||||
// returns 0-based indices of extruders used to print the object (without brim, support and other helper extrusions)
|
||||
@ -2682,7 +2682,6 @@ bool PrintObject::update_layer_height_profile(const ModelObject &model_object, c
|
||||
if (layer_height_profile.empty()) {
|
||||
// use the constructor because the assignement is crashing on ASAN OsX
|
||||
layer_height_profile = model_object.layer_height_profile.get();
|
||||
// layer_height_profile = model_object.layer_height_profile;
|
||||
// The layer height returned is sampled with high density for the UI layer height painting
|
||||
// and smoothing tool to work.
|
||||
updated = true;
|
||||
@ -2693,8 +2692,9 @@ bool PrintObject::update_layer_height_profile(const ModelObject &model_object, c
|
||||
// Must not be of even length.
|
||||
((layer_height_profile.size() & 1) != 0 ||
|
||||
// Last entry must be at the top of the object.
|
||||
std::abs(layer_height_profile[layer_height_profile.size() - 2] - slicing_parameters.object_print_z_max + slicing_parameters.object_print_z_min) > 1e-3))
|
||||
std::abs(layer_height_profile[layer_height_profile.size() - 2] - slicing_parameters.object_print_z_uncompensated_max + slicing_parameters.object_print_z_min) > 1e-3)) {
|
||||
layer_height_profile.clear();
|
||||
}
|
||||
|
||||
if (layer_height_profile.empty()) {
|
||||
//layer_height_profile = layer_height_profile_adaptive(slicing_parameters, model_object.layer_config_ranges, model_object.volumes);
|
||||
|
@ -63,10 +63,11 @@ coordf_t Slicing::max_layer_height_from_nozzle(const DynamicPrintConfig &print_c
|
||||
}
|
||||
|
||||
SlicingParameters SlicingParameters::create_from_config(
|
||||
const PrintConfig &print_config,
|
||||
const PrintObjectConfig &object_config,
|
||||
coordf_t object_height,
|
||||
const std::vector<unsigned int> &object_extruders)
|
||||
const PrintConfig &print_config,
|
||||
const PrintObjectConfig &object_config,
|
||||
coordf_t object_height,
|
||||
const std::vector<unsigned int> &object_extruders,
|
||||
const Vec3d &object_shrinkage_compensation)
|
||||
{
|
||||
assert(! print_config.first_layer_height.percent);
|
||||
coordf_t first_layer_height = (print_config.first_layer_height.value <= 0) ?
|
||||
@ -85,7 +86,9 @@ SlicingParameters SlicingParameters::create_from_config(
|
||||
params.first_print_layer_height = first_layer_height;
|
||||
params.first_object_layer_height = first_layer_height;
|
||||
params.object_print_z_min = 0.;
|
||||
params.object_print_z_max = object_height;
|
||||
params.object_print_z_max = object_height * object_shrinkage_compensation.z();
|
||||
params.object_print_z_uncompensated_max = object_height;
|
||||
params.object_shrinkage_compensation_z = object_shrinkage_compensation.z();
|
||||
params.base_raft_layers = object_config.raft_layers.value;
|
||||
params.soluble_interface = soluble_interface;
|
||||
|
||||
@ -152,6 +155,7 @@ SlicingParameters SlicingParameters::create_from_config(
|
||||
coordf_t print_z = params.raft_contact_top_z + params.gap_raft_object;
|
||||
params.object_print_z_min = print_z;
|
||||
params.object_print_z_max += print_z;
|
||||
params.object_print_z_uncompensated_max += print_z;
|
||||
}
|
||||
|
||||
params.valid = true;
|
||||
@ -224,10 +228,10 @@ std::vector<coordf_t> layer_height_profile_from_ranges(
|
||||
lh_append(hi, height);
|
||||
}
|
||||
|
||||
if (coordf_t z = last_z(); z < slicing_params.object_print_z_height()) {
|
||||
if (coordf_t z = last_z(); z < slicing_params.object_print_z_uncompensated_height()) {
|
||||
// Insert a step of normal layer height up to the object top.
|
||||
lh_append(z, slicing_params.layer_height);
|
||||
lh_append(slicing_params.object_print_z_height(), slicing_params.layer_height);
|
||||
lh_append(slicing_params.object_print_z_uncompensated_height(), slicing_params.layer_height);
|
||||
}
|
||||
|
||||
return layer_height_profile;
|
||||
@ -418,12 +422,12 @@ void adjust_layer_height_profile(
|
||||
std::pair<coordf_t, coordf_t> z_span_variable =
|
||||
std::pair<coordf_t, coordf_t>(
|
||||
slicing_params.first_object_layer_height_fixed() ? slicing_params.first_object_layer_height : 0.,
|
||||
slicing_params.object_print_z_height());
|
||||
slicing_params.object_print_z_uncompensated_height());
|
||||
if (z < z_span_variable.first || z > z_span_variable.second)
|
||||
return;
|
||||
|
||||
assert(layer_height_profile.size() >= 2);
|
||||
assert(std::abs(layer_height_profile[layer_height_profile.size() - 2] - slicing_params.object_print_z_height()) < EPSILON);
|
||||
assert(std::abs(layer_height_profile[layer_height_profile.size() - 2] - slicing_params.object_print_z_uncompensated_height()) < EPSILON);
|
||||
|
||||
// 1) Get the current layer thickness at z.
|
||||
coordf_t current_layer_height = slicing_params.layer_height;
|
||||
@ -584,7 +588,7 @@ void adjust_layer_height_profile(
|
||||
assert(layer_height_profile.size() > 2);
|
||||
assert(layer_height_profile.size() % 2 == 0);
|
||||
assert(layer_height_profile[0] == 0.);
|
||||
assert(std::abs(layer_height_profile[layer_height_profile.size() - 2] - slicing_params.object_print_z_height()) < EPSILON);
|
||||
assert(std::abs(layer_height_profile[layer_height_profile.size() - 2] - slicing_params.object_print_z_uncompensated_height()) < EPSILON);
|
||||
#ifdef _DEBUG
|
||||
for (size_t i = 2; i < layer_height_profile.size(); i += 2)
|
||||
assert(layer_height_profile[i - 2] <= layer_height_profile[i]);
|
||||
@ -613,6 +617,7 @@ std::vector<coordf_t> generate_object_layers(
|
||||
out.push_back(print_z);
|
||||
}
|
||||
|
||||
const coordf_t shrinkage_compensation_z = slicing_params.object_shrinkage_compensation_z;
|
||||
size_t idx_layer_height_profile = 0;
|
||||
// loop until we have at least one layer and the max slice_z reaches the object height
|
||||
coordf_t slice_z = print_z + 0.5 * slicing_params.min_layer_height;
|
||||
@ -621,17 +626,18 @@ std::vector<coordf_t> generate_object_layers(
|
||||
if (idx_layer_height_profile < layer_height_profile.size()) {
|
||||
size_t next = idx_layer_height_profile + 2;
|
||||
for (;;) {
|
||||
if (next >= layer_height_profile.size() || slice_z < layer_height_profile[next])
|
||||
if (next >= layer_height_profile.size() || slice_z < layer_height_profile[next] * shrinkage_compensation_z)
|
||||
break;
|
||||
idx_layer_height_profile = next;
|
||||
next += 2;
|
||||
}
|
||||
coordf_t z1 = layer_height_profile[idx_layer_height_profile];
|
||||
coordf_t h1 = layer_height_profile[idx_layer_height_profile + 1];
|
||||
|
||||
const coordf_t z1 = layer_height_profile[idx_layer_height_profile] * shrinkage_compensation_z;
|
||||
const coordf_t h1 = layer_height_profile[idx_layer_height_profile + 1];
|
||||
height = h1;
|
||||
if (next < layer_height_profile.size()) {
|
||||
coordf_t z2 = layer_height_profile[next];
|
||||
coordf_t h2 = layer_height_profile[next + 1];
|
||||
const coordf_t z2 = layer_height_profile[next] * shrinkage_compensation_z;
|
||||
const coordf_t h2 = layer_height_profile[next + 1];
|
||||
height = lerp(h1, h2, (slice_z - z1) / (z2 - z1));
|
||||
assert(height >= slicing_params.min_layer_height - EPSILON && height <= slicing_params.max_layer_height + EPSILON);
|
||||
}
|
||||
|
@ -33,10 +33,11 @@ struct SlicingParameters
|
||||
SlicingParameters() = default;
|
||||
|
||||
static SlicingParameters create_from_config(
|
||||
const PrintConfig &print_config,
|
||||
const PrintObjectConfig &object_config,
|
||||
coordf_t object_height,
|
||||
const std::vector<unsigned int> &object_extruders);
|
||||
const PrintConfig &print_config,
|
||||
const PrintObjectConfig &object_config,
|
||||
coordf_t object_height,
|
||||
const std::vector<unsigned int> &object_extruders,
|
||||
const Vec3d &object_shrinkage_compensation);
|
||||
|
||||
// Has any raft layers?
|
||||
bool has_raft() const { return raft_layers() > 0; }
|
||||
@ -46,8 +47,13 @@ struct SlicingParameters
|
||||
bool first_object_layer_height_fixed() const { return ! has_raft() || first_object_layer_bridging; }
|
||||
|
||||
// Height of the object to be printed. This value does not contain the raft height.
|
||||
// This value is scaled by shrinkage compensation in the Z-axis.
|
||||
coordf_t object_print_z_height() const { return object_print_z_max - object_print_z_min; }
|
||||
|
||||
// Height of the object to be printed. This value does not contain the raft height.
|
||||
// This value isn't scaled by shrinkage compensation in the Z-axis.
|
||||
coordf_t object_print_z_uncompensated_height() const { return object_print_z_uncompensated_max - object_print_z_min; }
|
||||
|
||||
bool valid { false };
|
||||
|
||||
// Number of raft layers.
|
||||
@ -99,7 +105,13 @@ struct SlicingParameters
|
||||
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 { 0 };
|
||||
// This value of maximum print Z is scaled by shrinkage compensation in the Z-axis.
|
||||
coordf_t object_print_z_max { 0 };
|
||||
|
||||
// This value of maximum print Z isn't scaled by shrinkage compensation.
|
||||
coordf_t object_print_z_uncompensated_max { 0 };
|
||||
// Scaling factor for compensating shrinkage in Z-axis.
|
||||
coordf_t object_shrinkage_compensation_z { 0 };
|
||||
};
|
||||
static_assert(IsTriviallyCopyable<SlicingParameters>::value, "SlicingParameters class is not POD (and it should be - see constructor).");
|
||||
|
||||
|
@ -628,11 +628,10 @@ void GLCanvas3D::LayersEditing::accept_changes(GLCanvas3D& canvas)
|
||||
m_layer_height_profile_modified = false;
|
||||
}
|
||||
|
||||
void GLCanvas3D::LayersEditing::update_slicing_parameters()
|
||||
{
|
||||
if (m_slicing_parameters == nullptr) {
|
||||
m_slicing_parameters = new SlicingParameters();
|
||||
*m_slicing_parameters = PrintObject::slicing_parameters(*m_config, *m_model_object, m_object_max_z);
|
||||
void GLCanvas3D::LayersEditing::update_slicing_parameters() {
|
||||
if (m_slicing_parameters == nullptr) {
|
||||
m_slicing_parameters = new SlicingParameters();
|
||||
*m_slicing_parameters = PrintObject::slicing_parameters(*m_config, *m_model_object, m_object_max_z, m_shrinkage_compensation);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1605,9 +1604,11 @@ void GLCanvas3D::set_config(const DynamicPrintConfig* config)
|
||||
m_config = config;
|
||||
m_layers_editing.set_config(config);
|
||||
|
||||
if (config) {
|
||||
PrinterTechnology ptech = current_printer_technology();
|
||||
const PrinterTechnology ptech = current_printer_technology();
|
||||
if (const Print *print = fff_print(); ptech == ptFFF && print != nullptr)
|
||||
m_layers_editing.set_shrinkage_compensation(fff_print()->shrinkage_compensation());
|
||||
|
||||
if (config) {
|
||||
auto slot = ArrangeSettingsDb_AppCfg::slotFFF;
|
||||
|
||||
if (ptech == ptSLA) {
|
||||
@ -3200,9 +3201,9 @@ void GLCanvas3D::on_mouse_wheel(wxMouseEvent& evt)
|
||||
}
|
||||
}
|
||||
|
||||
// If Undo/Redo list is opened,
|
||||
// If Undo/Redo list is opened,
|
||||
// update them according to the event
|
||||
if (m_undoredo_toolbar.is_item_pressed("undo") ||
|
||||
if (m_undoredo_toolbar.is_item_pressed("undo") ||
|
||||
m_undoredo_toolbar.is_item_pressed("redo")) {
|
||||
m_mouse_wheel = int((double)evt.GetWheelRotation() / (double)evt.GetWheelDelta());
|
||||
return;
|
||||
|
@ -219,6 +219,8 @@ class GLCanvas3D
|
||||
SlicingParameters *m_slicing_parameters{ nullptr };
|
||||
std::vector<double> m_layer_height_profile;
|
||||
bool m_layer_height_profile_modified{ false };
|
||||
// Shrinkage compensation to apply when we need to use object_max_z with Z compensation.
|
||||
Vec3d m_shrinkage_compensation{ Vec3d::Ones() };
|
||||
|
||||
mutable float m_adaptive_quality{ 0.5f };
|
||||
mutable HeightProfileSmoothingParams m_smooth_params;
|
||||
@ -299,6 +301,8 @@ class GLCanvas3D
|
||||
|
||||
std::pair<SlicingParameters, const std::vector<double>> get_layers_height_data();
|
||||
|
||||
void set_shrinkage_compensation(const Vec3d &shrinkage_compensation) { m_shrinkage_compensation = shrinkage_compensation; };
|
||||
|
||||
private:
|
||||
bool is_initialized() const;
|
||||
void generate_layer_height_texture();
|
||||
|
@ -1938,6 +1938,10 @@ void Plater::priv::process_validation_warning(const std::vector<std::string>& wa
|
||||
if (text == "_BED_TEMPS_DIFFER")
|
||||
text = _u8L("Bed temperatures for the used filaments differ significantly.");
|
||||
|
||||
if (text == "_FILAMENT_SHRINKAGE_DIFFER")
|
||||
text = _u8L("Filament shrinkage will not be used because filament shrinkage "
|
||||
"for the used filaments differs significantly.");
|
||||
|
||||
notification_manager->push_notification(
|
||||
NotificationType::ValidateWarning,
|
||||
NotificationManager::NotificationLevel::WarningNotificationLevel,
|
||||
|
@ -2237,6 +2237,10 @@ void TabFilament::build()
|
||||
};
|
||||
optgroup->append_line(line);
|
||||
|
||||
optgroup = page->new_optgroup(L("Shrinkage compensation"));
|
||||
optgroup->append_single_option_line("filament_shrinkage_compensation_xy");
|
||||
optgroup->append_single_option_line("filament_shrinkage_compensation_z");
|
||||
|
||||
optgroup = page->new_optgroup(L("Wipe tower parameters"));
|
||||
optgroup->append_single_option_line("filament_minimal_purge_on_wipe_tower");
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user