Prusa Slicer 2.6.0
Loading...
Searching...
No Matches
Slic3r::Print Class Reference

#include <src/libslic3r/Print.hpp>

+ Inheritance diagram for Slic3r::Print:
+ Collaboration diagram for Slic3r::Print:

Public Types

using PrintStepEnum = PrintStep
 
enum  ApplyStatus { APPLY_STATUS_UNCHANGED , APPLY_STATUS_CHANGED , APPLY_STATUS_INVALIDATED }
 
enum  CancelStatus { NOT_CANCELED = 0 , CANCELED_BY_USER = 1 , CANCELED_INTERNAL = 2 }
 
typedef std::function< void(const SlicingStatus &)> status_callback_type
 
typedef std::function< void()> cancel_callback_type
 
using Timestamp = uint64_t
 

Public Member Functions

 Print ()=default
 
virtual ~Print ()
 
PrinterTechnology technology () const noexcept override
 
void clear () override
 
bool empty () const override
 
std::vector< ObjectIDprint_object_ids () const override
 
ApplyStatus apply (const Model &model, DynamicPrintConfig config) override
 
void set_task (const TaskParams &params) override
 
void process () override
 
void finalize () override
 
void cleanup () override
 
std::string export_gcode (const std::string &path_template, GCodeProcessorResult *result, ThumbnailsGeneratorCallback thumbnail_cb=nullptr)
 
bool is_step_done (PrintStep step) const
 
bool is_step_done (PrintObjectStep step) const
 
bool finished () const override
 
bool has_infinite_skirt () const
 
bool has_skirt () const
 
bool has_brim () const
 
std::string validate (std::vector< std::string > *warnings=nullptr) const override
 
double skirt_first_layer_height () const
 
Flow brim_flow () const
 
Flow skirt_flow () const
 
std::vector< unsigned int > object_extruders () const
 
std::vector< unsigned int > support_material_extruders () const
 
std::vector< unsigned int > extruders () const
 
double max_allowed_layer_height () const
 
bool has_support_material () const
 
void auto_assign_extruders (ModelObject *model_object) const
 
const PrintConfig & config () const
 
const PrintObjectConfigdefault_object_config () const
 
const PrintRegionConfigdefault_region_config () const
 
SpanOfConstPtrs< PrintObjectobjects () const
 
PrintObjectget_object (size_t idx)
 
const PrintObjectget_object (size_t idx) const
 
const PrintObjectget_print_object_by_model_object_id (ObjectID object_id) const
 
const PrintObjectget_object (ObjectID object_id) const
 
unsigned int num_object_instances () const
 
PrintObjectPtrsobjects_mutable ()
 
PrintRegionPtrsprint_regions_mutable ()
 
const ExtrusionEntityCollectionskirt () const
 
const ExtrusionEntityCollectionbrim () const
 
const Polygonfirst_layer_convex_hull () const
 
const PrintStatisticsprint_statistics () const
 
PrintStatisticsprint_statistics ()
 
bool has_wipe_tower () const
 
const WipeTowerDatawipe_tower_data (size_t extruders_cnt=0) const
 
const ToolOrderingtool_ordering () const
 
std::string output_filename (const std::string &filename_base=std::string()) const override
 
size_t num_print_regions () const throw ()
 
const PrintRegionget_print_region (size_t idx) const
 
const ToolOrderingget_tool_ordering () const
 
const Polygonsget_sequential_print_clearance_contours () const
 
PrintStateBase::StateWithTimeStamp step_state_with_timestamp (PrintStepEnum step) const
 
PrintStateBase::StateWithWarnings step_state_with_warnings (PrintStepEnum step) const
 
const Modelmodel () const
 
void set_status_default ()
 
void set_status_silent ()
 
void set_status_callback (status_callback_type cb)
 
void set_status (int percent, const std::string &message, unsigned int flags=SlicingStatus::DEFAULT)
 
void set_cancel_callback (cancel_callback_type cancel_callback)
 
CancelStatus cancel_status () const
 
bool canceled () const
 
void cancel ()
 
void cancel_internal ()
 
void restart ()
 
const PlaceholderParserplaceholder_parser () const
 
const DynamicPrintConfigfull_print_config () const
 
std::string output_filepath (const std::string &path, const std::string &filename_base=std::string()) const
 
ObjectID id () const
 
virtual Timestamp timestamp () const
 

Static Public Member Functions

static bool sequential_print_horizontal_clearance_valid (const Print &print, Polygons *polygons=nullptr)
 

Static Public Attributes

static constexpr const size_t PrintStepEnumSize
 

Protected Member Functions

bool invalidate_step (PrintStep step)
 
bool set_started (PrintStepEnum step)
 
PrintStateBase::TimeStamp set_done (PrintStepEnum step)
 
bool invalidate_steps (StepTypeIterator step_begin, StepTypeIterator step_end)
 
bool invalidate_steps (std::initializer_list< PrintStepEnum > il)
 
bool invalidate_all_steps ()
 
bool is_step_started_unguarded (PrintStepEnum step) const
 
bool is_step_done_unguarded (PrintStepEnum step) const
 
void active_step_add_warning (PrintStateBase::WarningLevel warning_level, const std::string &message, int message_id=0)
 
void set_task_impl (const TaskParams &params, std::vector< PrintObject * > &print_objects)
 
void finalize_impl (std::vector< PrintObject * > &print_objects)
 
std::string output_filename (const std::string &format, const std::string &default_ext, const std::string &filename_base, const DynamicConfig *config_override=nullptr) const
 
std::mutex & state_mutex () const
 
std::function< void()> cancel_callback ()
 
void call_cancel_callback ()
 
void status_update_warnings (int step, PrintStateBase::WarningLevel warning_level, const std::string &message, const PrintObjectBase *print_object=nullptr)
 
void throw_if_canceled () const
 
PrintTryCancel make_try_cancel () const
 
void update_object_placeholders (DynamicConfig &config, const std::string &default_ext) const
 
void set_new_unique_id ()
 
void set_invalid_id ()
 
void copy_id (const ObjectBase &rhs)
 
virtual void assign_new_unique_ids_recursive ()
 

Protected Attributes

Model m_model
 
DynamicPrintConfig m_full_print_config
 
PlaceholderParser m_placeholder_parser
 
status_callback_type m_status_callback
 

Private Types

typedef PrintBaseWithState< PrintStep, psCountInherited
 
typedef std::pair< PrintObject *, bool > PrintObjectInfo
 

Private Member Functions

bool invalidate_state_by_config_options (const ConfigOptionResolver &new_config, const std::vector< t_config_option_key > &opt_keys)
 
void _make_skirt ()
 
void _make_wipe_tower ()
 
void finalize_first_layer_convex_hull ()
 
void alert_when_supports_needed ()
 
Polygons first_layer_islands () const
 
Points first_layer_wipe_tower_corners () const
 
template<class Archive >
void serialize (Archive &ar)
 

Static Private Member Functions

static bool is_shared_print_object_step_valid_unguarded (SpanOfConstPtrs< PrintObject > print_objects, PrintObjectStep print_object_step)
 
static ObjectID generate_new_id ()
 
template<class Archive >
static void load_and_construct (Archive &ar, cereal::construct< ObjectBase > &construct)
 

Private Attributes

PrintConfig m_config
 
PrintObjectConfig m_default_object_config
 
PrintRegionConfig m_default_region_config
 
PrintObjectPtrs m_objects
 
PrintRegionPtrs m_print_regions
 
ExtrusionEntityCollection m_skirt
 
ExtrusionEntityCollection m_brim
 
Polygon m_first_layer_convex_hull
 
Points m_skirt_convex_hull
 
ToolOrdering m_tool_ordering
 
WipeTowerData m_wipe_tower_data {m_tool_ordering}
 
PrintStatistics m_print_statistics
 
Polygons m_sequential_print_clearance_contours
 
ConflictResultOpt m_conflict_result
 
FakeWipeTower m_fake_wipe_tower
 
PrintState< PrintStepEnum, COUNT > m_state
 
std::atomic< CancelStatusm_cancel_status
 
cancel_callback_type m_cancel_callback = [](){}
 
std::mutex m_state_mutex
 
friend PrintTryCancel
 
ObjectID m_id
 

Static Private Attributes

static size_t s_last_id = 0
 

Friends

class GCode
 
class GCodeProcessor
 
class PrintObject
 

Detailed Description

Member Typedef Documentation

◆ cancel_callback_type

typedef std::function<void()> Slic3r::PrintBase::cancel_callback_type
inherited

◆ Inherited

◆ PrintObjectInfo

typedef std::pair<PrintObject *, bool> Slic3r::Print::PrintObjectInfo
private

◆ PrintStepEnum

using Slic3r::PrintBaseWithState< PrintStep , COUNT >::PrintStepEnum = PrintStep
inherited

◆ status_callback_type

◆ Timestamp

Member Enumeration Documentation

◆ ApplyStatus

Enumerator
APPLY_STATUS_UNCHANGED 
APPLY_STATUS_CHANGED 
APPLY_STATUS_INVALIDATED 
423 {
424 // No change after the Print::apply() call.
426 // Some of the Print / PrintObject / PrintObjectInstance data was changed,
427 // but no result was invalidated (only data influencing not yet calculated results were changed).
429 // Some data was changed, which in turn invalidated already calculated steps.
431 };
@ APPLY_STATUS_UNCHANGED
Definition PrintBase.hpp:425
@ APPLY_STATUS_CHANGED
Definition PrintBase.hpp:428
@ APPLY_STATUS_INVALIDATED
Definition PrintBase.hpp:430

◆ CancelStatus

Enumerator
NOT_CANCELED 
CANCELED_BY_USER 
CANCELED_INTERNAL 
503 {
504 // No cancelation, background processing should run.
505 NOT_CANCELED = 0,
506 // Canceled by user from the user interface (user pressed the "Cancel" button or user closed the application).
508 // Canceled internally from Print::apply() through the Print/PrintObject::invalidate_step() or ::invalidate_all_steps().
510 };
@ NOT_CANCELED
Definition PrintBase.hpp:505
@ CANCELED_INTERNAL
Definition PrintBase.hpp:509
@ CANCELED_BY_USER
Definition PrintBase.hpp:507

Constructor & Destructor Documentation

◆ Print()

Slic3r::Print::Print ( )
default

◆ ~Print()

virtual Slic3r::Print::~Print ( )
inlinevirtual
548{ this->clear(); }
void clear() override
Definition Print.cpp:38

References clear().

+ Here is the call graph for this function:

Member Function Documentation

◆ _make_skirt()

void Slic3r::Print::_make_skirt ( )
private
1010{
1011 // First off we need to decide how tall the skirt must be.
1012 // The skirt_height option from config is expressed in layers, but our
1013 // object might have different layer heights, so we need to find the print_z
1014 // of the highest layer involved.
1015 // Note that unless has_infinite_skirt() == true
1016 // the actual skirt might not reach this $skirt_height_z value since the print
1017 // order of objects on each layer is not guaranteed and will not generally
1018 // include the thickest object first. It is just guaranteed that a skirt is
1019 // prepended to the first 'n' layers (with 'n' = skirt_height).
1020 // $skirt_height_z in this case is the highest possible skirt height for safety.
1021 coordf_t skirt_height_z = 0.;
1022 for (const PrintObject *object : m_objects) {
1023 size_t skirt_layers = this->has_infinite_skirt() ?
1024 object->layer_count() :
1025 std::min(size_t(m_config.skirt_height.value), object->layer_count());
1026 skirt_height_z = std::max(skirt_height_z, object->m_layers[skirt_layers-1]->print_z);
1027 }
1028
1029 // Collect points from all layers contained in skirt height.
1030 Points points;
1031 for (const PrintObject *object : m_objects) {
1032 Points object_points;
1033 // Get object layers up to skirt_height_z.
1034 for (const Layer *layer : object->m_layers) {
1035 if (layer->print_z > skirt_height_z)
1036 break;
1037 for (const ExPolygon &expoly : layer->lslices)
1038 // Collect the outer contour points only, ignore holes for the calculation of the convex hull.
1039 append(object_points, expoly.contour.points);
1040 }
1041 // Get support layers up to skirt_height_z.
1042 for (const SupportLayer *layer : object->support_layers()) {
1043 if (layer->print_z > skirt_height_z)
1044 break;
1045 layer->support_fills.collect_points(object_points);
1046 }
1047 // Repeat points for each object copy.
1048 for (const PrintInstance &instance : object->instances()) {
1049 Points copy_points = object_points;
1050 for (Point &pt : copy_points)
1051 pt += instance.shift;
1052 append(points, copy_points);
1053 }
1054 }
1055
1056 // Include the wipe tower.
1057 append(points, this->first_layer_wipe_tower_corners());
1058
1059 // Unless draft shield is enabled, include all brims as well.
1060 if (config().draft_shield == dsDisabled)
1062
1063 if (points.size() < 3)
1064 // At least three points required for a convex hull.
1065 return;
1066
1067 this->throw_if_canceled();
1069
1070 // Skirt may be printed on several layers, having distinct layer heights,
1071 // but loops must be aligned so can't vary width/spacing
1072 // TODO: use each extruder's own flow
1073 double first_layer_height = this->skirt_first_layer_height();
1074 Flow flow = this->skirt_flow();
1075 float spacing = flow.spacing();
1076 double mm3_per_mm = flow.mm3_per_mm();
1077
1078 std::vector<size_t> extruders;
1079 std::vector<double> extruders_e_per_mm;
1080 {
1081 auto set_extruders = this->extruders();
1082 extruders.reserve(set_extruders.size());
1083 extruders_e_per_mm.reserve(set_extruders.size());
1084 for (auto &extruder_id : set_extruders) {
1085 extruders.push_back(extruder_id);
1086 extruders_e_per_mm.push_back(Extruder((unsigned int)extruder_id, &m_config).e_per_mm(mm3_per_mm));
1087 }
1088 }
1089
1090 // Number of skirt loops per skirt layer.
1091 size_t n_skirts = m_config.skirts.value;
1092 if (this->has_infinite_skirt() && n_skirts == 0)
1093 n_skirts = 1;
1094
1095 // Initial offset of the brim inner edge from the object (possible with a support & raft).
1096 // The skirt will touch the brim if the brim is extruded.
1097 auto distance = float(scale_(m_config.skirt_distance.value) - spacing/2.);
1098 // Draw outlines from outside to inside.
1099 // Loop while we have less skirts than required or any extruder hasn't reached the min length if any.
1100 std::vector<coordf_t> extruded_length(extruders.size(), 0.);
1101 for (size_t i = n_skirts, extruder_idx = 0; i > 0; -- i) {
1102 this->throw_if_canceled();
1103 // Offset the skirt outside.
1104 distance += float(scale_(spacing));
1105 // Generate the skirt centerline.
1106 Polygon loop;
1107 {
1108 Polygons loops = offset(convex_hull, distance, ClipperLib::jtRound, float(scale_(0.1)));
1109 Geometry::simplify_polygons(loops, scale_(0.05), &loops);
1110 if (loops.empty())
1111 break;
1112 loop = loops.front();
1113 }
1114 // Extrude the skirt loop.
1115 ExtrusionLoop eloop(elrSkirt);
1116 eloop.paths.emplace_back(ExtrusionPath(
1117 ExtrusionPath(
1119 (float)mm3_per_mm, // this will be overridden at G-code export time
1120 flow.width(),
1121 (float)first_layer_height // this will be overridden at G-code export time
1122 )));
1123 eloop.paths.back().polyline = loop.split_at_first_point();
1124 m_skirt.append(eloop);
1125 if (m_config.min_skirt_length.value > 0) {
1126 // The skirt length is limited. Sum the total amount of filament length extruded, in mm.
1127 extruded_length[extruder_idx] += unscale<double>(loop.length()) * extruders_e_per_mm[extruder_idx];
1128 if (extruded_length[extruder_idx] < m_config.min_skirt_length.value) {
1129 // Not extruded enough yet with the current extruder. Add another loop.
1130 if (i == 1)
1131 ++ i;
1132 } else {
1133 assert(extruded_length[extruder_idx] >= m_config.min_skirt_length.value);
1134 // Enough extruded with the current extruder. Extrude with the next one,
1135 // until the prescribed number of skirt loops is extruded.
1136 if (extruder_idx + 1 < extruders.size())
1137 ++ extruder_idx;
1138 }
1139 } else {
1140 // The skirt lenght is not limited, extrude the skirt with the 1st extruder only.
1141 }
1142 }
1143 // Brims were generated inside out, reverse to print the outmost contour first.
1144 m_skirt.reverse();
1145
1146 // Remember the outer edge of the last skirt line extruded as m_skirt_convex_hull.
1147 for (Polygon &poly : offset(convex_hull, distance + 0.5f * float(scale_(spacing)), ClipperLib::jtRound, float(scale_(0.1))))
1148 append(m_skirt_convex_hull, std::move(poly.points));
1149}
void append(const ExtrusionEntity &entity)
Definition ExtrusionEntityCollection.hpp:68
void reverse() override
Definition ExtrusionEntityCollection.cpp:64
Points points
Definition MultiPoint.hpp:18
void throw_if_canceled() const
Definition PrintBase.hpp:544
double skirt_first_layer_height() const
Definition Print.cpp:826
Flow skirt_flow() const
Definition Print.cpp:852
ExtrusionEntityCollection m_skirt
Definition Print.hpp:679
Points m_skirt_convex_hull
Definition Print.hpp:687
bool has_infinite_skirt() const
Definition Print.cpp:370
Polygon m_first_layer_convex_hull
Definition Print.hpp:686
PrintObjectPtrs m_objects
Definition Print.hpp:675
friend class PrintObject
Definition Print.hpp:704
Points first_layer_wipe_tower_corners() const
Definition Print.cpp:1172
PrintConfig m_config
Definition Print.hpp:672
const PrintConfig & config() const
Definition Print.hpp:597
std::vector< unsigned int > extruders() const
Definition Print.cpp:327
#define scale_(val)
Definition libslic3r.h:69
double coordf_t
Definition libslic3r.h:45
Definition clipper.cpp:60
@ jtRound
Definition clipper.hpp:138
Polygon convex_hull(Points pts)
Definition ConvexHull.cpp:11
void simplify_polygons(const Polygons &polygons, double tolerance, Polygons *retval)
Definition Geometry.cpp:53
std::vector< Polygon, PointsAllocator< Polygon > > Polygons
Definition Polygon.hpp:15
@ elrSkirt
Definition ExtrusionRole.hpp:98
Slic3r::Polygons offset(const Slic3r::Polygon &polygon, const float delta, ClipperLib::JoinType joinType, double miterLimit)
Definition ClipperUtils.cpp:416
void append(std::vector< T, Alloc > &dest, const std::vector< T, Alloc2 > &src)
Definition libslic3r.h:110
@ dsDisabled
Definition PrintConfig.hpp:125
std::vector< Point, PointsAllocator< Point > > Points
Definition Point.hpp:58
const Polygon & contour(const ExPolygon &p)
Definition AGGRaster.hpp:21
IGL_INLINE void convex_hull(const Eigen::MatrixBase< DerivedV > &V, Eigen::PlainObjectBase< DerivedW > &W, Eigen::PlainObjectBase< DerivedG > &G)
Definition convex_hull.cpp:21
IGL_INLINE void loop(const int n_verts, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::SparseMatrix< SType > &S, Eigen::PlainObjectBase< DerivedNF > &NF)
Definition loop.cpp:21
double distance(const P &p1, const P &p2)
Definition geometry_traits.hpp:329
Slic3r::Polygon Polygon
Definition Emboss.cpp:34
STL namespace.
Kernel::Point_2 Point
Definition point_areas.cpp:20
static constexpr const ExtrusionRoleModifiers Skirt
Definition ExtrusionRole.hpp:71

References Slic3r::ExtrusionEntityCollection::append(), Slic3r::append(), config(), Slic3r::Geometry::convex_hull(), Slic3r::dsDisabled, Slic3r::Extruder::e_per_mm(), Slic3r::elrSkirt, extruders(), first_layer_wipe_tower_corners(), has_infinite_skirt(), ClipperLib::jtRound, m_config, m_first_layer_convex_hull, m_objects, m_skirt, m_skirt_convex_hull, Slic3r::Flow::mm3_per_mm(), Slic3r::offset(), Slic3r::ExtrusionLoop::paths, Slic3r::MultiPoint::points, Slic3r::ExtrusionEntityCollection::reverse(), scale_, Slic3r::Geometry::simplify_polygons(), Slic3r::ExtrusionRole::Skirt, skirt_first_layer_height(), skirt_flow(), Slic3r::Flow::spacing(), Slic3r::PrintBase::throw_if_canceled(), and Slic3r::Flow::width().

Referenced by process().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ _make_wipe_tower()

void Slic3r::Print::_make_wipe_tower ( )
private
1404{
1406 if (! this->has_wipe_tower())
1407 return;
1408
1409 std::vector<std::vector<float>> wipe_volumes = WipeTower::extract_wipe_volumes(m_config);
1410
1411 // Let the ToolOrdering class know there will be initial priming extrusions at the start of the print.
1412 m_wipe_tower_data.tool_ordering = ToolOrdering(*this, (unsigned int)-1, true);
1413
1415 // Don't generate any wipe tower.
1416 return;
1417
1418 // Check whether there are any layers in m_tool_ordering, which are marked with has_wipe_tower,
1419 // they print neither object, nor support. These layers are above the raft and below the object, and they
1420 // shall be added to the support layers to be printed.
1421 // see https://github.com/prusa3d/PrusaSlicer/issues/607
1422 {
1423 size_t idx_begin = size_t(-1);
1424 size_t idx_end = m_wipe_tower_data.tool_ordering.layer_tools().size();
1425 // Find the first wipe tower layer, which does not have a counterpart in an object or a support layer.
1426 for (size_t i = 0; i < idx_end; ++ i) {
1427 const LayerTools &lt = m_wipe_tower_data.tool_ordering.layer_tools()[i];
1428 if (lt.has_wipe_tower && ! lt.has_object && ! lt.has_support) {
1429 idx_begin = i;
1430 break;
1431 }
1432 }
1433 if (idx_begin != size_t(-1)) {
1434 // Find the position in m_objects.first()->support_layers to insert these new support layers.
1435 double wipe_tower_new_layer_print_z_first = m_wipe_tower_data.tool_ordering.layer_tools()[idx_begin].print_z;
1436 auto it_layer = m_objects.front()->support_layers().begin();
1437 auto it_end = m_objects.front()->support_layers().end();
1438 for (; it_layer != it_end && (*it_layer)->print_z - EPSILON < wipe_tower_new_layer_print_z_first; ++ it_layer);
1439 // Find the stopper of the sequence of wipe tower layers, which do not have a counterpart in an object or a support layer.
1440 for (size_t i = idx_begin; i < idx_end; ++ i) {
1441 LayerTools &lt = const_cast<LayerTools&>(m_wipe_tower_data.tool_ordering.layer_tools()[i]);
1442 if (! (lt.has_wipe_tower && ! lt.has_object && ! lt.has_support))
1443 break;
1444 lt.has_support = true;
1445 // Insert the new support layer.
1446 double height = lt.print_z - (i == 0 ? 0. : m_wipe_tower_data.tool_ordering.layer_tools()[i-1].print_z);
1447 //FIXME the support layer ID is set to -1, as Vojtech hopes it is not being used anyway.
1448 it_layer = m_objects.front()->insert_support_layer(it_layer, -1, 0, height, lt.print_z, lt.print_z - 0.5 * height);
1449 ++ it_layer;
1450 }
1451 }
1452 }
1453 this->throw_if_canceled();
1454
1455 // Initialize the wipe tower.
1457
1458 //wipe_tower.set_retract();
1459 //wipe_tower.set_zhop();
1460
1461 // Set the extruder & material properties at the wipe tower object.
1462 for (size_t i = 0; i < m_config.nozzle_diameter.size(); ++ i)
1463 wipe_tower.set_extruder(i, m_config);
1464
1465 m_wipe_tower_data.priming = Slic3r::make_unique<std::vector<WipeTower::ToolChangeResult>>(
1466 wipe_tower.prime((float)this->skirt_first_layer_height(), m_wipe_tower_data.tool_ordering.all_extruders(), false));
1467
1468 // Lets go through the wipe tower layers and determine pairs of extruder changes for each
1469 // to pass to wipe_tower (so that it can use it for planning the layout of the tower)
1470 {
1471 unsigned int current_extruder_id = m_wipe_tower_data.tool_ordering.all_extruders().back();
1472 for (auto &layer_tools : m_wipe_tower_data.tool_ordering.layer_tools()) { // for all layers
1473 if (!layer_tools.has_wipe_tower) continue;
1474 bool first_layer = &layer_tools == &m_wipe_tower_data.tool_ordering.front();
1475 wipe_tower.plan_toolchange((float)layer_tools.print_z, (float)layer_tools.wipe_tower_layer_height, current_extruder_id, current_extruder_id, false);
1476 for (const auto extruder_id : layer_tools.extruders) {
1477 if ((first_layer && extruder_id == m_wipe_tower_data.tool_ordering.all_extruders().back()) || extruder_id != current_extruder_id) {
1478 float volume_to_wipe = wipe_volumes[current_extruder_id][extruder_id]; // total volume to wipe after this toolchange
1479 // Not all of that can be used for infill purging:
1480 volume_to_wipe -= (float)m_config.filament_minimal_purge_on_wipe_tower.get_at(extruder_id);
1481
1482 // try to assign some infills/objects for the wiping:
1483 volume_to_wipe = layer_tools.wiping_extrusions_nonconst().mark_wiping_extrusions(*this, layer_tools, current_extruder_id, extruder_id, volume_to_wipe);
1484
1485 // add back the minimal amount toforce on the wipe tower:
1486 volume_to_wipe += (float)m_config.filament_minimal_purge_on_wipe_tower.get_at(extruder_id);
1487
1488 // request a toolchange at the wipe tower with at least volume_to_wipe purging amount
1489 wipe_tower.plan_toolchange((float)layer_tools.print_z, (float)layer_tools.wipe_tower_layer_height,
1490 current_extruder_id, extruder_id, volume_to_wipe);
1491 current_extruder_id = extruder_id;
1492 }
1493 }
1494 layer_tools.wiping_extrusions_nonconst().ensure_perimeters_infills_order(*this, layer_tools);
1495 if (&layer_tools == &m_wipe_tower_data.tool_ordering.back() || (&layer_tools + 1)->wipe_tower_partitions == 0)
1496 break;
1497 }
1498 }
1499
1500 // Generate the wipe tower layers.
1502 wipe_tower.generate(m_wipe_tower_data.tool_changes);
1503 m_wipe_tower_data.depth = wipe_tower.get_depth();
1504 m_wipe_tower_data.z_and_depth_pairs = wipe_tower.get_z_and_depth_pairs();
1505 m_wipe_tower_data.brim_width = wipe_tower.get_brim_width();
1506 m_wipe_tower_data.height = wipe_tower.get_wipe_tower_height();
1507
1508 // Unload the current filament over the purge tower.
1509 coordf_t layer_height = m_objects.front()->config().layer_height.value;
1511 // The wipe tower goes up to the last layer of the print.
1512 if (wipe_tower.layer_finished()) {
1513 // The wipe tower is printed to the top of the print and it has no space left for the final extruder purge.
1514 // Lift Z to the next layer.
1515 wipe_tower.set_layer(float(m_wipe_tower_data.tool_ordering.back().print_z + layer_height), float(layer_height), 0, false, true);
1516 } else {
1517 // There is yet enough space at this layer of the wipe tower for the final purge.
1518 }
1519 } else {
1520 // The wipe tower does not reach the last print layer, perform the pruge at the last print layer.
1522 wipe_tower.set_layer(float(m_wipe_tower_data.tool_ordering.back().print_z), float(layer_height), 0, false, true);
1523 }
1524 m_wipe_tower_data.final_purge = Slic3r::make_unique<WipeTower::ToolChangeResult>(
1525 wipe_tower.tool_change((unsigned int)(-1)));
1526
1527 m_wipe_tower_data.used_filament = wipe_tower.get_used_filament();
1528 m_wipe_tower_data.number_of_toolchanges = wipe_tower.get_number_of_toolchanges();
1529 const Vec3d origin = Vec3d::Zero();
1530 m_fake_wipe_tower.set_fake_extrusion_data(wipe_tower.position(), wipe_tower.width(), wipe_tower.get_wipe_tower_height(), config().first_layer_height, m_wipe_tower_data.depth,
1531 m_wipe_tower_data.z_and_depth_pairs, m_wipe_tower_data.brim_width, config().wipe_tower_rotation_angle, config().wipe_tower_cone_angle, {scale_(origin.x()), scale_(origin.y())});
1532
1533}
coordf_t print_z
Definition ToolOrdering.hpp:89
size_t wipe_tower_partitions
Definition ToolOrdering.hpp:106
const ToolOrdering & tool_ordering() const
Definition Print.hpp:638
WipeTowerData m_wipe_tower_data
Definition Print.hpp:691
bool has_wipe_tower() const
Definition Print.cpp:1369
FakeWipeTower m_fake_wipe_tower
Definition Print.hpp:707
bool has_wipe_tower() const
Definition ToolOrdering.hpp:163
const LayerTools & back() const
Definition ToolOrdering.hpp:158
const LayerTools & front() const
Definition ToolOrdering.hpp:157
unsigned int first_extruder() const
Definition ToolOrdering.hpp:145
const std::vector< unsigned int > & all_extruders() const
Definition ToolOrdering.hpp:151
std::vector< LayerTools > & layer_tools()
Definition ToolOrdering.hpp:162
static std::vector< std::vector< float > > extract_wipe_volumes(const PrintConfig &config)
Definition WipeTower.cpp:1349
static constexpr double EPSILON
Definition libslic3r.h:51
coord_t height(const BoundingBox &box)
Definition Arrange.cpp:540
layer_height((ConfigOptionInt, faded_layers))((ConfigOptionFloat
Eigen::Matrix< double, 3, 1, Eigen::DontAlign > Vec3d
Definition Point.hpp:52
void set_fake_extrusion_data(const Vec2f &p, float w, float h, float lh, float d, const std::vector< std::pair< float, float > > &zad, float bd, float ra, float ca, const Vec2d &o)
Definition Print.hpp:435
std::vector< float > used_filament
Definition Print.hpp:464
std::unique_ptr< WipeTower::ToolChangeResult > final_purge
Definition Print.hpp:463
std::vector< std::pair< float, float > > z_and_depth_pairs
Definition Print.hpp:469
std::unique_ptr< std::vector< WipeTower::ToolChangeResult > > priming
Definition Print.hpp:461
void clear()
Definition Print.hpp:473
ToolOrdering & tool_ordering
Definition Print.hpp:459
float brim_width
Definition Print.hpp:470
float depth
Definition Print.hpp:468
std::vector< std::vector< WipeTower::ToolChangeResult > > tool_changes
Definition Print.hpp:462
float height
Definition Print.hpp:471
int number_of_toolchanges
Definition Print.hpp:465

References Slic3r::ToolOrdering::all_extruders(), Slic3r::ToolOrdering::back(), Slic3r::WipeTowerData::brim_width, Slic3r::WipeTowerData::clear(), config(), Slic3r::WipeTowerData::depth, EPSILON, Slic3r::WipeTower::extract_wipe_volumes(), Slic3r::WipeTowerData::final_purge, Slic3r::ToolOrdering::first_extruder(), Slic3r::ToolOrdering::front(), Slic3r::WipeTower::generate(), Slic3r::WipeTower::get_brim_width(), Slic3r::WipeTower::get_depth(), Slic3r::WipeTower::get_number_of_toolchanges(), Slic3r::WipeTower::get_used_filament(), Slic3r::WipeTower::get_wipe_tower_height(), Slic3r::WipeTower::get_z_and_depth_pairs(), Slic3r::LayerTools::has_object, Slic3r::LayerTools::has_support, Slic3r::LayerTools::has_wipe_tower, Slic3r::ToolOrdering::has_wipe_tower(), has_wipe_tower(), Slic3r::WipeTowerData::height, Slic3r::WipeTower::layer_finished(), Slic3r::layer_height(), Slic3r::ToolOrdering::layer_tools(), m_config, m_fake_wipe_tower, m_objects, m_wipe_tower_data, Slic3r::WipeTowerData::number_of_toolchanges, Slic3r::WipeTower::plan_toolchange(), Slic3r::WipeTower::position(), Slic3r::WipeTower::prime(), Slic3r::WipeTowerData::priming, Slic3r::LayerTools::print_z, scale_, Slic3r::WipeTower::set_extruder(), Slic3r::FakeWipeTower::set_fake_extrusion_data(), Slic3r::WipeTower::set_layer(), skirt_first_layer_height(), Slic3r::PrintBase::throw_if_canceled(), Slic3r::WipeTower::tool_change(), Slic3r::WipeTowerData::tool_changes, Slic3r::WipeTowerData::tool_ordering, Slic3r::WipeTowerData::used_filament, Slic3r::WipeTower::width(), Slic3r::LayerTools::wipe_tower_partitions, and Slic3r::WipeTowerData::z_and_depth_pairs.

Referenced by process().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ active_step_add_warning()

void Slic3r::PrintBaseWithState< PrintStep , COUNT >::active_step_add_warning ( PrintStateBase::WarningLevel  warning_level,
const std::string &  message,
int  message_id = 0 
)
inlineprotectedinherited
610 {
611 std::pair<PrintStepEnum, bool> active_step = m_state.active_step_add_warning(warning_level, message, message_id, this->state_mutex());
612 if (active_step.second)
613 // Update UI.
614 this->status_update_warnings(static_cast<int>(active_step.first), warning_level, message);
615 }
void status_update_warnings(int step, PrintStateBase::WarningLevel warning_level, const std::string &message, const PrintObjectBase *print_object=nullptr)
Definition PrintBase.cpp:100
std::mutex & state_mutex() const
Definition PrintBase.hpp:534
PrintState< PrintStepEnum, COUNT > m_state
Definition PrintBase.hpp:725
std::pair< StepType, bool > active_step_add_warning(PrintStateBase::WarningLevel warning_level, const std::string &message, int message_id, std::mutex &mtx)
Definition PrintBase.hpp:321

◆ alert_when_supports_needed()

void Slic3r::Print::alert_when_supports_needed ( )
private
1217{
1219 BOOST_LOG_TRIVIAL(debug) << "psAlertWhenSupportsNeeded - start";
1220 set_status(69, _u8L("Alert if supports needed"));
1221
1222 auto issue_to_alert_message = [](SupportSpotsGenerator::SupportPointCause cause, bool critical) {
1223 std::string message;
1224 switch (cause) {
1225 //TRN Alert when support is needed. Describes that the model has long bridging extrusions which may print badly
1226 case SupportSpotsGenerator::SupportPointCause::LongBridge: message = _u8L("Long bridging extrusions"); break;
1227 //TRN Alert when support is needed. Describes bridge anchors/turns in the air, which will definitely print badly
1228 case SupportSpotsGenerator::SupportPointCause::FloatingBridgeAnchor: message = _u8L("Floating bridge anchors"); break;
1230 if (critical) {
1231 //TRN Alert when support is needed. Describes that the print has large overhang area which will print badly or not print at all.
1232 message = _u8L("Collapsing overhang");
1233 } else {
1234 //TRN Alert when support is needed. Describes extrusions that are not supported enough and come out curled or loose.
1235 message = _u8L("Loose extrusions");
1236 }
1237 break;
1238 //TRN Alert when support is needed. Describes that the print has low bed adhesion and may became loose.
1239 case SupportSpotsGenerator::SupportPointCause::SeparationFromBed: message = _u8L("Low bed adhesion"); break;
1240 //TRN Alert when support is needed. Describes that the object has part that is not connected to the bed and will not print at all without supports.
1241 case SupportSpotsGenerator::SupportPointCause::UnstableFloatingPart: message = _u8L("Floating object part"); break;
1242 //TRN Alert when support is needed. Describes that the object has thin part that may brake during printing
1243 case SupportSpotsGenerator::SupportPointCause::WeakObjectPart: message = _u8L("Thin fragile part"); break;
1244 }
1245
1246 return message;
1247 };
1248
1249 // TRN this translation rule is used to translate lists of uknown size on single line. The first argument is element of the list,
1250 // the second argument may be element or rest of the list. For most languages, this does not need translation, but some use different
1251 // separator than comma and some use blank space in front of the separator.
1252 auto single_line_list_rule = L("%1%, %2%");
1253 auto multiline_list_rule = "%1%\n%2%";
1254
1255 auto elements_to_translated_list = [](const std::vector<std::string> &translated_elements, std::string expansion_rule) {
1256 if (expansion_rule.find("%1%") == expansion_rule.npos || expansion_rule.find("%2%") == expansion_rule.npos) {
1257 BOOST_LOG_TRIVIAL(error) << "INCORRECT EXPANSION RULE FOR LIST TRANSLATION: " << expansion_rule
1258 << " - IT SHOULD CONTAIN %1% and %2%!";
1259 expansion_rule = "%1% %2%";
1260 }
1261 if (translated_elements.size() == 0) {
1262 return std::string{};
1263 }
1264 if (translated_elements.size() == 1) {
1265 return translated_elements.front();
1266 }
1267
1268 std::string translated_list = expansion_rule;
1269 for (int i = 0; i < int(translated_elements.size()) - 1; ++ i) {
1270 auto first_elem = translated_list.find("%1%");
1271 assert(first_elem != translated_list.npos);
1272 translated_list.replace(first_elem, 3, translated_elements[i]);
1273
1274 // expand the translated list by another application of the same rule
1275 auto second_elem = translated_list.find("%2%");
1276 assert(second_elem != translated_list.npos);
1277 if (i < int(translated_elements.size()) - 2) {
1278 translated_list.replace(second_elem, 3, expansion_rule);
1279 } else {
1280 translated_list.replace(second_elem, 3, translated_elements[i + 1]);
1281 }
1282 }
1283
1284 return translated_list;
1285 };
1286
1287 // vector of pairs of object and its issues, where each issue is a pair of type and critical flag
1288 std::vector<std::pair<const PrintObject *, std::vector<std::pair<SupportSpotsGenerator::SupportPointCause, bool>>>> objects_isssues;
1289
1290 for (const PrintObject *object : m_objects) {
1291 std::unordered_set<const ModelObject *> checked_model_objects;
1292 if (!object->has_support() && checked_model_objects.find(object->model_object()) == checked_model_objects.end()) {
1293 if (object->m_shared_regions->generated_support_points.has_value()) {
1294 SupportSpotsGenerator::SupportPoints supp_points = object->m_shared_regions->generated_support_points->support_points;
1295 SupportSpotsGenerator::PartialObjects partial_objects = object->m_shared_regions->generated_support_points
1296 ->partial_objects;
1297 auto issues = SupportSpotsGenerator::gather_issues(supp_points, partial_objects);
1298 if (issues.size() > 0) {
1299 objects_isssues.emplace_back(object, issues);
1300 }
1301 }
1302 checked_model_objects.emplace(object->model_object());
1303 }
1304 }
1305
1306 bool recommend_brim = false;
1307 std::map<std::pair<SupportSpotsGenerator::SupportPointCause, bool>, std::vector<const PrintObject *>> po_by_support_issues;
1308 for (const auto &obj : objects_isssues) {
1309 for (const auto &issue : obj.second) {
1310 po_by_support_issues[issue].push_back(obj.first);
1311 if (issue.first == SupportSpotsGenerator::SupportPointCause::SeparationFromBed && !obj.first->has_brim()) {
1312 recommend_brim = true;
1313 }
1314 }
1315 }
1316
1317 std::vector<std::pair<std::string, std::vector<std::string>>> message_elements;
1318 if (objects_isssues.size() > po_by_support_issues.size()) {
1319 // there are more objects than causes, group by issues
1320 for (const auto &issue : po_by_support_issues) {
1321 auto &pair = message_elements.emplace_back(issue_to_alert_message(issue.first.first, issue.first.second),
1322 std::vector<std::string>{});
1323 for (const auto &obj : issue.second) {
1324 pair.second.push_back(obj->m_model_object->name);
1325 }
1326 }
1327 } else {
1328 // more causes than objects, group by objects
1329 for (const auto &obj : objects_isssues) {
1330 auto &pair = message_elements.emplace_back(obj.first->model_object()->name, std::vector<std::string>{});
1331 for (const auto &issue : obj.second) {
1332 pair.second.push_back(issue_to_alert_message(issue.first, issue.second));
1333 }
1334 }
1335 }
1336
1337 // first, gather sublements into single line list, store in first subelement
1338 for (auto &pair : message_elements) {
1339 pair.second.front() = elements_to_translated_list(pair.second, single_line_list_rule);
1340 }
1341
1342 // then gather elements to create multiline list
1343 std::vector<std::string> lines = {};
1344 for (auto &pair : message_elements) {
1345 lines.push_back(""); // empty line for readability
1346 lines.push_back(pair.first);
1347 lines.push_back(pair.second.front());
1348 }
1349
1350 lines.push_back("");
1351 lines.push_back(_u8L("Consider enabling supports."));
1352 if (recommend_brim) {
1353 lines.push_back(_u8L("Also consider enabling brim."));
1354 }
1355
1356 // TRN Alert message for detected print issues. first argument is a list of detected issues.
1357 auto message = Slic3r::format(_u8L("Detected print stability issues:\n%1%"), elements_to_translated_list(lines, multiline_list_rule));
1358
1359 if (objects_isssues.size() > 0) {
1361 }
1362
1363 BOOST_LOG_TRIVIAL(debug) << "psAlertWhenSupportsNeeded - end";
1365 }
1366}
#define _u8L(s)
macro used to mark string used at localization, return same string
Definition SLAPrint.cpp:29
void set_status(int percent, const std::string &message, unsigned int flags=SlicingStatus::DEFAULT)
Definition PrintBase.hpp:492
void active_step_add_warning(PrintStateBase::WarningLevel warning_level, const std::string &message, int message_id=0)
Definition PrintBase.hpp:610
bool set_started(PrintStepEnum step)
Definition PrintBase.hpp:588
PrintStateBase::TimeStamp set_done(PrintStepEnum step)
Definition PrintBase.hpp:589
std::vector< SupportPoint > SupportPoints
Definition SupportSpotsGenerator.hpp:129
std::vector< std::pair< SupportPointCause, bool > > gather_issues(const SupportPoints &support_points, PartialObjects &partial_objects)
Definition SupportSpotsGenerator.cpp:1234
SupportPointCause
Definition SupportSpotsGenerator.hpp:81
std::vector< PartialObject > PartialObjects
Definition SupportSpotsGenerator.hpp:146
@ psAlertWhenSupportsNeeded
Definition Print.hpp:59
std::string format(const char *fmt, TArgs &&... args)
Definition format.hpp:44
#define L(s)
Definition I18N.hpp:18
static char error[256]
Definition tga.cpp:50

References _u8L, Slic3r::PrintBaseWithState< PrintStep, psCount >::active_step_add_warning(), error, Slic3r::SupportSpotsGenerator::FloatingBridgeAnchor, Slic3r::SupportSpotsGenerator::FloatingExtrusion, Slic3r::format(), Slic3r::SupportSpotsGenerator::gather_issues(), L, Slic3r::SupportSpotsGenerator::LongBridge, m_objects, Slic3r::PrintStateBase::NON_CRITICAL, Slic3r::psAlertWhenSupportsNeeded, Slic3r::SupportSpotsGenerator::SeparationFromBed, Slic3r::PrintBaseWithState< PrintStep, psCount >::set_done(), Slic3r::PrintBaseWithState< PrintStep, psCount >::set_started(), Slic3r::PrintBase::set_status(), Slic3r::SupportSpotsGenerator::UnstableFloatingPart, and Slic3r::SupportSpotsGenerator::WeakObjectPart.

Referenced by process().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ apply()

Print::ApplyStatus Slic3r::Print::apply ( const Model model,
DynamicPrintConfig  config 
)
overridevirtual

Implements Slic3r::PrintBase.

966{
967#ifdef _DEBUG
969#endif /* _DEBUG */
970
971 // Normalize the config.
972 new_full_config.option("print_settings_id", true);
973 new_full_config.option("filament_settings_id", true);
974 new_full_config.option("printer_settings_id", true);
975 new_full_config.option("physical_printer_settings_id", true);
976 new_full_config.normalize_fdm();
977
978 // Find modified keys of the various configs. Resolve overrides extruder retract values by filament profiles.
979 DynamicPrintConfig filament_overrides;
980 t_config_option_keys print_diff = print_config_diffs(m_config, new_full_config, filament_overrides);
981 t_config_option_keys full_config_diff = full_print_config_diffs(m_full_print_config, new_full_config);
982 // If just a physical printer was changed, but printer preset is the same, then there is no need to apply whole print
983 // see https://github.com/prusa3d/PrusaSlicer/issues/8800
984 if (full_config_diff.size() == 1 && full_config_diff[0] == "physical_printer_settings_id")
985 full_config_diff.clear();
986
987 // Collect changes to object and region configs.
988 t_config_option_keys object_diff = m_default_object_config.diff(new_full_config);
989 t_config_option_keys region_diff = m_default_region_config.diff(new_full_config);
990
991 // Do not use the ApplyStatus as we will use the max function when updating apply_status.
992 unsigned int apply_status = APPLY_STATUS_UNCHANGED;
993 auto update_apply_status = [&apply_status](bool invalidated)
994 { apply_status = std::max<unsigned int>(apply_status, invalidated ? APPLY_STATUS_INVALIDATED : APPLY_STATUS_CHANGED); };
995 if (! (print_diff.empty() && object_diff.empty() && region_diff.empty()))
996 update_apply_status(false);
997
998 // Grab the lock for the Print / PrintObject milestones.
999 std::scoped_lock<std::mutex> lock(this->state_mutex());
1000
1001 // The following call may stop the background processing.
1002 if (! print_diff.empty())
1003 update_apply_status(this->invalidate_state_by_config_options(new_full_config, print_diff));
1004
1005 // Apply variables to placeholder parser. The placeholder parser is used by G-code export,
1006 // which should be stopped if print_diff is not empty.
1007 size_t num_extruders = m_config.nozzle_diameter.size();
1008 bool num_extruders_changed = false;
1009 if (! full_config_diff.empty()) {
1010 update_apply_status(this->invalidate_step(psGCodeExport));
1012 // Set the profile aliases for the PrintBase::output_filename()
1013 m_placeholder_parser.set("print_preset", new_full_config.option("print_settings_id")->clone());
1014 m_placeholder_parser.set("filament_preset", new_full_config.option("filament_settings_id")->clone());
1015 m_placeholder_parser.set("printer_preset", new_full_config.option("printer_settings_id")->clone());
1016 m_placeholder_parser.set("physical_printer_preset", new_full_config.option("physical_printer_settings_id")->clone());
1017 // We want the filament overrides to be applied over their respective extruder parameters by the PlaceholderParser.
1018 // see "Placeholders do not respect filament overrides." GH issue #3649
1019 m_placeholder_parser.apply_config(filament_overrides);
1020 // It is also safe to change m_config now after this->invalidate_state_by_config_options() call.
1021 m_config.apply_only(new_full_config, print_diff, true);
1022 //FIXME use move semantics once ConfigBase supports it.
1023 // Some filament_overrides may contain values different from new_full_config, but equal to m_config.
1024 // As long as these config options don't reallocate memory when copying, we are safe overriding a value, which is in use by a worker thread.
1025 m_config.apply(filament_overrides);
1026 // Handle changes to object config defaults
1027 m_default_object_config.apply_only(new_full_config, object_diff, true);
1028 // Handle changes to regions config defaults
1029 m_default_region_config.apply_only(new_full_config, region_diff, true);
1030 m_full_print_config = std::move(new_full_config);
1031 if (num_extruders != m_config.nozzle_diameter.size()) {
1032 num_extruders = m_config.nozzle_diameter.size();
1033 num_extruders_changed = true;
1034 }
1035 }
1036
1037 ModelObjectStatusDB model_object_status_db;
1038
1039 // 1) Synchronize model objects.
1040 bool print_regions_reshuffled = false;
1041 if (model.id() != m_model.id()) {
1042 // Kill everything, initialize from scratch.
1043 // Stop background processing.
1044 this->call_cancel_callback();
1045 update_apply_status(this->invalidate_all_steps());
1046 for (PrintObject *object : m_objects) {
1047 model_object_status_db.add(*object->model_object(), ModelObjectStatus::Deleted);
1048 update_apply_status(object->invalidate_all_steps());
1049 delete object;
1050 }
1051 m_objects.clear();
1052 print_regions_reshuffled = true;
1053 m_model.assign_copy(model);
1054 for (const ModelObject *model_object : m_model.objects)
1055 model_object_status_db.add(*model_object, ModelObjectStatus::New);
1056 } else {
1058 update_apply_status(num_extruders_changed ||
1059 // Tool change G-codes are applied as color changes for a single extruder printer, no need to invalidate tool ordering.
1060 //FIXME The tool ordering may be invalidated unnecessarily if the custom_gcode_per_print_z.mode is not applicable
1061 // to the active print / model state, and then it is reset, so it is being applicable, but empty, thus the effect is the same.
1063 // The Tool Ordering and the Wipe Tower are no more valid.
1064 this->invalidate_steps({ psWipeTower, psGCodeExport }) :
1065 // There is no change in Tool Changes stored in custom_gcode_per_print_z, therefore there is no need to update Tool Ordering.
1068 }
1070 // The object list did not change.
1071 for (const ModelObject *model_object : m_model.objects)
1072 model_object_status_db.add(*model_object, ModelObjectStatus::Old);
1074 // Add new objects. Their volumes and configs will be synchronized later.
1075 update_apply_status(this->invalidate_step(psGCodeExport));
1076 for (const ModelObject *model_object : m_model.objects)
1077 model_object_status_db.add(*model_object, ModelObjectStatus::Old);
1078 for (size_t i = m_model.objects.size(); i < model.objects.size(); ++ i) {
1079 model_object_status_db.add(*model.objects[i], ModelObjectStatus::New);
1080 m_model.objects.emplace_back(ModelObject::new_copy(*model.objects[i]));
1081 m_model.objects.back()->set_model(&m_model);
1082 }
1083 } else {
1084 // Reorder the objects, add new objects.
1085 // First stop background processing before shuffling or deleting the PrintObjects in the object list.
1086 this->call_cancel_callback();
1087 update_apply_status(this->invalidate_step(psGCodeExport));
1088 // Second create a new list of objects.
1089 std::vector<ModelObject*> model_objects_old(std::move(m_model.objects));
1090 m_model.objects.clear();
1091 m_model.objects.reserve(model.objects.size());
1092 auto by_id_lower = [](const ModelObject *lhs, const ModelObject *rhs){ return lhs->id() < rhs->id(); };
1093 std::sort(model_objects_old.begin(), model_objects_old.end(), by_id_lower);
1094 for (const ModelObject *mobj : model.objects) {
1095 auto it = std::lower_bound(model_objects_old.begin(), model_objects_old.end(), mobj, by_id_lower);
1096 if (it == model_objects_old.end() || (*it)->id() != mobj->id()) {
1097 // New ModelObject added.
1098 m_model.objects.emplace_back(ModelObject::new_copy(*mobj));
1099 m_model.objects.back()->set_model(&m_model);
1100 model_object_status_db.add(*mobj, ModelObjectStatus::New);
1101 } else {
1102 // Existing ModelObject re-added (possibly moved in the list).
1103 m_model.objects.emplace_back(*it);
1104 model_object_status_db.add(*mobj, ModelObjectStatus::Moved);
1105 }
1106 }
1107 bool deleted_any = false;
1108 for (ModelObject *&model_object : model_objects_old)
1109 if (model_object_status_db.add_if_new(*model_object, ModelObjectStatus::Deleted))
1110 deleted_any = true;
1111 else
1112 // Do not delete this ModelObject instance.
1113 model_object = nullptr;
1114 if (deleted_any) {
1115 // Delete PrintObjects of the deleted ModelObjects.
1116 PrintObjectPtrs print_objects_old = std::move(m_objects);
1117 m_objects.clear();
1118 m_objects.reserve(print_objects_old.size());
1119 for (PrintObject *print_object : print_objects_old) {
1120 const ModelObjectStatus &status = model_object_status_db.get(*print_object->model_object());
1121 if (status.status == ModelObjectStatus::Deleted) {
1122 update_apply_status(print_object->invalidate_all_steps());
1123 delete print_object;
1124 } else
1125 m_objects.emplace_back(print_object);
1126 }
1127 for (ModelObject *model_object : model_objects_old)
1128 delete model_object;
1129 print_regions_reshuffled = true;
1130 }
1131 }
1132 }
1133
1134 // 2) Map print objects including their transformation matrices.
1135 PrintObjectStatusDB print_object_status_db(m_objects);
1136
1137 // 3) Synchronize ModelObjects & PrintObjects.
1138 const std::initializer_list<ModelVolumeType> solid_or_modifier_types { ModelVolumeType::MODEL_PART, ModelVolumeType::NEGATIVE_VOLUME, ModelVolumeType::PARAMETER_MODIFIER };
1139 for (size_t idx_model_object = 0; idx_model_object < model.objects.size(); ++ idx_model_object) {
1140 ModelObject &model_object = *m_model.objects[idx_model_object];
1141 ModelObjectStatus &model_object_status = const_cast<ModelObjectStatus&>(model_object_status_db.reuse(model_object));
1142 const ModelObject &model_object_new = *model.objects[idx_model_object];
1143 if (model_object_status.status == ModelObjectStatus::New)
1144 // PrintObject instances will be added in the next loop.
1145 continue;
1146 // Update the ModelObject instance, possibly invalidate the linked PrintObjects.
1147 assert(model_object_status.status == ModelObjectStatus::Old || model_object_status.status == ModelObjectStatus::Moved);
1148 // Check whether a model part volume was added or removed, their transformations or order changed.
1149 // Only volume IDs, volume types, transformation matrices and their order are checked, configuration and other parameters are NOT checked.
1150 bool solid_or_modifier_differ = model_volume_list_changed(model_object, model_object_new, solid_or_modifier_types) ||
1151 model_mmu_segmentation_data_changed(model_object, model_object_new) ||
1152 (model_object_new.is_mm_painted() && num_extruders_changed);
1153 bool supports_differ = model_volume_list_changed(model_object, model_object_new, ModelVolumeType::SUPPORT_BLOCKER) ||
1154 model_volume_list_changed(model_object, model_object_new, ModelVolumeType::SUPPORT_ENFORCER);
1155 bool layer_height_ranges_differ = ! layer_height_ranges_equal(model_object.layer_config_ranges, model_object_new.layer_config_ranges, model_object_new.layer_height_profile.empty());
1156 bool model_origin_translation_differ = model_object.origin_translation != model_object_new.origin_translation;
1157 auto print_objects_range = print_object_status_db.get_range(model_object);
1158 // The list actually can be empty if all instances are out of the print bed.
1159 //assert(print_objects_range.begin() != print_objects_range.end());
1160 // All PrintObjects in print_objects_range shall point to the same prints_objects_regions
1161 if (print_objects_range.begin() != print_objects_range.end()) {
1162 model_object_status.print_object_regions = print_objects_range.begin()->print_object->m_shared_regions;
1163 model_object_status.print_object_regions->ref_cnt_inc();
1164 }
1165 if (solid_or_modifier_differ || model_origin_translation_differ || layer_height_ranges_differ ||
1166 ! model_object.layer_height_profile.timestamp_matches(model_object_new.layer_height_profile)) {
1167 // The very first step (the slicing step) is invalidated. One may freely remove all associated PrintObjects.
1168 model_object_status.print_object_regions_status =
1169 model_object_status.print_object_regions == nullptr || model_origin_translation_differ || layer_height_ranges_differ ?
1170 // Drop print_objects_regions.
1172 // Reuse bounding boxes of print_objects_regions for ModelVolumes with unmodified transformation.
1174 for (const PrintObjectStatus &print_object_status : print_objects_range) {
1175 update_apply_status(print_object_status.print_object->invalidate_all_steps());
1176 const_cast<PrintObjectStatus&>(print_object_status).status = PrintObjectStatus::Deleted;
1177 }
1178 if (model_object_status.print_object_regions_status == ModelObjectStatus::PrintObjectRegionsStatus::PartiallyValid)
1179 // Drop everything from PrintObjectRegions but those VolumeExtents (of their particular ModelVolumes) that are still valid.
1180 print_objects_regions_invalidate_keep_some_volumes(*model_object_status.print_object_regions, model_object.volumes, model_object_new.volumes);
1181 else if (model_object_status.print_object_regions != nullptr)
1182 model_object_status.print_object_regions->clear();
1183 // Copy content of the ModelObject including its ID, do not change the parent.
1184 model_object.assign_copy(model_object_new);
1185 } else {
1186 model_object_status.print_object_regions_status = ModelObjectStatus::PrintObjectRegionsStatus::Valid;
1187 if (supports_differ || model_custom_supports_data_changed(model_object, model_object_new)) {
1188 // First stop background processing before shuffling or deleting the ModelVolumes in the ModelObject's list.
1189 if (supports_differ) {
1190 this->call_cancel_callback();
1191 update_apply_status(false);
1192 }
1193 // Invalidate just the supports step.
1194 for (const PrintObjectStatus &print_object_status : print_objects_range) {
1195 update_apply_status(print_object_status.print_object->invalidate_step(posSupportMaterial));
1196 }
1197 if (supports_differ) {
1198 // Copy just the support volumes.
1199 model_volume_list_update_supports(model_object, model_object_new);
1200 }
1201 } else if (model_custom_seam_data_changed(model_object, model_object_new)) {
1202 update_apply_status(this->invalidate_step(psGCodeExport));
1203 }
1204 }
1205 if (! solid_or_modifier_differ) {
1206 // Synchronize Object's config.
1207 bool object_config_changed = ! model_object.config.timestamp_matches(model_object_new.config);
1208 if (object_config_changed)
1209 model_object.config.assign_config(model_object_new.config);
1210 if (! object_diff.empty() || object_config_changed || num_extruders_changed) {
1212 for (const PrintObjectStatus &print_object_status : print_object_status_db.get_range(model_object)) {
1213 t_config_option_keys diff = print_object_status.print_object->config().diff(new_config);
1214 if (! diff.empty()) {
1215 update_apply_status(print_object_status.print_object->invalidate_state_by_config_options(print_object_status.print_object->config(), new_config, diff));
1216 print_object_status.print_object->config_apply_only(new_config, diff, true);
1217 }
1218 }
1219 }
1220 // Synchronize (just copy) the remaining data of ModelVolumes (name, config, custom supports data).
1221 //FIXME What to do with m_material_id?
1222 model_volume_list_copy_configs(model_object /* dst */, model_object_new /* src */, ModelVolumeType::MODEL_PART);
1223 model_volume_list_copy_configs(model_object /* dst */, model_object_new /* src */, ModelVolumeType::PARAMETER_MODIFIER);
1224 layer_height_ranges_copy_configs(model_object.layer_config_ranges /* dst */, model_object_new.layer_config_ranges /* src */);
1225 // Copy the ModelObject name, input_file and instances. The instances will be compared against PrintObject instances in the next step.
1226 model_object.name = model_object_new.name;
1227 model_object.input_file = model_object_new.input_file;
1228 // Only refresh ModelInstances if there is any change.
1229 if (model_object.instances.size() != model_object_new.instances.size() ||
1230 ! std::equal(model_object.instances.begin(), model_object.instances.end(), model_object_new.instances.begin(), [](auto l, auto r){ return l->id() == r->id(); })) {
1231 // G-code generator accesses model_object.instances to generate sequential print ordering matching the Plater object list.
1232 update_apply_status(this->invalidate_step(psGCodeExport));
1233 model_object.clear_instances();
1234 model_object.instances.reserve(model_object_new.instances.size());
1235 for (const ModelInstance *model_instance : model_object_new.instances) {
1236 model_object.instances.emplace_back(new ModelInstance(*model_instance));
1237 model_object.instances.back()->set_model_object(&model_object);
1238 }
1239 } else if (! std::equal(model_object.instances.begin(), model_object.instances.end(), model_object_new.instances.begin(),
1240 [](auto l, auto r){ return l->print_volume_state == r->print_volume_state && l->printable == r->printable &&
1241 l->get_transformation().get_matrix().isApprox(r->get_transformation().get_matrix()); })) {
1242 // If some of the instances changed, the bounding box of the updated ModelObject is likely no more valid.
1243 // This is safe as the ModelObject's bounding box is only accessed from this function, which is called from the main thread only.
1244 // Synchronize the content of instances.
1245 auto new_instance = model_object_new.instances.begin();
1246 for (auto old_instance = model_object.instances.begin(); old_instance != model_object.instances.end(); ++ old_instance, ++ new_instance) {
1247 (*old_instance)->set_transformation((*new_instance)->get_transformation());
1248 (*old_instance)->print_volume_state = (*new_instance)->print_volume_state;
1249 (*old_instance)->printable = (*new_instance)->printable;
1250 }
1251 }
1252 // Source / dest object share the same bounding boxes, just copy them.
1253 model_object.copy_transformation_caches(model_object_new);
1254 }
1255 }
1256
1257 // 4) Generate PrintObjects from ModelObjects and their instances.
1258 {
1259 PrintObjectPtrs print_objects_new;
1260 print_objects_new.reserve(std::max(m_objects.size(), m_model.objects.size()));
1261 bool new_objects = false;
1262 // Walk over all new model objects and check, whether there are matching PrintObjects.
1263 for (ModelObject *model_object : m_model.objects) {
1264 ModelObjectStatus &model_object_status = const_cast<ModelObjectStatus&>(model_object_status_db.reuse(*model_object));
1265 model_object_status.print_instances = print_objects_from_model_object(*model_object);
1266 std::vector<const PrintObjectStatus*> old;
1267 old.reserve(print_object_status_db.count(*model_object));
1268 for (const PrintObjectStatus &print_object_status : print_object_status_db.get_range(*model_object))
1269 if (print_object_status.status != PrintObjectStatus::Deleted)
1270 old.emplace_back(&print_object_status);
1271 // Generate a list of trafos and XY offsets for instances of a ModelObject
1272 // Producing the config for PrintObject on demand, caching it at print_object_last.
1273 const PrintObject *print_object_last = nullptr;
1274 auto print_object_apply_config = [this, &print_object_last, model_object, num_extruders](PrintObject *print_object) {
1275 print_object->config_apply(print_object_last ?
1276 print_object_last->config() :
1278 print_object_last = print_object;
1279 };
1280 if (old.empty()) {
1281 // Simple case, just generate new instances.
1282 for (PrintObjectTrafoAndInstances &print_instances : model_object_status.print_instances) {
1283 PrintObject *print_object = new PrintObject(this, model_object, print_instances.trafo, std::move(print_instances.instances));
1284 print_object_apply_config(print_object);
1285 print_objects_new.emplace_back(print_object);
1286 // print_object_status.emplace(PrintObjectStatus(print_object, PrintObjectStatus::New));
1287 new_objects = true;
1288 }
1289 continue;
1290 }
1291 // Complex case, try to merge the two lists.
1292 // Sort the old lexicographically by their trafos.
1293 std::sort(old.begin(), old.end(), [](const PrintObjectStatus *lhs, const PrintObjectStatus *rhs){ return transform3d_lower(lhs->trafo, rhs->trafo); });
1294 // Merge the old / new lists.
1295 auto it_old = old.begin();
1296 for (PrintObjectTrafoAndInstances &new_instances : model_object_status.print_instances) {
1297 for (; it_old != old.end() && transform3d_lower((*it_old)->trafo, new_instances.trafo); ++ it_old);
1298 if (it_old == old.end() || ! transform3d_equal((*it_old)->trafo, new_instances.trafo)) {
1299 // This is a new instance (or a set of instances with the same trafo). Just add it.
1300 PrintObject *print_object = new PrintObject(this, model_object, new_instances.trafo, std::move(new_instances.instances));
1301 print_object_apply_config(print_object);
1302 print_objects_new.emplace_back(print_object);
1303 // print_object_status.emplace(PrintObjectStatus(print_object, PrintObjectStatus::New));
1304 new_objects = true;
1305 if (it_old != old.end())
1306 const_cast<PrintObjectStatus*>(*it_old)->status = PrintObjectStatus::Deleted;
1307 } else {
1308 // The PrintObject already exists and the copies differ.
1309 PrintBase::ApplyStatus status = (*it_old)->print_object->set_instances(std::move(new_instances.instances));
1311 update_apply_status(status == PrintBase::APPLY_STATUS_INVALIDATED);
1312 print_objects_new.emplace_back((*it_old)->print_object);
1313 const_cast<PrintObjectStatus*>(*it_old)->status = PrintObjectStatus::Reused;
1314 }
1315 }
1316 }
1317 if (m_objects != print_objects_new) {
1318 this->call_cancel_callback();
1319 update_apply_status(this->invalidate_all_steps());
1320 m_objects = print_objects_new;
1321 // Delete the PrintObjects marked as Unknown or Deleted.
1322 bool deleted_objects = false;
1323 for (const PrintObjectStatus &pos : print_object_status_db)
1324 if (pos.status == PrintObjectStatus::Unknown || pos.status == PrintObjectStatus::Deleted) {
1325 update_apply_status(pos.print_object->invalidate_all_steps());
1326 delete pos.print_object;
1327 deleted_objects = true;
1328 }
1329 if (new_objects || deleted_objects)
1331 if (new_objects)
1332 update_apply_status(false);
1333 print_regions_reshuffled = true;
1334 }
1335 print_object_status_db.clear();
1336 }
1337
1338 // All regions now have distinct settings.
1339 // Check whether applying the new region config defaults we would get different regions,
1340 // update regions or create regions from scratch.
1341 for (auto it_print_object = m_objects.begin(); it_print_object != m_objects.end();) {
1342 // Find the range of PrintObjects sharing the same associated ModelObject.
1343 auto it_print_object_end = it_print_object;
1344 PrintObject &print_object = *(*it_print_object);
1345 const ModelObject &model_object = *print_object.model_object();
1346 ModelObjectStatus &model_object_status = const_cast<ModelObjectStatus&>(model_object_status_db.reuse(model_object));
1347 PrintObjectRegions *print_object_regions = model_object_status.print_object_regions;
1348 for (++ it_print_object_end; it_print_object_end != m_objects.end() && (*it_print_object)->model_object() == (*it_print_object_end)->model_object(); ++ it_print_object_end)
1349 assert((*it_print_object_end)->m_shared_regions == nullptr || (*it_print_object_end)->m_shared_regions == print_object_regions);
1350 if (print_object_regions == nullptr) {
1351 print_object_regions = new PrintObjectRegions{};
1352 model_object_status.print_object_regions = print_object_regions;
1353 print_object_regions->ref_cnt_inc();
1354 }
1355 std::vector<unsigned int> painting_extruders;
1356 if (const auto &volumes = print_object.model_object()->volumes;
1357 num_extruders > 1 &&
1358 std::find_if(volumes.begin(), volumes.end(), [](const ModelVolume *v) { return ! v->mmu_segmentation_facets.empty(); }) != volumes.end()) {
1359 //FIXME be more specific! Don't enumerate extruders that are not used for painting!
1360 painting_extruders.assign(num_extruders, 0);
1361 std::iota(painting_extruders.begin(), painting_extruders.end(), 1);
1362 }
1363 if (model_object_status.print_object_regions_status == ModelObjectStatus::PrintObjectRegionsStatus::Valid) {
1364 // Verify that the trafo for regions & volume bounding boxes thus for regions is still applicable.
1365 auto invalidate = [it_print_object, it_print_object_end, update_apply_status]() {
1366 for (auto it = it_print_object; it != it_print_object_end; ++ it)
1367 if ((*it)->m_shared_regions != nullptr)
1368 update_apply_status((*it)->invalidate_all_steps());
1369 };
1370 if (print_object_regions && ! trafos_differ_in_rotation_by_z_and_mirroring_by_xy_only(print_object_regions->trafo_bboxes, model_object_status.print_instances.front().trafo)) {
1371 invalidate();
1372 print_object_regions->clear();
1373 model_object_status.print_object_regions_status = ModelObjectStatus::PrintObjectRegionsStatus::Invalid;
1374 print_regions_reshuffled = true;
1375 } else if (print_object_regions &&
1377 print_object.model_object()->volumes,
1379 num_extruders,
1380 painting_extruders,
1381 *print_object_regions,
1382 [it_print_object, it_print_object_end, &update_apply_status](const PrintRegionConfig &old_config, const PrintRegionConfig &new_config, const t_config_option_keys &diff_keys) {
1383 for (auto it = it_print_object; it != it_print_object_end; ++it)
1384 if ((*it)->m_shared_regions != nullptr)
1385 update_apply_status((*it)->invalidate_state_by_config_options(old_config, new_config, diff_keys));
1386 })) {
1387 // Regions are valid, just keep them.
1388 } else {
1389 // Regions were reshuffled.
1390 invalidate();
1391 // At least reuse layer ranges and bounding boxes of ModelVolumes.
1392 model_object_status.print_object_regions_status = ModelObjectStatus::PrintObjectRegionsStatus::PartiallyValid;
1393 print_regions_reshuffled = true;
1394 }
1395 }
1396 if (print_object_regions == nullptr || model_object_status.print_object_regions_status != ModelObjectStatus::PrintObjectRegionsStatus::Valid) {
1397 // Layer ranges with their associated configurations. Remove overlaps between the ranges
1398 // and create the regions from scratch.
1399 print_object_regions = generate_print_object_regions(
1400 print_object_regions,
1401 print_object.model_object()->volumes,
1402 LayerRanges(print_object.model_object()->layer_config_ranges),
1404 model_object_status.print_instances.front().trafo,
1405 num_extruders,
1406 print_object.is_mm_painted() ? 0.f : float(print_object.config().xy_size_compensation.value),
1407 painting_extruders);
1408 }
1409 for (auto it = it_print_object; it != it_print_object_end; ++it)
1410 if ((*it)->m_shared_regions) {
1411 assert((*it)->m_shared_regions == print_object_regions);
1412 } else {
1413 (*it)->m_shared_regions = print_object_regions;
1414 print_object_regions->ref_cnt_inc();
1415 }
1416 it_print_object = it_print_object_end;
1417 }
1418
1419 if (print_regions_reshuffled) {
1420 // Update Print::m_print_regions from objects.
1421 struct cmp { bool operator() (const PrintRegion *l, const PrintRegion *r) const { return l->config_hash() == r->config_hash() && l->config() == r->config(); } };
1422 std::set<const PrintRegion*, cmp> region_set;
1423 m_print_regions.clear();
1424 PrintObjectRegions *print_object_regions = nullptr;
1425 for (PrintObject *print_object : m_objects)
1426 if (print_object_regions != print_object->m_shared_regions) {
1427 print_object_regions = print_object->m_shared_regions;
1428 for (std::unique_ptr<Slic3r::PrintRegion> &print_region : print_object_regions->all_regions)
1429 if (auto it = region_set.find(print_region.get()); it == region_set.end()) {
1430 int print_region_id = int(m_print_regions.size());
1431 m_print_regions.emplace_back(print_region.get());
1432 print_region->m_print_region_id = print_region_id;
1433 } else {
1434 print_region->m_print_region_id = (*it)->print_region_id();
1435 }
1436 }
1437 }
1438
1439 // Update SlicingParameters for each object where the SlicingParameters is not valid.
1440 // If it is not valid, then it is ensured that PrintObject.m_slicing_params is not in use
1441 // (posSlicing and posSupportMaterial was invalidated).
1442 for (PrintObject *object : m_objects)
1443 object->update_slicing_parameters();
1444
1445 if (apply_status == APPLY_STATUS_CHANGED || apply_status == APPLY_STATUS_INVALIDATED)
1446 this->cleanup();
1447
1448#ifdef _DEBUG
1450#endif /* _DEBUG */
1451
1452 return static_cast<ApplyStatus>(apply_status);
1453}
ModelObjectPtrs objects
Definition Model.hpp:1254
CustomGCode::Info custom_gcode_per_print_z
Definition Model.hpp:1259
ObjectID id() const
Definition ObjectID.hpp:55
bool apply_config(const DynamicPrintConfig &config)
Definition PlaceholderParser.cpp:124
void set(const std::string &key, const std::string &value)
Definition PlaceholderParser.hpp:44
void clear_config()
Definition PlaceholderParser.hpp:31
void call_cancel_callback()
Definition PrintBase.hpp:536
ApplyStatus
Definition PrintBase.hpp:423
const Model & model() const
Definition PrintBase.hpp:433
DynamicPrintConfig m_full_print_config
Definition PrintBase.hpp:554
Model m_model
Definition PrintBase.hpp:553
PlaceholderParser m_placeholder_parser
Definition PrintBase.hpp:555
bool invalidate_all_steps()
Definition PrintBase.hpp:602
bool invalidate_steps(StepTypeIterator step_begin, StepTypeIterator step_end)
Definition PrintBase.hpp:598
void cleanup() override
Definition PrintApply.cpp:1455
PrintRegionConfig m_default_region_config
Definition Print.hpp:674
bool invalidate_step(PrintStep step)
Definition Print.cpp:258
PrintRegionPtrs m_print_regions
Definition Print.hpp:676
PrintObjectConfig m_default_object_config
Definition Print.hpp:673
SpanOfConstPtrs< PrintObject > objects() const
Definition Print.hpp:600
bool invalidate_state_by_config_options(const ConfigOptionResolver &new_config, const std::vector< t_config_option_key > &opt_keys)
Definition Print.cpp:52
static PrintObjectConfig object_config_from_model_object(const PrintObjectConfig &default_object_config, const ModelObject &object, size_t num_extruders)
Definition PrintObject.cpp:2462
if(!(yy_init))
Definition lexer.c:1190
Vec3d pos(const Pt &p)
Definition ReprojectPointsOnMesh.hpp:14
bool model_mmu_segmentation_data_changed(const ModelObject &mo, const ModelObject &mo_new)
Definition Model.cpp:2580
std::vector< PrintObject * > PrintObjectPtrs
Definition Print.hpp:533
static void layer_height_ranges_copy_configs(t_layer_config_ranges &lr_dst, const t_layer_config_ranges &lr_src)
Definition PrintApply.cpp:86
bool model_custom_seam_data_changed(const ModelObject &mo, const ModelObject &mo_new)
Definition Model.cpp:2573
void check_model_ids_validity(const Model &model)
Definition Model.cpp:2623
@ posSupportMaterial
Definition Print.hpp:70
bool model_object_list_extended(const Model &model_old, const Model &model_new)
Definition Model.cpp:2481
void check_model_ids_equal(const Model &model1, const Model &model2)
Definition Model.cpp:2647
PrintObjectConfig
Definition PrintConfig.hpp:840
static bool custom_per_printz_gcodes_tool_changes_differ(const std::vector< CustomGCode::Item > &va, const std::vector< CustomGCode::Item > &vb)
Definition PrintApply.cpp:169
void model_volume_list_update_supports(ModelObject &model_object_dst, const ModelObject &model_object_new)
Definition PrintApply.cpp:13
static bool layer_height_ranges_equal(const t_layer_config_ranges &lr1, const t_layer_config_ranges &lr2, bool check_layer_height)
Definition PrintApply.cpp:153
PrintRegionConfig
Definition PrintConfig.hpp:840
static bool transform3d_lower(const Transform3d &lhs, const Transform3d &rhs)
Definition PrintApply.cpp:100
std::vector< std::string > t_config_option_keys
Definition Config.hpp:77
static t_config_option_keys print_config_diffs(const PrintConfig &current_config, const DynamicPrintConfig &new_full_config, DynamicPrintConfig &filament_overrides)
Definition PrintApply.cpp:200
@ psWipeTower
Definition Print.hpp:54
@ psSkirtBrim
Definition Print.hpp:60
@ psGCodeExport
Definition Print.hpp:64
static bool transform3d_equal(const Transform3d &lhs, const Transform3d &rhs)
Definition PrintApply.cpp:114
static t_config_option_keys full_print_config_diffs(const DynamicPrintConfig &current_full_config, const DynamicPrintConfig &new_full_config)
Definition PrintApply.cpp:240
static std::vector< PrintObjectTrafoAndInstances > print_objects_from_model_object(const ModelObject &model_object)
Definition PrintApply.cpp:133
static bool trafos_differ_in_rotation_by_z_and_mirroring_by_xy_only(const Transform3d &t1, const Transform3d &t2)
Definition PrintApply.cpp:466
static PrintObjectRegions * generate_print_object_regions(PrintObjectRegions *print_object_regions_old, const ModelVolumePtrs &model_volumes, const LayerRanges &model_layer_ranges, const PrintRegionConfig &default_region_config, const Transform3d &trafo, size_t num_extruders, const float xy_size_compensation, const std::vector< unsigned int > &painting_extruders)
Definition PrintApply.cpp:844
bool model_volume_list_changed(const ModelObject &model_object_old, const ModelObject &model_object_new, TypeFilterFn type_filter)
Definition Model.cpp:2492
bool model_custom_supports_data_changed(const ModelObject &mo, const ModelObject &mo_new)
Definition Model.cpp:2566
static void model_volume_list_copy_configs(ModelObject &model_object_dst, const ModelObject &model_object_src, const ModelVolumeType type)
Definition PrintApply.cpp:55
void print_objects_regions_invalidate_keep_some_volumes(PrintObjectRegions &print_object_regions, ModelVolumePtrs old_volumes, ModelVolumePtrs new_volumes)
Definition PrintApply.cpp:577
bool verify_update_print_object_regions(ModelVolumePtrs model_volumes, const PrintRegionConfig &default_region_config, size_t num_extruders, const std::vector< unsigned int > &painting_extruders, PrintObjectRegions &print_object_regions, const std::function< void(const PrintRegionConfig &, const PrintRegionConfig &, const t_config_option_keys &)> &callback_invalidate)
Definition PrintApply.cpp:647
bool model_object_list_equal(const Model &model_old, const Model &model_new)
Definition Model.cpp:2469
Slic3r::Polygons diff(const Slic3r::Polygon &subject, const Slic3r::Polygon &clip, ApplySafetyOffset do_safety_offset)
Definition ClipperUtils.cpp:672
constexpr auto get(span< E, S > s) -> decltype(s[N])
Definition span.hpp:590
IGL_INLINE void find(const Eigen::SparseMatrix< T > &X, Eigen::DenseBase< DerivedI > &I, Eigen::DenseBase< DerivedJ > &J, Eigen::DenseBase< DerivedV > &V)
Definition find.cpp:18
std::vector< Item > gcodes
Definition CustomGCode.hpp:65
@ New
Definition PrintApply.cpp:323
@ Old
Definition PrintApply.cpp:322
@ Moved
Definition PrintApply.cpp:324
@ Deleted
Definition PrintApply.cpp:325
@ Deleted
Definition PrintApply.cpp:386
@ Reused
Definition PrintApply.cpp:387

References Slic3r::ModelObjectStatusDB::add(), Slic3r::ModelObjectStatusDB::add_if_new(), Slic3r::PrintObjectRegions::all_regions, Slic3r::ModelConfig::assign_config(), Slic3r::check_model_ids_equal(), Slic3r::check_model_ids_validity(), Slic3r::PrintObjectRegions::clear(), Slic3r::PrintObjectStatusDB::clear(), Slic3r::ModelObject::clear_instances(), Slic3r::ConfigOption::clone(), Slic3r::ModelObject::config, Slic3r::PrintRegion::config(), Slic3r::PrintObject::config(), Slic3r::PrintObject::config_apply(), Slic3r::PrintRegion::config_hash(), Slic3r::ModelObject::copy_transformation_caches(), Slic3r::PrintObjectStatusDB::count(), Slic3r::Model::custom_gcode_per_print_z, Slic3r::custom_per_printz_gcodes_tool_changes_differ(), Slic3r::diff(), Slic3r::LayerHeightProfile::empty(), Slic3r::full_print_config_diffs(), Slic3r::CustomGCode::Info::gcodes, Slic3r::generate_print_object_regions(), Slic3r::ModelObjectStatusDB::get(), Slic3r::PrintObjectStatusDB::get_range(), Slic3r::ObjectID::id, Slic3r::ObjectBase::id(), Slic3r::ModelObject::input_file, Slic3r::ModelObject::instances, Slic3r::ModelObject::is_mm_painted(), Slic3r::PrintObject::is_mm_painted(), Slic3r::ModelObject::layer_config_ranges, Slic3r::ModelObject::layer_height_profile, Slic3r::layer_height_ranges_copy_configs(), Slic3r::layer_height_ranges_equal(), Slic3r::model_custom_seam_data_changed(), Slic3r::model_custom_supports_data_changed(), Slic3r::model_mmu_segmentation_data_changed(), Slic3r::PrintObjectBase::model_object(), Slic3r::model_object_list_equal(), Slic3r::model_object_list_extended(), Slic3r::model_volume_list_changed(), Slic3r::model_volume_list_copy_configs(), Slic3r::model_volume_list_update_supports(), Slic3r::ModelObject::name, Slic3r::DynamicPrintConfig::normalize_fdm(), Slic3r::Model::objects, Slic3r::ConfigBase::option(), Slic3r::ModelObject::origin_translation, Slic3r::posSupportMaterial, Slic3r::print_config_diffs(), Slic3r::ModelObjectStatus::print_instances, Slic3r::ModelObjectStatus::print_object_regions, Slic3r::ModelObjectStatus::print_object_regions_status, Slic3r::print_objects_from_model_object(), Slic3r::print_objects_regions_invalidate_keep_some_volumes(), Slic3r::PrintObjectConfig, Slic3r::PrintRegionConfig, Slic3r::psAlertWhenSupportsNeeded, Slic3r::psGCodeExport, Slic3r::psSkirtBrim, Slic3r::psWipeTower, Slic3r::PrintObjectRegions::ref_cnt_inc(), Slic3r::ModelObjectStatusDB::reuse(), Slic3r::ModelObjectStatus::status, Slic3r::PrintObjectStatus::status, Slic3r::ModelConfig::timestamp_matches(), Slic3r::ObjectWithTimestamp::timestamp_matches(), Slic3r::PrintObjectRegions::trafo_bboxes, Slic3r::transform3d_equal(), Slic3r::transform3d_lower(), Slic3r::verify_update_print_object_regions(), and Slic3r::ModelObject::volumes.

+ Here is the call graph for this function:

◆ assign_new_unique_ids_recursive()

virtual void Slic3r::ObjectBase::assign_new_unique_ids_recursive ( )
inlineprotectedvirtualinherited

Reimplemented in Slic3r::Model, Slic3r::ModelObject, and Slic3r::ModelVolume.

79{ this->set_new_unique_id(); }
void set_new_unique_id()
Definition ObjectID.hpp:73

References Slic3r::ObjectBase::set_new_unique_id().

+ Here is the call graph for this function:

◆ auto_assign_extruders()

void Slic3r::Print::auto_assign_extruders ( ModelObject model_object) const
883{
884 // only assign extruders if object has more than one volume
885 if (model_object->volumes.size() < 2)
886 return;
887
888// size_t extruders = m_config.nozzle_diameter.values.size();
889 for (size_t volume_id = 0; volume_id < model_object->volumes.size(); ++ volume_id) {
890 ModelVolume *volume = model_object->volumes[volume_id];
891 //FIXME Vojtech: This assigns an extruder ID even to a modifier volume, if it has a material assigned.
892 if ((volume->is_model_part() || volume->is_modifier()) && ! volume->material_id().empty() && ! volume->config.has("extruder"))
893 volume->config.set("extruder", int(volume_id + 1));
894 }
895}
IGL_INLINE void volume(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedT > &T, Eigen::PlainObjectBase< Derivedvol > &vol)
Definition volume.cpp:15

References Slic3r::ModelObject::volumes.

Referenced by Slic3r::CLI::run().

+ Here is the caller graph for this function:

◆ brim()

const ExtrusionEntityCollection & Slic3r::Print::brim ( ) const
inline
624{ return m_brim; }
ExtrusionEntityCollection m_brim
Definition Print.hpp:680

References m_brim.

Referenced by Slic3r::GUI::GLCanvas3D::_load_print_toolpaths(), Slic3r::get_print_extrusions_extents(), and Slic3r::GCode::process_layer().

+ Here is the caller graph for this function:

◆ brim_flow()

Flow Slic3r::Print::brim_flow ( ) const
833{
834 ConfigOptionFloatOrPercent width = m_config.first_layer_extrusion_width;
835 if (width.value == 0)
836 width = m_print_regions.front()->config().perimeter_extrusion_width;
837 if (width.value == 0)
838 width = m_objects.front()->config().extrusion_width;
839
840 /* We currently use a random region's perimeter extruder.
841 While this works for most cases, we should probably consider all of the perimeter
842 extruders and take the one with, say, the smallest index.
843 The same logic should be applied to the code that selects the extruder during G-code
844 generation as well. */
847 width,
848 (float)m_config.nozzle_diameter.get_at(m_print_regions.front()->config().perimeter_extruder-1),
849 (float)this->skirt_first_layer_height());
850}
static Flow new_from_config_width(FlowRole role, const ConfigOptionFloatOrPercent &width, float nozzle_diameter, float height)
Definition Flow.cpp:115
coord_t width(const BoundingBox &box)
Definition Arrange.cpp:539
@ frPerimeter
Definition Flow.hpp:18

References Slic3r::frPerimeter, m_config, m_objects, m_print_regions, and Slic3r::Flow::new_from_config_width().

Referenced by Slic3r::make_brim(), and Slic3r::make_inner_brim().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ call_cancel_callback()

void Slic3r::PrintBase::call_cancel_callback ( )
inlineprotectedinherited
cancel_callback_type m_cancel_callback
Definition PrintBase.hpp:564

References Slic3r::PrintBase::m_cancel_callback.

Referenced by Slic3r::SLAPrint::apply(), and Slic3r::PrintBaseWithState< PrintStepEnumType, COUNT >::set_task_impl().

+ Here is the caller graph for this function:

◆ cancel()

void Slic3r::PrintBase::cancel ( )
inlineinherited
std::atomic< CancelStatus > m_cancel_status
Definition PrintBase.hpp:561

References Slic3r::PrintBase::CANCELED_BY_USER, and Slic3r::PrintBase::m_cancel_status.

Referenced by Slic3r::BackgroundSlicingProcess::stop().

+ Here is the caller graph for this function:

◆ cancel_callback()

std::function< void()> Slic3r::PrintBase::cancel_callback ( )
inlineprotectedinherited

◆ cancel_internal()

void Slic3r::PrintBase::cancel_internal ( )
inlineinherited

References Slic3r::PrintBase::CANCELED_INTERNAL, and Slic3r::PrintBase::m_cancel_status.

Referenced by Slic3r::BackgroundSlicingProcess::stop_internal().

+ Here is the caller graph for this function:

◆ cancel_status()

CancelStatus Slic3r::PrintBase::cancel_status ( ) const
inlineinherited
511{ return m_cancel_status.load(std::memory_order_acquire); }

References Slic3r::PrintBase::m_cancel_status.

Referenced by Slic3r::BackgroundSlicingProcess::thread_proc().

+ Here is the caller graph for this function:

◆ canceled()

◆ cleanup()

void Slic3r::Print::cleanup ( )
overridevirtual

Implements Slic3r::PrintBase.

1456{
1457 // Invalidate data of a single ModelObject shared by multiple PrintObjects.
1458 // Find spans of PrintObjects sharing the same PrintObjectRegions.
1459 std::vector<PrintObject*> all_objects(m_objects);
1460 std::sort(all_objects.begin(), all_objects.end(), [](const PrintObject *l, const PrintObject *r){ return l->shared_regions() < r->shared_regions(); } );
1461 for (auto it = all_objects.begin(); it != all_objects.end();) {
1462 PrintObjectRegions *shared_regions = (*it)->m_shared_regions;
1463 auto it_begin = it;
1464 for (; it != all_objects.end() && shared_regions == (*it)->shared_regions(); ++ it)
1465 // Let the PrintObject clean up its data with invalidated milestones.
1466 (*it)->cleanup();
1467 auto this_objects = SpanOfConstPtrs<PrintObject>(const_cast<const PrintObject* const* const>(&(*it_begin)), it - it_begin);
1469 shared_regions->generated_support_points.reset();
1470 }
1471}
static bool is_shared_print_object_step_valid_unguarded(SpanOfConstPtrs< PrintObject > print_objects, PrintObjectStep print_object_step)
Definition PrintApply.cpp:1473
#define const
Definition getopt.c:38
@ posSupportSpotsSearch
Definition Print.hpp:70

References const, Slic3r::PrintObjectRegions::generated_support_points, and Slic3r::posSupportSpotsSearch.

◆ clear()

void Slic3r::Print::clear ( )
overridevirtual

Implements Slic3r::PrintBase.

39{
40 std::scoped_lock<std::mutex> lock(this->state_mutex());
41 // The following call should stop background processing if it is running.
43 for (PrintObject *object : m_objects)
44 delete object;
45 m_objects.clear();
46 m_print_regions.clear();
48}
void clear_objects()
Definition Model.cpp:272

References Slic3r::Model::clear_objects(), Slic3r::PrintBaseWithState< PrintStep, psCount >::invalidate_all_steps(), Slic3r::PrintBase::m_model, m_objects, m_print_regions, and Slic3r::PrintBase::state_mutex().

Referenced by ~Print(), and validate().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ config()

const PrintConfig & Slic3r::Print::config ( ) const
inline
597{ return m_config; }

References m_config.

Referenced by Slic3r::FillLightning::Generator::Generator(), Slic3r::GUI::PlaterAfterLoadAutoArrange::PlaterAfterLoadAutoArrange(), Slic3r::ToolOrdering::ToolOrdering(), Slic3r::FFFTreeSupport::TreeSupportMeshGroupSettings::TreeSupportMeshGroupSettings(), Slic3r::GCode::_do_export(), Slic3r::GUI::GLCanvas3D::_load_print_toolpaths(), Slic3r::GUI::GLCanvas3D::_load_wipe_tower_toolpaths(), _make_skirt(), _make_wipe_tower(), Slic3r::GCode::_print_first_layer_bed_temperature(), Slic3r::GCode::_print_first_layer_extruder_temperatures(), Slic3r::FillAdaptive::adaptive_fill_line_spacing(), Slic3r::ToolOrdering::assign_custom_gcodes(), Slic3r::DoExport::autospeed_volumetric_limit(), Slic3r::LayerRegion::bridging_flow(), Slic3r::PrintRegion::collect_object_printing_extruders(), Slic3r::GUI::GLCanvas3D::do_rotate(), Slic3r::GUI::GLCanvas3D::do_scale(), Slic3r::WipingExtrusions::ensure_perimeters_infills_order(), extruders(), Slic3r::FFFTreeSupport::generate_overhangs(), Slic3r::get_default_perimeter_spacing(), Slic3r::GUI::get_skirt_offset(), Slic3r::get_wipe_tower_extrusions_extents(), Slic3r::DoExport::init_ooze_prevention(), Slic3r::GUI::GCodeViewer::load_shells(), Slic3r::make_brim(), Slic3r::make_inner_brim(), Slic3r::LayerRegion::make_perimeters(), Slic3r::Skirt::make_skirt_loops_per_extruder_other_layers(), Slic3r::WipingExtrusions::mark_wiping_extrusions(), Slic3r::mmu_segmentation_top_and_bottom_layers(), Slic3r::multi_material_segmentation_by_painting(), output_filename(), Slic3r::GCode::print_machine_envelope(), process(), Slic3r::GCode::process_layer(), Slic3r::GCode::process_layer_single_object(), sequential_print_horizontal_clearance_valid(), Slic3r::sequential_print_vertical_clearance_valid(), Slic3r::PrintObject::slice_volumes(), Slic3r::support_material_flow(), Slic3r::support_material_interface_flow(), validate(), and Slic3r::DoExport::validate_custom_gcode().

+ Here is the caller graph for this function:

◆ copy_id()

void Slic3r::ObjectBase::copy_id ( const ObjectBase rhs)
inlineprotectedinherited
76{ m_id = rhs.id(); }
ObjectID m_id
Definition ObjectID.hpp:82
size_t id
Definition ObjectID.hpp:37

References Slic3r::ObjectBase::id(), and Slic3r::ObjectBase::m_id.

Referenced by Slic3r::CutObjectBase::copy().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ default_object_config()

const PrintObjectConfig & Slic3r::Print::default_object_config ( ) const
inline

◆ default_region_config()

const PrintRegionConfig & Slic3r::Print::default_region_config ( ) const
inline

◆ empty()

bool Slic3r::Print::empty ( ) const
inlineoverridevirtual

Implements Slic3r::PrintBase.

558{ return m_objects.empty(); }

References m_objects.

Referenced by Slic3r::GUI::GLCanvas3D::_load_wipe_tower_toolpaths().

+ Here is the caller graph for this function:

◆ export_gcode()

std::string Slic3r::Print::export_gcode ( const std::string &  path_template,
GCodeProcessorResult result,
ThumbnailsGeneratorCallback  thumbnail_cb = nullptr 
)
985{
986 // output everything to a G-code file
987 // The following call may die if the output_filename_format template substitution fails.
988 std::string path = this->output_filepath(path_template);
989 std::string message;
990 if (!path.empty() && result == nullptr) {
991 // Only show the path if preview_data is not set -> running from command line.
992 message = _u8L("Exporting G-code");
993 message += " to ";
994 message += path;
995 } else
996 message = _u8L("Generating G-code");
997 this->set_status(90, message);
998
999 // Create GCode on heap, it has quite a lot of data.
1000 std::unique_ptr<GCode> gcode(new GCode);
1001 gcode->do_export(this, path.c_str(), result, thumbnail_cb);
1002
1003 if (m_conflict_result.has_value())
1004 result->conflict_result = *m_conflict_result;
1005
1006 return path.c_str();
1007}
std::string output_filepath(const std::string &path, const std::string &filename_base=std::string()) const
Definition PrintBase.cpp:84
ConflictResultOpt m_conflict_result
Definition Print.hpp:706
friend class GCode
Definition Print.hpp:700

References _u8L, Slic3r::GCodeProcessorResult::conflict_result, m_conflict_result, Slic3r::PrintBase::output_filepath(), and Slic3r::PrintBase::set_status().

Referenced by Slic3r::BackgroundSlicingProcess::process_fff(), and Slic3r::CLI::run().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ extruders()

std::vector< unsigned int > Slic3r::Print::extruders ( ) const
328{
329 std::vector<unsigned int> extruders = this->object_extruders();
330 append(extruders, this->support_material_extruders());
331 sort_remove_duplicates(extruders);
332
333 // The wipe tower extruder can also be set. When the wipe tower is enabled and it will be generated,
334 // append its extruder into the list too.
335 if (has_wipe_tower() && config().wipe_tower_extruder != 0 && extruders.size() > 1) {
336 assert(config().wipe_tower_extruder > 0 && config().wipe_tower_extruder < int(config().nozzle_diameter.size()));
337 extruders.emplace_back(config().wipe_tower_extruder - 1); // the config value is 1-based
339 }
340
341 return extruders;
342}
std::vector< unsigned int > support_material_extruders() const
Definition Print.cpp:293
std::vector< unsigned int > object_extruders() const
Definition Print.cpp:281
void sort_remove_duplicates(std::vector< T > &vec)
Definition libslic3r.h:188

References Slic3r::append(), config(), extruders(), has_wipe_tower(), object_extruders(), Slic3r::sort_remove_duplicates(), and support_material_extruders().

Referenced by Slic3r::GCode::_do_export(), _make_skirt(), Slic3r::GCode::_print_first_layer_extruder_temperatures(), extruders(), Slic3r::GUI::Preview::load_print_as_fff(), max_allowed_layer_height(), object_extruders(), support_material_extruders(), and validate().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ finalize()

void Slic3r::Print::finalize ( )
inlineoverridevirtual

Implements Slic3r::PrintBase.

void finalize_impl(std::vector< PrintObject * > &print_objects)
Definition PrintBase.hpp:714

References Slic3r::PrintBaseWithState< PrintStepEnumType, COUNT >::finalize_impl(), and m_objects.

+ Here is the call graph for this function:

◆ finalize_first_layer_convex_hull()

void Slic3r::Print::finalize_first_layer_convex_hull ( )
private
1205{
1208 // Neither skirt nor brim was extruded. Collect points of printed objects from 1st layer.
1209 for (Polygon &poly : this->first_layer_islands())
1210 append(m_first_layer_convex_hull.points, std::move(poly.points));
1211 }
1212 append(m_first_layer_convex_hull.points, this->first_layer_wipe_tower_corners());
1214}
bool empty() const
Definition MultiPoint.hpp:40
Polygons first_layer_islands() const
Definition Print.cpp:1153

References Slic3r::append(), Slic3r::Geometry::convex_hull(), Slic3r::MultiPoint::empty(), first_layer_islands(), m_first_layer_convex_hull, m_skirt_convex_hull, and Slic3r::MultiPoint::points.

Referenced by process().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ finalize_impl()

void Slic3r::PrintBaseWithState< PrintStep , COUNT >::finalize_impl ( std::vector< PrintObject * > &  print_objects)
inlineprotectedinherited
715 {
716 // Grab the lock for the Print / PrintObject milestones.
717 std::scoped_lock<std::mutex> lock(this->state_mutex());
718 for (auto *po : print_objects)
719 po->finalize_impl();
722 }
void mark_canceled_unguarded()
Definition PrintBase.hpp:308
void enable_all_unguarded(bool enable)
Definition PrintBase.hpp:154

◆ finished()

bool Slic3r::Print::finished ( ) const
inlineoverridevirtual

Implements Slic3r::PrintBase.

577{ return this->is_step_done(psGCodeExport); }
bool is_step_done(PrintStep step) const
Definition Print.hpp:573

References is_step_done(), and Slic3r::psGCodeExport.

Referenced by output_filename().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ first_layer_convex_hull()

const Polygon & Slic3r::Print::first_layer_convex_hull ( ) const
inline

References m_first_layer_convex_hull.

Referenced by Slic3r::GCode::_do_export().

+ Here is the caller graph for this function:

◆ first_layer_islands()

Polygons Slic3r::Print::first_layer_islands ( ) const
private
1154{
1155 Polygons islands;
1156 for (PrintObject *object : m_objects) {
1157 Polygons object_islands;
1158 for (ExPolygon &expoly : object->m_layers.front()->lslices)
1159 object_islands.push_back(expoly.contour);
1160 if (! object->support_layers().empty())
1161 object->support_layers().front()->support_fills.polygons_covered_by_spacing(object_islands, float(SCALED_EPSILON));
1162 islands.reserve(islands.size() + object_islands.size() * object->instances().size());
1163 for (const PrintInstance &instance : object->instances())
1164 for (Polygon &poly : object_islands) {
1165 islands.push_back(poly);
1166 islands.back().translate(instance.shift);
1167 }
1168 }
1169 return islands;
1170}
#define SCALED_EPSILON
Definition libslic3r.h:71
TPoint< P > front(const P &p)
Definition geometry_traits.hpp:872

References m_objects, and SCALED_EPSILON.

Referenced by finalize_first_layer_convex_hull(), and process().

+ Here is the caller graph for this function:

◆ first_layer_wipe_tower_corners()

Points Slic3r::Print::first_layer_wipe_tower_corners ( ) const
private
1173{
1174 Points pts_scaled;
1175
1176 if (has_wipe_tower() && ! m_wipe_tower_data.tool_changes.empty()) {
1177 double width = m_config.wipe_tower_width + 2*m_wipe_tower_data.brim_width;
1180
1181 // First the corners.
1182 std::vector<Vec2d> pts = { pt0,
1183 Vec2d(pt0.x()+width, pt0.y()),
1184 Vec2d(pt0.x()+width, pt0.y()+depth),
1185 Vec2d(pt0.x(),pt0.y()+depth)
1186 };
1187
1188 // Now the stabilization cone.
1189 Vec2d center = (pts[0] + pts[2])/2.;
1190 const auto [cone_R, cone_x_scale] = WipeTower::get_wipe_tower_cone_base(m_config.wipe_tower_width, m_wipe_tower_data.height, m_wipe_tower_data.depth, m_config.wipe_tower_cone_angle);
1191 double r = cone_R + m_wipe_tower_data.brim_width;
1192 for (double alpha = 0.; alpha<2*M_PI; alpha += M_PI/20.)
1193 pts.emplace_back(center + r*Vec2d(std::cos(alpha)/cone_x_scale, std::sin(alpha)));
1194
1195 for (Vec2d& pt : pts) {
1196 pt = Eigen::Rotation2Dd(Geometry::deg2rad(m_config.wipe_tower_rotation_angle.value)) * pt;
1197 pt += Vec2d(m_config.wipe_tower_x.value, m_config.wipe_tower_y.value);
1198 pts_scaled.emplace_back(Point(scale_(pt.x()), scale_(pt.y())));
1199 }
1200 }
1201 return pts_scaled;
1202}
#define M_PI
Definition ExtrusionSimulator.cpp:20
static std::pair< double, double > get_wipe_tower_cone_base(double width, double height, double depth, double angle_deg)
Definition WipeTower.cpp:1332
Rotation2D< double > Rotation2Dd
Definition Rotation2D.h:168
constexpr T deg2rad(const T angle)
Definition Geometry.hpp:289
Eigen::Matrix< double, 2, 1, Eigen::DontAlign > Vec2d
Definition Point.hpp:51

References Slic3r::WipeTowerData::brim_width, Slic3r::Geometry::deg2rad(), Slic3r::WipeTowerData::depth, Slic3r::WipeTower::get_wipe_tower_cone_base(), has_wipe_tower(), Slic3r::WipeTowerData::height, m_config, M_PI, m_wipe_tower_data, scale_, and Slic3r::WipeTowerData::tool_changes.

Referenced by _make_skirt().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ full_print_config()

◆ generate_new_id()

static ObjectID Slic3r::ObjectBase::generate_new_id ( )
inlinestaticprivateinherited
84{ return ObjectID(++ s_last_id); }
static size_t s_last_id
Definition ObjectID.hpp:85

References Slic3r::ObjectBase::s_last_id.

Referenced by Slic3r::ObjectBase::set_new_unique_id().

+ Here is the caller graph for this function:

◆ get_object() [1/3]

const PrintObject * Slic3r::Print::get_object ( ObjectID  object_id) const
inline
610 {
611 auto it = std::find_if(m_objects.begin(), m_objects.end(),
612 [object_id](const PrintObject *obj) { return obj->id() == object_id; });
613 return (it == m_objects.end()) ? nullptr : *it;
614 }

References m_objects.

◆ get_object() [2/3]

PrintObject * Slic3r::Print::get_object ( size_t  idx)
inline
601{ return const_cast<PrintObject*>(m_objects[idx]); }

References m_objects.

Referenced by Slic3r::FFFTreeSupport::generate_support_areas(), Slic3r::FFFTreeSupport::group_meshes(), Slic3r::GUI::Plater::priv::on_slicing_update(), and Slic3r::FFFTreeSupport::precalculate().

+ Here is the caller graph for this function:

◆ get_object() [3/3]

const PrintObject * Slic3r::Print::get_object ( size_t  idx) const
inline
602{ return m_objects[idx]; }

References m_objects.

◆ get_print_object_by_model_object_id()

const PrintObject * Slic3r::Print::get_print_object_by_model_object_id ( ObjectID  object_id) const
inline
603 {
604 auto it = std::find_if(m_objects.begin(), m_objects.end(),
605 [object_id](const PrintObject* obj) { return obj->model_object()->id() == object_id; });
606 return (it == m_objects.end()) ? nullptr : *it;
607 }

References m_objects.

Referenced by Slic3r::GUI::get_arrange_poly().

+ Here is the caller graph for this function:

◆ get_print_region()

const PrintRegion & Slic3r::Print::get_print_region ( size_t  idx) const
inline
643{ return *m_print_regions[idx]; }

References m_print_regions.

Referenced by Slic3r::GCode::_do_export(), and Slic3r::GCode::process_layer_single_object().

+ Here is the caller graph for this function:

◆ get_sequential_print_clearance_contours()

const Polygons & Slic3r::Print::get_sequential_print_clearance_contours ( ) const
inline
Polygons m_sequential_print_clearance_contours
Definition Print.hpp:697

References m_sequential_print_clearance_contours.

◆ get_tool_ordering()

const ToolOrdering & Slic3r::Print::get_tool_ordering ( ) const
inline

◆ has_brim()

bool Slic3r::Print::has_brim ( ) const
383{
384 return std::any_of(m_objects.begin(), m_objects.end(), [](PrintObject *object) { return object->has_brim(); });
385}

References m_objects.

Referenced by Slic3r::GUI::GLCanvas3D::_load_print_toolpaths(), Slic3r::PrintRegion::collect_object_printing_extruders(), process(), and Slic3r::GCode::process_layer().

+ Here is the caller graph for this function:

◆ has_infinite_skirt()

bool Slic3r::Print::has_infinite_skirt ( ) const
371{
372 return (m_config.draft_shield == dsEnabled && m_config.skirts > 0)/* || (m_config.ooze_prevention && this->extruders().size() > 1)*/;
373}
@ dsEnabled
Definition PrintConfig.hpp:125

References Slic3r::dsEnabled, and m_config.

Referenced by Slic3r::GUI::GLCanvas3D::_load_print_toolpaths(), _make_skirt(), has_skirt(), Slic3r::Skirt::make_skirt_loops_per_extruder_other_layers(), and Slic3r::GCode::process_layer().

+ Here is the caller graph for this function:

◆ has_skirt()

bool Slic3r::Print::has_skirt ( ) const
376{
377 return (m_config.skirt_height > 0 && m_config.skirts > 0) || has_infinite_skirt();
378 // case dsLimited should only be taken into account when skirt_height and skirts are positive,
379 // so it is covered by the first condition.
380}

References has_infinite_skirt(), and m_config.

Referenced by Slic3r::GUI::GLCanvas3D::_load_print_toolpaths(), Slic3r::GUI::get_skirt_offset(), Slic3r::Skirt::make_skirt_loops_per_extruder_1st_layer(), Slic3r::Skirt::make_skirt_loops_per_extruder_other_layers(), and process().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ has_support_material()

bool Slic3r::Print::has_support_material ( ) const
873{
874 for (const PrintObject *object : m_objects)
875 if (object->has_support_material())
876 return true;
877 return false;
878}
bool has_support_material() const
Definition Print.cpp:872

References m_objects.

Referenced by Slic3r::GCode::_do_export().

+ Here is the caller graph for this function:

◆ has_wipe_tower()

bool Slic3r::Print::has_wipe_tower ( ) const
1370{
1371 return
1372 ! m_config.spiral_vase.value &&
1373 m_config.wipe_tower.value &&
1374 m_config.nozzle_diameter.values.size() > 1;
1375}

References m_config.

Referenced by Slic3r::GCode::_do_export(), _make_wipe_tower(), extruders(), first_layer_wipe_tower_corners(), process(), and validate().

+ Here is the caller graph for this function:

◆ id()

ObjectID Slic3r::ObjectBase::id ( ) const
inlineinherited
55{ return m_id; }

References Slic3r::ObjectBase::m_id.

Referenced by Slic3r::Model::Model(), Slic3r::ModelInstance::ModelInstance(), Slic3r::ModelMaterial::ModelMaterial(), Slic3r::ModelObject::ModelObject(), Slic3r::ModelObject::ModelObject(), Slic3r::ModelObject::ModelObject(), Slic3r::ModelObject::ModelObject(), Slic3r::ModelObject::ModelObject(), Slic3r::ModelVolume::ModelVolume(), Slic3r::ModelVolume::ModelVolume(), Slic3r::ModelVolume::ModelVolume(), Slic3r::_3MF_Importer::_load_model_from_file(), Slic3r::GUI::Plater::priv::actualize_slicing_warnings(), Slic3r::ModelObjectStatusDB::add(), Slic3r::ModelObjectStatusDB::add_if_new(), apply(), Slic3r::SLAPrint::apply(), Slic3r::GUI::GLGizmoFdmSupports::apply_data_from_backend(), Slic3r::ModelVolume::check(), Slic3r::check_model_ids_equal(), Slic3r::ModelObject::convert_units(), Slic3r::ObjectBase::copy_id(), Slic3r::PrintObjectStatusDB::count(), anonymous_namespace{RaycastManager.cpp}::create_key(), priv::create_volume(), Slic3r::GUI::Emboss::create_volume_sources(), Slic3r::GUI::GLGizmoHollow::data_changed(), Slic3r::GUI::GLGizmoPainterBase::data_changed(), Slic3r::GUI::GLGizmoSlaSupports::data_changed(), Slic3r::Model::delete_object(), Slic3r::GUI::Plater::export_stl_obj(), Slic3r::ModelObjectStatusDB::get(), Slic3r::GUI::get_arrange_poly(), Slic3r::GUI::GLGizmoSlaSupports::get_data_from_backend(), Slic3r::PrintObjectStatusDB::get_range(), Slic3r::GUI::GLGizmoFdmSupports::has_backend_supports(), Slic3r::GUI::GLGizmoSlaSupports::has_backend_supports(), Slic3r::CutObjectBase::has_same_id(), Slic3r::UndoRedo::StackImpl::immutable_object_id_impl(), Slic3r::GUI::GLGizmoSimplify::init_model(), Slic3r::inner_brim_area(), Slic3r::ModelObject::is_cut(), Slic3r::CutObjectBase::is_equal(), Slic3r::ObjectBase::load_and_construct(), Slic3r::UndoRedo::StackImpl::load_snapshot(), Slic3r::GUI::ObjectList::merge(), Slic3r::model_property_changed(), Slic3r::model_volume_list_changed(), Slic3r::model_volume_list_copy_configs(), Slic3r::ModelConfigObject::object_id_and_timestamp_match(), Slic3r::ObjectWithTimestamp::object_id_and_timestamp_match(), Slic3r::GUI::GLGizmoEmboss::on_mouse_change_selection(), Slic3r::GUI::CommonGizmosDataObjects::SelectionInfo::on_update(), Slic3r::CutObjectBase::operator<(), Slic3r::Model::operator=(), Slic3r::ModelObject::operator=(), Slic3r::ModelObject::operator=(), Slic3r::CutObjectBase::operator==(), Slic3r::GUI::GLGizmoCut3D::perform_cut(), Slic3r::GUI::GLGizmoEmboss::process(), Slic3r::GUI::processed_objects_idxs(), Slic3r::GUI::GLCanvas3D::reload_scene(), Slic3r::GUI::GLCanvas3D::LayersEditing::select_object(), Slic3r::ModelMaterial::serialize(), Slic3r::SLAPrintObject::SliceRecord::set_model_slice_idx(), Slic3r::SLAPrintObject::SliceRecord::set_support_slice_idx(), Slic3r::slices_to_regions(), Slic3r::ModelObject::split(), Slic3r::UndoRedo::StackImpl::take_snapshot(), Slic3r::top_level_outer_brim_area(), Slic3r::GUI::update_object_cut_id(), and anonymous_namespace{EmbossJob.cpp}::update_volume_name().

◆ invalidate_all_steps()

bool Slic3r::PrintBaseWithState< PrintStep , COUNT >::invalidate_all_steps ( )
inlineprotectedinherited
603 { return m_state.invalidate_all(this->cancel_callback()); }
std::function< void()> cancel_callback()
Definition PrintBase.hpp:535
bool invalidate_all(CancelationCallback cancel)
Definition PrintBase.hpp:279

◆ invalidate_state_by_config_options()

bool Slic3r::Print::invalidate_state_by_config_options ( const ConfigOptionResolver new_config,
const std::vector< t_config_option_key > &  opt_keys 
)
private
53{
54 if (opt_keys.empty())
55 return false;
56
57 // Cache the plenty of parameters, which influence the G-code generator only,
58 // or they are only notes not influencing the generated G-code.
59 static std::unordered_set<std::string> steps_gcode = {
60 "autoemit_temperature_commands",
61 "avoid_crossing_perimeters",
62 "avoid_crossing_perimeters_max_detour",
63 "bed_shape",
64 "bed_temperature",
65 "before_layer_gcode",
66 "between_objects_gcode",
67 "bridge_acceleration",
68 "bridge_fan_speed",
69 "enable_dynamic_fan_speeds",
70 "overhang_fan_speed_0",
71 "overhang_fan_speed_1",
72 "overhang_fan_speed_2",
73 "overhang_fan_speed_3",
74 "colorprint_heights",
75 "cooling",
76 "default_acceleration",
77 "deretract_speed",
78 "disable_fan_first_layers",
79 "duplicate_distance",
80 "end_gcode",
81 "end_filament_gcode",
82 "external_perimeter_acceleration",
83 "extrusion_axis",
84 "extruder_clearance_height",
85 "extruder_clearance_radius",
86 "extruder_colour",
87 "extruder_offset",
88 "extrusion_multiplier",
89 "fan_always_on",
90 "fan_below_layer_time",
91 "full_fan_speed_layer",
92 "filament_colour",
93 "filament_diameter",
94 "filament_density",
95 "filament_notes",
96 "filament_cost",
97 "filament_spool_weight",
98 "first_layer_acceleration",
99 "first_layer_acceleration_over_raft",
100 "first_layer_bed_temperature",
101 "first_layer_speed_over_raft",
102 "gcode_comments",
103 "gcode_label_objects",
104 "infill_acceleration",
105 "layer_gcode",
106 "min_fan_speed",
107 "max_fan_speed",
108 "max_print_height",
109 "min_print_speed",
110 "max_print_speed",
111 "max_volumetric_speed",
112 "max_volumetric_extrusion_rate_slope_positive",
113 "max_volumetric_extrusion_rate_slope_negative",
114 "notes",
115 "only_retract_when_crossing_perimeters",
116 "output_filename_format",
117 "perimeter_acceleration",
118 "post_process",
119 "gcode_substitutions",
120 "printer_notes",
121 "retract_before_travel",
122 "retract_before_wipe",
123 "retract_layer_change",
124 "retract_length",
125 "retract_length_toolchange",
126 "retract_lift",
127 "retract_lift_above",
128 "retract_lift_below",
129 "retract_restart_extra",
130 "retract_restart_extra_toolchange",
131 "retract_speed",
132 "single_extruder_multi_material_priming",
133 "slowdown_below_layer_time",
134 "solid_infill_acceleration",
135 "standby_temperature_delta",
136 "start_gcode",
137 "start_filament_gcode",
138 "toolchange_gcode",
139 "top_solid_infill_acceleration",
140 "travel_acceleration",
141 "thumbnails",
142 "thumbnails_format",
143 "use_firmware_retraction",
144 "use_relative_e_distances",
145 "use_volumetric_e",
146 "variable_layer_height",
147 "wipe"
148 };
149
150 static std::unordered_set<std::string> steps_ignore;
151
152 std::vector<PrintStep> steps;
153 std::vector<PrintObjectStep> osteps;
154 bool invalidated = false;
155
156 for (const t_config_option_key &opt_key : opt_keys) {
157 if (steps_gcode.find(opt_key) != steps_gcode.end()) {
158 // These options only affect G-code export or they are just notes without influence on the generated G-code,
159 // so there is nothing to invalidate.
160 steps.emplace_back(psGCodeExport);
161 } else if (steps_ignore.find(opt_key) != steps_ignore.end()) {
162 // These steps have no influence on the G-code whatsoever. Just ignore them.
163 } else if (
164 opt_key == "skirts"
165 || opt_key == "skirt_height"
166 || opt_key == "draft_shield"
167 || opt_key == "skirt_distance"
168 || opt_key == "min_skirt_length"
169 || opt_key == "ooze_prevention"
170 || opt_key == "wipe_tower_x"
171 || opt_key == "wipe_tower_y"
172 || opt_key == "wipe_tower_rotation_angle") {
173 steps.emplace_back(psSkirtBrim);
174 } else if (
175 opt_key == "first_layer_height"
176 || opt_key == "nozzle_diameter"
177 || opt_key == "resolution"
178 // Spiral Vase forces different kind of slicing than the normal model:
179 // In Spiral Vase mode, holes are closed and only the largest area contour is kept at each layer.
180 // Therefore toggling the Spiral Vase on / off requires complete reslicing.
181 || opt_key == "spiral_vase") {
182 osteps.emplace_back(posSlice);
183 } else if (
184 opt_key == "complete_objects"
185 || opt_key == "filament_type"
186 || opt_key == "first_layer_temperature"
187 || opt_key == "filament_loading_speed"
188 || opt_key == "filament_loading_speed_start"
189 || opt_key == "filament_unloading_speed"
190 || opt_key == "filament_unloading_speed_start"
191 || opt_key == "filament_toolchange_delay"
192 || opt_key == "filament_cooling_moves"
193 || opt_key == "filament_minimal_purge_on_wipe_tower"
194 || opt_key == "filament_cooling_initial_speed"
195 || opt_key == "filament_cooling_final_speed"
196 || opt_key == "filament_ramming_parameters"
197 || opt_key == "filament_max_volumetric_speed"
198 || opt_key == "gcode_flavor"
199 || opt_key == "high_current_on_filament_swap"
200 || opt_key == "infill_first"
201 || opt_key == "single_extruder_multi_material"
202 || opt_key == "temperature"
203 || opt_key == "idle_temperature"
204 || opt_key == "wipe_tower"
205 || opt_key == "wipe_tower_width"
206 || opt_key == "wipe_tower_brim_width"
207 || opt_key == "wipe_tower_cone_angle"
208 || opt_key == "wipe_tower_bridging"
209 || opt_key == "wipe_tower_extra_spacing"
210 || opt_key == "wipe_tower_no_sparse_layers"
211 || opt_key == "wipe_tower_extruder"
212 || opt_key == "wiping_volumes_matrix"
213 || opt_key == "parking_pos_retraction"
214 || opt_key == "cooling_tube_retraction"
215 || opt_key == "cooling_tube_length"
216 || opt_key == "extra_loading_move"
217 || opt_key == "travel_speed"
218 || opt_key == "travel_speed_z"
219 || opt_key == "first_layer_speed"
220 || opt_key == "z_offset") {
221 steps.emplace_back(psWipeTower);
222 steps.emplace_back(psSkirtBrim);
223 } else if (opt_key == "filament_soluble") {
224 steps.emplace_back(psWipeTower);
225 // Soluble support interface / non-soluble base interface produces non-soluble interface layers below soluble interface layers.
226 // Thus switching between soluble / non-soluble interface layer material may require recalculation of supports.
227 //FIXME Killing supports on any change of "filament_soluble" is rough. We should check for each object whether that is necessary.
228 osteps.emplace_back(posSupportMaterial);
229 } else if (
230 opt_key == "first_layer_extrusion_width"
231 || opt_key == "min_layer_height"
232 || opt_key == "max_layer_height"
233 || opt_key == "gcode_resolution") {
234 osteps.emplace_back(posPerimeters);
235 osteps.emplace_back(posInfill);
236 osteps.emplace_back(posSupportMaterial);
237 steps.emplace_back(psSkirtBrim);
238 } else if (opt_key == "avoid_crossing_curled_overhangs") {
239 osteps.emplace_back(posEstimateCurledExtrusions);
240 } else {
241 // for legacy, if we can't handle this option let's invalidate all steps
242 //FIXME invalidate all steps of all objects as well?
243 invalidated |= this->invalidate_all_steps();
244 // Continue with the other opt_keys to possibly invalidate any object specific steps.
245 }
246 }
247
249 for (PrintStep step : steps)
250 invalidated |= this->invalidate_step(step);
252 for (PrintObjectStep ostep : osteps)
253 for (PrintObject *object : m_objects)
254 invalidated |= object->invalidate_step(ostep);
255 return invalidated;
256}
PrintObjectStep
Definition Print.hpp:68
@ posSlice
Definition Print.hpp:69
@ posInfill
Definition Print.hpp:70
@ posPerimeters
Definition Print.hpp:69
@ posEstimateCurledExtrusions
Definition Print.hpp:70
std::string t_config_option_key
Definition Config.hpp:76
PrintStep
Definition Print.hpp:53
Coord step(const Coord &crd, Dir d)
Definition MarchingSquares.hpp:137

References Slic3r::PrintBaseWithState< PrintStep, psCount >::invalidate_all_steps(), invalidate_step(), m_objects, Slic3r::posEstimateCurledExtrusions, Slic3r::posInfill, Slic3r::posPerimeters, Slic3r::posSlice, Slic3r::posSupportMaterial, Slic3r::psGCodeExport, Slic3r::psSkirtBrim, Slic3r::psWipeTower, and Slic3r::sort_remove_duplicates().

+ Here is the call graph for this function:

◆ invalidate_step()

bool Slic3r::Print::invalidate_step ( PrintStep  step)
protected
259{
260 bool invalidated = Inherited::invalidate_step(step);
261 // Propagate to dependent steps.
262 if (step != psGCodeExport)
264 return invalidated;
265}
bool invalidate_step(PrintStepEnum step)
Definition PrintBase.hpp:595

References Slic3r::PrintBaseWithState< PrintStep, psCount >::invalidate_step(), and Slic3r::psGCodeExport.

Referenced by invalidate_state_by_config_options(), and Slic3r::PrintObject::set_instances().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ invalidate_steps() [1/2]

bool Slic3r::PrintBaseWithState< PrintStep , COUNT >::invalidate_steps ( std::initializer_list< PrintStepEnum il)
inlineprotectedinherited
601 { return m_state.invalidate_multiple(il.begin(), il.end(), this->cancel_callback()); }
bool invalidate_multiple(StepTypeIterator step_begin, StepTypeIterator step_end, CancelationCallback cancel)
Definition PrintBase.hpp:249

◆ invalidate_steps() [2/2]

bool Slic3r::PrintBaseWithState< PrintStep , COUNT >::invalidate_steps ( StepTypeIterator  step_begin,
StepTypeIterator  step_end 
)
inlineprotectedinherited
599 { return m_state.invalidate_multiple(step_begin, step_end, this->cancel_callback()); }

◆ is_shared_print_object_step_valid_unguarded()

bool Slic3r::Print::is_shared_print_object_step_valid_unguarded ( SpanOfConstPtrs< PrintObject print_objects,
PrintObjectStep  print_object_step 
)
staticprivate
1474{
1475 return std::any_of(print_objects.begin(), print_objects.end(), [print_object_step](auto po){ return po->is_step_done_unguarded(print_object_step); });
1476}

◆ is_step_done() [1/2]

bool Slic3r::Print::is_step_done ( PrintObjectStep  step) const
270{
271 if (m_objects.empty())
272 return false;
273 std::scoped_lock<std::mutex> lock(this->state_mutex());
274 for (const PrintObject *object : m_objects)
275 if (! object->is_step_done_unguarded(step))
276 return false;
277 return true;
278}
bool is_step_done_unguarded(PrintStepEnum step) const
Definition PrintBase.hpp:606

References m_objects, and Slic3r::PrintBase::state_mutex().

+ Here is the call graph for this function:

◆ is_step_done() [2/2]

bool Slic3r::Print::is_step_done ( PrintStep  step) const
inline
573{ return Inherited::is_step_done(step); }
bool is_step_done(PrintStepEnum step) const
Definition PrintBase.hpp:583

References Slic3r::PrintBaseWithState< PrintStep, psCount >::is_step_done().

Referenced by Slic3r::GUI::GLCanvas3D::_load_print_toolpaths(), Slic3r::GUI::GLCanvas3D::_load_wipe_tower_toolpaths(), Slic3r::BackgroundSlicingProcess::apply(), finished(), Slic3r::GUI::Preview::load_print_as_fff(), Slic3r::GUI::GCodeViewer::load_shells(), Slic3r::GUI::GLCanvas3D::reload_scene(), and wipe_tower_data().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ is_step_done_unguarded()

bool Slic3r::PrintBaseWithState< PrintStep , COUNT >::is_step_done_unguarded ( PrintStepEnum  step) const
inlineprotectedinherited
606{ return m_state.is_done_unguarded(step); }
bool is_done_unguarded(StepType step) const
Definition PrintBase.hpp:146

◆ is_step_started_unguarded()

bool Slic3r::PrintBaseWithState< PrintStep , COUNT >::is_step_started_unguarded ( PrintStepEnum  step) const
inlineprotectedinherited
605{ return m_state.is_started_unguarded(step); }
bool is_started_unguarded(StepType step) const
Definition PrintBase.hpp:142

◆ load_and_construct()

template<class Archive >
static void Slic3r::ObjectBase::load_and_construct ( Archive &  ar,
cereal::construct< ObjectBase > &  construct 
)
inlinestaticprivateinherited
96{ ObjectID id; ar(id); construct(id); }

References Slic3r::ObjectBase::id().

+ Here is the call graph for this function:

◆ make_try_cancel()

PrintTryCancel Slic3r::PrintBase::make_try_cancel ( ) const
inlineprotectedinherited
546{ return PrintTryCancel(this); }
friend PrintTryCancel
Definition PrintBase.hpp:571

References Slic3r::PrintBase::PrintTryCancel.

Referenced by process().

+ Here is the caller graph for this function:

◆ max_allowed_layer_height()

double Slic3r::Print::max_allowed_layer_height ( ) const
353{
354 double nozzle_diameter_max = 0.;
355 for (unsigned int extruder_id : this->extruders())
356 nozzle_diameter_max = std::max(nozzle_diameter_max, m_config.nozzle_diameter.get_at(extruder_id));
357 return nozzle_diameter_max;
358}
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half() max(const half &a, const half &b)
Definition Half.h:516

References extruders(), and m_config.

+ Here is the call graph for this function:

◆ model()

const Model & Slic3r::PrintBase::model ( ) const
inlineinherited

◆ num_object_instances()

unsigned int Slic3r::Print::num_object_instances ( ) const
345{
346 unsigned int instances = 0;
347 for (const PrintObject *print_object : m_objects)
348 instances += (unsigned int)print_object->instances().size();
349 return instances;
350}
constexpr auto size(const C &c) -> decltype(c.size())
Definition span.hpp:183

References m_objects.

Referenced by Slic3r::sort_object_instances_by_model_order().

+ Here is the caller graph for this function:

◆ num_print_regions()

size_t Slic3r::Print::num_print_regions ( ) const
throw (
)
inline
642{ return m_print_regions.size(); }

References m_print_regions.

Referenced by Slic3r::GCode::_do_export().

+ Here is the caller graph for this function:

◆ object_extruders()

std::vector< unsigned int > Slic3r::Print::object_extruders ( ) const
282{
283 std::vector<unsigned int> extruders;
284 extruders.reserve(m_print_regions.size() * m_objects.size() * 3);
285 for (const PrintObject *object : m_objects)
286 for (const PrintRegion &region : object->all_regions())
287 region.collect_object_printing_extruders(*this, extruders);
289 return extruders;
290}

References extruders(), m_objects, m_print_regions, and Slic3r::sort_remove_duplicates().

Referenced by Slic3r::ToolOrdering::ToolOrdering(), Slic3r::ToolOrdering::assign_custom_gcodes(), extruders(), and support_material_extruders().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ objects()

SpanOfConstPtrs< PrintObject > Slic3r::Print::objects ( ) const
inline
600{ return SpanOfConstPtrs<PrintObject>(const_cast<const PrintObject* const* const>(m_objects.data()), m_objects.size()); }

References const, and m_objects.

Referenced by Slic3r::ToolOrdering::ToolOrdering(), Slic3r::GCode::_do_export(), Slic3r::GUI::GLCanvas3D::_load_print_toolpaths(), Slic3r::GUI::GLGizmoFdmSupports::apply_data_from_backend(), Slic3r::DoubleSlider::Control::auto_color_change(), Slic3r::DoExport::autospeed_volumetric_limit(), Slic3r::chain_print_object_instances(), Slic3r::GCode::collect_layers_to_print(), Slic3r::WipingExtrusions::ensure_perimeters_infills_order(), Slic3r::fff_tree_support_generate(), Slic3r::get_boundary_external(), Slic3r::get_perimeter_spacing_external(), Slic3r::get_print_bottom_layers_expolygons(), Slic3r::get_top_level_objects_with_brim(), Slic3r::GUI::GLGizmoFdmSupports::has_backend_supports(), Slic3r::has_polygons_nothing_inside(), Slic3r::SeamPlacer::init(), Slic3r::inner_brim_area(), Slic3r::DoubleSlider::Control::IsNewPrint(), Slic3r::GUI::GLCanvas3D::load_preview(), Slic3r::GUI::Preview::load_print_as_fff(), Slic3r::GUI::GCodeViewer::load_shells(), Slic3r::make_brim(), Slic3r::make_inner_brim(), Slic3r::WipingExtrusions::mark_wiping_extrusions(), Slic3r::GCode::process_layer_single_object(), sequential_print_horizontal_clearance_valid(), Slic3r::sort_object_instances_by_model_order(), Slic3r::top_level_outer_brim_area(), and Slic3r::GUI::Preview::update_layers_slider().

+ Here is the caller graph for this function:

◆ objects_mutable()

PrintObjectPtrs & Slic3r::Print::objects_mutable ( )
inline
620{ return m_objects; }

References m_objects.

◆ output_filename() [1/2]

std::string Slic3r::Print::output_filename ( const std::string &  filename_base = std::string()) const
overridevirtual

Implements Slic3r::PrintBase.

1539{
1540 // Set the placeholders for the data know first after the G-code export is finished.
1541 // These values will be just propagated into the output file name.
1542 DynamicConfig config = this->finished() ? this->print_statistics().config() : this->print_statistics().placeholders();
1543 config.set_key_value("num_extruders", new ConfigOptionInt((int)m_config.nozzle_diameter.size()));
1544 config.set_key_value("default_output_extension", new ConfigOptionString(".gcode"));
1545 return this->PrintBase::output_filename(m_config.output_filename_format.value, ".gcode", filename_base, &config);
1546}
bool set_key_value(const std::string &opt_key, ConfigOption *opt)
Definition Config.hpp:2431
virtual std::string output_filename(const std::string &filename_base=std::string()) const =0
const PrintStatistics & print_statistics() const
Definition Print.hpp:632
bool finished() const override
Definition Print.hpp:577
static DynamicConfig placeholders()
Definition Print.cpp:1573
DynamicConfig config() const
Definition Print.cpp:1548

References Slic3r::PrintStatistics::config(), config(), finished(), m_config, Slic3r::PrintBase::output_filename(), Slic3r::PrintStatistics::placeholders(), print_statistics(), and Slic3r::DynamicConfig::set_key_value().

+ Here is the call graph for this function:

◆ output_filename() [2/2]

std::string Slic3r::PrintBase::output_filename ( const std::string &  format,
const std::string &  default_ext,
const std::string &  filename_base,
const DynamicConfig config_override = nullptr 
) const
protectedinherited
61{
62 DynamicConfig cfg;
63 if (config_override != nullptr)
64 cfg = *config_override;
65 cfg.set_key_value("version", new ConfigOptionString(std::string(SLIC3R_VERSION)));
67 this->update_object_placeholders(cfg, default_ext);
68 if (! filename_base.empty()) {
69 cfg.set_key_value("input_filename", new ConfigOptionString(filename_base + default_ext));
70 cfg.set_key_value("input_filename_base", new ConfigOptionString(filename_base));
71 }
72 try {
73 boost::filesystem::path filename = format.empty() ?
74 cfg.opt_string("input_filename_base") + default_ext :
75 this->placeholder_parser().process(format, 0, &cfg);
76 if (filename.extension().empty())
77 filename = boost::filesystem::change_extension(filename, default_ext);
78 return filename.string();
79 } catch (std::runtime_error &err) {
80 throw Slic3r::PlaceholderParserError(_u8L("Failed processing of the output_filename_format template.") + "\n" + err.what());
81 }
82}
std::string process(const std::string &templ, unsigned int current_extruder_id, const DynamicConfig *config_override, DynamicConfig *config_outputs, ContextData *context) const
Definition PlaceholderParser.cpp:2344
void update_timestamp()
Definition PlaceholderParser.hpp:72
void update_object_placeholders(DynamicConfig &config, const std::string &default_ext) const
Definition PrintBase.cpp:20
const PlaceholderParser & placeholder_parser() const
Definition PrintBase.hpp:522

References _u8L, Slic3r::format(), Slic3r::ConfigBase::opt_string(), Slic3r::PrintBase::placeholder_parser(), Slic3r::PlaceholderParser::process(), Slic3r::DynamicConfig::set_key_value(), Slic3r::PrintBase::update_object_placeholders(), and Slic3r::PlaceholderParser::update_timestamp().

+ Here is the call graph for this function:

◆ output_filepath()

std::string Slic3r::PrintBase::output_filepath ( const std::string &  path,
const std::string &  filename_base = std::string() 
) const
inherited
85{
86 // if we were supplied no path, generate an automatic one based on our first object's input file
87 if (path.empty())
88 // get the first input file name
89 return (boost::filesystem::path(m_model.propose_export_file_name_and_path()).parent_path() / this->output_filename(filename_base)).make_preferred().string();
90
91 // if we were supplied a directory, use it and append our automatically generated filename
92 boost::filesystem::path p(path);
93 if (boost::filesystem::is_directory(p))
94 return (p / this->output_filename(filename_base)).make_preferred().string();
95
96 // if we were supplied a file which is not a directory, use it
97 return path;
98}
std::string propose_export_file_name_and_path() const
Definition Model.cpp:585

References Slic3r::PrintBase::m_model, Slic3r::PrintBase::output_filename(), and Slic3r::Model::propose_export_file_name_and_path().

Referenced by export_gcode(), Slic3r::BackgroundSlicingProcess::output_filepath_for_project(), and Slic3r::CLI::run().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ placeholder_parser()

const PlaceholderParser & Slic3r::PrintBase::placeholder_parser ( ) const
inlineinherited
522{ return m_placeholder_parser; }

References Slic3r::PrintBase::m_placeholder_parser.

Referenced by Slic3r::GCode::_do_export(), and Slic3r::PrintBase::output_filename().

+ Here is the caller graph for this function:

◆ print_object_ids()

std::vector< ObjectID > Slic3r::Print::print_object_ids ( ) const
overridevirtual

Implements Slic3r::PrintBase.

361{
362 std::vector<ObjectID> out;
363 // Reserve one more for the caller to append the ID of the Print itself.
364 out.reserve(m_objects.size() + 1);
365 for (const PrintObject *print_object : m_objects)
366 out.emplace_back(print_object->id());
367 return out;
368}

References m_objects.

◆ print_regions_mutable()

PrintRegionPtrs & Slic3r::Print::print_regions_mutable ( )
inline
621{ return m_print_regions; }

References m_print_regions.

◆ print_statistics() [1/2]

PrintStatistics & Slic3r::Print::print_statistics ( )
inline
633{ return m_print_statistics; }
PrintStatistics m_print_statistics
Definition Print.hpp:694

References m_print_statistics.

◆ print_statistics() [2/2]

const PrintStatistics & Slic3r::Print::print_statistics ( ) const
inline
632{ return m_print_statistics; }

References m_print_statistics.

Referenced by Slic3r::BackgroundSlicingProcess::finalize_gcode(), output_filename(), Slic3r::BackgroundSlicingProcess::prepare_upload(), and Slic3r::CLI::run().

+ Here is the caller graph for this function:

◆ process()

void Slic3r::Print::process ( )
overridevirtual

Implements Slic3r::PrintBase.

899{
901
902 BOOST_LOG_TRIVIAL(info) << "Starting the slicing process." << log_memory_info();
903 for (PrintObject *obj : m_objects)
904 obj->make_perimeters();
905 for (PrintObject *obj : m_objects)
906 obj->infill();
907 for (PrintObject *obj : m_objects)
908 obj->ironing();
909 for (PrintObject *obj : m_objects)
910 obj->generate_support_spots();
911 // check data from previous step, format the error message(s) and send alert to ui
913 for (PrintObject *obj : m_objects)
914 obj->generate_support_material();
915 for (PrintObject *obj : m_objects)
916 obj->estimate_curled_extrusions();
917 if (this->set_started(psWipeTower)) {
920 if (this->has_wipe_tower()) {
921 //this->set_status(95, _u8L("Generating wipe tower"));
922 this->_make_wipe_tower();
923 } else if (! this->config().complete_objects.value) {
924 // Initialize the tool ordering, so it could be used by the G-code preview slider for planning tool changes and filament switches.
925 m_tool_ordering = ToolOrdering(*this, -1, false);
926 if (m_tool_ordering.empty() || m_tool_ordering.last_extruder() == unsigned(-1))
927 throw Slic3r::SlicingError("The print is empty. The model is not printable with current print settings.");
928 }
929 this->set_done(psWipeTower);
930 }
931 if (this->set_started(psSkirtBrim)) {
932 this->set_status(88, _u8L("Generating skirt and brim"));
933
934 m_skirt.clear();
935 m_skirt_convex_hull.clear();
937 const bool draft_shield = config().draft_shield != dsDisabled;
938
939 if (this->has_skirt() && draft_shield) {
940 // In case that draft shield is active, generate skirt first so brim
941 // can be trimmed to make room for it.
942 _make_skirt();
943 }
944
945 m_brim.clear();
947 if (this->has_brim()) {
948 Polygons islands_area;
949 m_brim = make_brim(*this, this->make_try_cancel(), islands_area);
950 for (Polygon &poly : union_(this->first_layer_islands(), islands_area))
951 append(m_first_layer_convex_hull.points, std::move(poly.points));
952 }
953
954
955 if (has_skirt() && ! draft_shield) {
956 // In case that draft shield is NOT active, generate skirt now.
957 // It will be placed around the brim, so brim has to be ready.
958 assert(m_skirt.empty());
959 _make_skirt();
960 }
961
963 this->set_done(psSkirtBrim);
964 }
965
966 std::optional<const FakeWipeTower*> wipe_tower_opt = {};
967 if (this->has_wipe_tower()) {
968 m_fake_wipe_tower.set_pos_and_rotation({ m_config.wipe_tower_x, m_config.wipe_tower_y }, m_config.wipe_tower_rotation_angle);
969 wipe_tower_opt = std::make_optional<const FakeWipeTower*>(&m_fake_wipe_tower);
970 }
971 auto conflictRes = ConflictChecker::find_inter_of_lines_in_diff_objs(m_objects, wipe_tower_opt);
972
973 m_conflict_result = conflictRes;
974 if (conflictRes.has_value())
975 BOOST_LOG_TRIVIAL(error) << boost::format("gcode path conflicts found between %1% and %2%") % conflictRes->_objName1 % conflictRes->_objName2;
976
977 BOOST_LOG_TRIVIAL(info) << "Slicing process finished." << log_memory_info();
978}
bool empty() const
Definition ExtrusionEntityCollection.hpp:65
void clear()
Definition ExtrusionEntityCollection.cpp:42
PrintTryCancel make_try_cancel() const
Definition PrintBase.hpp:546
void _make_skirt()
Definition Print.cpp:1009
bool has_skirt() const
Definition Print.cpp:375
void finalize_first_layer_convex_hull()
Definition Print.cpp:1204
void alert_when_supports_needed()
Definition Print.cpp:1216
bool has_brim() const
Definition Print.cpp:382
ToolOrdering m_tool_ordering
Definition Print.hpp:690
void _make_wipe_tower()
Definition Print.cpp:1403
void clear()
Definition ToolOrdering.hpp:136
bool empty() const
Definition ToolOrdering.hpp:161
unsigned int last_extruder() const
Definition ToolOrdering.hpp:148
Slic3r::Polygons union_(const Slic3r::Polygons &subject)
Definition ClipperUtils.cpp:704
ironing((ConfigOptionEnum< IroningType >, ironing_type))((ConfigOptionPercent
std::string log_memory_info(bool ignore_loglevel)
Definition utils.cpp:1073
void name_tbb_thread_pool_threads_set_locale()
Definition Thread.cpp:222
ExtrusionEntityCollection make_brim(const Print &print, PrintTryCancel try_cancel, Polygons &islands_area)
Definition Brim.cpp:499
static ConflictResultOpt find_inter_of_lines_in_diff_objs(PrintObjectPtrs objs, std::optional< const FakeWipeTower * > wtdptr)
Definition ConflictChecker.cpp:206
void set_pos_and_rotation(const Vec2f &p, float rotation)
Definition Print.hpp:449

References _make_skirt(), _make_wipe_tower(), _u8L, alert_when_supports_needed(), Slic3r::append(), Slic3r::ExtrusionEntityCollection::clear(), Slic3r::ToolOrdering::clear(), Slic3r::WipeTowerData::clear(), config(), Slic3r::dsDisabled, Slic3r::ExtrusionEntityCollection::empty(), Slic3r::ToolOrdering::empty(), error, finalize_first_layer_convex_hull(), Slic3r::ConflictChecker::find_inter_of_lines_in_diff_objs(), first_layer_islands(), has_brim(), has_skirt(), has_wipe_tower(), Slic3r::ToolOrdering::last_extruder(), Slic3r::log_memory_info(), m_brim, m_config, m_conflict_result, m_fake_wipe_tower, m_first_layer_convex_hull, m_objects, m_skirt, m_skirt_convex_hull, m_tool_ordering, m_wipe_tower_data, Slic3r::make_brim(), Slic3r::PrintBase::make_try_cancel(), Slic3r::name_tbb_thread_pool_threads_set_locale(), Slic3r::MultiPoint::points, Slic3r::psSkirtBrim, Slic3r::psWipeTower, Slic3r::PrintBaseWithState< PrintStep, psCount >::set_done(), Slic3r::FakeWipeTower::set_pos_and_rotation(), Slic3r::PrintBaseWithState< PrintStep, psCount >::set_started(), Slic3r::PrintBase::set_status(), and Slic3r::union_().

+ Here is the call graph for this function:

◆ restart()

void Slic3r::PrintBase::restart ( )
inlineinherited

References Slic3r::PrintBase::m_cancel_status, and Slic3r::PrintBase::NOT_CANCELED.

Referenced by Slic3r::PrintBase::PrintBase(), and Slic3r::BackgroundSlicingProcess::thread_proc().

+ Here is the caller graph for this function:

◆ sequential_print_horizontal_clearance_valid()

bool Slic3r::Print::sequential_print_horizontal_clearance_valid ( const Print print,
Polygons polygons = nullptr 
)
static
388{
389 Polygons convex_hulls_other;
390 if (polygons != nullptr)
391 polygons->clear();
392 std::vector<size_t> intersecting_idxs;
393
394 std::map<ObjectID, Polygon> map_model_object_to_convex_hull;
395 for (const PrintObject *print_object : print.objects()) {
396 assert(! print_object->model_object()->instances.empty());
397 assert(! print_object->instances().empty());
398 ObjectID model_object_id = print_object->model_object()->id();
399 auto it_convex_hull = map_model_object_to_convex_hull.find(model_object_id);
400 // Get convex hull of all printable volumes assigned to this print object.
401 ModelInstance *model_instance0 = print_object->model_object()->instances.front();
402 if (it_convex_hull == map_model_object_to_convex_hull.end()) {
403 // Calculate the convex hull of a printable object.
404 // Grow convex hull with the clearance margin.
405 // FIXME: Arrangement has different parameters for offsetting (jtMiter, limit 2)
406 // which causes that the warning will be showed after arrangement with the
407 // appropriate object distance. Even if I set this to jtMiter the warning still shows up.
408 Geometry::Transformation trafo = model_instance0->get_transformation();
409 trafo.set_offset({ 0.0, 0.0, model_instance0->get_offset().z() });
410 it_convex_hull = map_model_object_to_convex_hull.emplace_hint(it_convex_hull, model_object_id,
411 offset(print_object->model_object()->convex_hull_2d(trafo.get_matrix()),
412 // Shrink the extruder_clearance_radius a tiny bit, so that if the object arrangement algorithm placed the objects
413 // exactly by satisfying the extruder_clearance_radius, this test will not trigger collision.
414 float(scale_(0.5 * print.config().extruder_clearance_radius.value - BuildVolume::BedEpsilon)),
415 jtRound, scale_(0.1)).front());
416 }
417 // Make a copy, so it may be rotated for instances.
418 Polygon convex_hull0 = it_convex_hull->second;
419 const double z_diff = Geometry::rotation_diff_z(model_instance0->get_matrix(), print_object->instances().front().model_instance->get_matrix());
420 if (std::abs(z_diff) > EPSILON)
421 convex_hull0.rotate(z_diff);
422 // Now we check that no instance of convex_hull intersects any of the previously checked object instances.
423 for (const PrintInstance &instance : print_object->instances()) {
424 Polygon convex_hull = convex_hull0;
425 // instance.shift is a position of a centered object, while model object may not be centered.
426 // Convert the shift from the PrintObject's coordinates into ModelObject's coordinates by removing the centering offset.
427 convex_hull.translate(instance.shift - print_object->center_offset());
428 // if output needed, collect indices (inside convex_hulls_other) of intersecting hulls
429 for (size_t i = 0; i < convex_hulls_other.size(); ++i) {
430 if (! intersection(convex_hulls_other[i], convex_hull).empty()) {
431 if (polygons == nullptr)
432 return false;
433 else {
434 intersecting_idxs.emplace_back(i);
435 intersecting_idxs.emplace_back(convex_hulls_other.size());
436 }
437 }
438 }
439 convex_hulls_other.emplace_back(std::move(convex_hull));
440 }
441 }
442
443 if (!intersecting_idxs.empty()) {
444 // use collected indices (inside convex_hulls_other) to update output
445 std::sort(intersecting_idxs.begin(), intersecting_idxs.end());
446 intersecting_idxs.erase(std::unique(intersecting_idxs.begin(), intersecting_idxs.end()), intersecting_idxs.end());
447 for (size_t i : intersecting_idxs) {
448 polygons->emplace_back(std::move(convex_hulls_other[i]));
449 }
450 return false;
451 }
452 return true;
453}
static constexpr const double BedEpsilon
Definition BuildVolume.hpp:90
bool empty() const override
Definition Print.hpp:558
double rotation_diff_z(const Transform3d &trafo_from, const Transform3d &trafo_to)
Definition Geometry.cpp:712
Slic3r::Polygons intersection(const Slic3r::Polygon &subject, const Slic3r::Polygon &clip, ApplySafetyOffset do_safety_offset)
Definition ClipperUtils.cpp:686

References Slic3r::BuildVolume::BedEpsilon, config(), EPSILON, Slic3r::Geometry::Transformation::get_matrix(), Slic3r::ModelInstance::get_matrix(), Slic3r::ModelInstance::get_offset(), Slic3r::ModelInstance::get_transformation(), Slic3r::ObjectID::id, Slic3r::intersection(), objects(), Slic3r::offset(), Slic3r::MultiPoint::rotate(), Slic3r::Geometry::rotation_diff_z(), scale_, and Slic3r::Geometry::Transformation::set_offset().

Referenced by validate().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ serialize()

template<class Archive >
void Slic3r::ObjectBase::serialize ( Archive &  ar)
inlineprivateinherited
92{ ar(m_id); }

References Slic3r::ObjectBase::m_id.

◆ set_cancel_callback()

void Slic3r::PrintBase::set_cancel_callback ( cancel_callback_type  cancel_callback)
inlineinherited

References Slic3r::PrintBase::cancel_callback(), and Slic3r::PrintBase::m_cancel_callback.

Referenced by Slic3r::BackgroundSlicingProcess::start(), Slic3r::BackgroundSlicingProcess::stop(), and Slic3r::BackgroundSlicingProcess::stop_internal().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ set_done()

PrintStateBase::TimeStamp Slic3r::PrintBaseWithState< PrintStep , COUNT >::set_done ( PrintStepEnum  step)
inlineprotectedinherited
589 {
590 std::pair<PrintStateBase::TimeStamp, bool> status = m_state.set_done(step, this->state_mutex(), [this](){ this->throw_if_canceled(); });
591 if (status.second)
592 this->status_update_warnings(static_cast<int>(step), PrintStateBase::WarningLevel::NON_CRITICAL, std::string());
593 return status.first;
594 }
std::pair< TimeStamp, bool > set_done(StepType step, std::mutex &mtx, ThrowIfCanceled throw_if_canceled)
Definition PrintBase.hpp:202

◆ set_invalid_id()

void Slic3r::ObjectBase::set_invalid_id ( )
inlineprotectedinherited
74{ m_id = 0; }

References Slic3r::ObjectBase::m_id.

Referenced by Slic3r::CutObjectBase::invalidate().

+ Here is the caller graph for this function:

◆ set_new_unique_id()

void Slic3r::ObjectBase::set_new_unique_id ( )
inlineprotectedinherited
73{ m_id = generate_new_id(); }
static ObjectID generate_new_id()
Definition ObjectID.hpp:84

References Slic3r::ObjectBase::generate_new_id(), and Slic3r::ObjectBase::m_id.

Referenced by Slic3r::ModelVolume::ModelVolume(), Slic3r::Model::assign_new_unique_ids_recursive(), Slic3r::ObjectBase::assign_new_unique_ids_recursive(), Slic3r::ModelObject::assign_new_unique_ids_recursive(), Slic3r::CutObjectBase::init(), Slic3r::ModelMaterial::set_new_unique_id(), Slic3r::ModelObject::set_new_unique_id(), and Slic3r::ModelVolume::set_new_unique_id().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ set_started()

bool Slic3r::PrintBaseWithState< PrintStep , COUNT >::set_started ( PrintStepEnum  step)
inlineprotectedinherited
588{ return m_state.set_started(step, this->state_mutex(), [this](){ this->throw_if_canceled(); }); }
bool set_started(StepType step, std::mutex &mtx, ThrowIfCanceled throw_if_canceled)
Definition PrintBase.hpp:169

◆ set_status()

void Slic3r::PrintBase::set_status ( int  percent,
const std::string &  message,
unsigned int  flags = SlicingStatus::DEFAULT 
)
inlineinherited
492 {
493 if (m_status_callback) m_status_callback(SlicingStatus(percent, message, flags));
494 else printf("%d => %s\n", percent, message.c_str());
495 }
status_callback_type m_status_callback
Definition PrintBase.hpp:558

References Slic3r::PrintBase::m_status_callback.

Referenced by alert_when_supports_needed(), export_gcode(), Slic3r::BackgroundSlicingProcess::finalize_gcode(), Slic3r::PrintObject::make_perimeters(), Slic3r::SLAPrint::StatusReporter::operator()(), Slic3r::BackgroundSlicingProcess::prepare_upload(), process(), Slic3r::BackgroundSlicingProcess::process_fff(), and Slic3r::BackgroundSlicingProcess::process_sla().

+ Here is the caller graph for this function:

◆ set_status_callback()

void Slic3r::PrintBase::set_status_callback ( status_callback_type  cb)
inlineinherited
490{ m_status_callback = cb; }

References Slic3r::PrintBase::m_status_callback.

Referenced by Slic3r::CLI::run().

+ Here is the caller graph for this function:

◆ set_status_default()

void Slic3r::PrintBase::set_status_default ( )
inlineinherited

◆ set_status_silent()

void Slic3r::PrintBase::set_status_silent ( )
inlineinherited
488{ m_status_callback = [](const SlicingStatus&){}; }

References Slic3r::PrintBase::m_status_callback.

◆ set_task()

void Slic3r::Print::set_task ( const TaskParams params)
inlineoverridevirtual

Implements Slic3r::PrintBase.

void set_task_impl(const TaskParams &params, std::vector< PrintObject * > &print_objects)
Definition PrintBase.hpp:620

References m_objects, and Slic3r::PrintBaseWithState< PrintStepEnumType, COUNT >::set_task_impl().

+ Here is the call graph for this function:

◆ set_task_impl()

void Slic3r::PrintBaseWithState< PrintStep , COUNT >::set_task_impl ( const TaskParams params,
std::vector< PrintObject * > &  print_objects 
)
inlineprotectedinherited
621 {
622 static constexpr const auto PrintObjectStepEnumSize = int(PrintObject::PrintObjectStepEnumSize);
623 using PrintObjectStepEnum = typename PrintObject::PrintObjectStepEnum;
624 // Grab the lock for the Print / PrintObject milestones.
625 std::scoped_lock<std::mutex> lock(this->state_mutex());
626
627 int n_object_steps = int(params.to_object_step) + 1;
628 if (n_object_steps == 0)
629 n_object_steps = PrintObjectStepEnumSize;
630
631 if (params.single_model_object.valid()) {
632 // Find the print object to be processed with priority.
633 PrintObject *print_object = nullptr;
634 size_t idx_print_object = 0;
635 for (; idx_print_object < print_objects.size(); ++ idx_print_object)
636 if (print_objects[idx_print_object]->model_object()->id() == params.single_model_object) {
637 print_object = print_objects[idx_print_object];
638 break;
639 }
640 assert(print_object != nullptr);
641 // Find out whether the priority print object is being currently processed.
642 bool running = false;
643 for (int istep = 0; istep < n_object_steps; ++ istep) {
644 if (! print_object->is_step_enabled_unguarded(PrintObjectStepEnum(istep)))
645 // Step was skipped, cancel.
646 break;
647 if (print_object->is_step_started_unguarded(PrintObjectStepEnum(istep))) {
648 // No step was skipped, and a wanted step is being processed. Don't cancel.
649 running = true;
650 break;
651 }
652 }
653 if (! running)
654 this->call_cancel_callback();
655
656 // Now the background process is either stopped, or it is inside one of the print object steps to be calculated anyway.
657 if (params.single_model_instance_only) {
658 // Suppress all the steps of other instances.
659 for (PrintObject *po : print_objects)
660 for (size_t istep = 0; istep < PrintObjectStepEnumSize; ++ istep)
661 po->enable_step_unguarded(PrintObjectStepEnum(istep), false);
662 } else if (! running) {
663 // Swap the print objects, so that the selected print_object is first in the row.
664 // At this point the background processing must be stopped, so it is safe to shuffle print objects.
665 if (idx_print_object != 0)
666 std::swap(print_objects.front(), print_objects[idx_print_object]);
667 }
668 // and set the steps for the current object.
669 for (int istep = 0; istep < n_object_steps; ++ istep)
670 print_object->enable_step_unguarded(PrintObjectStepEnum(istep), true);
671 for (int istep = n_object_steps; istep < PrintObjectStepEnumSize; ++ istep)
672 print_object->enable_step_unguarded(PrintObjectStepEnum(istep), false);
673 } else {
674 // Slicing all objects.
675 bool running = false;
676 for (PrintObject *print_object : print_objects)
677 for (int istep = 0; istep < n_object_steps; ++ istep) {
678 if (! print_object->is_step_enabled_unguarded(PrintObjectStepEnum(istep))) {
679 // Step may have been skipped. Restart.
680 goto loop_end;
681 }
682 if (print_object->is_step_started_unguarded(PrintObjectStepEnum(istep))) {
683 // This step is running, and the state cannot be changed due to the this->state_mutex() being locked.
684 // It is safe to manipulate m_stepmask of other PrintObjects and Print now.
685 running = true;
686 goto loop_end;
687 }
688 }
689 loop_end:
690 if (! running)
691 this->call_cancel_callback();
692 for (PrintObject *po : print_objects) {
693 for (int istep = 0; istep < n_object_steps; ++ istep)
694 po->enable_step_unguarded(PrintObjectStepEnum(istep), true);
695 for (int istep = n_object_steps; istep < PrintObjectStepEnumSize; ++ istep)
696 po->enable_step_unguarded(PrintObjectStepEnum(istep), false);
697 }
698 }
699
700 if (params.to_object_step != -1 || params.to_print_step != -1) {
701 // Limit the print steps.
702 size_t istep = (params.to_object_step != -1) ? 0 : size_t(params.to_print_step) + 1;
703 for (; istep < PrintStepEnumSize; ++ istep)
705 }
706 }
PrintStep PrintStepEnum
Definition PrintBase.hpp:578
static constexpr const size_t PrintStepEnumSize
Definition PrintBase.hpp:579
void enable_unguarded(StepType step, bool enable)
Definition PrintBase.hpp:150

◆ skirt()

const ExtrusionEntityCollection & Slic3r::Print::skirt ( ) const
inline
623{ return m_skirt; }

References m_skirt.

Referenced by Slic3r::GUI::GLCanvas3D::_load_print_toolpaths(), Slic3r::get_print_extrusions_extents(), Slic3r::Skirt::make_skirt_loops_per_extruder_1st_layer(), Slic3r::Skirt::make_skirt_loops_per_extruder_other_layers(), Slic3r::GCode::process_layer(), and Slic3r::Skirt::skirt_loops_per_extruder_all_printing().

+ Here is the caller graph for this function:

◆ skirt_first_layer_height()

double Slic3r::Print::skirt_first_layer_height ( ) const
827{
828 assert(! m_config.first_layer_height.percent);
829 return m_config.first_layer_height.value;
830}

References m_config.

Referenced by _make_skirt(), and _make_wipe_tower().

+ Here is the caller graph for this function:

◆ skirt_flow()

Flow Slic3r::Print::skirt_flow ( ) const
853{
854 ConfigOptionFloatOrPercent width = m_config.first_layer_extrusion_width;
855 if (width.value == 0)
856 width = m_print_regions.front()->config().perimeter_extrusion_width;
857 if (width.value == 0)
858 width = m_objects.front()->config().extrusion_width;
859
860 /* We currently use a random object's support material extruder.
861 While this works for most cases, we should probably consider all of the support material
862 extruders and take the one with, say, the smallest index;
863 The same logic should be applied to the code that selects the extruder during G-code
864 generation as well. */
867 width,
868 (float)m_config.nozzle_diameter.get_at(m_objects.front()->config().support_material_extruder-1),
869 (float)this->skirt_first_layer_height());
870}

References Slic3r::frPerimeter, m_config, m_objects, m_print_regions, and Slic3r::Flow::new_from_config_width().

Referenced by _make_skirt(), and Slic3r::GCode::process_layer().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ state_mutex()

std::mutex & Slic3r::PrintBase::state_mutex ( ) const
inlineprotectedinherited

◆ status_update_warnings()

void Slic3r::PrintBase::status_update_warnings ( int  step,
PrintStateBase::WarningLevel  warning_level,
const std::string &  message,
const PrintObjectBase print_object = nullptr 
)
protectedinherited
101{
102 if (m_status_callback) {
103 auto status = print_object ? SlicingStatus(*print_object, step) : SlicingStatus(*this, step);
104 m_status_callback(status);
105 }
106 else if (! message.empty())
107 printf("%s warning: %s\n", print_object ? "print_object" : "print", message.c_str());
108}

References Slic3r::PrintBase::m_status_callback.

Referenced by Slic3r::PrintBaseWithState< PrintStepEnumType, COUNT >::active_step_add_warning(), Slic3r::PrintBaseWithState< PrintStepEnumType, COUNT >::set_done(), and Slic3r::PrintObjectBase::status_update_warnings().

+ Here is the caller graph for this function:

◆ step_state_with_timestamp()

PrintStateBase::StateWithTimeStamp Slic3r::PrintBaseWithState< PrintStep , COUNT >::step_state_with_timestamp ( PrintStepEnum  step) const
inlineinherited
584{ return m_state.state_with_timestamp(step, this->state_mutex()); }
StateWithTimeStamp state_with_timestamp(StepType step, std::mutex &mtx) const
Definition PrintBase.hpp:118

◆ step_state_with_warnings()

PrintStateBase::StateWithWarnings Slic3r::PrintBaseWithState< PrintStep , COUNT >::step_state_with_warnings ( PrintStepEnum  step) const
inlineinherited
585{ return m_state.state_with_warnings(step, this->state_mutex()); }
StateWithWarnings state_with_warnings(StepType step, std::mutex &mtx) const
Definition PrintBase.hpp:124

◆ support_material_extruders()

std::vector< unsigned int > Slic3r::Print::support_material_extruders ( ) const
294{
295 std::vector<unsigned int> extruders;
296 bool support_uses_current_extruder = false;
297 auto num_extruders = (unsigned int)m_config.nozzle_diameter.size();
298
299 for (PrintObject *object : m_objects) {
300 if (object->has_support_material()) {
301 assert(object->config().support_material_extruder >= 0);
302 if (object->config().support_material_extruder == 0)
303 support_uses_current_extruder = true;
304 else {
305 unsigned int i = (unsigned int)object->config().support_material_extruder - 1;
306 extruders.emplace_back((i >= num_extruders) ? 0 : i);
307 }
308 assert(object->config().support_material_interface_extruder >= 0);
309 if (object->config().support_material_interface_extruder == 0)
310 support_uses_current_extruder = true;
311 else {
312 unsigned int i = (unsigned int)object->config().support_material_interface_extruder - 1;
313 extruders.emplace_back((i >= num_extruders) ? 0 : i);
314 }
315 }
316 }
317
318 if (support_uses_current_extruder)
319 // Add all object extruders to the support extruders as it is not know which one will be used to print supports.
321
322 sort_remove_duplicates(extruders);
323 return extruders;
324}

References Slic3r::append(), extruders(), m_config, m_objects, object_extruders(), and Slic3r::sort_remove_duplicates().

Referenced by extruders().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ technology()

PrinterTechnology Slic3r::Print::technology ( ) const
inlineoverridevirtualnoexcept

Implements Slic3r::PrintBase.

550{ return ptFFF; }
@ ptFFF
Definition Config.hpp:207

References Slic3r::ptFFF.

◆ throw_if_canceled()

◆ timestamp()

virtual Timestamp Slic3r::ObjectBase::timestamp ( ) const
inlinevirtualinherited

Reimplemented in Slic3r::ModelConfigObject, and Slic3r::ObjectWithTimestamp.

60{ return 0; }

Referenced by Slic3r::GUI::Plater::priv::undo_redo_to().

+ Here is the caller graph for this function:

◆ tool_ordering()

const ToolOrdering & Slic3r::Print::tool_ordering ( ) const
inline
638{ return m_tool_ordering; }

References m_tool_ordering.

Referenced by Slic3r::GCode::_do_export().

+ Here is the caller graph for this function:

◆ update_object_placeholders()

void Slic3r::PrintBase::update_object_placeholders ( DynamicConfig config,
const std::string &  default_ext 
) const
protectedinherited
21{
22 // get the first input file name
23 std::string input_file;
24 std::vector<std::string> v_scale;
25 int num_objects = 0;
26 int num_instances = 0;
27 for (const ModelObject *model_object : m_model.objects) {
28 ModelInstance *printable = nullptr;
29 for (ModelInstance *model_instance : model_object->instances)
30 if (model_instance->is_printable()) {
31 printable = model_instance;
32 ++ num_instances;
33 }
34 if (printable) {
35 ++ num_objects;
36 // CHECK_ME -> Is the following correct ?
37 v_scale.push_back("x:" + boost::lexical_cast<std::string>(printable->get_scaling_factor(X) * 100) +
38 "% y:" + boost::lexical_cast<std::string>(printable->get_scaling_factor(Y) * 100) +
39 "% z:" + boost::lexical_cast<std::string>(printable->get_scaling_factor(Z) * 100) + "%");
40 if (input_file.empty())
41 input_file = model_object->name.empty() ? model_object->input_file : model_object->name;
42 }
43 }
44
45 config.set_key_value("num_objects", new ConfigOptionInt(num_objects));
46 config.set_key_value("num_instances", new ConfigOptionInt(num_instances));
47
48 config.set_key_value("scale", new ConfigOptionStrings(v_scale));
49 if (! input_file.empty()) {
50 // get basename with and without suffix
51 const std::string input_filename = boost::filesystem::path(input_file).filename().string();
52 const std::string input_filename_base = input_filename.substr(0, input_filename.find_last_of("."));
53 config.set_key_value("input_filename", new ConfigOptionString(input_filename_base + default_ext));
54 config.set_key_value("input_filename_base", new ConfigOptionString(input_filename_base));
55 }
56}
@ Y
Definition libslic3r.h:99
@ Z
Definition libslic3r.h:100
@ X
Definition libslic3r.h:98

References Slic3r::ModelInstance::get_scaling_factor(), Slic3r::PrintBase::m_model, Slic3r::Model::objects, Slic3r::DynamicConfig::set_key_value(), Slic3r::X, Slic3r::Y, and Slic3r::Z.

Referenced by Slic3r::GCode::_do_export(), and Slic3r::PrintBase::output_filename().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ validate()

std::string Slic3r::Print::validate ( std::vector< std::string > *  warnings = nullptr) const
overridevirtual

Reimplemented from Slic3r::PrintBase.

472{
473 std::vector<unsigned int> extruders = this->extruders();
474
475 if (warnings) {
476 for (size_t a=0; a<extruders.size(); ++a)
477 for (size_t b=a+1; b<extruders.size(); ++b)
478 if (std::abs(m_config.bed_temperature.get_at(extruders[a]) - m_config.bed_temperature.get_at(extruders[b])) > 15
479 || std::abs(m_config.first_layer_bed_temperature.get_at(extruders[a]) - m_config.first_layer_bed_temperature.get_at(extruders[b])) > 15) {
480 warnings->emplace_back("_BED_TEMPS_DIFFER");
481 goto DONE;
482 }
483 DONE:;
484 }
485
486 if (m_objects.empty())
487 return _u8L("All objects are outside of the print volume.");
488
489 if (extruders.empty())
490 return _u8L("The supplied settings will cause an empty print.");
491
492 if (m_config.complete_objects) {
494 return _u8L("Some objects are too close; your extruder will collide with them.");
496 return _u8L("Some objects are too tall and cannot be printed without extruder collisions.");
497 }
498 else
500
501 if (m_config.avoid_crossing_perimeters && m_config.avoid_crossing_curled_overhangs) {
502 return _u8L("Avoid crossing perimeters option and avoid crossing curled overhangs option cannot be both enabled together.");
503 }
504
505 if (m_config.spiral_vase) {
506 size_t total_copies_count = 0;
507 for (const PrintObject *object : m_objects)
508 total_copies_count += object->instances().size();
509 // #4043
510 if (total_copies_count > 1 && ! m_config.complete_objects.value)
511 return _u8L("Only a single object may be printed at a time in Spiral Vase mode. "
512 "Either remove all but the last object, or enable sequential mode by \"complete_objects\".");
513 assert(m_objects.size() == 1);
514 if (m_objects.front()->all_regions().size() > 1)
515 return _u8L("The Spiral Vase option can only be used when printing single material objects.");
516 }
517
518 if (m_config.machine_limits_usage == MachineLimitsUsage::EmitToGCode && m_config.gcode_flavor == gcfKlipper)
519 return L("Machine limits cannot be emitted to G-Code when Klipper firmware flavor is used. "
520 "Change the value of machine_limits_usage.");
521
522 // Cache of layer height profiles for checking:
523 // 1) Whether all layers are synchronized if printing with wipe tower and / or unsynchronized supports.
524 // 2) Whether layer height is constant for Organic supports.
525 // 3) Whether build volume Z is not violated.
526 std::vector<std::vector<coordf_t>> layer_height_profiles;
527 auto layer_height_profile = [this, &layer_height_profiles](const size_t print_object_idx) -> const std::vector<coordf_t>& {
528 const PrintObject &print_object = *m_objects[print_object_idx];
529 if (layer_height_profiles.empty())
530 layer_height_profiles.assign(m_objects.size(), std::vector<coordf_t>());
531 std::vector<coordf_t> &profile = layer_height_profiles[print_object_idx];
532 if (profile.empty())
533 PrintObject::update_layer_height_profile(*print_object.model_object(), print_object.slicing_parameters(), profile);
534 return profile;
535 };
536
537 // Checks that the print does not exceed the max print height
538 for (size_t print_object_idx = 0; print_object_idx < m_objects.size(); ++ print_object_idx) {
539 const PrintObject &print_object = *m_objects[print_object_idx];
540 //FIXME It is quite expensive to generate object layers just to get the print height!
541 if (auto layers = generate_object_layers(print_object.slicing_parameters(), layer_height_profile(print_object_idx));
542 ! layers.empty() && layers.back() > this->config().max_print_height + EPSILON) {
543 return
544 // Test whether the last slicing plane is below or above the print volume.
545 0.5 * (layers[layers.size() - 2] + layers.back()) > this->config().max_print_height + EPSILON ?
546 format(_u8L("The object %1% exceeds the maximum build volume height."), print_object.model_object()->name) :
547 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) +
548 " " + _u8L("You might want to reduce the size of your model or change current print settings and retry.");
549 }
550 }
551
552 // Some of the objects has variable layer height applied by painting or by a table.
553 bool has_custom_layering = std::find_if(m_objects.begin(), m_objects.end(),
554 [](const PrintObject *object) { return object->model_object()->has_custom_layering(); })
555 != m_objects.end();
556
557 // Custom layering is not allowed for tree supports as of now.
558 for (size_t print_object_idx = 0; print_object_idx < m_objects.size(); ++ print_object_idx)
559 if (const PrintObject &print_object = *m_objects[print_object_idx];
560 print_object.has_support_material() && print_object.config().support_material_style.value == smsOrganic &&
561 print_object.model_object()->has_custom_layering()) {
562 if (const std::vector<coordf_t> &layers = layer_height_profile(print_object_idx); ! layers.empty())
563 if (! check_object_layers_fixed(print_object.slicing_parameters(), layers))
564 return _u8L("Variable layer height is not supported with Organic supports.");
565 }
566
567 if (this->has_wipe_tower() && ! m_objects.empty()) {
568 // Make sure all extruders use same diameter filament and have the same nozzle diameter
569 // EPSILON comparison is used for nozzles and 10 % tolerance is used for filaments
570 double first_nozzle_diam = m_config.nozzle_diameter.get_at(extruders.front());
571 double first_filament_diam = m_config.filament_diameter.get_at(extruders.front());
572 for (const auto& extruder_idx : extruders) {
573 double nozzle_diam = m_config.nozzle_diameter.get_at(extruder_idx);
574 double filament_diam = m_config.filament_diameter.get_at(extruder_idx);
575 if (nozzle_diam - EPSILON > first_nozzle_diam || nozzle_diam + EPSILON < first_nozzle_diam
576 || std::abs((filament_diam-first_filament_diam)/first_filament_diam) > 0.1)
577 return _u8L("The wipe tower is only supported if all extruders have the same nozzle diameter "
578 "and use filaments of the same diameter.");
579 }
580
581 if (m_config.gcode_flavor != gcfRepRapSprinter && m_config.gcode_flavor != gcfRepRapFirmware &&
582 m_config.gcode_flavor != gcfRepetier && m_config.gcode_flavor != gcfMarlinLegacy &&
583 m_config.gcode_flavor != gcfMarlinFirmware && m_config.gcode_flavor != gcfKlipper)
584 return _u8L("The Wipe Tower is currently only supported for the Marlin, Klipper, RepRap/Sprinter, RepRapFirmware and Repetier G-code flavors.");
585 if (! m_config.use_relative_e_distances)
586 return _u8L("The Wipe Tower is currently only supported with the relative extruder addressing (use_relative_e_distances=1).");
587 if (m_config.ooze_prevention && m_config.single_extruder_multi_material)
588 return _u8L("Ooze prevention is only supported with the wipe tower when 'single_extruder_multi_material' is off.");
589 if (m_config.use_volumetric_e)
590 return _u8L("The Wipe Tower currently does not support volumetric E (use_volumetric_e=0).");
591 if (m_config.complete_objects && extruders.size() > 1)
592 return _u8L("The Wipe Tower is currently not supported for multimaterial sequential prints.");
593
594 if (m_objects.size() > 1) {
595 const SlicingParameters &slicing_params0 = m_objects.front()->slicing_parameters();
596 size_t tallest_object_idx = 0;
597 for (size_t i = 1; i < m_objects.size(); ++ i) {
598 const PrintObject *object = m_objects[i];
599 const SlicingParameters &slicing_params = object->slicing_parameters();
600 if (std::abs(slicing_params.first_print_layer_height - slicing_params0.first_print_layer_height) > EPSILON ||
601 std::abs(slicing_params.layer_height - slicing_params0.layer_height ) > EPSILON)
602 return _u8L("The Wipe Tower is only supported for multiple objects if they have equal layer heights");
603 if (slicing_params.raft_layers() != slicing_params0.raft_layers())
604 return _u8L("The Wipe Tower is only supported for multiple objects if they are printed over an equal number of raft layers");
605 if (slicing_params0.gap_object_support != slicing_params.gap_object_support ||
606 slicing_params0.gap_support_object != slicing_params.gap_support_object)
607 return _u8L("The Wipe Tower is only supported for multiple objects if they are printed with the same support_material_contact_distance");
608 if (! equal_layering(slicing_params, slicing_params0))
609 return _u8L("The Wipe Tower is only supported for multiple objects if they are sliced equally.");
610 if (has_custom_layering) {
611 auto &lh = layer_height_profile(i);
612 auto &lh_tallest = layer_height_profile(tallest_object_idx);
613 if (*(lh.end()-2) > *(lh_tallest.end()-2))
614 tallest_object_idx = i;
615 }
616 }
617
618 if (has_custom_layering) {
619 for (size_t idx_object = 0; idx_object < m_objects.size(); ++ idx_object) {
620 if (idx_object == tallest_object_idx)
621 continue;
622 // Check that the layer height profiles are equal. This will happen when one object is
623 // a copy of another, or when a layer height modifier is used the same way on both objects.
624 // The latter case might create a floating point inaccuracy mismatch, so compare
625 // element-wise using an epsilon check.
626 size_t i = 0;
627 const coordf_t eps = 0.5 * EPSILON; // layers closer than EPSILON will be merged later. Let's make
628 // this check a bit more sensitive to make sure we never consider two different layers as one.
629 while (i < layer_height_profiles[idx_object].size()
630 && i < layer_height_profiles[tallest_object_idx].size()) {
631 if (i%2 == 0 && layer_height_profiles[tallest_object_idx][i] > layer_height_profiles[idx_object][layer_height_profiles[idx_object].size() - 2 ])
632 break;
633 if (std::abs(layer_height_profiles[idx_object][i] - layer_height_profiles[tallest_object_idx][i]) > eps)
634 return _u8L("The Wipe tower is only supported if all objects have the same variable layer height");
635 ++i;
636 }
637 }
638 }
639 }
640 }
641
642 {
643 // Find the smallest used nozzle diameter and the number of unique nozzle diameters.
644 double min_nozzle_diameter = std::numeric_limits<double>::max();
645 double max_nozzle_diameter = 0;
646 for (unsigned int extruder_id : extruders) {
647 double dmr = m_config.nozzle_diameter.get_at(extruder_id);
648 min_nozzle_diameter = std::min(min_nozzle_diameter, dmr);
649 max_nozzle_diameter = std::max(max_nozzle_diameter, dmr);
650 }
651
652#if 0
653 // We currently allow one to assign extruders with a higher index than the number
654 // of physical extruders the machine is equipped with, as the Printer::apply() clamps them.
655 unsigned int total_extruders_count = m_config.nozzle_diameter.size();
656 for (const auto& extruder_idx : extruders)
657 if ( extruder_idx >= total_extruders_count )
658 return _u8L("One or more object were assigned an extruder that the printer does not have.");
659#endif
660
661 auto validate_extrusion_width = [/*min_nozzle_diameter,*/ max_nozzle_diameter](const ConfigBase &config, const char *opt_key, double layer_height, std::string &err_msg) -> bool {
662 // This may change in the future, if we switch to "extrusion width wrt. nozzle diameter"
663 // instead of currently used logic "extrusion width wrt. layer height", see GH issues #1923 #2829.
664// double extrusion_width_min = config.get_abs_value(opt_key, min_nozzle_diameter);
665// double extrusion_width_max = config.get_abs_value(opt_key, max_nozzle_diameter);
666 double extrusion_width_min = config.get_abs_value(opt_key, layer_height);
667 double extrusion_width_max = config.get_abs_value(opt_key, layer_height);
668 if (extrusion_width_min == 0) {
669 // Default "auto-generated" extrusion width is always valid.
670 } else if (extrusion_width_min <= layer_height) {
671 err_msg = (boost::format(_u8L("%1%=%2% mm is too low to be printable at a layer height %3% mm")) % opt_key % extrusion_width_min % layer_height).str();
672 return false;
673 } else if (extrusion_width_max >= max_nozzle_diameter * 3.) {
674 err_msg = (boost::format(_u8L("Excessive %1%=%2% mm to be printable with a nozzle diameter %3% mm")) % opt_key % extrusion_width_max % max_nozzle_diameter).str();
675 return false;
676 }
677 return true;
678 };
679 for (PrintObject *object : m_objects) {
680 if (object->has_support_material()) {
681 if ((object->config().support_material_extruder == 0 || object->config().support_material_interface_extruder == 0) && max_nozzle_diameter - min_nozzle_diameter > EPSILON) {
682 // The object has some form of support and either support_material_extruder or support_material_interface_extruder
683 // will be printed with the current tool without a forced tool change. Play safe, assert that all object nozzles
684 // are of the same diameter.
685 return _u8L("Printing with multiple extruders of differing nozzle diameters. "
686 "If support is to be printed with the current extruder (support_material_extruder == 0 or support_material_interface_extruder == 0), "
687 "all nozzles have to be of the same diameter.");
688 }
689 if (this->has_wipe_tower() && object->config().support_material_style != smsOrganic) {
690 if (object->config().support_material_contact_distance == 0) {
691 // Soluble interface
692 if (! object->config().support_material_synchronize_layers)
693 return _u8L("For the Wipe Tower to work with the soluble supports, the support layers need to be synchronized with the object layers.");
694 } else {
695 // Non-soluble interface
696 if (object->config().support_material_extruder != 0 || object->config().support_material_interface_extruder != 0)
697 return _u8L("The Wipe Tower currently supports the non-soluble supports only if they are printed with the current extruder without triggering a tool change. "
698 "(both support_material_extruder and support_material_interface_extruder need to be set to 0).");
699 }
700 }
701 }
702
703 // Do we have custom support data that would not be used?
704 // Notify the user in that case.
705 if (! object->has_support() && warnings) {
706 for (const ModelVolume* mv : object->model_object()->volumes) {
707 bool has_enforcers = mv->is_support_enforcer() ||
708 (mv->is_model_part() && mv->supported_facets.has_facets(*mv, EnforcerBlockerType::ENFORCER));
709 if (has_enforcers) {
710 warnings->emplace_back("_SUPPORTS_OFF");
711 break;
712 }
713 }
714 }
715
716 // validate first_layer_height
717 assert(! m_config.first_layer_height.percent);
718 double first_layer_height = m_config.first_layer_height.value;
719 double first_layer_min_nozzle_diameter;
720 if (object->has_raft()) {
721 // if we have raft layers, only support material extruder is used on first layer
722 size_t first_layer_extruder = object->config().raft_layers == 1
723 ? object->config().support_material_interface_extruder-1
724 : object->config().support_material_extruder-1;
725 first_layer_min_nozzle_diameter = (first_layer_extruder == size_t(-1)) ?
726 min_nozzle_diameter :
727 m_config.nozzle_diameter.get_at(first_layer_extruder);
728 } else {
729 // if we don't have raft layers, any nozzle diameter is potentially used in first layer
730 first_layer_min_nozzle_diameter = min_nozzle_diameter;
731 }
732 if (first_layer_height > first_layer_min_nozzle_diameter)
733 return _u8L("First layer height can't be greater than nozzle diameter");
734
735 // validate layer_height
736 double layer_height = object->config().layer_height.value;
737 if (layer_height > min_nozzle_diameter)
738 return _u8L("Layer height can't be greater than nozzle diameter");
739
740 // Validate extrusion widths.
741 std::string err_msg;
742 if (! validate_extrusion_width(object->config(), "extrusion_width", layer_height, err_msg))
743 return err_msg;
744 if ((object->has_support() || object->has_raft()) && ! validate_extrusion_width(object->config(), "support_material_extrusion_width", layer_height, err_msg))
745 return err_msg;
746 for (const char *opt_key : { "perimeter_extrusion_width", "external_perimeter_extrusion_width", "infill_extrusion_width", "solid_infill_extrusion_width", "top_infill_extrusion_width" })
747 for (const PrintRegion &region : object->all_regions())
748 if (! validate_extrusion_width(region.config(), opt_key, layer_height, err_msg))
749 return err_msg;
750 }
751 }
752 {
753 bool before_layer_gcode_resets_extruder = boost::regex_search(m_config.before_layer_gcode.value, regex_g92e0);
754 bool layer_gcode_resets_extruder = boost::regex_search(m_config.layer_gcode.value, regex_g92e0);
755 if (m_config.use_relative_e_distances) {
756 // See GH issues #6336 #5073
757 if ((m_config.gcode_flavor == gcfMarlinLegacy || m_config.gcode_flavor == gcfMarlinFirmware) &&
758 ! before_layer_gcode_resets_extruder && ! layer_gcode_resets_extruder)
759 return _u8L("Relative extruder addressing requires resetting the extruder position at each layer to prevent loss of floating point accuracy. Add \"G92 E0\" to layer_gcode.");
760 } else if (before_layer_gcode_resets_extruder)
761 return _u8L("\"G92 E0\" was found in before_layer_gcode, which is incompatible with absolute extruder addressing.");
762 else if (layer_gcode_resets_extruder)
763 return _u8L("\"G92 E0\" was found in layer_gcode, which is incompatible with absolute extruder addressing.");
764 }
765
766 return std::string();
767}
static bool sequential_print_horizontal_clearance_valid(const Print &print, Polygons *polygons=nullptr)
Definition Print.cpp:387
static bool update_layer_height_profile(const ModelObject &model_object, const SlicingParameters &slicing_parameters, std::vector< coordf_t > &layer_height_profile)
Definition PrintObject.cpp:2592
@ gcfMarlinFirmware
Definition PrintConfig.hpp:35
@ gcfKlipper
Definition PrintConfig.hpp:35
@ gcfRepetier
Definition PrintConfig.hpp:35
@ gcfRepRapFirmware
Definition PrintConfig.hpp:35
@ gcfMarlinLegacy
Definition PrintConfig.hpp:35
@ gcfRepRapSprinter
Definition PrintConfig.hpp:35
bool check_object_layers_fixed(const SlicingParameters &slicing_params, const std::vector< coordf_t > &layer_height_profile)
Definition Slicing.cpp:651
bool equal_layering(const SlicingParameters &sp1, const SlicingParameters &sp2)
Definition Slicing.hpp:103
static bool sequential_print_vertical_clearance_valid(const Print &print)
Definition Print.cpp:455
boost::regex regex_g92e0
Definition Print.cpp:468
std::vector< coordf_t > generate_object_layers(const SlicingParameters &slicing_params, const std::vector< coordf_t > &layer_height_profile)
Definition Slicing.cpp:595
@ smsOrganic
Definition PrintConfig.hpp:90

References _u8L, Slic3r::check_object_layers_fixed(), clear(), Slic3r::PrintObject::config(), config(), Slic3r::EmitToGCode, Slic3r::ENFORCER, EPSILON, Slic3r::equal_layering(), extruders(), Slic3r::SlicingParameters::first_print_layer_height, Slic3r::format(), Slic3r::SlicingParameters::gap_object_support, Slic3r::SlicingParameters::gap_support_object, Slic3r::gcfKlipper, Slic3r::gcfMarlinFirmware, Slic3r::gcfMarlinLegacy, Slic3r::gcfRepetier, Slic3r::gcfRepRapFirmware, Slic3r::gcfRepRapSprinter, Slic3r::generate_object_layers(), Slic3r::PrintObject::has_raft(), Slic3r::PrintObject::has_support(), Slic3r::PrintObject::has_support_material(), has_wipe_tower(), L, Slic3r::layer_height(), Slic3r::SlicingParameters::layer_height, m_config, m_objects, m_sequential_print_clearance_contours, Slic3r::PrintObjectBase::model_object(), Slic3r::ModelObject::name, Slic3r::SlicingParameters::raft_layers(), Slic3r::regex_g92e0, sequential_print_horizontal_clearance_valid(), Slic3r::sequential_print_vertical_clearance_valid(), Slic3r::PrintObject::slicing_parameters(), Slic3r::smsOrganic, and Slic3r::PrintObject::update_layer_height_profile().

+ Here is the call graph for this function:

◆ wipe_tower_data()

const WipeTowerData & Slic3r::Print::wipe_tower_data ( size_t  extruders_cnt = 0) const
1378{
1379 // If the wipe tower wasn't created yet, make sure the depth and brim_width members are set to default.
1380 if (! is_step_done(psWipeTower) && extruders_cnt !=0) {
1381 const_cast<Print*>(this)->m_wipe_tower_data.brim_width = m_config.wipe_tower_brim_width;
1382
1383 // Calculating depth should take into account currently set wiping volumes.
1384 // For a long time, the initial preview would just use 900/width per toolchange (15mm on a 60mm wide tower)
1385 // and it worked well enough. Let's try to do slightly better by accounting for the purging volumes.
1386 std::vector<std::vector<float>> wipe_volumes = WipeTower::extract_wipe_volumes(m_config);
1387 std::vector<float> max_wipe_volumes;
1388 for (const std::vector<float>& v : wipe_volumes)
1389 max_wipe_volumes.emplace_back(*std::max_element(v.begin(), v.end()));
1390 float maximum = std::accumulate(max_wipe_volumes.begin(), max_wipe_volumes.end(), 0.f);
1391 maximum = maximum * extruders_cnt / max_wipe_volumes.size();
1392
1393 float width = float(m_config.wipe_tower_width);
1394 float layer_height = 0.2f; // just assume fixed value, it will still be better than before.
1395
1396 const_cast<Print*>(this)->m_wipe_tower_data.depth = (maximum/layer_height)/width;
1397 const_cast<Print*>(this)->m_wipe_tower_data.height = -1.f; // unknown yet
1398 }
1399
1400 return m_wipe_tower_data;
1401}
Print()=default
S::iterator begin(S &sh, const PathTag &)
Definition geometry_traits.hpp:614
S::iterator end(S &sh, const PathTag &)
Definition geometry_traits.hpp:620

References Slic3r::WipeTowerData::brim_width, Slic3r::WipeTowerData::depth, Slic3r::WipeTower::extract_wipe_volumes(), Slic3r::WipeTowerData::height, is_step_done(), Slic3r::layer_height(), m_config, m_wipe_tower_data, and Slic3r::psWipeTower.

Referenced by Slic3r::GCode::_do_export(), Slic3r::GUI::GLCanvas3D::_load_wipe_tower_toolpaths(), Slic3r::get_wipe_tower_extrusions_extents(), Slic3r::get_wipe_tower_priming_extrusions_extents(), Slic3r::GUI::GCodeViewer::load_shells(), and Slic3r::GUI::GLCanvas3D::reload_scene().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Friends And Related Symbol Documentation

◆ GCode

friend class GCode
friend

◆ GCodeProcessor

friend class GCodeProcessor
friend

◆ PrintObject

friend class PrintObject
friend

Member Data Documentation

◆ m_brim

ExtrusionEntityCollection Slic3r::Print::m_brim
private

Referenced by brim(), and process().

◆ m_cancel_callback

◆ m_cancel_status

◆ m_config

◆ m_conflict_result

ConflictResultOpt Slic3r::Print::m_conflict_result
private

Referenced by export_gcode(), and process().

◆ m_default_object_config

PrintObjectConfig Slic3r::Print::m_default_object_config
private

Referenced by default_object_config().

◆ m_default_region_config

PrintRegionConfig Slic3r::Print::m_default_region_config
private

Referenced by default_region_config().

◆ m_fake_wipe_tower

FakeWipeTower Slic3r::Print::m_fake_wipe_tower
private

Referenced by _make_wipe_tower(), and process().

◆ m_first_layer_convex_hull

Polygon Slic3r::Print::m_first_layer_convex_hull
private

◆ m_full_print_config

DynamicPrintConfig Slic3r::PrintBase::m_full_print_config
protectedinherited

◆ m_id

◆ m_model

◆ m_objects

◆ m_placeholder_parser

PlaceholderParser Slic3r::PrintBase::m_placeholder_parser
protectedinherited

◆ m_print_regions

◆ m_print_statistics

PrintStatistics Slic3r::Print::m_print_statistics
private

◆ m_sequential_print_clearance_contours

Polygons Slic3r::Print::m_sequential_print_clearance_contours
private

◆ m_skirt

ExtrusionEntityCollection Slic3r::Print::m_skirt
private

Referenced by _make_skirt(), process(), and skirt().

◆ m_skirt_convex_hull

Points Slic3r::Print::m_skirt_convex_hull
private

◆ m_state

PrintState<PrintStepEnum, COUNT> Slic3r::PrintBaseWithState< PrintStep , COUNT >::m_state
privateinherited

◆ m_state_mutex

std::mutex Slic3r::PrintBase::m_state_mutex
mutableprivateinherited

◆ m_status_callback

◆ m_tool_ordering

ToolOrdering Slic3r::Print::m_tool_ordering
private

Referenced by process(), and tool_ordering().

◆ m_wipe_tower_data

◆ PrintStepEnumSize

constexpr const size_t Slic3r::PrintBaseWithState< PrintStep , COUNT >::PrintStepEnumSize
staticconstexprinherited

◆ PrintTryCancel

friend Slic3r::PrintBase::PrintTryCancel
privateinherited

◆ s_last_id

size_t Slic3r::ObjectBase::s_last_id = 0
staticprivateinherited

The documentation for this class was generated from the following files: