OrcaSlicer latest
OrcaSlicer
Loading...
Searching...
No Matches
Slic3r::GUI::ArrangeJob Class Reference

#include </home/runner/work/OrcaSlicer/OrcaSlicer/src/slic3r/GUI/Jobs/ArrangeJob.hpp>

Inheritance diagram for Slic3r::GUI::ArrangeJob:
Collaboration diagram for Slic3r::GUI::ArrangeJob:

Public Types

enum  JobPrepareState { PREPARE_STATE_DEFAULT = 0 , PREPARE_STATE_MENU = 1 }

Public Member Functions

void prepare ()
void process (Ctl &ctl) override
 ArrangeJob ()
int status_range () const
void finalize (bool canceled, std::exception_ptr &e) override

Protected Member Functions

void check_unprintable ()

Private Types

using ArrangePolygon = arrangement::ArrangePolygon
using ArrangePolygons = arrangement::ArrangePolygons

Private Member Functions

void clear_input ()
void prepare_selected ()
void prepare_all ()
void prepare_partplate ()
void prepare_wipe_tower ()
void prepare_belt_regions (int num_plates)
void prepare_imex_zones ()
ArrangePolygon prepare_arrange_polygon (void *instance, const PartPlate *mapping_plate=nullptr)

Private Attributes

ArrangePolygons m_selected
ArrangePolygons m_unselected
ArrangePolygons m_unprintable
ArrangePolygons m_locked
std::vector< ModelInstance * > m_unarranged
std::map< int, ArrangePolygons > m_selected_groups
std::vector< int > m_uncompatible_plates
ImexArrangeInput m_imex
arrangement::ArrangeParams params
int current_plate_index = 0
Polygon bed_poly
Plater * m_plater
bool only_on_partplate {false}

Detailed Description

Member Typedef Documentation

◆ ArrangePolygon

◆ ArrangePolygons

Member Enumeration Documentation

◆ JobPrepareState

Enumerator
PREPARE_STATE_DEFAULT 
PREPARE_STATE_MENU 
22 {
25 };
@ PREPARE_STATE_MENU
Definition Job.hpp:24
@ PREPARE_STATE_DEFAULT
Definition Job.hpp:23

Constructor & Destructor Documentation

◆ ArrangeJob()

Slic3r::GUI::ArrangeJob::ArrangeJob ( )
807: m_plater{wxGetApp().plater()} { }
Plater * m_plater
Definition ArrangeJob.hpp:61

References m_plater, and Slic3r::GUI::plater().

Here is the call graph for this function:

Member Function Documentation

◆ check_unprintable()

void Slic3r::GUI::ArrangeJob::check_unprintable ( )
protected
698{
699 for (auto it = m_selected.begin(); it != m_selected.end();) {
700 if (it->poly.area() < 0.001 || it->height>params.printable_height)
701 {
702#if SAVE_ARRANGE_POLY
703 SVG svg(data_dir() + "/SVG/arrange_unprintable_"+it->name+".svg", get_extents(it->poly));
704 if (svg.is_opened())
705 svg.draw_outline(it->poly);
706#endif
707 if (it->poly.area() < 0.001) {
708 auto msg = (boost::format(
709 _u8L("Object %s has zero size and can't be arranged."))
710 % it->name).str();
711 m_plater->get_notification_manager()->push_notification(NotificationType::BBLPlateInfo,
713 }
714 m_unprintable.push_back(*it);
715 it = m_selected.erase(it);
716 }
717 else
718 it++;
719 }
720}
ArrangePolygons m_unprintable
Definition ArrangeJob.hpp:37
ArrangePolygons m_selected
Definition ArrangeJob.hpp:37
arrangement::ArrangeParams params
Definition ArrangeJob.hpp:58
@ WarningNotificationLevel
Definition NotificationManager.hpp:224
@ BBLPlateInfo
Definition NotificationManager.hpp:157
const std::string & data_dir()
Definition utils.cpp:365
BoundingBox get_extents(const ExPolygonsWithIds &e)
Definition Emboss.cpp:1374
#define _u8L(s)
Definition I18N.hpp:11

References _u8L, Slic3r::GUI::BBLPlateInfo, Slic3r::data_dir(), Slic3r::SVG::draw_outline(), Slic3r::get_extents(), Slic3r::SVG::is_opened(), m_plater, m_selected, m_unprintable, params, and Slic3r::GUI::NotificationManager::WarningNotificationLevel.

Referenced by prepare().

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

◆ clear_input()

void Slic3r::GUI::ArrangeJob::clear_input ( )
private
227{
228 const Model &model = m_plater->model();
229
230 size_t count = 0, cunprint = 0; // To know how much space to reserve
231 for (auto obj : model.objects)
232 for (auto mi : obj->instances)
233 mi->printable ? count++ : cunprint++;
234
235 params.nonprefered_regions.clear();
236 m_selected.clear();
237 m_unselected.clear();
238 m_unprintable.clear();
239 m_locked.clear();
240 m_unarranged.clear();
241 m_uncompatible_plates.clear();
242 m_selected.reserve(count + 1 /* for optional wti */);
243 m_unselected.reserve(count + 1 /* for optional wti */);
244 m_unprintable.reserve(cunprint /* for optional wti */);
245 m_locked.reserve(count + 1 /* for optional wti */);
247}
static unsigned int count
Definition AuxiliaryDataViewModel.cpp:246
ArrangePolygons m_locked
Definition ArrangeJob.hpp:37
int current_plate_index
Definition ArrangeJob.hpp:59
std::vector< ModelInstance * > m_unarranged
Definition ArrangeJob.hpp:38
ArrangePolygons m_unselected
Definition ArrangeJob.hpp:37
std::vector< int > m_uncompatible_plates
Definition ArrangeJob.hpp:40

References count, current_plate_index, m_locked, m_plater, m_selected, m_unarranged, m_uncompatible_plates, m_unprintable, m_unselected, Slic3r::Model::objects, and params.

Referenced by prepare_all(), prepare_partplate(), and prepare_selected().

Here is the caller graph for this function:

◆ finalize()

void Slic3r::GUI::ArrangeJob::finalize ( bool canceled,
std::exception_ptr & e )
overridevirtual

Reimplemented from Slic3r::GUI::Job.

819 {
820 try {
821 if (eptr)
822 std::rethrow_exception(eptr);
823 } catch (libnest2d::GeometryException &) {
824 show_error(m_plater, _(L("Arrange failed. "
825 "Found some exceptions when processing object geometries.")));
826 eptr = nullptr;
827 } catch (...) {
828 eptr = std::current_exception();
829 }
830
831 if (canceled || eptr)
832 return;
833
834 // Nothing could be placed: leave the plates and the instances exactly as they were.
835 // Rebuilding the plates would only re-home the instances by their bounds, which moves
836 // a too large item to whichever plate it happens to reach over.
837 const bool nothing_arranged = !m_selected.empty() &&
838 std::all_of(m_selected.begin(), m_selected.end(), [](const ArrangePolygon &ap) { return !ap.is_arranged(); });
839 if (nothing_arranged) {
840 m_plater->get_notification_manager()->close_notification_of_type(NotificationType::ArrangeOngoing);
841 m_plater->m_arrange_running.store(false);
842 return;
843 }
844
845 // Unprintable items go to the last virtual bed
846 int beds = 0;
847
848 //BBS: partplate
849 PartPlateList& plate_list = m_plater->get_partplate_list();
850 //clear all the relations before apply the arrangement results
851 if (only_on_partplate) {
852 plate_list.clear(false, false, true, current_plate_index);
853 }
854 else
855 plate_list.clear(false, false, true, -1);
856 //BBS: adjust the bed_index, create new plates, get the max bed_index
857 for (ArrangePolygon& ap : m_selected) {
858 //if (ap.bed_idx < 0) continue; // bed_idx<0 means unarrangable
859 //BBS: partplate postprocess
861 plate_list.postprocess_bed_index_for_current_plate(ap);
862 else
863 plate_list.postprocess_bed_index_for_selected(ap);
864
865 beds = std::max(ap.bed_idx, beds);
866
867 BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(": arrange selected %4%: bed_id %1%, trans {%2%,%3%}") % ap.bed_idx % unscale<double>(ap.translation(X)) % unscale<double>(ap.translation(Y)) % ap.name;
868 }
869
870 //BBS: adjust the bed_index, create new plates, get the max bed_index
871 for (ArrangePolygon& ap : m_unselected)
872 {
873 if (ap.is_virt_object)
874 continue;
875
876 //BBS: partplate postprocess
878 plate_list.postprocess_bed_index_for_unselected(ap);
879
880 beds = std::max(ap.bed_idx, beds);
881 BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(":arrange unselected %4%: bed_id %1%, trans {%2%,%3%}") % ap.bed_idx % unscale<double>(ap.translation(X)) % unscale<double>(ap.translation(Y)) % ap.name;
882 }
883
884 for (ArrangePolygon& ap : m_locked) {
885 beds = std::max(ap.bed_idx, beds);
886
887 plate_list.postprocess_arrange_polygon(ap, false);
888
889 ap.apply();
890 }
891
892 // Apply the arrange result to all selected objects
893 for (ArrangePolygon& ap : m_selected) {
894 //BBS: partplate postprocess
895 plate_list.postprocess_arrange_polygon(ap, true);
896
897 ap.apply();
898 }
899
900 // Apply the arrange result to unselected objects(due to the sukodu-style column changes, the position of unselected may also be modified)
901 for (ArrangePolygon& ap : m_unselected)
902 {
903 if (ap.is_virt_object)
904 continue;
905
906 //BBS: partplate postprocess
907 plate_list.postprocess_arrange_polygon(ap, false);
908
909 ap.apply();
910 }
911
912 // Move the unprintable items to the last virtual bed.
913 // Note ap.apply() moves relatively according to bed_idx, so we need to subtract the orignal bed_idx
914 for (ArrangePolygon& ap : m_unprintable) {
915 ap.bed_idx = beds + 1;
916 plate_list.postprocess_arrange_polygon(ap, true);
917
918 ap.apply();
919 BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(":arrange m_unprintable: name: %4%, bed_id %1%, trans {%2%,%3%}") % ap.bed_idx % unscale<double>(ap.translation(X)) % unscale<double>(ap.translation(Y)) % ap.name;
920 }
921
922 {
923 Slic3r::LifecycleEventContext ctx;
925 ctx.msg = "arranged";
927 }
928
929 m_plater->update();
930 // BBS
931 //wxGetApp().obj_manipul()->set_dirty();
932
933 if (!m_unarranged.empty()) {
934 std::set<std::string> names;
935 for (ModelInstance *mi : m_unarranged)
936 names.insert(mi->get_object()->name);
937
938 m_plater->get_notification_manager()->push_notification(GUI::format(
939 _L("Arrangement ignored the following objects which can't fit into a single bed:\n%s"),
940 concat_strings(names, "\n")));
941 }
942 m_plater->get_notification_manager()->close_notification_of_type(NotificationType::ArrangeOngoing);
943
944 //BBS: reload all objects due to arrange. Plates are never recycled here: arranging
945 // must not remove a plate the user created, even when the arrange left it empty.
946 if (only_on_partplate) {
947 plate_list.rebuild_plates_after_arrangement(false, true, current_plate_index);
948 }
949 else {
950 plate_list.rebuild_plates_after_arrangement(false, true);
951 }
952
953 // unlock the plates we just locked
954 for (int i : m_uncompatible_plates)
955 plate_list.get_plate(i)->lock(false);
956
957 // BBS: update slice context and gcode result.
958 m_plater->update_slicing_context_to_current_partplate();
959
960 wxGetApp().obj_list()->reload_all_plates();
961
962 m_plater->update();
963
964 m_plater->m_arrange_running.store(false);
965}
#define _(s)
Definition 3mf.cpp:306
#define L(s)
Definition ExtrusionEntity.cpp:25
#define _L(s)
Definition OBJ.cpp:34
arrangement::ArrangePolygon ArrangePolygon
Definition ArrangeJob.hpp:33
bool only_on_partplate
Definition ArrangeJob.hpp:64
void show_error(wxWindow *parent, const wxString &message, bool has_code_excerpts)
Definition GUI.cpp:296
@ ArrangeOngoing
Definition NotificationManager.hpp:155
std::string format(const char *fmt, TArgs &&... args)
Definition format.hpp:36
static std::string concat_strings(const std::set< std::string > &strings, const std::string &delim="\n")
Definition ArrangeJob.cpp:809
std::string msg
Definition LifecycleEvents.hpp:83
@ ObjectTransformed
Definition LifecycleEvents.hpp:38
@ Ok
Definition LifecycleEvents.hpp:68
T unscale(Q v)
Definition libslic3r.h:138
LifecycleEvtCode code
Definition LifecycleEvents.hpp:79
@ Y
Definition libslic3r.h:142
@ X
Definition libslic3r.h:141
void fire_lifecycle_event(LifecycleEvent event, const LifecycleEventContext &ctx)
Definition LifecycleEvents.hpp:234

References _, _L, Slic3r::arrangement::ArrangePolygon::apply(), Slic3r::GUI::ArrangeOngoing, Slic3r::arrangement::ArrangePolygon::bed_idx, Slic3r::GUI::PartPlateList::clear(), Slic3r::LifecycleEventContext::code, Slic3r::GUI::concat_strings(), current_plate_index, Slic3r::fire_lifecycle_event(), Slic3r::GUI::format(), Slic3r::GUI::PartPlateList::get_plate(), Slic3r::arrangement::ArrangePolygon::is_virt_object, L, Slic3r::GUI::PartPlate::lock(), m_locked, m_plater, m_selected, m_unarranged, m_uncompatible_plates, m_unprintable, m_unselected, Slic3r::LifecycleEventContext::msg, Slic3r::arrangement::ArrangePolygon::name, Slic3r::ObjectTransformed, Slic3r::Ok, only_on_partplate, Slic3r::GUI::PartPlateList::postprocess_arrange_polygon(), Slic3r::GUI::PartPlateList::postprocess_bed_index_for_current_plate(), Slic3r::GUI::PartPlateList::postprocess_bed_index_for_selected(), Slic3r::GUI::PartPlateList::postprocess_bed_index_for_unselected(), Slic3r::GUI::PartPlateList::rebuild_plates_after_arrangement(), Slic3r::GUI::show_error(), Slic3r::arrangement::ArrangePolygon::translation, Slic3r::unscale(), Slic3r::X, and Slic3r::Y.

Here is the call graph for this function:

◆ prepare()

void Slic3r::GUI::ArrangeJob::prepare ( )
633{
634 m_plater->get_notification_manager()->push_notification(NotificationType::ArrangeOngoing,
636 m_plater->get_notification_manager()->bbl_close_plateinfo_notification();
637
639
640 //BBS update extruder params and speed table before arranging
641 const Slic3r::DynamicPrintConfig& config = wxGetApp().preset_bundle->full_config();
642 auto& print = wxGetApp().plater()->get_partplate_list().get_current_fff_print();
643 auto print_config = print.config();
644 int numExtruders = wxGetApp().preset_bundle->filament_presets.size();
645
646 Model::setExtruderParams(config, numExtruders);
647 Model::setPrintSpeedTable(config, print_config);
648
649 int state = m_plater->get_prepare_state();
651 only_on_partplate = false;
652 prepare_all();
653 }
655 only_on_partplate = true; // only arrange items on current plate
657 }
658
659 // After prepare_all(), which locks the plates it must leave alone.
661
662
663#if SAVE_ARRANGE_POLY
664 if (1)
665 { // subtract excluded region and get a polygon bed
666 auto& print = wxGetApp().plater()->get_partplate_list().get_current_fff_print();
667 auto print_config = print.config();
668 bed_poly.points = get_bed_shape(*m_plater->config());
669 Polygons exclude_polys = get_bed_excluded_area(print_config);
670 bed_poly = diff({ bed_poly }, exclude_polys)[0];
671 }
672
673 BoundingBox bbox = bed_poly.bounding_box();
674 Point center = bbox.center();
675 auto polys_to_draw = m_selected;
676 for (auto it = polys_to_draw.begin(); it != polys_to_draw.end(); it++) {
677 it->poly.translate(center);
678 bbox.merge(it->poly);
679 }
680 SVG svg("SVG/arrange_poly.svg", bbox);
681 if (svg.is_opened()) {
682 svg.draw_outline(bed_poly);
683 //svg.draw_grid(bbox, "gray", scale_(0.05));
684 std::vector<std::string> color_array = { "red","black","yellow","gree","blue" };
685 for (auto it = polys_to_draw.begin(); it != polys_to_draw.end(); it++) {
686 std::string color = color_array[(it - polys_to_draw.begin()) % color_array.size()];
687 svg.add_comment(it->name);
688 svg.draw_text(get_extents(it->poly).min, it->name.c_str(), color.c_str());
689 svg.draw_outline(it->poly, color);
690 }
691 }
692#endif
693
695}
PointType min
Definition BoundingBox.hpp:20
void prepare_partplate()
Definition ArrangeJob.cpp:532
void prepare_all()
Definition ArrangeJob.cpp:342
void prepare_imex_zones()
Definition ArrangeJob.cpp:605
Polygon bed_poly
Definition ArrangeJob.hpp:60
void check_unprintable()
Definition ArrangeJob.cpp:697
@ RegularNotificationLevel
Definition NotificationManager.hpp:216
static void setPrintSpeedTable(const DynamicPrintConfig &config, const PrintConfig &print_config)
Definition Model.cpp:3209
static void setExtruderParams(const DynamicPrintConfig &config, int extruders_count)
Definition Model.cpp:3267
arrangement::ArrangeParams init_arrange_params(Plater *p)
Definition ArrangeJob.cpp:989
Kernel::Point_3 Point
Definition MeshRepair.cpp:81
void center(ExPolygonsWithIds &e)
Definition Emboss.cpp:1382
std::vector< Polygon, PointsAllocator< Polygon > > Polygons
Definition Polygon.hpp:22
Polygons get_bed_excluded_area(const PrintConfig &cfg)
Definition PrintConfig.cpp:14376
Slic3r::Polygons diff(const Slic3r::Polygon &subject, const Slic3r::Polygon &clip, ApplySafetyOffset do_safety_offset)
Definition ClipperUtils.cpp:731
Points get_bed_shape(const DynamicPrintConfig &config, bool use_share)
Definition PrintConfig.cpp:13837

References _u8L, Slic3r::SVG::add_comment(), Slic3r::GUI::ArrangeOngoing, bed_poly, Slic3r::BoundingBoxBase< PointType, APointsType >::center(), Slic3r::center(), check_unprintable(), Slic3r::diff(), Slic3r::SVG::draw_outline(), Slic3r::SVG::draw_text(), Slic3r::get_bed_excluded_area(), Slic3r::get_bed_shape(), Slic3r::get_extents(), Slic3r::GUI::init_arrange_params(), Slic3r::SVG::is_opened(), m_plater, m_selected, Slic3r::BoundingBoxBase< PointType, APointsType >::merge(), Slic3r::BoundingBoxBase< PointType, APointsType >::min, only_on_partplate, params, prepare_all(), prepare_imex_zones(), prepare_partplate(), Slic3r::GUI::Job::PREPARE_STATE_DEFAULT, Slic3r::GUI::Job::PREPARE_STATE_MENU, Slic3r::GUI::NotificationManager::RegularNotificationLevel, Slic3r::Model::setExtruderParams(), Slic3r::Model::setPrintSpeedTable(), and Slic3r::DynamicConfig::size().

Referenced by process().

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

◆ prepare_all()

void Slic3r::GUI::ArrangeJob::prepare_all ( )
private
342 {
343 clear_input();
344
345 PartPlateList& plate_list = m_plater->get_partplate_list();
346 for (size_t i = 0; i < plate_list.get_plate_count(); i++) {
347 PartPlate* plate = plate_list.get_plate(i);
348 bool same_as_global_print_seq = true;
349 plate->get_real_print_seq(&same_as_global_print_seq);
350 if (plate->is_locked() == false && !same_as_global_print_seq) {
351 plate->lock(true);
352 m_uncompatible_plates.push_back(i);
353 }
354 }
355
356
357 Model &model = m_plater->model();
358 bool selected_is_locked = false;
359
360 // Go through the objects and check if inside the selection
361 for (size_t oidx = 0; oidx < model.objects.size(); ++oidx) {
362 ModelObject *mo = model.objects[oidx];
363 if (is_belt_purge_prism(mo))
364 continue;
365
366 for (size_t i = 0; i < mo->instances.size(); ++i) {
367 ModelInstance * mi = mo->instances[i];
368 ArrangePolygon&& ap = prepare_arrange_polygon(mo->instances[i]);
370 ap, *mo, plate_list, wxGetApp().preset_bundle->full_config());
371 //BBS: partplate_list preprocess
372 //remove the locked plate's instances, neither in selected, nor in un-selected
373 bool locked = plate_list.preprocess_arrange_polygon(oidx, i, ap, true);
374 if (!locked)
375 {
376 ArrangePolygons& cont = mo->instances[i]->printable ? m_selected :m_unprintable;
377
378 ap.itemid = cont.size();
379 cont.emplace_back(std::move(ap));
380 }
381 else
382 {
383 //skip this object due to be locked in plate
384 ap.itemid = m_locked.size();
385 m_locked.emplace_back(std::move(ap));
386 selected_is_locked = true;
387 BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(": skip locked instance, obj_id %1%, instance_id %2%") % oidx % i;
388 }
389 }
390 }
391
392
393 // If the selection was empty arrange everything
394 //if (m_selected.empty()) m_selected.swap(m_unselected);
395 if (m_selected.empty()) {
396 if (!selected_is_locked) {
397 m_plater->get_notification_manager()->push_notification(NotificationType::BBLPlateInfo,
398 NotificationManager::NotificationLevel::WarningNotificationLevel, into_u8(_L("No arrangeable objects are selected.")));
399 }
400 else {
401 m_plater->get_notification_manager()->push_notification(NotificationType::BBLPlateInfo,
402 NotificationManager::NotificationLevel::WarningNotificationLevel, into_u8(_L("All the selected objects are on a locked plate.\nCannot auto-arrange these objects.")));
403 }
404 }
405
407
408 const DynamicPrintConfig& current_config = wxGetApp().preset_bundle->prints.get_edited_preset().config;
409 bool enable_wrapping = current_config.option<ConfigOptionBool>("enable_wrapping_detection")->value;
410
411 // add the virtual object into unselect list if has
412 plate_list.preprocess_exclude_areas(m_unselected, wxGetApp().preset_bundle->full_config(), enable_wrapping, MAX_NUM_PLATES);
413 prepare_belt_regions(MAX_NUM_PLATES);
414}
void clear_input()
Definition ArrangeJob.cpp:226
arrangement::ArrangePolygons ArrangePolygons
Definition ArrangeJob.hpp:34
void prepare_belt_regions(int num_plates)
Definition ArrangeJob.cpp:176
void prepare_wipe_tower()
Definition ArrangeJob.cpp:442
ArrangePolygon prepare_arrange_polygon(void *instance, const PartPlate *mapping_plate=nullptr)
Definition ArrangeJob.cpp:249
static void set_arrange_polygon_bed_exclusion_extruders_for_all_plates(ArrangePolygon &polygon, const ModelObject &object, PartPlateList &plate_list, const DynamicPrintConfig &config)
Definition ArrangeJob.cpp:83
std::string into_u8(const wxString &str)
Definition GUI.cpp:549
static bool is_belt_purge_prism(const ModelObject *mo)
Definition ArrangeJob.cpp:149

References _L, Slic3r::GUI::BBLPlateInfo, clear_input(), Slic3r::GUI::PartPlateList::get_plate(), Slic3r::GUI::PartPlateList::get_plate_count(), Slic3r::GUI::PartPlate::get_real_print_seq(), Slic3r::ModelObject::instances, Slic3r::GUI::into_u8(), Slic3r::GUI::is_belt_purge_prism(), Slic3r::GUI::PartPlate::is_locked(), Slic3r::arrangement::ArrangePolygon::itemid, Slic3r::GUI::PartPlate::lock(), m_locked, m_plater, m_selected, m_uncompatible_plates, m_unprintable, m_unselected, Slic3r::Model::objects, Slic3r::ConfigBase::option(), prepare_arrange_polygon(), prepare_belt_regions(), prepare_wipe_tower(), Slic3r::GUI::PartPlateList::preprocess_arrange_polygon(), Slic3r::GUI::PartPlateList::preprocess_exclude_areas(), Slic3r::GUI::set_arrange_polygon_bed_exclusion_extruders_for_all_plates(), and Slic3r::GUI::NotificationManager::WarningNotificationLevel.

Referenced by prepare().

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

◆ prepare_arrange_polygon()

ArrangePolygon Slic3r::GUI::ArrangeJob::prepare_arrange_polygon ( void * instance,
const PartPlate * mapping_plate = nullptr )
private
250{
251 ModelInstance* instance = (ModelInstance*)model_instance;
252 const Slic3r::DynamicPrintConfig& config = wxGetApp().preset_bundle->full_config();
253 ArrangePolygon polygon = get_instance_arrange_poly(instance, config);
254 if (mapping_plate != nullptr)
255 set_arrange_polygon_bed_exclusion_extruders(polygon, *instance->get_object(), *mapping_plate, config);
256 return polygon;
257}
void set_arrange_polygon_bed_exclusion_extruders(ArrangePolygon &polygon, const ModelObject &object, const PartPlate &plate, const DynamicPrintConfig &config)
Definition ArrangeJob.cpp:53
ArrangePolygon get_instance_arrange_poly(ModelInstance *instance, const Slic3r::DynamicPrintConfig &config)
Definition ModelArrange.cpp:135

References Slic3r::get_instance_arrange_poly(), Slic3r::ModelInstance::get_object(), and Slic3r::GUI::set_arrange_polygon_bed_exclusion_extruders().

Referenced by prepare_all(), prepare_partplate(), and prepare_selected().

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

◆ prepare_belt_regions()

void Slic3r::GUI::ArrangeJob::prepare_belt_regions ( int num_plates)
private
177{
178 if (!params.is_belt || params.is_seq_print)
179 return;
180 const DynamicPrintConfig &config = wxGetApp().preset_bundle->full_config();
181 const BoundingBoxf bed = get_extents(config.opt<ConfigOptionPoints>("printable_area")->values);
182 const bool belt_is_y = params.belt_axis == 1;
183 std::vector<BoundingBoxf> regions;
184
185 std::set<int> filaments;
186 for (const ArrangePolygons *items : { &m_selected, &m_unselected })
187 for (const ArrangePolygon &ap : *items)
188 if (!ap.is_virt_object)
189 filaments.insert(ap.extrude_ids.begin(), ap.extrude_ids.end());
190 if (config.opt_bool("enable_belt_purge_tower") && filaments.size() > 1) {
191 // The prism is at least one millimetre per island plus the gaps between them.
192 const int islands = int(filaments.size()) - 1;
193 const double width = std::max(config.opt_float("belt_purge_tower_width"), 2. * islands - 1.) + 1.; // + the prism's edge inset
194 BoundingBoxf strip = bed;
195 if (belt_is_y)
196 strip.min.x() = std::max(bed.min.x(), bed.max.x() - width);
197 else
198 strip.min.y() = std::max(bed.min.y(), bed.max.y() - width);
199 regions.push_back(strip);
200 }
201
202 // Virtual items are inflated by the one millimetre exclusion gap already.
203 const double brim = config.opt_enum<BrimType>("brim_type") == btNoBrim ? 0. :
204 config.opt_float("brim_width") + config.opt_float("brim_object_gap") + config.opt_float("extra_brim_width") - 1.;
205 if (brim > 0.) {
206 regions.emplace_back(bed.min, Vec2d(bed.min.x() + brim, bed.max.y()));
207 regions.emplace_back(Vec2d(bed.max.x() - brim, bed.min.y()), bed.max);
208 regions.emplace_back(bed.min, Vec2d(bed.max.x(), bed.min.y() + brim));
209 regions.emplace_back(Vec2d(bed.min.x(), bed.max.y() - brim), bed.max);
210 }
211
212 for (int j = 0; j < num_plates; ++j)
213 for (size_t i = 0; i < regions.size(); ++i) {
215 ap.poly.contour = scaled(regions[i]).polygon();
216 ap.translation = Vec2crd(0, 0);
217 ap.rotation = 0.f;
218 ap.is_virt_object = true;
219 ap.bed_idx = j;
220 ap.height = 1;
221 ap.name = "BeltRegion" + std::to_string(i);
222 m_unselected.emplace_back(std::move(ap));
223 }
224}
void polygon(Polygon *polygon) const
Definition BoundingBox.cpp:20
coord_t width(const BoundingBox &box)
Definition Arrange.cpp:1184
BrimType
Definition PrintConfig.hpp:454
@ btNoBrim
Definition PrintConfig.hpp:461
BoundingBox scaled(const BoundingBoxf &bb)
Definition BoundingBox.hpp:284
Eigen::Matrix< coord_t, 2, 1, Eigen::DontAlign > Vec2crd
Definition Point.hpp:52
Eigen::Matrix< double, 2, 1, Eigen::DontAlign > Vec2d
Definition Point.hpp:67

References Slic3r::arrangement::ArrangePolygon::bed_idx, Slic3r::btNoBrim, Slic3r::ExPolygon::contour, Slic3r::get_extents(), Slic3r::arrangement::ArrangePolygon::height, Slic3r::arrangement::ArrangePolygon::is_virt_object, m_selected, m_unselected, Slic3r::BoundingBoxBase< PointType, APointsType >::max, Slic3r::BoundingBoxBase< PointType, APointsType >::min, Slic3r::arrangement::ArrangePolygon::name, Slic3r::DynamicConfig::opt(), Slic3r::DynamicConfig::opt_bool(), Slic3r::DynamicConfig::opt_enum(), Slic3r::DynamicConfig::opt_float(), params, Slic3r::arrangement::ArrangePolygon::poly, Slic3r::BoundingBox::polygon(), Slic3r::arrangement::ArrangePolygon::rotation, Slic3r::scaled(), Slic3r::arrangement::ArrangePolygon::translation, and Slic3r::ConfigOptionVector< T >::values.

Referenced by prepare_all(), prepare_partplate(), and prepare_selected().

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

◆ prepare_imex_zones()

void Slic3r::GUI::ArrangeJob::prepare_imex_zones ( )
private
606{
607 m_imex = {};
608 PartPlateList& plate_list = m_plater->get_partplate_list();
609 std::vector<PartPlate*> plates;
611 plates.push_back(plate_list.get_curr_plate());
612 else
613 for (int i = 0; i < plate_list.get_plate_count(); ++i)
614 if (!plate_list.get_plate(i)->is_locked())
615 plates.push_back(plate_list.get_plate(i));
616
617 for (PartPlate* plate : plates) {
618 std::optional<ImexArrangeZones> zones;
619 if (const std::optional<BoundingBoxf> pz = plate ? plate->imex_primary_zone() : std::nullopt) {
620 const Vec2d o = plate->get_origin().head<2>();
621 zones = ImexArrangeZones{BoundingBoxf(Vec2d(pz->min - o), Vec2d(pz->max - o)), {}};
622 for (const BoundingBoxf3& strip : plate->imex_collision_zones())
623 zones->collision_zones.emplace_back(Vec2d(strip.min.head<2>() - o), Vec2d(strip.max.head<2>() - o));
624 }
625 m_imex.beds.push_back(std::move(zones));
626 }
627 m_imex.adds_plates = !only_on_partplate;
628 m_imex.read_config(wxGetApp().preset_bundle->full_config());
629}
ImexArrangeInput m_imex
Definition ArrangeJob.hpp:56

References Slic3r::ImexArrangeZones::collision_zones, Slic3r::GUI::PartPlateList::get_curr_plate(), Slic3r::GUI::PartPlateList::get_plate(), Slic3r::GUI::PartPlateList::get_plate_count(), Slic3r::GUI::PartPlate::is_locked(), m_imex, m_plater, and only_on_partplate.

Referenced by prepare().

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

◆ prepare_partplate()

void Slic3r::GUI::ArrangeJob::prepare_partplate ( )
private
532 {
533 clear_input();
534
535 PartPlateList& plate_list = m_plater->get_partplate_list();
536 PartPlate* plate = plate_list.get_curr_plate();
537 current_plate_index = plate_list.get_curr_plate_index();
538 assert(plate != nullptr);
539
540 if (plate->empty())
541 {
542 //no instances on this plate
543 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": no instances in current plate!");
544
545 return;
546 }
547
548 if (plate->is_locked()) {
549 m_plater->get_notification_manager()->push_notification(NotificationType::BBLPlateInfo,
550 NotificationManager::NotificationLevel::WarningNotificationLevel, into_u8(_L("This plate is locked.\nCannot auto-arrange on this plate.")));
551 return;
552 }
553
554 Model& model = m_plater->model();
555
556 // Go through the objects and check if inside the selection
557 for (size_t oidx = 0; oidx < model.objects.size(); ++oidx)
558 {
559 ModelObject* mo = model.objects[oidx];
560 if (is_belt_purge_prism(mo))
561 continue;
562 for (size_t inst_idx = 0; inst_idx < mo->instances.size(); ++inst_idx)
563 {
564 bool in_plate = plate->contain_instance(oidx, inst_idx) || plate->intersect_instance(oidx, inst_idx);
565 ArrangePolygon&& ap = prepare_arrange_polygon(mo->instances[inst_idx], plate);
566
567 ArrangePolygons& cont = mo->instances[inst_idx]->printable ?
568 (in_plate ? m_selected : m_unselected) :
570 bool locked = plate_list.preprocess_arrange_polygon_other_locked(oidx, inst_idx, ap, in_plate);
571 if (!locked)
572 {
573 ap.itemid = cont.size();
574 cont.emplace_back(std::move(ap));
575 }
576 else
577 {
578 //skip this object due to be not in current plate, treated as locked
579 ap.itemid = m_locked.size();
580 m_locked.emplace_back(std::move(ap));
581 //BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(": skip locked instance, obj_id %1%, name %2%") % oidx % mo->name;
582 }
583 }
584 }
585
586 // BBS
587 if (auto wti = get_wipe_tower(*m_plater, current_plate_index)) {
589 m_unselected.emplace_back(std::move(ap));
590 }
591
592 const DynamicPrintConfig &current_config = wxGetApp().preset_bundle->prints.get_edited_preset().config;
593 bool enable_wrapping = current_config.option<ConfigOptionBool>("enable_wrapping_detection")->value;
594
595 // add the virtual object into unselect list if has
596 plate_list.preprocess_exclude_areas(
597 m_unselected, wxGetApp().preset_bundle->full_config(), enable_wrapping, current_plate_index + 1);
599}
static WipeTower get_wipe_tower(const Plater &plater, int plate_idx)
Definition ArrangeJob.cpp:156
arrangement::ArrangePolygon get_wipetower_arrange_poly(WipeTower *tower)
Definition ArrangeJob.cpp:161

References _L, Slic3r::GUI::BBLPlateInfo, clear_input(), Slic3r::GUI::PartPlate::contain_instance(), current_plate_index, Slic3r::GUI::PartPlate::empty(), Slic3r::GUI::PartPlateList::get_curr_plate(), Slic3r::GUI::PartPlateList::get_curr_plate_index(), Slic3r::GUI::get_wipe_tower(), Slic3r::GUI::get_wipetower_arrange_poly(), Slic3r::ModelObject::instances, Slic3r::GUI::PartPlate::intersect_instance(), Slic3r::GUI::into_u8(), Slic3r::GUI::is_belt_purge_prism(), Slic3r::GUI::PartPlate::is_locked(), Slic3r::arrangement::ArrangePolygon::itemid, m_locked, m_plater, m_selected, m_unprintable, m_unselected, Slic3r::Model::objects, Slic3r::ConfigBase::option(), prepare_arrange_polygon(), prepare_belt_regions(), Slic3r::GUI::PartPlateList::preprocess_arrange_polygon_other_locked(), Slic3r::GUI::PartPlateList::preprocess_exclude_areas(), and Slic3r::GUI::NotificationManager::WarningNotificationLevel.

Referenced by prepare().

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

◆ prepare_selected()

void Slic3r::GUI::ArrangeJob::prepare_selected ( )
private
259 {
260 PartPlateList& plate_list = m_plater->get_partplate_list();
261
262 clear_input();
263
264 Model& model = m_plater->model();
265 bool selected_is_locked = false;
266 //BBS: remove logic for unselected object
267 //double stride = bed_stride_x(m_plater);
268
269 std::vector<const Selection::InstanceIdxsList*>
270 obj_sel(model.objects.size(), nullptr);
271
272 for (auto& s : m_plater->get_selection().get_content())
273 if (s.first < int(obj_sel.size()))
274 obj_sel[size_t(s.first)] = &s.second;
275
276 // Go through the objects and check if inside the selection
277 for (size_t oidx = 0; oidx < model.objects.size(); ++oidx) {
278 const Selection::InstanceIdxsList* instlist = obj_sel[oidx];
279 ModelObject* mo = model.objects[oidx];
280 if (is_belt_purge_prism(mo))
281 continue;
282
283 std::vector<bool> inst_sel(mo->instances.size(), false);
284
285 if (instlist)
286 for (auto inst_id : *instlist)
287 inst_sel[size_t(inst_id)] = true;
288
289 for (size_t i = 0; i < inst_sel.size(); ++i) {
290 ModelInstance* mi = mo->instances[i];
291 ArrangePolygon&& ap = prepare_arrange_polygon(mo->instances[i]);
293 ap, *mo, plate_list, wxGetApp().preset_bundle->full_config());
294 //BBS: partplate_list preprocess
295 //remove the locked plate's instances, neither in selected, nor in un-selected
296 bool locked = plate_list.preprocess_arrange_polygon(oidx, i, ap, inst_sel[i]);
297 if (!locked)
298 {
299 ArrangePolygons& cont = mo->instances[i]->printable ?
300 (inst_sel[i] ? m_selected :
301 m_unselected) :
303
304 ap.itemid = cont.size();
305 cont.emplace_back(std::move(ap));
306 }
307 else
308 {
309 //skip this object due to be locked in plate
310 ap.itemid = m_locked.size();
311 m_locked.emplace_back(std::move(ap));
312 if (inst_sel[i])
313 selected_is_locked = true;
314 BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(": skip locked instance, obj_id %1%, instance_id %2%, name %3%") % oidx % i % mo->name;
315 }
316 }
317 }
318
319
320 // If the selection was empty arrange everything
321 //if (m_selected.empty()) m_selected.swap(m_unselected);
322 if (m_selected.empty()) {
323 if (!selected_is_locked)
325 else {
326 m_plater->get_notification_manager()->push_notification(NotificationType::BBLPlateInfo,
327 NotificationManager::NotificationLevel::WarningNotificationLevel, into_u8(_L("All the selected objects are on a locked plate.\nCannot auto-arrange these objects.")));
328 }
329 }
330
332 prepare_belt_regions(MAX_NUM_PLATES);
333
334
335 // The strides have to be removed from the fixed items. For the
336 // arrangeable (selected) items bed_idx is ignored and the
337 // translation is irrelevant.
338 //BBS: remove logic for unselected object
339 //for (auto &p : m_unselected) p.translation(X) -= p.bed_idx * stride;
340}
std::set< int > InstanceIdxsList
Definition Selection.hpp:110

References _L, Slic3r::GUI::BBLPlateInfo, clear_input(), Slic3r::ModelObject::instances, Slic3r::GUI::into_u8(), Slic3r::GUI::is_belt_purge_prism(), Slic3r::arrangement::ArrangePolygon::itemid, m_locked, m_plater, m_selected, m_unprintable, m_unselected, Slic3r::ModelObject::name, Slic3r::Model::objects, prepare_arrange_polygon(), prepare_belt_regions(), prepare_wipe_tower(), Slic3r::GUI::PartPlateList::preprocess_arrange_polygon(), Slic3r::GUI::set_arrange_polygon_bed_exclusion_extruders_for_all_plates(), and Slic3r::GUI::NotificationManager::WarningNotificationLevel.

Here is the call graph for this function:

◆ prepare_wipe_tower()

void Slic3r::GUI::ArrangeJob::prepare_wipe_tower ( )
private
443{
444 bool need_wipe_tower = false;
445
446 // if wipe tower is explicitly disabled, no need to estimate
447 DynamicPrintConfig& current_config = wxGetApp().preset_bundle->prints.get_edited_preset().config;
448 auto op = current_config.option("enable_prime_tower");
449 bool enable_prime_tower = op && op->getBool();
450 if (!enable_prime_tower || params.is_seq_print) return;
451
452 // Belt printers have no classic wipe tower; purging goes into the belt purge
453 // prism, whose strip prepare_belt_regions() reserves.
454 if (params.is_belt)
455 return;
456
457 bool smooth_timelapse = false;
458 auto sop = current_config.option("timelapse_type");
459 if (sop) { smooth_timelapse = sop->getInt() == TimelapseType::tlSmooth; }
460 if (smooth_timelapse) { need_wipe_tower = true; }
461
462 // estimate if we need wipe tower for all plates:
463 // need wipe tower if some object has multiple extruders (has paint-on colors or support material)
464 for (const auto& item : m_selected) {
465 std::set<int> obj_extruders;
466 obj_extruders.insert(item.extrude_ids.begin(), item.extrude_ids.end());
467 if (obj_extruders.size() > 1) {
468 need_wipe_tower = true;
469 BOOST_LOG_TRIVIAL(info) << "arrange: need wipe tower because object " << item.name << " has multiple extruders (has paint-on colors)";
470 break;
471 }
472 }
473
474 // if multile extruders have same bed temp, we need wipe tower
475 // 允许不同材料落在相同盘,且所有选定对象中使用了多种热床温度相同的材料
476 if (params.allow_multi_materials_on_same_plate) {
477 std::map<int, std::set<int>> bedTemp2extruderIds;
478 for (const auto& item : m_selected)
479 for (auto id : item.extrude_ids) { bedTemp2extruderIds[item.bed_temp].insert(id); }
480 for (const auto& be : bedTemp2extruderIds) {
481 if (be.second.size() > 1) {
482 need_wipe_tower = true;
483 BOOST_LOG_TRIVIAL(info) << "arrange: need wipe tower because allow_multi_materials_on_same_plate=true and we have multiple extruders of same type";
484 break;
485 }
486 }
487 }
488 BOOST_LOG_TRIVIAL(info) << "arrange: need_wipe_tower=" << need_wipe_tower;
489
490
491 ArrangePolygon wipe_tower_ap;
492 wipe_tower_ap.name = "WipeTower";
493 wipe_tower_ap.is_virt_object = true;
494 wipe_tower_ap.is_wipe_tower = true;
495 const GLCanvas3D* canvas3D = static_cast<const GLCanvas3D*>(m_plater->canvas3D());
496
497 std::set<int> extruder_ids;
498 PartPlateList& ppl = wxGetApp().plater()->get_partplate_list();
499 int plate_count = ppl.get_plate_count();
500 if (!only_on_partplate) {
501 extruder_ids = ppl.get_extruders(true);
502 }
503
504 int bedid_unlocked = 0;
505 for (int bedid = 0; bedid < MAX_NUM_PLATES; bedid++) {
506 int plate_index_valid = std::min(bedid, plate_count - 1);
507 PartPlate* pl = ppl.get_plate(plate_index_valid);
508 if(bedid<plate_count && pl->is_locked())
509 continue;
510 if (auto wti = get_wipe_tower(*m_plater, bedid)) {
511 // wipe tower is already there
512 wipe_tower_ap = get_wipetower_arrange_poly(&wti);
513 wipe_tower_ap.bed_idx = bedid_unlocked;
514 m_unselected.emplace_back(wipe_tower_ap);
515 }
516 else if (need_wipe_tower) {
517 if (only_on_partplate) {
518 auto plate_extruders = pl->get_extruders(true);
519 extruder_ids.clear();
520 extruder_ids.insert(plate_extruders.begin(), plate_extruders.end());
521 }
522 wipe_tower_ap = estimate_wipe_tower_info(bedid, extruder_ids);
523 wipe_tower_ap.bed_idx = bedid_unlocked;
524 m_unselected.emplace_back(wipe_tower_ap);
525 }
526 bedid_unlocked++;
527 }
528}
arrangement::ArrangePolygon estimate_wipe_tower_info(int plate_index, std::set< int > &extruder_ids)
Definition ArrangeJob.cpp:416
@ tlSmooth
Definition PrintConfig.hpp:470

References Slic3r::arrangement::ArrangePolygon::bed_idx, Slic3r::GUI::estimate_wipe_tower_info(), Slic3r::GUI::PartPlate::get_extruders(), Slic3r::GUI::PartPlateList::get_extruders(), Slic3r::GUI::PartPlateList::get_plate(), Slic3r::GUI::PartPlateList::get_plate_count(), Slic3r::GUI::get_wipe_tower(), Slic3r::GUI::get_wipetower_arrange_poly(), Slic3r::ConfigOption::getBool(), Slic3r::arrangement::ArrangePolygon::is_virt_object, Slic3r::arrangement::ArrangePolygon::is_wipe_tower, m_plater, m_selected, m_unselected, Slic3r::arrangement::ArrangePolygon::name, only_on_partplate, Slic3r::ConfigBase::option(), params, and Slic3r::tlSmooth.

Referenced by prepare_all(), and prepare_selected().

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

◆ process()

void Slic3r::GUI::ArrangeJob::process ( Ctl & ctl)
overridevirtual

Implements Slic3r::GUI::Job.

723{
724 static const auto arrangestr = _u8L("Arranging");
725 ctl.update_status(0, arrangestr);
726 ctl.call_on_main_thread([this]{ prepare(); }).wait();;
727
728 auto & partplate_list = m_plater->get_partplate_list();
729
730 const Slic3r::DynamicPrintConfig& global_config = wxGetApp().preset_bundle->full_config();
731 PresetBundle* preset_bundle = wxGetApp().preset_bundle;
732 const bool is_bbl = wxGetApp().preset_bundle->is_bbl_vendor();
733 if (is_bbl && params.avoid_extrusion_cali_region && global_config.opt_bool("scan_first_layer"))
734 partplate_list.preprocess_nonprefered_areas(m_unselected, MAX_NUM_PLATES);
735
740
741 Points bedpts = get_shrink_bedpts(m_plater->config(),params);
742
743 // Keep the parts on IDEX/IQEX plates in their primary zones; see ImexArranger.
744 const ImexArranger imex(m_imex, params, bedpts);
745 bedpts = imex.bed_shape();
746 imex.add_keep_outs(m_unselected);
747
748 bool enable_wrapping = global_config.option<ConfigOptionBool>("enable_wrapping_detection")->value;
749 partplate_list.preprocess_exclude_areas(params.excluded_regions, global_config, enable_wrapping, 1, scale_(1));
750
751 BOOST_LOG_TRIVIAL(debug) << "arrange bedpts:" << bedpts[0].transpose() << ", " << bedpts[1].transpose() << ", " << bedpts[2].transpose() << ", " << bedpts[3].transpose();
752
753 params.stopcondition = [&ctl]() { return ctl.was_canceled(); };
754
755 params.progressind = [this, &ctl](unsigned num_finished, std::string str = "") {
756 // TRN Progress status. %1% is the name of the object being arranged.
757 ctl.update_status(num_finished * 100 / status_range(), GUI::format(_u8L("Arranging %1%"), str));
758 };
759
760 {
761 BOOST_LOG_TRIVIAL(warning)<< "Arrange full params: "<< params.to_json();
762 BOOST_LOG_TRIVIAL(info) << boost::format("arrange: items selected before arranging: %1%") % m_selected.size();
763 for (auto selected : m_selected) {
764 BOOST_LOG_TRIVIAL(debug) << selected.name << ", extruder: " << selected.extrude_ids.back() << ", bed: " << selected.bed_idx << ", filemant_type:" << selected.filament_temp_type
765 << ", trans: " << selected.translation.transpose();
766 }
767 BOOST_LOG_TRIVIAL(debug) << "arrange: items unselected before arrange: " << m_unselected.size();
768 for (auto item : m_unselected)
769 BOOST_LOG_TRIVIAL(debug) << item.name << ", bed: " << item.bed_idx << ", trans: " << item.translation.transpose()
770 <<", bbox:"<<get_extents(item.poly).min.transpose()<<","<<get_extents(item.poly).max.transpose();
771 }
772
773 const ArrangePolygons before = imex.active() ? m_selected : ArrangePolygons();
775 if (!ctl.was_canceled())
776 imex.finish(m_selected, before, m_unselected, params);
777
778 // sort by item id
779 std::sort(m_selected.begin(), m_selected.end(), [](auto a, auto b) {return a.itemid < b.itemid; });
780 {
781 BOOST_LOG_TRIVIAL(info) << boost::format("arrange: items selected after arranging: %1%") % m_selected.size();
782 for (auto selected : m_selected)
783 BOOST_LOG_TRIVIAL(debug) << selected.name << ", extruder: " << selected.extrude_ids.back() << ", bed: " << selected.bed_idx
784 << ", bed_temp: " << selected.first_bed_temp << ", print_temp: " << selected.print_temp
785 << ", trans: " << unscale<double>(selected.translation(X)) << ","<< unscale<double>(selected.translation(Y));
786 BOOST_LOG_TRIVIAL(debug) << "arrange: items unselected after arrange: "<< m_unselected.size();
787 for (auto item : m_unselected)
788 BOOST_LOG_TRIVIAL(debug) << item.name << ", bed: " << item.bed_idx << ", trans: " << item.translation.transpose();
789 }
790
791 // put unpackable items to m_unprintable so they goes outside
792 bool we_have_unpackable_items = false;
793 for (auto item : m_selected) {
794 if (item.bed_idx < 0) {
795 //BBS: already processed in m_selected
796 //m_unprintable.push_back(std::move(item));
797 we_have_unpackable_items = true;
798 }
799 }
800
801 // finalize just here.
802 ctl.update_status(100,
803 ctl.was_canceled() ? _u8L("Arranging canceled.") :
804 we_have_unpackable_items ? _u8L("Arranging complete, but some items were not able to be arranged. Reduce spacing and try again.") : _u8L("Arranging done."));
805}
PointType max
Definition BoundingBox.hpp:21
ConfigOption * option(const t_config_option_key &opt_key, bool create=false)
Definition Config.hpp:2768
bool opt_bool(const t_config_option_key &opt_key) const
Definition Config.hpp:3072
void prepare()
Definition ArrangeJob.cpp:632
int status_range() const
Definition ArrangeJob.hpp:95
#define scale_(val)
Definition libslic3r.h:106
void update_arrange_params(ArrangeParams &params, const DynamicPrintConfig *print_cfg, const ArrangePolygons &selected)
Definition Arrange.cpp:148
void update_selected_items_inflation(ArrangePolygons &selected, const DynamicPrintConfig *print_cfg, ArrangeParams &params)
Definition Arrange.cpp:163
void update_selected_items_axis_align(ArrangePolygons &selected, const DynamicPrintConfig *print_cfg, const ArrangeParams &params)
Definition Arrange.cpp:234
Points get_shrink_bedpts(const DynamicPrintConfig *print_cfg, const ArrangeParams &params)
Definition Arrange.cpp:339
void arrange(ArrangePolygons &items, const ArrangePolygons &excludes, const Points &bed, const ArrangeParams &params)
Definition Arrange.cpp:1280
void update_unselected_items_inflation(ArrangePolygons &unselected, const DynamicPrintConfig *print_cfg, const ArrangeParams &params)
Definition Arrange.cpp:213
std::vector< Point, PointsAllocator< Point > > Points
Definition Point.hpp:73

References _u8L, Slic3r::ImexArranger::active(), Slic3r::ImexArranger::add_keep_outs(), Slic3r::arrangement::arrange(), Slic3r::ImexArranger::bed_shape(), Slic3r::GUI::Job::Ctl::call_on_main_thread(), Slic3r::ImexArranger::finish(), Slic3r::GUI::format(), Slic3r::get_extents(), Slic3r::PresetBundle::is_bbl_vendor(), m_imex, m_plater, m_selected, m_unselected, Slic3r::BoundingBoxBase< PointType, APointsType >::max, Slic3r::BoundingBoxBase< PointType, APointsType >::min, Slic3r::DynamicConfig::opt_bool(), Slic3r::ConfigBase::option(), params, prepare(), scale_, status_range(), Slic3r::unscale(), Slic3r::GUI::Job::Ctl::update_status(), Slic3r::GUI::Job::Ctl::was_canceled(), Slic3r::X, and Slic3r::Y.

Here is the call graph for this function:

◆ status_range()

int Slic3r::GUI::ArrangeJob::status_range ( ) const
inline
96 {
97 // ensure finalize() is called after all operations in process() is finished.
98 return int(m_selected.size() + m_unprintable.size() + 1);
99 }

References m_selected, and m_unprintable.

Referenced by process().

Here is the caller graph for this function:

Member Data Documentation

◆ bed_poly

Polygon Slic3r::GUI::ArrangeJob::bed_poly
private

Referenced by prepare().

◆ current_plate_index

int Slic3r::GUI::ArrangeJob::current_plate_index = 0
private

◆ m_imex

ImexArrangeInput Slic3r::GUI::ArrangeJob::m_imex
private

Referenced by prepare_imex_zones(), and process().

◆ m_locked

ArrangePolygons Slic3r::GUI::ArrangeJob::m_locked
private

◆ m_plater

◆ m_selected

◆ m_selected_groups

std::map<int, ArrangePolygons> Slic3r::GUI::ArrangeJob::m_selected_groups
private

◆ m_unarranged

std::vector<ModelInstance*> Slic3r::GUI::ArrangeJob::m_unarranged
private

Referenced by clear_input(), and finalize().

◆ m_uncompatible_plates

std::vector<int> Slic3r::GUI::ArrangeJob::m_uncompatible_plates
private

Referenced by clear_input(), finalize(), and prepare_all().

◆ m_unprintable

ArrangePolygons Slic3r::GUI::ArrangeJob::m_unprintable
private

◆ m_unselected

◆ only_on_partplate

bool Slic3r::GUI::ArrangeJob::only_on_partplate {false}
private

◆ params


The documentation for this class was generated from the following files:
  • /home/runner/work/OrcaSlicer/OrcaSlicer/src/slic3r/GUI/Jobs/ArrangeJob.hpp
  • /home/runner/work/OrcaSlicer/OrcaSlicer/src/slic3r/GUI/Jobs/ArrangeJob.cpp