ENH: auto arrange wipe tower when changing bed
Allow wipe tower to be arranged with highest priority. jira: STUDIO-10225 Change-Id: Ia88374666906afd226bf8580d28fe788dad5f4c0
This commit is contained in:
parent
e684f8fcc6
commit
2dfb9a15f4
|
@ -559,10 +559,12 @@ public:
|
|||
template<class Range = ConstItemRange<typename Base::DefaultIter>>
|
||||
PackResult trypack(Item& item,
|
||||
const Range& remaining = Range()) {
|
||||
auto result = _trypack(item, remaining);
|
||||
if (item.is_wipe_tower) {
|
||||
PackResult result1 = _trypack_with_original_pos(item);
|
||||
if (result1.score() >= 0 && result1.score() < LARGE_COST_TO_REJECT) return result1;
|
||||
}
|
||||
|
||||
// Experimental
|
||||
// if(!result) repack(item, result);
|
||||
auto result = _trypack(item, remaining);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -1003,6 +1005,101 @@ private:
|
|||
item.rotation(final_rot);
|
||||
}
|
||||
|
||||
#ifdef SVGTOOLS_HPP
|
||||
if (config_.save_svg) {
|
||||
svg::SVGWriter<RawShape> svgwriter;
|
||||
Box binbb2(binbb.width() * 2, binbb.height() * 2, binbb.center()); // expand bbox to allow object be drawed outside
|
||||
svgwriter.setSize(binbb2);
|
||||
svgwriter.conf_.x0 = binbb.width();
|
||||
svgwriter.conf_.y0 = -binbb.height() / 2; // origin is top left corner
|
||||
svgwriter.add_comment("bed");
|
||||
svgwriter.writeShape(box2RawShape(binbb), "none", "black");
|
||||
svgwriter.add_comment("nfps");
|
||||
for (int i = 0; i < nfps.size(); i++) svgwriter.writeShape(nfps[i], "none", "blue");
|
||||
for (int i = 0; i < items_.size(); i++) {
|
||||
svgwriter.add_comment(items_[i].get().name);
|
||||
svgwriter.writeItem(items_[i], "none", "black");
|
||||
}
|
||||
svgwriter.add_comment("merged_pile_");
|
||||
for (int i = 0; i < merged_pile_.size(); i++) svgwriter.writeShape(merged_pile_[i], "none", "yellow");
|
||||
svgwriter.add_comment("current item");
|
||||
svgwriter.writeItem(item, "red", "red", 2);
|
||||
|
||||
std::stringstream ss;
|
||||
ss.setf(std::ios::fixed | std::ios::showpoint);
|
||||
ss.precision(1);
|
||||
ss << "t=" << round(item.translation().x() / 1e6) << ","
|
||||
<< round(item.translation().y() / 1e6)
|
||||
//<< "-rot=" << round(item.rotation().toDegrees())
|
||||
<< "-sco=" << round(global_score);
|
||||
svgwriter.draw_text(20, 20, ss.str(), "blue", 20);
|
||||
ss.str("");
|
||||
ss << "items.size=" << items_.size() << "-merged_pile.size=" << merged_pile_.size();
|
||||
svgwriter.draw_text(20, 40, ss.str(), "blue", 20);
|
||||
svgwriter.save(boost::filesystem::path("C:/Users/arthur.tang/AppData/Roaming/BambuStudioInternal/SVG") /
|
||||
("nfpplacer_" + std::to_string(plate_id) + "_" + ss.str() + "_" + item.name + ".svg"));
|
||||
}
|
||||
#endif
|
||||
|
||||
if(can_pack) {
|
||||
ret = PackResult(item);
|
||||
ret.score_ = global_score;
|
||||
//merged_pile_ = nfp::merge(merged_pile_, item.transformedShape());
|
||||
} else {
|
||||
ret = PackResult(best_overfit);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
PackResult _trypack_with_original_pos(Item &item)
|
||||
{
|
||||
PackResult ret;
|
||||
|
||||
bool can_pack = false;
|
||||
double best_overfit = std::numeric_limits<double>::max();
|
||||
double global_score = std::numeric_limits<double>::max();
|
||||
|
||||
auto initial_tr = item.translation();
|
||||
auto initial_rot = item.rotation();
|
||||
Vertex final_tr = initial_tr;
|
||||
Radians final_rot = initial_rot;
|
||||
Shapes nfps;
|
||||
|
||||
auto binbb = sl::boundingBox(bin_);
|
||||
|
||||
for (auto &it : items_) { config_.progressFunc("existing object: " + it.get().name); }
|
||||
|
||||
// item won't overlap with virtual objects if it's inside or touches NFP
|
||||
// @return 1 if current item overlaps with virtual objects, 0 otherwise
|
||||
auto overlapWithVirtObject = [&]() -> double {
|
||||
if (items_.empty()) return 0;
|
||||
nfps = calcnfp(item, binbb, Lvl<MaxNfpLevel::value>());
|
||||
auto v = item.referenceVertex();
|
||||
for (const RawShape &nfp : nfps) {
|
||||
if (sl::isInside(v, nfp) || sl::touches(v, nfp)) { return 0; }
|
||||
}
|
||||
return 1;
|
||||
};
|
||||
|
||||
{
|
||||
for (auto rot : item.allowed_rotations) {
|
||||
item.translation(initial_tr);
|
||||
item.rotation(initial_rot + rot);
|
||||
|
||||
if (0==overlapWithVirtObject()) {
|
||||
can_pack = true;
|
||||
final_tr = initial_tr;
|
||||
final_rot = initial_rot + rot;
|
||||
global_score = 0.3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
item.translation(final_tr);
|
||||
item.rotation(final_rot);
|
||||
}
|
||||
|
||||
#ifdef SVGTOOLS_HPP
|
||||
if (config_.save_svg) {
|
||||
svg::SVGWriter<RawShape> svgwriter;
|
||||
|
|
|
@ -118,6 +118,11 @@ public:
|
|||
int j = 0;
|
||||
while(!was_packed && !cancelled()) {
|
||||
for(; j < placers.size() && !was_packed && !cancelled(); j++) {
|
||||
if (it->get().is_wipe_tower && it->get().binId() != placers[j].plateID()) {
|
||||
if (this->unfitindicator_)
|
||||
this->unfitindicator_(it->get().name + " cant be placed in plate_id=" + std::to_string(j) + "/" + std::to_string(placers.size()) + ", continue to next plate");
|
||||
continue;
|
||||
}
|
||||
result = placers[j].pack(*it, rem(it, store_));
|
||||
score = result.score();
|
||||
score_all_plates = score;
|
||||
|
@ -184,11 +189,11 @@ public:
|
|||
if(!was_packed){
|
||||
if (this->unfitindicator_ && !placers.empty())
|
||||
this->unfitindicator_(it->get().name + " not fit! height=" +std::to_string(it->get().height)
|
||||
+ " ,plate_id=" + std::to_string(j-1)
|
||||
+ " ,plate_id=" + std::to_string(j)
|
||||
+ ", score=" + std::to_string(score)
|
||||
+ ", best_bed_id=" + std::to_string(best_bed_id)
|
||||
+ ", score_all_plates=" + std::to_string(score_all_plates)
|
||||
+", overfit=" + std::to_string(result.overfit()));
|
||||
+", item.bed_id=" + std::to_string(it->get().binId()));
|
||||
|
||||
placers.emplace_back(bin);
|
||||
placers.back().plateID(placers.size() - 1);
|
||||
|
|
|
@ -1033,6 +1033,7 @@ wxDEFINE_EVENT(EVT_GLCANVAS_REMOVE_OBJECT, SimpleEvent);
|
|||
wxDEFINE_EVENT(EVT_GLCANVAS_ARRANGE, SimpleEvent);
|
||||
//BBS: add arrange and orient event
|
||||
wxDEFINE_EVENT(EVT_GLCANVAS_ARRANGE_PARTPLATE, SimpleEvent);
|
||||
wxDEFINE_EVENT(EVT_GLCANVAS_ARRANGE_OUTPLATE, SimpleEvent);
|
||||
wxDEFINE_EVENT(EVT_GLCANVAS_ORIENT, SimpleEvent);
|
||||
wxDEFINE_EVENT(EVT_GLCANVAS_ORIENT_PARTPLATE, SimpleEvent);
|
||||
wxDEFINE_EVENT(EVT_GLCANVAS_SELECT_CURR_PLATE_ALL, SimpleEvent);
|
||||
|
|
|
@ -162,6 +162,7 @@ wxDECLARE_EVENT(EVT_GLCANVAS_REMOVE_OBJECT, SimpleEvent);
|
|||
wxDECLARE_EVENT(EVT_GLCANVAS_ARRANGE, SimpleEvent);
|
||||
//BBS: add arrange and orient event
|
||||
wxDECLARE_EVENT(EVT_GLCANVAS_ARRANGE_PARTPLATE, SimpleEvent);
|
||||
wxDECLARE_EVENT(EVT_GLCANVAS_ARRANGE_OUTPLATE, SimpleEvent);
|
||||
wxDECLARE_EVENT(EVT_GLCANVAS_ORIENT, SimpleEvent);
|
||||
wxDECLARE_EVENT(EVT_GLCANVAS_ORIENT_PARTPLATE, SimpleEvent);
|
||||
wxDECLARE_EVENT(EVT_GLCANVAS_SELECT_CURR_PLATE_ALL, SimpleEvent);
|
||||
|
|
|
@ -30,9 +30,10 @@ public:
|
|||
: GLCanvas3D::WipeTowerInfo(std::move(wti))
|
||||
{}
|
||||
|
||||
void apply_arrange_result(const Vec2d& tr, double rotation, int item_id)
|
||||
void apply_arrange_result(const Vec2d& tr, double rotation, int item_id, int bed_id)
|
||||
{
|
||||
m_pos = unscaled(tr); m_rotation = rotation;
|
||||
m_plate_idx = bed_id;
|
||||
apply_wipe_tower();
|
||||
}
|
||||
|
||||
|
@ -71,7 +72,13 @@ arrangement::ArrangePolygon get_wipetower_arrange_poly(WipeTower* tower)
|
|||
{
|
||||
ArrangePolygon ap = tower->get_arrange_polygon();
|
||||
ap.bed_idx = 0;
|
||||
ap.setter = NULL; // do not move wipe tower
|
||||
//ap.setter = NULL; // do not move wipe tower
|
||||
ap.setter = [tower](const ArrangePolygon &p) {
|
||||
if (p.is_arranged()) {
|
||||
Vec2d t = p.translation.cast<double>();
|
||||
tower->apply_arrange_result(t, p.rotation, p.itemid, p.bed_idx);
|
||||
}
|
||||
};
|
||||
return ap;
|
||||
}
|
||||
|
||||
|
@ -301,7 +308,7 @@ arrangement::ArrangePolygon estimate_wipe_tower_info(int plate_index, std::set<i
|
|||
// 2)打开了支撑,且支撑体与接触面使用的是不同材料
|
||||
// 3)允许不同材料落在相同盘,且所有选定对象中使用了多种热床温度相同的材料
|
||||
// (所有对象都是单色的,但不同对象的材料不同,例如:对象A使用红色PLA,对象B使用白色PLA)
|
||||
void ArrangeJob::prepare_wipe_tower()
|
||||
void ArrangeJob::prepare_wipe_tower(bool select)
|
||||
{
|
||||
bool need_wipe_tower = false;
|
||||
|
||||
|
@ -368,6 +375,10 @@ void ArrangeJob::prepare_wipe_tower()
|
|||
// wipe tower is already there
|
||||
wipe_tower_ap = get_wipetower_arrange_poly(&wti);
|
||||
wipe_tower_ap.bed_idx = bedid_unlocked;
|
||||
wipe_tower_ap.name = "WipeTower" + std::to_string(bedid_unlocked);
|
||||
if (select)
|
||||
m_selected.emplace_back(wipe_tower_ap);
|
||||
else
|
||||
m_unselected.emplace_back(wipe_tower_ap);
|
||||
}
|
||||
else if (need_wipe_tower) {
|
||||
|
@ -433,7 +444,7 @@ void ArrangeJob::prepare_partplate() {
|
|||
//skip this object due to be not in current plate, treated as locked
|
||||
ap.itemid = m_locked.size();
|
||||
m_locked.emplace_back(std::move(ap));
|
||||
//BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(": skip locked instance, obj_id %1%, name %2%") % oidx % mo->name;
|
||||
//ARRANGE_LOG(debug) << __FUNCTION__ << boost::format(": skip locked instance, obj_id %1%, name %2%") % oidx % mo->name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -450,9 +461,9 @@ void ArrangeJob::prepare_partplate() {
|
|||
|
||||
void ArrangeJob::prepare_outside_plate() {
|
||||
clear_input();
|
||||
|
||||
std::set<std::pair<int, int>> all_inside_objects;
|
||||
std::set<std::pair<int, int>> all_outside_objects;
|
||||
typedef std::tuple<int, int, int> obj_inst_plate_t;
|
||||
std::map<std::pair<int,int>,int> all_inside_objects;
|
||||
std::map<std::pair<int, int>, int> all_outside_objects;
|
||||
|
||||
Model &model = m_plater->model();
|
||||
PartPlateList &plate_list = m_plater->get_partplate_list();
|
||||
|
@ -468,9 +479,8 @@ void ArrangeJob::prepare_outside_plate() {
|
|||
continue;
|
||||
}
|
||||
|
||||
all_inside_objects.insert(plate_objects.begin(), plate_objects.end());
|
||||
if (!plate_outside_objects.empty())
|
||||
all_outside_objects.insert(plate_outside_objects.begin(), plate_outside_objects.end());
|
||||
for (auto &obj_inst : plate_objects) { all_inside_objects[obj_inst] = plate_idx; }
|
||||
for (auto &obj_inst : plate_outside_objects) { all_outside_objects[obj_inst] = plate_idx; }
|
||||
|
||||
if (plate->is_locked()) {
|
||||
ARRANGE_LOG(info) << __FUNCTION__ << format(": skip locked plate %d!", plate_idx);
|
||||
|
@ -478,24 +488,22 @@ void ArrangeJob::prepare_outside_plate() {
|
|||
}
|
||||
|
||||
// if there are objects inside the plate, lock the plate and don't put new objects in it
|
||||
if (plate_objects.size() > plate_outside_objects.size()) {
|
||||
plate->lock(true);
|
||||
m_uncompatible_plates.push_back(plate_idx);
|
||||
ARRANGE_LOG(info) << __FUNCTION__ << format(": lock plate %d because there are objects inside!", plate_idx);
|
||||
}
|
||||
//if (plate_objects.size() > plate_outside_objects.size()) {
|
||||
// plate->lock(true);
|
||||
// m_uncompatible_plates.push_back(plate_idx);
|
||||
// ARRANGE_LOG(info) << __FUNCTION__ << format(": lock plate %d because there are objects inside!", plate_idx);
|
||||
//}
|
||||
}
|
||||
|
||||
for (int obj_idx = 0; obj_idx < model.objects.size(); obj_idx++) {
|
||||
ModelObject *object = model.objects[obj_idx];
|
||||
for (size_t inst_idx = 0; inst_idx < object->instances.size(); ++inst_idx) {
|
||||
ModelInstance * instance = object->instances[inst_idx];
|
||||
std::set<std::pair<int, int>>::iterator iter1, iter2;
|
||||
|
||||
iter1 = all_inside_objects.find(std::pair(obj_idx, inst_idx));
|
||||
iter2 = all_outside_objects.find(std::pair(obj_idx, inst_idx));
|
||||
auto iter1 = all_inside_objects.find(std::pair(obj_idx, inst_idx));
|
||||
auto iter2 = all_outside_objects.find(std::pair(obj_idx, inst_idx));
|
||||
bool outside_plate = false;
|
||||
if (iter1 == all_inside_objects.end()) {
|
||||
//skip
|
||||
continue;
|
||||
}
|
||||
if (iter2 != all_outside_objects.end()) {
|
||||
|
@ -505,13 +513,15 @@ void ArrangeJob::prepare_outside_plate() {
|
|||
ArrangePolygons &cont = instance->printable ? (outside_plate ? m_selected : m_locked) : m_unprintable;
|
||||
ap.itemid = cont.size();
|
||||
if (!outside_plate) {
|
||||
plate_list.preprocess_arrange_polygon(obj_idx, inst_idx, ap, true);
|
||||
plate_list.preprocess_arrange_polygon(obj_idx, inst_idx, ap, false);
|
||||
ap.bed_idx = iter1->second;
|
||||
ap.locked_plate = iter1->second;
|
||||
}
|
||||
cont.emplace_back(std::move(ap));
|
||||
}
|
||||
}
|
||||
|
||||
prepare_wipe_tower();
|
||||
prepare_wipe_tower(true);
|
||||
|
||||
// add the virtual object into unselect list if has
|
||||
plate_list.preprocess_exclude_areas(m_unselected, current_plate_index + 1);
|
||||
|
@ -544,6 +554,7 @@ void ArrangeJob::prepare()
|
|||
prepare_outside_plate();
|
||||
}
|
||||
|
||||
ARRANGE_LOG(info) << "prepare state: " << state << ", items selected : " << m_selected.size();
|
||||
|
||||
#if SAVE_ARRANGE_POLY
|
||||
if (1)
|
||||
|
@ -586,6 +597,12 @@ void ArrangeJob::prepare()
|
|||
#endif
|
||||
|
||||
check_unprintable();
|
||||
|
||||
if (!m_selected.empty()) {
|
||||
m_plater->get_notification_manager()->push_notification(NotificationType::ArrangeOngoing, NotificationManager::NotificationLevel::RegularNotificationLevel,
|
||||
_u8L("Arranging..."));
|
||||
m_plater->get_notification_manager()->bbl_close_plateinfo_notification();
|
||||
}
|
||||
}
|
||||
|
||||
void ArrangeJob::check_unprintable()
|
||||
|
@ -640,7 +657,7 @@ void ArrangeJob::process()
|
|||
|
||||
partplate_list.preprocess_exclude_areas(params.excluded_regions, 1, scale_(1));
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << "arrange bedpts:" << bedpts[0].transpose() << ", " << bedpts[1].transpose() << ", " << bedpts[2].transpose() << ", " << bedpts[3].transpose();
|
||||
ARRANGE_LOG(debug) << "bedpts:" << bedpts[0].transpose() << ", " << bedpts[1].transpose() << ", " << bedpts[2].transpose() << ", " << bedpts[3].transpose();
|
||||
|
||||
params.stopcondition = [this]() { return was_canceled(); };
|
||||
|
||||
|
@ -648,35 +665,36 @@ void ArrangeJob::process()
|
|||
update_status(num_finished, _L("Arranging") + " "+ wxString::FromUTF8(str));
|
||||
};
|
||||
|
||||
ArrangePolygons unselected_and_locked = m_unselected;
|
||||
append(unselected_and_locked, m_locked);
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(warning)<< "Arrange full params: "<< params.to_json();
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("arrange: items selected before arranging: %1%") % m_selected.size();
|
||||
ARRANGE_LOG(warning)<< "full params: "<< params.to_json();
|
||||
ARRANGE_LOG(info) << boost::format("items selected before arranging: %1%") % m_selected.size();
|
||||
for (auto selected : m_selected) {
|
||||
BOOST_LOG_TRIVIAL(debug) << selected.name << ", extruder: " << VectorFormatter(selected.extrude_ids)
|
||||
ARRANGE_LOG(debug) << selected.name << ", extruder: " << VectorFormatter(selected.extrude_ids)
|
||||
<< ", filament types: " << VectorFormatter(selected.filament_types) << ", bed: " << selected.bed_idx
|
||||
<< ", filemant_type:" << selected.filament_temp_type << ", trans: " << unscale<double>(selected.translation(X)) << ","
|
||||
<< unscale<double>(selected.translation(Y)) << ", rotation: " << selected.rotation;
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(debug) << "arrange: items unselected before arrange: " << m_unselected.size();
|
||||
for (auto item : m_unselected)
|
||||
BOOST_LOG_TRIVIAL(debug) << item.name << ", bed: " << item.bed_idx << ", trans: " << item.translation.transpose()
|
||||
<<", bbox:"<<get_extents(item.poly).min.transpose()<<","<<get_extents(item.poly).max.transpose();
|
||||
ARRANGE_LOG(debug) << "items unselected before arrange: " << unselected_and_locked.size();
|
||||
for (auto item : unselected_and_locked)
|
||||
ARRANGE_LOG(debug) << item.name << ", bed: " << item.bed_idx << ", trans: " << unscale<double>(item.translation(X)) << "," << unscale<double>(item.translation(Y));
|
||||
}
|
||||
|
||||
arrangement::arrange(m_selected, m_unselected, bedpts, params);
|
||||
arrangement::arrange(m_selected, unselected_and_locked, bedpts, params);
|
||||
|
||||
// sort by item id
|
||||
std::sort(m_selected.begin(), m_selected.end(), [](auto a, auto b) {return a.itemid < b.itemid; });
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("arrange: items selected after arranging: %1%") % m_selected.size();
|
||||
ARRANGE_LOG(info) << boost::format("items selected after arranging: %1%") % m_selected.size();
|
||||
for (auto selected : m_selected)
|
||||
BOOST_LOG_TRIVIAL(debug) << selected.name << ", extruder: " << VectorFormatter(selected.extrude_ids) << ", bed: " << selected.bed_idx
|
||||
ARRANGE_LOG(debug) << selected.name << ", extruder: " << VectorFormatter(selected.extrude_ids) << ", bed: " << selected.bed_idx
|
||||
<< ", bed_temp: " << selected.first_bed_temp << ", print_temp: " << selected.print_temp
|
||||
<< ", trans: " << unscale<double>(selected.translation(X)) << "," << unscale<double>(selected.translation(Y))
|
||||
<< ", rotation: " << selected.rotation;
|
||||
BOOST_LOG_TRIVIAL(debug) << "arrange: items unselected after arrange: "<< m_unselected.size();
|
||||
for (auto item : m_unselected)
|
||||
BOOST_LOG_TRIVIAL(debug) << item.name << ", bed: " << item.bed_idx << ", trans: " << item.translation.transpose() << ", rotation: " << item.rotation;
|
||||
ARRANGE_LOG(debug) << "items unselected after arrange: " << unselected_and_locked.size();
|
||||
for (auto item : unselected_and_locked)
|
||||
ARRANGE_LOG(debug) << item.name << ", bed: " << item.bed_idx << ", trans: " << unscale<double>(item.translation(X)) << "," << unscale<double>(item.translation(Y));
|
||||
}
|
||||
|
||||
// put unpackable items to m_unprintable so they goes outside
|
||||
|
@ -732,7 +750,7 @@ void ArrangeJob::finalize()
|
|||
|
||||
beds = std::max(ap.bed_idx, beds);
|
||||
|
||||
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;
|
||||
ARRANGE_LOG(debug) << __FUNCTION__ << boost::format(": selected %4%: bed_id %1%, trans {%2%,%3%}") % ap.bed_idx % unscale<double>(ap.translation(X)) % unscale<double>(ap.translation(Y)) % ap.name;
|
||||
}
|
||||
|
||||
//BBS: adjust the bed_index, create new plates, get the max bed_index
|
||||
|
@ -745,7 +763,7 @@ void ArrangeJob::finalize()
|
|||
plate_list.postprocess_bed_index_for_unselected(ap);
|
||||
|
||||
beds = std::max(ap.bed_idx, beds);
|
||||
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;
|
||||
ARRANGE_LOG(debug) << __FUNCTION__ << boost::format(": unselected %4%: bed_id %1%, trans {%2%,%3%}") % ap.bed_idx % unscale<double>(ap.translation(X)) % unscale<double>(ap.translation(Y)) % ap.name;
|
||||
}
|
||||
|
||||
for (ArrangePolygon& ap : m_locked) {
|
||||
|
@ -782,7 +800,7 @@ void ArrangeJob::finalize()
|
|||
plate_list.postprocess_arrange_polygon(ap, true);
|
||||
|
||||
ap.apply();
|
||||
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;
|
||||
ARRANGE_LOG(debug) << __FUNCTION__ << boost::format(": 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;
|
||||
}
|
||||
|
||||
m_plater->update();
|
||||
|
|
|
@ -42,9 +42,7 @@ class ArrangeJob : public PlaterJob
|
|||
// prepare the items which are selected and not on the current partplate
|
||||
void prepare_outside_plate();
|
||||
|
||||
void prepare_wipe_tower();
|
||||
|
||||
ArrangePolygon prepare_arrange_polygon(void* instance);
|
||||
void prepare_wipe_tower(bool select = false);
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -68,6 +66,8 @@ public:
|
|||
}
|
||||
|
||||
void finalize() override;
|
||||
|
||||
static ArrangePolygon prepare_arrange_polygon(void *instance);
|
||||
};
|
||||
|
||||
std::optional<arrangement::ArrangePolygon> get_wipe_tower_arrangepoly(const Plater &);
|
||||
|
|
|
@ -4375,7 +4375,14 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
|
|||
view3D_canvas->Bind(EVT_GLCANVAS_ARRANGE_PARTPLATE, [this](SimpleEvent& evt) {
|
||||
//BBS arrage from EVT set default state.
|
||||
this->q->set_prepare_state(Job::PREPARE_STATE_MENU);
|
||||
this->q->arrange(); });
|
||||
this->q->arrange();
|
||||
});
|
||||
view3D_canvas->Bind(EVT_GLCANVAS_ARRANGE_OUTPLATE, [this](SimpleEvent &evt) {
|
||||
if (this->q->last_arrange_job_is_finished()) {
|
||||
this->q->set_prepare_state(Job::PREPARE_STATE_OUTSIDE_BED);
|
||||
this->q->arrange();
|
||||
}
|
||||
});
|
||||
view3D_canvas->Bind(EVT_GLCANVAS_ORIENT, [this](SimpleEvent& evt) {
|
||||
//BBS oriant from EVT set default state.
|
||||
this->q->set_prepare_state(Job::PREPARE_STATE_DEFAULT);
|
||||
|
@ -9437,6 +9444,7 @@ void Plater::priv::update_objects_position_when_select_preset(const std::functio
|
|||
bool cur_plate_is_smaller = cur_plate_size.x() + 1.0 < old_plate_size.x() || cur_plate_size.y() + 1.0 < old_plate_size.y();
|
||||
BOOST_LOG_TRIVIAL(info) << format("change bed pos from (%.0f,%.0f) to (%.0f,%.0f)", old_plate_pos.x(), old_plate_pos.y(), cur_plate_pos.x(), cur_plate_pos.y());
|
||||
|
||||
bool plate_not_empty = std::any_of(plate_object.begin(), plate_object.end(), [](const std::vector<int> &obj_idxs) { return !obj_idxs.empty(); });
|
||||
if (old_plate_pos.x() != cur_plate_pos.x() || old_plate_pos.y() != cur_plate_pos.y() || cur_plate_is_smaller) {
|
||||
for (int i = 0; i < plate_object.size(); ++i) {
|
||||
view3D->select_object_from_idx(plate_object[i]);
|
||||
|
@ -9445,7 +9453,7 @@ void Plater::priv::update_objects_position_when_select_preset(const std::functio
|
|||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << format("change bed size from (%.0f,%.0f) to (%.0f,%.0f)", old_plate_size.x(), old_plate_size.y(), cur_plate_size.x(), cur_plate_size.y());
|
||||
if (cur_plate_is_smaller && std::any_of(plate_object.begin(), plate_object.end(), [](const std::vector<int>& obj_idxs) { return !obj_idxs.empty(); })) {
|
||||
if (cur_plate_is_smaller && plate_not_empty) {
|
||||
take_snapshot("Arrange after bed size changes");
|
||||
//collect all the objects on the current plates
|
||||
std::set<ModelObject*> new_all_plate_object;
|
||||
|
@ -9465,8 +9473,6 @@ void Plater::priv::update_objects_position_when_select_preset(const std::functio
|
|||
obj_out_set.emplace(std::pair<int, int>{i, 0});
|
||||
}
|
||||
}
|
||||
q->set_prepare_state(Job::PREPARE_STATE_OUTSIDE_BED);
|
||||
q->arrange();
|
||||
}
|
||||
#if 0
|
||||
const BoundingBoxf3 &cur_platelist_bbox = cur_plate_list.get_bounding_box();
|
||||
|
@ -9504,6 +9510,8 @@ void Plater::priv::update_objects_position_when_select_preset(const std::functio
|
|||
#endif
|
||||
view3D->deselect_all();
|
||||
}
|
||||
|
||||
wxQueueEvent(view3D->get_wxglcanvas(), new SimpleEvent(EVT_GLCANVAS_ARRANGE_OUTPLATE));
|
||||
}
|
||||
|
||||
void Plater::orient()
|
||||
|
|
Loading…
Reference in New Issue