Working on arrange selection only
feature.
revert changes related to scale/unscale
This commit is contained in:
parent
f93e7496f7
commit
f4ed0d8137
1 changed files with 104 additions and 134 deletions
|
@ -667,11 +667,10 @@ ShapeData2D projectModelFromTop(const Slic3r::Model &model,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply the calculated translations and rotations (currently disabled) to the
|
// Apply the calculated translations and rotations (currently disabled) to
|
||||||
// Model object instances.
|
// the Model object instances.
|
||||||
void applyResult(
|
void applyResult(IndexedPackGroup::value_type &group,
|
||||||
IndexedPackGroup::value_type& group,
|
ClipperLib::cInt batch_offset,
|
||||||
Coord batch_offset,
|
|
||||||
ShapeData2D & shapemap,
|
ShapeData2D & shapemap,
|
||||||
WipeTowerInfo & wti)
|
WipeTowerInfo & wti)
|
||||||
{
|
{
|
||||||
|
@ -687,8 +686,8 @@ void applyResult(
|
||||||
auto off = item.translation();
|
auto off = item.translation();
|
||||||
Radians rot = item.rotation();
|
Radians rot = item.rotation();
|
||||||
|
|
||||||
Vec3d foff(off.X*SCALING_FACTOR + batch_offset,
|
Vec3d foff(unscaled(off.X + batch_offset) ,
|
||||||
off.Y*SCALING_FACTOR,
|
unscaled(off.Y),
|
||||||
inst_ptr ? inst_ptr->get_offset()(Z) : 0.);
|
inst_ptr ? inst_ptr->get_offset()(Z) : 0.);
|
||||||
|
|
||||||
if (inst_ptr) {
|
if (inst_ptr) {
|
||||||
|
@ -785,6 +784,72 @@ BedShapeHint bedShape(const Polyline &bed) {
|
||||||
|
|
||||||
static const SLIC3R_CONSTEXPR double SIMPLIFY_TOLERANCE_MM = 0.1;
|
static const SLIC3R_CONSTEXPR double SIMPLIFY_TOLERANCE_MM = 0.1;
|
||||||
|
|
||||||
|
template<class BinT>
|
||||||
|
IndexedPackGroup _arrange(std::vector<std::reference_wrapper<Item>> &shapes,
|
||||||
|
const BinT & bin,
|
||||||
|
coord_t minobjd,
|
||||||
|
std::function<void(unsigned)> prind,
|
||||||
|
std::function<bool()> stopfn)
|
||||||
|
{
|
||||||
|
AutoArranger<BinT> arranger{bin, minobjd, prind, stopfn};
|
||||||
|
return arranger(shapes.begin(), shapes.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};
|
||||||
|
|
||||||
|
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.
|
||||||
|
auto shptrit = minstances.begin();
|
||||||
|
for(auto shit = shapes.begin(); shit != shapes.end(); ++shit, ++shptrit)
|
||||||
|
{
|
||||||
|
// Try to place items to the center
|
||||||
|
Item& itm = *shit;
|
||||||
|
auto ibb = itm.boundingBox();
|
||||||
|
auto d = binbb.center() - ibb.center();
|
||||||
|
itm.translate(d);
|
||||||
|
if(!arranger.is_colliding(itm)) {
|
||||||
|
arranger.preload({{itm}});
|
||||||
|
|
||||||
|
auto offset = itm.translation();
|
||||||
|
Radians rot = itm.rotation();
|
||||||
|
ModelInstance *minst = *shptrit;
|
||||||
|
|
||||||
|
Vec3d foffset(unscaled(offset.X),
|
||||||
|
unscaled(offset.Y),
|
||||||
|
minst->get_offset()(Z));
|
||||||
|
|
||||||
|
// write the transformation data into the model instance
|
||||||
|
minst->set_rotation(Z, rot);
|
||||||
|
minst->set_offset(foffset);
|
||||||
|
|
||||||
|
shit = shapes.erase(shit);
|
||||||
|
shptrit = minstances.erase(shptrit);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return arranger(shapes.begin(), shapes.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline SLIC3R_CONSTEXPR libnest2d::Coord stride_padding(Coord w)
|
||||||
|
{
|
||||||
|
return w + w / 5;
|
||||||
|
}
|
||||||
|
|
||||||
// The final client function to arrange the Model. A progress indicator and
|
// The final client function to arrange the Model. A progress indicator and
|
||||||
// a stop predicate can be also be passed to control the process.
|
// a stop predicate can be also be passed to control the process.
|
||||||
bool arrange(Model &model, // The model with the geometries
|
bool arrange(Model &model, // The model with the geometries
|
||||||
|
@ -826,44 +891,28 @@ bool arrange(Model &model, // The model with the geometries
|
||||||
coord_t md = min_obj_distance - SCALED_EPSILON;
|
coord_t md = min_obj_distance - SCALED_EPSILON;
|
||||||
md = (md % 2) ? md / 2 + 1 : md / 2;
|
md = (md % 2) ? md / 2 + 1 : md / 2;
|
||||||
|
|
||||||
auto binbb = Box({libnest2d::Coord{bbb.min(0)} - md,
|
auto binbb = Box({ClipperLib::cInt{bbb.min(0)} - md,
|
||||||
libnest2d::Coord{bbb.min(1)} - md},
|
ClipperLib::cInt{bbb.min(1)} - md},
|
||||||
{libnest2d::Coord{bbb.max(0)} + md,
|
{ClipperLib::cInt{bbb.max(0)} + md,
|
||||||
libnest2d::Coord{bbb.max(1)} + md});
|
ClipperLib::cInt{bbb.max(1)} + md});
|
||||||
|
|
||||||
switch(bedhint.type) {
|
switch(bedhint.type) {
|
||||||
case BedShapeType::BOX: {
|
case BedShapeType::BOX: {
|
||||||
|
|
||||||
// Create the arranger for the box shaped bed
|
// Create the arranger for the box shaped bed
|
||||||
AutoArranger<Box> arrange(binbb, min_obj_distance, progressind, cfn);
|
result = _arrange(shapes, binbb, min_obj_distance, progressind, cfn);
|
||||||
|
|
||||||
// Arrange and return the items with their respective indices within the
|
|
||||||
// input sequence.
|
|
||||||
result = arrange(shapes.begin(), shapes.end());
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case BedShapeType::CIRCLE: {
|
case BedShapeType::CIRCLE: {
|
||||||
|
|
||||||
auto c = bedhint.shape.circ;
|
auto c = bedhint.shape.circ;
|
||||||
auto cc = to_lnCircle(c);
|
auto cc = to_lnCircle(c);
|
||||||
|
result = _arrange(shapes, cc, min_obj_distance, progressind, cfn);
|
||||||
AutoArranger<lnCircle> arrange(cc, min_obj_distance, progressind, cfn);
|
|
||||||
result = arrange(shapes.begin(), shapes.end());
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case BedShapeType::IRREGULAR:
|
case BedShapeType::IRREGULAR:
|
||||||
case BedShapeType::WHO_KNOWS: {
|
case BedShapeType::WHO_KNOWS: {
|
||||||
|
|
||||||
using P = libnest2d::PolygonImpl;
|
|
||||||
|
|
||||||
auto ctour = Slic3rMultiPoint_to_ClipperPath(bed);
|
auto ctour = Slic3rMultiPoint_to_ClipperPath(bed);
|
||||||
P irrbed = sl::create<PolygonImpl>(std::move(ctour));
|
ClipperLib::Polygon irrbed = sl::create<PolygonImpl>(std::move(ctour));
|
||||||
|
result = _arrange(shapes, irrbed, min_obj_distance, progressind, cfn);
|
||||||
AutoArranger<P> arrange(irrbed, min_obj_distance, progressind, cfn);
|
|
||||||
|
|
||||||
// Arrange and return the items with their respective indices within the
|
|
||||||
// input sequence.
|
|
||||||
result = arrange(shapes.begin(), shapes.end());
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -874,11 +923,8 @@ bool arrange(Model &model, // The model with the geometries
|
||||||
applyResult(result.front(), 0, shapemap, wti);
|
applyResult(result.front(), 0, shapemap, wti);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
const auto STRIDE_PADDING = 1.2;
|
ClipperLib::cInt stride = stride_padding(binbb.width());
|
||||||
|
ClipperLib::cInt batch_offset = 0;
|
||||||
Coord stride = static_cast<Coord>(STRIDE_PADDING*
|
|
||||||
binbb.width()*SCALING_FACTOR);
|
|
||||||
Coord batch_offset = 0;
|
|
||||||
|
|
||||||
for(auto& group : result) {
|
for(auto& group : result) {
|
||||||
applyResult(group, batch_offset, shapemap, wti);
|
applyResult(group, batch_offset, shapemap, wti);
|
||||||
|
@ -904,7 +950,7 @@ void find_new_position(const Model &model,
|
||||||
// Get the 2D projected shapes with their 3D model instance pointers
|
// Get the 2D projected shapes with their 3D model instance pointers
|
||||||
auto shapemap = arr::projectModelFromTop(model, wti, SIMPLIFY_TOLERANCE_MM);
|
auto shapemap = arr::projectModelFromTop(model, wti, SIMPLIFY_TOLERANCE_MM);
|
||||||
|
|
||||||
// Copy the references for the shapes only as the arranger expects a
|
// Copy the references for the shapes only, as the arranger expects a
|
||||||
// sequence of objects convertible to Item or ClipperPolygon
|
// sequence of objects convertible to Item or ClipperPolygon
|
||||||
PackGroup preshapes; preshapes.emplace_back();
|
PackGroup preshapes; preshapes.emplace_back();
|
||||||
ItemGroup shapes;
|
ItemGroup shapes;
|
||||||
|
@ -922,12 +968,15 @@ void find_new_position(const Model &model,
|
||||||
coord_t md = min_obj_distance - SCALED_EPSILON;
|
coord_t md = min_obj_distance - SCALED_EPSILON;
|
||||||
md = (md % 2) ? md / 2 + 1 : md / 2;
|
md = (md % 2) ? md / 2 + 1 : md / 2;
|
||||||
|
|
||||||
auto binbb = Box({libnest2d::Coord{bbb.min(0)} - md,
|
auto binbb = Box({ClipperLib::cInt{bbb.min(0)} - md,
|
||||||
libnest2d::Coord{bbb.min(1)} - md},
|
ClipperLib::cInt{bbb.min(1)} - md},
|
||||||
{libnest2d::Coord{bbb.max(0)} + md,
|
{ClipperLib::cInt{bbb.max(0)} + md,
|
||||||
libnest2d::Coord{bbb.max(1)} + md});
|
ClipperLib::cInt{bbb.max(1)} + md});
|
||||||
|
|
||||||
for(auto it = shapemap.begin(); it != shapemap.end(); ++it) {
|
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(std::find(toadd.begin(), toadd.end(), it->first) == toadd.end()) {
|
||||||
if(it->second.isInside(binbb)) // just ignore items which are outside
|
if(it->second.isInside(binbb)) // just ignore items which are outside
|
||||||
preshapes.front().emplace_back(std::ref(it->second));
|
preshapes.front().emplace_back(std::ref(it->second));
|
||||||
|
@ -938,101 +987,23 @@ void find_new_position(const Model &model,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
// Try to place items to the center
|
|
||||||
Item& itm = *shit;
|
|
||||||
auto ibb = itm.boundingBox();
|
|
||||||
auto d = binbb.center() - ibb.center();
|
|
||||||
itm.translate(d);
|
|
||||||
if(!is_colliding(itm)) {
|
|
||||||
preload(itm);
|
|
||||||
|
|
||||||
auto offset = itm.translation();
|
|
||||||
Radians rot = itm.rotation();
|
|
||||||
ModelInstance *minst = *shptrit;
|
|
||||||
Vec3d foffset(offset.X*SCALING_FACTOR,
|
|
||||||
offset.Y*SCALING_FACTOR,
|
|
||||||
minst->get_offset()(Z));
|
|
||||||
|
|
||||||
// write the transformation data into the model instance
|
|
||||||
minst->set_rotation(Z, rot);
|
|
||||||
minst->set_offset(foffset);
|
|
||||||
|
|
||||||
shit = shapes.erase(shit);
|
|
||||||
shptrit = shapes_ptr.erase(shptrit);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
switch(bedhint.type) {
|
switch(bedhint.type) {
|
||||||
case BedShapeType::BOX: {
|
case BedShapeType::BOX: {
|
||||||
|
|
||||||
// Create the arranger for the box shaped bed
|
// Create the arranger for the box shaped bed
|
||||||
AutoArranger<Box> arrange(binbb, min_obj_distance);
|
result = _arrange(shapes, preshapes, shapes_ptr, 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.
|
|
||||||
result = arrange(shapes.begin(), shapes.end());
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case BedShapeType::CIRCLE: {
|
case BedShapeType::CIRCLE: {
|
||||||
|
|
||||||
auto c = bedhint.shape.circ;
|
auto c = bedhint.shape.circ;
|
||||||
auto cc = to_lnCircle(c);
|
auto cc = to_lnCircle(c);
|
||||||
|
result = _arrange(shapes, preshapes, shapes_ptr, cc, min_obj_distance);
|
||||||
// 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;
|
break;
|
||||||
}
|
}
|
||||||
case BedShapeType::IRREGULAR:
|
case BedShapeType::IRREGULAR:
|
||||||
case BedShapeType::WHO_KNOWS: {
|
case BedShapeType::WHO_KNOWS: {
|
||||||
using P = libnest2d::PolygonImpl;
|
|
||||||
|
|
||||||
auto ctour = Slic3rMultiPoint_to_ClipperPath(bed);
|
auto ctour = Slic3rMultiPoint_to_ClipperPath(bed);
|
||||||
P irrbed = sl::create<PolygonImpl>(std::move(ctour));
|
ClipperLib::Polygon irrbed = sl::create<PolygonImpl>(std::move(ctour));
|
||||||
|
result = _arrange(shapes, preshapes, shapes_ptr, irrbed, min_obj_distance);
|
||||||
AutoArranger<P> arrange(irrbed, 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;
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1040,9 +1011,8 @@ void find_new_position(const Model &model,
|
||||||
// Now we go through the result which will contain the fixed and the moving
|
// 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.
|
// polygons as well. We will have to search for our item.
|
||||||
|
|
||||||
const auto STRIDE_PADDING = 1.2;
|
ClipperLib::cInt stride = stride_padding(binbb.width());
|
||||||
Coord stride = Coord(STRIDE_PADDING*binbb.width()*SCALING_FACTOR);
|
ClipperLib::cInt batch_offset = 0;
|
||||||
Coord batch_offset = 0;
|
|
||||||
|
|
||||||
for(auto& group : result) {
|
for(auto& group : result) {
|
||||||
for(auto& r : group) if(r.first < shapes.size()) {
|
for(auto& r : group) if(r.first < shapes.size()) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue