Holes now printed correctly. export changed to pgm which is grayscale.
This commit is contained in:
parent
c3a944ef97
commit
d97939c012
3 changed files with 147 additions and 92 deletions
|
@ -13,6 +13,7 @@
|
|||
|
||||
// For png export of the sliced model
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <wx/dcmemory.h>
|
||||
#include <wx/bitmap.h>
|
||||
#include <wx/image.h>
|
||||
|
@ -1256,41 +1257,79 @@ void Print::set_status(int percent, const std::string &message)
|
|||
template<Print::FilePrinterFormat format>
|
||||
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<Print::FilePrinterFormat::PNG> {
|
||||
std::unique_ptr<Raster> rst_;
|
||||
std::vector<std::pair<Raster, std::stringstream>> 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<FilePrinter<format>> printers;
|
||||
printers.reserve(layers.size());
|
||||
FilePrinter<format> printer(std::forward<Args>(args)...);
|
||||
printer.layers(layers.size());
|
||||
|
||||
for(unsigned i = 0; i < layers.size(); i++) {
|
||||
printers.emplace_back(std::forward<Args>(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,
|
||||
|
|
|
@ -22,13 +22,13 @@ namespace Slic3r {
|
|||
|
||||
class Raster::Impl {
|
||||
public:
|
||||
using TBuffer = std::vector<std::array<std::uint8_t,3>>;
|
||||
using TPixelRenderer = agg::pixfmt_rgb24;
|
||||
using TPixelRenderer = agg::pixfmt_gray8; // agg::pixfmt_rgb24;
|
||||
using TRawRenderer = agg::renderer_base<TPixelRenderer>;
|
||||
using TRenderer = agg::renderer_primitives<TRawRenderer>;
|
||||
using TPixel = TPixelRenderer::color_type;
|
||||
using TRawBuffer = agg::rendering_buffer;
|
||||
|
||||
using TBuffer = std::vector<TPixelRenderer::pixel_type>;
|
||||
|
||||
using TRendererAA = agg::renderer_scanline_aa_solid<TRawRenderer>;
|
||||
|
||||
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<std::uint8_t*>(buf_.data()),
|
||||
res.width_px, res.height_px, res.width_px*sizeof(TBuffer::value_type)),
|
||||
rbuf_(reinterpret_cast<TPixelRenderer::value_type*>(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<const char*>(impl_->buffer().data()),
|
||||
impl_->buffer().size()*sizeof(Impl::TBuffer::value_type));
|
||||
break;
|
||||
}
|
||||
|
||||
stream.write(reinterpret_cast<const char*>(impl_->buffer().data()),
|
||||
impl_->buffer().size()*sizeof(Impl::TBuffer::value_type));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#define RASTERIZER_HPP
|
||||
|
||||
#include <ostream>
|
||||
#include <Polygon.hpp>
|
||||
#include <ExPolygon.hpp>
|
||||
|
||||
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);
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue