mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-06-26 09:25:26 -06:00
Allow specifying rotation patterns for Sparse and Solid infill (#9924)
* SPE-2405: Add Zig Zag infill that is rectilinear infill but with a consistent pattern between layers. This Zig Zag infill is inspired by the Zig Zag infill in Cura. Change-Id: I798affa99f4b5c3bd67f47643e67530fb7c3e0cb (cherry picked from commit 2808d04d5deef6f99f9618648e46f11de03efc98) * Add Cross zag and locked-zag for shoes Ported from BambuStudio * wip * sparse infill roratation template * solid_infill_rotate_template * remove rotate_solid_infill_direction * hide sparse infill rotation template for non applicable infill pattern * hide solid_infill_rotate_template for non supported solid infill patterns * update icon * support empty string for ConfigOptionFloats deserialize * fix build errors --------- Co-authored-by: Lukáš Hejl <hejl.lukas@gmail.com>
This commit is contained in:
parent
fa70582ed1
commit
88fb8187d9
39 changed files with 1551 additions and 714 deletions
44
resources/images/param_crosszag.svg
Normal file
44
resources/images/param_crosszag.svg
Normal file
|
@ -0,0 +1,44 @@
|
|||
<svg width="10" height="10" viewBox="0 0 10 10" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_50_344)">
|
||||
<path d="M2.30558 2.99865L3.36346 4.03181L4.42135 2.99837" stroke="#707273" stroke-width="0.5"/>
|
||||
<path d="M2.75277 2.39845L3.37108 3.00231L3.98939 2.39829" stroke="#ABABAB" stroke-width="0.5"/>
|
||||
<path d="M3.94212 1.39367L5 2.42683L6.05789 1.39339" stroke="#707273" stroke-width="0.5"/>
|
||||
<path d="M4.38931 0.793474L5.00762 1.39733L5.62593 0.793312" stroke="#ABABAB" stroke-width="0.5"/>
|
||||
<path d="M5.56148 2.88305L6.61936 3.91621L7.67725 2.88277" stroke="#707273" stroke-width="0.5"/>
|
||||
<path d="M6.00867 2.28285L6.62698 2.88671L7.24529 2.28269" stroke="#ABABAB" stroke-width="0.5"/>
|
||||
<path d="M3.94973 4.62451L5.00761 5.65767L6.0655 4.62423" stroke="#707273" stroke-width="0.5"/>
|
||||
<path d="M4.39692 4.02431L5.01523 4.62817L5.63354 4.02415" stroke="#ABABAB" stroke-width="0.5"/>
|
||||
<path d="M5.62593 6.1643L6.68381 7.19746L7.7417 6.16402" stroke="#707273" stroke-width="0.5"/>
|
||||
<path d="M6.07312 5.5641L6.69143 6.16796L7.30974 5.56394" stroke="#ABABAB" stroke-width="0.5"/>
|
||||
<path d="M7.19075 4.62451L8.24864 5.65767L9.30652 4.62423" stroke="#707273" stroke-width="0.5"/>
|
||||
<path d="M7.63794 4.02431L8.25625 4.62817L8.87457 4.02415" stroke="#ABABAB" stroke-width="0.5"/>
|
||||
<path d="M3.93647 7.79784L4.99436 8.831L6.05224 7.79757" stroke="#707273" stroke-width="0.5"/>
|
||||
<path d="M4.38366 7.19765L5.00197 7.80151L5.62029 7.19749" stroke="#ABABAB" stroke-width="0.5"/>
|
||||
<path d="M7.16011 7.79784L8.218 8.831L9.27588 7.79757" stroke="#707273" stroke-width="0.5"/>
|
||||
<path d="M7.6073 7.19765L8.22561 7.80151L8.84393 7.19749" stroke="#ABABAB" stroke-width="0.5"/>
|
||||
<path d="M2.28115 6.2777L3.33903 7.31086L4.39692 6.27743" stroke="#707273" stroke-width="0.5"/>
|
||||
<path d="M2.72834 5.67751L3.34665 6.28137L3.96496 5.67735" stroke="#ABABAB" stroke-width="0.5"/>
|
||||
<path d="M0.746016 7.9252L1.67045 8.83104L2.72834 7.79761" stroke="#707273" stroke-width="0.5"/>
|
||||
<path d="M1.05976 7.19765L1.67807 7.80151L2.29638 7.19749" stroke="#ABABAB" stroke-width="0.5"/>
|
||||
<path d="M0.674093 4.62451L1.73198 5.65767L2.78986 4.62423" stroke="#707273" stroke-width="0.5"/>
|
||||
<path d="M1.12128 4.02431L1.73959 4.62817L2.3579 4.02415" stroke="#ABABAB" stroke-width="0.5"/>
|
||||
<path d="M0.678528 1.37752L1.67045 2.32702L2.72834 1.29358" stroke="#707273" stroke-width="0.5"/>
|
||||
<path d="M1.05976 0.69362L1.67807 1.29748L2.29638 0.693458" stroke="#ABABAB" stroke-width="0.5"/>
|
||||
<path d="M7.21014 1.24951L8.26802 2.28267L9.32591 1.24923" stroke="#707273" stroke-width="0.5"/>
|
||||
<path d="M7.76739 0.77738L8.27564 1.25297L8.76419 0.777344" stroke="#ABABAB" stroke-width="0.5"/>
|
||||
<path d="M8.99436 0.75769H0.99436C0.856289 0.75769 0.74436 0.869619 0.74436 1.00769V9.00769C0.74436 9.14576 0.856289 9.25769 0.99436 9.25769H8.99436C9.13243 9.25769 9.24436 9.14576 9.24436 9.00769V1.00769C9.24436 0.869619 9.13243 0.75769 8.99436 0.75769Z" stroke="#262E30" stroke-width="0.5"/>
|
||||
<path d="M9.32591 5.65771L5.6773 9.30652" stroke="#262E30" stroke-width="0.5"/>
|
||||
<path d="M4.43306 0.724121L0.674093 4.48328" stroke="#262E30" stroke-width="0.5"/>
|
||||
<path d="M9.27161 2.4071L2.42689 9.2522" stroke="#262E30" stroke-width="0.5"/>
|
||||
<path d="M7.67725 0.693481L0.68421 7.68688" stroke="#262E30" stroke-width="0.5"/>
|
||||
<path d="M4.34229 9.32598L0.693487 5.67737" stroke="#262E30" stroke-width="0.5"/>
|
||||
<path d="M9.27588 4.43303L5.51673 0.674072" stroke="#262E30" stroke-width="0.5"/>
|
||||
<path d="M7.5929 9.27161L0.747808 2.42688" stroke="#262E30" stroke-width="0.5"/>
|
||||
<path d="M9.30652 7.67724L2.31313 0.684204" stroke="#262E30" stroke-width="0.5"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_50_344">
|
||||
<rect width="10" height="10" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 3.6 KiB |
29
resources/images/param_lockedzag.svg
Normal file
29
resources/images/param_lockedzag.svg
Normal file
|
@ -0,0 +1,29 @@
|
|||
<svg width="10" height="10" viewBox="0 0 10 10" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_252_3415)">
|
||||
<path d="M9.00005 0.799805H1.00005C0.900049 0.799805 0.800049 0.899805 0.800049 0.999805V8.9998C0.800049 9.0998 0.900049 9.1998 1.00005 9.1998H9.00005C9.10005 9.1998 9.20005 9.0998 9.20005 8.9998V0.999805C9.20005 0.899805 9.10005 0.799805 9.00005 0.799805Z" stroke="#009688" stroke-width="0.5"/>
|
||||
<path d="M4.40245 0.799805L0.78833 4.51161" stroke="#009688" stroke-width="0.5"/>
|
||||
<path d="M4.98863 6.66064L2.44897 9.2003" stroke="#009688" stroke-width="0.5"/>
|
||||
<path d="M9.30005 2.3999L8.30005 3.3999" stroke="#009688" stroke-width="0.5"/>
|
||||
<path d="M7.62586 0.799805L0.78833 7.63733" stroke="#009688" stroke-width="0.5"/>
|
||||
<path d="M4.30477 9.20004L0.78833 5.68359" stroke="#009688" stroke-width="0.5"/>
|
||||
<path d="M8.21206 3.43714L5.47705 0.799805" stroke="#009688" stroke-width="0.5"/>
|
||||
<path d="M4.98853 6.66064L0.78833 2.46045" stroke="#009688" stroke-width="0.5"/>
|
||||
<path d="M4.98865 3.43714L2.35132 0.799805" stroke="#009688" stroke-width="0.5"/>
|
||||
<path d="M6.56562 3.38428L4.98853 4.96138" stroke="#009688" stroke-width="0.5"/>
|
||||
<path d="M8.14272 3.38428L4.98853 6.53847" stroke="#009688" stroke-width="0.5"/>
|
||||
<path d="M9.22692 4.07471L5.08704 8.21459" stroke="#009688" stroke-width="0.5"/>
|
||||
<path d="M9.12844 5.94727L5.97424 9.10146" stroke="#009688" stroke-width="0.5"/>
|
||||
<path d="M9.22718 7.5249L7.55151 9.20057" stroke="#009688" stroke-width="0.5"/>
|
||||
<path d="M9.22688 4.96138L7.64978 3.38428" stroke="#009688" stroke-width="0.5"/>
|
||||
<path d="M9.22695 6.53847L6.07275 3.38428" stroke="#009688" stroke-width="0.5"/>
|
||||
<path d="M9.22692 8.21459L5.08704 4.07471" stroke="#009688" stroke-width="0.5"/>
|
||||
<path d="M8.24123 9.20009L5.08704 6.0459" stroke="#009688" stroke-width="0.5"/>
|
||||
<path d="M6.66419 9.10145L4.98853 7.42578" stroke="#009688" stroke-width="0.5"/>
|
||||
<path d="M5.09767 3.3999H9.20002V8.8697C9.20002 8.96738 9.10235 9.16273 8.907 9.16273H5V3.3999H5.09767Z" stroke="#009688" stroke-width="0.5"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_252_3415">
|
||||
<rect width="10" height="10" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 2.1 KiB |
158
resources/images/param_zigzag.svg
Normal file
158
resources/images/param_zigzag.svg
Normal file
|
@ -0,0 +1,158 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="10"
|
||||
height="10"
|
||||
viewBox="0 0 10 10"
|
||||
fill="none"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
sodipodi:docname="param_zigzag.svg"
|
||||
inkscape:version="1.3.2 (091e20e, 2023-11-25, custom)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview5"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#009688"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="81.3"
|
||||
inkscape:cx="5"
|
||||
inkscape:cy="5"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1009"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg5" />
|
||||
<g
|
||||
clip-path="url(#clip0_8991_35043)"
|
||||
id="g5">
|
||||
<rect
|
||||
x="0.75"
|
||||
y="0.75"
|
||||
width="8.5"
|
||||
height="8.5"
|
||||
rx="0.25"
|
||||
stroke="#262E30"
|
||||
stroke-width="0.5"
|
||||
id="rect1" />
|
||||
<path
|
||||
d="M0.872559 0.918608L9.08702 9.13218"
|
||||
stroke="#262E30"
|
||||
stroke-width="0.5"
|
||||
stroke-linecap="round"
|
||||
id="path1" />
|
||||
<path
|
||||
d="M0.872559 3.73519L6.27013 9.13218"
|
||||
stroke="#262E30"
|
||||
stroke-width="0.5"
|
||||
stroke-linecap="round"
|
||||
id="path2" />
|
||||
<path
|
||||
d="M0.87207 6.43369L3.57086 9.13218"
|
||||
stroke="#262E30"
|
||||
stroke-width="0.5"
|
||||
stroke-linecap="round"
|
||||
id="path3" />
|
||||
<path
|
||||
d="M9.20605 6.19391L3.80848 0.796919"
|
||||
stroke="#262E30"
|
||||
stroke-width="0.5"
|
||||
stroke-linecap="round"
|
||||
id="path4" />
|
||||
<path
|
||||
d="M9.20605 3.49542L6.50727 0.796921"
|
||||
stroke="#262E30"
|
||||
stroke-width="0.5"
|
||||
stroke-linecap="round"
|
||||
id="path5" />
|
||||
</g>
|
||||
<g
|
||||
clip-path="url(#clip0_8991_35043-1)"
|
||||
id="g5-5"
|
||||
transform="rotate(-90,4.9876999,5.0055351)"
|
||||
style="stroke:#009688;stroke-opacity:1">
|
||||
<rect
|
||||
x="0.75"
|
||||
y="0.75"
|
||||
width="8.5"
|
||||
height="8.5"
|
||||
rx="0.25"
|
||||
stroke="#262e30"
|
||||
stroke-width="0.5"
|
||||
id="rect1-3"
|
||||
style="stroke:#009688;stroke-opacity:1" />
|
||||
<path
|
||||
d="M 0.872559,0.918608 9.08702,9.13218"
|
||||
stroke="#262e30"
|
||||
stroke-width="0.5"
|
||||
stroke-linecap="round"
|
||||
id="path1-4"
|
||||
style="stroke:#009688;stroke-opacity:1" />
|
||||
<path
|
||||
d="M 0.872559,3.73519 6.27013,9.13218"
|
||||
stroke="#262e30"
|
||||
stroke-width="0.5"
|
||||
stroke-linecap="round"
|
||||
id="path2-4"
|
||||
style="stroke:#009688;stroke-opacity:1" />
|
||||
<path
|
||||
d="M 0.87207,6.43369 3.57086,9.13218"
|
||||
stroke="#262e30"
|
||||
stroke-width="0.5"
|
||||
stroke-linecap="round"
|
||||
id="path3-0"
|
||||
style="stroke:#009688;stroke-opacity:1" />
|
||||
<path
|
||||
d="M 9.20605,6.19391 3.80848,0.796919"
|
||||
stroke="#262e30"
|
||||
stroke-width="0.5"
|
||||
stroke-linecap="round"
|
||||
id="path4-1"
|
||||
style="stroke:#009688;stroke-opacity:1" />
|
||||
<path
|
||||
d="M 9.20605,3.49542 6.50727,0.796921"
|
||||
stroke="#262e30"
|
||||
stroke-width="0.5"
|
||||
stroke-linecap="round"
|
||||
id="path5-0"
|
||||
style="stroke:#009688;stroke-opacity:1" />
|
||||
</g>
|
||||
<defs
|
||||
id="defs5">
|
||||
<clipPath
|
||||
id="clip0_8991_35043">
|
||||
<rect
|
||||
width="10"
|
||||
height="10"
|
||||
fill="white"
|
||||
id="rect5" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
id="clip0_8991_35043-9">
|
||||
<rect
|
||||
width="10"
|
||||
height="10"
|
||||
fill="#ffffff"
|
||||
id="rect5-5"
|
||||
x="0"
|
||||
y="0" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
id="clip0_8991_35043-1">
|
||||
<rect
|
||||
width="10"
|
||||
height="10"
|
||||
fill="#ffffff"
|
||||
id="rect5-0"
|
||||
x="0"
|
||||
y="0" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 3.9 KiB |
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "Bambulab",
|
||||
"url": "http://www.bambulab.com/Parameters/vendor/BBL.json",
|
||||
"version": "01.10.00.36",
|
||||
"version": "02.00.00.53",
|
||||
"force_update": "0",
|
||||
"description": "the initial version of BBL configurations",
|
||||
"machine_model_list": [
|
||||
|
|
|
@ -71,5 +71,8 @@
|
|||
"compatible_printers": [],
|
||||
"smooth_coefficient": "80",
|
||||
"overhang_totally_speed": "19",
|
||||
"scarf_angle_threshold": "155"
|
||||
"scarf_angle_threshold": "155",
|
||||
"infill_shift_step": "0.4",
|
||||
"infill_rotate_step": "0",
|
||||
"symmetric_infill_y_axis": "false"
|
||||
}
|
|
@ -49,6 +49,13 @@ BoundingBox BoundingBox::rotated(double angle, const Point ¢er) const
|
|||
return out;
|
||||
}
|
||||
|
||||
BoundingBox BoundingBox::scaled(double factor) const
|
||||
{
|
||||
BoundingBox out(*this);
|
||||
out.scale(factor);
|
||||
return out;
|
||||
}
|
||||
|
||||
template <class PointType, typename APointsType> void
|
||||
BoundingBoxBase<PointType, APointsType>::scale(double factor)
|
||||
{
|
||||
|
|
|
@ -222,7 +222,9 @@ public:
|
|||
BoundingBox(const Point &pmin, const Point &pmax) : BoundingBoxBase<Point, Points>(pmin, pmax) {}
|
||||
BoundingBox(const Points &points) : BoundingBoxBase<Point, Points>(points) {}
|
||||
|
||||
BoundingBox inflated(coordf_t delta) const throw() { BoundingBox out(*this); out.offset(delta); return out; }
|
||||
BoundingBox inflated(coordf_t delta) const noexcept { BoundingBox out(*this); out.offset(delta); return out; }
|
||||
|
||||
BoundingBox scaled(double factor) const;
|
||||
|
||||
friend BoundingBox get_extents_rotated(const Points &points, double angle);
|
||||
};
|
||||
|
|
|
@ -657,6 +657,11 @@ public:
|
|||
{
|
||||
if (! append)
|
||||
this->values.clear();
|
||||
|
||||
if (str.empty()) {
|
||||
this->values.push_back(0);
|
||||
return true;
|
||||
}
|
||||
std::istringstream is(str);
|
||||
std::string item_str;
|
||||
while (std::getline(is, item_str, ',')) {
|
||||
|
@ -675,6 +680,13 @@ public:
|
|||
}
|
||||
return true;
|
||||
}
|
||||
static bool validate_string(const std::string &str)
|
||||
{
|
||||
// should only have number and commas
|
||||
return std::all_of(str.begin(), str.end(), [](char c) {
|
||||
return std::isdigit(c) || c == ','|| std::isspace(c);
|
||||
});
|
||||
}
|
||||
|
||||
ConfigOptionFloatsTempl& operator=(const ConfigOption *opt)
|
||||
{
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -56,7 +56,7 @@ public:
|
|||
bool on_boundary(const Point &point, double eps) const;
|
||||
// Projection of a point onto the polygon.
|
||||
Point point_projection(const Point &point) const;
|
||||
|
||||
void symmetric_y(const coord_t &y_axis);
|
||||
// Does this expolygon overlap another expolygon?
|
||||
// Either the ExPolygons intersect, or one is fully inside the other,
|
||||
// and it is not inside a hole of the other expolygon.
|
||||
|
|
|
@ -34,7 +34,6 @@ struct SurfaceFillParams
|
|||
coordf_t overlap = 0.;
|
||||
// Angle as provided by the region config, in radians.
|
||||
float angle = 0.f;
|
||||
bool rotate_angle = true;
|
||||
// Is bridging used for this fill? Bridging parameters may be used even if this->flow.bridge() is not set.
|
||||
bool bridge;
|
||||
// Non-negative for a bridge.
|
||||
|
@ -68,6 +67,9 @@ struct SurfaceFillParams
|
|||
// Params for lattice infill angles
|
||||
float lattice_angle_1 = 0.f;
|
||||
float lattice_angle_2 = 0.f;
|
||||
float infill_lock_depth = 0;
|
||||
float skin_infill_depth = 0;
|
||||
bool symmetric_infill_y_axis = false;
|
||||
|
||||
// Params for 2D honeycomb
|
||||
float infill_overhang_angle = 60.f;
|
||||
|
@ -85,7 +87,6 @@ struct SurfaceFillParams
|
|||
RETURN_COMPARE_NON_EQUAL(spacing);
|
||||
RETURN_COMPARE_NON_EQUAL(overlap);
|
||||
RETURN_COMPARE_NON_EQUAL(angle);
|
||||
RETURN_COMPARE_NON_EQUAL(rotate_angle);
|
||||
RETURN_COMPARE_NON_EQUAL(density);
|
||||
// RETURN_COMPARE_NON_EQUAL_TYPED(unsigned, dont_adjust);
|
||||
RETURN_COMPARE_NON_EQUAL(anchor_length);
|
||||
|
@ -100,33 +101,36 @@ struct SurfaceFillParams
|
|||
RETURN_COMPARE_NON_EQUAL(solid_infill_speed);
|
||||
RETURN_COMPARE_NON_EQUAL(lattice_angle_1);
|
||||
RETURN_COMPARE_NON_EQUAL(lattice_angle_2);
|
||||
RETURN_COMPARE_NON_EQUAL(infill_overhang_angle);
|
||||
RETURN_COMPARE_NON_EQUAL(symmetric_infill_y_axis);
|
||||
RETURN_COMPARE_NON_EQUAL(infill_lock_depth);
|
||||
RETURN_COMPARE_NON_EQUAL(skin_infill_depth); RETURN_COMPARE_NON_EQUAL(infill_overhang_angle);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator==(const SurfaceFillParams &rhs) const {
|
||||
return this->extruder == rhs.extruder &&
|
||||
this->pattern == rhs.pattern &&
|
||||
this->spacing == rhs.spacing &&
|
||||
this->overlap == rhs.overlap &&
|
||||
this->angle == rhs.angle &&
|
||||
this->rotate_angle == rhs.rotate_angle &&
|
||||
this->bridge == rhs.bridge &&
|
||||
this->bridge_angle == rhs.bridge_angle &&
|
||||
this->density == rhs.density &&
|
||||
// this->dont_adjust == rhs.dont_adjust &&
|
||||
this->anchor_length == rhs.anchor_length &&
|
||||
this->anchor_length_max == rhs.anchor_length_max &&
|
||||
this->flow == rhs.flow &&
|
||||
this->extrusion_role == rhs.extrusion_role &&
|
||||
this->sparse_infill_speed == rhs.sparse_infill_speed &&
|
||||
this->top_surface_speed == rhs.top_surface_speed &&
|
||||
this->solid_infill_speed == rhs.solid_infill_speed &&
|
||||
this->lattice_angle_1 == rhs.lattice_angle_1 &&
|
||||
this->lattice_angle_2 == rhs.lattice_angle_2 &&
|
||||
bool operator==(const SurfaceFillParams &rhs) const {
|
||||
return this->extruder == rhs.extruder &&
|
||||
this->pattern == rhs.pattern &&
|
||||
this->spacing == rhs.spacing &&
|
||||
this->overlap == rhs.overlap &&
|
||||
this->angle == rhs.angle &&
|
||||
this->bridge == rhs.bridge &&
|
||||
this->bridge_angle == rhs.bridge_angle &&
|
||||
this->density == rhs.density &&
|
||||
// this->dont_adjust == rhs.dont_adjust &&
|
||||
this->anchor_length == rhs.anchor_length &&
|
||||
this->anchor_length_max == rhs.anchor_length_max &&
|
||||
this->flow == rhs.flow &&
|
||||
this->extrusion_role == rhs.extrusion_role &&
|
||||
this->sparse_infill_speed == rhs.sparse_infill_speed &&
|
||||
this->top_surface_speed == rhs.top_surface_speed &&
|
||||
this->solid_infill_speed == rhs.solid_infill_speed &&
|
||||
this->lattice_angle_1 == rhs.lattice_angle_1 &&
|
||||
this->lattice_angle_2 == rhs.lattice_angle_2 &&
|
||||
this->infill_lock_depth == rhs.infill_lock_depth &&
|
||||
this->skin_infill_depth == rhs.skin_infill_depth &&
|
||||
this->infill_overhang_angle == rhs.infill_overhang_angle;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct SurfaceFill {
|
||||
|
@ -602,16 +606,34 @@ void split_solid_surface(size_t layer_id, const SurfaceFill &fill, ExPolygons &n
|
|||
#endif
|
||||
}
|
||||
|
||||
std::vector<SurfaceFill> group_fills(const Layer &layer)
|
||||
std::vector<SurfaceFill> group_fills(const Layer &layer, LockRegionParam &lock_param)
|
||||
{
|
||||
std::vector<SurfaceFill> surface_fills;
|
||||
|
||||
// Fill in a map of a region & surface to SurfaceFillParams.
|
||||
std::set<SurfaceFillParams> set_surface_params;
|
||||
std::vector<std::vector<const SurfaceFillParams*>> region_to_surface_params(layer.regions().size(), std::vector<const SurfaceFillParams*>());
|
||||
SurfaceFillParams params;
|
||||
bool has_internal_voids = false;
|
||||
const PrintObjectConfig& object_config = layer.object()->config();
|
||||
|
||||
auto append_flow_param = [](std::map<Flow, ExPolygons> &flow_params, Flow flow, const ExPolygon &exp) {
|
||||
auto it = flow_params.find(flow);
|
||||
if (it == flow_params.end())
|
||||
flow_params.insert({flow, {exp}});
|
||||
else
|
||||
it->second.push_back(exp);
|
||||
it++;
|
||||
};
|
||||
|
||||
auto append_density_param = [](std::map<float, ExPolygons> &density_params, float density, const ExPolygon &exp) {
|
||||
auto it = density_params.find(density);
|
||||
if (it == density_params.end())
|
||||
density_params.insert({density, {exp}});
|
||||
else
|
||||
it->second.push_back(exp);
|
||||
it++;
|
||||
};
|
||||
|
||||
for (size_t region_id = 0; region_id < layer.regions().size(); ++ region_id) {
|
||||
const LayerRegion &layerm = *layer.regions()[region_id];
|
||||
region_to_surface_params[region_id].assign(layerm.fill_surfaces.size(), nullptr);
|
||||
|
@ -628,8 +650,19 @@ std::vector<SurfaceFill> group_fills(const Layer &layer)
|
|||
params.lattice_angle_1 = region_config.lattice_angle_1;
|
||||
params.lattice_angle_2 = region_config.lattice_angle_2;
|
||||
params.infill_overhang_angle = region_config.infill_overhang_angle;
|
||||
if (params.pattern == ipLockedZag) {
|
||||
params.infill_lock_depth = scale_(region_config.infill_lock_depth);
|
||||
params.skin_infill_depth = scale_(region_config.skin_infill_depth);
|
||||
}
|
||||
if (params.pattern == ipCrossZag || params.pattern == ipLockedZag) {
|
||||
params.symmetric_infill_y_axis = region_config.symmetric_infill_y_axis;
|
||||
} else if (params.pattern == ipZigZag) {
|
||||
|
||||
if (surface.is_solid()) {
|
||||
|
||||
params.symmetric_infill_y_axis = region_config.symmetric_infill_y_axis;
|
||||
}
|
||||
|
||||
if (surface.is_solid()) {
|
||||
params.density = 100.f;
|
||||
//FIXME for non-thick bridges, shall we allow a bottom surface pattern?
|
||||
if (surface.is_solid_infill())
|
||||
|
@ -667,10 +700,8 @@ std::vector<SurfaceFill> group_fills(const Layer &layer)
|
|||
params.bridge_angle = float(surface.bridge_angle);
|
||||
if (params.extrusion_role == erInternalInfill) {
|
||||
params.angle = float(Geometry::deg2rad(region_config.infill_direction.value));
|
||||
params.rotate_angle = (params.pattern == ipRectilinear || params.pattern == ipLine);
|
||||
} else {
|
||||
params.angle = float(Geometry::deg2rad(region_config.solid_infill_direction.value));
|
||||
params.rotate_angle = region_config.rotate_solid_infill_direction;
|
||||
}
|
||||
|
||||
// Calculate the actual flow we'll be using for this infill.
|
||||
|
@ -709,7 +740,28 @@ std::vector<SurfaceFill> group_fills(const Layer &layer)
|
|||
params.anchor_length = std::min(params.anchor_length, params.anchor_length_max);
|
||||
}
|
||||
|
||||
auto it_params = set_surface_params.find(params);
|
||||
//get locked region param
|
||||
if (params.pattern == ipLockedZag){
|
||||
const PrintObject *object = layerm.layer()->object();
|
||||
auto nozzle_diameter = float(object->print()->config().nozzle_diameter.get_at(layerm.region().extruder(extrusion_role) - 1));
|
||||
Flow skin_flow = params.bridge ? params.flow : Flow::new_from_config_width(extrusion_role, region_config.skin_infill_line_width, nozzle_diameter, float((surface.thickness == -1) ? layer.height : surface.thickness));
|
||||
//add skin flow
|
||||
append_flow_param(lock_param.skin_flow_params, skin_flow, surface.expolygon);
|
||||
|
||||
Flow skeleton_flow = params.bridge ? params.flow : Flow::new_from_config_width(extrusion_role, region_config.skeleton_infill_line_width, nozzle_diameter, float((surface.thickness == -1) ? layer.height : surface.thickness)) ;
|
||||
// add skeleton flow
|
||||
append_flow_param(lock_param.skeleton_flow_params, skeleton_flow, surface.expolygon);
|
||||
|
||||
// add skin density
|
||||
append_density_param(lock_param.skin_density_params, float(0.01 * region_config.skin_infill_density), surface.expolygon);
|
||||
|
||||
// add skin density
|
||||
append_density_param(lock_param.skeleton_density_params, float(0.01 * region_config.skeleton_infill_density), surface.expolygon);
|
||||
|
||||
}
|
||||
|
||||
auto it_params = set_surface_params.find(params);
|
||||
|
||||
if (it_params == set_surface_params.end())
|
||||
it_params = set_surface_params.insert(it_params, params);
|
||||
region_to_surface_params[region_id][&surface - &layerm.fill_surfaces.surfaces.front()] = &(*it_params);
|
||||
|
@ -829,7 +881,6 @@ std::vector<SurfaceFill> group_fills(const Layer &layer)
|
|||
params.density = 100.f;
|
||||
params.extrusion_role = erSolidInfill;
|
||||
params.angle = float(Geometry::deg2rad(layerm.region().config().solid_infill_direction.value));
|
||||
params.rotate_angle = layerm.region().config().rotate_solid_infill_direction;
|
||||
// calculate the actual flow we'll be using for this infill
|
||||
params.flow = layerm.flow(frSolidInfill);
|
||||
params.spacing = params.flow.spacing();
|
||||
|
@ -914,8 +965,8 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
|
|||
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
||||
// this->export_region_fill_surfaces_to_svg_debug("10_fill-initial");
|
||||
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
|
||||
|
||||
std::vector<SurfaceFill> surface_fills = group_fills(*this);
|
||||
LockRegionParam lock_param;
|
||||
std::vector<SurfaceFill> surface_fills = group_fills(*this, lock_param);
|
||||
const Slic3r::BoundingBox bbox = this->object()->bounding_box();
|
||||
const auto resolution = this->object()->print()->config().resolution.value;
|
||||
|
||||
|
@ -933,14 +984,22 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
|
|||
f->layer_id = this->id();
|
||||
f->z = this->print_z;
|
||||
f->angle = surface_fill.params.angle;
|
||||
f->rotate_angle = surface_fill.params.rotate_angle;
|
||||
f->adapt_fill_octree = (surface_fill.params.pattern == ipSupportCubic) ? support_fill_octree : adaptive_fill_octree;
|
||||
f->print_config = &this->object()->print()->config();
|
||||
f->print_object_config = &this->object()->config();
|
||||
|
||||
if (surface_fill.params.pattern == ipLightning)
|
||||
f->adapt_fill_octree = (surface_fill.params.pattern == ipSupportCubic) ? support_fill_octree : adaptive_fill_octree;
|
||||
if (surface_fill.params.pattern == ipConcentricInternal) {
|
||||
FillConcentricInternal *fill_concentric = dynamic_cast<FillConcentricInternal *>(f.get());
|
||||
assert(fill_concentric != nullptr);
|
||||
fill_concentric->print_config = &this->object()->print()->config();
|
||||
fill_concentric->print_object_config = &this->object()->config();
|
||||
} else if (surface_fill.params.pattern == ipConcentric) {
|
||||
FillConcentric *fill_concentric = dynamic_cast<FillConcentric *>(f.get());
|
||||
assert(fill_concentric != nullptr);
|
||||
fill_concentric->print_config = &this->object()->print()->config();
|
||||
fill_concentric->print_object_config = &this->object()->config();
|
||||
} else if (surface_fill.params.pattern == ipLightning)
|
||||
dynamic_cast<FillLightning::Filler*>(f.get())->generator = lightning_generator;
|
||||
|
||||
// calculate flow spacing for infill pattern generation
|
||||
bool using_internal_flow = ! surface_fill.surface.is_solid() && ! surface_fill.params.bridge;
|
||||
double link_max_length = 0.;
|
||||
|
@ -979,11 +1038,41 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
|
|||
params.extrusion_role = surface_fill.params.extrusion_role;
|
||||
params.using_internal_flow = using_internal_flow;
|
||||
params.no_extrusion_overlap = surface_fill.params.overlap;
|
||||
params.config = &layerm->region().config();
|
||||
auto ®ion_config = layerm->region().config();
|
||||
|
||||
ConfigOptionFloats rotate_angles;
|
||||
rotate_angles.deserialize( surface_fill.params.extrusion_role == erInternalInfill ? region_config.sparse_infill_rotate_template.value : region_config.solid_infill_rotate_template.value);
|
||||
auto rotate_angle_idx = f->layer_id % rotate_angles.size();
|
||||
f->rotate_angle = Geometry::deg2rad(rotate_angles.values[rotate_angle_idx]);
|
||||
|
||||
params.config = ®ion_config;
|
||||
params.pattern = surface_fill.params.pattern;
|
||||
if( surface_fill.params.pattern == ipLockedZag ) {
|
||||
params.locked_zag = true;
|
||||
params.infill_lock_depth = surface_fill.params.infill_lock_depth;
|
||||
params.skin_infill_depth = surface_fill.params.skin_infill_depth;
|
||||
f->set_lock_region_param(lock_param);
|
||||
}
|
||||
if (surface_fill.params.pattern == ipCrossZag || surface_fill.params.pattern == ipLockedZag) {
|
||||
if (f->layer_id % 2 == 0) {
|
||||
params.horiz_move -= scale_(region_config.infill_shift_step) * (f->layer_id / 2);
|
||||
} else {
|
||||
params.horiz_move += scale_(region_config.infill_shift_step) * (f->layer_id / 2);
|
||||
}
|
||||
|
||||
params.symmetric_infill_y_axis = surface_fill.params.symmetric_infill_y_axis;
|
||||
|
||||
}
|
||||
if (surface_fill.params.pattern == ipGrid)
|
||||
params.can_reverse = false;
|
||||
for (ExPolygon& expoly : surface_fill.expolygons) {
|
||||
f->no_overlap_expolygons = intersection_ex(surface_fill.no_overlap_expolygons, ExPolygons() = {expoly}, ApplySafetyOffset::Yes);
|
||||
|
||||
f->no_overlap_expolygons = intersection_ex(surface_fill.no_overlap_expolygons, ExPolygons() = {expoly}, ApplySafetyOffset::Yes);
|
||||
if (params.symmetric_infill_y_axis) {
|
||||
params.symmetric_y_axis = f->extended_object_bounding_box().center().x();
|
||||
expoly.symmetric_y(params.symmetric_y_axis);
|
||||
}
|
||||
|
||||
// Spacing is modified by the filler to indicate adjustments. Reset it for each expolygon.
|
||||
f->spacing = surface_fill.params.spacing;
|
||||
surface_fill.surface.expolygon = std::move(expoly);
|
||||
|
@ -1023,9 +1112,10 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
|
|||
|
||||
Polylines Layer::generate_sparse_infill_polylines_for_anchoring(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive::Octree* support_fill_octree, FillLightning::Generator* lightning_generator) const
|
||||
{
|
||||
std::vector<SurfaceFill> surface_fills = group_fills(*this);
|
||||
const Slic3r::BoundingBox bbox = this->object()->bounding_box();
|
||||
const auto resolution = this->object()->print()->config().resolution.value;
|
||||
LockRegionParam skin_inner_param;
|
||||
std::vector<SurfaceFill> surface_fills = group_fills(*this, skin_inner_param);
|
||||
const Slic3r::BoundingBox bbox = this->object()->bounding_box();
|
||||
const auto resolution = this->object()->print()->config().resolution.value;
|
||||
|
||||
Polylines sparse_infill_polylines{};
|
||||
|
||||
|
@ -1059,7 +1149,10 @@ Polylines Layer::generate_sparse_infill_polylines_for_anchoring(FillAdaptive::Oc
|
|||
case ipTpmsD:
|
||||
case ipHilbertCurve:
|
||||
case ipArchimedeanChords:
|
||||
case ipOctagramSpiral: break;
|
||||
case ipOctagramSpiral:
|
||||
case ipZigZag:
|
||||
case ipCrossZag:
|
||||
case ipLockedZag: break;
|
||||
}
|
||||
|
||||
// Create the filler object.
|
||||
|
|
|
@ -15,6 +15,10 @@ public:
|
|||
Fill* clone() const override { return new Fill3DHoneycomb(*this); };
|
||||
~Fill3DHoneycomb() override {}
|
||||
|
||||
// require bridge flow since most of this pattern hangs in air
|
||||
bool use_bridge_flow() const override { return true; }
|
||||
bool is_self_crossing() override { return false; }
|
||||
|
||||
protected:
|
||||
void _fill_surface_single(
|
||||
const FillParams ¶ms,
|
||||
|
|
|
@ -71,6 +71,7 @@ protected:
|
|||
// may not be optimal as the internal infill lines may get extruded before the long infill
|
||||
// lines to which the short infill lines are supposed to anchor.
|
||||
bool no_sort() const override { return false; }
|
||||
bool is_self_crossing() override { return true; }
|
||||
};
|
||||
|
||||
} // namespace FillAdaptive
|
||||
|
|
|
@ -67,6 +67,9 @@ Fill* Fill::new_from_type(const InfillPattern type)
|
|||
// BBS: for bottom and top surface only
|
||||
// Orca: Replace BBS implementation with Prusa implementation
|
||||
case ipMonotonicLine: return new FillMonotonicLines();
|
||||
case ipZigZag: return new FillZigZag();
|
||||
case ipCrossZag: return new FillCrossZag();
|
||||
case ipLockedZag: return new FillLockedZag();
|
||||
default: throw Slic3r::InvalidArgument("unknown type");
|
||||
}
|
||||
}
|
||||
|
@ -243,7 +246,7 @@ void Fill::_create_gap_fill(const Surface* surface, const FillParams& params, Ex
|
|||
|
||||
// Calculate a new spacing to fill width with possibly integer number of lines,
|
||||
// the first and last line being centered at the interval ends.
|
||||
// This function possibly increases the spacing, never decreases,
|
||||
// This function possibly increases the spacing, never decreases,
|
||||
// and for a narrow width the increase in spacing may become severe,
|
||||
// therefore the adjustment is limited to 20% increase.
|
||||
coord_t Fill::_adjust_solid_spacing(const coord_t width, const coord_t distance)
|
||||
|
@ -252,8 +255,8 @@ coord_t Fill::_adjust_solid_spacing(const coord_t width, const coord_t distance)
|
|||
assert(distance > 0);
|
||||
// floor(width / distance)
|
||||
const auto number_of_intervals = coord_t((width - EPSILON) / distance);
|
||||
coord_t distance_new = (number_of_intervals == 0) ?
|
||||
distance :
|
||||
coord_t distance_new = (number_of_intervals == 0) ?
|
||||
distance :
|
||||
coord_t((width - EPSILON) / number_of_intervals);
|
||||
const coordf_t factor = coordf_t(distance_new) / coordf_t(distance);
|
||||
assert(factor > 1. - 1e-5);
|
||||
|
@ -279,8 +282,8 @@ std::pair<float, Point> Fill::_infill_direction(const Surface *surface) const
|
|||
|
||||
// Bounding box is the bounding box of a perl object Slic3r::Print::Object (c++ object Slic3r::PrintObject)
|
||||
// The bounding box is only undefined in unit tests.
|
||||
Point out_shift = empty(this->bounding_box) ?
|
||||
surface->expolygon.contour.bounding_box().center() :
|
||||
Point out_shift = empty(this->bounding_box) ?
|
||||
surface->expolygon.contour.bounding_box().center() :
|
||||
this->bounding_box.center();
|
||||
|
||||
#if 0
|
||||
|
@ -354,10 +357,10 @@ struct ContourIntersectionPoint {
|
|||
bool could_take_next() const throw() { return ! this->consumed && this->contour_not_taken_length_next > SCALED_EPSILON; }
|
||||
|
||||
// Could extrude a complete segment from this to this->prev_on_contour.
|
||||
bool could_connect_prev() const throw()
|
||||
bool could_connect_prev() const throw()
|
||||
{ return ! this->consumed && this->prev_on_contour != this && ! this->prev_on_contour->consumed && ! this->prev_trimmed && ! this->prev_on_contour->next_trimmed; }
|
||||
// Could extrude a complete segment from this to this->next_on_contour.
|
||||
bool could_connect_next() const throw()
|
||||
bool could_connect_next() const throw()
|
||||
{ return ! this->consumed && this->next_on_contour != this && ! this->next_on_contour->consumed && ! this->next_trimmed && ! this->next_on_contour->prev_trimmed; }
|
||||
};
|
||||
|
||||
|
@ -566,7 +569,7 @@ static void take(Polyline &pl1, const Polyline &pl2, const Points &contour, Cont
|
|||
}
|
||||
|
||||
static void take_limited(
|
||||
Polyline &pl1, const Points &contour, const std::vector<double> ¶ms,
|
||||
Polyline &pl1, const Points &contour, const std::vector<double> ¶ms,
|
||||
ContourIntersectionPoint *cp_start, ContourIntersectionPoint *cp_end, bool clockwise, double take_max_length, double line_half_width)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
|
@ -730,8 +733,8 @@ static inline SegmentPoint clip_end_segment_and_point(const Points &polyline, do
|
|||
// Calculate intersection of a line with a thick segment.
|
||||
// Returns Eucledian parameters of the line / thick segment overlap.
|
||||
static inline bool line_rounded_thick_segment_collision(
|
||||
const Vec2d &line_a, const Vec2d &line_b,
|
||||
const Vec2d &segment_a, const Vec2d &segment_b, const double offset,
|
||||
const Vec2d &line_a, const Vec2d &line_b,
|
||||
const Vec2d &segment_a, const Vec2d &segment_b, const double offset,
|
||||
std::pair<double, double> &out_interval)
|
||||
{
|
||||
const Vec2d line_v0 = line_b - line_a;
|
||||
|
@ -794,8 +797,8 @@ static inline bool line_rounded_thick_segment_collision(
|
|||
std::pair<double, double> interval;
|
||||
if (Geometry::liang_barsky_line_clipping_interval(
|
||||
Vec2d(line_p0.dot(dir_x), line_p0.dot(dir_y)),
|
||||
Vec2d(line_v0.dot(dir_x), line_v0.dot(dir_y)),
|
||||
BoundingBoxf(Vec2d(0., - offset), Vec2d(segment_l, offset)),
|
||||
Vec2d(line_v0.dot(dir_x), line_v0.dot(dir_y)),
|
||||
BoundingBoxf(Vec2d(0., - offset), Vec2d(segment_l, offset)),
|
||||
interval))
|
||||
extend_interval(interval.first, interval.second);
|
||||
} else
|
||||
|
@ -1155,7 +1158,7 @@ void mark_boundary_segments_touching_infill(
|
|||
// Clip the infill polyline by the Eucledian distance along the polyline.
|
||||
SegmentPoint start_point = clip_start_segment_and_point(polyline.points, clip_distance);
|
||||
SegmentPoint end_point = clip_end_segment_and_point(polyline.points, clip_distance);
|
||||
if (start_point.valid() && end_point.valid() &&
|
||||
if (start_point.valid() && end_point.valid() &&
|
||||
(start_point.idx_segment < end_point.idx_segment || (start_point.idx_segment == end_point.idx_segment && start_point.t < end_point.t))) {
|
||||
// The clipped polyline is non-empty.
|
||||
#ifdef INFILL_DEBUG_OUTPUT
|
||||
|
@ -1295,21 +1298,21 @@ struct BoundaryInfillGraph
|
|||
};
|
||||
|
||||
static Direction dir(const Point &p1, const Point &p2) {
|
||||
return p1.x() == p2.x() ?
|
||||
return p1.x() == p2.x() ?
|
||||
(p1.y() < p2.y() ? Up : Down) :
|
||||
(p1.x() < p2.x() ? Right : Left);
|
||||
}
|
||||
|
||||
const Direction dir_prev(const ContourIntersectionPoint &cp) const {
|
||||
assert(cp.prev_on_contour);
|
||||
return cp.could_take_prev() ?
|
||||
return cp.could_take_prev() ?
|
||||
dir(this->point(cp), this->point(*cp.prev_on_contour)) :
|
||||
Taken;
|
||||
}
|
||||
|
||||
const Direction dir_next(const ContourIntersectionPoint &cp) const {
|
||||
assert(cp.next_on_contour);
|
||||
return cp.could_take_next() ?
|
||||
return cp.could_take_next() ?
|
||||
dir(this->point(cp), this->point(*cp.next_on_contour)) :
|
||||
Taken;
|
||||
}
|
||||
|
@ -1367,7 +1370,7 @@ static inline void mark_boundary_segments_overlapping_infill(
|
|||
assert(interval.first == 0.);
|
||||
double len_out = closed_contour_distance_ccw(contour_params[cp.point_idx], contour_params[i], contour_params.back()) + interval.second;
|
||||
if (len_out < cp.contour_not_taken_length_next) {
|
||||
// Leaving the infill line region before exiting cp.contour_not_taken_length_next,
|
||||
// Leaving the infill line region before exiting cp.contour_not_taken_length_next,
|
||||
// thus at least some of the contour is outside and we will extrude this segment.
|
||||
inside = false;
|
||||
break;
|
||||
|
@ -1399,7 +1402,7 @@ static inline void mark_boundary_segments_overlapping_infill(
|
|||
assert(interval.first == 0.);
|
||||
double len_out = closed_contour_distance_cw(contour_params[cp.point_idx], contour_params[i], contour_params.back()) + interval.second;
|
||||
if (len_out < cp.contour_not_taken_length_prev) {
|
||||
// Leaving the infill line region before exiting cp.contour_not_taken_length_next,
|
||||
// Leaving the infill line region before exiting cp.contour_not_taken_length_next,
|
||||
// thus at least some of the contour is outside and we will extrude this segment.
|
||||
inside = false;
|
||||
break;
|
||||
|
@ -1496,7 +1499,7 @@ BoundaryInfillGraph create_boundary_infill_graph(const Polylines &infill_ordered
|
|||
ContourIntersectionPoint *pthis = &out.map_infill_end_point_to_boundary[it->second];
|
||||
if (pprev) {
|
||||
pprev->next_on_contour = pthis;
|
||||
pthis->prev_on_contour = pprev;
|
||||
pthis->prev_on_contour = pprev;
|
||||
} else
|
||||
pfirst = pthis;
|
||||
contour_intersection_points.emplace_back(pthis);
|
||||
|
@ -1521,7 +1524,7 @@ BoundaryInfillGraph create_boundary_infill_graph(const Polylines &infill_ordered
|
|||
ip->param = contour_params[ip->point_idx];
|
||||
// and measure distance to the previous and next intersection point.
|
||||
const double contour_length = contour_params.back();
|
||||
for (ContourIntersectionPoint *ip : contour_intersection_points)
|
||||
for (ContourIntersectionPoint *ip : contour_intersection_points)
|
||||
if (ip->next_on_contour == ip) {
|
||||
assert(ip->prev_on_contour == ip);
|
||||
ip->contour_not_taken_length_prev = ip->contour_not_taken_length_next = contour_length;
|
||||
|
@ -1556,6 +1559,18 @@ BoundaryInfillGraph create_boundary_infill_graph(const Polylines &infill_ordered
|
|||
return out;
|
||||
}
|
||||
|
||||
// The extended bounding box of the whole object that covers any rotation of every layer.
|
||||
BoundingBox Fill::extended_object_bounding_box() const
|
||||
{
|
||||
BoundingBox out = bounding_box;
|
||||
out.merge(Point(out.min.y(), out.min.x()));
|
||||
out.merge(Point(out.max.y(), out.max.x()));
|
||||
|
||||
// The bounding box is scaled by sqrt(2.) to ensure that the bounding box
|
||||
// covers any possible rotations.
|
||||
return out.scaled(sqrt(2.));
|
||||
}
|
||||
|
||||
void Fill::connect_infill(Polylines &&infill_ordered, const std::vector<const Polygon*> &boundary_src, const BoundingBox &bbox, Polylines &polylines_out, const double spacing, const FillParams ¶ms)
|
||||
{
|
||||
assert(! infill_ordered.empty());
|
||||
|
@ -1927,14 +1942,14 @@ static inline void base_support_extend_infill_lines(Polylines &infill, BoundaryI
|
|||
// The contour is supposed to enter the "forbidden" zone outside of the (left, right) band at tbegin and also at tend.
|
||||
static inline void emit_loops_in_band(
|
||||
// Vertical band, which will trim the contour between tbegin and tend.
|
||||
coord_t left,
|
||||
coord_t left,
|
||||
coord_t right,
|
||||
// Contour and its parametrization.
|
||||
const Points &contour,
|
||||
const std::vector<double> &contour_params,
|
||||
// Span of the parameters of an arch to trim with the vertical band.
|
||||
double tbegin,
|
||||
double tend,
|
||||
double tend,
|
||||
// Minimum arch length to put into polylines_out. Shorter arches are not necessary to support a dense support infill.
|
||||
double min_length,
|
||||
Polylines &polylines_out)
|
||||
|
@ -1990,13 +2005,13 @@ static inline void emit_loops_in_band(
|
|||
};
|
||||
|
||||
enum InOutBand {
|
||||
Entering,
|
||||
Entering,
|
||||
Leaving,
|
||||
};
|
||||
|
||||
class State {
|
||||
public:
|
||||
State(coord_t left, coord_t right, double min_length, Polylines &polylines_out) :
|
||||
State(coord_t left, coord_t right, double min_length, Polylines &polylines_out) :
|
||||
m_left(left), m_right(right), m_min_length(min_length), m_polylines_out(polylines_out) {}
|
||||
|
||||
void add_inner_point(const Point* p)
|
||||
|
@ -2297,7 +2312,7 @@ void Fill::connect_base_support(Polylines &&infill_ordered, const std::vector<co
|
|||
#endif // INFILL_DEBUG_OUTPUT
|
||||
|
||||
base_support_extend_infill_lines(infill_ordered, graph, spacing, params);
|
||||
|
||||
|
||||
#ifdef INFILL_DEBUG_OUTPUT
|
||||
export_partial_infill_to_svg(debug_out_path("connect_base_support-extended-%03d.svg", iRun), graph, infill_ordered, polylines_out);
|
||||
#endif // INFILL_DEBUG_OUTPUT
|
||||
|
@ -2332,7 +2347,7 @@ void Fill::connect_base_support(Polylines &&infill_ordered, const std::vector<co
|
|||
};
|
||||
|
||||
// Connect infill lines at cp and cpo_next_on_contour.
|
||||
// If the complete arch cannot be taken, then
|
||||
// If the complete arch cannot be taken, then
|
||||
// if (take_first)
|
||||
// take the infill line at cp and an arc from cp towards cp.next_on_contour.
|
||||
// else
|
||||
|
@ -2626,7 +2641,7 @@ void Fill::connect_base_support(Polylines &&infill_ordered, const std::vector<co
|
|||
for (ContourIntersectionPoint &cp : graph.map_infill_end_point_to_boundary) {
|
||||
const SupportArcCost &cost_prev = arches[(&cp - graph.map_infill_end_point_to_boundary.data()) * 2];
|
||||
const SupportArcCost &cost_next = *(&cost_prev + 1);
|
||||
if (cp.contour_not_taken_length_prev > SCALED_EPSILON &&
|
||||
if (cp.contour_not_taken_length_prev > SCALED_EPSILON &&
|
||||
(cost_prev.self_loop ?
|
||||
cost_prev.cost > cap_cost :
|
||||
cost_prev.cost > cost_veryhigh)) {
|
||||
|
@ -2643,7 +2658,7 @@ void Fill::connect_base_support(Polylines &&infill_ordered, const std::vector<co
|
|||
polylines_out.emplace_back(std::move(pl));
|
||||
}
|
||||
}
|
||||
if (cp.contour_not_taken_length_next > SCALED_EPSILON &&
|
||||
if (cp.contour_not_taken_length_next > SCALED_EPSILON &&
|
||||
(cost_next.self_loop ?
|
||||
cost_next.cost > cap_cost :
|
||||
cost_next.cost > cost_veryhigh)) {
|
||||
|
|
|
@ -36,6 +36,15 @@ public:
|
|||
InfillFailedException() : Slic3r::RuntimeError("Infill failed") {}
|
||||
};
|
||||
|
||||
struct LockRegionParam
|
||||
{
|
||||
LockRegionParam() {}
|
||||
std::map<float, ExPolygons> skin_density_params;
|
||||
std::map<float, ExPolygons> skeleton_density_params;
|
||||
std::map<Flow, ExPolygons> skin_flow_params;
|
||||
std::map<Flow, ExPolygons> skeleton_flow_params;
|
||||
};
|
||||
|
||||
struct FillParams
|
||||
{
|
||||
bool full_infill() const { return density > 0.9999f; }
|
||||
|
@ -72,6 +81,7 @@ struct FillParams
|
|||
// For 2D lattice
|
||||
coordf_t lattice_angle_1 { 0.f };
|
||||
coordf_t lattice_angle_2 { 0.f };
|
||||
InfillPattern pattern{ ipRectilinear };
|
||||
|
||||
// For 2D Honeycomb
|
||||
float infill_overhang_angle { 60 };
|
||||
|
@ -85,6 +95,13 @@ struct FillParams
|
|||
const PrintRegionConfig* config{ nullptr };
|
||||
bool dont_sort{ false }; // do not sort the lines, just simply connect them
|
||||
bool can_reverse{true};
|
||||
|
||||
float horiz_move{0.0}; //move infill to get cross zag pattern
|
||||
bool symmetric_infill_y_axis{false};
|
||||
coord_t symmetric_y_axis{0};
|
||||
bool locked_zag{false};
|
||||
float infill_lock_depth{0.0};
|
||||
float skin_infill_depth{0.0};
|
||||
};
|
||||
static_assert(IsTriviallyCopyable<FillParams>::value, "FillParams class is not POD (and it should be - see constructor).");
|
||||
|
||||
|
@ -102,7 +119,7 @@ public:
|
|||
// in radians, ccw, 0 = East
|
||||
float angle;
|
||||
// Orca: enable angle shifting for layer change
|
||||
bool rotate_angle{ true };
|
||||
float rotate_angle{ M_PI/180.0 };
|
||||
// In scaled coordinates. Maximum lenght of a perimeter segment connecting two infill lines.
|
||||
// Used by the FillRectilinear2, FillGrid2, FillTriangles, FillStars and FillCubic.
|
||||
// If left to zero, the links will not be limited.
|
||||
|
@ -135,20 +152,25 @@ public:
|
|||
static bool use_bridge_flow(const InfillPattern type);
|
||||
|
||||
void set_bounding_box(const Slic3r::BoundingBox &bbox) { bounding_box = bbox; }
|
||||
|
||||
BoundingBox extended_object_bounding_box() const;
|
||||
// Use bridge flow for the fill?
|
||||
virtual bool use_bridge_flow() const { return false; }
|
||||
|
||||
// Do not sort the fill lines to optimize the print head path?
|
||||
virtual bool no_sort() const { return false; }
|
||||
|
||||
virtual bool is_self_crossing() = 0;
|
||||
|
||||
// Return true if infill has a consistent pattern between layers.
|
||||
virtual bool has_consistent_pattern() const { return false; }
|
||||
|
||||
// Perform the fill.
|
||||
virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms);
|
||||
virtual ThickPolylines fill_surface_arachne(const Surface* surface, const FillParams& params);
|
||||
|
||||
virtual void set_lock_region_param(const LockRegionParam &lock_param){};
|
||||
// BBS: this method is used to fill the ExtrusionEntityCollection.
|
||||
// It call fill_surface by default
|
||||
virtual void fill_surface_extrusion(const Surface* surface, const FillParams& params, ExtrusionEntitiesPtr& out);
|
||||
virtual void fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, ExtrusionEntitiesPtr &out);
|
||||
|
||||
protected:
|
||||
Fill() :
|
||||
|
@ -159,7 +181,7 @@ protected:
|
|||
overlap(0.),
|
||||
// Initial angle is undefined.
|
||||
angle(FLT_MAX),
|
||||
rotate_angle(true),
|
||||
rotate_angle(M_PI/180.0),
|
||||
link_max_length(0),
|
||||
loop_clipping(0),
|
||||
// The initial bounding box is empty, therefore undefined.
|
||||
|
@ -168,11 +190,11 @@ protected:
|
|||
|
||||
// The expolygon may be modified by the method to avoid a copy.
|
||||
virtual void _fill_surface_single(
|
||||
const FillParams & /* params */,
|
||||
const FillParams & /* params */,
|
||||
unsigned int /* thickness_layers */,
|
||||
const std::pair<float, Point> & /* direction */,
|
||||
const std::pair<float, Point> & /* direction */,
|
||||
ExPolygon /* expolygon */,
|
||||
Polylines & /* polylines_out */) {};
|
||||
Polylines & /* polylines_out */) {}
|
||||
|
||||
// Used for concentric infill to generate ThickPolylines using Arachne.
|
||||
virtual void _fill_surface_single(const FillParams& params,
|
||||
|
@ -181,7 +203,7 @@ protected:
|
|||
ExPolygon expolygon,
|
||||
ThickPolylines& thick_polylines_out) {}
|
||||
|
||||
virtual float _layer_angle(size_t idx) const { return (rotate_angle && (idx & 1)) ? float(M_PI/2.) : 0; }
|
||||
virtual float _layer_angle(size_t idx) const { return rotate_angle; }
|
||||
|
||||
virtual std::pair<float, Point> _infill_direction(const Surface *surface) const;
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ class FillConcentric : public Fill
|
|||
{
|
||||
public:
|
||||
~FillConcentric() override = default;
|
||||
bool is_self_crossing() override { return false; }
|
||||
|
||||
protected:
|
||||
Fill* clone() const override { return new FillConcentric(*this); };
|
||||
|
|
|
@ -10,6 +10,7 @@ class FillConcentricInternal : public Fill
|
|||
public:
|
||||
~FillConcentricInternal() override = default;
|
||||
void fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, ExtrusionEntitiesPtr &out) override;
|
||||
bool is_self_crossing() override { return false; }
|
||||
|
||||
protected:
|
||||
Fill* clone() const override { return new FillConcentricInternal(*this); };
|
||||
|
|
|
@ -14,6 +14,7 @@ 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(
|
||||
|
|
|
@ -15,6 +15,7 @@ public:
|
|||
|
||||
// require bridge flow since most of this pattern hangs in air
|
||||
bool use_bridge_flow() const override { return false; }
|
||||
bool is_self_crossing() override { return false; }
|
||||
|
||||
// Correction applied to regular infill angle to maximize printing
|
||||
// speed in default configuration (degrees)
|
||||
|
|
|
@ -13,6 +13,7 @@ class FillHoneycomb : public Fill
|
|||
{
|
||||
public:
|
||||
~FillHoneycomb() override {}
|
||||
bool is_self_crossing() override { return false; }
|
||||
|
||||
protected:
|
||||
Fill* clone() const override { return new FillHoneycomb(*this); };
|
||||
|
|
|
@ -20,6 +20,7 @@ class Filler : public Slic3r::Fill
|
|||
{
|
||||
public:
|
||||
~Filler() override = default;
|
||||
bool is_self_crossing() override { return false; }
|
||||
|
||||
Generator *generator { nullptr };
|
||||
protected:
|
||||
|
|
|
@ -14,6 +14,7 @@ class FillLine : public Fill
|
|||
public:
|
||||
Fill* clone() const override { return new FillLine(*this); };
|
||||
~FillLine() override = default;
|
||||
bool is_self_crossing() override { return false; }
|
||||
|
||||
protected:
|
||||
void _fill_surface_single(
|
||||
|
|
|
@ -37,6 +37,7 @@ class FillPlanePath : public Fill
|
|||
{
|
||||
public:
|
||||
~FillPlanePath() override = default;
|
||||
bool is_self_crossing() override { return false; }
|
||||
|
||||
protected:
|
||||
void _fill_surface_single(
|
||||
|
|
|
@ -987,7 +987,6 @@ static std::vector<SegmentedIntersectionLine> slice_region_by_vertical_lines(con
|
|||
throw;
|
||||
}
|
||||
#endif //INFILL_DEBUG_OUTPUT
|
||||
|
||||
return segs;
|
||||
}
|
||||
|
||||
|
@ -1352,8 +1351,11 @@ static SegmentIntersection& end_of_vertical_run(SegmentedIntersectionLine &il, S
|
|||
return const_cast<SegmentIntersection&>(end_of_vertical_run(std::as_const(il), std::as_const(start)));
|
||||
}
|
||||
|
||||
static void traverse_graph_generate_polylines(
|
||||
const ExPolygonWithOffset& poly_with_offset, const FillParams& params, const coord_t link_max_length, std::vector<SegmentedIntersectionLine>& segs, Polylines& polylines_out)
|
||||
static void traverse_graph_generate_polylines(const ExPolygonWithOffset &poly_with_offset,
|
||||
const FillParams ¶ms,
|
||||
std::vector<SegmentedIntersectionLine> &segs,
|
||||
const bool consistent_pattern,
|
||||
Polylines &polylines_out)
|
||||
{
|
||||
// For each outer only chords, measure their maximum distance to the bow of the outer contour.
|
||||
// Mark an outer only chord as consumed, if the distance is low.
|
||||
|
@ -1387,34 +1389,28 @@ static void traverse_graph_generate_polylines(
|
|||
pointLast = polylines_out.back().points.back();
|
||||
for (;;) {
|
||||
if (i_intersection == -1) {
|
||||
// The path has been interrupted. Find a next starting point, closest to the previous extruder position.
|
||||
coordf_t dist2min = std::numeric_limits<coordf_t>().max();
|
||||
for (int i_vline2 = 0; i_vline2 < int(segs.size()); ++ i_vline2) {
|
||||
// The path has been interrupted. Find a next starting point.
|
||||
for (int i_vline2 = 0; i_vline2 < int(segs.size()); ++i_vline2) {
|
||||
const SegmentedIntersectionLine &vline = segs[i_vline2];
|
||||
if (! vline.intersections.empty()) {
|
||||
if (!vline.intersections.empty()) {
|
||||
assert(vline.intersections.size() > 1);
|
||||
// Even number of intersections with the loops.
|
||||
assert((vline.intersections.size() & 1) == 0);
|
||||
assert(vline.intersections.front().type == SegmentIntersection::OUTER_LOW);
|
||||
for (int i = 0; i < int(vline.intersections.size()); ++ i) {
|
||||
const SegmentIntersection& intrsctn = vline.intersections[i];
|
||||
|
||||
// For infill that needs to be consistent between layers (like Zig Zag),
|
||||
// we are switching between forward and backward passes based on the line index.
|
||||
const bool forward_pass = !consistent_pattern || (i_vline2 % 2 == 0);
|
||||
for (int i = 0; i < int(vline.intersections.size()); ++i) {
|
||||
const int intrsctn_idx = forward_pass ? i : int(vline.intersections.size()) - i - 1;
|
||||
const SegmentIntersection &intrsctn = vline.intersections[intrsctn_idx];
|
||||
if (intrsctn.is_outer()) {
|
||||
assert(intrsctn.is_low() || i > 0);
|
||||
bool consumed = intrsctn.is_low() ?
|
||||
intrsctn.consumed_vertical_up :
|
||||
vline.intersections[i - 1].consumed_vertical_up;
|
||||
if (! consumed) {
|
||||
coordf_t dist2 = sqr(coordf_t(pointLast(0) - vline.pos)) + sqr(coordf_t(pointLast(1) - intrsctn.pos()));
|
||||
if (dist2 < dist2min) {
|
||||
dist2min = dist2;
|
||||
i_vline = i_vline2;
|
||||
i_intersection = i;
|
||||
//FIXME We are taking the first left point always. Verify, that the caller chains the paths
|
||||
// by a shortest distance, while reversing the paths if needed.
|
||||
//if (polylines_out.empty())
|
||||
// Initial state, take the first line, which is the first from the left.
|
||||
goto found;
|
||||
}
|
||||
assert(intrsctn.is_low() || intrsctn_idx > 0);
|
||||
const bool consumed = intrsctn.is_low() ? intrsctn.consumed_vertical_up : vline.intersections[intrsctn_idx - 1].consumed_vertical_up;
|
||||
if (!consumed) {
|
||||
i_vline = i_vline2;
|
||||
i_intersection = intrsctn_idx;
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1487,9 +1483,13 @@ static void traverse_graph_generate_polylines(
|
|||
// 1) Find possible connection points on the previous / next vertical line.
|
||||
int i_prev = it->left_horizontal();
|
||||
int i_next = it->right_horizontal();
|
||||
bool intersection_prev_valid = intersection_on_prev_vertical_line_valid(segs, i_vline, i_intersection);
|
||||
|
||||
// To ensure pattern consistency between layers for Zig Zag infill, we always
|
||||
// try to connect to the next vertical line and never to the previous vertical line.
|
||||
bool intersection_prev_valid = intersection_on_prev_vertical_line_valid(segs, i_vline, i_intersection) && !consistent_pattern;
|
||||
bool intersection_next_valid = intersection_on_next_vertical_line_valid(segs, i_vline, i_intersection);
|
||||
bool intersection_horizontal_valid = intersection_prev_valid || intersection_next_valid;
|
||||
|
||||
// Mark both the left and right connecting segment as consumed, because one cannot go to this intersection point as it has been consumed.
|
||||
if (i_prev != -1)
|
||||
segs[i_vline - 1].intersections[i_prev].consumed_perimeter_right = true;
|
||||
|
@ -2737,6 +2737,17 @@ static void polylines_from_paths(const std::vector<MonotonicRegionLink> &path, c
|
|||
}
|
||||
}
|
||||
|
||||
// The extended bounding box of the whole object that covers any rotation of every layer.
|
||||
BoundingBox FillRectilinear::extended_object_bounding_box() const {
|
||||
BoundingBox out = this->bounding_box;
|
||||
out.merge(Point(out.min.y(), out.min.x()));
|
||||
out.merge(Point(out.max.y(), out.max.x()));
|
||||
|
||||
// The bounding box is scaled by sqrt(2.) to ensure that the bounding box
|
||||
// covers any possible rotations.
|
||||
return out.scaled(sqrt(2.));
|
||||
}
|
||||
|
||||
bool FillRectilinear::fill_surface_by_lines(const Surface *surface, const FillParams ¶ms, float angleBase, float pattern_shift, Polylines &polylines_out)
|
||||
{
|
||||
// At the end, only the new polylines will be rotated back.
|
||||
|
@ -2749,6 +2760,8 @@ bool FillRectilinear::fill_surface_by_lines(const Surface *surface, const FillPa
|
|||
|
||||
// Rotate polygons so that we can work with vertical lines here
|
||||
std::pair<float, Point> rotate_vector = this->_infill_direction(surface);
|
||||
if (params.locked_zag)
|
||||
rotate_vector.first += float(M_PI/2.);
|
||||
rotate_vector.first += angleBase;
|
||||
|
||||
assert(params.density > 0.0001f && params.density <= 1.f);
|
||||
|
@ -2766,11 +2779,14 @@ bool FillRectilinear::fill_surface_by_lines(const Surface *surface, const FillPa
|
|||
return true;
|
||||
}
|
||||
|
||||
BoundingBox bounding_box = poly_with_offset.bounding_box_src();
|
||||
// For infill that needs to be consistent between layers (like Zig Zag),
|
||||
// we use bounding box of whole object to match vertical lines between layers.
|
||||
BoundingBox bounding_box_src = poly_with_offset.bounding_box_src();
|
||||
BoundingBox bounding_box = this->has_consistent_pattern() ? this->extended_object_bounding_box() : bounding_box_src;
|
||||
|
||||
// define flow spacing according to requested density
|
||||
if (params.full_infill() && !params.dont_adjust) {
|
||||
line_spacing = this->_adjust_solid_spacing(bounding_box.size()(0), line_spacing);
|
||||
line_spacing = this->_adjust_solid_spacing(bounding_box_src.size().x(), line_spacing);
|
||||
this->spacing = unscale<double>(line_spacing);
|
||||
} else {
|
||||
// extend bounding box so that our pattern will be aligned with other layers
|
||||
|
@ -2792,6 +2808,13 @@ bool FillRectilinear::fill_surface_by_lines(const Surface *surface, const FillPa
|
|||
if (params.full_infill())
|
||||
x0 += (line_spacing + coord_t(SCALED_EPSILON)) / 2;
|
||||
|
||||
int gap_line = params.horiz_move / line_spacing;
|
||||
if (gap_line % 2 == 0) {
|
||||
x0 += params.horiz_move - gap_line * line_spacing;
|
||||
} else {
|
||||
x0 += params.horiz_move - (gap_line - 1) * line_spacing;
|
||||
n_vlines += 1;
|
||||
}
|
||||
#ifdef SLIC3R_DEBUG
|
||||
static int iRun = 0;
|
||||
BoundingBox bbox_svg = poly_with_offset.bounding_box_outer();
|
||||
|
@ -2803,7 +2826,6 @@ bool FillRectilinear::fill_surface_by_lines(const Surface *surface, const FillPa
|
|||
}
|
||||
iRun ++;
|
||||
#endif /* SLIC3R_DEBUG */
|
||||
|
||||
std::vector<SegmentedIntersectionLine> segs = slice_region_by_vertical_lines(poly_with_offset, n_vlines, x0, line_spacing);
|
||||
// Connect by horizontal / vertical links, classify the links based on link_max_length as too long.
|
||||
connect_segment_intersections_by_contours(poly_with_offset, segs, params, link_max_length);
|
||||
|
@ -2848,8 +2870,9 @@ bool FillRectilinear::fill_surface_by_lines(const Surface *surface, const FillPa
|
|||
std::vector<MonotonicRegionLink> path = chain_monotonic_regions(regions, poly_with_offset, segs, rng);
|
||||
polylines_from_paths(path, poly_with_offset, segs, polylines_out);
|
||||
}
|
||||
} else
|
||||
traverse_graph_generate_polylines(poly_with_offset, params, this->link_max_length, segs, polylines_out);
|
||||
} else {
|
||||
traverse_graph_generate_polylines(poly_with_offset, params, segs, this->has_consistent_pattern(), polylines_out);
|
||||
}
|
||||
|
||||
#ifdef SLIC3R_DEBUG
|
||||
{
|
||||
|
@ -2876,6 +2899,11 @@ bool FillRectilinear::fill_surface_by_lines(const Surface *surface, const FillPa
|
|||
//FIXME rather simplify the paths to avoid very short edges?
|
||||
//assert(! it->has_duplicate_points());
|
||||
it->remove_duplicate_points();
|
||||
|
||||
//get origin direction infill
|
||||
if (params.symmetric_infill_y_axis) {
|
||||
it->symmetric_y(params.symmetric_y_axis);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SLIC3R_DEBUG
|
||||
|
@ -2884,6 +2912,8 @@ bool FillRectilinear::fill_surface_by_lines(const Surface *surface, const FillPa
|
|||
assert(! polyline.has_duplicate_points());
|
||||
#endif /* SLIC3R_DEBUG */
|
||||
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2963,7 +2993,8 @@ bool FillRectilinear::fill_surface_by_multilines(const Surface *surface, FillPar
|
|||
Polylines FillRectilinear::fill_surface(const Surface *surface, const FillParams ¶ms)
|
||||
{
|
||||
Polylines polylines_out;
|
||||
if (params.full_infill()) {
|
||||
// Orca Todo: fow now don't use fill_surface_by_multilines for zipzag infill
|
||||
if (params.full_infill() || params.pattern == ipCrossZag || params.pattern == ipZigZag || params.pattern == ipLockedZag) {
|
||||
if (!fill_surface_by_lines(surface, params, 0.f, 0.f, polylines_out))
|
||||
BOOST_LOG_TRIVIAL(error) << "FillRectilinear::fill_surface() fill_surface_by_lines() failed to fill a region.";
|
||||
} else {
|
||||
|
@ -3409,5 +3440,119 @@ void FillMonotonicLineWGapFill::fill_surface_by_lines(const Surface* surface, co
|
|||
}
|
||||
}*/
|
||||
|
||||
void FillLockedZag::fill_surface_locked_zag (const Surface * surface,
|
||||
const FillParams & params,
|
||||
std::vector<std::pair<Polylines, Flow>> &multi_width_polyline)
|
||||
{
|
||||
// merge different part exps
|
||||
// diff skin flow
|
||||
Polylines skin_lines;
|
||||
Polylines skeloton_lines;
|
||||
double offset_threshold = params.skin_infill_depth;
|
||||
double overlap_threshold = params.infill_lock_depth;
|
||||
Surface cross_surface = *surface;
|
||||
Surface zig_surface = *surface;
|
||||
// inner exps
|
||||
// inner union exps
|
||||
ExPolygons zig_expas = offset_ex({surface->expolygon}, -offset_threshold);
|
||||
ExPolygons cross_expas = diff_ex(surface->expolygon, zig_expas);
|
||||
|
||||
bool zig_get = false;
|
||||
FillParams zig_params = params;
|
||||
zig_params.horiz_move = 0;
|
||||
// generate skeleton for diff density
|
||||
auto generate_for_different_flow = [&multi_width_polyline](const std::map<Flow, ExPolygons> &flow_params, const Polylines &polylines) {
|
||||
auto it = flow_params.begin();
|
||||
while (it != flow_params.end()) {
|
||||
ExPolygons region_exp = union_safety_offset_ex(it->second);
|
||||
|
||||
Polylines polys = intersection_pl(polylines, region_exp);
|
||||
multi_width_polyline.emplace_back(polys, it->first);
|
||||
it++;
|
||||
}
|
||||
};
|
||||
|
||||
auto it = this->lock_param.skeleton_density_params.begin();
|
||||
while (it != this->lock_param.skeleton_density_params.end()) {
|
||||
ExPolygons region_exp = union_safety_offset_ex(it->second);
|
||||
ExPolygons exps = intersection_ex(region_exp, zig_expas);
|
||||
zig_params.density = it->first;
|
||||
exps = intersection_ex(offset_ex(exps, overlap_threshold), surface->expolygon);
|
||||
for (ExPolygon &exp : exps) {
|
||||
zig_surface.expolygon = exp;
|
||||
|
||||
Polylines zig_polylines_out = this->fill_surface(&zig_surface, zig_params);
|
||||
skeloton_lines.insert(skeloton_lines.end(), zig_polylines_out.begin(), zig_polylines_out.end());
|
||||
}
|
||||
it++;
|
||||
}
|
||||
|
||||
// set skeleton flow
|
||||
generate_for_different_flow(this->lock_param.skeleton_flow_params, skeloton_lines);
|
||||
|
||||
// skin exps
|
||||
bool cross_get = false;
|
||||
FillParams cross_params = params;
|
||||
cross_params.locked_zag = false;
|
||||
auto skin_density = this->lock_param.skin_density_params.begin();
|
||||
while (skin_density != this->lock_param.skin_density_params.end()) {
|
||||
ExPolygons region_exp = union_safety_offset_ex(skin_density->second);
|
||||
ExPolygons exps = intersection_ex(region_exp, cross_expas);
|
||||
cross_params.density = skin_density->first;
|
||||
for (ExPolygon &exp : exps) {
|
||||
cross_surface.expolygon = exp;
|
||||
Polylines cross_polylines_out = this->fill_surface(&cross_surface, cross_params);
|
||||
skin_lines.insert(skin_lines.end(), cross_polylines_out.begin(), cross_polylines_out.end());
|
||||
}
|
||||
skin_density++;
|
||||
}
|
||||
|
||||
generate_for_different_flow(this->lock_param.skin_flow_params, skin_lines);
|
||||
}
|
||||
|
||||
void FillLockedZag::fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, ExtrusionEntitiesPtr &out)
|
||||
{
|
||||
Polylines polylines;
|
||||
ThickPolylines thick_polylines;
|
||||
std::vector<std::pair<Polylines, Flow>> multi_width_polyline;
|
||||
try {
|
||||
this->fill_surface_locked_zag(surface, params, multi_width_polyline);
|
||||
}
|
||||
catch (InfillFailedException&) {}
|
||||
|
||||
if (!thick_polylines.empty() || !multi_width_polyline.empty()) {
|
||||
// Save into layer.
|
||||
ExtrusionEntityCollection* eec = nullptr;
|
||||
out.push_back(eec = new ExtrusionEntityCollection());
|
||||
// Only concentric fills are not sorted.
|
||||
eec->no_sort = this->no_sort();
|
||||
size_t idx = eec->entities.size();
|
||||
{
|
||||
for (std::pair<Polylines, Flow> &poly_with_flow: multi_width_polyline) {
|
||||
// calculate actual flow from spacing (which might have been adjusted by the infill
|
||||
// pattern generator)
|
||||
double flow_mm3_per_mm = poly_with_flow.second.mm3_per_mm();
|
||||
double flow_width = poly_with_flow.second.width();
|
||||
if (params.using_internal_flow) {
|
||||
// if we used the internal flow we're not doing a solid infill
|
||||
// so we can safely ignore the slight variation that might have
|
||||
// been applied to f->spacing
|
||||
} else {
|
||||
Flow new_flow = poly_with_flow.second.with_spacing(this->spacing);
|
||||
flow_mm3_per_mm = new_flow.mm3_per_mm();
|
||||
flow_width = new_flow.width();
|
||||
}
|
||||
extrusion_entities_append_paths(
|
||||
eec->entities, std::move(poly_with_flow.first),
|
||||
params.extrusion_role,
|
||||
flow_mm3_per_mm, float(flow_width), poly_with_flow.second.height());
|
||||
}
|
||||
}
|
||||
if (!params.can_reverse) {
|
||||
for (size_t i = idx; i < eec->entities.size(); i++)
|
||||
eec->entities[i]->set_reverse();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
|
|
|
@ -16,6 +16,7 @@ public:
|
|||
Fill* clone() const override { return new FillRectilinear(*this); }
|
||||
~FillRectilinear() override = default;
|
||||
Polylines fill_surface(const Surface *surface, const FillParams ¶ms) override;
|
||||
bool is_self_crossing() override { return false; }
|
||||
|
||||
protected:
|
||||
// Fill by single directional lines, interconnect the lines along perimeters.
|
||||
|
@ -28,6 +29,9 @@ protected:
|
|||
float pattern_shift;
|
||||
};
|
||||
bool fill_surface_by_multilines(const Surface *surface, FillParams params, const std::initializer_list<SweepParams> &sweep_params, Polylines &polylines_out);
|
||||
|
||||
// The extended bounding box of the whole object that covers any rotation of every layer.
|
||||
BoundingBox extended_object_bounding_box() const;
|
||||
};
|
||||
|
||||
class FillAlignedRectilinear : public FillRectilinear
|
||||
|
@ -65,6 +69,7 @@ public:
|
|||
Fill* clone() const override { return new FillGrid(*this); }
|
||||
~FillGrid() override = default;
|
||||
Polylines fill_surface(const Surface *surface, const FillParams ¶ms) override;
|
||||
bool is_self_crossing() override { return true; }
|
||||
|
||||
protected:
|
||||
// The grid fill will keep the angle constant between the layers, see the implementation of Slic3r::Fill.
|
||||
|
@ -89,6 +94,7 @@ public:
|
|||
Fill* clone() const override { return new FillTriangles(*this); }
|
||||
~FillTriangles() override = default;
|
||||
Polylines fill_surface(const Surface *surface, const FillParams ¶ms) override;
|
||||
bool is_self_crossing() override { return true; }
|
||||
|
||||
protected:
|
||||
// The grid fill will keep the angle constant between the layers, see the implementation of Slic3r::Fill.
|
||||
|
@ -101,6 +107,7 @@ public:
|
|||
Fill* clone() const override { return new FillStars(*this); }
|
||||
~FillStars() override = default;
|
||||
Polylines fill_surface(const Surface *surface, const FillParams ¶ms) override;
|
||||
bool is_self_crossing() override { return true; }
|
||||
|
||||
protected:
|
||||
// The grid fill will keep the angle constant between the layers, see the implementation of Slic3r::Fill.
|
||||
|
@ -113,6 +120,7 @@ public:
|
|||
Fill* clone() const override { return new FillCubic(*this); }
|
||||
~FillCubic() override = default;
|
||||
Polylines fill_surface(const Surface *surface, const FillParams ¶ms) override;
|
||||
bool is_self_crossing() override { return true; }
|
||||
|
||||
protected:
|
||||
// The grid fill will keep the angle constant between the layers, see the implementation of Slic3r::Fill.
|
||||
|
@ -170,6 +178,7 @@ public:
|
|||
public:
|
||||
~FillMonotonicLineWGapFill() override = default;
|
||||
void fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, ExtrusionEntitiesPtr &out) override;
|
||||
bool is_self_crossing() override { return false; }
|
||||
|
||||
protected:
|
||||
Fill* clone() const override { return new FillMonotonicLineWGapFill(*this); };
|
||||
|
@ -179,9 +188,43 @@ private:
|
|||
void fill_surface_by_lines(const Surface* surface, const FillParams& params, Polylines& polylines_out);
|
||||
};*/
|
||||
|
||||
Points sample_grid_pattern(const ExPolygon& expolygon, coord_t spacing, const BoundingBox& global_bounding_box);
|
||||
Points sample_grid_pattern(const ExPolygons& expolygons, coord_t spacing, const BoundingBox& global_bounding_box);
|
||||
Points sample_grid_pattern(const Polygons& polygons, coord_t spacing, const BoundingBox& global_bounding_box);
|
||||
class FillZigZag : public FillRectilinear
|
||||
{
|
||||
public:
|
||||
Fill* clone() const override { return new FillZigZag(*this); }
|
||||
~FillZigZag() override = default;
|
||||
|
||||
bool has_consistent_pattern() const override { return true; }
|
||||
};
|
||||
|
||||
class FillCrossZag : public FillRectilinear
|
||||
{
|
||||
public:
|
||||
Fill *clone() const override { return new FillCrossZag(*this); }
|
||||
~FillCrossZag() override = default;
|
||||
|
||||
bool has_consistent_pattern() const override { return true; }
|
||||
};
|
||||
|
||||
class FillLockedZag : public FillRectilinear
|
||||
{
|
||||
public:
|
||||
Fill *clone() const override { return new FillLockedZag(*this); }
|
||||
~FillLockedZag() override = default;
|
||||
LockRegionParam lock_param;
|
||||
|
||||
void fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, ExtrusionEntitiesPtr &out) override;
|
||||
|
||||
bool has_consistent_pattern() const override { return true; }
|
||||
void set_lock_region_param(const LockRegionParam &lock_param) override { this->lock_param = lock_param;};
|
||||
void fill_surface_locked_zag(const Surface * surface,
|
||||
const FillParams & params,
|
||||
std::vector<std::pair<Polylines, Flow>> &multi_width_polyline);
|
||||
};
|
||||
|
||||
Points sample_grid_pattern(const ExPolygon &expolygon, coord_t spacing, const BoundingBox &global_bounding_box);
|
||||
Points sample_grid_pattern(const ExPolygons &expolygons, coord_t spacing, const BoundingBox &global_bounding_box);
|
||||
Points sample_grid_pattern(const Polygons &polygons, coord_t spacing, const BoundingBox &global_bounding_box);
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
|
|
|
@ -25,20 +25,20 @@ public:
|
|||
// speed in default configuration (degrees)
|
||||
static constexpr float CorrectionAngle = -45.;
|
||||
|
||||
void _fill_surface_single(const FillParams& params,
|
||||
unsigned int thickness_layers,
|
||||
const std::pair<float, Point>& direction,
|
||||
ExPolygon expolygon,
|
||||
Polylines& polylines_out) override;
|
||||
|
||||
bool is_self_crossing() override { return false; }
|
||||
|
||||
// Density adjustment to have a good %of weight.
|
||||
static constexpr double DensityAdjust = 2.1;
|
||||
|
||||
// Gyroid upper resolution tolerance (mm^-2)
|
||||
static constexpr double PatternTolerance = 0.1;
|
||||
|
||||
|
||||
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
|
||||
|
|
|
@ -82,6 +82,13 @@ public:
|
|||
|
||||
bool operator==(const Flow &rhs) const { return m_width == rhs.m_width && m_height == rhs.m_height && m_nozzle_diameter == rhs.m_nozzle_diameter && m_bridge == rhs.m_bridge; }
|
||||
|
||||
bool operator!=(const Flow &rhs) const{
|
||||
return m_width != rhs.m_width || m_height != rhs.m_height || m_nozzle_diameter != rhs.m_nozzle_diameter || m_bridge != rhs.m_bridge;
|
||||
}
|
||||
|
||||
bool operator <(const Flow &rhs) const {
|
||||
return this->mm3_per_mm() < rhs.mm3_per_mm();
|
||||
}
|
||||
Flow with_width (float width) const {
|
||||
assert(! m_bridge);
|
||||
return Flow(width, m_height, rounded_rectangle_extrusion_spacing(width, m_height), m_nozzle_diameter, m_bridge);
|
||||
|
|
|
@ -507,4 +507,11 @@ BoundingBox get_extents_rotated(const MultiPoint &mp, double angle)
|
|||
return get_extents_rotated(mp.points, angle);
|
||||
}
|
||||
|
||||
void MultiPoint::symmetric_y(const coord_t &x_axis)
|
||||
{
|
||||
for (Point &pt : points) {
|
||||
pt(0) = 2 * x_axis - pt(0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -94,7 +94,7 @@ public:
|
|||
bool intersection(const Line& line, Point* intersection) const;
|
||||
bool first_intersection(const Line& line, Point* intersection) const;
|
||||
bool intersections(const Line &line, Points *intersections) const;
|
||||
|
||||
void symmetric_y(const coord_t &y_axis);
|
||||
static Points _douglas_peucker(const Points &points, const double tolerance);
|
||||
static Points visivalingam(const Points& pts, const double tolerance);
|
||||
static Points concave_hull_2d(const Points& pts, const double tolerence);
|
||||
|
|
|
@ -786,7 +786,7 @@ static std::vector<std::string> s_Preset_print_options {
|
|||
"top_shell_layers", "top_shell_thickness", "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",
|
||||
"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",
|
||||
"infill_direction", "solid_infill_direction", "rotate_solid_infill_direction", "counterbore_hole_bridging",
|
||||
"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",
|
||||
"ironing_type", "ironing_pattern", "ironing_flow", "ironing_speed", "ironing_spacing", "ironing_angle", "ironing_inset",
|
||||
"support_ironing", "support_ironing_pattern", "support_ironing_flow", "support_ironing_spacing",
|
||||
|
@ -806,8 +806,9 @@ static std::vector<std::string> s_Preset_print_options {
|
|||
"support_top_z_distance", "support_on_build_plate_only","support_critical_regions_only", "bridge_no_support", "thick_bridges", "thick_internal_bridges","dont_filter_internal_bridges","enable_extra_bridge_layer", "max_bridge_length", "print_sequence", "print_order", "support_remove_small_overhang",
|
||||
"filename_format", "wall_filament", "support_bottom_z_distance",
|
||||
"sparse_infill_filament", "solid_infill_filament", "support_filament", "support_interface_filament","support_interface_not_for_body",
|
||||
"ooze_prevention", "standby_temperature_delta", "preheat_time","preheat_steps", "interface_shells", "line_width", "initial_layer_line_width",
|
||||
"inner_wall_line_width", "outer_wall_line_width", "sparse_infill_line_width", "internal_solid_infill_line_width",
|
||||
"ooze_prevention", "standby_temperature_delta", "preheat_time","preheat_steps", "interface_shells", "line_width", "initial_layer_line_width", "inner_wall_line_width",
|
||||
"outer_wall_line_width", "sparse_infill_line_width", "internal_solid_infill_line_width",
|
||||
"skin_infill_line_width","skeleton_infill_line_width",
|
||||
"top_surface_line_width", "support_line_width", "infill_wall_overlap","top_bottom_infill_wall_overlap", "bridge_flow", "internal_bridge_flow",
|
||||
"elefant_foot_compensation", "elefant_foot_compensation_layers", "xy_contour_compensation", "xy_hole_compensation", "resolution", "enable_prime_tower",
|
||||
"prime_tower_width", "prime_tower_brim_width", "prime_volume",
|
||||
|
|
|
@ -1387,7 +1387,7 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
|
|||
if (!validate_extrusion_width(object->config(), "support_line_width", layer_height, err_msg))
|
||||
return {err_msg, object, "support_line_width"};
|
||||
}
|
||||
for (const char *opt_key : { "inner_wall_line_width", "outer_wall_line_width", "sparse_infill_line_width", "internal_solid_infill_line_width", "top_surface_line_width" })
|
||||
for (const char *opt_key : { "inner_wall_line_width", "outer_wall_line_width", "sparse_infill_line_width", "internal_solid_infill_line_width", "top_surface_line_width","skin_infill_line_width" ,"skeleton_infill_line_width"})
|
||||
for (const PrintRegion ®ion : object->all_regions())
|
||||
if (!validate_extrusion_width(region.config(), opt_key, layer_height, err_msg))
|
||||
return {err_msg, object, opt_key};
|
||||
|
|
|
@ -161,6 +161,9 @@ static t_config_enum_values s_keys_map_InfillPattern {
|
|||
{ "lightning", ipLightning },
|
||||
{ "crosshatch", ipCrossHatch},
|
||||
{ "quartercubic", ipQuarterCubic},
|
||||
{ "zigzag", ipZigZag },
|
||||
{ "crosszag", ipCrossZag },
|
||||
{ "lockedzag", ipLockedZag }
|
||||
};
|
||||
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(InfillPattern)
|
||||
|
||||
|
@ -2348,13 +2351,6 @@ void PrintConfigDef::init_fff_params()
|
|||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(45));
|
||||
|
||||
def = this->add("rotate_solid_infill_direction", coBool);
|
||||
def->label = L("Rotate solid infill direction");
|
||||
def->category = L("Strength");
|
||||
def->tooltip = L("Rotate the solid infill direction by 90° for each layer.");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBool(true));
|
||||
|
||||
def = this->add("sparse_infill_density", coPercent);
|
||||
def->label = L("Sparse infill density");
|
||||
def->category = L("Strength");
|
||||
|
@ -2392,6 +2388,9 @@ void PrintConfigDef::init_fff_params()
|
|||
def->enum_values.push_back("lightning");
|
||||
def->enum_values.push_back("crosshatch");
|
||||
def->enum_values.push_back("quartercubic");
|
||||
def->enum_values.push_back("zigzag");
|
||||
def->enum_values.push_back("crosszag");
|
||||
def->enum_values.push_back("lockedzag");
|
||||
def->enum_labels.push_back(L("Concentric"));
|
||||
def->enum_labels.push_back(L("Rectilinear"));
|
||||
def->enum_labels.push_back(L("Grid"));
|
||||
|
@ -2414,6 +2413,9 @@ void PrintConfigDef::init_fff_params()
|
|||
def->enum_labels.push_back(L("Lightning"));
|
||||
def->enum_labels.push_back(L("Cross Hatch"));
|
||||
def->enum_labels.push_back(L("Quarter Cubic"));
|
||||
def->enum_labels.push_back(L("Zig Zag"));
|
||||
def->enum_labels.push_back(L("Cross Zag"));
|
||||
def->enum_labels.push_back(L("Locked Zag"));
|
||||
def->set_default_value(new ConfigOptionEnum<InfillPattern>(ipCrossHatch));
|
||||
|
||||
def = this->add("lattice_angle_1", coFloat);
|
||||
|
@ -3100,6 +3102,113 @@ void PrintConfigDef::init_fff_params()
|
|||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("infill_shift_step", coFloat);
|
||||
def->label = L("Infill shift step");
|
||||
def->category = L("Strength");
|
||||
def->tooltip = L("This parameter adds a slight displacement to each layer of infill to create a cross texture.");
|
||||
def->sidetext = L("mm");
|
||||
def->min = 0;
|
||||
def->max = 10;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(0.4));
|
||||
|
||||
//Orca
|
||||
def = this->add("sparse_infill_rotate_template", coString);
|
||||
def->label = L("Sparse infill rotatation template");
|
||||
def->category = L("Strength");
|
||||
def->tooltip = L("This parameter adds a rotation of sparse infill direction to each layer according to the specified template. "
|
||||
"The template is a comma-separated list of angles in degrees, e.g. '0,90'. "
|
||||
"The first angle is applied to the first layer, the second angle to the second layer, and so on. "
|
||||
"If there are more layers than angles, the angles will be repeated. Note that not all all sparse infill patterns support rotation.");
|
||||
def->sidetext = L("°");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionString("0,90"));
|
||||
|
||||
//Orca
|
||||
def = this->add("solid_infill_rotate_template", coString);
|
||||
def->label = L("Solid infill rotatation template");
|
||||
def->category = L("Strength");
|
||||
def->tooltip = L("This parameter adds a rotation of solid infill direction to each layer according to the specified template. "
|
||||
"The template is a comma-separated list of angles in degrees, e.g. '0,90'. "
|
||||
"The first angle is applied to the first layer, the second angle to the second layer, and so on. "
|
||||
"If there are more layers than angles, the angles will be repeated. Note that not all all solid infill patterns support rotation.");
|
||||
def->sidetext = L("°");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionString("0,90"));
|
||||
|
||||
|
||||
def = this->add("skeleton_infill_density", coPercent);
|
||||
def->label = L("Skeleton infill density");
|
||||
def->category = L("Strength");
|
||||
def->tooltip = L("The remaining part of the model contour after removing a certain depth from the surface is called the skeleton. This parameter is used to adjust the density of this section."
|
||||
"When two regions have the same sparse infill settings but different skeleton densities, their skeleton areas will develop overlapping sections."
|
||||
"default is as same as infill density.");
|
||||
def->sidetext = "%";
|
||||
def->min = 0;
|
||||
def->max = 100;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionPercent(25));
|
||||
|
||||
def = this->add("skin_infill_density", coPercent);
|
||||
def->label = L("Skin infill density");
|
||||
def->category = L("Strength");
|
||||
def->tooltip = L("The portion of the model's outer surface within a certain depth range is called the skin. This parameter is used to adjust the density of this section."
|
||||
"When two regions have the same sparse infill settings but different skin densities, This area will not be split into two separate regions."
|
||||
"default is as same as infill density.");
|
||||
def->sidetext = "%";
|
||||
def->min = 0;
|
||||
def->max = 100;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionPercent(25));
|
||||
|
||||
def = this->add("skin_infill_depth", coFloat);
|
||||
def->label = L("Skin infill depth");
|
||||
def->category = L("Strength");
|
||||
def->tooltip = L("The parameter sets the depth of skin.");
|
||||
def->sidetext = L("mm");
|
||||
def->min = 0;
|
||||
def->max = 100;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(2.0));
|
||||
|
||||
def = this->add("infill_lock_depth", coFloat);
|
||||
def->label = L("Infill lock depth");
|
||||
def->category = L("Strength");
|
||||
def->tooltip = L("The parameter sets the overlapping depth between the interior and skin.");
|
||||
def->sidetext = L("mm");
|
||||
def->min = 0;
|
||||
def->max = 100;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(1.0));
|
||||
|
||||
def = this->add("skin_infill_line_width", coFloatOrPercent);
|
||||
def->label = L("Skin line width");
|
||||
def->category = L("Strength");
|
||||
def->tooltip = L("Adjust the line width of the selected skin paths.");
|
||||
def->sidetext = L("mm");
|
||||
def->ratio_over = "nozzle_diameter";
|
||||
def->min = 0;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloatOrPercent(0.4, false));
|
||||
|
||||
def = this->add("skeleton_infill_line_width", coFloatOrPercent);
|
||||
def->label = L("Skeleton line width");
|
||||
def->category = L("Strength");
|
||||
def->tooltip = L("Adjust the line width of the selected skeleton paths.");
|
||||
def->sidetext = L("mm");
|
||||
def->ratio_over = "nozzle_diameter";
|
||||
def->min = 0;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloatOrPercent(0.4, false));
|
||||
|
||||
def = this->add("symmetric_infill_y_axis", coBool);
|
||||
def->label = L("Symmetric infill y axis");
|
||||
def->category = L("Strength");
|
||||
def->tooltip = L("If the model has two parts that are symmetric about the y-axis,"
|
||||
" and you want these parts to have symmetric textures, please click this option on one of the parts.");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
// Orca: max layer height for combined infill
|
||||
def = this->add("infill_combination_max_layer_height", coFloatOrPercent);
|
||||
def->label = L("Infill combination - Max layer height");
|
||||
|
@ -6657,33 +6766,31 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va
|
|||
else if (value == "0"){
|
||||
value = "ensure_moderate";
|
||||
}
|
||||
}
|
||||
else if (opt_key == "sparse_infill_anchor") {
|
||||
} else if (opt_key == "rotate_solid_infill_direction") {
|
||||
opt_key = "solid_infill_rotate_template";
|
||||
if (value == "1") {
|
||||
value = "0,90";
|
||||
} else if (value == "0") {
|
||||
value = "0";
|
||||
}
|
||||
} else if (opt_key == "sparse_infill_anchor") {
|
||||
opt_key = "infill_anchor";
|
||||
}
|
||||
else if (opt_key == "sparse_infill_anchor_max") {
|
||||
} else if (opt_key == "sparse_infill_anchor_max") {
|
||||
opt_key = "infill_anchor_max";
|
||||
}
|
||||
else if (opt_key == "chamber_temperatures") {
|
||||
} else if (opt_key == "chamber_temperatures") {
|
||||
opt_key = "chamber_temperature";
|
||||
}
|
||||
else if (opt_key == "thumbnail_size") {
|
||||
} else if (opt_key == "thumbnail_size") {
|
||||
opt_key = "thumbnails";
|
||||
}
|
||||
else if (opt_key == "top_one_wall_type" && value != "none") {
|
||||
} else if (opt_key == "top_one_wall_type" && value != "none") {
|
||||
opt_key = "only_one_wall_top";
|
||||
value = "1";
|
||||
}
|
||||
else if (opt_key == "initial_layer_flow_ratio") {
|
||||
} else if (opt_key == "initial_layer_flow_ratio") {
|
||||
opt_key = "bottom_solid_infill_flow_ratio";
|
||||
}
|
||||
else if(opt_key == "ironing_direction") {
|
||||
} else if (opt_key == "ironing_direction") {
|
||||
opt_key = "ironing_angle";
|
||||
}
|
||||
else if(opt_key == "counterbole_hole_bridging") {
|
||||
} else if (opt_key == "counterbole_hole_bridging") {
|
||||
opt_key = "counterbore_hole_bridging";
|
||||
}
|
||||
else if (opt_key == "draft_shield" && value == "limited") {
|
||||
} else if (opt_key == "draft_shield" && value == "limited") {
|
||||
value = "disabled";
|
||||
}
|
||||
|
||||
|
@ -7304,7 +7411,9 @@ std::map<std::string, std::string> validate(const FullPrintConfig &cfg, bool und
|
|||
"internal_solid_infill_line_width",
|
||||
"top_surface_line_width",
|
||||
"support_line_width",
|
||||
"initial_layer_line_width" };
|
||||
"initial_layer_line_width",
|
||||
"skin_infill_line_width",
|
||||
"skeleton_infill_line_width"};
|
||||
for (size_t i = 0; i < sizeof(widths) / sizeof(widths[i]); ++ i) {
|
||||
std::string key(widths[i]);
|
||||
if (cfg.get_abs_value(key, max_nozzle_diameter) > 2.5 * max_nozzle_diameter) {
|
||||
|
|
|
@ -60,7 +60,7 @@ enum AuthorizationType {
|
|||
enum InfillPattern : int {
|
||||
ipConcentric, ipRectilinear, ipGrid, ip2DLattice, ipLine, ipCubic, ipTriangles, ipStars, ipGyroid, ipTpmsD, ipHoneycomb, ipAdaptiveCubic, ipMonotonic, ipMonotonicLine, ipAlignedRectilinear, ip2DHoneycomb, ip3DHoneycomb,
|
||||
ipHilbertCurve, ipArchimedeanChords, ipOctagramSpiral, ipSupportCubic, ipSupportBase, ipConcentricInternal,
|
||||
ipLightning, ipCrossHatch, ipQuarterCubic,
|
||||
ipLightning, ipCrossHatch, ipQuarterCubic, ipZigZag, ipCrossZag, ipLockedZag,
|
||||
ipCount,
|
||||
};
|
||||
|
||||
|
@ -946,7 +946,10 @@ PRINT_CONFIG_CLASS_DEFINE(
|
|||
((ConfigOptionFloat, outer_wall_speed))
|
||||
((ConfigOptionFloat, infill_direction))
|
||||
((ConfigOptionFloat, solid_infill_direction))
|
||||
((ConfigOptionBool, rotate_solid_infill_direction))
|
||||
((ConfigOptionString, solid_infill_rotate_template))
|
||||
((ConfigOptionBool, symmetric_infill_y_axis))
|
||||
((ConfigOptionFloat, infill_shift_step))
|
||||
((ConfigOptionString, sparse_infill_rotate_template))
|
||||
((ConfigOptionPercent, sparse_infill_density))
|
||||
((ConfigOptionEnum<InfillPattern>, sparse_infill_pattern))
|
||||
((ConfigOptionFloat, lattice_angle_1))
|
||||
|
@ -966,7 +969,12 @@ PRINT_CONFIG_CLASS_DEFINE(
|
|||
((ConfigOptionPercent, infill_wall_overlap))
|
||||
((ConfigOptionPercent, top_bottom_infill_wall_overlap))
|
||||
((ConfigOptionFloat, sparse_infill_speed))
|
||||
//BBS
|
||||
((ConfigOptionPercent, skeleton_infill_density))
|
||||
((ConfigOptionPercent, skin_infill_density))
|
||||
((ConfigOptionFloat, infill_lock_depth))
|
||||
((ConfigOptionFloat, skin_infill_depth))
|
||||
((ConfigOptionFloatOrPercent, skin_infill_line_width))
|
||||
((ConfigOptionFloatOrPercent, skeleton_infill_line_width))
|
||||
((ConfigOptionBool, infill_combination))
|
||||
// Orca:
|
||||
((ConfigOptionFloatOrPercent, infill_combination_max_layer_height))
|
||||
|
|
|
@ -1073,9 +1073,10 @@ bool PrintObject::invalidate_state_by_config_options(
|
|||
|| opt_key == "sparse_infill_filament"
|
||||
|| opt_key == "solid_infill_filament"
|
||||
|| opt_key == "sparse_infill_line_width"
|
||||
|| opt_key == "skin_infill_line_width"
|
||||
|| opt_key == "skeleton_infill_line_width"
|
||||
|| opt_key == "infill_direction"
|
||||
|| opt_key == "solid_infill_direction"
|
||||
|| opt_key == "rotate_solid_infill_direction"
|
||||
|| opt_key == "ensure_vertical_shell_thickness"
|
||||
|| opt_key == "bridge_angle"
|
||||
|| opt_key == "internal_bridge_angle" // ORCA: Internal bridge angle override
|
||||
|
@ -1097,7 +1098,15 @@ bool PrintObject::invalidate_state_by_config_options(
|
|||
|| opt_key == "lattice_angle_2"
|
||||
|| opt_key == "infill_overhang_angle") {
|
||||
steps.emplace_back(posInfill);
|
||||
} else if (opt_key == "sparse_infill_pattern") {
|
||||
} else if (opt_key == "sparse_infill_pattern"
|
||||
|| opt_key == "symmetric_infill_y_axis"
|
||||
|| opt_key == "infill_shift_step"
|
||||
|| opt_key == "sparse_infill_rotate_template"
|
||||
|| opt_key == "solid_infill_rotate_template"
|
||||
|| opt_key == "skeleton_infill_density"
|
||||
|| opt_key == "skin_infill_density"
|
||||
|| opt_key == "infill_lock_depth"
|
||||
|| opt_key == "skin_infill_depth") {
|
||||
steps.emplace_back(posPrepareInfill);
|
||||
} else if (opt_key == "sparse_infill_density") {
|
||||
// One likely wants to reslice only when switching between zero infill to simulate boolean difference (subtracting volumes),
|
||||
|
|
|
@ -472,6 +472,20 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con
|
|||
apply(config, &new_conf);
|
||||
is_msg_dlg_already_exist = false;
|
||||
}
|
||||
|
||||
// layer_height shouldn't be equal to zero
|
||||
float skin_depth = config->opt_float("skin_infill_depth");
|
||||
if (config->opt_float("infill_lock_depth") > skin_depth) {
|
||||
const wxString msg_text = _(L("lock depth should smaller than skin depth.\nReset to 50% of skin depth"));
|
||||
MessageDialog dialog(m_msg_dlg_parent, msg_text, "", wxICON_WARNING | wxOK);
|
||||
DynamicPrintConfig new_conf = *config;
|
||||
is_msg_dlg_already_exist = true;
|
||||
dialog.ShowModal();
|
||||
new_conf.set_key_value("infill_lock_depth", new ConfigOptionFloat(skin_depth / 2));
|
||||
apply(config, &new_conf);
|
||||
is_msg_dlg_already_exist = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ConfigManipulation::apply_null_fff_config(DynamicPrintConfig *config, std::vector<std::string> const &keys, std::map<ObjectBase *, ModelConfig *> const &configs)
|
||||
|
@ -526,7 +540,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
|
|||
bool have_infill = config->option<ConfigOptionPercent>("sparse_infill_density")->value > 0;
|
||||
// sparse_infill_filament uses the same logic as in Print::extruders()
|
||||
for (auto el : { "sparse_infill_pattern", "infill_combination",
|
||||
"minimum_sparse_infill_area", "sparse_infill_filament", "infill_anchor_max"})
|
||||
"minimum_sparse_infill_area", "sparse_infill_filament", "infill_anchor_max","infill_shift_step","sparse_infill_rotate_template","symmetric_infill_y_axis"})
|
||||
toggle_line(el, have_infill);
|
||||
|
||||
bool have_combined_infill = config->opt_bool("infill_combination") && have_infill;
|
||||
|
@ -539,6 +553,19 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
|
|||
bool has_infill_anchors = have_infill && config->option<ConfigOptionFloatOrPercent>("infill_anchor_max")->value > 0 && infill_anchor;
|
||||
toggle_field("infill_anchor", has_infill_anchors);
|
||||
|
||||
//cross zag
|
||||
bool is_cross_zag = config->option<ConfigOptionEnum<InfillPattern>>("sparse_infill_pattern")->value == InfillPattern::ipCrossZag;
|
||||
bool is_locked_zig = config->option<ConfigOptionEnum<InfillPattern>>("sparse_infill_pattern")->value == InfillPattern::ipLockedZag;
|
||||
|
||||
toggle_line("infill_shift_step", is_cross_zag || is_locked_zig);
|
||||
|
||||
for (auto el : { "skeleton_infill_density", "skin_infill_density", "infill_lock_depth", "skin_infill_depth","skin_infill_line_width", "skeleton_infill_line_width" })
|
||||
toggle_line(el, is_locked_zig);
|
||||
|
||||
bool is_zig_zag = config->option<ConfigOptionEnum<InfillPattern>>("sparse_infill_pattern")->value == InfillPattern::ipZigZag;
|
||||
|
||||
toggle_line("symmetric_infill_y_axis", is_zig_zag || is_cross_zag || is_locked_zig);
|
||||
|
||||
bool has_spiral_vase = config->opt_bool("spiral_mode");
|
||||
toggle_line("spiral_mode_smooth", has_spiral_vase);
|
||||
toggle_line("spiral_mode_max_xy_smoothing", has_spiral_vase && config->opt_bool("spiral_mode_smooth"));
|
||||
|
@ -552,7 +579,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
|
|||
|
||||
for (auto el : { "infill_direction", "sparse_infill_line_width",
|
||||
"sparse_infill_speed", "bridge_speed", "internal_bridge_speed", "bridge_angle", "internal_bridge_angle",
|
||||
"solid_infill_direction", "rotate_solid_infill_direction", "internal_solid_infill_pattern", "solid_infill_filament",
|
||||
"solid_infill_direction", "solid_infill_rotate_template", "internal_solid_infill_pattern", "solid_infill_filament",
|
||||
})
|
||||
toggle_field(el, have_infill || has_solid_infill);
|
||||
|
||||
|
@ -823,6 +850,22 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
|
|||
for (auto el : { "lattice_angle_1", "lattice_angle_2"})
|
||||
toggle_line(el, lattice_options);
|
||||
|
||||
//Orca: hide rotate template for solid infill if not support
|
||||
const auto _sparse_infill_pattern = config->option<ConfigOptionEnum<InfillPattern>>("sparse_infill_pattern")->value;
|
||||
bool show_sparse_infill_rotate_template = _sparse_infill_pattern == ipRectilinear || _sparse_infill_pattern == ipLine ||
|
||||
_sparse_infill_pattern == ipZigZag || _sparse_infill_pattern == ipCrossZag ||
|
||||
_sparse_infill_pattern == ipLockedZag;
|
||||
|
||||
toggle_line("sparse_infill_rotate_template", show_sparse_infill_rotate_template);
|
||||
|
||||
//Orca: hide rotate template for solid infill if not support
|
||||
const auto _solid_infill_pattern = config->option<ConfigOptionEnum<InfillPattern>>("internal_solid_infill_pattern")->value;
|
||||
bool show_solid_infill_rotate_template = _solid_infill_pattern == ipRectilinear || _solid_infill_pattern == ipMonotonic ||
|
||||
_solid_infill_pattern == ipMonotonicLine || _solid_infill_pattern == ipAlignedRectilinear;
|
||||
|
||||
toggle_line("solid_infill_rotate_template", show_solid_infill_rotate_template);
|
||||
|
||||
|
||||
toggle_line("infill_overhang_angle", config->opt_enum<InfillPattern>("sparse_infill_pattern") == InfillPattern::ip2DHoneycomb);
|
||||
}
|
||||
|
||||
|
|
|
@ -430,6 +430,16 @@ void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true
|
|||
str = str_out;
|
||||
set_value(str, true);
|
||||
}
|
||||
} else if (m_opt.opt_key == "sparse_infill_rotate_template" || m_opt.opt_key == "solid_infill_rotate_template") {
|
||||
if (!ConfigOptionFloats::validate_string(str.utf8_string())) {
|
||||
show_error(m_parent, format_wxstr(_L("This parameter expects a comma-delimited list of numbers. E.g, \"0,90\".")));
|
||||
wxString old_value(boost::any_cast<std::string>(m_value));
|
||||
this->set_value(old_value, true); // Revert to previous value
|
||||
} else {
|
||||
// Valid string, so update m_value with the new string from the control.
|
||||
m_value = into_u8(str);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
m_value = into_u8(str);
|
||||
|
|
|
@ -107,7 +107,7 @@ std::map<std::string, std::vector<SimpleSettingData>> SettingsFactory::PART_CAT
|
|||
{ L("Strength"), {{"wall_loops", "",1},{"top_shell_layers", L("Top Solid Layers"),1},{"top_shell_thickness", L("Top Minimum Shell Thickness"),1},
|
||||
{"bottom_shell_layers", L("Bottom Solid Layers"),1}, {"bottom_shell_thickness", L("Bottom Minimum Shell Thickness"),1},
|
||||
{"sparse_infill_density", "",1},{"sparse_infill_pattern", "",1},{"lattice_angle_1", "",1},{"lattice_angle_2", "",1},{"infill_overhang_angle", "",1},{"infill_anchor", "",1},{"infill_anchor_max", "",1},{"top_surface_pattern", "",1},{"bottom_surface_pattern", "",1}, {"internal_solid_infill_pattern", "",1},
|
||||
{"infill_combination", "",1}, {"infill_combination_max_layer_height", "",1}, {"infill_wall_overlap", "",1},{"top_bottom_infill_wall_overlap", "",1}, {"solid_infill_direction", "",1}, {"rotate_solid_infill_direction", "",1}, {"infill_direction", "",1}, {"bridge_angle", "",1}, {"internal_bridge_angle", "",1}, {"minimum_sparse_infill_area", "",1}
|
||||
{"infill_combination", "",1}, {"infill_combination_max_layer_height", "",1}, {"infill_wall_overlap", "",1},{"top_bottom_infill_wall_overlap", "",1}, {"solid_infill_direction", "",1}, {"infill_direction", "",1}, {"bridge_angle", "",1}, {"internal_bridge_angle", "",1}, {"minimum_sparse_infill_area", "",1}
|
||||
}},
|
||||
{ L("Speed"), {{"outer_wall_speed", "",1},{"inner_wall_speed", "",2},{"sparse_infill_speed", "",3},{"top_surface_speed", "",4}, {"internal_solid_infill_speed", "",5},
|
||||
{"enable_overhang_speed", "",6}, {"overhang_1_4_speed", "",7}, {"overhang_2_4_speed", "",8}, {"overhang_3_4_speed", "",9}, {"overhang_4_4_speed", "",10},
|
||||
|
|
|
@ -9920,7 +9920,6 @@ void adjust_settings_for_flowrate_calib(ModelObjectPtrs& objects, bool linear, i
|
|||
_obj->config.set_key_value("top_solid_infill_flow_ratio", new ConfigOptionFloat(1.0f));
|
||||
_obj->config.set_key_value("infill_direction", new ConfigOptionFloat(45));
|
||||
_obj->config.set_key_value("solid_infill_direction", new ConfigOptionFloat(135));
|
||||
_obj->config.set_key_value("rotate_solid_infill_direction", new ConfigOptionBool(true));
|
||||
_obj->config.set_key_value("ironing_type", new ConfigOptionEnum<IroningType>(IroningType::NoIroning));
|
||||
_obj->config.set_key_value("internal_solid_infill_speed", new ConfigOptionFloat(internal_solid_speed));
|
||||
_obj->config.set_key_value("top_surface_speed", new ConfigOptionFloat(top_surface_speed));
|
||||
|
|
|
@ -1470,6 +1470,9 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value)
|
|||
}
|
||||
}
|
||||
|
||||
if (opt_key == "single_extruder_multi_material" || opt_key == "extruders_count" )
|
||||
update_wiping_button_visibility();
|
||||
|
||||
|
||||
if (opt_key == "pellet_flow_coefficient")
|
||||
{
|
||||
|
@ -1483,6 +1486,44 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value)
|
|||
}
|
||||
|
||||
|
||||
if (opt_key == "single_extruder_multi_material" ){
|
||||
const auto bSEMM = m_config->opt_bool("single_extruder_multi_material");
|
||||
wxGetApp().sidebar().show_SEMM_buttons(bSEMM);
|
||||
wxGetApp().get_tab(Preset::TYPE_PRINT)->update();
|
||||
}
|
||||
|
||||
if(opt_key == "purge_in_prime_tower")
|
||||
wxGetApp().get_tab(Preset::TYPE_PRINT)->update();
|
||||
|
||||
|
||||
if (opt_key == "enable_prime_tower") {
|
||||
auto timelapse_type = m_config->option<ConfigOptionEnum<TimelapseType>>("timelapse_type");
|
||||
bool timelapse_enabled = timelapse_type->value == TimelapseType::tlSmooth;
|
||||
if (!boost::any_cast<bool>(value) && timelapse_enabled) {
|
||||
MessageDialog dlg(wxGetApp().plater(), _L("A prime tower is required for smooth timelapse. There may be flaws on the model without prime tower. Are you sure you want to disable prime tower?"),
|
||||
_L("Warning"), wxICON_WARNING | wxYES | wxNO);
|
||||
if (dlg.ShowModal() == wxID_NO) {
|
||||
DynamicPrintConfig new_conf = *m_config;
|
||||
new_conf.set_key_value("enable_prime_tower", new ConfigOptionBool(true));
|
||||
m_config_manipulation.apply(m_config, &new_conf);
|
||||
}
|
||||
wxGetApp().plater()->update();
|
||||
}
|
||||
bool is_precise_z_height = m_config->option<ConfigOptionBool>("precise_z_height")->value;
|
||||
if (boost::any_cast<bool>(value) && is_precise_z_height) {
|
||||
MessageDialog dlg(wxGetApp().plater(), _L("Enabling both precise Z height and the prime tower may cause the size of prime tower to increase. Do you still want to enable?"),
|
||||
_L("Warning"), wxICON_WARNING | wxYES | wxNO);
|
||||
if (dlg.ShowModal() == wxID_NO) {
|
||||
DynamicPrintConfig new_conf = *m_config;
|
||||
new_conf.set_key_value("enable_prime_tower", new ConfigOptionBool(false));
|
||||
m_config_manipulation.apply(m_config, &new_conf);
|
||||
}
|
||||
wxGetApp().plater()->update();
|
||||
}
|
||||
update_wiping_button_visibility();
|
||||
}
|
||||
|
||||
|
||||
if (opt_key == "single_extruder_multi_material" ){
|
||||
const auto bSEMM = m_config->opt_bool("single_extruder_multi_material");
|
||||
wxGetApp().sidebar().show_SEMM_buttons(bSEMM);
|
||||
|
@ -2165,20 +2206,30 @@ void TabPrint::build()
|
|||
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_pattern", "strength_settings_infill#sparse-infill-pattern");
|
||||
optgroup->append_single_option_line("infill_direction");
|
||||
optgroup->append_single_option_line("sparse_infill_rotate_template");
|
||||
optgroup->append_single_option_line("skin_infill_density");
|
||||
optgroup->append_single_option_line("skeleton_infill_density");
|
||||
optgroup->append_single_option_line("infill_lock_depth");
|
||||
optgroup->append_single_option_line("skin_infill_depth");
|
||||
optgroup->append_single_option_line("skin_infill_line_width", "parameter/line-width");
|
||||
optgroup->append_single_option_line("skeleton_infill_line_width", "parameter/line-width");
|
||||
optgroup->append_single_option_line("symmetric_infill_y_axis");
|
||||
optgroup->append_single_option_line("infill_shift_step");
|
||||
|
||||
optgroup->append_single_option_line("lattice_angle_1");
|
||||
optgroup->append_single_option_line("lattice_angle_2");
|
||||
optgroup->append_single_option_line("infill_overhang_angle");
|
||||
optgroup->append_single_option_line("infill_anchor_max");
|
||||
optgroup->append_single_option_line("infill_anchor");
|
||||
optgroup->append_single_option_line("internal_solid_infill_pattern");
|
||||
optgroup->append_single_option_line("solid_infill_direction");
|
||||
optgroup->append_single_option_line("solid_infill_rotate_template");
|
||||
optgroup->append_single_option_line("gap_fill_target");
|
||||
optgroup->append_single_option_line("filter_out_gap_fill");
|
||||
optgroup->append_single_option_line("infill_wall_overlap");
|
||||
|
||||
optgroup = page->new_optgroup(L("Advanced"), L"param_advanced");
|
||||
optgroup->append_single_option_line("infill_direction");
|
||||
optgroup->append_single_option_line("solid_infill_direction");
|
||||
optgroup->append_single_option_line("rotate_solid_infill_direction");
|
||||
optgroup->append_single_option_line("bridge_angle");
|
||||
optgroup->append_single_option_line("internal_bridge_angle"); // ORCA: Internal bridge angle override
|
||||
optgroup->append_single_option_line("minimum_sparse_infill_area");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue