mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-10-26 10:11:10 -06:00
Merge branch 'master' of https://github.com/Prusa3D/PrusaSlicer
This commit is contained in:
commit
d5e6b17d70
67 changed files with 21006 additions and 16685 deletions
|
|
@ -7,6 +7,7 @@
|
|||
#include <libnest2d/optimizers/nlopt/subplex.hpp>
|
||||
#include <libnest2d/placers/nfpplacer.hpp>
|
||||
#include <libnest2d/selections/firstfit.hpp>
|
||||
#include <libnest2d/utils/rotcalipers.hpp>
|
||||
|
||||
#include <numeric>
|
||||
#include <ClipperUtils.hpp>
|
||||
|
|
@ -83,7 +84,7 @@ const double BIG_ITEM_TRESHOLD = 0.02;
|
|||
// Fill in the placer algorithm configuration with values carefully chosen for
|
||||
// Slic3r.
|
||||
template<class PConf>
|
||||
void fill_config(PConf& pcfg) {
|
||||
void fill_config(PConf& pcfg, const ArrangeParams ¶ms) {
|
||||
|
||||
// Align the arranged pile into the center of the bin
|
||||
pcfg.alignment = PConf::Alignment::CENTER;
|
||||
|
|
@ -93,14 +94,17 @@ void fill_config(PConf& pcfg) {
|
|||
|
||||
// TODO cannot use rotations until multiple objects of same geometry can
|
||||
// handle different rotations.
|
||||
pcfg.rotations = { 0.0 };
|
||||
if (params.allow_rotations)
|
||||
pcfg.rotations = {0., PI / 2., PI, 3. * PI / 2. };
|
||||
else
|
||||
pcfg.rotations = {0.};
|
||||
|
||||
// The accuracy of optimization.
|
||||
// Goes from 0.0 to 1.0 and scales performance as well
|
||||
pcfg.accuracy = 0.65f;
|
||||
pcfg.accuracy = params.accuracy;
|
||||
|
||||
// Allow parallel execution.
|
||||
pcfg.parallel = true;
|
||||
pcfg.parallel = params.parallel;
|
||||
}
|
||||
|
||||
// Apply penalty to object function result. This is used only when alignment
|
||||
|
|
@ -277,10 +281,10 @@ protected:
|
|||
if (result.empty())
|
||||
score = 0.50 * dist + 0.50 * density;
|
||||
else
|
||||
score = R * 0.60 * dist +
|
||||
(1.0 - R) * 0.20 * density +
|
||||
0.20 * alignment_score;
|
||||
|
||||
// Let the density matter more when fewer objects remain
|
||||
score = 0.50 * dist + (1.0 - R) * 0.20 * density +
|
||||
0.30 * alignment_score;
|
||||
|
||||
break;
|
||||
}
|
||||
case LAST_BIG_ITEM: {
|
||||
|
|
@ -304,15 +308,15 @@ protected:
|
|||
|
||||
public:
|
||||
AutoArranger(const TBin & bin,
|
||||
Distance dist,
|
||||
const ArrangeParams ¶ms,
|
||||
std::function<void(unsigned)> progressind,
|
||||
std::function<bool(void)> stopcond)
|
||||
: m_pck(bin, dist)
|
||||
: m_pck(bin, params.min_obj_distance)
|
||||
, m_bin(bin)
|
||||
, m_bin_area(sl::area(bin))
|
||||
, m_norm(std::sqrt(m_bin_area))
|
||||
{
|
||||
fill_config(m_pconf);
|
||||
fill_config(m_pconf, params);
|
||||
|
||||
// Set up a callback that is called just before arranging starts
|
||||
// This functionality is provided by the Nester class (m_pack).
|
||||
|
|
@ -349,12 +353,6 @@ public:
|
|||
|
||||
m_pck.configure(m_pconf);
|
||||
}
|
||||
|
||||
AutoArranger(const TBin & bin,
|
||||
std::function<void(unsigned)> progressind,
|
||||
std::function<bool(void)> stopcond)
|
||||
: AutoArranger{bin, 0 /* no min distance */, progressind, stopcond}
|
||||
{}
|
||||
|
||||
template<class It> inline void operator()(It from, It to) {
|
||||
m_rtree.clear();
|
||||
|
|
@ -452,12 +450,18 @@ template<class Bin> void remove_large_items(std::vector<Item> &items, Bin &&bin)
|
|||
++it : it = items.erase(it);
|
||||
}
|
||||
|
||||
template<class S> Radians min_area_boundingbox_rotation(const S &sh)
|
||||
{
|
||||
return minAreaBoundingBox<S, TCompute<S>, boost::rational<LargeInt>>(sh)
|
||||
.angleToX();
|
||||
}
|
||||
|
||||
template<class BinT> // Arrange for arbitrary bin type
|
||||
void _arrange(
|
||||
std::vector<Item> & shapes,
|
||||
std::vector<Item> & excludes,
|
||||
const BinT & bin,
|
||||
const ArrangeParams & params,
|
||||
const ArrangeParams ¶ms,
|
||||
std::function<void(unsigned)> progressfn,
|
||||
std::function<bool()> stopfn)
|
||||
{
|
||||
|
|
@ -467,11 +471,10 @@ void _arrange(
|
|||
|
||||
auto corrected_bin = bin;
|
||||
sl::offset(corrected_bin, md);
|
||||
|
||||
AutoArranger<BinT> arranger{corrected_bin, progressfn, stopfn};
|
||||
|
||||
arranger.config().accuracy = params.accuracy;
|
||||
arranger.config().parallel = params.parallel;
|
||||
ArrangeParams mod_params = params;
|
||||
mod_params.min_obj_distance = 0;
|
||||
|
||||
AutoArranger<BinT> arranger{corrected_bin, mod_params, progressfn, stopfn};
|
||||
|
||||
auto infl = coord_t(std::ceil(params.min_obj_distance / 2.0));
|
||||
for (Item& itm : shapes) itm.inflate(infl);
|
||||
|
|
@ -487,6 +490,13 @@ void _arrange(
|
|||
for (auto &itm : shapes ) inp.emplace_back(itm);
|
||||
for (auto &itm : excludes) inp.emplace_back(itm);
|
||||
|
||||
// Use the minimum bounding box rotation as a starting point.
|
||||
// TODO: This only works for convex hull. If we ever switch to concave
|
||||
// polygon nesting, a convex hull needs to be calculated.
|
||||
if (params.allow_rotations)
|
||||
for (auto &itm : shapes)
|
||||
itm.rotation(min_area_boundingbox_rotation(itm.rawShape()));
|
||||
|
||||
arranger(inp.begin(), inp.end());
|
||||
for (Item &itm : inp) itm.inflate(-infl);
|
||||
}
|
||||
|
|
@ -556,28 +566,35 @@ static void process_arrangeable(const ArrangePolygon &arrpoly,
|
|||
outp.back().priority(arrpoly.priority);
|
||||
}
|
||||
|
||||
template<class Fn> auto call_with_bed(const Points &bed, Fn &&fn)
|
||||
{
|
||||
if (bed.empty())
|
||||
return fn(InfiniteBed{});
|
||||
else if (bed.size() == 1)
|
||||
return fn(InfiniteBed{bed.front()});
|
||||
else {
|
||||
auto bb = BoundingBox(bed);
|
||||
CircleBed circ = to_circle(bb.center(), bed);
|
||||
auto parea = poly_area(bed);
|
||||
|
||||
if ((1.0 - parea / area(bb)) < 1e-3)
|
||||
return fn(bb);
|
||||
else if (!std::isnan(circ.radius()))
|
||||
return fn(circ);
|
||||
else
|
||||
return fn(Polygon(bed));
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
void arrange(ArrangePolygons & items,
|
||||
const ArrangePolygons &excludes,
|
||||
const Points & bed,
|
||||
const ArrangeParams & params)
|
||||
{
|
||||
if (bed.empty())
|
||||
arrange(items, excludes, InfiniteBed{}, params);
|
||||
else if (bed.size() == 1)
|
||||
arrange(items, excludes, InfiniteBed{bed.front()}, params);
|
||||
else {
|
||||
auto bb = BoundingBox(bed);
|
||||
CircleBed circ = to_circle(bb.center(), bed);
|
||||
auto parea = poly_area(bed);
|
||||
|
||||
if ((1.0 - parea / area(bb)) < 1e-3)
|
||||
arrange(items, excludes, bb, params);
|
||||
else if (!std::isnan(circ.radius()))
|
||||
arrange(items, excludes, circ, params);
|
||||
else
|
||||
arrange(items, excludes, Polygon(bed), params);
|
||||
}
|
||||
call_with_bed(bed, [&](const auto &bin) {
|
||||
arrange(items, excludes, bin, params);
|
||||
});
|
||||
}
|
||||
|
||||
template<class BedT>
|
||||
|
|
|
|||
|
|
@ -78,6 +78,8 @@ struct ArrangeParams {
|
|||
|
||||
/// Allow parallel execution.
|
||||
bool parallel = true;
|
||||
|
||||
bool allow_rotations = false;
|
||||
|
||||
/// Progress indicator callback called when an object gets packed.
|
||||
/// The unsigned argument is the number of items remaining to pack.
|
||||
|
|
|
|||
|
|
@ -1858,7 +1858,7 @@ void GCode::process_layer(
|
|||
std::string gcode;
|
||||
|
||||
// add tag for processor
|
||||
gcode += "; " + GCodeProcessor::Layer_Change_Tag + "\n";
|
||||
gcode += ";" + GCodeProcessor::Layer_Change_Tag + "\n";
|
||||
// export layer z
|
||||
char buf[64];
|
||||
sprintf(buf, ";Z:%g\n", print_z);
|
||||
|
|
|
|||
|
|
@ -393,7 +393,7 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename)
|
|||
auto is_temporary_decoration = [](const std::string& gcode_line) {
|
||||
// remove trailing '\n'
|
||||
std::string line = gcode_line.substr(0, gcode_line.length() - 1);
|
||||
if (line == "; " + Layer_Change_Tag)
|
||||
if (line == ";" + Layer_Change_Tag)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
|
|
@ -817,6 +817,10 @@ void GCodeProcessor::process_file(const std::string& filename, bool apply_postpr
|
|||
|
||||
update_estimated_times_stats();
|
||||
|
||||
// ensure at least one (default) color is defined
|
||||
if (m_result.extruder_colors.empty())
|
||||
m_result.extruder_colors.push_back("#FF8000");
|
||||
|
||||
// post-process to add M73 lines into the gcode
|
||||
if (apply_postprocess)
|
||||
m_time_processor.post_process(filename);
|
||||
|
|
|
|||
|
|
@ -1840,8 +1840,11 @@ namespace PresetUtils {
|
|||
{
|
||||
std::string out;
|
||||
const VendorProfile::PrinterModel* pm = PresetUtils::system_printer_model(preset);
|
||||
if (pm != nullptr && !pm->bed_model.empty())
|
||||
out = Slic3r::resources_dir() + "/profiles/" + preset.vendor->id + "/" + pm->bed_model;
|
||||
if (pm != nullptr && !pm->bed_model.empty()) {
|
||||
out = Slic3r::data_dir() + "/vendor/" + preset.vendor->id + "/" + pm->bed_model;
|
||||
if (!boost::filesystem::exists(boost::filesystem::path(out)))
|
||||
out = Slic3r::resources_dir() + "/profiles/" + preset.vendor->id + "/" + pm->bed_model;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
|
|
@ -1849,8 +1852,11 @@ namespace PresetUtils {
|
|||
{
|
||||
std::string out;
|
||||
const VendorProfile::PrinterModel* pm = PresetUtils::system_printer_model(preset);
|
||||
if (pm != nullptr && !pm->bed_texture.empty())
|
||||
out = Slic3r::resources_dir() + "/profiles/" + preset.vendor->id + "/" + pm->bed_texture;
|
||||
if (pm != nullptr && !pm->bed_texture.empty()) {
|
||||
out = Slic3r::data_dir() + "/vendor/" + preset.vendor->id + "/" + pm->bed_texture;
|
||||
if (!boost::filesystem::exists(boost::filesystem::path(out)))
|
||||
out = Slic3r::resources_dir() + "/profiles/" + preset.vendor->id + "/" + pm->bed_texture;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
} // namespace PresetUtils
|
||||
|
|
|
|||
|
|
@ -350,6 +350,7 @@ struct SLAPrintStatistics
|
|||
size_t fast_layers_count;
|
||||
double total_cost;
|
||||
double total_weight;
|
||||
std::vector<double> layers_times;
|
||||
|
||||
// Config with the filled in print statistics.
|
||||
DynamicConfig config() const;
|
||||
|
|
@ -366,6 +367,7 @@ struct SLAPrintStatistics
|
|||
fast_layers_count = 0;
|
||||
total_cost = 0.;
|
||||
total_weight = 0.;
|
||||
layers_times.clear();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -671,6 +671,8 @@ void SLAPrint::Steps::merge_slices_and_eval_stats() {
|
|||
double models_volume(0.0);
|
||||
|
||||
double estim_time(0.0);
|
||||
std::vector<double> layers_times;
|
||||
layers_times.reserve(printer_input.size());
|
||||
|
||||
size_t slow_layers = 0;
|
||||
size_t fast_layers = 0;
|
||||
|
|
@ -688,7 +690,7 @@ void SLAPrint::Steps::merge_slices_and_eval_stats() {
|
|||
|
||||
// write vars
|
||||
&mutex, &models_volume, &supports_volume, &estim_time, &slow_layers,
|
||||
&fast_layers, &fade_layer_time](size_t sliced_layer_cnt)
|
||||
&fast_layers, &fade_layer_time, &layers_times](size_t sliced_layer_cnt)
|
||||
{
|
||||
PrintLayer &layer = m_print->m_printer_input[sliced_layer_cnt];
|
||||
|
||||
|
|
@ -775,20 +777,21 @@ void SLAPrint::Steps::merge_slices_and_eval_stats() {
|
|||
else
|
||||
slow_layers++;
|
||||
|
||||
|
||||
// Calculation of the printing time
|
||||
|
||||
|
||||
double layer_times = 0.0;
|
||||
if (sliced_layer_cnt < 3)
|
||||
estim_time += init_exp_time;
|
||||
else if (fade_layer_time > exp_time)
|
||||
{
|
||||
layer_times += init_exp_time;
|
||||
else if (fade_layer_time > exp_time) {
|
||||
fade_layer_time -= delta_fade_time;
|
||||
estim_time += fade_layer_time;
|
||||
layer_times += fade_layer_time;
|
||||
}
|
||||
else
|
||||
estim_time += exp_time;
|
||||
|
||||
estim_time += tilt_time;
|
||||
layer_times += exp_time;
|
||||
layer_times += tilt_time;
|
||||
|
||||
layers_times.push_back(layer_times);
|
||||
estim_time += layer_times;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -804,8 +807,10 @@ void SLAPrint::Steps::merge_slices_and_eval_stats() {
|
|||
// A layers count o the highest object
|
||||
if (printer_input.size() == 0)
|
||||
print_statistics.estimated_print_time = std::nan("");
|
||||
else
|
||||
else {
|
||||
print_statistics.estimated_print_time = estim_time;
|
||||
print_statistics.layers_times = layers_times;
|
||||
}
|
||||
|
||||
print_statistics.fast_layers_count = fast_layers;
|
||||
print_statistics.slow_layers_count = slow_layers;
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@
|
|||
#define ENABLE_2_3_0_ALPHA4 1
|
||||
|
||||
#define ENABLE_FIXED_SCREEN_SIZE_POINT_MARKERS (1 && ENABLE_GCODE_VIEWER && ENABLE_2_3_0_ALPHA4)
|
||||
#define ENABLE_SHOW_OPTION_POINT_LAYERS (1 && ENABLE_GCODE_VIEWER && ENABLE_2_3_0_ALPHA4)
|
||||
|
||||
|
||||
#endif // _prusaslicer_technologies_h_
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue