From 4e8c570d52f73fb597d4a759a94d2056f295426f Mon Sep 17 00:00:00 2001 From: tamasmeszaros <meszaros.q@gmail.com> Date: Wed, 23 Jan 2019 13:12:44 +0100 Subject: [PATCH] Polishing autoplacement feature for testing --- .../include/libnest2d/placers/nfpplacer.hpp | 5 +- src/libslic3r/ModelArrange.cpp | 89 +++++++++++++------ src/slic3r/GUI/Plater.cpp | 17 +--- 3 files changed, 66 insertions(+), 45 deletions(-) diff --git a/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp b/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp index 3cdc0cca1..4573027e4 100644 --- a/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp +++ b/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp @@ -911,12 +911,13 @@ private: if(config_.object_function) _objfunc = config_.object_function; else { - // Inside check has to be strict if no alignment was enabled. + // Inside check has to be strict if no alignment was enabled std::function<double(const Box&)> ins_check; if(config_.alignment == Config::Alignment::DONT_ALIGN) ins_check = [&binbb, norm](const Box& fullbb) { double ret = 0; - if(sl::isInside<RawShape>(fullbb, binbb)) ret += norm; + if(sl::isInside<RawShape>(fullbb, binbb)) + ret += norm*norm; return ret; }; else diff --git a/src/libslic3r/ModelArrange.cpp b/src/libslic3r/ModelArrange.cpp index 572788925..d527db9da 100644 --- a/src/libslic3r/ModelArrange.cpp +++ b/src/libslic3r/ModelArrange.cpp @@ -434,8 +434,8 @@ template<> class AutoArranger<lnCircle>: public _ArrBase<lnCircle> { public: AutoArranger(const lnCircle& bin, Distance dist, - std::function<void(unsigned)> progressind, - std::function<bool(void)> stopcond): + std::function<void(unsigned)> progressind = [](unsigned){}, + std::function<bool(void)> stopcond = [](){return false;}): _ArrBase<lnCircle>(bin, dist, progressind, stopcond) { // As with the box, only the inside check is different. @@ -479,8 +479,8 @@ public: template<> class AutoArranger<PolygonImpl>: public _ArrBase<PolygonImpl> { public: AutoArranger(const PolygonImpl& bin, Distance dist, - std::function<void(unsigned)> progressind, - std::function<bool(void)> stopcond): + std::function<void(unsigned)> progressind = [](unsigned){}, + std::function<bool(void)> stopcond = [](){return false;}): _ArrBase<PolygonImpl>(bin, dist, progressind, stopcond) { m_pconf.object_function = [this, &bin] (const Item &item) { @@ -846,9 +846,9 @@ void find_new_position(const Model &model, }); for(auto it = shapemap.begin(); it != shapemap.end(); ++it) { - if(std::find(toadd.begin(), toadd.end(), it->first) == toadd.end() && - it->second.isInside(binbb)) { // just ignore items which are outside - preshapes.front().emplace_back(std::ref(it->second)); + if(std::find(toadd.begin(), toadd.end(), it->first) == toadd.end()) { + if(it->second.isInside(binbb)) // just ignore items which are outside + preshapes.front().emplace_back(std::ref(it->second)); } else { shapes_ptr.emplace_back(it->first); @@ -856,15 +856,12 @@ void find_new_position(const Model &model, } } - switch(bedhint.type) { - case BedShapeType::BOX: { - - // Create the arranger for the box shaped bed - AutoArranger<Box> arrange(binbb, min_obj_distance); - std::cout << "preload size: " << preshapes.front().size() << std::endl; - - if(!preshapes.front().empty()) arrange.preload(preshapes); - + auto try_first_to_center = [&shapes, &shapes_ptr, &binbb] + (std::function<bool(const Item&)> is_colliding, + std::function<void(Item&)> preload) + { + // Try to put the first item to the center, as the arranger will not + // do this for us. auto shptrit = shapes_ptr.begin(); for(auto shit = shapes.begin(); shit != shapes.end(); ++shit, ++shptrit) { @@ -873,8 +870,8 @@ void find_new_position(const Model &model, auto ibb = itm.boundingBox(); auto d = binbb.center() - ibb.center(); itm.translate(d); - if(!arrange.is_colliding(itm)) { - arrange.preload({{itm}}); + if(!is_colliding(itm)) { + preload(itm); auto offset = itm.translation(); Radians rot = itm.rotation(); @@ -892,6 +889,21 @@ void find_new_position(const Model &model, break; } } + }; + + switch(bedhint.type) { + case BedShapeType::BOX: { + + // Create the arranger for the box shaped bed + AutoArranger<Box> arrange(binbb, min_obj_distance); + + if(!preshapes.front().empty()) { // If there is something on the plate + arrange.preload(preshapes); + try_first_to_center( + [&arrange](const Item& itm) {return arrange.is_colliding(itm);}, + [&arrange](Item& itm) { arrange.preload({{itm}}); } + ); + } // Arrange and return the items with their respective indices within the // input sequence. @@ -900,26 +912,45 @@ void find_new_position(const Model &model, } case BedShapeType::CIRCLE: { -// auto c = bedhint.shape.circ; -// auto cc = to_lnCircle(c); + auto c = bedhint.shape.circ; + auto cc = to_lnCircle(c); -// AutoArranger<lnCircle> arrange(cc, min_obj_distance, progressind, cfn); -// result = arrange(shapes.begin(), shapes.end()); + // Create the arranger for the box shaped bed + AutoArranger<lnCircle> arrange(cc, min_obj_distance); + + if(!preshapes.front().empty()) { // If there is something on the plate + arrange.preload(preshapes); + try_first_to_center( + [&arrange](const Item& itm) {return arrange.is_colliding(itm);}, + [&arrange](Item& itm) { arrange.preload({{itm}}); } + ); + } + + // Arrange and return the items with their respective indices within the + // input sequence. + result = arrange(shapes.begin(), shapes.end()); break; } case BedShapeType::IRREGULAR: case BedShapeType::WHO_KNOWS: { + using P = libnest2d::PolygonImpl; -// using P = libnest2d::PolygonImpl; + auto ctour = Slic3rMultiPoint_to_ClipperPath(bed); + P irrbed = sl::create<PolygonImpl>(std::move(ctour)); -// auto ctour = Slic3rMultiPoint_to_ClipperPath(bed); -// P irrbed = sl::create<PolygonImpl>(std::move(ctour)); + AutoArranger<P> arrange(irrbed, min_obj_distance); -// AutoArranger<P> arrange(irrbed, min_obj_distance, progressind, cfn); + if(!preshapes.front().empty()) { // If there is something on the plate + arrange.preload(preshapes); + try_first_to_center( + [&arrange](const Item& itm) {return arrange.is_colliding(itm);}, + [&arrange](Item& itm) { arrange.preload({{itm}}); } + ); + } -// // Arrange and return the items with their respective indices within the -// // input sequence. -// result = arrange(shapes.begin(), shapes.end()); + // Arrange and return the items with their respective indices within the + // input sequence. + result = arrange(shapes.begin(), shapes.end()); break; } }; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 45575546f..ac4988a6c 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1399,8 +1399,6 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_ if (one_by_one) { auto loaded_idxs = load_model_objects(model.objects); obj_idxs.insert(obj_idxs.end(), loaded_idxs.begin(), loaded_idxs.end()); - - std::cout << "New model objects added..." << std::endl; } else { // This must be an .stl or .obj file, which may contain a maximum of one volume. for (const ModelObject* model_object : model.objects) { @@ -1450,7 +1448,6 @@ std::vector<size_t> Plater::priv::load_model_objects(const ModelObjectPtrs &mode const BoundingBoxf bed_shape = bed_shape_bb(); const Vec3d bed_size = Slic3r::to_3d(bed_shape.size().cast<double>(), 1.0) - 2.0 * Vec3d::Ones(); -// bool need_arrange = false; bool scaled_down = false; std::vector<size_t> obj_idxs; unsigned int obj_count = model.objects.size(); @@ -1462,16 +1459,8 @@ std::vector<size_t> Plater::priv::load_model_objects(const ModelObjectPtrs &mode obj_idxs.push_back(obj_count++); if (model_object->instances.empty()) { - // if object has no defined position(s) we need to rearrange everything after loading -// need_arrange = true; - object->center_around_origin(); new_instances.emplace_back(object->add_instance()); - -// // add a default instance and center object around origin -// object->center_around_origin(); // also aligns object to Z = 0 -// ModelInstance* instance = object->add_instance(); -// instance->set_offset(Slic3r::to_3d(bed_shape.center().cast<double>(), -object->origin_translation(2))); } const Vec3d size = object->bounding_box().size(); @@ -1498,7 +1487,7 @@ std::vector<size_t> Plater::priv::load_model_objects(const ModelObjectPtrs &mode // print.add_model_object(object); } - // FIXME distance should be a config value + // FIXME distance should be a config value ///////////////////////////////// auto min_obj_distance = static_cast<coord_t>(6/SCALING_FACTOR); const auto *bed_shape_opt = config->opt<ConfigOptionPoints>("bed_shape"); assert(bed_shape_opt); @@ -1506,8 +1495,8 @@ std::vector<size_t> Plater::priv::load_model_objects(const ModelObjectPtrs &mode Polyline bed; bed.points.reserve(bedpoints.size()); for(auto& v : bedpoints) bed.append(Point::new_scale(v(0), v(1))); - arr::find_new_position(model, new_instances, - min_obj_distance, bed); + arr::find_new_position(model, new_instances, min_obj_distance, bed); + // ///////////////////////////////////////////////////////////////////////// if (scaled_down) { GUI::show_info(q,