#include "../ClipperUtils.hpp" #include "../ExPolygon.hpp" #include "../Surface.hpp" #include "FillConcentric.hpp" namespace Slic3r { void FillConcentric::_fill_surface_single( const FillParams ¶ms, unsigned int thickness_layers, const std::pair &direction, ExPolygon &expolygon, Polylines &polylines_out) { // no rotation is supported for this infill pattern BoundingBox bounding_box = expolygon.contour.bounding_box(); coord_t min_spacing = scale_(this->spacing); coord_t distance = coord_t(min_spacing / params.density); if (params.density > 0.9999f && !params.dont_adjust) { distance = this->_adjust_solid_spacing(bounding_box.size()(0), distance); this->spacing = unscale(distance); } Polygons loops = (Polygons)expolygon; Polygons last = loops; while (! last.empty()) { last = offset2(last, -(distance + min_spacing/2), +min_spacing/2); loops.insert(loops.end(), last.begin(), last.end()); } // generate paths from the outermost to the innermost, to avoid // adhesion problems of the first central tiny loops loops = union_pt_chained(loops, false); // split paths using a nearest neighbor search size_t iPathFirst = polylines_out.size(); Point last_pos(0, 0); for (const Polygon &loop : loops) { polylines_out.push_back(loop.split_at_index(last_pos.nearest_point_index(loop))); last_pos = polylines_out.back().last_point(); } // clip the paths to prevent the extruder from getting exactly on the first point of the loop // Keep valid paths only. size_t j = iPathFirst; for (size_t i = iPathFirst; i < polylines_out.size(); ++ i) { polylines_out[i].clip_end(this->loop_clipping); if (polylines_out[i].is_valid()) { if (j < i) polylines_out[j] = std::move(polylines_out[i]); ++ j; } } if (j < polylines_out.size()) polylines_out.erase(polylines_out.begin() + j, polylines_out.end()); //TODO: return ExtrusionLoop objects to get better chained paths, // otherwise the outermost loop starts at the closest point to (0, 0). // We want the loops to be split inside the G-code generator to get optimum path planning. } } // namespace Slic3r