Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/supermerill/SuperSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/libslic3r/Print.cpp')
-rw-r--r--src/libslic3r/Print.cpp167
1 files changed, 74 insertions, 93 deletions
diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp
index f89c316da..9a210abaa 100644
--- a/src/libslic3r/Print.cpp
+++ b/src/libslic3r/Print.cpp
@@ -13,6 +13,7 @@
#include "PrintExport.hpp"
#include <algorithm>
+#include <limits>
#include <unordered_set>
#include <boost/filesystem/path.hpp>
#include <boost/log/trivial.hpp>
@@ -292,18 +293,8 @@ std::vector<unsigned int> Print::object_extruders() const
{
std::vector<unsigned int> extruders;
extruders.reserve(m_regions.size() * 3);
-
- for (const PrintRegion *region : m_regions) {
- // these checks reflect the same logic used in the GUI for enabling/disabling
- // extruder selection fields
- if (region->config().perimeters.value > 0 || m_config.brim_width.value > 0)
- extruders.emplace_back(region->config().perimeter_extruder - 1);
- if (region->config().fill_density.value > 0)
- extruders.emplace_back(region->config().infill_extruder - 1);
- if (region->config().top_solid_layers.value > 0 || region->config().bottom_solid_layers.value > 0)
- extruders.emplace_back(region->config().solid_infill_extruder - 1);
- }
-
+ for (const PrintRegion *region : m_regions)
+ region->collect_object_printing_extruders(extruders);
sort_remove_duplicates(extruders);
return extruders;
}
@@ -371,37 +362,6 @@ double Print::max_allowed_layer_height() const
return nozzle_diameter_max;
}
-static void clamp_exturder_to_default(ConfigOptionInt &opt, size_t num_extruders)
-{
- if (opt.value > (int)num_extruders)
- // assign the default extruder
- opt.value = 1;
-}
-
-static PrintObjectConfig object_config_from_model(const PrintObjectConfig &default_object_config, const ModelObject &object, size_t num_extruders)
-{
- PrintObjectConfig config = default_object_config;
- normalize_and_apply_config(config, object.config);
- // Clamp invalid extruders to the default extruder (with index 1).
- clamp_exturder_to_default(config.support_material_extruder, num_extruders);
- clamp_exturder_to_default(config.support_material_interface_extruder, num_extruders);
- return config;
-}
-
-static PrintRegionConfig region_config_from_model_volume(const PrintRegionConfig &default_region_config, const ModelVolume &volume, size_t num_extruders)
-{
- PrintRegionConfig config = default_region_config;
- normalize_and_apply_config(config, volume.get_object()->config);
- normalize_and_apply_config(config, volume.config);
- if (! volume.material_id().empty())
- normalize_and_apply_config(config, volume.material()->config);
- // Clamp invalid extruders to the default extruder (with index 1).
- clamp_exturder_to_default(config.infill_extruder, num_extruders);
- clamp_exturder_to_default(config.perimeter_extruder, num_extruders);
- clamp_exturder_to_default(config.solid_infill_extruder, num_extruders);
- return config;
-}
-
// Caller is responsible for supplying models whose objects don't collide
// and have explicit instance positions.
void Print::add_model_object(ModelObject* model_object, int idx)
@@ -438,7 +398,7 @@ void Print::add_model_object(ModelObject* model_object, int idx)
if (! volume->is_model_part() && ! volume->is_modifier())
continue;
// Get the config applied to this volume.
- PrintRegionConfig config = region_config_from_model_volume(m_default_region_config, *volume, 99999);
+ PrintRegionConfig config = PrintObject::region_config_from_model_volume(m_default_region_config, *volume, 99999);
// Find an existing print region with the same config.
size_t region_id = size_t(-1);
for (size_t i = 0; i < m_regions.size(); ++ i)
@@ -519,12 +479,12 @@ bool Print::apply_config(DynamicPrintConfig config)
// If the new config for this volume differs from the other
// volume configs currently associated to this region, it means
// the region subdivision does not make sense anymore.
- if (! this_region_config.equals(region_config_from_model_volume(m_default_region_config, volume, 99999))) {
+ if (! this_region_config.equals(PrintObject::region_config_from_model_volume(m_default_region_config, volume, 99999))) {
rearrange_regions = true;
goto exit_for_rearrange_regions;
}
} else {
- this_region_config = region_config_from_model_volume(m_default_region_config, volume, 99999);
+ this_region_config = PrintObject::region_config_from_model_volume(m_default_region_config, volume, 99999);
this_region_config_set = true;
}
for (const PrintRegionConfig &cfg : other_region_configs) {
@@ -568,10 +528,6 @@ exit_for_rearrange_regions:
invalidated = true;
}
- // Always make sure that the layer_height_profiles are set, as they should not be modified from the worker threads.
- for (PrintObject *object : m_objects)
- object->update_layer_height_profile();
-
return invalidated;
}
@@ -893,8 +849,7 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co
if (model_parts_differ || modifiers_differ ||
model_object.origin_translation != model_object_new.origin_translation ||
model_object.layer_height_ranges != model_object_new.layer_height_ranges ||
- model_object.layer_height_profile != model_object_new.layer_height_profile ||
- model_object.layer_height_profile_valid != model_object_new.layer_height_profile_valid) {
+ model_object.layer_height_profile != model_object_new.layer_height_profile) {
// The very first step (the slicing step) is invalidated. One may freely remove all associated PrintObjects.
auto range = print_object_status.equal_range(PrintObjectStatus(model_object.id()));
for (auto it = range.first; it != range.second; ++ it) {
@@ -920,7 +875,7 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co
if (object_config_changed)
model_object.config = model_object_new.config;
if (! object_diff.empty() || object_config_changed) {
- PrintObjectConfig new_config = object_config_from_model(m_default_object_config, model_object, num_extruders);
+ PrintObjectConfig new_config = PrintObject::object_config_from_model_object(m_default_object_config, model_object, num_extruders);
auto range = print_object_status.equal_range(PrintObjectStatus(model_object.id()));
for (auto it = range.first; it != range.second; ++ it) {
t_config_option_keys diff = it->print_object->config().diff(new_config);
@@ -962,7 +917,7 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co
old.emplace_back(&(*it));
}
// Generate a list of trafos and XY offsets for instances of a ModelObject
- PrintObjectConfig config = object_config_from_model(m_default_object_config, *model_object, num_extruders);
+ PrintObjectConfig config = PrintObject::object_config_from_model_object(m_default_object_config, *model_object, num_extruders);
std::vector<PrintInstances> new_print_instances = print_objects_from_model_object(*model_object);
if (old.empty()) {
// Simple case, just generate new instances.
@@ -1053,11 +1008,11 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co
// If the new config for this volume differs from the other
// volume configs currently associated to this region, it means
// the region subdivision does not make sense anymore.
- if (! this_region_config.equals(region_config_from_model_volume(m_default_region_config, volume, num_extruders)))
+ if (! this_region_config.equals(PrintObject::region_config_from_model_volume(m_default_region_config, volume, num_extruders)))
// Regions were split. Reset this print_object.
goto print_object_end;
} else {
- this_region_config = region_config_from_model_volume(m_default_region_config, volume, num_extruders);
+ this_region_config = PrintObject::region_config_from_model_volume(m_default_region_config, volume, num_extruders);
for (size_t i = 0; i < region_id; ++i) {
const PrintRegion &region_other = *m_regions[i];
if (region_other.m_refcnt != 0 && region_other.config().equals(this_region_config))
@@ -1108,7 +1063,7 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co
int region_id = -1;
if (&print_object == &print_object0) {
// Get the config applied to this volume.
- PrintRegionConfig config = region_config_from_model_volume(m_default_region_config, *volume, num_extruders);
+ PrintRegionConfig config = PrintObject::region_config_from_model_volume(m_default_region_config, *volume, num_extruders);
// Find an existing print region with the same config.
int idx_empty_slot = -1;
for (int i = 0; i < (int)m_regions.size(); ++ i) {
@@ -1144,13 +1099,6 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co
}
}
- // Always make sure that the layer_height_profiles are set, as they should not be modified from the worker threads.
- for (PrintObject *object : m_objects)
- if (! object->layer_height_profile_valid)
- // No need to call the next line as the step should already be invalidated above.
- // update_apply_status(object->invalidate_step(posSlice));
- object->update_layer_height_profile();
-
//FIXME there may be a race condition with the G-code export running at the background thread.
this->update_object_placeholders();
@@ -1183,7 +1131,7 @@ std::string Print::validate() const
// Check horizontal clearance.
{
Polygons convex_hulls_other;
- for (PrintObject *object : m_objects) {
+ for (const PrintObject *object : m_objects) {
// Get convex hull of all meshes assigned to this print object.
Polygon convex_hull;
{
@@ -1244,15 +1192,24 @@ std::string Print::validate() const
return L("The Wipe Tower is currently only supported for the Marlin, RepRap/Sprinter and Repetier G-code flavors.");
if (! m_config.use_relative_e_distances)
return L("The Wipe Tower is currently only supported with the relative extruder addressing (use_relative_e_distances=1).");
- SlicingParameters slicing_params0 = m_objects.front()->slicing_parameters();
-
- const PrintObject* tallest_object = m_objects.front(); // let's find the tallest object
- for (const auto* object : m_objects)
- if (*(object->layer_height_profile.end()-2) > *(tallest_object->layer_height_profile.end()-2) )
- tallest_object = object;
- for (PrintObject *object : m_objects) {
- SlicingParameters slicing_params = object->slicing_parameters();
+ if (m_objects.size() > 1) {
+ bool has_custom_layering = false;
+ std::vector<std::vector<coordf_t>> layer_height_profiles;
+ for (const PrintObject *object : m_objects) {
+ has_custom_layering = ! object->model_object()->layer_height_ranges.empty() || ! object->model_object()->layer_height_profile.empty();
+ if (has_custom_layering) {
+ layer_height_profiles.assign(m_objects.size(), std::vector<coordf_t>());
+ break;
+ }
+ }
+ SlicingParameters slicing_params0 = m_objects.front()->slicing_parameters();
+ size_t tallest_object_idx = 0;
+ if (has_custom_layering)
+ PrintObject::update_layer_height_profile(*m_objects.front()->model_object(), slicing_params0, layer_height_profiles.front());
+ for (size_t i = 1; i < m_objects.size(); ++ i) {
+ const PrintObject *object = m_objects[i];
+ const SlicingParameters slicing_params = object->slicing_parameters();
if (std::abs(slicing_params.first_print_layer_height - slicing_params0.first_print_layer_height) > EPSILON ||
std::abs(slicing_params.layer_height - slicing_params0.layer_height ) > EPSILON)
return L("The Wipe Tower is only supported for multiple objects if they have equal layer heigths");
@@ -1264,42 +1221,54 @@ std::string Print::validate() const
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.");
+ if (has_custom_layering) {
+ PrintObject::update_layer_height_profile(*object->model_object(), slicing_params, layer_height_profiles[i]);
+ if (*(layer_height_profiles[i].end()-2) > *(layer_height_profiles[tallest_object_idx].end()-2))
+ tallest_object_idx = i;
+ }
+ }
- if ( m_config.variable_layer_height ) { // comparing layer height profiles
+ if (has_custom_layering) {
+ const std::vector<coordf_t> &layer_height_profile_tallest = layer_height_profiles[tallest_object_idx];
+ for (size_t idx_object = 0; idx_object < m_objects.size(); ++ idx_object) {
+ const PrintObject *object = m_objects[idx_object];
+ const std::vector<coordf_t> &layer_height_profile = layer_height_profiles[idx_object];
bool failed = false;
- // layer_height_profile should be set by Print::apply().
- if (tallest_object->layer_height_profile.size() >= object->layer_height_profile.size() ) {
+ if (layer_height_profile_tallest.size() >= layer_height_profile.size()) {
int i = 0;
- while ( i < object->layer_height_profile.size() && i < tallest_object->layer_height_profile.size()) {
- if (std::abs(tallest_object->layer_height_profile[i] - object->layer_height_profile[i])) {
+ while (i < layer_height_profile.size() && i < layer_height_profile_tallest.size()) {
+ if (std::abs(layer_height_profile_tallest[i] - layer_height_profile[i])) {
failed = true;
break;
}
- ++i;
- if (i == object->layer_height_profile.size()-2) // this element contains this objects max z
- if (tallest_object->layer_height_profile[i] > object->layer_height_profile[i]) // the difference does not matter in this case
- ++i;
+ ++ i;
+ if (i == layer_height_profile.size() - 2) // this element contains this objects max z
+ if (layer_height_profile_tallest[i] > layer_height_profile[i]) // the difference does not matter in this case
+ ++ i;
}
- }
- else
+ } else
failed = true;
-
if (failed)
return L("The Wipe tower is only supported if all objects have the same layer height profile");
}
}
}
+ }
{
// find the smallest nozzle diameter
std::vector<unsigned int> extruders = this->extruders();
if (extruders.empty())
return L("The supplied settings will cause an empty print.");
-
- std::vector<double> nozzle_diameters;
- for (unsigned int extruder_id : extruders)
- nozzle_diameters.push_back(m_config.nozzle_diameter.get_at(extruder_id));
- double min_nozzle_diameter = *std::min_element(nozzle_diameters.begin(), nozzle_diameters.end());
+
+ // Find the smallest used nozzle diameter and the number of unique nozzle diameters.
+ double min_nozzle_diameter = std::numeric_limits<double>::max();
+ double max_nozzle_diameter = 0;
+ for (unsigned int extruder_id : extruders) {
+ double dmr = m_config.nozzle_diameter.get_at(extruder_id);
+ min_nozzle_diameter = std::min(min_nozzle_diameter, dmr);
+ max_nozzle_diameter = std::max(max_nozzle_diameter, dmr);
+ }
#if 0
// We currently allow one to assign extruders with a higher index than the number
@@ -1311,16 +1280,28 @@ std::string Print::validate() const
#endif
for (PrintObject *object : m_objects) {
- if ((object->config().support_material_extruder == -1 || object->config().support_material_interface_extruder == -1) &&
- (object->config().raft_layers > 0 || object->config().support_material.value)) {
+ if (object->config().raft_layers > 0 || object->config().support_material.value) {
+ if ((object->config().support_material_extruder == 0 || object->config().support_material_interface_extruder == 0) && max_nozzle_diameter - min_nozzle_diameter > EPSILON) {
// The object has some form of support and either support_material_extruder or support_material_interface_extruder
// will be printed with the current tool without a forced tool change. Play safe, assert that all object nozzles
// are of the same diameter.
- if (nozzle_diameters.size() > 1)
return L("Printing with multiple extruders of differing nozzle diameters. "
"If support is to be printed with the current extruder (support_material_extruder == 0 or support_material_interface_extruder == 0), "
"all nozzles have to be of the same diameter.");
}
+ if (this->has_wipe_tower()) {
+ if (object->config().support_material_contact_distance == 0) {
+ // Soluble interface
+ if (object->config().support_material_contact_distance == 0 && ! object->config().support_material_synchronize_layers)
+ return L("For the Wipe Tower to work with the soluble supports, the support layers need to be synchronized with the object layers.");
+ } else {
+ // Non-soluble interface
+ if (object->config().support_material_extruder != 0 || object->config().support_material_interface_extruder != 0)
+ return L("The Wipe Tower currently supports the non-soluble supports only if they are printed with the current extruder without triggering a tool change. "
+ "(both support_material_extruder and support_material_interface_extruder need to be set to 0).");
+ }
+ }
+ }
// validate first_layer_height
double first_layer_height = object->config().get_abs_value(L("first_layer_height"));