mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-23 06:33:57 -06:00
Infill Line Multiplier (#9432)
* Infill Line Multiplier * Modular Offset Function * Lightning multiline * Crosshatch Multiline ipCrosshatch * cleaning Cleaning clean2 * 3d Honeycomb cut poliline ends * Fill Tpmsd Multiline Fill Tpmsd Multiline * Update Multiline function multiline funcion simplify * Update FillTpmsD * FillHoneycomb * Update src/libslic3r/PrintConfig.cpp Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Fix Honeycomb Multiline Simplify polylines in honeycomb infill generation * Improve multiline infill support and pattern simplification Moved multiline infill application after pattern translation and simplification in Fill3DHoneycomb, and added multiline support to FillAdaptive. Updated honeycomb and 3D honeycomb infill to simplify polylines to 5x line width. Extended GUI and config to support multiline for Adaptive Cubic infill pattern and clarified max value comment. minimum changes Co-Authored-By: Ian Bassi <12130714+ianalexis@users.noreply.github.com> * Increase multiline fill spacing in honeycomb infill Adjusts the spacing parameter in the multiline_fill function to 1.1 times the original spacing, potentially improving infill distribution or print quality. * Refine fill_multiline tooltip and pattern support logic Updated the tooltip for the 'fill_multiline' parameter to improve clarity and punctuation. Refactored the logic in ConfigManipulation.cpp to clarify which infill patterns support multiline infill. * better management of non supported infill patterns --------- Co-authored-by: SoftFever <softfeverever@gmail.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Ian Bassi <ian.bassi@outlook.com> Co-authored-by: Ian Bassi <12130714+ianalexis@users.noreply.github.com>
This commit is contained in:
parent
10687085ee
commit
a8141ef360
17 changed files with 164 additions and 37 deletions
|
@ -41,6 +41,8 @@ struct SurfaceFillParams
|
||||||
|
|
||||||
// FillParams
|
// FillParams
|
||||||
float density = 0.f;
|
float density = 0.f;
|
||||||
|
// Infill line multiplier count.
|
||||||
|
int multiline = 1;
|
||||||
// Don't adjust spacing to fill the space evenly.
|
// Don't adjust spacing to fill the space evenly.
|
||||||
// bool dont_adjust = false;
|
// bool dont_adjust = false;
|
||||||
// Length of the infill anchor along the perimeter line.
|
// Length of the infill anchor along the perimeter line.
|
||||||
|
@ -88,6 +90,7 @@ struct SurfaceFillParams
|
||||||
RETURN_COMPARE_NON_EQUAL(overlap);
|
RETURN_COMPARE_NON_EQUAL(overlap);
|
||||||
RETURN_COMPARE_NON_EQUAL(angle);
|
RETURN_COMPARE_NON_EQUAL(angle);
|
||||||
RETURN_COMPARE_NON_EQUAL(density);
|
RETURN_COMPARE_NON_EQUAL(density);
|
||||||
|
RETURN_COMPARE_NON_EQUAL(multiline);
|
||||||
// RETURN_COMPARE_NON_EQUAL_TYPED(unsigned, dont_adjust);
|
// RETURN_COMPARE_NON_EQUAL_TYPED(unsigned, dont_adjust);
|
||||||
RETURN_COMPARE_NON_EQUAL(anchor_length);
|
RETURN_COMPARE_NON_EQUAL(anchor_length);
|
||||||
RETURN_COMPARE_NON_EQUAL(anchor_length_max);
|
RETURN_COMPARE_NON_EQUAL(anchor_length_max);
|
||||||
|
@ -117,6 +120,7 @@ struct SurfaceFillParams
|
||||||
this->bridge == rhs.bridge &&
|
this->bridge == rhs.bridge &&
|
||||||
this->bridge_angle == rhs.bridge_angle &&
|
this->bridge_angle == rhs.bridge_angle &&
|
||||||
this->density == rhs.density &&
|
this->density == rhs.density &&
|
||||||
|
this->multiline == rhs.multiline &&
|
||||||
// this->dont_adjust == rhs.dont_adjust &&
|
// this->dont_adjust == rhs.dont_adjust &&
|
||||||
this->anchor_length == rhs.anchor_length &&
|
this->anchor_length == rhs.anchor_length &&
|
||||||
this->anchor_length_max == rhs.anchor_length_max &&
|
this->anchor_length_max == rhs.anchor_length_max &&
|
||||||
|
@ -647,6 +651,7 @@ std::vector<SurfaceFill> group_fills(const Layer &layer, LockRegionParam &lock_p
|
||||||
params.extruder = layerm.region().extruder(extrusion_role);
|
params.extruder = layerm.region().extruder(extrusion_role);
|
||||||
params.pattern = region_config.sparse_infill_pattern.value;
|
params.pattern = region_config.sparse_infill_pattern.value;
|
||||||
params.density = float(region_config.sparse_infill_density);
|
params.density = float(region_config.sparse_infill_density);
|
||||||
|
params.multiline = int(region_config.fill_multiline);
|
||||||
params.lattice_angle_1 = region_config.lattice_angle_1;
|
params.lattice_angle_1 = region_config.lattice_angle_1;
|
||||||
params.lattice_angle_2 = region_config.lattice_angle_2;
|
params.lattice_angle_2 = region_config.lattice_angle_2;
|
||||||
params.infill_overhang_angle = region_config.infill_overhang_angle;
|
params.infill_overhang_angle = region_config.infill_overhang_angle;
|
||||||
|
@ -1023,6 +1028,7 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
|
||||||
// apply half spacing using this flow's own spacing and generate infill
|
// apply half spacing using this flow's own spacing and generate infill
|
||||||
FillParams params;
|
FillParams params;
|
||||||
params.density = float(0.01 * surface_fill.params.density);
|
params.density = float(0.01 * surface_fill.params.density);
|
||||||
|
params.multiline = surface_fill.params.multiline;
|
||||||
params.dont_adjust = false; // surface_fill.params.dont_adjust;
|
params.dont_adjust = false; // surface_fill.params.dont_adjust;
|
||||||
params.anchor_length = surface_fill.params.anchor_length;
|
params.anchor_length = surface_fill.params.anchor_length;
|
||||||
params.anchor_length_max = surface_fill.params.anchor_length_max;
|
params.anchor_length_max = surface_fill.params.anchor_length_max;
|
||||||
|
@ -1199,6 +1205,7 @@ Polylines Layer::generate_sparse_infill_polylines_for_anchoring(FillAdaptive::Oc
|
||||||
params.lattice_angle_1 = surface_fill.params.lattice_angle_1;
|
params.lattice_angle_1 = surface_fill.params.lattice_angle_1;
|
||||||
params.lattice_angle_2 = surface_fill.params.lattice_angle_2;
|
params.lattice_angle_2 = surface_fill.params.lattice_angle_2;
|
||||||
params.infill_overhang_angle = surface_fill.params.infill_overhang_angle;
|
params.infill_overhang_angle = surface_fill.params.infill_overhang_angle;
|
||||||
|
params.multiline = surface_fill.params.multiline;
|
||||||
|
|
||||||
for (ExPolygon &expoly : surface_fill.expolygons) {
|
for (ExPolygon &expoly : surface_fill.expolygons) {
|
||||||
// Spacing is modified by the filler to indicate adjustments. Reset it for each expolygon.
|
// Spacing is modified by the filler to indicate adjustments. Reset it for each expolygon.
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#include "../ClipperUtils.hpp"
|
#include "../ClipperUtils.hpp"
|
||||||
#include "../ShortestPath.hpp"
|
#include "../ShortestPath.hpp"
|
||||||
#include "../Surface.hpp"
|
#include "../Surface.hpp"
|
||||||
|
#include "FillBase.hpp"
|
||||||
#include "Fill3DHoneycomb.hpp"
|
#include "Fill3DHoneycomb.hpp"
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
@ -212,7 +212,7 @@ void Fill3DHoneycomb::_fill_surface_single(
|
||||||
// = 4 * integrate(func=4*x(sqrt(2) - 1) + 1, from=0, to=0.25)
|
// = 4 * integrate(func=4*x(sqrt(2) - 1) + 1, from=0, to=0.25)
|
||||||
// = (sqrt(2) + 1) / 2 [... I think]
|
// = (sqrt(2) + 1) / 2 [... I think]
|
||||||
// make a first guess at the preferred grid Size
|
// make a first guess at the preferred grid Size
|
||||||
coordf_t gridSize = (scale_(this->spacing) * ((zScale + 1.) / 2.) / params.density);
|
coordf_t gridSize = (scale_(this->spacing) * ((zScale + 1.) / 2.) * params.multiline / params.density);
|
||||||
|
|
||||||
// This density calculation is incorrect for many values > 25%, possibly
|
// This density calculation is incorrect for many values > 25%, possibly
|
||||||
// due to quantisation error, so this value is used as a first guess, then the
|
// due to quantisation error, so this value is used as a first guess, then the
|
||||||
|
@ -228,7 +228,7 @@ void Fill3DHoneycomb::_fill_surface_single(
|
||||||
layersPerModule = 2;
|
layersPerModule = 2;
|
||||||
// re-adjust the grid size for a partial octahedral path
|
// re-adjust the grid size for a partial octahedral path
|
||||||
// (scale of 1.1 guessed based on modeling)
|
// (scale of 1.1 guessed based on modeling)
|
||||||
gridSize = (scale_(this->spacing) * 1.1 / params.density);
|
gridSize = (scale_(this->spacing) * 1.1 * params.multiline / params.density);
|
||||||
// re-adjust zScale to make layering consistent
|
// re-adjust zScale to make layering consistent
|
||||||
zScale = (gridSize * 2) / (layersPerModule * layerHeight);
|
zScale = (gridSize * 2) / (layersPerModule * layerHeight);
|
||||||
} else {
|
} else {
|
||||||
|
@ -238,7 +238,7 @@ void Fill3DHoneycomb::_fill_surface_single(
|
||||||
// re-adjust zScale to make layering consistent
|
// re-adjust zScale to make layering consistent
|
||||||
zScale = (gridSize * 2) / (layersPerModule * layerHeight);
|
zScale = (gridSize * 2) / (layersPerModule * layerHeight);
|
||||||
// re-adjust the grid size to account for the new zScale
|
// re-adjust the grid size to account for the new zScale
|
||||||
gridSize = (scale_(this->spacing) * ((zScale + 1.) / 2.) / params.density);
|
gridSize = (scale_(this->spacing) * ((zScale + 1.) / 2.) * params.multiline / params.density);
|
||||||
// re-calculate layersPerModule and zScale
|
// re-calculate layersPerModule and zScale
|
||||||
layersPerModule = floor((gridSize * 2) / (zScale * layerHeight) + 0.05);
|
layersPerModule = floor((gridSize * 2) / (zScale * layerHeight) + 0.05);
|
||||||
if(layersPerModule < 2){
|
if(layersPerModule < 2){
|
||||||
|
@ -264,11 +264,24 @@ void Fill3DHoneycomb::_fill_surface_single(
|
||||||
// move pattern in place
|
// move pattern in place
|
||||||
for (Polyline &pl : polylines){
|
for (Polyline &pl : polylines){
|
||||||
pl.translate(bb.min);
|
pl.translate(bb.min);
|
||||||
|
pl.simplify(5 * spacing); // simplify to 5x line width
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply multiline offset if needed
|
||||||
|
multiline_fill(polylines, params, spacing);
|
||||||
|
|
||||||
// clip pattern to boundaries, chain the clipped polylines
|
// clip pattern to boundaries, chain the clipped polylines
|
||||||
polylines = intersection_pl(polylines, to_polygons(expolygon));
|
polylines = intersection_pl(polylines, to_polygons(expolygon));
|
||||||
|
|
||||||
|
if (! polylines.empty()) {
|
||||||
|
// Remove very small bits, but be careful to not remove infill lines connecting thin walls!
|
||||||
|
// The infill perimeter lines should be separated by around a single infill line width.
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
// copy from fliplines
|
// copy from fliplines
|
||||||
if (!polylines.empty()) {
|
if (!polylines.empty()) {
|
||||||
int infill_start_idx = polylines_out.size(); // only rotate what belongs to us.
|
int infill_start_idx = polylines_out.size(); // only rotate what belongs to us.
|
||||||
|
|
|
@ -1369,6 +1369,10 @@ void Filler::_fill_surface_single(
|
||||||
// Convert lines to polylines.
|
// Convert lines to polylines.
|
||||||
all_polylines.reserve(lines.size());
|
all_polylines.reserve(lines.size());
|
||||||
std::transform(lines.begin(), lines.end(), std::back_inserter(all_polylines), [](const Line& l) { return Polyline{ l.a, l.b }; });
|
std::transform(lines.begin(), lines.end(), std::back_inserter(all_polylines), [](const Line& l) { return Polyline{ l.a, l.b }; });
|
||||||
|
|
||||||
|
// Apply multiline offset if needed
|
||||||
|
multiline_fill(all_polylines, params, spacing);
|
||||||
|
|
||||||
// Crop all polylines
|
// Crop all polylines
|
||||||
all_polylines = intersection_pl(std::move(all_polylines), expolygon);
|
all_polylines = intersection_pl(std::move(all_polylines), expolygon);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
#include "../ClipperUtils.hpp"
|
#include "../ClipperUtils.hpp"
|
||||||
#include "../EdgeGrid.hpp"
|
#include "../EdgeGrid.hpp"
|
||||||
#include "../Geometry.hpp"
|
#include "../Geometry.hpp"
|
||||||
|
@ -25,7 +26,6 @@
|
||||||
// BBS: new infill pattern header
|
// BBS: new infill pattern header
|
||||||
#include "FillConcentricInternal.hpp"
|
#include "FillConcentricInternal.hpp"
|
||||||
#include "FillCrossHatch.hpp"
|
#include "FillCrossHatch.hpp"
|
||||||
|
|
||||||
// #define INFILL_DEBUG_OUTPUT
|
// #define INFILL_DEBUG_OUTPUT
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
@ -190,22 +190,22 @@ void Fill::fill_surface_extrusion(const Surface* surface, const FillParams& para
|
||||||
// Orca: Dedicated function to calculate gap fill lines for the provided surface, according to the print object parameters
|
// Orca: Dedicated function to calculate gap fill lines for the provided surface, according to the print object parameters
|
||||||
// and append them to the out ExtrusionEntityCollection.
|
// and append them to the out ExtrusionEntityCollection.
|
||||||
void Fill::_create_gap_fill(const Surface* surface, const FillParams& params, ExtrusionEntityCollection* out){
|
void Fill::_create_gap_fill(const Surface* surface, const FillParams& params, ExtrusionEntityCollection* out){
|
||||||
|
|
||||||
//Orca: just to be safe, check against null pointer for the print object config and if NULL return.
|
//Orca: just to be safe, check against null pointer for the print object config and if NULL return.
|
||||||
if (this->print_object_config == nullptr) return;
|
if (this->print_object_config == nullptr) return;
|
||||||
|
|
||||||
// Orca: Enable gap fill as per the user preference. Return early if gap fill is to not be applied.
|
// Orca: Enable gap fill as per the user preference. Return early if gap fill is to not be applied.
|
||||||
if ((this->print_object_config->gap_fill_target.value == gftNowhere) ||
|
if ((this->print_object_config->gap_fill_target.value == gftNowhere) ||
|
||||||
(surface->surface_type == stInternalSolid && this->print_object_config->gap_fill_target.value != gftEverywhere))
|
(surface->surface_type == stInternalSolid && this->print_object_config->gap_fill_target.value != gftEverywhere))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Flow new_flow = params.flow;
|
Flow new_flow = params.flow;
|
||||||
ExPolygons unextruded_areas;
|
ExPolygons unextruded_areas;
|
||||||
unextruded_areas = diff_ex(this->no_overlap_expolygons, union_ex(out->polygons_covered_by_spacing(10)));
|
unextruded_areas = diff_ex(this->no_overlap_expolygons, union_ex(out->polygons_covered_by_spacing(10)));
|
||||||
ExPolygons gapfill_areas = union_ex(unextruded_areas);
|
ExPolygons gapfill_areas = union_ex(unextruded_areas);
|
||||||
if (!this->no_overlap_expolygons.empty())
|
if (!this->no_overlap_expolygons.empty())
|
||||||
gapfill_areas = intersection_ex(gapfill_areas, this->no_overlap_expolygons);
|
gapfill_areas = intersection_ex(gapfill_areas, this->no_overlap_expolygons);
|
||||||
|
|
||||||
if (gapfill_areas.size() > 0 && params.density >= 1) {
|
if (gapfill_areas.size() > 0 && params.density >= 1) {
|
||||||
double min = 0.2 * new_flow.scaled_spacing() * (1 - INSET_OVERLAP_TOLERANCE);
|
double min = 0.2 * new_flow.scaled_spacing() * (1 - INSET_OVERLAP_TOLERANCE);
|
||||||
double max = 2. * new_flow.scaled_spacing();
|
double max = 2. * new_flow.scaled_spacing();
|
||||||
|
@ -222,20 +222,20 @@ void Fill::_create_gap_fill(const Surface* surface, const FillParams& params, Ex
|
||||||
std::vector<Points::size_type> order2 = chain_points(ordering_points);
|
std::vector<Points::size_type> order2 = chain_points(ordering_points);
|
||||||
for (size_t i : order2)
|
for (size_t i : order2)
|
||||||
gaps_ex_sorted.emplace_back(std::move(gaps_ex[i]));
|
gaps_ex_sorted.emplace_back(std::move(gaps_ex[i]));
|
||||||
|
|
||||||
ThickPolylines polylines;
|
ThickPolylines polylines;
|
||||||
for (ExPolygon& ex : gaps_ex_sorted) {
|
for (ExPolygon& ex : gaps_ex_sorted) {
|
||||||
//BBS: Use DP simplify to avoid duplicated points and accelerate medial-axis calculation as well.
|
//BBS: Use DP simplify to avoid duplicated points and accelerate medial-axis calculation as well.
|
||||||
ex.douglas_peucker(SCALED_RESOLUTION * 0.1);
|
ex.douglas_peucker(SCALED_RESOLUTION * 0.1);
|
||||||
ex.medial_axis(min, max, &polylines);
|
ex.medial_axis(min, max, &polylines);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!polylines.empty() && !is_bridge(params.extrusion_role)) {
|
if (!polylines.empty() && !is_bridge(params.extrusion_role)) {
|
||||||
polylines.erase(std::remove_if(polylines.begin(), polylines.end(),
|
polylines.erase(std::remove_if(polylines.begin(), polylines.end(),
|
||||||
[&](const ThickPolyline& p) {
|
[&](const ThickPolyline& p) {
|
||||||
return p.length() < scale_(params.config->filter_out_gap_fill.value);
|
return p.length() < scale_(params.config->filter_out_gap_fill.value);
|
||||||
}), polylines.end());
|
}), polylines.end());
|
||||||
|
|
||||||
ExtrusionEntityCollection gap_fill;
|
ExtrusionEntityCollection gap_fill;
|
||||||
variable_width(polylines, erGapFill, params.flow, gap_fill.entities);
|
variable_width(polylines, erGapFill, params.flow, gap_fill.entities);
|
||||||
auto gap = std::move(gap_fill.entities);
|
auto gap = std::move(gap_fill.entities);
|
||||||
|
@ -2696,4 +2696,55 @@ void Fill::connect_base_support(Polylines &&infill_ordered, const Polygons &boun
|
||||||
connect_base_support(std::move(infill_ordered), polygons_src, bbox, polylines_out, spacing, params);
|
connect_base_support(std::move(infill_ordered), polygons_src, bbox, polylines_out, spacing, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Fill Multiline
|
||||||
|
void multiline_fill(Polylines& polylines, const FillParams& params, float spacing)
|
||||||
|
{
|
||||||
|
if (params.multiline > 1) {
|
||||||
|
const int n_lines = params.multiline;
|
||||||
|
const int n_polylines = static_cast<int>(polylines.size());
|
||||||
|
Polylines all_polylines;
|
||||||
|
all_polylines.reserve(n_lines * n_polylines);
|
||||||
|
|
||||||
|
const float center = (n_lines - 1) / 2.0f;
|
||||||
|
|
||||||
|
for (int line = 0; line < n_lines; ++line) {
|
||||||
|
float offset = (static_cast<float>(line) - center) * spacing;
|
||||||
|
|
||||||
|
for (const Polyline& pl : polylines) {
|
||||||
|
const size_t n = pl.points.size();
|
||||||
|
if (n < 2) {
|
||||||
|
all_polylines.emplace_back(pl);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Points new_points;
|
||||||
|
new_points.reserve(n);
|
||||||
|
for (size_t i = 0; i < n; ++i) {
|
||||||
|
Vec2f tangent;
|
||||||
|
if (i == 0)
|
||||||
|
tangent = Vec2f(pl.points[1].x() - pl.points[0].x(), pl.points[1].y() - pl.points[0].y());
|
||||||
|
else if (i == n - 1)
|
||||||
|
tangent = Vec2f(pl.points[n - 1].x() - pl.points[n - 2].x(), pl.points[n - 1].y() - pl.points[n - 2].y());
|
||||||
|
else
|
||||||
|
tangent = Vec2f(pl.points[i + 1].x() - pl.points[i - 1].x(), pl.points[i + 1].y() - pl.points[i - 1].y());
|
||||||
|
|
||||||
|
float len = std::hypot(tangent.x(), tangent.y());
|
||||||
|
if (len == 0)
|
||||||
|
len = 1.0f;
|
||||||
|
tangent /= len;
|
||||||
|
Vec2f normal(-tangent.y(), tangent.x());
|
||||||
|
|
||||||
|
Point p = pl.points[i];
|
||||||
|
p.x() += scale_(normal.x() * offset);
|
||||||
|
p.y() += scale_(normal.y() * offset);
|
||||||
|
new_points.push_back(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
all_polylines.emplace_back(std::move(new_points));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
polylines = std::move(all_polylines);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
|
|
@ -53,6 +53,7 @@ struct FillParams
|
||||||
|
|
||||||
// Fill density, fraction in <0, 1>
|
// Fill density, fraction in <0, 1>
|
||||||
float density { 0.f };
|
float density { 0.f };
|
||||||
|
int multiline{1};
|
||||||
|
|
||||||
// Length of an infill anchor along the perimeter.
|
// Length of an infill anchor along the perimeter.
|
||||||
// 1000mm is roughly the maximum length line that fits into a 32bit coord_t.
|
// 1000mm is roughly the maximum length line that fits into a 32bit coord_t.
|
||||||
|
@ -223,7 +224,8 @@ public:
|
||||||
|
|
||||||
static coord_t _adjust_solid_spacing(const coord_t width, const coord_t distance);
|
static coord_t _adjust_solid_spacing(const coord_t width, const coord_t distance);
|
||||||
};
|
};
|
||||||
|
//Fill Multiline
|
||||||
|
void multiline_fill(Polylines& polylines, const FillParams& params, float spacing);
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
|
||||||
#endif // slic3r_FillBase_hpp_
|
#endif // slic3r_FillBase_hpp_
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#include "../ShortestPath.hpp"
|
#include "../ShortestPath.hpp"
|
||||||
#include "../Surface.hpp"
|
#include "../Surface.hpp"
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include "FillBase.hpp"
|
||||||
#include "FillCrossHatch.hpp"
|
#include "FillCrossHatch.hpp"
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
@ -186,7 +186,8 @@ void FillCrossHatch ::_fill_surface_single(
|
||||||
BoundingBox bb = expolygon.contour.bounding_box();
|
BoundingBox bb = expolygon.contour.bounding_box();
|
||||||
|
|
||||||
// linespace modifier
|
// linespace modifier
|
||||||
coord_t line_spacing = coord_t(scale_(this->spacing) / params.density);
|
double density_adjusted = params.density / params.multiline;
|
||||||
|
coord_t line_spacing = coord_t(scale_(this->spacing) / density_adjusted);
|
||||||
|
|
||||||
// reduce density
|
// reduce density
|
||||||
if (params.density < 0.999) line_spacing *= 1.08;
|
if (params.density < 0.999) line_spacing *= 1.08;
|
||||||
|
@ -204,6 +205,9 @@ void FillCrossHatch ::_fill_surface_single(
|
||||||
// shift the pattern to the actual space
|
// shift the pattern to the actual space
|
||||||
for (Polyline &pl : polylines) { pl.translate(bb.min); }
|
for (Polyline &pl : polylines) { pl.translate(bb.min); }
|
||||||
|
|
||||||
|
// Apply multiline offset if needed
|
||||||
|
multiline_fill(polylines, params, spacing);
|
||||||
|
|
||||||
polylines = intersection_pl(polylines, to_polygons(expolygon));
|
polylines = intersection_pl(polylines, to_polygons(expolygon));
|
||||||
|
|
||||||
// --- remove small remains from gyroid infill
|
// --- remove small remains from gyroid infill
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include "FillBase.hpp"
|
||||||
#include "FillGyroid.hpp"
|
#include "FillGyroid.hpp"
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
@ -149,10 +149,10 @@ static Polylines make_gyroid_waves(double gridZ, double density_adjusted, double
|
||||||
constexpr double FillGyroid::PatternTolerance;
|
constexpr double FillGyroid::PatternTolerance;
|
||||||
|
|
||||||
void FillGyroid::_fill_surface_single(
|
void FillGyroid::_fill_surface_single(
|
||||||
const FillParams ¶ms,
|
const FillParams ¶ms,
|
||||||
unsigned int thickness_layers,
|
unsigned int thickness_layers,
|
||||||
const std::pair<float, Point> &direction,
|
const std::pair<float, Point> &direction,
|
||||||
ExPolygon expolygon,
|
ExPolygon expolygon,
|
||||||
Polylines &polylines_out)
|
Polylines &polylines_out)
|
||||||
{
|
{
|
||||||
auto infill_angle = float(this->angle + (CorrectionAngle * 2*M_PI) / 360.);
|
auto infill_angle = float(this->angle + (CorrectionAngle * 2*M_PI) / 360.);
|
||||||
|
@ -161,7 +161,7 @@ void FillGyroid::_fill_surface_single(
|
||||||
|
|
||||||
BoundingBox bb = expolygon.contour.bounding_box();
|
BoundingBox bb = expolygon.contour.bounding_box();
|
||||||
// Density adjusted to have a good %of weight.
|
// Density adjusted to have a good %of weight.
|
||||||
double density_adjusted = std::max(0., params.density * DensityAdjust);
|
double density_adjusted = std::max(0., params.density * DensityAdjust / params.multiline);
|
||||||
// Distance between the gyroid waves in scaled coordinates.
|
// Distance between the gyroid waves in scaled coordinates.
|
||||||
coord_t distance = coord_t(scale_(this->spacing) / density_adjusted);
|
coord_t distance = coord_t(scale_(this->spacing) / density_adjusted);
|
||||||
|
|
||||||
|
@ -184,6 +184,9 @@ void FillGyroid::_fill_surface_single(
|
||||||
for (Polyline &pl : polylines)
|
for (Polyline &pl : polylines)
|
||||||
pl.translate(bb.min);
|
pl.translate(bb.min);
|
||||||
|
|
||||||
|
// Apply multiline offset if needed
|
||||||
|
multiline_fill(polylines, params, spacing);
|
||||||
|
|
||||||
polylines = intersection_pl(polylines, expolygon);
|
polylines = intersection_pl(polylines, expolygon);
|
||||||
|
|
||||||
if (! polylines.empty()) {
|
if (! polylines.empty()) {
|
||||||
|
|
|
@ -7,9 +7,9 @@
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
void FillHoneycomb::_fill_surface_single(
|
void FillHoneycomb::_fill_surface_single(
|
||||||
const FillParams ¶ms,
|
const FillParams ¶ms,
|
||||||
unsigned int thickness_layers,
|
unsigned int thickness_layers,
|
||||||
const std::pair<float, Point> &direction,
|
const std::pair<float, Point> &direction,
|
||||||
ExPolygon expolygon,
|
ExPolygon expolygon,
|
||||||
Polylines &polylines_out)
|
Polylines &polylines_out)
|
||||||
{
|
{
|
||||||
|
@ -19,7 +19,7 @@ void FillHoneycomb::_fill_surface_single(
|
||||||
if (it_m == this->cache.end()) {
|
if (it_m == this->cache.end()) {
|
||||||
it_m = this->cache.insert(it_m, std::pair<CacheID, CacheData>(cache_id, CacheData()));
|
it_m = this->cache.insert(it_m, std::pair<CacheID, CacheData>(cache_id, CacheData()));
|
||||||
CacheData &m = it_m->second;
|
CacheData &m = it_m->second;
|
||||||
coord_t min_spacing = coord_t(scale_(this->spacing));
|
coord_t min_spacing = coord_t(scale_(this->spacing)) * params.multiline;
|
||||||
m.distance = coord_t(min_spacing / params.density);
|
m.distance = coord_t(min_spacing / params.density);
|
||||||
m.hex_side = coord_t(m.distance / (sqrt(3)/2));
|
m.hex_side = coord_t(m.distance / (sqrt(3)/2));
|
||||||
m.hex_width = m.distance * 2; // $m->{hex_width} == $m->{hex_side} * sqrt(3);
|
m.hex_width = m.distance * 2; // $m->{hex_width} == $m->{hex_side} * sqrt(3);
|
||||||
|
@ -36,14 +36,14 @@ void FillHoneycomb::_fill_surface_single(
|
||||||
{
|
{
|
||||||
// adjust actual bounding box to the nearest multiple of our hex pattern
|
// adjust actual bounding box to the nearest multiple of our hex pattern
|
||||||
// and align it so that it matches across layers
|
// and align it so that it matches across layers
|
||||||
|
|
||||||
BoundingBox bounding_box = expolygon.contour.bounding_box();
|
BoundingBox bounding_box = expolygon.contour.bounding_box();
|
||||||
{
|
{
|
||||||
// rotate bounding box according to infill direction
|
// rotate bounding box according to infill direction
|
||||||
Polygon bb_polygon = bounding_box.polygon();
|
Polygon bb_polygon = bounding_box.polygon();
|
||||||
bb_polygon.rotate(direction.first, m.hex_center);
|
bb_polygon.rotate(direction.first, m.hex_center);
|
||||||
bounding_box = bb_polygon.bounding_box();
|
bounding_box = bb_polygon.bounding_box();
|
||||||
|
|
||||||
// extend bounding box so that our pattern will be aligned with other layers
|
// extend bounding box so that our pattern will be aligned with other layers
|
||||||
// $bounding_box->[X1] and [Y1] represent the displacement between new bounding box offset and old one
|
// $bounding_box->[X1] and [Y1] represent the displacement between new bounding box offset and old one
|
||||||
// The infill is not aligned to the object bounding box, but to a world coordinate system. Supposedly good enough.
|
// The infill is not aligned to the object bounding box, but to a world coordinate system. Supposedly good enough.
|
||||||
|
@ -69,10 +69,13 @@ void FillHoneycomb::_fill_surface_single(
|
||||||
x += m.distance;
|
x += m.distance;
|
||||||
}
|
}
|
||||||
p.rotate(-direction.first, m.hex_center);
|
p.rotate(-direction.first, m.hex_center);
|
||||||
|
p.simplify(5 * spacing); // simplify to 5x line width
|
||||||
all_polylines.push_back(p);
|
all_polylines.push_back(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Apply multiline offset if needed
|
||||||
|
multiline_fill(all_polylines, params, 1.1 * spacing);
|
||||||
|
|
||||||
all_polylines = intersection_pl(std::move(all_polylines), expolygon);
|
all_polylines = intersection_pl(std::move(all_polylines), expolygon);
|
||||||
chain_or_connect_infill(std::move(all_polylines), expolygon, polylines_out, this->spacing, params);
|
chain_or_connect_infill(std::move(all_polylines), expolygon, polylines_out, this->spacing, params);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include "../Print.hpp"
|
#include "../Print.hpp"
|
||||||
#include "../ShortestPath.hpp"
|
#include "../ShortestPath.hpp"
|
||||||
|
#include "FillBase.hpp"
|
||||||
#include "FillLightning.hpp"
|
#include "FillLightning.hpp"
|
||||||
#include "Lightning/Generator.hpp"
|
#include "Lightning/Generator.hpp"
|
||||||
|
|
||||||
|
@ -16,6 +16,10 @@ void Filler::_fill_surface_single(
|
||||||
const Layer &layer = generator->getTreesForLayer(this->layer_id);
|
const Layer &layer = generator->getTreesForLayer(this->layer_id);
|
||||||
Polylines fill_lines = layer.convertToLines(to_polygons(expolygon), scaled<coord_t>(0.5 * this->spacing - this->overlap));
|
Polylines fill_lines = layer.convertToLines(to_polygons(expolygon), scaled<coord_t>(0.5 * this->spacing - this->overlap));
|
||||||
|
|
||||||
|
// Apply multiline offset if needed
|
||||||
|
multiline_fill(fill_lines, params, spacing);
|
||||||
|
|
||||||
|
|
||||||
chain_or_connect_infill(std::move(fill_lines), expolygon, polylines_out, this->spacing, params);
|
chain_or_connect_infill(std::move(fill_lines), expolygon, polylines_out, this->spacing, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2956,11 +2956,12 @@ void make_fill_lines(const ExPolygonWithOffset &poly_with_offset, Point refpt, d
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FillRectilinear::fill_surface_by_multilines(const Surface *surface, FillParams params, const std::initializer_list<SweepParams> &sweep_params, Polylines &polylines_out)
|
bool FillRectilinear::fill_surface_by_multilines(const Surface *surface, FillParams params, const std::initializer_list<SweepParams> &sweep_params, Polylines &polylines_out) // fill multiline
|
||||||
{
|
{
|
||||||
assert(sweep_params.size() >= 1);
|
assert(sweep_params.size() >= 1);
|
||||||
assert(! params.full_infill());
|
assert(!params.full_infill());
|
||||||
params.density /= double(sweep_params.size());
|
params.density /= double(sweep_params.size());
|
||||||
|
int n_multilines = params.multiline;
|
||||||
assert(params.density > 0.0001f && params.density <= 1.f);
|
assert(params.density > 0.0001f && params.density <= 1.f);
|
||||||
|
|
||||||
ExPolygonWithOffset poly_with_offset_base(surface->expolygon, 0, float(scale_(this->overlap - 0.5 * this->spacing)));
|
ExPolygonWithOffset poly_with_offset_base(surface->expolygon, 0, float(scale_(this->overlap - 0.5 * this->spacing)));
|
||||||
|
@ -2970,12 +2971,21 @@ bool FillRectilinear::fill_surface_by_multilines(const Surface *surface, FillPar
|
||||||
|
|
||||||
Polylines fill_lines;
|
Polylines fill_lines;
|
||||||
coord_t line_width = coord_t(scale_(this->spacing));
|
coord_t line_width = coord_t(scale_(this->spacing));
|
||||||
coord_t line_spacing = coord_t(scale_(this->spacing) / params.density);
|
coord_t line_spacing = coord_t(scale_(this->spacing) * params.multiline / params.density);
|
||||||
std::pair<float, Point> rotate_vector = this->_infill_direction(surface);
|
std::pair<float, Point> rotate_vector = this->_infill_direction(surface);
|
||||||
for (const SweepParams &sweep : sweep_params) {
|
for (const SweepParams &sweep : sweep_params) {
|
||||||
// Rotate polygons so that we can work with vertical lines here
|
// Rotate polygons so that we can work with vertical lines here
|
||||||
float angle = rotate_vector.first + sweep.angle_base;
|
float angle = rotate_vector.first + sweep.angle_base;
|
||||||
make_fill_lines(ExPolygonWithOffset(poly_with_offset_base, - angle), rotate_vector.second.rotated(-angle), angle, line_width + coord_t(SCALED_EPSILON), line_spacing, coord_t(scale_(sweep.pattern_shift)), fill_lines);
|
//Fill Multiline
|
||||||
|
for (int i = 0; i < n_multilines; ++i) {
|
||||||
|
coord_t group_offset = i * line_spacing;
|
||||||
|
coord_t internal_offset = (i - (n_multilines - 1) / 2.0f) * line_width;
|
||||||
|
coord_t total_offset = group_offset + internal_offset;
|
||||||
|
coord_t pattern_shift = scale_(sweep.pattern_shift + unscale_(total_offset));
|
||||||
|
|
||||||
|
make_fill_lines(ExPolygonWithOffset(poly_with_offset_base, -angle), rotate_vector.second.rotated(-angle), angle,
|
||||||
|
line_width + coord_t(SCALED_EPSILON), line_spacing, pattern_shift, fill_lines);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fill_lines.empty()) {
|
if (!fill_lines.empty()) {
|
||||||
|
@ -3057,8 +3067,7 @@ Polylines Fill2DLattice::fill_surface(const Surface *surface, const FillParams &
|
||||||
return polylines_out;
|
return polylines_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
Polylines FillTriangles::fill_surface(const Surface *surface, const FillParams ¶ms)
|
Polylines FillTriangles::fill_surface(const Surface *surface, const FillParams ¶ms){
|
||||||
{
|
|
||||||
Polylines polylines_out;
|
Polylines polylines_out;
|
||||||
if (! this->fill_surface_by_multilines(
|
if (! this->fill_surface_by_multilines(
|
||||||
surface, params,
|
surface, params,
|
||||||
|
@ -3073,7 +3082,7 @@ Polylines FillStars::fill_surface(const Surface *surface, const FillParams ¶
|
||||||
Polylines polylines_out;
|
Polylines polylines_out;
|
||||||
if (! this->fill_surface_by_multilines(
|
if (! this->fill_surface_by_multilines(
|
||||||
surface, params,
|
surface, params,
|
||||||
{ { 0.f, 0.f }, { float(M_PI / 3.), 0.f }, { float(2. * M_PI / 3.), float((3./2.) * this->spacing / params.density) } },
|
{ { 0.f, 0.f }, { float(M_PI / 3.), 0.f }, { float(2. * M_PI / 3.), float((3./2.) * this->spacing * params.multiline / params.density) } },
|
||||||
polylines_out))
|
polylines_out))
|
||||||
BOOST_LOG_TRIVIAL(error) << "FillStars::fill_surface() failed to fill a region.";
|
BOOST_LOG_TRIVIAL(error) << "FillStars::fill_surface() failed to fill a region.";
|
||||||
return polylines_out;
|
return polylines_out;
|
||||||
|
@ -3094,7 +3103,6 @@ Polylines FillCubic::fill_surface(const Surface *surface, const FillParams ¶
|
||||||
Polylines FillQuarterCubic::fill_surface(const Surface* surface, const FillParams& params)
|
Polylines FillQuarterCubic::fill_surface(const Surface* surface, const FillParams& params)
|
||||||
{
|
{
|
||||||
using namespace boost::math::float_constants;
|
using namespace boost::math::float_constants;
|
||||||
|
|
||||||
Polylines polylines_out;
|
Polylines polylines_out;
|
||||||
|
|
||||||
coord_t line_width = coord_t(scale_(this->spacing));
|
coord_t line_width = coord_t(scale_(this->spacing));
|
||||||
|
|
|
@ -110,7 +110,7 @@ void FillTpmsD::_fill_surface_single(
|
||||||
|
|
||||||
BoundingBox bb = expolygon.contour.bounding_box();
|
BoundingBox bb = expolygon.contour.bounding_box();
|
||||||
// Density adjusted to have a good %of weight.
|
// Density adjusted to have a good %of weight.
|
||||||
double density_adjusted = std::max(0., params.density * DensityAdjust);
|
double density_adjusted = std::max(0., params.density * DensityAdjust / params.multiline);
|
||||||
// Distance between the gyroid waves in scaled coordinates.
|
// Distance between the gyroid waves in scaled coordinates.
|
||||||
coord_t distance = coord_t(scale_(this->spacing) / density_adjusted);
|
coord_t distance = coord_t(scale_(this->spacing) / density_adjusted);
|
||||||
|
|
||||||
|
@ -129,6 +129,8 @@ void FillTpmsD::_fill_surface_single(
|
||||||
for (Polyline &pl : polylines)
|
for (Polyline &pl : polylines)
|
||||||
pl.translate(bb.min);
|
pl.translate(bb.min);
|
||||||
|
|
||||||
|
// Apply multiline offset if needed
|
||||||
|
multiline_fill(polylines, params, spacing);
|
||||||
|
|
||||||
polylines = intersection_pl(polylines, expolygon);
|
polylines = intersection_pl(polylines, expolygon);
|
||||||
|
|
||||||
|
|
|
@ -785,7 +785,7 @@ static std::vector<std::string> s_Preset_print_options {
|
||||||
"layer_height", "initial_layer_print_height", "wall_loops", "alternate_extra_wall", "slice_closing_radius", "spiral_mode", "spiral_mode_smooth", "spiral_mode_max_xy_smoothing", "spiral_starting_flow_ratio", "spiral_finishing_flow_ratio", "slicing_mode",
|
"layer_height", "initial_layer_print_height", "wall_loops", "alternate_extra_wall", "slice_closing_radius", "spiral_mode", "spiral_mode_smooth", "spiral_mode_max_xy_smoothing", "spiral_starting_flow_ratio", "spiral_finishing_flow_ratio", "slicing_mode",
|
||||||
"top_shell_layers", "top_shell_thickness", "top_surface_density", "bottom_surface_density", "bottom_shell_layers", "bottom_shell_thickness",
|
"top_shell_layers", "top_shell_thickness", "top_surface_density", "bottom_surface_density", "bottom_shell_layers", "bottom_shell_thickness",
|
||||||
"extra_perimeters_on_overhangs", "ensure_vertical_shell_thickness", "reduce_crossing_wall", "detect_thin_wall", "detect_overhang_wall", "overhang_reverse", "overhang_reverse_threshold","overhang_reverse_internal_only", "wall_direction",
|
"extra_perimeters_on_overhangs", "ensure_vertical_shell_thickness", "reduce_crossing_wall", "detect_thin_wall", "detect_overhang_wall", "overhang_reverse", "overhang_reverse_threshold","overhang_reverse_internal_only", "wall_direction",
|
||||||
"seam_position", "staggered_inner_seams", "wall_sequence", "is_infill_first", "sparse_infill_density", "sparse_infill_pattern", "lattice_angle_1", "lattice_angle_2", "infill_overhang_angle", "top_surface_pattern", "bottom_surface_pattern",
|
"seam_position", "staggered_inner_seams", "wall_sequence", "is_infill_first", "sparse_infill_density","fill_multiline", "sparse_infill_pattern", "lattice_angle_1", "lattice_angle_2", "infill_overhang_angle", "top_surface_pattern", "bottom_surface_pattern",
|
||||||
"infill_direction", "solid_infill_direction", "counterbore_hole_bridging","infill_shift_step", "sparse_infill_rotate_template", "solid_infill_rotate_template", "symmetric_infill_y_axis","skeleton_infill_density", "infill_lock_depth", "skin_infill_depth", "skin_infill_density",
|
"infill_direction", "solid_infill_direction", "counterbore_hole_bridging","infill_shift_step", "sparse_infill_rotate_template", "solid_infill_rotate_template", "symmetric_infill_y_axis","skeleton_infill_density", "infill_lock_depth", "skin_infill_depth", "skin_infill_density",
|
||||||
"minimum_sparse_infill_area", "reduce_infill_retraction","internal_solid_infill_pattern","gap_fill_target",
|
"minimum_sparse_infill_area", "reduce_infill_retraction","internal_solid_infill_pattern","gap_fill_target",
|
||||||
"ironing_type", "ironing_pattern", "ironing_flow", "ironing_speed", "ironing_spacing", "ironing_angle", "ironing_inset",
|
"ironing_type", "ironing_pattern", "ironing_flow", "ironing_speed", "ironing_spacing", "ironing_angle", "ironing_inset",
|
||||||
|
|
|
@ -2361,6 +2361,14 @@ void PrintConfigDef::init_fff_params()
|
||||||
def->max = 100;
|
def->max = 100;
|
||||||
def->set_default_value(new ConfigOptionPercent(20));
|
def->set_default_value(new ConfigOptionPercent(20));
|
||||||
|
|
||||||
|
// Infill multiline
|
||||||
|
def = this->add("fill_multiline", coInt);
|
||||||
|
def->label = L("Fill Multiline");
|
||||||
|
def->tooltip = L("Using multiple lines for the infill pattern, if supported by infill pattern.");
|
||||||
|
def->min = 1;
|
||||||
|
def->max = 5; // Maximum number of lines for infill pattern
|
||||||
|
def->set_default_value(new ConfigOptionInt(1));
|
||||||
|
|
||||||
def = this->add("sparse_infill_pattern", coEnum);
|
def = this->add("sparse_infill_pattern", coEnum);
|
||||||
def->label = L("Sparse infill pattern");
|
def->label = L("Sparse infill pattern");
|
||||||
def->category = L("Strength");
|
def->category = L("Strength");
|
||||||
|
|
|
@ -980,6 +980,7 @@ PRINT_CONFIG_CLASS_DEFINE(
|
||||||
((ConfigOptionBool, infill_combination))
|
((ConfigOptionBool, infill_combination))
|
||||||
// Orca:
|
// Orca:
|
||||||
((ConfigOptionFloatOrPercent, infill_combination_max_layer_height))
|
((ConfigOptionFloatOrPercent, infill_combination_max_layer_height))
|
||||||
|
((ConfigOptionInt, fill_multiline))
|
||||||
// Ironing options
|
// Ironing options
|
||||||
((ConfigOptionEnum<IroningType>, ironing_type))
|
((ConfigOptionEnum<IroningType>, ironing_type))
|
||||||
((ConfigOptionEnum<InfillPattern>, ironing_pattern))
|
((ConfigOptionEnum<InfillPattern>, ironing_pattern))
|
||||||
|
|
|
@ -1065,6 +1065,7 @@ bool PrintObject::invalidate_state_by_config_options(
|
||||||
#endif
|
#endif
|
||||||
} else if (
|
} else if (
|
||||||
opt_key == "interface_shells"
|
opt_key == "interface_shells"
|
||||||
|
|| opt_key == "infill_multiline"
|
||||||
|| opt_key == "infill_combination"
|
|| opt_key == "infill_combination"
|
||||||
|| opt_key == "infill_combination_max_layer_height"
|
|| opt_key == "infill_combination_max_layer_height"
|
||||||
|| opt_key == "bottom_shell_thickness"
|
|| opt_key == "bottom_shell_thickness"
|
||||||
|
|
|
@ -294,6 +294,7 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con
|
||||||
}
|
}
|
||||||
|
|
||||||
double sparse_infill_density = config->option<ConfigOptionPercent>("sparse_infill_density")->value;
|
double sparse_infill_density = config->option<ConfigOptionPercent>("sparse_infill_density")->value;
|
||||||
|
int fill_multiline = config->option<ConfigOptionInt>("fill_multiline")->value;
|
||||||
auto timelapse_type = config->opt_enum<TimelapseType>("timelapse_type");
|
auto timelapse_type = config->opt_enum<TimelapseType>("timelapse_type");
|
||||||
|
|
||||||
if (!is_plate_config &&
|
if (!is_plate_config &&
|
||||||
|
@ -546,6 +547,20 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
|
||||||
bool have_combined_infill = config->opt_bool("infill_combination") && have_infill;
|
bool have_combined_infill = config->opt_bool("infill_combination") && have_infill;
|
||||||
toggle_line("infill_combination_max_layer_height", have_combined_infill);
|
toggle_line("infill_combination_max_layer_height", have_combined_infill);
|
||||||
|
|
||||||
|
// Infill patterns that support multiline infill.
|
||||||
|
InfillPattern pattern = config->opt_enum<InfillPattern>("sparse_infill_pattern");
|
||||||
|
bool have_multiline_infill_pattern = pattern == ipGyroid || pattern == ipGrid || pattern == ipRectilinear || pattern == ipTpmsD || pattern == ipCrossHatch || pattern == ipHoneycomb ||
|
||||||
|
pattern == ipCubic || pattern == ipStars || pattern == ipAlignedRectilinear || pattern == ipLightning || pattern == ip3DHoneycomb || pattern == ipAdaptiveCubic || pattern == ipSupportCubic;
|
||||||
|
toggle_line("fill_multiline", have_multiline_infill_pattern);
|
||||||
|
|
||||||
|
// If the infill pattern does not support multiline infill, set fill_multiline to 1.
|
||||||
|
if (have_multiline_infill_pattern==false) {
|
||||||
|
DynamicPrintConfig new_conf = *config;
|
||||||
|
new_conf.set_key_value("fill_multiline", new ConfigOptionInt(1));
|
||||||
|
apply(config, &new_conf);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hide infill anchor max if sparse_infill_pattern is not line or if sparse_infill_pattern is line but infill_anchor_max is 0.
|
||||||
bool infill_anchor = config->opt_enum<InfillPattern>("sparse_infill_pattern") != ipLine;
|
bool infill_anchor = config->opt_enum<InfillPattern>("sparse_infill_pattern") != ipLine;
|
||||||
toggle_field("infill_anchor_max",infill_anchor);
|
toggle_field("infill_anchor_max",infill_anchor);
|
||||||
|
|
||||||
|
|
|
@ -2207,6 +2207,7 @@ void TabPrint::build()
|
||||||
|
|
||||||
optgroup = page->new_optgroup(L("Infill"), L"param_infill");
|
optgroup = page->new_optgroup(L("Infill"), L"param_infill");
|
||||||
optgroup->append_single_option_line("sparse_infill_density", "strength_settings_infill#sparse-infill-density");
|
optgroup->append_single_option_line("sparse_infill_density", "strength_settings_infill#sparse-infill-density");
|
||||||
|
optgroup->append_single_option_line("fill_multiline"); // fill multiline
|
||||||
optgroup->append_single_option_line("sparse_infill_pattern", "strength_settings_infill#sparse-infill-pattern");
|
optgroup->append_single_option_line("sparse_infill_pattern", "strength_settings_infill#sparse-infill-pattern");
|
||||||
optgroup->append_single_option_line("infill_direction", "strength_settings_infill#direction");
|
optgroup->append_single_option_line("infill_direction", "strength_settings_infill#direction");
|
||||||
optgroup->append_single_option_line("sparse_infill_rotate_template", "strength_settings_infill#rotation");
|
optgroup->append_single_option_line("sparse_infill_rotate_template", "strength_settings_infill#rotation");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue