mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-10-24 09:11:23 -06:00
Adapt find_new_position is WIP. Cleaning up comments.
This commit is contained in:
parent
299e4f74c7
commit
cb3a586deb
5 changed files with 181 additions and 301 deletions
|
|
@ -1,5 +1,4 @@
|
|||
#include "ModelArrange.hpp"
|
||||
//#include "Model.hpp"
|
||||
#include "Geometry.hpp"
|
||||
#include "SVG.hpp"
|
||||
#include "MTUtils.hpp"
|
||||
|
|
@ -656,34 +655,35 @@ BedShapeHint bedShape(const Polyline &bed) {
|
|||
|
||||
//static const SLIC3R_CONSTEXPR double SIMPLIFY_TOLERANCE_MM = 0.1;
|
||||
|
||||
//template<class BinT>
|
||||
//PackGroup _arrange(std::vector<Item> & items,
|
||||
// const BinT & bin,
|
||||
// coord_t minobjd,
|
||||
// std::function<void(unsigned)> prind,
|
||||
// std::function<bool()> stopfn)
|
||||
//{
|
||||
// AutoArranger<BinT> arranger{bin, minobjd, prind, stopfn};
|
||||
// return arranger(items.begin(), items.end());
|
||||
//}
|
||||
|
||||
template<class BinT>
|
||||
PackGroup _arrange(std::vector<Item> & items,
|
||||
PackGroup _arrange(std::vector<Item> & shapes,
|
||||
const PackGroup & preshapes,
|
||||
const BinT & bin,
|
||||
coord_t minobjd,
|
||||
std::function<void(unsigned)> prind,
|
||||
std::function<bool()> stopfn)
|
||||
{
|
||||
AutoArranger<BinT> arranger{bin, minobjd, prind, stopfn};
|
||||
return arranger(items.begin(), items.end());
|
||||
}
|
||||
|
||||
//template<class BinT>
|
||||
//IndexedPackGroup _arrange(std::vector<std::reference_wrapper<Item>> &shapes,
|
||||
// const PackGroup & preshapes,
|
||||
// std::vector<ModelInstance *> &minstances,
|
||||
// const BinT & bin,
|
||||
// coord_t minobjd)
|
||||
//{
|
||||
|
||||
// auto binbb = sl::boundingBox(bin);
|
||||
|
||||
// AutoArranger<BinT> arranger{bin, minobjd};
|
||||
AutoArranger<BinT> arranger{bin, minobjd, prind, stopfn};
|
||||
|
||||
// if(!preshapes.front().empty()) { // If there is something on the plate
|
||||
// arranger.preload(preshapes);
|
||||
if(!preshapes.front().empty()) { // If there is something on the plate
|
||||
arranger.preload(preshapes);
|
||||
|
||||
// // Try to put the first item to the center, as the arranger will not
|
||||
// // do this for us.
|
||||
// Try to put the first item to the center, as the arranger will not
|
||||
// do this for us.
|
||||
// auto shptrit = minstances.begin();
|
||||
// for(auto shit = shapes.begin(); shit != shapes.end(); ++shit, ++shptrit)
|
||||
// {
|
||||
|
|
@ -712,10 +712,10 @@ PackGroup _arrange(std::vector<Item> & items,
|
|||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
// return arranger(shapes.begin(), shapes.end());
|
||||
//}
|
||||
return arranger(shapes.begin(), shapes.end());
|
||||
}
|
||||
|
||||
inline SLIC3R_CONSTEXPR coord_t stride_padding(coord_t w)
|
||||
{
|
||||
|
|
@ -725,53 +725,73 @@ inline SLIC3R_CONSTEXPR coord_t stride_padding(coord_t w)
|
|||
//// The final client function to arrange the Model. A progress indicator and
|
||||
//// a stop predicate can be also be passed to control the process.
|
||||
bool arrange(Arrangeables & arrangables,
|
||||
const Arrangeables & excludes,
|
||||
coord_t min_obj_distance,
|
||||
BedShapeHint bedhint,
|
||||
const BedShapeHint & bedhint,
|
||||
std::function<void(unsigned)> progressind,
|
||||
std::function<bool()> stopcondition)
|
||||
{
|
||||
bool ret = true;
|
||||
namespace clppr = ClipperLib;
|
||||
|
||||
std::vector<Item> items;
|
||||
std::vector<Item> items, excluded_items;
|
||||
items.reserve(arrangables.size());
|
||||
coord_t binwidth = 0;
|
||||
|
||||
for (Arrangeable *arrangeable : arrangables) {
|
||||
assert(arrangeable);
|
||||
|
||||
auto arrangeitem = arrangeable->get_arrange_polygon();
|
||||
|
||||
Polygon& p = std::get<0>(arrangeitem);
|
||||
const Vec2crd& offs = std::get<1>(arrangeitem);
|
||||
double rotation = std::get<2>(arrangeitem);
|
||||
|
||||
if (p.is_counter_clockwise()) p.reverse();
|
||||
|
||||
clppr::Polygon clpath(Slic3rMultiPoint_to_ClipperPath(p));
|
||||
|
||||
auto firstp = clpath.Contour.front();
|
||||
clpath.Contour.emplace_back(firstp);
|
||||
PackGroup preshapes{ {} }; // pack group with one initial bin for preloading
|
||||
|
||||
items.emplace_back(
|
||||
auto process_arrangeable =
|
||||
[](const Arrangeable * arrangeable,
|
||||
std::vector<Item> & outp,
|
||||
std::function<void(const Item &, unsigned)> applyfn)
|
||||
{
|
||||
assert(arrangeable);
|
||||
|
||||
auto arrangeitem = arrangeable->get_arrange_polygon();
|
||||
|
||||
Polygon & p = std::get<0>(arrangeitem);
|
||||
const Vec2crd &offs = std::get<1>(arrangeitem);
|
||||
double rotation = std::get<2>(arrangeitem);
|
||||
|
||||
if (p.is_counter_clockwise()) p.reverse();
|
||||
|
||||
clppr::Polygon clpath(Slic3rMultiPoint_to_ClipperPath(p));
|
||||
|
||||
auto firstp = clpath.Contour.front();
|
||||
clpath.Contour.emplace_back(firstp);
|
||||
|
||||
outp.emplace_back(applyfn, std::move(clpath));
|
||||
outp.front().rotation(rotation);
|
||||
outp.front().translation({offs.x(), offs.y()});
|
||||
};
|
||||
|
||||
for (Arrangeable *arrangeable : arrangables) {
|
||||
process_arrangeable(
|
||||
arrangeable,
|
||||
items,
|
||||
// callback called by arrange to apply the result on the arrangeable
|
||||
[arrangeable, &binwidth](const Item &itm, unsigned binidx) {
|
||||
clppr::cInt stride = binidx * stride_padding(binwidth);
|
||||
|
||||
clppr::IntPoint offs = itm.translation();
|
||||
arrangeable->apply_arrange_result({unscaled(offs.X + stride),
|
||||
arrangeable->apply_arrange_result({unscaled(offs.X +
|
||||
stride),
|
||||
unscaled(offs.Y)},
|
||||
itm.rotation());
|
||||
},
|
||||
std::move(clpath));
|
||||
items.front().rotation(rotation);
|
||||
items.front().translation({offs.x(), offs.y()});
|
||||
});
|
||||
}
|
||||
|
||||
for (const Arrangeable * fixed: excludes)
|
||||
process_arrangeable(fixed, excluded_items, nullptr);
|
||||
|
||||
for(Item& excl : excluded_items) preshapes.front().emplace_back(excl);
|
||||
|
||||
// Integer ceiling the min distance from the bed perimeters
|
||||
coord_t md = min_obj_distance - SCALED_EPSILON;
|
||||
md = (md % 2) ? md / 2 + 1 : md / 2;
|
||||
|
||||
|
||||
auto& cfn = stopcondition;
|
||||
|
||||
switch (bedhint.type) {
|
||||
case BedShapeType::BOX: {
|
||||
// Create the arranger for the box shaped bed
|
||||
|
|
@ -781,14 +801,14 @@ bool arrange(Arrangeables & arrangables,
|
|||
Box binbb{{bbb.min(X), bbb.min(Y)}, {bbb.max(X), bbb.max(Y)}};
|
||||
binwidth = coord_t(binbb.width());
|
||||
|
||||
_arrange(items, binbb, min_obj_distance, progressind, stopcondition);
|
||||
_arrange(items, preshapes, binbb, min_obj_distance, progressind, cfn);
|
||||
break;
|
||||
}
|
||||
case BedShapeType::CIRCLE: {
|
||||
auto c = bedhint.shape.circ;
|
||||
auto cc = to_lnCircle(c);
|
||||
binwidth = scaled(c.radius());
|
||||
_arrange(items, cc, min_obj_distance, progressind, stopcondition);
|
||||
_arrange(items, preshapes, cc, min_obj_distance, progressind, cfn);
|
||||
break;
|
||||
}
|
||||
case BedShapeType::IRREGULAR: {
|
||||
|
|
@ -796,11 +816,11 @@ bool arrange(Arrangeables & arrangables,
|
|||
auto irrbed = sl::create<clppr::Polygon>(std::move(ctour));
|
||||
BoundingBox polybb(bedhint.shape.polygon);
|
||||
binwidth = (polybb.max(X) - polybb.min(X));
|
||||
_arrange(items, irrbed, min_obj_distance, progressind, stopcondition);
|
||||
_arrange(items, preshapes, irrbed, min_obj_distance, progressind, cfn);
|
||||
break;
|
||||
}
|
||||
case BedShapeType::WHO_KNOWS: {
|
||||
_arrange(items, false, min_obj_distance, progressind, stopcondition);
|
||||
_arrange(items, preshapes, false, min_obj_distance, progressind, cfn);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
|
@ -810,99 +830,15 @@ bool arrange(Arrangeables & arrangables,
|
|||
return ret;
|
||||
}
|
||||
|
||||
//void find_new_position(const Model &model,
|
||||
// ModelInstancePtrs toadd,
|
||||
// coord_t min_obj_distance,
|
||||
// const Polyline &bed,
|
||||
// WipeTowerInfo& wti)
|
||||
//{
|
||||
// // Get the 2D projected shapes with their 3D model instance pointers
|
||||
// auto shapemap = arr::projectModelFromTop(model, wti, SIMPLIFY_TOLERANCE_MM);
|
||||
|
||||
// // Copy the references for the shapes only, as the arranger expects a
|
||||
// // sequence of objects convertible to Item or ClipperPolygon
|
||||
// PackGroup preshapes; preshapes.emplace_back();
|
||||
// ItemGroup shapes;
|
||||
// preshapes.front().reserve(shapemap.size());
|
||||
|
||||
// std::vector<ModelInstance*> shapes_ptr; shapes_ptr.reserve(toadd.size());
|
||||
// IndexedPackGroup result;
|
||||
|
||||
// // If there is no hint about the shape, we will try to guess
|
||||
// BedShapeHint bedhint = bedShape(bed);
|
||||
|
||||
// BoundingBox bbb(bed);
|
||||
|
||||
// // Integer ceiling the min distance from the bed perimeters
|
||||
// coord_t md = min_obj_distance - SCALED_EPSILON;
|
||||
// md = (md % 2) ? md / 2 + 1 : md / 2;
|
||||
|
||||
// auto binbb = Box({ClipperLib::cInt{bbb.min(0)} - md,
|
||||
// ClipperLib::cInt{bbb.min(1)} - md},
|
||||
// {ClipperLib::cInt{bbb.max(0)} + md,
|
||||
// ClipperLib::cInt{bbb.max(1)} + md});
|
||||
|
||||
// for(auto it = shapemap.begin(); it != shapemap.end(); ++it) {
|
||||
// // `toadd` vector contains the instance pointers which have to be
|
||||
// // considered by arrange. If `it` points to an ModelInstance, which
|
||||
// // is NOT in `toadd`, add it to preshapes.
|
||||
// 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);
|
||||
// shapes.emplace_back(std::ref(it->second));
|
||||
// }
|
||||
// }
|
||||
|
||||
// switch(bedhint.type) {
|
||||
// case BedShapeType::BOX: {
|
||||
// // Create the arranger for the box shaped bed
|
||||
// result = _arrange(shapes, preshapes, shapes_ptr, binbb, min_obj_distance);
|
||||
// break;
|
||||
// }
|
||||
// case BedShapeType::CIRCLE: {
|
||||
// auto c = bedhint.shape.circ;
|
||||
// auto cc = to_lnCircle(c);
|
||||
// result = _arrange(shapes, preshapes, shapes_ptr, cc, min_obj_distance);
|
||||
// break;
|
||||
// }
|
||||
// case BedShapeType::IRREGULAR:
|
||||
// case BedShapeType::WHO_KNOWS: {
|
||||
// auto ctour = Slic3rMultiPoint_to_ClipperPath(bed);
|
||||
// ClipperLib::Polygon irrbed = sl::create<PolygonImpl>(std::move(ctour));
|
||||
// result = _arrange(shapes, preshapes, shapes_ptr, irrbed, min_obj_distance);
|
||||
// break;
|
||||
// }
|
||||
// };
|
||||
|
||||
// // Now we go through the result which will contain the fixed and the moving
|
||||
// // polygons as well. We will have to search for our item.
|
||||
|
||||
// ClipperLib::cInt stride = stride_padding(binbb.width());
|
||||
// ClipperLib::cInt batch_offset = 0;
|
||||
|
||||
// for(auto& group : result) {
|
||||
// for(auto& r : group) if(r.first < shapes.size()) {
|
||||
// Item& resultitem = r.second;
|
||||
// unsigned idx = r.first;
|
||||
// auto offset = resultitem.translation();
|
||||
// Radians rot = resultitem.rotation();
|
||||
// ModelInstance *minst = shapes_ptr[idx];
|
||||
// Vec3d foffset(unscaled(offset.X + batch_offset),
|
||||
// unscaled(offset.Y),
|
||||
// minst->get_offset()(Z));
|
||||
|
||||
// // write the transformation data into the model instance
|
||||
// minst->set_rotation(Z, rot);
|
||||
// minst->set_offset(foffset);
|
||||
// }
|
||||
// batch_offset += stride;
|
||||
// }
|
||||
//}
|
||||
|
||||
/// Arrange, without the fixed items (excludes)
|
||||
bool arrange(Arrangeables & inp,
|
||||
coord_t min_d,
|
||||
const BedShapeHint & bedhint,
|
||||
std::function<void(unsigned)> prfn,
|
||||
std::function<bool()> stopfn)
|
||||
{
|
||||
return arrange(inp, {}, min_d, bedhint, prfn, stopfn);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
} // namespace arr
|
||||
} // namespace Slic3r
|
||||
|
|
|
|||
|
|
@ -1,16 +1,14 @@
|
|||
#ifndef MODELARRANGE_HPP
|
||||
#define MODELARRANGE_HPP
|
||||
|
||||
//#include "Model.hpp"
|
||||
#include "Polygon.hpp"
|
||||
#include "BoundingBox.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class Model;
|
||||
|
||||
namespace arr {
|
||||
|
||||
/// A geometry abstraction for a circular print bed. Similarly to BoundingBox.
|
||||
class CircleBed {
|
||||
Point center_;
|
||||
double radius_;
|
||||
|
|
@ -24,6 +22,7 @@ public:
|
|||
inline operator bool() { return !std::isnan(radius_); }
|
||||
};
|
||||
|
||||
/// Types of print bed shapes.
|
||||
enum class BedShapeType {
|
||||
BOX,
|
||||
CIRCLE,
|
||||
|
|
@ -31,6 +30,7 @@ enum class BedShapeType {
|
|||
WHO_KNOWS
|
||||
};
|
||||
|
||||
/// Info about the print bed for the arrange() function.
|
||||
struct BedShapeHint {
|
||||
BedShapeType type = BedShapeType::WHO_KNOWS;
|
||||
/*union*/ struct { // I know but who cares... TODO: use variant from cpp17?
|
||||
|
|
@ -40,13 +40,19 @@ struct BedShapeHint {
|
|||
} shape;
|
||||
};
|
||||
|
||||
/// Get a bed shape hint for arrange() from a naked Polyline.
|
||||
BedShapeHint bedShape(const Polyline& bed);
|
||||
|
||||
/**
|
||||
* @brief Classes implementing the Arrangeable interface can be used as input
|
||||
* to the arrange function.
|
||||
*/
|
||||
class Arrangeable {
|
||||
public:
|
||||
|
||||
virtual ~Arrangeable() = default;
|
||||
|
||||
/// Apply the result transformation calculated by the arrangement.
|
||||
virtual void apply_arrange_result(Vec2d offset, double rotation_rads) = 0;
|
||||
|
||||
/// Get the 2D silhouette to arrange and an initial offset and rotation
|
||||
|
|
@ -58,56 +64,48 @@ using Arrangeables = std::vector<Arrangeable*>;
|
|||
/**
|
||||
* \brief Arranges the model objects on the screen.
|
||||
*
|
||||
* The arrangement considers multiple bins (aka. print beds) for placing all
|
||||
* the items provided in the model argument. If the items don't fit on one
|
||||
* print bed, the remaining will be placed onto newly created print beds.
|
||||
* The first_bin_only parameter, if set to true, disables this behavior and
|
||||
* makes sure that only one print bed is filled and the remaining items will be
|
||||
* untouched. When set to false, the items which could not fit onto the
|
||||
* print bed will be placed next to the print bed so the user should see a
|
||||
* pile of items on the print bed and some other piles outside the print
|
||||
* area that can be dragged later onto the print bed as a group.
|
||||
* The arrangement considers multiple bins (aka. print beds) for placing
|
||||
* all the items provided in the model argument. If the items don't fit on
|
||||
* one print bed, the remaining will be placed onto newly created print
|
||||
* beds. The first_bin_only parameter, if set to true, disables this
|
||||
* behavior and makes sure that only one print bed is filled and the
|
||||
* remaining items will be untouched. When set to false, the items which
|
||||
* could not fit onto the print bed will be placed next to the print bed so
|
||||
* the user should see a pile of items on the print bed and some other
|
||||
* piles outside the print area that can be dragged later onto the print
|
||||
* bed as a group.
|
||||
*
|
||||
* \param items Input which are object pointers implementing the
|
||||
* Arrangeable interface.
|
||||
*
|
||||
* \param min_obj_distance The minimum distance which is allowed for any
|
||||
* pair of items on the print bed in any direction.
|
||||
*
|
||||
* \param bedhint Info about the shape and type of the
|
||||
* bed. 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 model The model object with the 3D content.
|
||||
* \param dist The minimum distance which is allowed for any pair of items
|
||||
* on the print bed in any direction.
|
||||
* \param bb The bounding box of the print bed. It corresponds to the 'bin'
|
||||
* for bin packing.
|
||||
* \param first_bin_only This parameter controls whether to place the
|
||||
* 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,
|
||||
// WipeTowerInfo& wipe_tower_info,
|
||||
// coord_t min_obj_distance,
|
||||
// const Slic3r::Polyline& bed,
|
||||
// BedShapeHint bedhint,
|
||||
// bool first_bin_only,
|
||||
// std::function<void(unsigned)> progressind,
|
||||
// std::function<bool(void)> stopcondition);
|
||||
|
||||
bool arrange(Arrangeables &items,
|
||||
coord_t min_obj_distance,
|
||||
BedShapeHint bedhint,
|
||||
const BedShapeHint& bedhint,
|
||||
std::function<void(unsigned)> progressind,
|
||||
std::function<bool(void)> stopcondition);
|
||||
|
||||
/// This will find a suitable position for a new object instance and leave the
|
||||
/// old items untouched.
|
||||
//void find_new_position(const Model& model,
|
||||
// ModelInstancePtrs instances_to_add,
|
||||
// coord_t min_obj_distance,
|
||||
// const Slic3r::Polyline& bed,
|
||||
// WipeTowerInfo& wti);
|
||||
void find_new_position(Arrangeables &items,
|
||||
const Arrangeables &instances_to_add,
|
||||
coord_t min_obj_distance,
|
||||
BedShapeHint bedhint);
|
||||
|
||||
/// Same as the previous, only that it takes unmovable items as an
|
||||
/// additional argument.
|
||||
bool arrange(Arrangeables &items,
|
||||
const Arrangeables &excludes,
|
||||
coord_t min_obj_distance,
|
||||
const BedShapeHint& bedhint,
|
||||
std::function<void(unsigned)> progressind,
|
||||
std::function<bool(void)> stopcondition);
|
||||
|
||||
} // arr
|
||||
} // Slic3r
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue