#include "RasterToPolygons.hpp" #include "AGGRaster.hpp" #include "libslic3r/MarchingSquares.hpp" #include "MTUtils.hpp" #include "ClipperUtils.hpp" namespace marchsq { // Specialize this struct to register a raster type for the Marching squares alg template<> struct _RasterTraits { using Rst = Slic3r::sla::RasterGrayscaleAA; // The type of pixel cell in the raster using ValueType = uint8_t; // Value at a given position static uint8_t get(const Rst &rst, size_t row, size_t col) { return rst.read_pixel(col, row); } // Number of rows and cols of the raster static size_t rows(const Rst &rst) { return rst.resolution().height_px; } static size_t cols(const Rst &rst) { return rst.resolution().width_px; } }; } // namespace Slic3r::marchsq namespace Slic3r { namespace sla { template void foreach_vertex(ExPolygon &poly, Fn &&fn) { for (auto &p : poly.contour.points) fn(p); for (auto &h : poly.holes) for (auto &p : h.points) fn(p); } ExPolygons raster_to_polygons(const RasterGrayscaleAA &rst, Vec2i windowsize) { size_t rows = rst.resolution().height_px, cols = rst.resolution().width_px; if (rows < 2 || cols < 2) return {}; Polygons polys; long w_rows = std::max(2l, long(windowsize.y())); long w_cols = std::max(2l, long(windowsize.x())); std::vector rings = marchsq::execute(rst, 128, {w_rows, w_cols}); polys.reserve(rings.size()); auto pxd = rst.pixel_dimensions(); pxd.w_mm = (rst.resolution().width_px * pxd.w_mm) / (rst.resolution().width_px - 1); pxd.h_mm = (rst.resolution().height_px * pxd.h_mm) / (rst.resolution().height_px - 1); for (const marchsq::Ring &ring : rings) { Polygon poly; Points &pts = poly.points; pts.reserve(ring.size()); for (const marchsq::Coord &crd : ring) pts.emplace_back(scaled(crd.c * pxd.w_mm), scaled(crd.r * pxd.h_mm)); polys.emplace_back(poly); } // reverse the raster transformations ExPolygons unioned = union_ex(polys); coord_t width = scaled(cols * pxd.h_mm), height = scaled(rows * pxd.w_mm); auto tr = rst.trafo(); for (ExPolygon &expoly : unioned) { if (tr.mirror_y) foreach_vertex(expoly, [height](Point &p) {p.y() = height - p.y(); }); if (tr.mirror_x) foreach_vertex(expoly, [width](Point &p) {p.x() = width - p.x(); }); expoly.translate(-tr.center_x, -tr.center_y); if (tr.flipXY) foreach_vertex(expoly, [](Point &p) { std::swap(p.x(), p.y()); }); if ((tr.mirror_x + tr.mirror_y + tr.flipXY) % 2) { expoly.contour.reverse(); for (auto &h : expoly.holes) h.reverse(); } } return unioned; } }} // namespace Slic3r