From 8194f9fb9684046b26162ae7d97628d3542ed8f4 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Tue, 21 Aug 2018 13:20:43 +0200 Subject: [PATCH] Edges now smoothed on the sides. --- xs/src/libslic3r/SLABasePool.cpp | 331 ++++++++++++++++++------------- 1 file changed, 198 insertions(+), 133 deletions(-) diff --git a/xs/src/libslic3r/SLABasePool.cpp b/xs/src/libslic3r/SLABasePool.cpp index 8923064ed..fb46a7296 100644 --- a/xs/src/libslic3r/SLABasePool.cpp +++ b/xs/src/libslic3r/SLABasePool.cpp @@ -118,35 +118,6 @@ inline Contour3D walls(const ExPolygon& floor_plate, const ExPolygon& ceiling, return ret; } -/// Generating the concave part of the 3D pool with the bottom plate and the -/// side walls. -inline Contour3D inner_bed(const ExPolygon& poly, coord_t depth) { - Polygons triangles; - poly.triangulate_p2t(&triangles); - - auto bottom = convert(triangles, -depth, false); - auto lines = poly.lines(); - - // Generate outer walls - auto fp = [](const Point& p, Point::coord_type z) { - return Pointf3::new_unscale(x(p), y(p), z); - }; - - for(auto& l : lines) { - auto s = coord_t(bottom.points.size()); - - bottom.points.emplace_back(fp(l.a, -depth)); - bottom.points.emplace_back(fp(l.b, -depth)); - bottom.points.emplace_back(fp(l.a, 0)); - bottom.points.emplace_back(fp(l.b, 0)); - - bottom.indices.emplace_back(s, s + 1, s + 3); - bottom.indices.emplace_back(s, s + 3, s + 2); - } - - return bottom; -} - /// Mesh from an existing contour. inline TriangleMesh mesh(const Contour3D& ctour) { return {ctour.points, ctour.indices}; @@ -211,6 +182,89 @@ inline void offset(ExPolygon& sh, coord_t distance) { } } +template +inline Contour3D round_edges(const ExPolygon& base_plate, + double radius_mm, + double degrees, + double ceilheight_mm, + bool dir, + ExP&& last_offset = ExP(), D&& last_height = D()) +{ + auto ob = base_plate; + auto ob_prev = ob; + double wh = ceilheight_mm, wh_prev = wh; + Contour3D curvedwalls; + + const size_t steps = 6; // steps for 180 degrees + degrees = std::fmod(degrees, 180); + const int portion = int(steps*degrees / 90); + const double ystep_mm = radius_mm/steps; + coord_t s = dir? 1 : -1; + for(int i = 0; i < portion; i++) { + ob = base_plate; + + // The offset is given by the equation: x = sqrt(r^2 - y^2) + // which can be derived from the circle equation. y is the current + // height for which the offset is calculated and x is the offset itself + // r is the radius of the circle that is used to smooth the edges + + double r2 = radius_mm * radius_mm; + double y2 = steps*ystep_mm - i*ystep_mm; + y2 *= y2; + + double xx = sqrt(r2 - y2); + + offset(ob, s*mm(xx)); + wh = ceilheight_mm - i*ystep_mm; + + Contour3D pwalls; + pwalls = walls(ob, ob_prev, wh, wh_prev); + + curvedwalls.merge(pwalls); + ob_prev = ob; + wh_prev = wh; + } + + last_offset = std::move(ob); + last_height = wh; + + return curvedwalls; +} + +/// Generating the concave part of the 3D pool with the bottom plate and the +/// side walls. +inline Contour3D inner_bed(const ExPolygon& poly, double depth_mm, + double begin_h_mm = 0) { + + Polygons triangles; + poly.triangulate_p2t(&triangles); + + coord_t depth = mm(depth_mm); + coord_t begin_h = mm(begin_h_mm); + + auto bottom = convert(triangles, -depth + begin_h, false); + auto lines = poly.lines(); + + // Generate outer walls + auto fp = [](const Point& p, Point::coord_type z) { + return Pointf3::new_unscale(x(p), y(p), z); + }; + + for(auto& l : lines) { + auto s = coord_t(bottom.points.size()); + + bottom.points.emplace_back(fp(l.a, -depth + begin_h)); + bottom.points.emplace_back(fp(l.b, -depth + begin_h)); + bottom.points.emplace_back(fp(l.a, begin_h)); + bottom.points.emplace_back(fp(l.b, begin_h)); + + bottom.indices.emplace_back(s, s + 1, s + 3); + bottom.indices.emplace_back(s, s + 3, s + 2); + } + + return bottom; +} + /// Unification of polygons (with clipper) preserving holes as well. inline ExPolygons unify(const ExPolygons& shapes) { ExPolygons retv; @@ -361,116 +415,127 @@ void create_base_pool(const ExPolygons &ground_layer, TriangleMesh& out, double min_wall_thickness_mm, double min_wall_height_mm) { - Contour3D pool; - - auto& poly = ground_layer.front(); - auto floor_poly = poly; - offset(floor_poly, mm(5)); - - Polygons floor_plate; - floor_poly.triangulate_p2t(&floor_plate); - auto floor_mesh = convert(floor_plate, mm(20), false); - pool.merge(floor_mesh); - - Polygons ceil_plate; - poly.triangulate_p2t(&ceil_plate); - auto ceil_mesh = convert(ceil_plate, mm(0), true); - pool.merge(ceil_mesh); - - auto ob = floor_poly; - auto ob_prev = ob; - double wh = 20, wh_prev = wh; - Contour3D curvedwalls; - - const size_t steps = 6; - const double radius_mm = 1; - const double ystep_mm = radius_mm/steps; - const double ceilheight_mm = 20; - for(int i = 0; i < 1.5*steps; i++) { - ob = floor_poly; - - // The offset is given by the equation: x = sqrt(r^2 - y^2) - // which can be derived from the circle equation. y is the current - // height for which the offset is calculated and x is the offset itself - // r is the radius of the circle that is used to smooth the edges - - double r2 = radius_mm * radius_mm; - double y2 = steps*ystep_mm - i*ystep_mm; - y2 *= y2; - - double x = sqrt(r2 - y2); - offset(ob, mm(x)); - wh = ceilheight_mm - i*ystep_mm; - - Contour3D pwalls; - pwalls = walls(ob, ob_prev, wh, wh_prev); - - curvedwalls.merge(pwalls); - ob_prev = ob; - wh_prev = wh; - } - - auto w = walls(ob, poly, wh, 0); - - pool.merge(w); - pool.merge(curvedwalls); - - out = mesh(pool); - -// auto concaveh = concave_hull(ground_layer); -// if(concaveh.contour.points.empty()) return; -// concaveh.holes.clear(); - -// BoundingBox bb(concaveh); -// coord_t w = bb.max.x - bb.min.x; -// coord_t h = bb.max.y - bb.min.y; - -// auto wall_thickness = coord_t(std::pow((w+h)*0.1, 0.8)); - -// const coord_t WALL_THICKNESS = mm(min_wall_thickness_mm) + wall_thickness; -// const coord_t WALL_DISTANCE = coord_t(0.3*WALL_THICKNESS); -// const coord_t HEIGHT = mm(min_wall_height_mm); - -// auto outer_base = concaveh; -// offset(outer_base, WALL_THICKNESS+WALL_DISTANCE); -// auto inner_base = outer_base; -// offset(inner_base, -WALL_THICKNESS); -// inner_base.holes.clear(); outer_base.holes.clear(); - -// ExPolygon top_poly; -// top_poly.contour = outer_base.contour; -// top_poly.holes.emplace_back(inner_base.contour); -// auto& tph = top_poly.holes.back().points; -// std::reverse(tph.begin(), tph.end()); - // Contour3D pool; -// auto pwalls = walls(outer_base, inner_base, 0, - min_wall_height_mm); -// pool.merge(pwalls); -//// auto ob = outer_base; -//// auto ob_prev = ob; -//// double wh = 0, wh_prev = h; -//// for(int i = 1; i <= 4; i++) { -//// offset(ob, mm(0.0002)); -//// wh = wh_prev - 0.0002; -//// auto poolwalls = walls(ob, ob_prev, wh, wh_prev); -//// pool.merge(poolwalls); -//// ob_prev = ob; -//// wh_prev = wh; -//// } +// auto& poly = ground_layer.front(); +// auto floor_poly = poly; +// offset(floor_poly, mm(5)); -// Polygons top_triangles, bottom_triangles; -// top_poly.triangulate_p2t(&top_triangles); -// inner_base.triangulate_p2t(&bottom_triangles); -// auto top_plate = convert(top_triangles, 0, false); -// auto bottom_plate = convert(bottom_triangles, -HEIGHT, true); -// auto innerbed = inner_bed(inner_base, HEIGHT/2); +// Polygons floor_plate; +// floor_poly.triangulate_p2t(&floor_plate); +// auto floor_mesh = convert(floor_plate, mm(20), false); +// pool.merge(floor_mesh); -// pool.merge(top_plate); -// pool.merge(bottom_plate); -// pool.merge(innerbed); +// Polygons ceil_plate; +// poly.triangulate_p2t(&ceil_plate); +// auto ceil_mesh = convert(ceil_plate, mm(0), true); +// pool.merge(ceil_mesh); + +// auto ob = floor_poly; +// auto ob_prev = ob; +// double wh = 20, wh_prev = wh; +// Contour3D curvedwalls; + +// const size_t steps = 6; +// const double radius_mm = 1; +// const double ystep_mm = radius_mm/steps; +// const double ceilheight_mm = 20; +// for(int i = 0; i < 1.5*steps; i++) { +// ob = floor_poly; + +// // The offset is given by the equation: x = sqrt(r^2 - y^2) +// // which can be derived from the circle equation. y is the current +// // height for which the offset is calculated and x is the offset itself +// // r is the radius of the circle that is used to smooth the edges + +// double r2 = radius_mm * radius_mm; +// double y2 = steps*ystep_mm - i*ystep_mm; +// y2 *= y2; + +// double x = sqrt(r2 - y2); +// offset(ob, mm(x)); +// wh = ceilheight_mm - i*ystep_mm; + +// Contour3D pwalls; +// pwalls = walls(ob, ob_prev, wh, wh_prev); + +// curvedwalls.merge(pwalls); +// ob_prev = ob; +// wh_prev = wh; +// } + +// auto w = walls(ob, poly, wh, 0); + +// pool.merge(w); +// pool.merge(curvedwalls); // out = mesh(pool); + + auto concaveh = concave_hull(ground_layer); + if(concaveh.contour.points.empty()) return; + concaveh.holes.clear(); + + BoundingBox bb(concaveh); + coord_t w = bb.max.x - bb.min.x; + coord_t h = bb.max.y - bb.min.y; + + auto wall_thickness = coord_t(std::pow((w+h)*0.1, 0.8)); + + const coord_t WALL_THICKNESS = mm(min_wall_thickness_mm) + wall_thickness; + const coord_t WALL_DISTANCE = coord_t(0.3*WALL_THICKNESS); + const coord_t HEIGHT = mm(min_wall_height_mm); + + auto outer_base = concaveh; + offset(outer_base, WALL_THICKNESS+WALL_DISTANCE); + auto inner_base = outer_base; + offset(inner_base, -WALL_THICKNESS); + inner_base.holes.clear(); outer_base.holes.clear(); + + ExPolygon top_poly; + top_poly.contour = outer_base.contour; + top_poly.holes.emplace_back(inner_base.contour); + auto& tph = top_poly.holes.back().points; + std::reverse(tph.begin(), tph.end()); + + Contour3D pool; + + ExPolygon ob = outer_base; double wh = 0; + auto curvedwalls = round_edges(ob, + 1, // radius 1 mm + 170, // 170 degrees + 0, // z position of the input plane + true, + ob, wh); + pool.merge(curvedwalls); + + ExPolygon ob_contr = ob; + ob_contr.holes.clear(); + + auto pwalls = walls(ob_contr, inner_base, wh, -min_wall_height_mm); + pool.merge(pwalls); + + Polygons top_triangles, bottom_triangles; + top_poly.triangulate_p2t(&top_triangles); + inner_base.triangulate_p2t(&bottom_triangles); + auto top_plate = convert(top_triangles, 0, false); + auto bottom_plate = convert(bottom_triangles, -HEIGHT, true); + + ob = inner_base; wh = 0; + curvedwalls = round_edges(ob, + 1, // radius 1 mm + 90, // 170 degrees + 0, // z position of the input plane + false, + ob, wh); + pool.merge(curvedwalls); + + auto innerbed = inner_bed(ob, min_wall_height_mm/2 + wh, wh); + + pool.merge(top_plate); + pool.merge(bottom_plate); + pool.merge(innerbed); + + out = mesh(pool); } }