1 #include "RasterToPolygons.hpp"
2 
3 #include "AGGRaster.hpp"
4 #include "libslic3r/MarchingSquares.hpp"
5 #include "MTUtils.hpp"
6 #include "ClipperUtils.hpp"
7 
8 namespace marchsq {
9 
10 // Specialize this struct to register a raster type for the Marching squares alg
11 template<> struct _RasterTraits<Slic3r::sla::RasterGrayscaleAA> {
12     using Rst = Slic3r::sla::RasterGrayscaleAA;
13 
14     // The type of pixel cell in the raster
15     using ValueType = uint8_t;
16 
17     // Value at a given position
getmarchsq::_RasterTraits18     static uint8_t get(const Rst &rst, size_t row, size_t col) { return rst.read_pixel(col, row); }
19 
20     // Number of rows and cols of the raster
rowsmarchsq::_RasterTraits21     static size_t rows(const Rst &rst) { return rst.resolution().height_px; }
colsmarchsq::_RasterTraits22     static size_t cols(const Rst &rst) { return rst.resolution().width_px; }
23 };
24 
25 } // namespace Slic3r::marchsq
26 
27 namespace Slic3r { namespace sla {
28 
foreach_vertex(ExPolygon & poly,Fn && fn)29 template<class Fn> void foreach_vertex(ExPolygon &poly, Fn &&fn)
30 {
31     for (auto &p : poly.contour.points) fn(p);
32     for (auto &h : poly.holes)
33         for (auto &p : h.points) fn(p);
34 }
35 
raster_to_polygons(const RasterGrayscaleAA & rst,Vec2i windowsize)36 ExPolygons raster_to_polygons(const RasterGrayscaleAA &rst, Vec2i windowsize)
37 {
38     size_t rows = rst.resolution().height_px, cols = rst.resolution().width_px;
39 
40     if (rows < 2 || cols < 2) return {};
41 
42     Polygons polys;
43     long w_rows = std::max(2l, long(windowsize.y()));
44     long w_cols = std::max(2l, long(windowsize.x()));
45 
46     std::vector<marchsq::Ring> rings =
47         marchsq::execute(rst, 128, {w_rows, w_cols});
48 
49     polys.reserve(rings.size());
50 
51     auto pxd = rst.pixel_dimensions();
52     pxd.w_mm = (rst.resolution().width_px * pxd.w_mm) / (rst.resolution().width_px - 1);
53     pxd.h_mm = (rst.resolution().height_px * pxd.h_mm) / (rst.resolution().height_px - 1);
54 
55     for (const marchsq::Ring &ring : rings) {
56         Polygon poly; Points &pts = poly.points;
57         pts.reserve(ring.size());
58 
59         for (const marchsq::Coord &crd : ring)
60             pts.emplace_back(scaled(crd.c * pxd.w_mm), scaled(crd.r * pxd.h_mm));
61 
62         polys.emplace_back(poly);
63     }
64 
65     // reverse the raster transformations
66     ExPolygons unioned = union_ex(polys);
67     coord_t width = scaled(cols * pxd.h_mm), height = scaled(rows * pxd.w_mm);
68 
69     auto tr = rst.trafo();
70     for (ExPolygon &expoly : unioned) {
71         if (tr.mirror_y)
72             foreach_vertex(expoly, [height](Point &p) {p.y() = height - p.y(); });
73 
74         if (tr.mirror_x)
75             foreach_vertex(expoly, [width](Point &p) {p.x() = width - p.x(); });
76 
77         expoly.translate(-tr.center_x, -tr.center_y);
78 
79         if (tr.flipXY)
80             foreach_vertex(expoly, [](Point &p) { std::swap(p.x(), p.y()); });
81 
82         if ((tr.mirror_x + tr.mirror_y + tr.flipXY) % 2) {
83             expoly.contour.reverse();
84             for (auto &h : expoly.holes) h.reverse();
85         }
86     }
87 
88     return unioned;
89 }
90 
91 }} // namespace Slic3r
92