2019-05-18 20:45:24 +00:00
|
|
|
#ifndef SLARASTERWRITER_HPP
|
|
|
|
#define SLARASTERWRITER_HPP
|
|
|
|
|
|
|
|
// For png export of the sliced model
|
|
|
|
#include <fstream>
|
2019-09-11 10:13:59 +00:00
|
|
|
#include <string>
|
2019-05-18 20:45:24 +00:00
|
|
|
#include <sstream>
|
|
|
|
#include <vector>
|
2019-09-11 10:13:59 +00:00
|
|
|
#include <map>
|
2019-05-20 09:19:43 +00:00
|
|
|
#include <array>
|
2019-05-18 20:45:24 +00:00
|
|
|
|
|
|
|
#include "libslic3r/PrintConfig.hpp"
|
|
|
|
|
|
|
|
#include "SLARaster.hpp"
|
|
|
|
|
|
|
|
namespace Slic3r { namespace sla {
|
|
|
|
|
|
|
|
// Implementation for PNG raster output
|
|
|
|
// Be aware that if a large number of layers are allocated, it can very well
|
|
|
|
// exhaust the available memory especially on 32 bit platform.
|
|
|
|
// This class is designed to be used in parallel mode. Layers have an ID and
|
|
|
|
// each layer can be written and compressed independently (in parallel).
|
|
|
|
// At the end when all layers where written, the save method can be used to
|
|
|
|
// write out the result into a zipped archive.
|
|
|
|
class SLARasterWriter
|
|
|
|
{
|
|
|
|
public:
|
2019-09-11 10:13:59 +00:00
|
|
|
enum Orientation {
|
2019-05-18 20:45:24 +00:00
|
|
|
roLandscape,
|
|
|
|
roPortrait
|
|
|
|
};
|
|
|
|
|
|
|
|
// Used for addressing parameters of set_statistics()
|
2019-09-11 10:13:59 +00:00
|
|
|
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;
|
2019-05-18 20:45:24 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
// A struct to bind the raster image data and its compressed bytes together.
|
|
|
|
struct Layer {
|
|
|
|
Raster raster;
|
|
|
|
RawBytes rawbytes;
|
|
|
|
|
|
|
|
Layer() = default;
|
|
|
|
|
2019-09-11 10:13:59 +00:00
|
|
|
// 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;
|
2019-05-18 20:45:24 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// We will save the compressed PNG data into RawBytes type buffers in
|
|
|
|
// parallel. Later we can write every layer to the disk sequentially.
|
|
|
|
std::vector<Layer> m_layers_rst;
|
|
|
|
Raster::Resolution m_res;
|
|
|
|
Raster::PixelDim m_pxdim;
|
|
|
|
std::array<bool, 2> m_mirror;
|
|
|
|
double m_gamma;
|
2019-09-11 10:13:59 +00:00
|
|
|
|
|
|
|
std::map<std::string, std::string> m_config;
|
|
|
|
|
2019-05-18 20:45:24 +00:00
|
|
|
std::string createIniContent(const std::string& projectname) const;
|
|
|
|
|
|
|
|
static void flpXY(ClipperLib::Polygon& poly);
|
|
|
|
static void flpXY(ExPolygon& poly);
|
|
|
|
|
|
|
|
public:
|
2019-09-11 10:13:59 +00:00
|
|
|
SLARasterWriter(const Raster::Resolution &res,
|
|
|
|
const Raster::PixelDim &pixdim,
|
|
|
|
const std::array<bool, 2> &mirror,
|
|
|
|
double gamma = 1.);
|
2019-05-18 20:45:24 +00:00
|
|
|
|
|
|
|
SLARasterWriter(const SLARasterWriter& ) = delete;
|
|
|
|
SLARasterWriter& operator=(const SLARasterWriter&) = delete;
|
2019-09-11 10:13:59 +00:00
|
|
|
SLARasterWriter(SLARasterWriter&& m) = default;
|
|
|
|
SLARasterWriter& operator=(SLARasterWriter&&) = default;
|
2019-05-18 20:45:24 +00:00
|
|
|
|
|
|
|
inline void layers(unsigned cnt) { if(cnt > 0) m_layers_rst.resize(cnt); }
|
|
|
|
inline unsigned layers() const { return unsigned(m_layers_rst.size()); }
|
|
|
|
|
2019-09-11 10:13:59 +00:00
|
|
|
template<class Poly> void draw_polygon(const Poly& p, unsigned lyr,
|
|
|
|
Orientation o = roPortrait)
|
|
|
|
{
|
2019-05-18 20:45:24 +00:00
|
|
|
assert(lyr < m_layers_rst.size());
|
2019-09-11 10:13:59 +00:00
|
|
|
|
|
|
|
switch (o) {
|
|
|
|
case roPortrait: {
|
|
|
|
Poly poly(p);
|
|
|
|
flpXY(poly);
|
2019-05-18 20:45:24 +00:00
|
|
|
m_layers_rst[lyr].raster.draw(poly);
|
2019-09-11 10:13:59 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case roLandscape:
|
|
|
|
m_layers_rst[lyr].raster.draw(p);
|
|
|
|
break;
|
2019-05-18 20:45:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void begin_layer(unsigned lyr) {
|
|
|
|
if(m_layers_rst.size() <= lyr) m_layers_rst.resize(lyr+1);
|
|
|
|
m_layers_rst[lyr].raster.reset(m_res, m_pxdim, m_mirror, m_gamma);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void begin_layer() {
|
|
|
|
m_layers_rst.emplace_back();
|
|
|
|
m_layers_rst.front().raster.reset(m_res, m_pxdim, m_mirror, m_gamma);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void finish_layer(unsigned lyr_id) {
|
|
|
|
assert(lyr_id < m_layers_rst.size());
|
|
|
|
m_layers_rst[lyr_id].rawbytes =
|
|
|
|
m_layers_rst[lyr_id].raster.save(Raster::Format::PNG);
|
|
|
|
m_layers_rst[lyr_id].raster.reset();
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void finish_layer() {
|
|
|
|
if(!m_layers_rst.empty()) {
|
|
|
|
m_layers_rst.back().rawbytes =
|
|
|
|
m_layers_rst.back().raster.save(Raster::Format::PNG);
|
|
|
|
m_layers_rst.back().raster.reset();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-11 10:13:59 +00:00
|
|
|
void save(const std::string &fpath, const std::string &prjname = "");
|
2019-05-18 20:45:24 +00:00
|
|
|
|
2019-09-11 10:13:59 +00:00
|
|
|
void set_statistics(const PrintStatistics &statistics);
|
|
|
|
|
|
|
|
void set_config(const DynamicPrintConfig &cfg);
|
2019-05-18 20:45:24 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace sla
|
|
|
|
} // namespace Slic3r
|
|
|
|
|
|
|
|
#endif // SLARASTERWRITER_HPP
|