mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-12 01:07:57 -06:00
Wip in Nester interface
This commit is contained in:
parent
e81f8a5fd9
commit
9372f1c6ad
2 changed files with 141 additions and 124 deletions
|
@ -36,20 +36,20 @@ class _Item {
|
||||||
// Transformation data
|
// Transformation data
|
||||||
Vertex translation_;
|
Vertex translation_;
|
||||||
Radians rotation_;
|
Radians rotation_;
|
||||||
Coord offset_distance_;
|
Coord inflation_;
|
||||||
|
|
||||||
// Info about whether the transformations will have to take place
|
// Info about whether the transformations will have to take place
|
||||||
// This is needed because if floating point is used, it is hard to say
|
// This is needed because if floating point is used, it is hard to say
|
||||||
// that a zero angle is not a rotation because of testing for equality.
|
// that a zero angle is not a rotation because of testing for equality.
|
||||||
bool has_rotation_ = false, has_translation_ = false, has_offset_ = false;
|
bool has_rotation_ = false, has_translation_ = false, has_inflation_ = false;
|
||||||
|
|
||||||
// For caching the calculations as they can get pretty expensive.
|
// For caching the calculations as they can get pretty expensive.
|
||||||
mutable RawShape tr_cache_;
|
mutable RawShape tr_cache_;
|
||||||
mutable bool tr_cache_valid_ = false;
|
mutable bool tr_cache_valid_ = false;
|
||||||
mutable double area_cache_ = 0;
|
mutable double area_cache_ = 0;
|
||||||
mutable bool area_cache_valid_ = false;
|
mutable bool area_cache_valid_ = false;
|
||||||
mutable RawShape offset_cache_;
|
mutable RawShape inflate_cache_;
|
||||||
mutable bool offset_cache_valid_ = false;
|
mutable bool inflate_cache_valid_ = false;
|
||||||
|
|
||||||
enum class Convexity: char {
|
enum class Convexity: char {
|
||||||
UNCHECKED,
|
UNCHECKED,
|
||||||
|
@ -66,7 +66,9 @@ class _Item {
|
||||||
BBCache(): valid(false) {}
|
BBCache(): valid(false) {}
|
||||||
} bb_cache_;
|
} bb_cache_;
|
||||||
|
|
||||||
std::function<void(const _Item&, unsigned)> applyfn_;
|
static const size_t ID_UNSET = size_t(-1);
|
||||||
|
|
||||||
|
size_t id_{ID_UNSET};
|
||||||
bool fixed_{false};
|
bool fixed_{false};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -126,12 +128,12 @@ public:
|
||||||
THolesContainer<RawShape>&& holes):
|
THolesContainer<RawShape>&& holes):
|
||||||
sh_(sl::create<RawShape>(std::move(contour), std::move(holes))) {}
|
sh_(sl::create<RawShape>(std::move(contour), std::move(holes))) {}
|
||||||
|
|
||||||
template<class... Args>
|
// template<class... Args>
|
||||||
_Item(std::function<void(const _Item&, unsigned)> applyfn, Args &&... args):
|
// _Item(std::function<void(const _Item&, unsigned)> applyfn, Args &&... args):
|
||||||
_Item(std::forward<Args>(args)...)
|
// _Item(std::forward<Args>(args)...)
|
||||||
{
|
// {
|
||||||
applyfn_ = std::move(applyfn);
|
// applyfn_ = std::move(applyfn);
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Call the apply callback set in constructor. Within the callback, the
|
// Call the apply callback set in constructor. Within the callback, the
|
||||||
// original caller can apply the stored transformation to the original
|
// original caller can apply the stored transformation to the original
|
||||||
|
@ -140,13 +142,15 @@ public:
|
||||||
// client uses a simplified or processed polygon for nesting)
|
// client uses a simplified or processed polygon for nesting)
|
||||||
// This callback, if present, will be called for each item after the nesting
|
// This callback, if present, will be called for each item after the nesting
|
||||||
// is finished.
|
// is finished.
|
||||||
inline void callApplyFunction(unsigned binidx) const
|
// inline void callApplyFunction(unsigned binidx) const
|
||||||
{
|
// {
|
||||||
if (applyfn_) applyfn_(*this, binidx);
|
// if (applyfn_) applyfn_(*this, binidx);
|
||||||
}
|
// }
|
||||||
|
|
||||||
inline bool isFixed() const noexcept { return fixed_; }
|
inline bool isFixed() const noexcept { return fixed_; }
|
||||||
inline void markAsFixed(bool fixed = true) { fixed_ = fixed; }
|
inline void markAsFixed(bool fixed = true) { fixed_ = fixed; }
|
||||||
|
inline void id(size_t idx) { id_ = idx; }
|
||||||
|
inline long id() const noexcept { return id_; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Convert the polygon to string representation. The format depends
|
* @brief Convert the polygon to string representation. The format depends
|
||||||
|
@ -224,7 +228,7 @@ public:
|
||||||
double ret ;
|
double ret ;
|
||||||
if(area_cache_valid_) ret = area_cache_;
|
if(area_cache_valid_) ret = area_cache_;
|
||||||
else {
|
else {
|
||||||
ret = sl::area(offsettedShape());
|
ret = sl::area(infaltedShape());
|
||||||
area_cache_ = ret;
|
area_cache_ = ret;
|
||||||
area_cache_valid_ = true;
|
area_cache_valid_ = true;
|
||||||
}
|
}
|
||||||
|
@ -296,16 +300,20 @@ public:
|
||||||
rotation(rotation() + rads);
|
rotation(rotation() + rads);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void addOffset(Coord distance) BP2D_NOEXCEPT
|
inline void inflation(Coord distance) BP2D_NOEXCEPT
|
||||||
{
|
{
|
||||||
offset_distance_ = distance;
|
inflation_ = distance;
|
||||||
has_offset_ = true;
|
has_inflation_ = true;
|
||||||
invalidateCache();
|
invalidateCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void removeOffset() BP2D_NOEXCEPT {
|
inline Coord inflation() const BP2D_NOEXCEPT {
|
||||||
has_offset_ = false;
|
return inflation_;
|
||||||
invalidateCache();
|
}
|
||||||
|
|
||||||
|
inline void inflate(Coord distance) BP2D_NOEXCEPT
|
||||||
|
{
|
||||||
|
inflation(inflation() + distance);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Radians rotation() const BP2D_NOEXCEPT
|
inline Radians rotation() const BP2D_NOEXCEPT
|
||||||
|
@ -339,7 +347,7 @@ public:
|
||||||
{
|
{
|
||||||
if(tr_cache_valid_) return tr_cache_;
|
if(tr_cache_valid_) return tr_cache_;
|
||||||
|
|
||||||
RawShape cpy = offsettedShape();
|
RawShape cpy = infaltedShape();
|
||||||
if(has_rotation_) sl::rotate(cpy, rotation_);
|
if(has_rotation_) sl::rotate(cpy, rotation_);
|
||||||
if(has_translation_) sl::translate(cpy, translation_);
|
if(has_translation_) sl::translate(cpy, translation_);
|
||||||
tr_cache_ = cpy; tr_cache_valid_ = true;
|
tr_cache_ = cpy; tr_cache_valid_ = true;
|
||||||
|
@ -360,17 +368,17 @@ public:
|
||||||
|
|
||||||
inline void resetTransformation() BP2D_NOEXCEPT
|
inline void resetTransformation() BP2D_NOEXCEPT
|
||||||
{
|
{
|
||||||
has_translation_ = false; has_rotation_ = false; has_offset_ = false;
|
has_translation_ = false; has_rotation_ = false; has_inflation_ = false;
|
||||||
invalidateCache();
|
invalidateCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Box boundingBox() const {
|
inline Box boundingBox() const {
|
||||||
if(!bb_cache_.valid) {
|
if(!bb_cache_.valid) {
|
||||||
if(!has_rotation_)
|
if(!has_rotation_)
|
||||||
bb_cache_.bb = sl::boundingBox(offsettedShape());
|
bb_cache_.bb = sl::boundingBox(infaltedShape());
|
||||||
else {
|
else {
|
||||||
// TODO make sure this works
|
// TODO make sure this works
|
||||||
auto rotsh = offsettedShape();
|
auto rotsh = infaltedShape();
|
||||||
sl::rotate(rotsh, rotation_);
|
sl::rotate(rotsh, rotation_);
|
||||||
bb_cache_.bb = sl::boundingBox(rotsh);
|
bb_cache_.bb = sl::boundingBox(rotsh);
|
||||||
}
|
}
|
||||||
|
@ -419,14 +427,14 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
inline const RawShape& offsettedShape() const {
|
inline const RawShape& infaltedShape() const {
|
||||||
if(has_offset_ ) {
|
if(has_inflation_ ) {
|
||||||
if(offset_cache_valid_) return offset_cache_;
|
if(inflate_cache_valid_) return inflate_cache_;
|
||||||
|
|
||||||
offset_cache_ = sh_;
|
inflate_cache_ = sh_;
|
||||||
sl::offset(offset_cache_, offset_distance_);
|
sl::offset(inflate_cache_, inflation_);
|
||||||
offset_cache_valid_ = true;
|
inflate_cache_valid_ = true;
|
||||||
return offset_cache_;
|
return inflate_cache_;
|
||||||
}
|
}
|
||||||
return sh_;
|
return sh_;
|
||||||
}
|
}
|
||||||
|
@ -436,7 +444,7 @@ private:
|
||||||
tr_cache_valid_ = false;
|
tr_cache_valid_ = false;
|
||||||
lmb_valid_ = false; rmt_valid_ = false;
|
lmb_valid_ = false; rmt_valid_ = false;
|
||||||
area_cache_valid_ = false;
|
area_cache_valid_ = false;
|
||||||
offset_cache_valid_ = false;
|
inflate_cache_valid_ = false;
|
||||||
bb_cache_.valid = false;
|
bb_cache_.valid = false;
|
||||||
convexity_ = Convexity::UNCHECKED;
|
convexity_ = Convexity::UNCHECKED;
|
||||||
}
|
}
|
||||||
|
@ -758,6 +766,25 @@ public:
|
||||||
void clear() { impl_.clear(); }
|
void clear() { impl_.clear(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using BinIdx = unsigned;
|
||||||
|
template<class S, class Key = size_t> using _NestResult =
|
||||||
|
std::vector<
|
||||||
|
std::tuple<Key, // Identifier of the original shape
|
||||||
|
TPoint<S>, // Translation calculated by nesting
|
||||||
|
Radians, // Rotation calculated by nesting
|
||||||
|
BinIdx> // Logical bin index, first is zero
|
||||||
|
>;
|
||||||
|
|
||||||
|
template<class T> struct Indexed {
|
||||||
|
using ShapeType = T;
|
||||||
|
static T& get(T& obj) { return obj; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class K, class S> struct Indexed<std::pair<K, S>> {
|
||||||
|
using ShapeType = S;
|
||||||
|
static S& get(std::pair<K, S>& obj) { return obj.second; }
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Arranger is the front-end class for the libnest2d library. It takes the
|
* The Arranger is the front-end class for the libnest2d library. It takes the
|
||||||
* input items and outputs the items with the proper transformations to be
|
* input items and outputs the items with the proper transformations to be
|
||||||
|
@ -769,6 +796,7 @@ class Nester {
|
||||||
TSel selector_;
|
TSel selector_;
|
||||||
public:
|
public:
|
||||||
using Item = typename PlacementStrategy::Item;
|
using Item = typename PlacementStrategy::Item;
|
||||||
|
using ShapeType = typename Item::ShapeType;
|
||||||
using ItemRef = std::reference_wrapper<Item>;
|
using ItemRef = std::reference_wrapper<Item>;
|
||||||
using TPlacer = PlacementStrategyLike<PlacementStrategy>;
|
using TPlacer = PlacementStrategyLike<PlacementStrategy>;
|
||||||
using BinType = typename TPlacer::BinType;
|
using BinType = typename TPlacer::BinType;
|
||||||
|
@ -777,6 +805,7 @@ public:
|
||||||
using Coord = TCoord<TPoint<typename Item::ShapeType>>;
|
using Coord = TCoord<TPoint<typename Item::ShapeType>>;
|
||||||
using PackGroup = _PackGroup<typename Item::ShapeType>;
|
using PackGroup = _PackGroup<typename Item::ShapeType>;
|
||||||
using ResultType = PackGroup;
|
using ResultType = PackGroup;
|
||||||
|
template<class K> using NestResult = _NestResult<ShapeType, K>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BinType bin_;
|
BinType bin_;
|
||||||
|
@ -835,10 +864,12 @@ public:
|
||||||
* The number of groups in the pack group is the number of bins opened by
|
* The number of groups in the pack group is the number of bins opened by
|
||||||
* the selection algorithm.
|
* the selection algorithm.
|
||||||
*/
|
*/
|
||||||
template<class TIterator>
|
template<class It, class Key = size_t>
|
||||||
inline PackGroup execute(TIterator from, TIterator to)
|
inline const NestResult<Key> execute(It from, It to,
|
||||||
|
std::function<Key(It)> keyfn = nullptr)
|
||||||
{
|
{
|
||||||
return _execute(from, to);
|
if (!keyfn) keyfn = [to](It it) { return to - it; };
|
||||||
|
return _execute(from, to, keyfn);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a progress indicator function object for the selector.
|
/// Set a progress indicator function object for the selector.
|
||||||
|
@ -858,65 +889,74 @@ public:
|
||||||
return selector_.getResult();
|
return selector_.getResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void preload(const PackGroup& pgrp)
|
|
||||||
{
|
|
||||||
selector_.preload(pgrp);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
template<class TIterator,
|
template<class It> using TVal = remove_cvref_t<typename It::value_type>;
|
||||||
class IT = remove_cvref_t<typename TIterator::value_type>,
|
|
||||||
|
|
||||||
// This function will be used only if the iterators are pointing to
|
template<class It, class Out>
|
||||||
// a type compatible with the libnets2d::_Item template.
|
using ConvertibleOnly =
|
||||||
// This way we can use references to input elements as they will
|
enable_if_t< std::is_convertible<TVal<It>, TPItem>::value, void>;
|
||||||
// have to exist for the lifetime of this call.
|
|
||||||
class T = enable_if_t< std::is_convertible<IT, TPItem>::value, IT>
|
template<class It, class Out>
|
||||||
>
|
using NotConvertibleOnly =
|
||||||
inline const PackGroup& _execute(TIterator from, TIterator to, bool = false)
|
enable_if_t< ! std::is_convertible<TVal<It>, TPItem>::value, void>;
|
||||||
|
|
||||||
|
// This function will be used only if the iterators are pointing to
|
||||||
|
// a type compatible with the libnets2d::_Item template.
|
||||||
|
// This way we can use references to input elements as they will
|
||||||
|
// have to exist for the lifetime of this call.
|
||||||
|
template<class It, class Key>
|
||||||
|
inline ConvertibleOnly<It, const NestResult<Key>> _execute(
|
||||||
|
It from, It to, std::function<Key(It)> keyfn)
|
||||||
{
|
{
|
||||||
__execute(from, to);
|
{
|
||||||
return lastResult();
|
auto it = from; size_t id = 0;
|
||||||
|
while(it != to)
|
||||||
|
if (it->id() == Item::ID_UNSET) (it++)->id(id++);
|
||||||
|
else { id = it->id() + 1; ++it; }
|
||||||
|
}
|
||||||
|
|
||||||
|
NestResult<Key> result(to - from);
|
||||||
|
|
||||||
|
__execute(from, to, keyfn);
|
||||||
|
|
||||||
|
BinIdx binidx = 0;
|
||||||
|
for(auto &itmgrp : lastResult()) {
|
||||||
|
for(const Item& itm : itmgrp)
|
||||||
|
result[itm.id()] =
|
||||||
|
std::make_tuple(keyfn(from + itm.id()), itm.translation(),
|
||||||
|
itm.rotation(), binidx);
|
||||||
|
|
||||||
|
++binidx;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class TIterator,
|
template<class It, class Key = size_t>
|
||||||
class IT = remove_cvref_t<typename TIterator::value_type>,
|
inline NotConvertibleOnly<It, const NestResult<Key>> _execute(
|
||||||
class T = enable_if_t<!std::is_convertible<IT, TPItem>::value, IT>
|
It from, It to, std::function<Key(It)> keyfn)
|
||||||
>
|
|
||||||
inline const PackGroup& _execute(TIterator from, TIterator to, int = false)
|
|
||||||
{
|
{
|
||||||
item_cache_ = {from, to};
|
item_cache_.reserve(to - from);
|
||||||
|
for(auto it = from; it != to; ++it)
|
||||||
|
item_cache_.emplace_back(Indexed<typename It::value_type>::get(*it));
|
||||||
|
|
||||||
__execute(item_cache_.begin(), item_cache_.end());
|
return _execute(item_cache_.begin(), item_cache_.end(), keyfn);
|
||||||
return lastResult();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class TIter> inline void __execute(TIter from, TIter to)
|
template<class It> inline void __execute(It from, It to)
|
||||||
{
|
{
|
||||||
if(min_obj_distance_ > 0) std::for_each(from, to, [this](Item& item) {
|
auto infl = static_cast<Coord>(std::ceil(min_obj_distance_/2.0));
|
||||||
auto offs = min_obj_distance_;
|
if(infl > 0) std::for_each(from, to, [this](Item& item) {
|
||||||
if (item.isFixed()) offs *= 0.99;
|
item.inflate(infl);
|
||||||
|
|
||||||
item.addOffset(static_cast<Coord>(std::ceil(offs/2.0)));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
selector_.template packItems<PlacementStrategy>(
|
selector_.template packItems<PlacementStrategy>(
|
||||||
from, to, bin_, pconfig_);
|
from, to, bin_, pconfig_);
|
||||||
|
|
||||||
if(min_obj_distance_ > 0) std::for_each(from, to, [](Item& item) {
|
if(min_obj_distance_ > 0) std::for_each(from, to, [](Item& item) {
|
||||||
item.removeOffset();
|
item.inflate(-infl);
|
||||||
});
|
});
|
||||||
|
|
||||||
if(!stopfn_ || (stopfn_ && !stopfn_())) {
|
|
||||||
// Ignore results if nesting was stopped.
|
|
||||||
const PackGroup& bins = lastResult();
|
|
||||||
unsigned binidx = 0;
|
|
||||||
for(auto& bin : bins) {
|
|
||||||
for(const Item& itm : bin) itm.callApplyFunction(binidx);
|
|
||||||
++binidx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -513,12 +513,13 @@ BedShapeHint bedShape(const Polyline &bed) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class BinT> // Arrange for arbitrary bin type
|
template<class BinT> // Arrange for arbitrary bin type
|
||||||
PackGroup _arrange(std::vector<Item> & shapes,
|
_NestResult<clppr::Polygon> _arrange(
|
||||||
std::vector<Item> & excludes,
|
std::vector<Item> & shapes,
|
||||||
const BinT & bin,
|
std::vector<Item> & excludes,
|
||||||
coord_t minobjd,
|
const BinT & bin,
|
||||||
std::function<void(unsigned)> prind,
|
coord_t minobjd,
|
||||||
std::function<bool()> stopfn)
|
std::function<void(unsigned)> prind,
|
||||||
|
std::function<bool()> stopfn)
|
||||||
{
|
{
|
||||||
AutoArranger<BinT> arranger{bin, minobjd, prind, stopfn};
|
AutoArranger<BinT> arranger{bin, minobjd, prind, stopfn};
|
||||||
|
|
||||||
|
@ -535,22 +536,13 @@ PackGroup _arrange(std::vector<Item> & shapes,
|
||||||
|
|
||||||
// Try to put the first item to the center, as the arranger
|
// Try to put the first item to the center, as the arranger
|
||||||
// will not do this for us.
|
// will not do this for us.
|
||||||
for (auto it = shapes.begin(); it != shapes.end(); ++it) {
|
for (Item &itm : shapes) {
|
||||||
Item &itm = *it;
|
|
||||||
auto ibb = itm.boundingBox();
|
auto ibb = itm.boundingBox();
|
||||||
auto d = binbb.center() - ibb.center();
|
auto d = binbb.center() - ibb.center();
|
||||||
itm.translate(d);
|
itm.translate(d);
|
||||||
|
|
||||||
if (!arranger.is_colliding(itm)) {
|
if (!arranger.is_colliding(itm)) {
|
||||||
itm.markAsFixed();
|
itm.markAsFixed();
|
||||||
|
|
||||||
// Write the transformation data into the item. The
|
|
||||||
// callback was set on the instantiation of Item and
|
|
||||||
// calls the Arrangeable interface.
|
|
||||||
it->callApplyFunction(0);
|
|
||||||
|
|
||||||
// Remove this item, as it is arranged now
|
|
||||||
it = shapes.erase(it);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -586,9 +578,7 @@ bool arrange(ArrangeablePtrs & arrangables,
|
||||||
coord_t binwidth = 0;
|
coord_t binwidth = 0;
|
||||||
|
|
||||||
auto process_arrangeable =
|
auto process_arrangeable =
|
||||||
[](const Arrangeable * arrangeable,
|
[](const Arrangeable *arrangeable, std::vector<Item> &outp)
|
||||||
std::vector<Item> & outp,
|
|
||||||
std::function<void(const Item &, unsigned)> applyfn)
|
|
||||||
{
|
{
|
||||||
assert(arrangeable);
|
assert(arrangeable);
|
||||||
|
|
||||||
|
@ -605,29 +595,16 @@ bool arrange(ArrangeablePtrs & arrangables,
|
||||||
auto firstp = clpath.Contour.front();
|
auto firstp = clpath.Contour.front();
|
||||||
clpath.Contour.emplace_back(firstp);
|
clpath.Contour.emplace_back(firstp);
|
||||||
|
|
||||||
outp.emplace_back(applyfn, std::move(clpath));
|
outp.emplace_back(std::move(clpath));
|
||||||
outp.back().rotation(rotation);
|
outp.back().rotation(rotation);
|
||||||
outp.back().translation({offs.x(), offs.y()});
|
outp.back().translation({offs.x(), offs.y()});
|
||||||
};
|
};
|
||||||
|
|
||||||
for (Arrangeable *arrangeable : arrangables) {
|
for (Arrangeable *arrangeable : arrangables)
|
||||||
process_arrangeable(
|
process_arrangeable(arrangeable, items);
|
||||||
arrangeable,
|
|
||||||
items,
|
|
||||||
// callback called by arrange to apply the result on the arrangeable
|
|
||||||
[arrangeable, &binwidth, &ret](const Item &itm, unsigned binidx) {
|
|
||||||
ret = !binidx; // Return value false more bed is required
|
|
||||||
clppr::cInt stride = binidx * stride_padding(binwidth);
|
|
||||||
|
|
||||||
clppr::IntPoint offs = itm.translation();
|
|
||||||
arrangeable->apply_arrange_result({unscaled(offs.X + stride),
|
|
||||||
unscaled(offs.Y)},
|
|
||||||
itm.rotation(), binidx);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const Arrangeable * fixed: excludes)
|
for (const Arrangeable * fixed: excludes)
|
||||||
process_arrangeable(fixed, fixeditems, nullptr);
|
process_arrangeable(fixed, fixeditems);
|
||||||
|
|
||||||
// Integer ceiling the min distance from the bed perimeters
|
// Integer ceiling the min distance from the bed perimeters
|
||||||
coord_t md = min_obj_dist - SCALED_EPSILON;
|
coord_t md = min_obj_dist - SCALED_EPSILON;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue