diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index a4366a717..7477a9736 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -13,6 +13,7 @@ // For png export of the sliced model #include +#include #include #include #include @@ -1256,41 +1257,79 @@ void Print::set_status(int percent, const std::string &message) template class FilePrinter { public: - void drawPolygon(const ExPolygon& p); - void finish(); + void drawPolygon(const ExPolygon& p, unsigned lyr); + void layers(unsigned layernum); + unsigned layers() const; + void beginLayer(unsigned layer); + void beginLayer(); + void finishLayer(unsigned layer); + void finishLayer(); void save(const std::string& path); }; template<> class FilePrinter { - std::unique_ptr rst_; + std::vector> layers_rst_; Raster::Resolution res_; Raster::PixelDim pxdim_; public: inline FilePrinter(unsigned width_px, unsigned height_px, - double width_mm, double height_mm): + double width_mm, double height_mm, + unsigned layer_cnt = 0): res_(width_px, height_px), - pxdim_(width_mm/width_px, height_mm/height_px) {} + pxdim_(width_mm/width_px, height_mm/height_px) { + layers(layer_cnt); + } FilePrinter(const FilePrinter& ) = delete; FilePrinter(FilePrinter&& m): - rst_(std::move(m.rst_)), + layers_rst_(std::move(m.layers_rst_)), res_(m.res_), pxdim_(m.pxdim_) {} - inline void drawPolygon(const Polygon& p) { - if(!rst_) rst_.reset(new Raster(res_, pxdim_)); - rst_->draw(p); + inline void layers(unsigned cnt) { if(cnt > 0) layers_rst_.resize(cnt); } + inline unsigned layers() const { return layers_rst_.size(); } + + inline void drawPolygon(const ExPolygon& p, unsigned lyr) { + assert(lyr_id < layers_rst_.size()); + layers_rst_[lyr].first.draw(p); } - inline void finish() { - rst_.reset(); + inline void beginLayer(unsigned lyr) { + if(layers_rst_.size() <= lyr) layers_rst_.resize(lyr+1); + layers_rst_[lyr].first.reset(res_, pxdim_); + } + + inline void beginLayer() { + layers_rst_.emplace_back(Raster(res_, pxdim_), std::stringstream()); + } + + inline void finishLayer(unsigned lyr_id) { + assert(lyr_id < layers_rst_.size()); + layers_rst_[lyr_id].first.save(layers_rst_[lyr_id].second); + layers_rst_[lyr_id].first.reset(); + } + + inline void finishLayer() { + if(!layers_rst_.empty()) { + layers_rst_.back().first.save(layers_rst_.back().second); + layers_rst_.back().first.reset(); + } } inline void save(const std::string& path) { - std::fstream out(path, std::fstream::out | std::fstream::binary); - rst_->save(out); - out.close(); + for(unsigned i = 0; i < layers_rst_.size(); i++) { + if(layers_rst_[i].second.rdbuf()->in_avail() > 0) { + std::string loc = path + "layer" + std::to_string(i) + ".pgm"; + std::fstream out(loc, std::fstream::out | std::fstream::binary); + if(out.good()) { + out << layers_rst_[i].second.rdbuf(); + } + out.close(); + layers_rst_[i].first.reset(); + layers_rst_[i].second.str(""); + } + } } }; @@ -1372,14 +1411,10 @@ void Print::print_to(std::string dirpath, Args...args) ExPolygons previous_layer_slices; auto print_bb = bounding_box(); - std::vector> printers; - printers.reserve(layers.size()); + FilePrinter printer(std::forward(args)...); + printer.layers(layers.size()); - for(unsigned i = 0; i < layers.size(); i++) { - printers.emplace_back(std::forward(args)...); - } - -#pragma omp parallel for +#pragma omp parallel for /*num_threads(8)*/ for(int layer_id = 0; layer_id < layers.size(); layer_id++) { Layer& l = *(layers[layer_id]); @@ -1393,7 +1428,12 @@ void Print::print_to(std::string dirpath, Args...args) ExPolygons current_layer_slices; - auto& printer = printers[layer_id]; + try { + printer.beginLayer(layer_id); + } catch(std::bad_alloc& ) { + printer.save(dir); + printer.beginLayer(layer_id); + } std::for_each(l.object()->_shifted_copies.begin(), l.object()->_shifted_copies.end(), @@ -1406,25 +1446,21 @@ void Print::print_to(std::string dirpath, Args...args) slice.translate(d.x, d.y); slice.translate(-print_bb.min.x, -print_bb.min.y); - printer.drawPolygon(slice.contour); - std::for_each(slice.holes.begin(), slice.holes.end(), - [&printer](const Polygon& hole){ - printer.drawPolygon(hole); - }); + printer.drawPolygon(slice, layer_id); current_layer_slices.push_back(slice); }); }); - printers[layer_id].save(dir + "layer" + std::to_string(layer_id) + ".ppm"); - printer.finish(); + printer.finishLayer(layer_id); + + std::cout << "processed layer: " << layer_id << " by thread: " + << omp_get_thread_num() << std::endl; -// std::cout << "processed layers: " << layer_id + 1 << std::endl; previous_layer_slices = current_layer_slices; } -// for(unsigned i = 0; i < printers.size(); i++) -// printers[i].save(dir + "layer" + std::to_string(i) + ".png"); + printer.save(dir); } void Print::print_to_png(std::string dirpath, long width_px, long height_px, diff --git a/xs/src/libslic3r/Rasterizer/Rasterizer.cpp b/xs/src/libslic3r/Rasterizer/Rasterizer.cpp index d4af2a6ca..bd27278ed 100644 --- a/xs/src/libslic3r/Rasterizer/Rasterizer.cpp +++ b/xs/src/libslic3r/Rasterizer/Rasterizer.cpp @@ -22,13 +22,13 @@ namespace Slic3r { class Raster::Impl { public: - using TBuffer = std::vector>; - using TPixelRenderer = agg::pixfmt_rgb24; + using TPixelRenderer = agg::pixfmt_gray8; // agg::pixfmt_rgb24; using TRawRenderer = agg::renderer_base; - using TRenderer = agg::renderer_primitives; using TPixel = TPixelRenderer::color_type; using TRawBuffer = agg::rendering_buffer; + using TBuffer = std::vector; + using TRendererAA = agg::renderer_scanline_aa_solid; static const TPixel ColorWhite; @@ -41,66 +41,36 @@ private: TRawBuffer rbuf_; TPixelRenderer pixfmt_; TRawRenderer raw_renderer_; + TRendererAA renderer_; public: inline Impl(const Raster::Resolution& res, const Raster::PixelDim &pd): resolution_(res), pxdim_(pd), buf_(res.pixels()), - rbuf_(reinterpret_cast(buf_.data()), - res.width_px, res.height_px, res.width_px*sizeof(TBuffer::value_type)), + rbuf_(reinterpret_cast(buf_.data()), + res.width_px, res.height_px, + res.width_px*TPixelRenderer::num_components), pixfmt_(rbuf_), - raw_renderer_(pixfmt_) + raw_renderer_(pixfmt_), + renderer_(raw_renderer_) { + renderer_.color(ColorWhite); + + // If we would like to play around with gamma + // ras.gamma(agg::gamma_power(1.0)); + clear(); } - void draw(const Polygon &p) { - TRendererAA ren_aa(raw_renderer_); + void draw(const ExPolygon &poly) { agg::rasterizer_scanline_aa<> ras; agg::scanline_p8 scanlines; - agg::path_storage paths; - -// ras.gamma(agg::gamma_power(1.0)); - - auto it = p.points.begin(); - auto itnext = std::next(it); - - { - double xf = std::round(it->x * SCALING_FACTOR/pxdim_.w_mm); - double yf = std::round(it->y * SCALING_FACTOR/pxdim_.h_mm); - double nxf = std::round(itnext->x * SCALING_FACTOR/pxdim_.w_mm); - double nyf = std::round(itnext->y * SCALING_FACTOR/pxdim_.h_mm); - - paths.move_to(xf, yf); - paths.line_to(nxf, nyf); - - ++it, ++itnext; - } - while(itnext != p.points.end() ) { -// double xf = std::round(it->x * SCALING_FACTOR/pxdim_.w_mm); -// double yf = std::round(it->y * SCALING_FACTOR/pxdim_.h_mm); -// auto x = renderer_.coord(xf); -// auto y = renderer_.coord(yf); - - double nxf = std::round(itnext->x * SCALING_FACTOR/pxdim_.w_mm); - double nyf = std::round(itnext->y * SCALING_FACTOR/pxdim_.h_mm); -// auto nx = renderer_.coord(nxf); -// auto ny = renderer_.coord(nyf); - -// renderer_.move_to(x, y); -// renderer_.line_to(nx, ny); - -// paths.move_to(xf, yf); - paths.line_to(nxf, nyf); - - /*++it,*/ ++itnext; + ras.add_path(to_path(poly.contour)); + for(auto h : poly.holes) { + ras.add_path(to_path(h)); } - paths.close_polygon(); - ras.add_path(paths); - - ren_aa.color(ColorWhite); - agg::render_scanlines(ras, scanlines, ren_aa); + agg::render_scanlines(ras, scanlines, renderer_); } inline void clear() { @@ -110,14 +80,37 @@ public: inline const TBuffer& buffer() const { return buf_; } inline const Raster::Resolution resolution() { return resolution_; } + +private: + double getPx(const Point& p) { + return p.x * SCALING_FACTOR/pxdim_.w_mm; + } + + double getPy(const Point& p) { + return p.y * SCALING_FACTOR/pxdim_.h_mm; + } + + agg::path_storage to_path(const Polygon& poly) { + agg::path_storage path; + auto it = poly.points.begin(); + path.move_to(getPx(*it), getPy(*it)); + while(++it != poly.points.end()) + path.line_to(getPx(*it), getPy(*it)); + + path.line_to(getPx(poly.points.front()), getPy(poly.points.front())); + return path; + } + }; -const Raster::Impl::TPixel Raster::Impl::ColorWhite = Raster::Impl::TPixel(255, 255, 255); -const Raster::Impl::TPixel Raster::Impl::ColorBlack = Raster::Impl::TPixel(0, 0, 0); +const Raster::Impl::TPixel Raster::Impl::ColorWhite = Raster::Impl::TPixel(255); +const Raster::Impl::TPixel Raster::Impl::ColorBlack = Raster::Impl::TPixel(0); Raster::Raster(const Resolution &r, const PixelDim &pd): impl_(new Impl(r, pd)) {} +Raster::Raster() {} + Raster::~Raster() {} Raster::Raster(const Raster &cpy) { @@ -127,30 +120,49 @@ Raster::Raster(const Raster &cpy) { Raster::Raster(Raster &&m): impl_(std::move(m.impl_)) {} +void Raster::reset(const Raster::Resolution &r, const Raster::PixelDim &pd) +{ + impl_.reset(new Impl(r, pd)); +} + +void Raster::reset() +{ + impl_.reset(); +} + +Raster::Resolution Raster::resolution() const +{ + if(impl_) return impl_->resolution(); + + return Resolution(0, 0); +} + void Raster::clear() { + assert(impl_); impl_->clear(); } -void Raster::draw(const Polygon &poly) +void Raster::draw(const ExPolygon &poly) { + assert(impl_); impl_->draw(poly); } void Raster::save(std::ostream& stream, Compression comp) { + assert(impl_); switch(comp) { - case Compression::RAW: case Compression::PNG: - stream << "P6 " + case Compression::RAW: + stream << "P5 " << impl_->resolution().width_px << " " << impl_->resolution().height_px << " " << "255 "; - - stream.write(reinterpret_cast(impl_->buffer().data()), - impl_->buffer().size()*sizeof(Impl::TBuffer::value_type)); - break; } + + stream.write(reinterpret_cast(impl_->buffer().data()), + impl_->buffer().size()*sizeof(Impl::TBuffer::value_type)); } } diff --git a/xs/src/libslic3r/Rasterizer/Rasterizer.hpp b/xs/src/libslic3r/Rasterizer/Rasterizer.hpp index d6b27ea82..31a1244ec 100644 --- a/xs/src/libslic3r/Rasterizer/Rasterizer.hpp +++ b/xs/src/libslic3r/Rasterizer/Rasterizer.hpp @@ -2,7 +2,7 @@ #define RASTERIZER_HPP #include -#include +#include namespace Slic3r { @@ -33,13 +33,20 @@ public: }; explicit Raster(const Resolution& r, const PixelDim& pd ); + Raster(); ~Raster(); Raster(const Raster& cpy); Raster(Raster&& m); + void reset(const Resolution& r, const PixelDim& pd); + + void reset(); + + Resolution resolution() const; + void clear(); - void draw(const Polygon& poly); + void draw(const ExPolygon& poly); void save(std::ostream& stream, Compression comp = Compression::RAW); };