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_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)
{
return double(val) / m_norm;
@ -318,6 +321,7 @@ public:
m_pilebb = sl::boundingBox(merged_pile);
m_rtree.clear();
// m_preload_idx.clear();
m_smallsrtree.clear();
// We will treat big items (compared to the print bed) differently
@ -341,7 +345,7 @@ public:
}
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)...);
}
@ -358,19 +362,25 @@ public:
for(unsigned idx = 0; idx < fixeditems.size(); ++idx) {
Item& itm = fixeditems[idx];
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);
}
bool is_colliding(const Item& item) {
if(m_rtree.empty()) return false;
std::vector<SpatElement> result;
m_rtree.query(bgi::intersects(item.boundingBox()),
std::back_inserter(result));
return !result.empty();
}
// int is_colliding(const Item& item) {
// size_t bedidx = item.binId() < 0 ? 0u : size_t(item.binId());
// if (m_preload_idx.size() <= bedidx || m_preload_idx[bedidx].empty())
// return false;
// 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()
@ -534,24 +544,21 @@ void _arrange(
++it : it = excludes.erase(it);
// If there is something on the plate
if(!excludes.empty())
{
arranger.preload(excludes);
auto binbb = sl::boundingBox(corrected_bin);
if (!excludes.empty()) {
arranger.preload(excludes);
// auto binbb = sl::boundingBox(corrected_bin);
// Try to put the first item to the center, as the arranger
// will not do this for us.
for (Item &itm : shapes) {
auto ibb = itm.boundingBox();
auto d = binbb.center() - ibb.center();
itm.translate(d);
// // Try to put the first item to the center, as the arranger
// // will not do this for us.
// for (Item &itm : shapes) {
// auto ibb = itm.boundingBox();
// auto d = binbb.center() - ibb.center();
// itm.translate(d);
// itm.binId(UNARRANGED);
if (!arranger.is_colliding(itm)) {
itm.markAsFixed();
break;
}
}
}
// if (!arranger.is_colliding(itm)) { itm.markAsFixed(); break; }
// }
}
std::vector<std::reference_wrapper<Item>> inp;
inp.reserve(shapes.size() + excludes.size());

View file

@ -1421,8 +1421,9 @@ struct Plater::priv
wxQueueEvent(this, evt);
}
priv &plater() { return *m_plater; }
bool was_canceled() const { return m_canceled.load(); }
priv & plater() { return *m_plater; }
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
virtual void prepare() {}
@ -1537,51 +1538,76 @@ struct Plater::priv
ArrangePolygons m_selected, m_unselected;
protected:
void prepare() override
{
// Get the selection map
Selection& sel = plater().get_selection();
const Selection::ObjectIdxsToInstanceIdxsMap &selmap =
sel.get_content();
Model &model = plater().model;
// clear m_selected and m_unselected, reserve space for next usage
void clear_input() {
const Model &model = plater().model;
size_t count = 0; // To know how much space to reserve
for (auto obj : model.objects) count += obj->instances.size();
m_selected.clear(), m_unselected.clear();
m_selected.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();
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
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];
std::vector<bool> inst_sel(mo->instances.size(), false);
if (oit != selmap.end())
for (auto inst_id : oit->second) inst_sel[inst_id] = true;
if (instlist)
for (auto inst_id : *instlist) inst_sel[inst_id] = true;
for (size_t i = 0; i < inst_sel.size(); ++i) {
ModelInstance *mi = mo->instances[i];
ArrangePolygon ap = mi->get_arrange_polygon();
ap.priority = 0;
ap.bed_idx = ap.translation.x() / stride;
ArrangePolygon &&ap = get_arrange_poly(mo->instances[i]);
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] ?
m_selected.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();
if (wti) {
ArrangePolygon ap = wti.get_arrange_polygon();
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);
}
};
ArrangePolygon &&ap = get_arrange_poly(&wti);
sel.is_wipe_tower() ?
plater().get_selection().is_wipe_tower() ?
m_selected.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;
}
protected:
void prepare() override
{
wxGetKeyState(WXK_SHIFT) ? prepare_selected() : prepare_all();
}
public:
using Job::Job;