Arrange selection if shift is pressed. Remove first item centering

This commit is contained in:
tamasmeszaros 2019-07-19 18:10:10 +02:00
parent 72ed8c034e
commit 63fada9469
2 changed files with 97 additions and 65 deletions

View file

@ -136,6 +136,9 @@ protected:
ItemGroup m_remaining; // Remaining items (m_items at the beginning) ItemGroup m_remaining; // Remaining items (m_items at the beginning)
ItemGroup m_items; // The items to be packed ItemGroup m_items; // The items to be packed
// Used only for preloading objects before arrange
// std::vector<SpatIndex> m_preload_idx; // spatial index for preloaded beds
template<class T> ArithmeticOnly<T, double> norm(T val) template<class T> ArithmeticOnly<T, double> norm(T val)
{ {
return double(val) / m_norm; return double(val) / m_norm;
@ -318,6 +321,7 @@ public:
m_pilebb = sl::boundingBox(merged_pile); m_pilebb = sl::boundingBox(merged_pile);
m_rtree.clear(); m_rtree.clear();
// m_preload_idx.clear();
m_smallsrtree.clear(); m_smallsrtree.clear();
// We will treat big items (compared to the print bed) differently // We will treat big items (compared to the print bed) differently
@ -341,7 +345,7 @@ public:
} }
template<class...Args> inline void operator()(Args&&...args) { template<class...Args> inline void operator()(Args&&...args) {
m_rtree.clear(); m_rtree.clear(); /*m_preload_idx.clear();*/
m_pck.execute(std::forward<Args>(args)...); m_pck.execute(std::forward<Args>(args)...);
} }
@ -358,19 +362,25 @@ public:
for(unsigned idx = 0; idx < fixeditems.size(); ++idx) { for(unsigned idx = 0; idx < fixeditems.size(); ++idx) {
Item& itm = fixeditems[idx]; Item& itm = fixeditems[idx];
itm.markAsFixed(); itm.markAsFixed();
m_rtree.insert({itm.boundingBox(), idx}); // size_t bedidx = itm.binId() < 0 ? 0u : size_t(itm.binId());
// while (m_preload_idx.size() <= bedidx) m_preload_idx.emplace_back();
// m_preload_idx[bedidx].insert({itm.boundingBox(), idx});
} }
m_pck.configure(m_pconf); m_pck.configure(m_pconf);
} }
bool is_colliding(const Item& item) { // int is_colliding(const Item& item) {
if(m_rtree.empty()) return false; // size_t bedidx = item.binId() < 0 ? 0u : size_t(item.binId());
std::vector<SpatElement> result; // if (m_preload_idx.size() <= bedidx || m_preload_idx[bedidx].empty())
m_rtree.query(bgi::intersects(item.boundingBox()), // return false;
std::back_inserter(result));
return !result.empty(); // std::vector<SpatElement> result;
} // m_preload_idx[bedidx].query(bgi::intersects(item.boundingBox()),
// std::back_inserter(result));
// return !result.empty();
// }
}; };
template<> std::function<double(const Item&)> AutoArranger<Box>::get_objfn() template<> std::function<double(const Item&)> AutoArranger<Box>::get_objfn()
@ -534,24 +544,21 @@ void _arrange(
++it : it = excludes.erase(it); ++it : it = excludes.erase(it);
// If there is something on the plate // If there is something on the plate
if(!excludes.empty()) if (!excludes.empty()) {
{ arranger.preload(excludes);
arranger.preload(excludes); // auto binbb = sl::boundingBox(corrected_bin);
auto binbb = sl::boundingBox(corrected_bin);
// Try to put the first item to the center, as the arranger // // Try to put the first item to the center, as the arranger
// will not do this for us. // // will not do this for us.
for (Item &itm : shapes) { // for (Item &itm : shapes) {
auto ibb = itm.boundingBox(); // auto ibb = itm.boundingBox();
auto d = binbb.center() - ibb.center(); // auto d = binbb.center() - ibb.center();
itm.translate(d); // itm.translate(d);
// itm.binId(UNARRANGED);
if (!arranger.is_colliding(itm)) { // if (!arranger.is_colliding(itm)) { itm.markAsFixed(); break; }
itm.markAsFixed(); // }
break; }
}
}
}
std::vector<std::reference_wrapper<Item>> inp; std::vector<std::reference_wrapper<Item>> inp;
inp.reserve(shapes.size() + excludes.size()); inp.reserve(shapes.size() + excludes.size());

View file

@ -1421,8 +1421,9 @@ struct Plater::priv
wxQueueEvent(this, evt); wxQueueEvent(this, evt);
} }
priv &plater() { return *m_plater; } priv & plater() { return *m_plater; }
bool was_canceled() const { return m_canceled.load(); } const priv &plater() const { return *m_plater; }
bool was_canceled() const { return m_canceled.load(); }
// Launched just before start(), a job can use it to prepare internals // Launched just before start(), a job can use it to prepare internals
virtual void prepare() {} virtual void prepare() {}
@ -1537,51 +1538,76 @@ struct Plater::priv
ArrangePolygons m_selected, m_unselected; ArrangePolygons m_selected, m_unselected;
protected: // clear m_selected and m_unselected, reserve space for next usage
void clear_input() {
void prepare() override const Model &model = plater().model;
{
// Get the selection map
Selection& sel = plater().get_selection();
const Selection::ObjectIdxsToInstanceIdxsMap &selmap =
sel.get_content();
Model &model = plater().model;
size_t count = 0; // To know how much space to reserve size_t count = 0; // To know how much space to reserve
for (auto obj : model.objects) count += obj->instances.size(); for (auto obj : model.objects) count += obj->instances.size();
m_selected.clear(), m_unselected.clear(); m_selected.clear(), m_unselected.clear();
m_selected.reserve(count + 1 /* for optional wti */); m_selected.reserve(count + 1 /* for optional wti */);
m_unselected.reserve(count + 1 /* for optional wti */); m_unselected.reserve(count + 1 /* for optional wti */);
}
// Stride between logical beds
// Stride between logical beds
coord_t bed_stride() const {
double bedwidth = plater().bed_shape_bb().size().x(); double bedwidth = plater().bed_shape_bb().size().x();
coord_t stride = scaled((1. + LOGICAL_BED_GAP) * bedwidth); return scaled((1. + LOGICAL_BED_GAP) * bedwidth);
}
// Set up arrange polygon for a ModelInstance and Wipe tower
template<class T> ArrangePolygon get_arrange_poly(T *obj) const {
ArrangePolygon ap = obj->get_arrange_polygon();
ap.priority = 0;
ap.bed_idx = ap.translation.x() / bed_stride();
ap.setter = [obj, this](const ArrangePolygon &p) {
if (p.is_arranged()) {
auto t = p.translation; t.x() += p.bed_idx * bed_stride();
obj->apply_arrange_result(t, p.rotation);
}
};
return ap;
}
// Prepare all objects on the bed regardless of the selection
void prepare_all() {
clear_input();
for (ModelObject *obj: plater().model.objects)
for (ModelInstance *mi : obj->instances)
m_selected.emplace_back(get_arrange_poly(mi));
auto& wti = plater().updated_wipe_tower();
if (wti) m_selected.emplace_back(get_arrange_poly(&wti));
}
// Prepare the selected and unselected items separately. If nothing is
// selected, behaves as if everything would be selected.
void prepare_selected() {
clear_input();
Model &model = plater().model;
coord_t stride = bed_stride();
std::vector<const Selection::InstanceIdxsList *>
obj_sel(model.objects.size(), nullptr);
for (auto &s : plater().get_selection().get_content())
if (s.first < int(obj_sel.size())) obj_sel[s.first] = &s.second;
// Go through the objects and check if inside the selection // Go through the objects and check if inside the selection
for (size_t oidx = 0; oidx < model.objects.size(); ++oidx) { for (size_t oidx = 0; oidx < model.objects.size(); ++oidx) {
auto oit = selmap.find(int(oidx)); const Selection::InstanceIdxsList * instlist = obj_sel[oidx];
ModelObject *mo = model.objects[oidx]; ModelObject *mo = model.objects[oidx];
std::vector<bool> inst_sel(mo->instances.size(), false); std::vector<bool> inst_sel(mo->instances.size(), false);
if (oit != selmap.end()) if (instlist)
for (auto inst_id : oit->second) inst_sel[inst_id] = true; for (auto inst_id : *instlist) inst_sel[inst_id] = true;
for (size_t i = 0; i < inst_sel.size(); ++i) { for (size_t i = 0; i < inst_sel.size(); ++i) {
ModelInstance *mi = mo->instances[i]; ArrangePolygon &&ap = get_arrange_poly(mo->instances[i]);
ArrangePolygon ap = mi->get_arrange_polygon();
ap.priority = 0;
ap.bed_idx = ap.translation.x() / stride;
ap.setter = [mi, stride](const ArrangePolygon &p) {
if (p.is_arranged()) {
auto t = p.translation; t.x() += p.bed_idx * stride;
mi->apply_arrange_result(t, p.rotation);
}
};
inst_sel[i] ? inst_sel[i] ?
m_selected.emplace_back(std::move(ap)) : m_selected.emplace_back(std::move(ap)) :
m_unselected.emplace_back(std::move(ap)); m_unselected.emplace_back(std::move(ap));
@ -1590,17 +1616,9 @@ struct Plater::priv
auto& wti = plater().updated_wipe_tower(); auto& wti = plater().updated_wipe_tower();
if (wti) { if (wti) {
ArrangePolygon ap = wti.get_arrange_polygon(); ArrangePolygon &&ap = get_arrange_poly(&wti);
ap.bed_idx = ap.translation.x() / stride;
ap.priority = 1; // Wipe tower should be on physical bed
ap.setter = [&wti, stride](const ArrangePolygon &p) {
if (p.is_arranged()) {
auto t = p.translation; t.x() += p.bed_idx * stride;
wti.apply_arrange_result(t, p.rotation);
}
};
sel.is_wipe_tower() ? plater().get_selection().is_wipe_tower() ?
m_selected.emplace_back(std::move(ap)) : m_selected.emplace_back(std::move(ap)) :
m_unselected.emplace_back(std::move(ap)); m_unselected.emplace_back(std::move(ap));
} }
@ -1614,6 +1632,13 @@ struct Plater::priv
for (auto &p : m_unselected) p.translation(X) -= p.bed_idx * stride; for (auto &p : m_unselected) p.translation(X) -= p.bed_idx * stride;
} }
protected:
void prepare() override
{
wxGetKeyState(WXK_SHIFT) ? prepare_selected() : prepare_all();
}
public: public:
using Job::Job; using Job::Job;