Merge remote-tracking branch 'origin/dev' into new_main_page_ui

This commit is contained in:
YuSanka 2018-09-13 16:12:07 +02:00
commit a31ac857ef
16 changed files with 102 additions and 37 deletions

View File

@ -640,6 +640,7 @@ public:
// The progress function will be called with the number of placed items
using ProgressFunction = std::function<void(unsigned)>;
using StopCondition = std::function<bool(void)>;
/**
* A wrapper interface (trait) class for any selections strategy provider.
@ -674,6 +675,8 @@ public:
*/
void progressIndicator(ProgressFunction fn) { impl_.progressIndicator(fn); }
void stopCondition(StopCondition cond) { impl_.stopCondition(cond); }
/**
* \brief A method to start the calculation on the input sequence.
*
@ -864,6 +867,11 @@ public:
selector_.progressIndicator(func); return *this;
}
/// Set a predicate to tell when to abort nesting.
inline Nester& stopCondition(StopCondition fn) {
selector_.stopCondition(fn); return *this;
}
inline PackGroup lastResult() {
PackGroup ret;
for(size_t i = 0; i < selector_.binCount(); i++) {

View File

@ -551,7 +551,7 @@ public:
// Safety test: try to pack each item into an empty bin. If it fails
// then it should be removed from the not_packed list
{ auto it = store_.begin();
while (it != store_.end()) {
while (it != store_.end() && !this->stopcond_()) {
Placer p(bin); p.configure(pconfig);
if(!p.pack(*it, rem(it, store_))) {
it = store_.erase(it);
@ -592,9 +592,11 @@ public:
bool do_pairs = config_.try_pairs;
bool do_triplets = config_.try_triplets;
StopCondition stopcond = this->stopcond_;
// The DJD heuristic algorithm itself:
auto packjob = [INITIAL_FILL_AREA, bin_area, w, do_triplets, do_pairs,
stopcond,
&tryOneByOne,
&tryGroupsOfTwo,
&tryGroupsOfThree,
@ -606,12 +608,12 @@ public:
double waste = .0;
bool lasttry = false;
while(!not_packed.empty()) {
while(!not_packed.empty() && !stopcond()) {
{// Fill the bin up to INITIAL_FILL_PROPORTION of its capacity
auto it = not_packed.begin();
while(it != not_packed.end() &&
while(it != not_packed.end() && !stopcond() &&
filled_area < INITIAL_FILL_AREA)
{
if(placer.pack(*it, rem(it, not_packed))) {
@ -623,14 +625,14 @@ public:
}
}
// try pieses one by one
// try pieces one by one
while(tryOneByOne(placer, not_packed, waste, free_area,
filled_area)) {
waste = 0; lasttry = false;
makeProgress(placer, idx, 1);
}
// try groups of 2 pieses
// try groups of 2 pieces
while(do_pairs &&
tryGroupsOfTwo(placer, not_packed, waste, free_area,
filled_area)) {
@ -638,7 +640,7 @@ public:
makeProgress(placer, idx, 2);
}
// try groups of 3 pieses
// try groups of 3 pieces
while(do_triplets &&
tryGroupsOfThree(placer, not_packed, waste, free_area,
filled_area)) {

View File

@ -60,7 +60,7 @@ public:
placer.configure(pconfig);
auto it = store_.begin();
while(it != store_.end()) {
while(it != store_.end() && !this->stopcond_()) {
if(!placer.pack(*it, {std::next(it), store_.end()})) {
if(packed_bins_.back().empty()) ++it;
placer.clearItems();

View File

@ -56,10 +56,12 @@ public:
this->progress_(static_cast<unsigned>(--total));
};
auto& cancelled = this->stopcond_;
// Safety test: try to pack each item into an empty bin. If it fails
// then it should be removed from the list
{ auto it = store_.begin();
while (it != store_.end()) {
while (it != store_.end() && !cancelled()) {
Placer p(bin); p.configure(pconfig);
if(!p.pack(*it)) {
it = store_.erase(it);
@ -67,13 +69,14 @@ public:
}
}
auto it = store_.begin();
while(it != store_.end()) {
while(it != store_.end() && !cancelled()) {
bool was_packed = false;
size_t j = 0;
while(!was_packed) {
for(; j < placers.size() && !was_packed; j++) {
while(!was_packed && !cancelled()) {
for(; j < placers.size() && !was_packed && !cancelled(); j++) {
if((was_packed = placers[j].pack(*it, rem(it, store_) )))
makeProgress(placers[j], j);
}

View File

@ -2,6 +2,7 @@
#define SELECTION_BOILERPLATE_HPP
#include "../libnest2d.hpp"
#include <atomic>
namespace libnest2d { namespace selections {
@ -25,14 +26,15 @@ public:
return packed_bins_[binIndex];
}
inline void progressIndicator(ProgressFunction fn) {
progress_ = fn;
}
inline void progressIndicator(ProgressFunction fn) { progress_ = fn; }
inline void stopCondition(StopCondition cond) { stopcond_ = cond; }
protected:
PackGroup packed_bins_;
ProgressFunction progress_ = [](unsigned){};
StopCondition stopcond_ = [](){ return false; };
};
}

View File

@ -299,7 +299,8 @@ protected:
public:
_ArrBase(const TBin& bin, Distance dist,
std::function<void(unsigned)> progressind):
std::function<void(unsigned)> progressind,
std::function<bool(void)> stopcond):
pck_(bin, dist), bin_area_(sl::area(bin)),
norm_(std::sqrt(sl::area(bin)))
{
@ -330,6 +331,7 @@ public:
};
pck_.progressIndicator(progressind);
pck_.stopCondition(stopcond);
}
template<class...Args> inline IndexedPackGroup operator()(Args&&...args) {
@ -343,8 +345,9 @@ class AutoArranger<Box>: public _ArrBase<Box> {
public:
AutoArranger(const Box& bin, Distance dist,
std::function<void(unsigned)> progressind):
_ArrBase<Box>(bin, dist, progressind)
std::function<void(unsigned)> progressind,
std::function<bool(void)> stopcond):
_ArrBase<Box>(bin, dist, progressind, stopcond)
{
pconf_.object_function = [this, bin] (const Item &item) {
@ -380,8 +383,9 @@ class AutoArranger<lnCircle>: public _ArrBase<lnCircle> {
public:
AutoArranger(const lnCircle& bin, Distance dist,
std::function<void(unsigned)> progressind):
_ArrBase<lnCircle>(bin, dist, progressind) {
std::function<void(unsigned)> progressind,
std::function<bool(void)> stopcond):
_ArrBase<lnCircle>(bin, dist, progressind, stopcond) {
pconf_.object_function = [this, &bin] (const Item &item) {
@ -421,8 +425,9 @@ template<>
class AutoArranger<PolygonImpl>: public _ArrBase<PolygonImpl> {
public:
AutoArranger(const PolygonImpl& bin, Distance dist,
std::function<void(unsigned)> progressind):
_ArrBase<PolygonImpl>(bin, dist, progressind)
std::function<void(unsigned)> progressind,
std::function<bool(void)> stopcond):
_ArrBase<PolygonImpl>(bin, dist, progressind, stopcond)
{
pconf_.object_function = [this, &bin] (const Item &item) {
@ -449,8 +454,9 @@ template<> // Specialization with no bin
class AutoArranger<bool>: public _ArrBase<Box> {
public:
AutoArranger(Distance dist, std::function<void(unsigned)> progressind):
_ArrBase<Box>(Box(0, 0), dist, progressind)
AutoArranger(Distance dist, std::function<void(unsigned)> progressind,
std::function<bool(void)> stopcond):
_ArrBase<Box>(Box(0, 0), dist, progressind, stopcond)
{
this->pconf_.object_function = [this] (const Item &item) {
@ -680,12 +686,16 @@ void applyResult(
* remaining items which do not fit onto the print area next to the print
* bed or leave them untouched (let the user arrange them by hand or remove
* them).
* \param progressind Progress indicator callback called when an object gets
* packed. The unsigned argument is the number of items remaining to pack.
* \param stopcondition A predicate returning true if abort is needed.
*/
bool arrange(Model &model, coordf_t min_obj_distance,
const Slic3r::Polyline& bed,
BedShapeHint bedhint,
bool first_bin_only,
std::function<void(unsigned)> progressind)
std::function<void(unsigned)> progressind,
std::function<bool(void)> stopcondition)
{
using ArrangeResult = _IndexedPackGroup<PolygonImpl>;
@ -710,6 +720,8 @@ bool arrange(Model &model, coordf_t min_obj_distance,
BoundingBox bbb(bed);
auto& cfn = stopcondition;
auto binbb = Box({
static_cast<libnest2d::Coord>(bbb.min(0)),
static_cast<libnest2d::Coord>(bbb.min(1))
@ -723,7 +735,7 @@ bool arrange(Model &model, coordf_t min_obj_distance,
case BedShapeType::BOX: {
// Create the arranger for the box shaped bed
AutoArranger<Box> arrange(binbb, min_obj_distance, progressind);
AutoArranger<Box> arrange(binbb, min_obj_distance, progressind, cfn);
// Arrange and return the items with their respective indices within the
// input sequence.
@ -735,7 +747,7 @@ bool arrange(Model &model, coordf_t min_obj_distance,
auto c = bedhint.shape.circ;
auto cc = lnCircle(c);
AutoArranger<lnCircle> arrange(cc, min_obj_distance, progressind);
AutoArranger<lnCircle> arrange(cc, min_obj_distance, progressind, cfn);
result = arrange(shapes.begin(), shapes.end());
break;
}
@ -747,7 +759,7 @@ bool arrange(Model &model, coordf_t min_obj_distance,
auto ctour = Slic3rMultiPoint_to_ClipperPath(bed);
P irrbed = sl::create<PolygonImpl>(std::move(ctour));
AutoArranger<P> arrange(irrbed, min_obj_distance, progressind);
AutoArranger<P> arrange(irrbed, min_obj_distance, progressind, cfn);
// Arrange and return the items with their respective indices within the
// input sequence.
@ -756,7 +768,7 @@ bool arrange(Model &model, coordf_t min_obj_distance,
}
};
if(result.empty()) return false;
if(result.empty() || stopcondition()) return false;
if(first_bin_only) {
applyResult(result.front(), 0, shapemap);

View File

@ -438,6 +438,11 @@ void AppController::arrange_model()
{
using Coord = libnest2d::TCoord<libnest2d::PointImpl>;
if(arranging_.load()) return;
// to prevent UI reentrancies
arranging_.store(true);
unsigned count = 0;
for(auto obj : model_->objects) count += obj->instances.size();
@ -451,8 +456,8 @@ void AppController::arrange_model()
// Set the range of the progress to the object count
pind->max(count);
pind->on_cancel([](){
std::cout << "Cannot be cancelled!" << std::endl;
pind->on_cancel([this](){
arranging_.store(false);
});
}
@ -478,10 +483,12 @@ void AppController::arrange_model()
bed,
hint,
false, // create many piles not just one pile
[pind, count](unsigned rem) {
[this, pind, count](unsigned rem) {
if(pind)
pind->update(count - rem, _(L("Arranging objects...")));
});
pind->update(count - rem, L("Arranging objects..."));
process_events();
}, [this] () { return !arranging_.load(); });
} catch(std::exception& e) {
std::cerr << e.what() << std::endl;
report_issue(IssueType::ERR,
@ -493,9 +500,13 @@ void AppController::arrange_model()
// Restore previous max value
if(pind) {
pind->max(pmax);
pind->update(0, _(L("Arranging done.")));
pind->update(0, arranging_.load() ? L("Arranging done.") :
L("Arranging canceled."));
pind->on_cancel(/*remove cancel function*/);
}
arranging_.store(false);
}
}

View File

@ -237,6 +237,7 @@ public:
class AppController: public AppControllerBoilerplate {
Model *model_ = nullptr;
PrintController::Ptr printctl;
std::atomic<bool> arranging_;
public:
/**

View File

@ -28,7 +28,7 @@ bool AppControllerBoilerplate::supports_asynch() const
void AppControllerBoilerplate::process_events()
{
wxSafeYield();
wxYieldIfNeeded();
}
AppControllerBoilerplate::PathList

View File

@ -2164,6 +2164,11 @@ int _3DScene::get_first_volume_id(wxGLCanvas* canvas, int obj_idx)
return s_canvas_mgr.get_first_volume_id(canvas, obj_idx);
}
int _3DScene::get_in_object_volume_id(wxGLCanvas* canvas, int scene_vol_idx)
{
return s_canvas_mgr.get_in_object_volume_id(canvas, scene_vol_idx);
}
void _3DScene::reload_scene(wxGLCanvas* canvas, bool force)
{
s_canvas_mgr.reload_scene(canvas, force);

View File

@ -577,6 +577,7 @@ public:
static std::vector<int> load_object(wxGLCanvas* canvas, const Model* model, int obj_idx);
static int get_first_volume_id(wxGLCanvas* canvas, int obj_idx);
static int get_in_object_volume_id(wxGLCanvas* canvas, int scene_vol_idx);
static void reload_scene(wxGLCanvas* canvas, bool force);

View File

@ -2493,6 +2493,11 @@ int GLCanvas3D::get_first_volume_id(int obj_idx) const
return -1;
}
int GLCanvas3D::get_in_object_volume_id(int scene_vol_idx) const
{
return ((0 <= scene_vol_idx) && (scene_vol_idx < (int)m_volumes.volumes.size())) ? m_volumes.volumes[scene_vol_idx]->volume_idx() : -1;
}
void GLCanvas3D::reload_scene(bool force)
{
if ((m_canvas == nullptr) || (m_config == nullptr) || (m_model == nullptr))

View File

@ -105,7 +105,6 @@ class GLCanvas3D
void reset() { first_volumes.clear(); }
};
public:
struct Camera
{
enum EType : unsigned char
@ -441,7 +440,6 @@ public:
void render(const GLCanvas3D& canvas) const;
};
private:
wxGLCanvas* m_canvas;
wxGLContext* m_context;
LegendTexture m_legend_texture;
@ -605,6 +603,7 @@ public:
std::vector<int> load_object(const Model& model, int obj_idx);
int get_first_volume_id(int obj_idx) const;
int get_in_object_volume_id(int scene_vol_idx) const;
void reload_scene(bool force);

View File

@ -548,6 +548,12 @@ int GLCanvas3DManager::get_first_volume_id(wxGLCanvas* canvas, int obj_idx) cons
return (it != m_canvases.end()) ? it->second->get_first_volume_id(obj_idx) : -1;
}
int GLCanvas3DManager::get_in_object_volume_id(wxGLCanvas* canvas, int scene_vol_idx) const
{
CanvasesMap::const_iterator it = _get_canvas(canvas);
return (it != m_canvases.end()) ? it->second->get_in_object_volume_id(scene_vol_idx) : -1;
}
void GLCanvas3DManager::reload_scene(wxGLCanvas* canvas, bool force)
{
CanvasesMap::iterator it = _get_canvas(canvas);

View File

@ -138,6 +138,7 @@ public:
std::vector<int> load_object(wxGLCanvas* canvas, const Model* model, int obj_idx);
int get_first_volume_id(wxGLCanvas* canvas, int obj_idx) const;
int get_in_object_volume_id(wxGLCanvas* canvas, int scene_vol_idx) const;
void reload_scene(wxGLCanvas* canvas, bool force);

View File

@ -767,6 +767,15 @@ get_first_volume_id(canvas, obj_idx)
OUTPUT:
RETVAL
int
get_in_object_volume_id(canvas, scene_vol_idx)
SV *canvas;
int scene_vol_idx;
CODE:
RETVAL = _3DScene::get_in_object_volume_id((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), scene_vol_idx);
OUTPUT:
RETVAL
std::vector<int>
load_model(canvas, model, obj_idx)
SV *canvas;