ENH: auto-arranging allows more filaments together
Auto-arranging allows more filaments to be printed on the same plate Only HighTemp and LowTemp filaments are not allowed on the same plate. Jira: https://jira.bambooolab.com/browse/STUDIO-4682 Change-Id: I1bd4966e6aaa55a6dd9dff05f0bd94f2795a62b0 (cherry picked from commit 965040912af0555ca190702e7c7ac92e177a2922)
This commit is contained in:
parent
2bd8a0806b
commit
3d5aa9479c
|
@ -69,13 +69,14 @@ class _Item {
|
||||||
Box bb; bool valid;
|
Box bb; bool valid;
|
||||||
BBCache(): valid(false) {}
|
BBCache(): valid(false) {}
|
||||||
} bb_cache_;
|
} bb_cache_;
|
||||||
|
|
||||||
int binid_{BIN_ID_UNSET}, priority_{0};
|
int binid_{BIN_ID_UNSET}, priority_{0};
|
||||||
bool fixed_{false};
|
bool fixed_{false};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int itemid_{ 0 };
|
int itemid_{ 0 };
|
||||||
std::vector<int> extrude_ids;
|
std::vector<int> extrude_ids;
|
||||||
|
int filament_temp_type = -1; // -1 means unset. otherwise should be {0,1,2}
|
||||||
double height{ 0 };
|
double height{ 0 };
|
||||||
double print_temp{ 0 };
|
double print_temp{ 0 };
|
||||||
double bed_temp{ 0 };
|
double bed_temp{ 0 };
|
||||||
|
@ -140,7 +141,7 @@ public:
|
||||||
inline _Item(TContour<RawShape>&& contour,
|
inline _Item(TContour<RawShape>&& contour,
|
||||||
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))) {}
|
||||||
|
|
||||||
inline bool isFixed() const noexcept { return fixed_; }
|
inline bool isFixed() const noexcept { return fixed_; }
|
||||||
inline void markAsFixedInBin(int binid)
|
inline void markAsFixedInBin(int binid)
|
||||||
{
|
{
|
||||||
|
@ -150,7 +151,7 @@ public:
|
||||||
|
|
||||||
inline void binId(int idx) { binid_ = idx; }
|
inline void binId(int idx) { binid_ = idx; }
|
||||||
inline int binId() const noexcept { return binid_; }
|
inline int binId() const noexcept { return binid_; }
|
||||||
|
|
||||||
inline void priority(int p) { priority_ = p; }
|
inline void priority(int p) { priority_ = p; }
|
||||||
inline int priority() const noexcept { return priority_; }
|
inline int priority() const noexcept { return priority_; }
|
||||||
|
|
||||||
|
@ -303,18 +304,18 @@ public:
|
||||||
{
|
{
|
||||||
rotation(rotation() + rads);
|
rotation(rotation() + rads);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void inflation(Coord distance) BP2D_NOEXCEPT
|
inline void inflation(Coord distance) BP2D_NOEXCEPT
|
||||||
{
|
{
|
||||||
inflation_ = distance;
|
inflation_ = distance;
|
||||||
has_inflation_ = true;
|
has_inflation_ = true;
|
||||||
invalidateCache();
|
invalidateCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Coord inflation() const BP2D_NOEXCEPT {
|
inline Coord inflation() const BP2D_NOEXCEPT {
|
||||||
return inflation_;
|
return inflation_;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void inflate(Coord distance) BP2D_NOEXCEPT
|
inline void inflate(Coord distance) BP2D_NOEXCEPT
|
||||||
{
|
{
|
||||||
inflation(inflation() + distance);
|
inflation(inflation() + distance);
|
||||||
|
@ -780,7 +781,7 @@ template<class PlacementStrategy, class SelectionStrategy >
|
||||||
class _Nester {
|
class _Nester {
|
||||||
using TSel = SelectionStrategyLike<SelectionStrategy>;
|
using TSel = SelectionStrategyLike<SelectionStrategy>;
|
||||||
TSel selector_;
|
TSel selector_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using Item = typename PlacementStrategy::Item;
|
using Item = typename PlacementStrategy::Item;
|
||||||
using ShapeType = typename Item::ShapeType;
|
using ShapeType = typename Item::ShapeType;
|
||||||
|
@ -805,7 +806,7 @@ private:
|
||||||
StopCondition stopfn_;
|
StopCondition stopfn_;
|
||||||
|
|
||||||
template<class It> using TVal = remove_ref_t<typename It::value_type>;
|
template<class It> using TVal = remove_ref_t<typename It::value_type>;
|
||||||
|
|
||||||
template<class It, class Out>
|
template<class It, class Out>
|
||||||
using ItemIteratorOnly =
|
using ItemIteratorOnly =
|
||||||
enable_if_t<std::is_convertible<TVal<It>&, TPItem&>::value, Out>;
|
enable_if_t<std::is_convertible<TVal<It>&, TPItem&>::value, Out>;
|
||||||
|
@ -863,14 +864,14 @@ public:
|
||||||
if(infl > 0) std::for_each(from, to, [infl](Item& item) {
|
if(infl > 0) std::for_each(from, to, [infl](Item& item) {
|
||||||
item.inflate(infl);
|
item.inflate(infl);
|
||||||
});
|
});
|
||||||
|
|
||||||
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, [infl](Item& item) {
|
if(min_obj_distance_ > 0) std::for_each(from, to, [infl](Item& item) {
|
||||||
item.inflate(-infl);
|
item.inflate(-infl);
|
||||||
});
|
});
|
||||||
|
|
||||||
return selector_.getResult().size();
|
return selector_.getResult().size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#include "Arrange.hpp"
|
#include "Arrange.hpp"
|
||||||
|
#include "Print.hpp"
|
||||||
#include "BoundingBox.hpp"
|
#include "BoundingBox.hpp"
|
||||||
|
|
||||||
#include <libnest2d/backends/libslic3r/geometries.hpp>
|
#include <libnest2d/backends/libslic3r/geometries.hpp>
|
||||||
|
@ -260,7 +260,7 @@ Points get_shrink_bedpts(const DynamicPrintConfig* print_cfg, const ArrangeParam
|
||||||
// Slic3r.
|
// Slic3r.
|
||||||
template<class PConf>
|
template<class PConf>
|
||||||
void fill_config(PConf& pcfg, const ArrangeParams ¶ms) {
|
void fill_config(PConf& pcfg, const ArrangeParams ¶ms) {
|
||||||
|
|
||||||
if (params.is_seq_print) {
|
if (params.is_seq_print) {
|
||||||
// Start placing the items from the center of the print bed
|
// Start placing the items from the center of the print bed
|
||||||
pcfg.starting_point = PConf::Alignment::BOTTOM_LEFT;
|
pcfg.starting_point = PConf::Alignment::BOTTOM_LEFT;
|
||||||
|
@ -269,7 +269,7 @@ void fill_config(PConf& pcfg, const ArrangeParams ¶ms) {
|
||||||
// Start placing the items from the center of the print bed
|
// Start placing the items from the center of the print bed
|
||||||
pcfg.starting_point = PConf::Alignment::TOP_RIGHT;
|
pcfg.starting_point = PConf::Alignment::TOP_RIGHT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.do_final_align) {
|
if (params.do_final_align) {
|
||||||
// Align the arranged pile into the center of the bin
|
// Align the arranged pile into the center of the bin
|
||||||
pcfg.alignment = PConf::Alignment::CENTER;
|
pcfg.alignment = PConf::Alignment::CENTER;
|
||||||
|
@ -286,7 +286,7 @@ void fill_config(PConf& pcfg, const ArrangeParams ¶ms) {
|
||||||
// The accuracy of optimization.
|
// The accuracy of optimization.
|
||||||
// Goes from 0.0 to 1.0 and scales performance as well
|
// Goes from 0.0 to 1.0 and scales performance as well
|
||||||
pcfg.accuracy = params.accuracy;
|
pcfg.accuracy = params.accuracy;
|
||||||
|
|
||||||
// Allow parallel execution.
|
// Allow parallel execution.
|
||||||
pcfg.parallel = params.parallel;
|
pcfg.parallel = params.parallel;
|
||||||
|
|
||||||
|
@ -312,7 +312,7 @@ static double fixed_overfit(const std::tuple<double, Box>& result, const Box &bi
|
||||||
Box fullbb = sl::boundingBox(pilebb, binbb);
|
Box fullbb = sl::boundingBox(pilebb, binbb);
|
||||||
auto diff = double(fullbb.area()) - binbb.area();
|
auto diff = double(fullbb.area()) - binbb.area();
|
||||||
if(diff > 0) score += diff;
|
if(diff > 0) score += diff;
|
||||||
|
|
||||||
return score;
|
return score;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -379,7 +379,7 @@ protected:
|
||||||
std::vector<Box> m_excluded_and_extruCali_regions; // excluded and extrusion calib regions
|
std::vector<Box> m_excluded_and_extruCali_regions; // excluded and extrusion calib regions
|
||||||
size_t m_item_count = 0; // Number of all items to be packed
|
size_t m_item_count = 0; // Number of all items to be packed
|
||||||
ArrangeParams params;
|
ArrangeParams params;
|
||||||
|
|
||||||
template<class T> ArithmeticOnly<T, double> norm(T val)
|
template<class T> ArithmeticOnly<T, double> norm(T val)
|
||||||
{
|
{
|
||||||
return double(val) / m_norm;
|
return double(val) / m_norm;
|
||||||
|
@ -417,18 +417,18 @@ protected:
|
||||||
const double bin_area = m_bin_area;
|
const double bin_area = m_bin_area;
|
||||||
const SpatIndex& spatindex = m_rtree;
|
const SpatIndex& spatindex = m_rtree;
|
||||||
const SpatIndex& smalls_spatindex = m_smallsrtree;
|
const SpatIndex& smalls_spatindex = m_smallsrtree;
|
||||||
|
|
||||||
// We will treat big items (compared to the print bed) differently
|
// We will treat big items (compared to the print bed) differently
|
||||||
auto isBig = [bin_area](double a) {
|
auto isBig = [bin_area](double a) {
|
||||||
return a/bin_area > BIG_ITEM_TRESHOLD ;
|
return a/bin_area > BIG_ITEM_TRESHOLD ;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Candidate item bounding box
|
// Candidate item bounding box
|
||||||
auto ibb = item.boundingBox();
|
auto ibb = item.boundingBox();
|
||||||
|
|
||||||
// Calculate the full bounding box of the pile with the candidate item
|
// Calculate the full bounding box of the pile with the candidate item
|
||||||
auto fullbb = sl::boundingBox(m_pilebb, ibb);
|
auto fullbb = sl::boundingBox(m_pilebb, ibb);
|
||||||
|
|
||||||
// The bounding box of the big items (they will accumulate in the center
|
// The bounding box of the big items (they will accumulate in the center
|
||||||
// of the pile
|
// of the pile
|
||||||
Box bigbb;
|
Box bigbb;
|
||||||
|
@ -437,31 +437,31 @@ protected:
|
||||||
auto boostbb = spatindex.bounds();
|
auto boostbb = spatindex.bounds();
|
||||||
boost::geometry::convert(boostbb, bigbb);
|
boost::geometry::convert(boostbb, bigbb);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Will hold the resulting score
|
// Will hold the resulting score
|
||||||
double score = 0;
|
double score = 0;
|
||||||
|
|
||||||
// Density is the pack density: how big is the arranged pile
|
// Density is the pack density: how big is the arranged pile
|
||||||
double density = 0;
|
double density = 0;
|
||||||
|
|
||||||
// Distinction of cases for the arrangement scene
|
// Distinction of cases for the arrangement scene
|
||||||
enum e_cases {
|
enum e_cases {
|
||||||
// This branch is for big items in a mixed (big and small) scene
|
// This branch is for big items in a mixed (big and small) scene
|
||||||
// OR for all items in a small-only scene.
|
// OR for all items in a small-only scene.
|
||||||
BIG_ITEM,
|
BIG_ITEM,
|
||||||
|
|
||||||
// This branch is for the last big item in a mixed scene
|
// This branch is for the last big item in a mixed scene
|
||||||
LAST_BIG_ITEM,
|
LAST_BIG_ITEM,
|
||||||
|
|
||||||
// For small items in a mixed scene.
|
// For small items in a mixed scene.
|
||||||
SMALL_ITEM
|
SMALL_ITEM
|
||||||
} compute_case;
|
} compute_case;
|
||||||
|
|
||||||
bool bigitems = isBig(item.area()) || spatindex.empty();
|
bool bigitems = isBig(item.area()) || spatindex.empty();
|
||||||
if(!params.is_seq_print && bigitems && !m_remaining.empty()) compute_case = BIG_ITEM; // do not use so complicated logic for sequential printing
|
if(!params.is_seq_print && bigitems && !m_remaining.empty()) compute_case = BIG_ITEM; // do not use so complicated logic for sequential printing
|
||||||
else if (bigitems && m_remaining.empty()) compute_case = LAST_BIG_ITEM;
|
else if (bigitems && m_remaining.empty()) compute_case = LAST_BIG_ITEM;
|
||||||
else compute_case = SMALL_ITEM;
|
else compute_case = SMALL_ITEM;
|
||||||
|
|
||||||
switch (compute_case) {
|
switch (compute_case) {
|
||||||
case BIG_ITEM: {
|
case BIG_ITEM: {
|
||||||
const Point& minc = ibb.minCorner(); // bottom left corner
|
const Point& minc = ibb.minCorner(); // bottom left corner
|
||||||
|
@ -566,7 +566,7 @@ protected:
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -603,9 +603,11 @@ protected:
|
||||||
for (int i = 0; i < m_items.size(); i++) {
|
for (int i = 0; i < m_items.size(); i++) {
|
||||||
Item& p = m_items[i];
|
Item& p = m_items[i];
|
||||||
if (p.is_virt_object) continue;
|
if (p.is_virt_object) continue;
|
||||||
score += lambda3 * (item.bed_temp - p.vitrify_temp > VITRIFY_TEMP_DIFF_THRSH);
|
//score += lambda3 * (item.bed_temp - p.vitrify_temp > VITRIFY_TEMP_DIFF_THRSH);
|
||||||
|
if (!Print::is_filaments_compatible({item.filament_temp_type,p.filament_temp_type}))
|
||||||
|
score += lambda3;
|
||||||
}
|
}
|
||||||
score += lambda3 * (item.bed_temp - item.vitrify_temp > VITRIFY_TEMP_DIFF_THRSH);
|
//score += lambda3 * (item.bed_temp - item.vitrify_temp > VITRIFY_TEMP_DIFF_THRSH);
|
||||||
score += lambda4 * hasRowHeightConflict + lambda4 * hasLidHeightConflict;
|
score += lambda4 * hasRowHeightConflict + lambda4 * hasLidHeightConflict;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -625,7 +627,9 @@ protected:
|
||||||
// 高度接近的件尽量摆到一起
|
// 高度接近的件尽量摆到一起
|
||||||
score += (1- std::abs(item.height - p.height) / params.printable_height)
|
score += (1- std::abs(item.height - p.height) / params.printable_height)
|
||||||
* norm(pl::distance(ibb.center(), p.boundingBox().center()));
|
* norm(pl::distance(ibb.center(), p.boundingBox().center()));
|
||||||
score += LARGE_COST_TO_REJECT * (item.bed_temp - p.bed_temp != 0);
|
//score += LARGE_COST_TO_REJECT * (item.bed_temp - p.bed_temp != 0);
|
||||||
|
if (!Print::is_filaments_compatible({ item.filament_temp_type,p.filament_temp_type }))
|
||||||
|
score += LARGE_COST_TO_REJECT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -656,9 +660,9 @@ protected:
|
||||||
|
|
||||||
return std::make_tuple(score, fullbb);
|
return std::make_tuple(score, fullbb);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::function<double(const Item&, const ItemGroup&)> get_objfn();
|
std::function<double(const Item&, const ItemGroup&)> get_objfn();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AutoArranger(const TBin & bin,
|
AutoArranger(const TBin & bin,
|
||||||
const ArrangeParams ¶ms,
|
const ArrangeParams ¶ms,
|
||||||
|
@ -708,7 +712,7 @@ public:
|
||||||
|
|
||||||
m_rtree.clear();
|
m_rtree.clear();
|
||||||
m_smallsrtree.clear();
|
m_smallsrtree.clear();
|
||||||
|
|
||||||
// We will treat big items (compared to the print bed) differently
|
// We will treat big items (compared to the print bed) differently
|
||||||
auto isBig = [this](double a) {
|
auto isBig = [this](double a) {
|
||||||
return a / m_bin_area > BIG_ITEM_TRESHOLD ;
|
return a / m_bin_area > BIG_ITEM_TRESHOLD ;
|
||||||
|
@ -721,7 +725,7 @@ public:
|
||||||
m_smallsrtree.insert({itm.boundingBox(), idx});
|
m_smallsrtree.insert({itm.boundingBox(), idx});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
m_pconf.object_function = get_objfn();
|
m_pconf.object_function = get_objfn();
|
||||||
|
|
||||||
// preload fixed items (and excluded regions) on plate
|
// preload fixed items (and excluded regions) on plate
|
||||||
|
@ -746,7 +750,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
auto on_packed = params.on_packed;
|
auto on_packed = params.on_packed;
|
||||||
|
|
||||||
if (progressind || on_packed)
|
if (progressind || on_packed)
|
||||||
m_pck.progressIndicator(
|
m_pck.progressIndicator(
|
||||||
[this, progressind, on_packed](unsigned num_finished) {
|
[this, progressind, on_packed](unsigned num_finished) {
|
||||||
|
@ -760,7 +764,8 @@ public:
|
||||||
if (on_packed)
|
if (on_packed)
|
||||||
on_packed(ap);
|
on_packed(ap);
|
||||||
BOOST_LOG_TRIVIAL(debug) << "arrange " + last_packed.name + " succeed!"
|
BOOST_LOG_TRIVIAL(debug) << "arrange " + last_packed.name + " succeed!"
|
||||||
<< ", plate id=" << ap.bed_idx << ", pos=" << last_packed.translation();
|
<< ", plate id=" << ap.bed_idx << ", pos=" << last_packed.translation()
|
||||||
|
<< ", temp_type=" << last_packed.filament_temp_type;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -783,21 +788,21 @@ public:
|
||||||
(i1.extrude_ids != i2.extrude_ids ? (i1.extrude_ids.front() < i2.extrude_ids.front()) : (i1.area() > i2.area()));
|
(i1.extrude_ids != i2.extrude_ids ? (i1.extrude_ids.front() < i2.extrude_ids.front()) : (i1.area() > i2.area()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
m_pck.configure(m_pconf);
|
m_pck.configure(m_pconf);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class It> inline void operator()(It from, It to) {
|
template<class It> inline void operator()(It from, It to) {
|
||||||
m_rtree.clear();
|
m_rtree.clear();
|
||||||
m_item_count += size_t(to - from);
|
m_item_count += size_t(to - from);
|
||||||
m_pck.execute(from, to);
|
m_pck.execute(from, to);
|
||||||
m_item_count = 0;
|
m_item_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
PConfig& config() { return m_pconf; }
|
PConfig& config() { return m_pconf; }
|
||||||
const PConfig& config() const { return m_pconf; }
|
const PConfig& config() const { return m_pconf; }
|
||||||
|
|
||||||
inline void preload(std::vector<Item>& fixeditems) {
|
inline void preload(std::vector<Item>& fixeditems) {
|
||||||
for(unsigned idx = 0; idx < fixeditems.size(); ++idx) {
|
for(unsigned idx = 0; idx < fixeditems.size(); ++idx) {
|
||||||
Item& itm = fixeditems[idx];
|
Item& itm = fixeditems[idx];
|
||||||
itm.markAsFixedInBin(itm.binId());
|
itm.markAsFixedInBin(itm.binId());
|
||||||
|
@ -813,7 +818,7 @@ template<> std::function<double(const Item&, const ItemGroup&)> AutoArranger<Box
|
||||||
|
|
||||||
return [this, origin_pack](const Item &itm, const ItemGroup&) {
|
return [this, origin_pack](const Item &itm, const ItemGroup&) {
|
||||||
auto result = objfunc(itm, origin_pack);
|
auto result = objfunc(itm, origin_pack);
|
||||||
|
|
||||||
double score = std::get<0>(result);
|
double score = std::get<0>(result);
|
||||||
auto& fullbb = std::get<1>(result);
|
auto& fullbb = std::get<1>(result);
|
||||||
|
|
||||||
|
@ -840,15 +845,15 @@ template<> std::function<double(const Item&, const ItemGroup&)> AutoArranger<Cir
|
||||||
auto bb = sl::boundingBox(m_bin);
|
auto bb = sl::boundingBox(m_bin);
|
||||||
auto origin_pack = m_pconf.starting_point == PConfig::Alignment::CENTER ? bb.center() : bb.minCorner();
|
auto origin_pack = m_pconf.starting_point == PConfig::Alignment::CENTER ? bb.center() : bb.minCorner();
|
||||||
return [this, origin_pack](const Item &item, const ItemGroup&) {
|
return [this, origin_pack](const Item &item, const ItemGroup&) {
|
||||||
|
|
||||||
auto result = objfunc(item, origin_pack);
|
auto result = objfunc(item, origin_pack);
|
||||||
|
|
||||||
double score = std::get<0>(result);
|
double score = std::get<0>(result);
|
||||||
|
|
||||||
auto isBig = [this](const Item& itm) {
|
auto isBig = [this](const Item& itm) {
|
||||||
return itm.area() / m_bin_area > BIG_ITEM_TRESHOLD ;
|
return itm.area() / m_bin_area > BIG_ITEM_TRESHOLD ;
|
||||||
};
|
};
|
||||||
|
|
||||||
if(isBig(item)) {
|
if(isBig(item)) {
|
||||||
auto mp = m_merged_pile;
|
auto mp = m_merged_pile;
|
||||||
mp.push_back(item.transformedShape());
|
mp.push_back(item.transformedShape());
|
||||||
|
@ -857,7 +862,7 @@ template<> std::function<double(const Item&, const ItemGroup&)> AutoArranger<Cir
|
||||||
if(miss < 0) miss = 0;
|
if(miss < 0) miss = 0;
|
||||||
score += miss*miss;
|
score += miss*miss;
|
||||||
}
|
}
|
||||||
|
|
||||||
return score;
|
return score;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -873,7 +878,7 @@ std::function<double(const Item &, const ItemGroup&)> AutoArranger<ExPolygon>::g
|
||||||
auto result = objfunc(itm, origin_pack);
|
auto result = objfunc(itm, origin_pack);
|
||||||
|
|
||||||
double score = std::get<0>(result);
|
double score = std::get<0>(result);
|
||||||
|
|
||||||
auto mp = m_merged_pile;
|
auto mp = m_merged_pile;
|
||||||
mp.emplace_back(itm.transformedShape());
|
mp.emplace_back(itm.transformedShape());
|
||||||
auto chull = sl::convexHull(mp);
|
auto chull = sl::convexHull(mp);
|
||||||
|
@ -930,14 +935,14 @@ void _arrange(
|
||||||
// Integer ceiling the min distance from the bed perimeters
|
// Integer ceiling the min distance from the bed perimeters
|
||||||
coord_t md = params.min_obj_distance;
|
coord_t md = params.min_obj_distance;
|
||||||
md = md / 2;
|
md = md / 2;
|
||||||
|
|
||||||
auto corrected_bin = bin;
|
auto corrected_bin = bin;
|
||||||
//sl::offset(corrected_bin, md);
|
//sl::offset(corrected_bin, md);
|
||||||
ArrangeParams mod_params = params;
|
ArrangeParams mod_params = params;
|
||||||
mod_params.min_obj_distance = 0; // items are already inflated
|
mod_params.min_obj_distance = 0; // items are already inflated
|
||||||
|
|
||||||
AutoArranger<BinT> arranger{corrected_bin, mod_params, progressfn, stopfn};
|
AutoArranger<BinT> arranger{corrected_bin, mod_params, progressfn, stopfn};
|
||||||
|
|
||||||
remove_large_items(excludes, corrected_bin);
|
remove_large_items(excludes, corrected_bin);
|
||||||
|
|
||||||
// If there is something on the plate
|
// If there is something on the plate
|
||||||
|
@ -947,7 +952,7 @@ void _arrange(
|
||||||
inp.reserve(shapes.size() + excludes.size());
|
inp.reserve(shapes.size() + excludes.size());
|
||||||
for (auto &itm : shapes ) inp.emplace_back(itm);
|
for (auto &itm : shapes ) inp.emplace_back(itm);
|
||||||
for (auto &itm : excludes) inp.emplace_back(itm);
|
for (auto &itm : excludes) inp.emplace_back(itm);
|
||||||
|
|
||||||
// Use the minimum bounding box rotation as a starting point.
|
// Use the minimum bounding box rotation as a starting point.
|
||||||
// TODO: This only works for convex hull. If we ever switch to concave
|
// TODO: This only works for convex hull. If we ever switch to concave
|
||||||
// polygon nesting, a convex hull needs to be calculated.
|
// polygon nesting, a convex hull needs to be calculated.
|
||||||
|
@ -987,16 +992,16 @@ inline double distance_to(const Point& p1, const Point& p2)
|
||||||
static CircleBed to_circle(const Point ¢er, const Points& points) {
|
static CircleBed to_circle(const Point ¢er, const Points& points) {
|
||||||
std::vector<double> vertex_distances;
|
std::vector<double> vertex_distances;
|
||||||
double avg_dist = 0;
|
double avg_dist = 0;
|
||||||
|
|
||||||
for (auto pt : points)
|
for (auto pt : points)
|
||||||
{
|
{
|
||||||
double distance = distance_to(center, pt);
|
double distance = distance_to(center, pt);
|
||||||
vertex_distances.push_back(distance);
|
vertex_distances.push_back(distance);
|
||||||
avg_dist += distance;
|
avg_dist += distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
avg_dist /= vertex_distances.size();
|
avg_dist /= vertex_distances.size();
|
||||||
|
|
||||||
CircleBed ret(center, avg_dist);
|
CircleBed ret(center, avg_dist);
|
||||||
for(auto el : vertex_distances)
|
for(auto el : vertex_distances)
|
||||||
{
|
{
|
||||||
|
@ -1005,7 +1010,7 @@ static CircleBed to_circle(const Point ¢er, const Points& points) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1039,6 +1044,7 @@ static void process_arrangeable(const ArrangePolygon &arrpoly,
|
||||||
item.print_temp = arrpoly.print_temp;
|
item.print_temp = arrpoly.print_temp;
|
||||||
item.vitrify_temp = arrpoly.vitrify_temp;
|
item.vitrify_temp = arrpoly.vitrify_temp;
|
||||||
item.inflation(arrpoly.inflation);
|
item.inflation(arrpoly.inflation);
|
||||||
|
item.filament_temp_type = arrpoly.filament_temp_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Fn> auto call_with_bed(const Points &bed, Fn &&fn)
|
template<class Fn> auto call_with_bed(const Points &bed, Fn &&fn)
|
||||||
|
@ -1079,20 +1085,20 @@ void arrange(ArrangePolygons & arrangables,
|
||||||
const ArrangeParams & params)
|
const ArrangeParams & params)
|
||||||
{
|
{
|
||||||
namespace clppr = Slic3r::ClipperLib;
|
namespace clppr = Slic3r::ClipperLib;
|
||||||
|
|
||||||
std::vector<Item> items, fixeditems;
|
std::vector<Item> items, fixeditems;
|
||||||
items.reserve(arrangables.size());
|
items.reserve(arrangables.size());
|
||||||
|
|
||||||
for (ArrangePolygon &arrangeable : arrangables)
|
for (ArrangePolygon &arrangeable : arrangables)
|
||||||
process_arrangeable(arrangeable, items);
|
process_arrangeable(arrangeable, items);
|
||||||
|
|
||||||
for (const ArrangePolygon &fixed: excludes)
|
for (const ArrangePolygon &fixed: excludes)
|
||||||
process_arrangeable(fixed, fixeditems);
|
process_arrangeable(fixed, fixeditems);
|
||||||
|
|
||||||
for (Item &itm : fixeditems) itm.inflate(scaled(-2. * EPSILON));
|
for (Item &itm : fixeditems) itm.inflate(scaled(-2. * EPSILON));
|
||||||
|
|
||||||
_arrange(items, fixeditems, to_nestbin(bed), params, params.progressind, params.stopcondition);
|
_arrange(items, fixeditems, to_nestbin(bed), params, params.progressind, params.stopcondition);
|
||||||
|
|
||||||
for(size_t i = 0; i < items.size(); ++i) {
|
for(size_t i = 0; i < items.size(); ++i) {
|
||||||
Point tr = items[i].translation();
|
Point tr = items[i].translation();
|
||||||
arrangables[i].translation = {coord_t(tr.x()), coord_t(tr.y())};
|
arrangables[i].translation = {coord_t(tr.x()), coord_t(tr.y())};
|
||||||
|
|
|
@ -40,12 +40,12 @@ static const constexpr int UNARRANGED = -1;
|
||||||
/// be modified during arrangement. Instead, the translation and rotation fields
|
/// be modified during arrangement. Instead, the translation and rotation fields
|
||||||
/// will mark the needed transformation for the polygon to be in the arranged
|
/// will mark the needed transformation for the polygon to be in the arranged
|
||||||
/// position. These can also be set to an initial offset and rotation.
|
/// position. These can also be set to an initial offset and rotation.
|
||||||
///
|
///
|
||||||
/// The bed_idx field will indicate the logical bed into which the
|
/// The bed_idx field will indicate the logical bed into which the
|
||||||
/// polygon belongs: UNARRANGED means no place for the polygon
|
/// polygon belongs: UNARRANGED means no place for the polygon
|
||||||
/// (also the initial state before arrange), 0..N means the index of the bed.
|
/// (also the initial state before arrange), 0..N means the index of the bed.
|
||||||
/// Zero is the physical bed, larger than zero means a virtual bed.
|
/// Zero is the physical bed, larger than zero means a virtual bed.
|
||||||
struct ArrangePolygon {
|
struct ArrangePolygon {
|
||||||
ExPolygon poly; /// The 2D silhouette to be arranged
|
ExPolygon poly; /// The 2D silhouette to be arranged
|
||||||
Vec2crd translation{0, 0}; /// The translation of the poly
|
Vec2crd translation{0, 0}; /// The translation of the poly
|
||||||
double rotation{0.0}; /// The rotation of the poly in radians
|
double rotation{0.0}; /// The rotation of the poly in radians
|
||||||
|
@ -62,6 +62,7 @@ struct ArrangePolygon {
|
||||||
int row{0};
|
int row{0};
|
||||||
int col{0};
|
int col{0};
|
||||||
std::vector<int> extrude_ids{}; /// extruder_id for least extruder switch
|
std::vector<int> extrude_ids{}; /// extruder_id for least extruder switch
|
||||||
|
int filament_temp_type{ -1 };
|
||||||
int bed_temp{0}; ///bed temperature for different material judge
|
int bed_temp{0}; ///bed temperature for different material judge
|
||||||
int print_temp{0}; ///print temperature for different material judge
|
int print_temp{0}; ///print temperature for different material judge
|
||||||
int first_bed_temp{ 0 }; ///first layer bed temperature for different material judge
|
int first_bed_temp{ 0 }; ///first layer bed temperature for different material judge
|
||||||
|
@ -69,20 +70,20 @@ struct ArrangePolygon {
|
||||||
int vitrify_temp{ 0 }; // max bed temperature for material compatibility, which is usually the filament vitrification temp
|
int vitrify_temp{ 0 }; // max bed temperature for material compatibility, which is usually the filament vitrification temp
|
||||||
int itemid{ 0 }; // item id in the vector, used for accessing all possible params like extrude_id
|
int itemid{ 0 }; // item id in the vector, used for accessing all possible params like extrude_id
|
||||||
int is_applied{ 0 }; // transform has been applied
|
int is_applied{ 0 }; // transform has been applied
|
||||||
double height{ 0 }; // item height
|
double height{ 0 }; // item height
|
||||||
double brim_width{ 0 }; // brim width
|
double brim_width{ 0 }; // brim width
|
||||||
std::string name;
|
std::string name;
|
||||||
|
|
||||||
// If empty, any rotation is allowed (currently unsupported)
|
// If empty, any rotation is allowed (currently unsupported)
|
||||||
// If only a zero is there, no rotation is allowed
|
// If only a zero is there, no rotation is allowed
|
||||||
std::vector<double> allowed_rotations = {0.};
|
std::vector<double> allowed_rotations = {0.};
|
||||||
|
|
||||||
/// Optional setter function which can store arbitrary data in its closure
|
/// Optional setter function which can store arbitrary data in its closure
|
||||||
std::function<void(const ArrangePolygon&)> setter = nullptr;
|
std::function<void(const ArrangePolygon&)> setter = nullptr;
|
||||||
|
|
||||||
/// Helper function to call the setter with the arrange data arguments
|
/// Helper function to call the setter with the arrange data arguments
|
||||||
void apply() {
|
void apply() {
|
||||||
if (setter && !is_applied) {
|
if (setter && !is_applied) {
|
||||||
setter(*this);
|
setter(*this);
|
||||||
is_applied = 1;
|
is_applied = 1;
|
||||||
}
|
}
|
||||||
|
@ -104,15 +105,15 @@ struct ArrangePolygon {
|
||||||
using ArrangePolygons = std::vector<ArrangePolygon>;
|
using ArrangePolygons = std::vector<ArrangePolygon>;
|
||||||
|
|
||||||
struct ArrangeParams {
|
struct ArrangeParams {
|
||||||
|
|
||||||
/// The minimum distance which is allowed for any
|
/// The minimum distance which is allowed for any
|
||||||
/// pair of items on the print bed in any direction.
|
/// pair of items on the print bed in any direction.
|
||||||
coord_t min_obj_distance = 0;
|
coord_t min_obj_distance = 0;
|
||||||
|
|
||||||
/// The accuracy of optimization.
|
/// The accuracy of optimization.
|
||||||
/// Goes from 0.0 to 1.0 and scales performance as well
|
/// Goes from 0.0 to 1.0 and scales performance as well
|
||||||
float accuracy = 1.f;
|
float accuracy = 1.f;
|
||||||
|
|
||||||
/// Allow parallel execution.
|
/// Allow parallel execution.
|
||||||
bool parallel = true;
|
bool parallel = true;
|
||||||
|
|
||||||
|
@ -136,18 +137,18 @@ struct ArrangeParams {
|
||||||
|
|
||||||
ArrangePolygons excluded_regions; // regions cant't be used
|
ArrangePolygons excluded_regions; // regions cant't be used
|
||||||
ArrangePolygons nonprefered_regions; // regions can be used but not prefered
|
ArrangePolygons nonprefered_regions; // regions can be used but not prefered
|
||||||
|
|
||||||
/// Progress indicator callback called when an object gets packed.
|
/// Progress indicator callback called when an object gets packed.
|
||||||
/// The unsigned argument is the number of items remaining to pack.
|
/// The unsigned argument is the number of items remaining to pack.
|
||||||
std::function<void(unsigned, std::string)> progressind = [](unsigned st, std::string str = "") {
|
std::function<void(unsigned, std::string)> progressind = [](unsigned st, std::string str = "") {
|
||||||
std::cout << "st=" << st << ", " << str << std::endl;
|
std::cout << "st=" << st << ", " << str << std::endl;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::function<void(const ArrangePolygon &)> on_packed;
|
std::function<void(const ArrangePolygon &)> on_packed;
|
||||||
|
|
||||||
/// A predicate returning true if abort is needed.
|
/// A predicate returning true if abort is needed.
|
||||||
std::function<bool(void)> stopcondition;
|
std::function<bool(void)> stopcondition;
|
||||||
|
|
||||||
ArrangeParams() = default;
|
ArrangeParams() = default;
|
||||||
explicit ArrangeParams(coord_t md) : min_obj_distance(md) {}
|
explicit ArrangeParams(coord_t md) : min_obj_distance(md) {}
|
||||||
// to json format
|
// to json format
|
||||||
|
@ -186,11 +187,11 @@ Points get_shrink_bedpts(const DynamicPrintConfig* print_cfg, const ArrangeParam
|
||||||
/**
|
/**
|
||||||
* \brief Arranges the input polygons.
|
* \brief Arranges the input polygons.
|
||||||
*
|
*
|
||||||
* WARNING: Currently, only convex polygons are supported by the libnest2d
|
* WARNING: Currently, only convex polygons are supported by the libnest2d
|
||||||
* library which is used to do the arrangement. This might change in the future
|
* library which is used to do the arrangement. This might change in the future
|
||||||
* this is why the interface contains a general polygon capable to have holes.
|
* this is why the interface contains a general polygon capable to have holes.
|
||||||
*
|
*
|
||||||
* \param items Input vector of ArrangePolygons. The transformation, rotation
|
* \param items Input vector of ArrangePolygons. The transformation, rotation
|
||||||
* and bin_idx fields will be changed after the call finished and can be used
|
* and bin_idx fields will be changed after the call finished and can be used
|
||||||
* to apply the result on the input polygon.
|
* to apply the result on the input polygon.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <libslic3r/Model.hpp>
|
#include <libslic3r/Model.hpp>
|
||||||
#include <libslic3r/Geometry/ConvexHull.hpp>
|
#include <libslic3r/Geometry/ConvexHull.hpp>
|
||||||
|
#include <libslic3r/Print.hpp>
|
||||||
#include "MTUtils.hpp"
|
#include "MTUtils.hpp"
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
@ -10,7 +11,7 @@ arrangement::ArrangePolygons get_arrange_polys(const Model &model, ModelInstance
|
||||||
{
|
{
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
for (auto obj : model.objects) count += obj->instances.size();
|
for (auto obj : model.objects) count += obj->instances.size();
|
||||||
|
|
||||||
ArrangePolygons input;
|
ArrangePolygons input;
|
||||||
input.reserve(count);
|
input.reserve(count);
|
||||||
instances.clear(); instances.reserve(count);
|
instances.clear(); instances.reserve(count);
|
||||||
|
@ -21,21 +22,21 @@ arrangement::ArrangePolygons get_arrange_polys(const Model &model, ModelInstance
|
||||||
input.emplace_back(ap);
|
input.emplace_back(ap);
|
||||||
instances.emplace_back(minst);
|
instances.emplace_back(minst);
|
||||||
}
|
}
|
||||||
|
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool apply_arrange_polys(ArrangePolygons &input, ModelInstancePtrs &instances, VirtualBedFn vfn)
|
bool apply_arrange_polys(ArrangePolygons &input, ModelInstancePtrs &instances, VirtualBedFn vfn)
|
||||||
{
|
{
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
|
|
||||||
for(size_t i = 0; i < input.size(); ++i) {
|
for(size_t i = 0; i < input.size(); ++i) {
|
||||||
if (input[i].bed_idx != 0) { ret = false; if (vfn) vfn(input[i]); }
|
if (input[i].bed_idx != 0) { ret = false; if (vfn) vfn(input[i]); }
|
||||||
if (input[i].bed_idx >= 0)
|
if (input[i].bed_idx >= 0)
|
||||||
instances[i]->apply_arrange_result(input[i].translation.cast<double>(),
|
instances[i]->apply_arrange_result(input[i].translation.cast<double>(),
|
||||||
input[i].rotation);
|
input[i].rotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,7 +53,7 @@ Slic3r::arrangement::ArrangePolygon get_arrange_poly(const Model &model)
|
||||||
const Points &pts = obj_ap.poly.contour.points;
|
const Points &pts = obj_ap.poly.contour.points;
|
||||||
std::copy(pts.begin(), pts.end(), std::back_inserter(apts));
|
std::copy(pts.begin(), pts.end(), std::back_inserter(apts));
|
||||||
}
|
}
|
||||||
|
|
||||||
apts = std::move(Geometry::convex_hull(apts).points);
|
apts = std::move(Geometry::convex_hull(apts).points);
|
||||||
return ap;
|
return ap;
|
||||||
}
|
}
|
||||||
|
@ -118,7 +119,7 @@ arrangement::ArrangePolygon get_arrange_poly(ModelInstance* inst, const Slic3r::
|
||||||
ArrangePolygon get_instance_arrange_poly(ModelInstance* instance, const Slic3r::DynamicPrintConfig& config)
|
ArrangePolygon get_instance_arrange_poly(ModelInstance* instance, const Slic3r::DynamicPrintConfig& config)
|
||||||
{
|
{
|
||||||
ArrangePolygon ap = get_arrange_poly(PtrWrapper{ instance }, config);
|
ArrangePolygon ap = get_arrange_poly(PtrWrapper{ instance }, config);
|
||||||
|
|
||||||
//BBS: add temperature information
|
//BBS: add temperature information
|
||||||
if (config.has("curr_bed_type")) {
|
if (config.has("curr_bed_type")) {
|
||||||
ap.bed_temp = 0;
|
ap.bed_temp = 0;
|
||||||
|
@ -138,11 +139,23 @@ ArrangePolygon get_instance_arrange_poly(ModelInstance* instance, const Slic3r::
|
||||||
ap.print_temp = config.opt_int("nozzle_temperature", ap.extrude_ids.front() - 1);
|
ap.print_temp = config.opt_int("nozzle_temperature", ap.extrude_ids.front() - 1);
|
||||||
if (config.has("nozzle_temperature_initial_layer")) //get the nozzle_temperature_initial_layer
|
if (config.has("nozzle_temperature_initial_layer")) //get the nozzle_temperature_initial_layer
|
||||||
ap.first_print_temp = config.opt_int("nozzle_temperature_initial_layer", ap.extrude_ids.front() - 1);
|
ap.first_print_temp = config.opt_int("nozzle_temperature_initial_layer", ap.extrude_ids.front() - 1);
|
||||||
|
|
||||||
if (config.has("temperature_vitrification")) {
|
if (config.has("temperature_vitrification")) {
|
||||||
ap.vitrify_temp = config.opt_int("temperature_vitrification", ap.extrude_ids.front() - 1);
|
ap.vitrify_temp = config.opt_int("temperature_vitrification", ap.extrude_ids.front() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get filament temp types
|
||||||
|
auto* filament_types_opt = dynamic_cast<const ConfigOptionStrings*>(config.option("filament_type"));
|
||||||
|
if (filament_types_opt) {
|
||||||
|
std::set<int> filament_temp_types;
|
||||||
|
for (auto i : ap.extrude_ids) {
|
||||||
|
std::string type_str = filament_types_opt->get_at(i-1);
|
||||||
|
int temp_type = Print::get_filament_temp_type(type_str);
|
||||||
|
filament_temp_types.insert(temp_type);
|
||||||
|
}
|
||||||
|
ap.filament_temp_type = Print::get_compatible_filament_type(filament_temp_types);
|
||||||
|
}
|
||||||
|
|
||||||
// get brim width
|
// get brim width
|
||||||
auto obj = instance->get_object();
|
auto obj = instance->get_object();
|
||||||
|
|
||||||
|
@ -162,7 +175,7 @@ ArrangePolygon get_instance_arrange_poly(ModelInstance* instance, const Slic3r::
|
||||||
ap.brim_width = 24.0; // 2*MAX_BRANCH_RADIUS_FIRST_LAYER
|
ap.brim_width = 24.0; // 2*MAX_BRANCH_RADIUS_FIRST_LAYER
|
||||||
ap.has_tree_support = true;
|
ap.has_tree_support = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ap.height = obj->bounding_box().size().z();
|
ap.height = obj->bounding_box().size().z();
|
||||||
ap.name = obj->name;
|
ap.name = obj->name;
|
||||||
return ap;
|
return ap;
|
||||||
|
|
|
@ -916,6 +916,44 @@ bool Print::check_multi_filaments_compatibility(const std::vector<std::string>&
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Print::is_filaments_compatible(const std::vector<int>& filament_types)
|
||||||
|
{
|
||||||
|
bool has_high_temperature_filament = false;
|
||||||
|
bool has_low_temperature_filament = false;
|
||||||
|
|
||||||
|
for (const auto& type : filament_types) {
|
||||||
|
if (type == FilamentTempType::HighTemp)
|
||||||
|
has_high_temperature_filament = true;
|
||||||
|
else if (type == FilamentTempType::LowTemp)
|
||||||
|
has_low_temperature_filament = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_high_temperature_filament && has_low_temperature_filament)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
int Print::get_compatible_filament_type(const std::set<int>& filament_types)
|
||||||
|
{
|
||||||
|
bool has_high_temperature_filament = false;
|
||||||
|
bool has_low_temperature_filament = false;
|
||||||
|
|
||||||
|
for (const auto& type : filament_types) {
|
||||||
|
if (type == FilamentTempType::HighTemp)
|
||||||
|
has_high_temperature_filament = true;
|
||||||
|
else if (type == FilamentTempType::LowTemp)
|
||||||
|
has_low_temperature_filament = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_high_temperature_filament && has_low_temperature_filament)
|
||||||
|
return HighLowCompatible;
|
||||||
|
else if (has_high_temperature_filament)
|
||||||
|
return HighTemp;
|
||||||
|
else if (has_low_temperature_filament)
|
||||||
|
return LowTemp;
|
||||||
|
return HighLowCompatible;
|
||||||
|
}
|
||||||
|
|
||||||
//BBS: this function is used to check whether multi filament can be printed
|
//BBS: this function is used to check whether multi filament can be printed
|
||||||
StringObjectException Print::check_multi_filament_valid(const Print& print)
|
StringObjectException Print::check_multi_filament_valid(const Print& print)
|
||||||
{
|
{
|
||||||
|
|
|
@ -830,6 +830,15 @@ public:
|
||||||
static FilamentTempType get_filament_temp_type(const std::string& filament_type);
|
static FilamentTempType get_filament_temp_type(const std::string& filament_type);
|
||||||
static int get_hrc_by_nozzle_type(const NozzleType& type);
|
static int get_hrc_by_nozzle_type(const NozzleType& type);
|
||||||
static bool check_multi_filaments_compatibility(const std::vector<std::string>& filament_types);
|
static bool check_multi_filaments_compatibility(const std::vector<std::string>& filament_types);
|
||||||
|
// similar to check_multi_filaments_compatibility, but the input is int, and may be negative (means unset)
|
||||||
|
static bool is_filaments_compatible(const std::vector<int>& types);
|
||||||
|
// get the compatible filament type of a multi-material object
|
||||||
|
// Rule:
|
||||||
|
// 1. LowTemp+HighLowCompatible=LowTemp
|
||||||
|
// 2. HighTemp++HighLowCompatible=HighTemp
|
||||||
|
// 3. LowTemp+HighTemp+...=HighLowCompatible
|
||||||
|
// Unset types are just ignored.
|
||||||
|
static int get_compatible_filament_type(const std::set<int>& types);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Invalidates the step, and its depending steps in Print.
|
// Invalidates the step, and its depending steps in Print.
|
||||||
|
|
|
@ -518,9 +518,9 @@ void ArrangeJob::process()
|
||||||
{
|
{
|
||||||
BOOST_LOG_TRIVIAL(warning)<< "Arrange full params: "<< params.to_json();
|
BOOST_LOG_TRIVIAL(warning)<< "Arrange full params: "<< params.to_json();
|
||||||
BOOST_LOG_TRIVIAL(info) << boost::format("arrange: items selected before arranging: %1%") % m_selected.size();
|
BOOST_LOG_TRIVIAL(info) << boost::format("arrange: items selected before arranging: %1%") % m_selected.size();
|
||||||
for (auto selected : m_selected)
|
for (auto selected : m_selected) {
|
||||||
BOOST_LOG_TRIVIAL(debug) << selected.name << ", extruder: " << selected.extrude_ids.back() << ", bed: " << selected.bed_idx
|
BOOST_LOG_TRIVIAL(debug) << selected.name << ", extruder: " << selected.extrude_ids.back() << ", bed: " << selected.bed_idx<<", filemant_type:" << selected.filament_temp_type;
|
||||||
<< ", bed_temp: " << selected.first_bed_temp << ", print_temp: " << selected.print_temp;
|
}
|
||||||
BOOST_LOG_TRIVIAL(debug) << "items unselected before arrange: ";
|
BOOST_LOG_TRIVIAL(debug) << "items unselected before arrange: ";
|
||||||
for (auto item : m_unselected)
|
for (auto item : m_unselected)
|
||||||
BOOST_LOG_TRIVIAL(debug) << item.name << ", bed: " << item.bed_idx << ", trans: " << item.translation.transpose();
|
BOOST_LOG_TRIVIAL(debug) << item.name << ", bed: " << item.bed_idx << ", trans: " << item.translation.transpose();
|
||||||
|
|
Loading…
Reference in New Issue