mirror of
https://github.com/Dark98/SliceBeam.git
synced 2026-07-05 16:49:04 +00:00
Add CrossHatch Infill
This commit is contained in:
@@ -782,6 +782,8 @@ add_library(slic3r
|
|||||||
src/main/jni/libslic3r/Fill/FillBase.hpp
|
src/main/jni/libslic3r/Fill/FillBase.hpp
|
||||||
src/main/jni/libslic3r/Fill/FillConcentric.cpp
|
src/main/jni/libslic3r/Fill/FillConcentric.cpp
|
||||||
src/main/jni/libslic3r/Fill/FillConcentric.hpp
|
src/main/jni/libslic3r/Fill/FillConcentric.hpp
|
||||||
|
src/main/jni/libslic3r/Fill/FillCrossHatch.cpp
|
||||||
|
src/main/jni/libslic3r/Fill/FillCrossHatch.hpp
|
||||||
src/main/jni/libslic3r/Fill/FillEnsuring.cpp
|
src/main/jni/libslic3r/Fill/FillEnsuring.cpp
|
||||||
src/main/jni/libslic3r/Fill/FillEnsuring.hpp
|
src/main/jni/libslic3r/Fill/FillEnsuring.hpp
|
||||||
src/main/jni/libslic3r/Fill/FillHoneycomb.cpp
|
src/main/jni/libslic3r/Fill/FillHoneycomb.cpp
|
||||||
|
|||||||
@@ -657,6 +657,7 @@ Polylines Layer::generate_sparse_infill_polylines_for_anchoring(FillAdaptive::Oc
|
|||||||
case ipHoneycomb:
|
case ipHoneycomb:
|
||||||
case ip3DHoneycomb:
|
case ip3DHoneycomb:
|
||||||
case ipGyroid:
|
case ipGyroid:
|
||||||
|
case ipCrossHatch:
|
||||||
case ipHilbertCurve:
|
case ipHilbertCurve:
|
||||||
case ipArchimedeanChords:
|
case ipArchimedeanChords:
|
||||||
case ipOctagramSpiral: break;
|
case ipOctagramSpiral: break;
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
#include "FillAdaptive.hpp"
|
#include "FillAdaptive.hpp"
|
||||||
#include "FillLightning.hpp"
|
#include "FillLightning.hpp"
|
||||||
#include "FillEnsuring.hpp"
|
#include "FillEnsuring.hpp"
|
||||||
|
#include "FillCrossHatch.hpp"
|
||||||
|
|
||||||
#include <boost/log/trivial.hpp>
|
#include <boost/log/trivial.hpp>
|
||||||
|
|
||||||
@@ -60,6 +61,7 @@ Fill* Fill::new_from_type(const InfillPattern type)
|
|||||||
case ipSupportCubic: return new FillAdaptive::Filler();
|
case ipSupportCubic: return new FillAdaptive::Filler();
|
||||||
case ipSupportBase: return new FillSupportBase();
|
case ipSupportBase: return new FillSupportBase();
|
||||||
case ipLightning: return new FillLightning::Filler();
|
case ipLightning: return new FillLightning::Filler();
|
||||||
|
case ipCrossHatch: return new FillCrossHatch();
|
||||||
case ipEnsuring: return new FillEnsuring();
|
case ipEnsuring: return new FillEnsuring();
|
||||||
default: throw Slic3r::InvalidArgument("unknown type");
|
default: throw Slic3r::InvalidArgument("unknown type");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,206 @@
|
|||||||
|
#include "../ClipperUtils.hpp"
|
||||||
|
#include "../ShortestPath.hpp"
|
||||||
|
#include "../Surface.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
#include "FillBase.hpp"
|
||||||
|
#include "FillCrossHatch.hpp"
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
|
||||||
|
// CrossHatch Infill: alternates line direction by 90 degrees every few layers
|
||||||
|
// with transform layers between direction shifts.
|
||||||
|
|
||||||
|
static Pointfs generate_one_cycle(double progress, coordf_t period)
|
||||||
|
{
|
||||||
|
Pointfs out;
|
||||||
|
double offset = progress * 1. / 8. * period;
|
||||||
|
out.reserve(4);
|
||||||
|
out.push_back(Vec2d(0.25 * period - offset, offset));
|
||||||
|
out.push_back(Vec2d(0.25 * period + offset, offset));
|
||||||
|
out.push_back(Vec2d(0.75 * period - offset, -offset));
|
||||||
|
out.push_back(Vec2d(0.75 * period + offset, -offset));
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Polylines generate_transform_pattern(double inprogress, int direction, coordf_t ingrid_size, coordf_t inwidth, coordf_t inheight)
|
||||||
|
{
|
||||||
|
coordf_t width = inwidth;
|
||||||
|
coordf_t height = inheight;
|
||||||
|
coordf_t grid_size = ingrid_size * 2; // odd and even separately.
|
||||||
|
double progress = inprogress;
|
||||||
|
Polylines out_polylines;
|
||||||
|
|
||||||
|
Pointfs one_cycle_points = generate_one_cycle(progress, grid_size);
|
||||||
|
|
||||||
|
Polyline one_cycle;
|
||||||
|
one_cycle.points.reserve(one_cycle_points.size());
|
||||||
|
for (size_t i = 0; i < one_cycle_points.size(); i++)
|
||||||
|
one_cycle.points.push_back(Point(one_cycle_points[i]));
|
||||||
|
|
||||||
|
if (direction < 0) {
|
||||||
|
width = height;
|
||||||
|
height = inwidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
Polylines odd_polylines;
|
||||||
|
Polyline odd_poly;
|
||||||
|
int num_of_cycle = int(width / grid_size) + 2;
|
||||||
|
odd_poly.points.reserve(num_of_cycle * one_cycle.size());
|
||||||
|
|
||||||
|
for (int i = 0; i < num_of_cycle; i++) {
|
||||||
|
Polyline odd_points = Polyline(one_cycle);
|
||||||
|
odd_points.translate(Point(i * grid_size, 0.0));
|
||||||
|
odd_poly.points.insert(odd_poly.points.end(), odd_points.begin(), odd_points.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
int num_of_lines = int(height / grid_size) + 2;
|
||||||
|
odd_polylines.reserve(num_of_lines * odd_poly.size());
|
||||||
|
for (int i = 0; i < num_of_lines; i++) {
|
||||||
|
Polyline poly = odd_poly;
|
||||||
|
poly.translate(Point(0.0, grid_size * i));
|
||||||
|
odd_polylines.push_back(poly);
|
||||||
|
}
|
||||||
|
out_polylines.insert(out_polylines.end(), odd_polylines.begin(), odd_polylines.end());
|
||||||
|
|
||||||
|
Polylines even_polylines;
|
||||||
|
even_polylines.reserve(odd_polylines.size());
|
||||||
|
for (size_t i = 0; i < odd_polylines.size(); i++) {
|
||||||
|
Polyline even = odd_poly;
|
||||||
|
even.translate(Point(-0.5 * grid_size, (coordf_t(i) + 0.5) * grid_size));
|
||||||
|
even_polylines.push_back(even);
|
||||||
|
}
|
||||||
|
|
||||||
|
out_polylines.insert(out_polylines.end(), even_polylines.begin(), even_polylines.end());
|
||||||
|
|
||||||
|
if (direction < 0) {
|
||||||
|
for (Polyline &poly : out_polylines) {
|
||||||
|
for (Point &p : poly)
|
||||||
|
std::swap(p.x(), p.y());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return out_polylines;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Polylines generate_repeat_pattern(int direction, coordf_t grid_size, coordf_t inwidth, coordf_t inheight)
|
||||||
|
{
|
||||||
|
coordf_t width = inwidth;
|
||||||
|
coordf_t height = inheight;
|
||||||
|
Polylines out_polylines;
|
||||||
|
|
||||||
|
if (direction < 0) {
|
||||||
|
width = height;
|
||||||
|
height = inwidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
int num_of_lines = int(height / grid_size) + 1;
|
||||||
|
out_polylines.reserve(num_of_lines);
|
||||||
|
|
||||||
|
for (int i = 0; i < num_of_lines; i++) {
|
||||||
|
Polyline poly;
|
||||||
|
poly.points.reserve(2);
|
||||||
|
poly.append(Point(coordf_t(0), coordf_t(grid_size * i)));
|
||||||
|
poly.append(Point(width, coordf_t(grid_size * i)));
|
||||||
|
out_polylines.push_back(poly);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (direction < 0) {
|
||||||
|
for (Polyline &poly : out_polylines) {
|
||||||
|
for (Point &p : poly)
|
||||||
|
std::swap(p.x(), p.y());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return out_polylines;
|
||||||
|
}
|
||||||
|
|
||||||
|
// repeat_ratio defines the ratio between the height of repeat pattern and grid
|
||||||
|
static Polylines generate_infill_layers(coordf_t z_height, double repeat_ratio, coordf_t grid_size, coordf_t width, coordf_t height)
|
||||||
|
{
|
||||||
|
Polylines result;
|
||||||
|
coordf_t trans_layer_size = grid_size * 0.4;
|
||||||
|
coordf_t repeat_layer_size = grid_size * repeat_ratio;
|
||||||
|
z_height += repeat_layer_size / 2 + trans_layer_size;
|
||||||
|
coordf_t period = trans_layer_size + repeat_layer_size;
|
||||||
|
coordf_t remains = z_height - std::floor(z_height / period) * period;
|
||||||
|
coordf_t trans_z = remains - repeat_layer_size;
|
||||||
|
|
||||||
|
int phase = int(fmod(z_height, period * 2) - (period - 1)); // add epsilon
|
||||||
|
int direction = phase <= 0 ? -1 : 1;
|
||||||
|
|
||||||
|
if (trans_z < 0) {
|
||||||
|
result = generate_repeat_pattern(direction, grid_size, width, height);
|
||||||
|
} else {
|
||||||
|
double progress = fmod(trans_z, trans_layer_size) / trans_layer_size;
|
||||||
|
if (progress < 0.5)
|
||||||
|
result = generate_transform_pattern((progress + 0.1) * 2, direction, grid_size, width, height);
|
||||||
|
else
|
||||||
|
result = generate_transform_pattern((1.1 - progress) * 2, -1 * direction, grid_size, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FillCrossHatch::_fill_surface_single(
|
||||||
|
const FillParams ¶ms,
|
||||||
|
unsigned int thickness_layers,
|
||||||
|
const std::pair<float, Point> &direction,
|
||||||
|
ExPolygon expolygon,
|
||||||
|
Polylines &polylines_out)
|
||||||
|
{
|
||||||
|
(void)thickness_layers;
|
||||||
|
(void)direction;
|
||||||
|
|
||||||
|
if (params.density <= 0.f)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto infill_angle = float(this->angle);
|
||||||
|
if (std::abs(infill_angle) >= EPSILON)
|
||||||
|
expolygon.rotate(-infill_angle);
|
||||||
|
|
||||||
|
BoundingBox bb = expolygon.contour.bounding_box();
|
||||||
|
|
||||||
|
double density_adjusted = params.density;
|
||||||
|
coord_t line_spacing = coord_t(scale_(this->spacing) / density_adjusted);
|
||||||
|
|
||||||
|
if (params.density < 0.999f)
|
||||||
|
line_spacing = coord_t(line_spacing * 1.08);
|
||||||
|
|
||||||
|
bb.merge(align_to_grid(bb.min, Point(line_spacing * 4, line_spacing * 4)));
|
||||||
|
|
||||||
|
double repeat_ratio = 1.0;
|
||||||
|
if (params.density < 0.3f)
|
||||||
|
repeat_ratio = std::clamp(1.0 - std::exp(-5 * params.density), 0.2, 1.0);
|
||||||
|
|
||||||
|
Polylines polylines = generate_infill_layers(scale_(this->z), repeat_ratio, line_spacing, bb.size()(0), bb.size()(1));
|
||||||
|
|
||||||
|
for (Polyline &pl : polylines)
|
||||||
|
pl.translate(bb.min);
|
||||||
|
|
||||||
|
polylines = intersection_pl(polylines, to_polygons(expolygon));
|
||||||
|
|
||||||
|
if (!polylines.empty()) {
|
||||||
|
const double minlength = scale_(0.8 * this->spacing);
|
||||||
|
polylines.erase(std::remove_if(polylines.begin(), polylines.end(),
|
||||||
|
[minlength](const Polyline &pl) { return pl.length() < minlength; }),
|
||||||
|
polylines.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!polylines.empty()) {
|
||||||
|
const size_t infill_start_idx = polylines_out.size();
|
||||||
|
if (params.dont_connect())
|
||||||
|
append(polylines_out, chain_polylines(std::move(polylines)));
|
||||||
|
else
|
||||||
|
connect_infill(std::move(polylines), expolygon, polylines_out, this->spacing, params);
|
||||||
|
|
||||||
|
if (std::abs(infill_angle) >= EPSILON) {
|
||||||
|
for (auto it = polylines_out.begin() + infill_start_idx; it != polylines_out.end(); ++it)
|
||||||
|
it->rotate(infill_angle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Slic3r
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
#ifndef slic3r_FillCrossHatch_hpp_
|
||||||
|
#define slic3r_FillCrossHatch_hpp_
|
||||||
|
|
||||||
|
#include "../libslic3r.h"
|
||||||
|
|
||||||
|
#include "FillBase.hpp"
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
|
||||||
|
class FillCrossHatch : public Fill
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Fill *clone() const override { return new FillCrossHatch(*this); }
|
||||||
|
~FillCrossHatch() override {}
|
||||||
|
bool is_self_crossing() override { return false; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void _fill_surface_single(
|
||||||
|
const FillParams ¶ms,
|
||||||
|
unsigned int thickness_layers,
|
||||||
|
const std::pair<float, Point> &direction,
|
||||||
|
ExPolygon expolygon,
|
||||||
|
Polylines &polylines_out) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Slic3r
|
||||||
|
|
||||||
|
#endif // slic3r_FillCrossHatch_hpp_
|
||||||
@@ -136,6 +136,7 @@ static const t_config_enum_values s_keys_map_InfillPattern {
|
|||||||
{ "honeycomb", ipHoneycomb },
|
{ "honeycomb", ipHoneycomb },
|
||||||
{ "3dhoneycomb", ip3DHoneycomb },
|
{ "3dhoneycomb", ip3DHoneycomb },
|
||||||
{ "gyroid", ipGyroid },
|
{ "gyroid", ipGyroid },
|
||||||
|
{ "crosshatch", ipCrossHatch },
|
||||||
{ "hilbertcurve", ipHilbertCurve },
|
{ "hilbertcurve", ipHilbertCurve },
|
||||||
{ "archimedeanchords", ipArchimedeanChords },
|
{ "archimedeanchords", ipArchimedeanChords },
|
||||||
{ "octagramspiral", ipOctagramSpiral },
|
{ "octagramspiral", ipOctagramSpiral },
|
||||||
@@ -1486,6 +1487,7 @@ void PrintConfigDef::init_fff_params()
|
|||||||
{ "honeycomb", L("Honeycomb")},
|
{ "honeycomb", L("Honeycomb")},
|
||||||
{ "3dhoneycomb", L("3D Honeycomb")},
|
{ "3dhoneycomb", L("3D Honeycomb")},
|
||||||
{ "gyroid", L("Gyroid")},
|
{ "gyroid", L("Gyroid")},
|
||||||
|
{ "crosshatch", L("Cross Hatch")},
|
||||||
{ "hilbertcurve", L("Hilbert Curve")},
|
{ "hilbertcurve", L("Hilbert Curve")},
|
||||||
{ "archimedeanchords", L("Archimedean Chords")},
|
{ "archimedeanchords", L("Archimedean Chords")},
|
||||||
{ "octagramspiral", L("Octagram Spiral")},
|
{ "octagramspiral", L("Octagram Spiral")},
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ enum class ElegooBedType {
|
|||||||
enum InfillPattern : int {
|
enum InfillPattern : int {
|
||||||
ipRectilinear, ipMonotonic, ipMonotonicLines, ipAlignedRectilinear, ipGrid, ipTriangles, ipStars, ipCubic, ipLine, ipConcentric, ipHoneycomb, ip3DHoneycomb,
|
ipRectilinear, ipMonotonic, ipMonotonicLines, ipAlignedRectilinear, ipGrid, ipTriangles, ipStars, ipCubic, ipLine, ipConcentric, ipHoneycomb, ip3DHoneycomb,
|
||||||
ipGyroid, ipHilbertCurve, ipArchimedeanChords, ipOctagramSpiral, ipAdaptiveCubic, ipSupportCubic, ipSupportBase,
|
ipGyroid, ipHilbertCurve, ipArchimedeanChords, ipOctagramSpiral, ipAdaptiveCubic, ipSupportCubic, ipSupportBase,
|
||||||
ipLightning,
|
ipLightning, ipCrossHatch,
|
||||||
ipEnsuring,
|
ipEnsuring,
|
||||||
ipCount,
|
ipCount,
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user