mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-10-26 18:21:18 -06:00
Merge branch 'master' of https://github.com/prusa3d/PrusaSlicer into et_reload_from_disk
This commit is contained in:
commit
e1774f9085
34 changed files with 774 additions and 962 deletions
|
|
@ -165,6 +165,8 @@ add_library(libslic3r STATIC
|
|||
TriangleMesh.hpp
|
||||
utils.cpp
|
||||
Utils.hpp
|
||||
Time.cpp
|
||||
Time.hpp
|
||||
MTUtils.hpp
|
||||
Zipper.hpp
|
||||
Zipper.cpp
|
||||
|
|
|
|||
|
|
@ -537,6 +537,21 @@ std::vector<GCode::LayerToPrint> GCode::collect_layers_to_print(const PrintObjec
|
|||
std::vector<GCode::LayerToPrint> layers_to_print;
|
||||
layers_to_print.reserve(object.layers().size() + object.support_layers().size());
|
||||
|
||||
// Calculate a minimum support layer height as a minimum over all extruders, but not smaller than 10um.
|
||||
// This is the same logic as in support generator.
|
||||
//FIXME should we use the printing extruders instead?
|
||||
double gap_over_supports = object.config().support_material_contact_distance;
|
||||
// FIXME should we test object.config().support_material_synchronize_layers ? Currently the support layers are synchronized with object layers iff soluble supports.
|
||||
assert(gap_over_supports != 0. || object.config().support_material_synchronize_layers);
|
||||
if (gap_over_supports != 0.) {
|
||||
gap_over_supports = std::max(0., gap_over_supports);
|
||||
// Not a soluble support,
|
||||
double support_layer_height_min = 1000000.;
|
||||
for (auto lh : object.print()->config().min_layer_height.values)
|
||||
support_layer_height_min = std::min(support_layer_height_min, std::max(0.01, lh));
|
||||
gap_over_supports += support_layer_height_min;
|
||||
}
|
||||
|
||||
// Pair the object layers with the support layers by z.
|
||||
size_t idx_object_layer = 0;
|
||||
size_t idx_support_layer = 0;
|
||||
|
|
@ -559,18 +574,19 @@ std::vector<GCode::LayerToPrint> GCode::collect_layers_to_print(const PrintObjec
|
|||
|
||||
// In case there are extrusions on this layer, check there is a layer to lay it on.
|
||||
if ((layer_to_print.object_layer && layer_to_print.object_layer->has_extrusions())
|
||||
|| (layer_to_print.support_layer && layer_to_print.support_layer->has_extrusions())) {
|
||||
// Allow empty support layers, as the support generator may produce no extrusions for non-empty support regions.
|
||||
|| (layer_to_print.support_layer /* && layer_to_print.support_layer->has_extrusions() */)) {
|
||||
double support_contact_z = (last_extrusion_layer && last_extrusion_layer->support_layer)
|
||||
? object.config().support_material_contact_distance
|
||||
? gap_over_supports
|
||||
: 0.;
|
||||
double maximal_print_z = (last_extrusion_layer ? last_extrusion_layer->print_z() : 0.)
|
||||
+ layer_to_print.layer()->height
|
||||
+ std::max(0., support_contact_z);
|
||||
+ support_contact_z;
|
||||
// Negative support_contact_z is not taken into account, it can result in false positives in cases
|
||||
// where previous layer has object extrusions too (https://github.com/prusa3d/PrusaSlicer/issues/2752)
|
||||
|
||||
|
||||
if (layer_to_print.print_z() > maximal_print_z + EPSILON)
|
||||
if (layer_to_print.print_z() > maximal_print_z + 2. * EPSILON)
|
||||
throw std::runtime_error(_(L("Empty layers detected, the output would not be printable.")) + "\n\n" +
|
||||
_(L("Object name: ")) + object.model_object()->name + "\n" + _(L("Print z: ")) +
|
||||
std::to_string(layers_to_print.back().print_z()) + "\n\n" + _(L("This is "
|
||||
|
|
|
|||
|
|
@ -529,7 +529,10 @@ void GCodeAnalyzer::_processT(const std::string& cmd)
|
|||
if (_get_extruder_id() != id)
|
||||
{
|
||||
if (id >= m_extruders_count)
|
||||
BOOST_LOG_TRIVIAL(error) << "GCodeAnalyzer encountered an invalid toolchange, maybe from a custom gcode.";
|
||||
{
|
||||
if (m_extruders_count > 1)
|
||||
BOOST_LOG_TRIVIAL(error) << "GCodeAnalyzer encountered an invalid toolchange, maybe from a custom gcode.";
|
||||
}
|
||||
else
|
||||
_set_extruder_id(id);
|
||||
|
||||
|
|
|
|||
|
|
@ -36,19 +36,6 @@ TODO LIST
|
|||
namespace Slic3r
|
||||
{
|
||||
|
||||
// Rotate the point around center of the wipe tower about given angle (in degrees)
|
||||
static Vec2f rotate(const Vec2f& pt, float width, float depth, float angle)
|
||||
{
|
||||
Vec2f out(0,0);
|
||||
float temp_x = pt(0) - width / 2.f;
|
||||
float temp_y = pt(1) - depth / 2.f;
|
||||
angle *= float(M_PI/180.);
|
||||
out.x() += temp_x * cos(angle) - temp_y * sin(angle) + width / 2.f;
|
||||
out.y() += temp_x * sin(angle) + temp_y * cos(angle) + depth / 2.f;
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
class WipeTowerWriter
|
||||
{
|
||||
public:
|
||||
|
|
@ -95,7 +82,7 @@ public:
|
|||
m_wipe_tower_width = width;
|
||||
m_wipe_tower_depth = depth;
|
||||
m_internal_angle = internal_angle;
|
||||
m_start_pos = rotate(pos + Vec2f(0.f,m_y_shift), m_wipe_tower_width, m_wipe_tower_depth, m_internal_angle);
|
||||
m_start_pos = this->rotate(pos);
|
||||
m_current_pos = pos;
|
||||
return *this;
|
||||
}
|
||||
|
|
@ -136,9 +123,9 @@ public:
|
|||
const std::vector<WipeTower::Extrusion>& extrusions() const { return m_extrusions; }
|
||||
float x() const { return m_current_pos.x(); }
|
||||
float y() const { return m_current_pos.y(); }
|
||||
const Vec2f& pos() const { return m_current_pos; }
|
||||
const Vec2f start_pos_rotated() const { return m_start_pos; }
|
||||
const Vec2f pos_rotated() const { return rotate(m_current_pos + Vec2f(0.f, m_y_shift), m_wipe_tower_width, m_wipe_tower_depth, m_internal_angle); }
|
||||
const Vec2f& pos() const { return m_current_pos; }
|
||||
const Vec2f start_pos_rotated() const { return m_start_pos; }
|
||||
const Vec2f pos_rotated() const { return this->rotate(m_current_pos); }
|
||||
float elapsed_time() const { return m_elapsed_time; }
|
||||
float get_and_reset_used_filament_length() { float temp = m_used_filament_length; m_used_filament_length = 0.f; return temp; }
|
||||
|
||||
|
|
@ -156,8 +143,8 @@ public:
|
|||
m_used_filament_length += e;
|
||||
|
||||
// Now do the "internal rotation" with respect to the wipe tower center
|
||||
Vec2f rotated_current_pos(rotate(m_current_pos + Vec2f(0.f,m_y_shift), m_wipe_tower_width, m_wipe_tower_depth, m_internal_angle)); // this is where we are
|
||||
Vec2f rot(rotate(Vec2f(x,y+m_y_shift), m_wipe_tower_width, m_wipe_tower_depth, m_internal_angle)); // this is where we want to go
|
||||
Vec2f rotated_current_pos(this->pos_rotated());
|
||||
Vec2f rot(this->rotate(Vec2f(x,y))); // this is where we want to go
|
||||
|
||||
if (! m_preview_suppressed && e > 0.f && len > 0.f) {
|
||||
change_analyzer_mm3_per_mm(len, e);
|
||||
|
|
@ -459,6 +446,18 @@ private:
|
|||
}
|
||||
|
||||
WipeTowerWriter& operator=(const WipeTowerWriter &rhs);
|
||||
|
||||
// Rotate the point around center of the wipe tower about given angle (in degrees)
|
||||
Vec2f rotate(Vec2f pt) const
|
||||
{
|
||||
pt.x() -= m_wipe_tower_width / 2.f;
|
||||
pt.y() += m_y_shift - m_wipe_tower_depth / 2.f;
|
||||
double angle = m_internal_angle * float(M_PI/180.);
|
||||
double c = cos(angle);
|
||||
double s = sin(angle);
|
||||
return Vec2f(float(pt.x() * c - pt.y() * s) + m_wipe_tower_width / 2.f, float(pt.x() * s + pt.y() * c) + m_wipe_tower_depth / 2.f);
|
||||
}
|
||||
|
||||
}; // class WipeTowerWriter
|
||||
|
||||
|
||||
|
|
@ -996,7 +995,8 @@ void WipeTower::toolchange_Change(
|
|||
|
||||
// Travel to where we assume we are. Custom toolchange or some special T code handling (parking extruder etc)
|
||||
// gcode could have left the extruder somewhere, we cannot just start extruding.
|
||||
writer.append(std::string("G1 X") + std::to_string(writer.x()) + " Y" + std::to_string(writer.y()) + "\n");
|
||||
Vec2f current_pos = writer.pos_rotated();
|
||||
writer.append(std::string("G1 X") + std::to_string(current_pos.x()) + " Y" + std::to_string(current_pos.y()) + "\n");
|
||||
|
||||
// The toolchange Tn command will be inserted later, only in case that the user does
|
||||
// not provide a custom toolchange gcode.
|
||||
|
|
|
|||
|
|
@ -68,15 +68,14 @@ public:
|
|||
|
||||
/// Type that represents a resolution in pixels.
|
||||
struct Resolution {
|
||||
unsigned width_px;
|
||||
unsigned height_px;
|
||||
size_t width_px;
|
||||
size_t height_px;
|
||||
|
||||
inline Resolution(unsigned w = 0, unsigned h = 0):
|
||||
width_px(w), height_px(h) {}
|
||||
inline Resolution(size_t w = 0, size_t h = 0)
|
||||
: width_px(w), height_px(h)
|
||||
{}
|
||||
|
||||
inline unsigned pixels() const /*noexcept*/ {
|
||||
return width_px * height_px;
|
||||
}
|
||||
inline size_t pixels() const { return width_px * height_px; }
|
||||
};
|
||||
|
||||
/// Types that represents the dimension of a pixel in millimeters.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
#include "SLARasterWriter.hpp"
|
||||
#include "libslic3r/Zipper.hpp"
|
||||
#include "libslic3r/Time.hpp"
|
||||
|
||||
#include "ExPolygon.hpp"
|
||||
#include <libnest2d/backends/clipper/clipper_polygon.hpp>
|
||||
|
||||
|
|
@ -10,25 +12,13 @@ namespace Slic3r { namespace sla {
|
|||
|
||||
std::string SLARasterWriter::createIniContent(const std::string& projectname) const
|
||||
{
|
||||
auto expt_str = std::to_string(m_exp_time_s);
|
||||
auto expt_first_str = std::to_string(m_exp_time_first_s);
|
||||
auto layerh_str = std::to_string(m_layer_height);
|
||||
|
||||
const std::string cnt_fade_layers = std::to_string(m_cnt_fade_layers);
|
||||
const std::string cnt_slow_layers = std::to_string(m_cnt_slow_layers);
|
||||
const std::string cnt_fast_layers = std::to_string(m_cnt_fast_layers);
|
||||
const std::string used_material = std::to_string(m_used_material);
|
||||
|
||||
return std::string(
|
||||
"action = print\n"
|
||||
"jobDir = ") + projectname + "\n" +
|
||||
"expTime = " + expt_str + "\n"
|
||||
"expTimeFirst = " + expt_first_str + "\n"
|
||||
"numFade = " + cnt_fade_layers + "\n"
|
||||
"layerHeight = " + layerh_str + "\n"
|
||||
"usedMaterial = " + used_material + "\n"
|
||||
"numSlow = " + cnt_slow_layers + "\n"
|
||||
"numFast = " + cnt_fast_layers + "\n";
|
||||
std::string out("action = print\njobDir = ");
|
||||
out += projectname + "\n";
|
||||
|
||||
for (auto ¶m : m_config)
|
||||
out += param.first + " = " + param.second + "\n";
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
void SLARasterWriter::flpXY(ClipperLib::Polygon &poly)
|
||||
|
|
@ -53,38 +43,14 @@ void SLARasterWriter::flpXY(ExPolygon &poly)
|
|||
}
|
||||
}
|
||||
|
||||
SLARasterWriter::SLARasterWriter(const SLAPrinterConfig &cfg,
|
||||
const SLAMaterialConfig &mcfg,
|
||||
double layer_height)
|
||||
SLARasterWriter::SLARasterWriter(const Raster::Resolution &res,
|
||||
const Raster::PixelDim &pixdim,
|
||||
const std::array<bool, 2> &mirror,
|
||||
double gamma)
|
||||
: m_res(res), m_pxdim(pixdim), m_mirror(mirror), m_gamma(gamma)
|
||||
{
|
||||
double w = cfg.display_width.getFloat();
|
||||
double h = cfg.display_height.getFloat();
|
||||
auto pw = unsigned(cfg.display_pixels_x.getInt());
|
||||
auto ph = unsigned(cfg.display_pixels_y.getInt());
|
||||
|
||||
m_mirror[X] = cfg.display_mirror_x.getBool();
|
||||
|
||||
// PNG raster will implicitly do an Y mirror
|
||||
m_mirror[Y] = ! cfg.display_mirror_y.getBool();
|
||||
|
||||
auto ro = cfg.display_orientation.getInt();
|
||||
|
||||
if(ro == roPortrait) {
|
||||
std::swap(w, h);
|
||||
std::swap(pw, ph);
|
||||
m_o = roPortrait;
|
||||
|
||||
// XY flipping implicitly does an X mirror
|
||||
m_mirror[X] = ! m_mirror[X];
|
||||
} else m_o = roLandscape;
|
||||
|
||||
m_res = Raster::Resolution(pw, ph);
|
||||
m_pxdim = Raster::PixelDim(w/pw, h/ph);
|
||||
m_exp_time_s = mcfg.exposure_time.getFloat();
|
||||
m_exp_time_first_s = mcfg.initial_exposure_time.getFloat();
|
||||
m_layer_height = layer_height;
|
||||
|
||||
m_gamma = cfg.gamma_correction.getFloat();
|
||||
m_mirror[1] = !m_mirror[1];
|
||||
}
|
||||
|
||||
void SLARasterWriter::save(const std::string &fpath, const std::string &prjname)
|
||||
|
|
@ -121,15 +87,44 @@ void SLARasterWriter::save(const std::string &fpath, const std::string &prjname)
|
|||
}
|
||||
}
|
||||
|
||||
void SLARasterWriter::set_statistics(const std::vector<double> statistics)
|
||||
namespace {
|
||||
|
||||
std::string get_cfg_value(const DynamicPrintConfig &cfg, const std::string &key)
|
||||
{
|
||||
if (statistics.size() != psCnt)
|
||||
return;
|
||||
std::string ret;
|
||||
|
||||
m_used_material = statistics[psUsedMaterial];
|
||||
m_cnt_fade_layers = int(statistics[psNumFade]);
|
||||
m_cnt_slow_layers = int(statistics[psNumSlow]);
|
||||
m_cnt_fast_layers = int(statistics[psNumFast]);
|
||||
if (cfg.has(key)) {
|
||||
auto opt = cfg.option(key);
|
||||
if (opt) ret = opt->serialize();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void SLARasterWriter::set_config(const DynamicPrintConfig &cfg)
|
||||
{
|
||||
m_config["layerHeight"] = get_cfg_value(cfg, "layer_height");
|
||||
m_config["expTime"] = get_cfg_value(cfg, "exposure_time");
|
||||
m_config["expTimeFirst"] = get_cfg_value(cfg, "initial_exposure_time");
|
||||
m_config["materialName"] = get_cfg_value(cfg, "sla_material_settings_id");
|
||||
m_config["printerModel"] = get_cfg_value(cfg, "printer_model");
|
||||
m_config["printerVariant"] = get_cfg_value(cfg, "printer_variant");
|
||||
m_config["printerProfile"] = get_cfg_value(cfg, "printer_settings_id");
|
||||
m_config["printProfile"] = get_cfg_value(cfg, "sla_print_settings_id");
|
||||
|
||||
m_config["fileCreationTimestamp"] = Utils::current_utc_time2str();
|
||||
m_config["prusaSlicerVersion"] = SLIC3R_BUILD_ID;
|
||||
}
|
||||
|
||||
void SLARasterWriter::set_statistics(const PrintStatistics &stats)
|
||||
{
|
||||
m_config["usedMaterial"] = std::to_string(stats.used_material);
|
||||
m_config["numFade"] = std::to_string(stats.num_fade);
|
||||
m_config["numSlow"] = std::to_string(stats.num_slow);
|
||||
m_config["numFast"] = std::to_string(stats.num_fast);
|
||||
m_config["printTime"] = std::to_string(stats.estimated_print_time_s);
|
||||
}
|
||||
|
||||
} // namespace sla
|
||||
|
|
|
|||
|
|
@ -3,8 +3,10 @@
|
|||
|
||||
// For png export of the sliced model
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <array>
|
||||
|
||||
#include "libslic3r/PrintConfig.hpp"
|
||||
|
|
@ -23,20 +25,19 @@ namespace Slic3r { namespace sla {
|
|||
class SLARasterWriter
|
||||
{
|
||||
public:
|
||||
enum RasterOrientation {
|
||||
enum Orientation {
|
||||
roLandscape,
|
||||
roPortrait
|
||||
};
|
||||
|
||||
// Used for addressing parameters of set_statistics()
|
||||
enum ePrintStatistics
|
||||
{
|
||||
psUsedMaterial = 0,
|
||||
psNumFade,
|
||||
psNumSlow,
|
||||
psNumFast,
|
||||
|
||||
psCnt
|
||||
struct PrintStatistics
|
||||
{
|
||||
double used_material = 0.;
|
||||
double estimated_print_time_s = 0.;
|
||||
size_t num_fade = 0;
|
||||
size_t num_slow = 0;
|
||||
size_t num_fast = 0;
|
||||
};
|
||||
|
||||
private:
|
||||
|
|
@ -47,21 +48,13 @@ private:
|
|||
RawBytes rawbytes;
|
||||
|
||||
Layer() = default;
|
||||
Layer(const Layer&) = delete; // The image is big, do not copy by accident
|
||||
Layer& operator=(const Layer&) = delete;
|
||||
|
||||
// /////////////////////////////////////////////////////////////////////
|
||||
// FIXME: the following is needed for MSVC2013 compatibility
|
||||
// /////////////////////////////////////////////////////////////////////
|
||||
// The image is big, do not copy by accident
|
||||
Layer(const Layer&) = delete;
|
||||
Layer& operator=(const Layer&) = delete;
|
||||
|
||||
// Layer(Layer&& m) = default;
|
||||
// Layer& operator=(Layer&&) = default;
|
||||
Layer(Layer &&m):
|
||||
raster(std::move(m.raster)), rawbytes(std::move(m.rawbytes)) {}
|
||||
Layer& operator=(Layer &&m) {
|
||||
raster = std::move(m.raster); rawbytes = std::move(m.rawbytes);
|
||||
return *this;
|
||||
}
|
||||
Layer(Layer &&m) = default;
|
||||
Layer &operator=(Layer &&) = default;
|
||||
};
|
||||
|
||||
// We will save the compressed PNG data into RawBytes type buffers in
|
||||
|
|
@ -69,66 +62,46 @@ private:
|
|||
std::vector<Layer> m_layers_rst;
|
||||
Raster::Resolution m_res;
|
||||
Raster::PixelDim m_pxdim;
|
||||
double m_exp_time_s = .0, m_exp_time_first_s = .0;
|
||||
double m_layer_height = .0;
|
||||
RasterOrientation m_o = roPortrait;
|
||||
std::array<bool, 2> m_mirror;
|
||||
|
||||
double m_gamma;
|
||||
|
||||
double m_used_material = 0.0;
|
||||
int m_cnt_fade_layers = 0;
|
||||
int m_cnt_slow_layers = 0;
|
||||
int m_cnt_fast_layers = 0;
|
||||
|
||||
|
||||
std::map<std::string, std::string> m_config;
|
||||
|
||||
std::string createIniContent(const std::string& projectname) const;
|
||||
|
||||
static void flpXY(ClipperLib::Polygon& poly);
|
||||
static void flpXY(ExPolygon& poly);
|
||||
|
||||
public:
|
||||
|
||||
SLARasterWriter(const SLAPrinterConfig& cfg,
|
||||
const SLAMaterialConfig& mcfg,
|
||||
double layer_height);
|
||||
SLARasterWriter(const Raster::Resolution &res,
|
||||
const Raster::PixelDim &pixdim,
|
||||
const std::array<bool, 2> &mirror,
|
||||
double gamma = 1.);
|
||||
|
||||
SLARasterWriter(const SLARasterWriter& ) = delete;
|
||||
SLARasterWriter& operator=(const SLARasterWriter&) = delete;
|
||||
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
// FIXME: the following is needed for MSVC2013 compatibility
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// SLARasterWriter(SLARasterWriter&& m) = default;
|
||||
// SLARasterWriter& operator=(SLARasterWriter&&) = default;
|
||||
SLARasterWriter(SLARasterWriter&& m):
|
||||
m_layers_rst(std::move(m.m_layers_rst)),
|
||||
m_res(m.m_res),
|
||||
m_pxdim(m.m_pxdim),
|
||||
m_exp_time_s(m.m_exp_time_s),
|
||||
m_exp_time_first_s(m.m_exp_time_first_s),
|
||||
m_layer_height(m.m_layer_height),
|
||||
m_o(m.m_o),
|
||||
m_mirror(std::move(m.m_mirror)),
|
||||
m_gamma(m.m_gamma),
|
||||
m_used_material(m.m_used_material),
|
||||
m_cnt_fade_layers(m.m_cnt_fade_layers),
|
||||
m_cnt_slow_layers(m.m_cnt_slow_layers),
|
||||
m_cnt_fast_layers(m.m_cnt_fast_layers)
|
||||
{}
|
||||
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
SLARasterWriter(SLARasterWriter&& m) = default;
|
||||
SLARasterWriter& operator=(SLARasterWriter&&) = default;
|
||||
|
||||
inline void layers(unsigned cnt) { if(cnt > 0) m_layers_rst.resize(cnt); }
|
||||
inline unsigned layers() const { return unsigned(m_layers_rst.size()); }
|
||||
|
||||
template<class Poly> void draw_polygon(const Poly& p, unsigned lyr) {
|
||||
template<class Poly> void draw_polygon(const Poly& p, unsigned lyr,
|
||||
Orientation o = roPortrait)
|
||||
{
|
||||
assert(lyr < m_layers_rst.size());
|
||||
if(m_o == roPortrait) {
|
||||
Poly poly(p); flpXY(poly);
|
||||
|
||||
switch (o) {
|
||||
case roPortrait: {
|
||||
Poly poly(p);
|
||||
flpXY(poly);
|
||||
m_layers_rst[lyr].raster.draw(poly);
|
||||
break;
|
||||
}
|
||||
case roLandscape:
|
||||
m_layers_rst[lyr].raster.draw(p);
|
||||
break;
|
||||
}
|
||||
else m_layers_rst[lyr].raster.draw(p);
|
||||
}
|
||||
|
||||
inline void begin_layer(unsigned lyr) {
|
||||
|
|
@ -156,9 +129,11 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void save(const std::string& fpath, const std::string& prjname = "");
|
||||
void save(const std::string &fpath, const std::string &prjname = "");
|
||||
|
||||
void set_statistics(const std::vector<double> statistics);
|
||||
void set_statistics(const PrintStatistics &statistics);
|
||||
|
||||
void set_config(const DynamicPrintConfig &cfg);
|
||||
};
|
||||
|
||||
} // namespace sla
|
||||
|
|
|
|||
|
|
@ -1381,9 +1381,9 @@ void SLAPrint::process()
|
|||
// Estimated printing time
|
||||
// A layers count o the highest object
|
||||
if (m_printer_input.size() == 0)
|
||||
m_print_statistics.estimated_print_time = "N/A";
|
||||
m_print_statistics.estimated_print_time = std::nan("");
|
||||
else
|
||||
m_print_statistics.estimated_print_time = get_time_dhms(float(estim_time));
|
||||
m_print_statistics.estimated_print_time = estim_time;
|
||||
|
||||
m_print_statistics.fast_layers_count = fast_layers;
|
||||
m_print_statistics.slow_layers_count = slow_layers;
|
||||
|
|
@ -1394,16 +1394,9 @@ void SLAPrint::process()
|
|||
// Rasterizing the model objects, and their supports
|
||||
auto rasterize = [this]() {
|
||||
if(canceled()) return;
|
||||
|
||||
{ // create a raster printer for the current print parameters
|
||||
double layerh = m_default_object_config.layer_height.getFloat();
|
||||
m_printer.reset(new sla::SLARasterWriter(m_printer_config,
|
||||
m_material_config,
|
||||
layerh));
|
||||
}
|
||||
|
||||
// Allocate space for all the layers
|
||||
sla::SLARasterWriter &printer = *m_printer;
|
||||
|
||||
// Set up the printer, allocate space for all the layers
|
||||
sla::SLARasterWriter &printer = init_printer();
|
||||
|
||||
auto lvlcnt = unsigned(m_printer_input.size());
|
||||
printer.layers(lvlcnt);
|
||||
|
|
@ -1422,10 +1415,12 @@ void SLAPrint::process()
|
|||
double dstatus = m_report_status.status();
|
||||
|
||||
SpinMutex slck;
|
||||
|
||||
auto orientation = get_printer_orientation();
|
||||
|
||||
// procedure to process one height level. This will run in parallel
|
||||
auto lvlfn =
|
||||
[this, &slck, &printer, increment, &dstatus, &pst]
|
||||
[this, &slck, &printer, increment, &dstatus, &pst, orientation]
|
||||
(unsigned level_id)
|
||||
{
|
||||
if(canceled()) return;
|
||||
|
|
@ -1436,7 +1431,7 @@ void SLAPrint::process()
|
|||
printer.begin_layer(level_id);
|
||||
|
||||
for(const ClipperLib::Polygon& poly : printlayer.transformed_slices())
|
||||
printer.draw_polygon(poly, level_id);
|
||||
printer.draw_polygon(poly, level_id, orientation);
|
||||
|
||||
// Finish the layer for later saving it.
|
||||
printer.finish_layer(level_id);
|
||||
|
|
@ -1464,12 +1459,18 @@ void SLAPrint::process()
|
|||
tbb::parallel_for<unsigned, decltype(lvlfn)>(0, lvlcnt, lvlfn);
|
||||
|
||||
// Set statistics values to the printer
|
||||
m_printer->set_statistics(
|
||||
{(m_print_statistics.objects_used_material
|
||||
+ m_print_statistics.support_used_material) / 1000,
|
||||
double(m_default_object_config.faded_layers.getInt()),
|
||||
double(m_print_statistics.slow_layers_count),
|
||||
double(m_print_statistics.fast_layers_count)});
|
||||
sla::SLARasterWriter::PrintStatistics stats;
|
||||
stats.used_material = (m_print_statistics.objects_used_material +
|
||||
m_print_statistics.support_used_material) /
|
||||
1000;
|
||||
|
||||
int num_fade = m_default_object_config.faded_layers.getInt();
|
||||
stats.num_fade = num_fade >= 0 ? size_t(num_fade) : size_t(0);
|
||||
stats.num_fast = m_print_statistics.fast_layers_count;
|
||||
stats.num_slow = m_print_statistics.slow_layers_count;
|
||||
stats.estimated_print_time_s = m_print_statistics.estimated_print_time;
|
||||
|
||||
m_printer->set_statistics(stats);
|
||||
};
|
||||
|
||||
using slaposFn = std::function<void(SLAPrintObject&)>;
|
||||
|
|
@ -1653,6 +1654,39 @@ bool SLAPrint::invalidate_state_by_config_options(const std::vector<t_config_opt
|
|||
return invalidated;
|
||||
}
|
||||
|
||||
sla::SLARasterWriter & SLAPrint::init_printer()
|
||||
{
|
||||
sla::Raster::Resolution res;
|
||||
sla::Raster::PixelDim pxdim;
|
||||
std::array<bool, 2> mirror;
|
||||
double gamma;
|
||||
|
||||
double w = m_printer_config.display_width.getFloat();
|
||||
double h = m_printer_config.display_height.getFloat();
|
||||
auto pw = size_t(m_printer_config.display_pixels_x.getInt());
|
||||
auto ph = size_t(m_printer_config.display_pixels_y.getInt());
|
||||
|
||||
mirror[X] = m_printer_config.display_mirror_x.getBool();
|
||||
mirror[Y] = m_printer_config.display_mirror_y.getBool();
|
||||
|
||||
if (get_printer_orientation() == sla::SLARasterWriter::roPortrait) {
|
||||
std::swap(w, h);
|
||||
std::swap(pw, ph);
|
||||
|
||||
// XY flipping implicitly does an X mirror
|
||||
mirror[X] = !mirror[X];
|
||||
}
|
||||
|
||||
res = sla::Raster::Resolution{pw, ph};
|
||||
pxdim = sla::Raster::PixelDim{w / pw, h / ph};
|
||||
|
||||
gamma = m_printer_config.gamma_correction.getFloat();
|
||||
|
||||
m_printer.reset(new sla::SLARasterWriter(res, pxdim, mirror, gamma));
|
||||
m_printer->set_config(m_full_print_config);
|
||||
return *m_printer;
|
||||
}
|
||||
|
||||
// Returns true if an object step is done on all objects and there's at least one object.
|
||||
bool SLAPrint::is_step_done(SLAPrintObjectStep step) const
|
||||
{
|
||||
|
|
@ -1932,7 +1966,7 @@ std::vector<sla::SupportPoint> SLAPrintObject::transformed_support_points() cons
|
|||
DynamicConfig SLAPrintStatistics::config() const
|
||||
{
|
||||
DynamicConfig config;
|
||||
const std::string print_time = Slic3r::short_time(this->estimated_print_time);
|
||||
const std::string print_time = Slic3r::short_time(get_time_dhms(float(this->estimated_print_time)));
|
||||
config.set_key_value("print_time", new ConfigOptionString(print_time));
|
||||
config.set_key_value("objects_used_material", new ConfigOptionFloat(this->objects_used_material));
|
||||
config.set_key_value("support_used_material", new ConfigOptionFloat(this->support_used_material));
|
||||
|
|
|
|||
|
|
@ -300,7 +300,7 @@ class TriangleMesh;
|
|||
struct SLAPrintStatistics
|
||||
{
|
||||
SLAPrintStatistics() { clear(); }
|
||||
std::string estimated_print_time;
|
||||
double estimated_print_time;
|
||||
double objects_used_material;
|
||||
double support_used_material;
|
||||
size_t slow_layers_count;
|
||||
|
|
@ -316,7 +316,7 @@ struct SLAPrintStatistics
|
|||
std::string finalize_output_path(const std::string &path_in) const;
|
||||
|
||||
void clear() {
|
||||
estimated_print_time.clear();
|
||||
estimated_print_time = 0.;
|
||||
objects_used_material = 0.;
|
||||
support_used_material = 0.;
|
||||
slow_layers_count = 0;
|
||||
|
|
@ -458,6 +458,16 @@ private:
|
|||
|
||||
double status() const { return m_st; }
|
||||
} m_report_status;
|
||||
|
||||
sla::SLARasterWriter &init_printer();
|
||||
|
||||
inline sla::SLARasterWriter::Orientation get_printer_orientation() const
|
||||
{
|
||||
auto ro = m_printer_config.display_orientation.getInt();
|
||||
return ro == sla::SLARasterWriter::roPortrait ?
|
||||
sla::SLARasterWriter::roPortrait :
|
||||
sla::SLARasterWriter::roLandscape;
|
||||
}
|
||||
|
||||
friend SLAPrintObject;
|
||||
};
|
||||
|
|
|
|||
118
src/libslic3r/Time.cpp
Normal file
118
src/libslic3r/Time.cpp
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
#include "Time.hpp"
|
||||
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <chrono>
|
||||
|
||||
//#include <boost/date_time/local_time/local_time.hpp>
|
||||
//#include <boost/chrono.hpp>
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#undef WIN32_LEAN_AND_MEAN
|
||||
#endif /* WIN32 */
|
||||
|
||||
namespace Slic3r {
|
||||
namespace Utils {
|
||||
|
||||
namespace {
|
||||
|
||||
// FIXME: after we switch to gcc > 4.9 on the build server, please remove me
|
||||
#if defined(__GNUC__) && __GNUC__ <= 4
|
||||
std::string put_time(const std::tm *tm, const char *fmt)
|
||||
{
|
||||
static const constexpr int MAX_CHARS = 200;
|
||||
char out[MAX_CHARS];
|
||||
std::strftime(out, MAX_CHARS, fmt, tm);
|
||||
return out;
|
||||
}
|
||||
#else
|
||||
auto put_time(const std::tm *tm, const char *fmt) -> decltype (std::put_time(tm, fmt))
|
||||
{
|
||||
return std::put_time(tm, fmt);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
time_t parse_time_ISO8601Z(const std::string &sdate)
|
||||
{
|
||||
int y, M, d, h, m, s;
|
||||
if (sscanf(sdate.c_str(), "%04d%02d%02dT%02d%02d%02dZ", &y, &M, &d, &h, &m, &s) != 6)
|
||||
return time_t(-1);
|
||||
struct tm tms;
|
||||
tms.tm_year = y - 1900; // Year since 1900
|
||||
tms.tm_mon = M - 1; // 0-11
|
||||
tms.tm_mday = d; // 1-31
|
||||
tms.tm_hour = h; // 0-23
|
||||
tms.tm_min = m; // 0-59
|
||||
tms.tm_sec = s; // 0-61 (0-60 in C++11)
|
||||
#ifdef WIN32
|
||||
return _mkgmtime(&tms);
|
||||
#else /* WIN32 */
|
||||
return timegm(&tms);
|
||||
#endif /* WIN32 */
|
||||
}
|
||||
|
||||
std::string format_time_ISO8601Z(time_t time)
|
||||
{
|
||||
struct tm tms;
|
||||
#ifdef WIN32
|
||||
gmtime_s(&tms, &time);
|
||||
#else
|
||||
gmtime_r(&time, &tms);
|
||||
#endif
|
||||
char buf[128];
|
||||
sprintf(buf, "%04d%02d%02dT%02d%02d%02dZ",
|
||||
tms.tm_year + 1900,
|
||||
tms.tm_mon + 1,
|
||||
tms.tm_mday,
|
||||
tms.tm_hour,
|
||||
tms.tm_min,
|
||||
tms.tm_sec);
|
||||
return buf;
|
||||
}
|
||||
|
||||
std::string format_local_date_time(time_t time)
|
||||
{
|
||||
struct tm tms;
|
||||
#ifdef WIN32
|
||||
// Converts a time_t time value to a tm structure, and corrects for the local time zone.
|
||||
localtime_s(&tms, &time);
|
||||
#else
|
||||
localtime_r(&time, &tms);
|
||||
#endif
|
||||
char buf[80];
|
||||
strftime(buf, 80, "%x %X", &tms);
|
||||
return buf;
|
||||
}
|
||||
|
||||
time_t get_current_time_utc()
|
||||
{
|
||||
using clk = std::chrono::system_clock;
|
||||
return clk::to_time_t(clk::now());
|
||||
}
|
||||
|
||||
static std::string tm2str(const std::tm *tm, const char *fmt)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << put_time(tm, fmt);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string time2str(const time_t &t, TimeZone zone, const char *fmt)
|
||||
{
|
||||
std::string ret;
|
||||
|
||||
switch (zone) {
|
||||
case TimeZone::local: ret = tm2str(std::localtime(&t), fmt); break;
|
||||
case TimeZone::utc: ret = tm2str(std::gmtime(&t), fmt) + " UTC"; break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
}; // namespace Utils
|
||||
}; // namespace Slic3r
|
||||
47
src/libslic3r/Time.hpp
Normal file
47
src/libslic3r/Time.hpp
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
#ifndef slic3r_Utils_Time_hpp_
|
||||
#define slic3r_Utils_Time_hpp_
|
||||
|
||||
#include <string>
|
||||
#include <ctime>
|
||||
|
||||
namespace Slic3r {
|
||||
namespace Utils {
|
||||
|
||||
// Utilities to convert an UTC time_t to/from an ISO8601 time format,
|
||||
// useful for putting timestamps into file and directory names.
|
||||
// Returns (time_t)-1 on error.
|
||||
time_t parse_time_ISO8601Z(const std::string &s);
|
||||
std::string format_time_ISO8601Z(time_t time);
|
||||
|
||||
// Format the date and time from an UTC time according to the active locales and a local time zone.
|
||||
// TODO: make sure time2str is a suitable replacement
|
||||
std::string format_local_date_time(time_t time);
|
||||
|
||||
// There is no gmtime() on windows.
|
||||
time_t get_current_time_utc();
|
||||
|
||||
const constexpr char *const SLIC3R_TIME_FMT = "%Y-%m-%d at %T";
|
||||
|
||||
enum class TimeZone { local, utc };
|
||||
|
||||
std::string time2str(const time_t &t, TimeZone zone, const char *fmt = SLIC3R_TIME_FMT);
|
||||
|
||||
inline std::string current_time2str(TimeZone zone, const char *fmt = SLIC3R_TIME_FMT)
|
||||
{
|
||||
return time2str(get_current_time_utc(), zone, fmt);
|
||||
}
|
||||
|
||||
inline std::string current_local_time2str(const char * fmt = SLIC3R_TIME_FMT)
|
||||
{
|
||||
return current_time2str(TimeZone::local, fmt);
|
||||
}
|
||||
|
||||
inline std::string current_utc_time2str(const char * fmt = SLIC3R_TIME_FMT)
|
||||
{
|
||||
return current_time2str(TimeZone::utc, fmt);
|
||||
}
|
||||
|
||||
}; // namespace Utils
|
||||
}; // namespace Slic3r
|
||||
|
||||
#endif /* slic3r_Utils_Time_hpp_ */
|
||||
|
|
@ -87,11 +87,9 @@ namespace PerlUtils {
|
|||
|
||||
std::string string_printf(const char *format, ...);
|
||||
|
||||
// Timestamp formatted for header_slic3r_generated().
|
||||
extern std::string timestamp_str();
|
||||
// Standard "generated by Slic3r version xxx timestamp xxx" header string,
|
||||
// to be placed at the top of Slic3r generated files.
|
||||
inline std::string header_slic3r_generated() { return std::string("generated by " SLIC3R_APP_NAME " " SLIC3R_VERSION " " ) + timestamp_str(); }
|
||||
std::string header_slic3r_generated();
|
||||
|
||||
// getpid platform wrapper
|
||||
extern unsigned get_current_pid();
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@
|
|||
#include <cstdarg>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "Time.hpp"
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#include <psapi.h>
|
||||
|
|
@ -29,7 +31,6 @@
|
|||
#include <boost/locale.hpp>
|
||||
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/date_time/local_time/local_time.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/nowide/fstream.hpp>
|
||||
|
|
@ -540,16 +541,9 @@ std::string string_printf(const char *format, ...)
|
|||
return res;
|
||||
}
|
||||
|
||||
|
||||
std::string timestamp_str()
|
||||
std::string header_slic3r_generated()
|
||||
{
|
||||
const auto now = boost::posix_time::second_clock::local_time();
|
||||
char buf[2048];
|
||||
sprintf(buf, "on %04d-%02d-%02d at %02d:%02d:%02d",
|
||||
// Local date in an ANSII format.
|
||||
int(now.date().year()), int(now.date().month()), int(now.date().day()),
|
||||
int(now.time_of_day().hours()), int(now.time_of_day().minutes()), int(now.time_of_day().seconds()));
|
||||
return buf;
|
||||
return std::string("generated by " SLIC3R_APP_NAME " " SLIC3R_VERSION " on " ) + Utils::current_utc_time2str();
|
||||
}
|
||||
|
||||
unsigned get_current_pid()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue