mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-11 19:17:33 +00:00
Merge remote-tracking branch 'upstream/main' into dev/h2d
# Conflicts: # resources/profiles/BBL.json # src/slic3r/GUI/AmsMappingPopup.cpp # src/slic3r/GUI/MediaFilePanel.cpp # src/slic3r/GUI/Plater.cpp # src/slic3r/GUI/StatusPanel.cpp
This commit is contained in:
@@ -21,6 +21,197 @@
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
// Calculate infill rotation angle (in radians) for a given layer from a rotation template.
|
||||
// Grammar subset handled (rotation only):
|
||||
// [±]α[*Z or !][joint][-][N|B|T][length][* or !]
|
||||
// [±]α* sets an initial angle only (no layer processed)
|
||||
// Where:
|
||||
// - α: angle in degrees. Without a sign it's absolute; with +/− it's relative. α% means a percentage of 360°.
|
||||
// - Runtime: *Z repeats the instruction Z times; bare * is a no-op used for initialization; ! runs once globally and then stops.
|
||||
// - Solid signs (D,S,O,M,R) are not processed here; if present they are treated as invalid/non-rotation characters.
|
||||
// - Joint signs (shape of the turn across a range):
|
||||
// / linear;
|
||||
// N,n vertical sinus (n = lazy/half amplitude);
|
||||
// Z,z horizontal sinus (z = lazy/half amplitude);
|
||||
// $ arcsin; L quarter circle H→V; l quarter circle V→H;
|
||||
// U,u squared; Q,q cubic; ~ random; ^ pseudorandom; | middle step; # vertical step at end.
|
||||
// - Counting / range length:
|
||||
// After the joint (or after α) a count determines duration of the turn:
|
||||
// N = layer count, B = bottom_shell_layers, T = top_shell_layers.
|
||||
// Prefix '-' flips the joint (swap initial/final orientation).
|
||||
// - Length modifiers convert the count to a Z range instead of a pure layer count:
|
||||
// mm, cm, m, ' (feet), " (inches), # (standard height of N layers), % (percent of model height).
|
||||
//
|
||||
// Behavior:
|
||||
// - The template string is tokenized by commas/whitespace and evaluated cyclically with one or more "ranges" per token.
|
||||
// - Absolute α resets the accumulated angle at the start of its range; relative α accumulates.
|
||||
// - *Z and ! control repetition and one-time execution of tokens across layers.
|
||||
// - If the template contains no metalanguage symbols, it is treated as a simple comma-separated list of angles repeated by modulo.
|
||||
// - Returns angle in radians for the requested layer_id. 0° aligns with +X; fillers may internally rotate as needed.
|
||||
double calculate_infill_rotation_angle(const PrintObject* object,
|
||||
size_t layer_id,
|
||||
const double& fixed_infill_angle,
|
||||
const std::string& template_string)
|
||||
{
|
||||
if (template_string.empty()) {
|
||||
return Geometry::deg2rad(fixed_infill_angle);
|
||||
}
|
||||
double angle = 0.0;
|
||||
ConfigOptionFloats rotate_angles;
|
||||
const std::string search_string = "/NnZz$LlUuQq~^|#";
|
||||
if (regex_search(template_string, std::regex("[+\\-%*@\'\"cm" + search_string + "]"))) { // template metalanguage of rotating infill
|
||||
std::regex del("[\\s,]+");
|
||||
std::sregex_token_iterator it(template_string.begin(), template_string.end(), del, -1);
|
||||
std::vector<std::string> tk;
|
||||
std::sregex_token_iterator end;
|
||||
while (it != end) {
|
||||
tk.push_back(*it++);
|
||||
}
|
||||
int t = 0;
|
||||
int repeats = 0;
|
||||
double angle_add = 0;
|
||||
double angle_steps = 1;
|
||||
double angle_start = 0;
|
||||
double limit_fill_z = object->get_layer(0)->bottom_z();
|
||||
double start_fill_z = limit_fill_z;
|
||||
bool _noop = false;
|
||||
auto fill_form = std::string::npos;
|
||||
bool _absolute = false;
|
||||
bool _negative = false;
|
||||
std::vector<bool> stop(tk.size(), false);
|
||||
|
||||
for (int i = 0; i <= layer_id; i++) {
|
||||
double fill_z = object->get_layer(i)->bottom_z();
|
||||
|
||||
if (limit_fill_z < object->get_layer(i)->slice_z) {
|
||||
if (repeats) { // if repeats >0 then restore parameters for new iteration
|
||||
limit_fill_z += limit_fill_z - start_fill_z;
|
||||
start_fill_z = fill_z;
|
||||
repeats--;
|
||||
} else {
|
||||
start_fill_z = fill_z;
|
||||
limit_fill_z = object->get_layer(i)->print_z;
|
||||
// Solid handling removed: this function only computes rotation.
|
||||
fill_form = std::string::npos;
|
||||
do {
|
||||
if (!stop[t]) {
|
||||
_noop = false;
|
||||
_absolute = false;
|
||||
_negative = false;
|
||||
angle_start += angle_add;
|
||||
angle_add = 0;
|
||||
angle_steps = 1;
|
||||
repeats = 1;
|
||||
if (tk[t].find('!') != std::string::npos) // this is an one-time instruction
|
||||
stop[t] = true;
|
||||
|
||||
char* cs = &tk[t][0];
|
||||
|
||||
if ((cs[0] >= '0' && cs[0] <= '9') && !(cs[0] == '+' || cs[0] == '-')) // absolute/relative
|
||||
_absolute = true;
|
||||
|
||||
angle_add = strtod(cs, &cs); // read angle parameter
|
||||
|
||||
if (cs[0] == '%') { // percentage of angles
|
||||
angle_add *= 3.6;
|
||||
cs = &cs[1];
|
||||
}
|
||||
|
||||
int tit = tk[t].find('*');
|
||||
if (tit != std::string::npos) // overall angle_cycles
|
||||
repeats = strtol(&tk[t][tit + 1], &cs, 0);
|
||||
|
||||
if (repeats) { // run if overall cycles greater than 0
|
||||
// Solid signs (D,S,O,M,R) are not handled here; if present they behave as invalid characters.
|
||||
|
||||
if (cs[0] == 'B') {
|
||||
angle_steps = object->print()->default_region_config().bottom_shell_layers.value;
|
||||
} else if (cs[0] == 'T') {
|
||||
angle_steps = object->print()->default_region_config().top_shell_layers.value;
|
||||
} else {
|
||||
fill_form = search_string.find(cs[0]);
|
||||
if (fill_form != std::string::npos)
|
||||
cs = &cs[1];
|
||||
|
||||
_negative = (cs[0] == '-'); // negative parameter
|
||||
angle_steps = abs(strtod(cs, &cs));
|
||||
|
||||
if (angle_steps && cs[0] != '\0' && cs[0] != '!') {
|
||||
if (cs[0] == '%') // value in the percents of fill_z
|
||||
limit_fill_z = angle_steps * object->height() * 1e-8;
|
||||
else if (cs[0] == '#') // value in the feet
|
||||
limit_fill_z = angle_steps * object->config().layer_height;
|
||||
else if (cs[0] == '\'') // value in the feet
|
||||
limit_fill_z = angle_steps * 12 * 25.4;
|
||||
else if (cs[0] == '\"') // value in the inches
|
||||
limit_fill_z = angle_steps * 25.4;
|
||||
else if (cs[0] == 'c') // value in centimeters
|
||||
limit_fill_z = angle_steps * 10.;
|
||||
else if (cs[0] == 'm') {
|
||||
if (cs[1] == 'm') { // value in the millimeters
|
||||
limit_fill_z = angle_steps * 1.;
|
||||
} else{
|
||||
limit_fill_z = angle_steps * 1000.;
|
||||
}
|
||||
}
|
||||
limit_fill_z += fill_z;
|
||||
angle_steps = 0; // limit_fill_z has already count
|
||||
}
|
||||
}
|
||||
if (angle_steps) { // if limit_fill_z does not setting by lenght method. Get count the layer id above model height
|
||||
if (fill_form == std::string::npos && !_absolute)
|
||||
angle_add *= (int) angle_steps;
|
||||
int idx = i + std::max(angle_steps - 1, 0.);
|
||||
int sdx = std::max(0, idx - (int) object->layers().size());
|
||||
idx = std::min(idx, (int) object->layers().size() - 1);
|
||||
limit_fill_z = object->get_layer(idx)->print_z + sdx * object->config().layer_height;
|
||||
}
|
||||
repeats = std::max(--repeats, 0);
|
||||
} else
|
||||
_noop = true; // set the dumb cycle
|
||||
if (_absolute) { // is absolute
|
||||
angle_start = angle_add;
|
||||
angle_add = 0;
|
||||
}
|
||||
}
|
||||
if (++t >= tk.size())
|
||||
t = 0;
|
||||
} while (std::all_of(stop.begin(), stop.end(), [](bool v) { return v; }) ?
|
||||
false :
|
||||
(t ? _noop : false) || stop[t]); // if this is a dumb instruction which never reaprated twice
|
||||
}
|
||||
}
|
||||
double top_z = object->get_layer(i)->print_z;
|
||||
double negvalue = (_negative ? limit_fill_z - top_z : top_z - start_fill_z) / (limit_fill_z - start_fill_z);
|
||||
|
||||
switch (fill_form) {
|
||||
case 0: break; // /-joint, linear
|
||||
case 1: negvalue -= sin(negvalue * PI * 2.) / (PI * 2.); break; // N-joint, sinus, vertical start
|
||||
case 2: negvalue -= sin(negvalue * PI * 2.) / (PI * 4.); break; // n-joint, sinus, vertical start, lazy
|
||||
case 3: negvalue += sin(negvalue * PI * 2.) / (PI * 2.); break; // Z-joint, sinus, horizontal start
|
||||
case 4: negvalue += sin(negvalue * PI * 2.) / (PI * 4.); break; // z-joint, sinus, horizontal start, lazy
|
||||
case 5: negvalue = asin(negvalue * 2. - 1.) / PI + 0.5; break; // $-joint, arcsin
|
||||
case 6: negvalue = sin(negvalue * PI / 2.); break; // L-joint, quarter of circle, horizontal start
|
||||
case 7: negvalue = 1. - cos(negvalue * PI / 2.); break; // l-joint, quarter of circle, vertical start
|
||||
case 8: negvalue = 1. - pow(1. - negvalue, 2); break; // U-joint, squared, x2
|
||||
case 9: negvalue = pow(1 - negvalue, 2); break; // u-joint, squared, x2 inverse
|
||||
case 10: negvalue = 1. - pow(1. - negvalue, 3); break; // Q-joint, cubic, x3
|
||||
case 11: negvalue = pow(1. - negvalue, 3); break; // q-joint, cubic, x3 inverse
|
||||
case 12: negvalue = (double) rand() / RAND_MAX; break; // ~-joint, random, fill the whole angle
|
||||
case 13: negvalue += (double) rand() / RAND_MAX - 0.5; break; // ^-joint, pseudorandom, disperse at middle line
|
||||
case 14: negvalue = 0.5; break; // |-joint, like #-joint but placed at middle angle
|
||||
case 15: negvalue = _negative ? 0. : 1.; break; // #-joint, vertical at the end angle
|
||||
}
|
||||
angle = Geometry::deg2rad(angle_start + angle_add * negvalue);
|
||||
}
|
||||
} else {
|
||||
rotate_angles.deserialize(template_string);
|
||||
auto rotate_angle_idx = layer_id % rotate_angles.size();
|
||||
angle = Geometry::deg2rad(rotate_angles.values[rotate_angle_idx]);
|
||||
}
|
||||
return angle;
|
||||
}
|
||||
|
||||
struct SurfaceFillParams
|
||||
{
|
||||
// Zero based extruder ID.
|
||||
@@ -35,6 +226,8 @@ struct SurfaceFillParams
|
||||
coordf_t overlap = 0.;
|
||||
// Angle as provided by the region config, in radians.
|
||||
float angle = 0.f;
|
||||
// Orca: is_using_template_angle
|
||||
bool is_using_template_angle = false;
|
||||
// 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.
|
||||
@@ -90,6 +283,7 @@ struct SurfaceFillParams
|
||||
RETURN_COMPARE_NON_EQUAL(spacing);
|
||||
RETURN_COMPARE_NON_EQUAL(overlap);
|
||||
RETURN_COMPARE_NON_EQUAL(angle);
|
||||
RETURN_COMPARE_NON_EQUAL(is_using_template_angle);
|
||||
RETURN_COMPARE_NON_EQUAL(density);
|
||||
RETURN_COMPARE_NON_EQUAL(multiline);
|
||||
// RETURN_COMPARE_NON_EQUAL_TYPED(unsigned, dont_adjust);
|
||||
@@ -118,6 +312,7 @@ struct SurfaceFillParams
|
||||
this->spacing == rhs.spacing &&
|
||||
this->overlap == rhs.overlap &&
|
||||
this->angle == rhs.angle &&
|
||||
this->is_using_template_angle == rhs.is_using_template_angle &&
|
||||
this->bridge == rhs.bridge &&
|
||||
this->bridge_angle == rhs.bridge_angle &&
|
||||
this->density == rhs.density &&
|
||||
@@ -627,7 +822,6 @@ std::vector<SurfaceFill> group_fills(const Layer &layer, LockRegionParam &lock_p
|
||||
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) {
|
||||
@@ -636,7 +830,6 @@ std::vector<SurfaceFill> group_fills(const Layer &layer, LockRegionParam &lock_p
|
||||
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) {
|
||||
@@ -652,11 +845,9 @@ std::vector<SurfaceFill> group_fills(const Layer &layer, LockRegionParam &lock_p
|
||||
params.extruder = layerm.region().extruder(extrusion_role);
|
||||
params.pattern = region_config.sparse_infill_pattern.value;
|
||||
params.density = float(region_config.sparse_infill_density);
|
||||
params.multiline = int(region_config.fill_multiline);
|
||||
params.lateral_lattice_angle_1 = region_config.lateral_lattice_angle_1;
|
||||
params.lateral_lattice_angle_2 = region_config.lateral_lattice_angle_2;
|
||||
params.infill_overhang_angle = region_config.infill_overhang_angle;
|
||||
params.angle = 0.;
|
||||
if (params.pattern == ipLockedZag) {
|
||||
params.infill_lock_depth = scale_(region_config.infill_lock_depth);
|
||||
params.skin_infill_depth = scale_(region_config.skin_infill_depth);
|
||||
@@ -704,17 +895,24 @@ std::vector<SurfaceFill> group_fills(const Layer &layer, LockRegionParam &lock_p
|
||||
params.extrusion_role = erSolidInfill;
|
||||
}
|
||||
}
|
||||
// Orca: apply fill multiline only for sparse infill
|
||||
params.multiline = params.extrusion_role == erInternalInfill ? int(region_config.fill_multiline) : 1;
|
||||
|
||||
if (params.extrusion_role == erInternalInfill) {
|
||||
params.angle = calculate_infill_rotation_angle(layer.object(), layer.id(), region_config.infill_direction.value,
|
||||
region_config.sparse_infill_rotate_template.value);
|
||||
params.is_using_template_angle = !region_config.sparse_infill_rotate_template.value.empty();
|
||||
} else {
|
||||
params.angle = calculate_infill_rotation_angle(layer.object(), layer.id(), region_config.solid_infill_direction.value,
|
||||
region_config.solid_infill_rotate_template.value);
|
||||
params.is_using_template_angle = !region_config.solid_infill_rotate_template.value.empty();
|
||||
}
|
||||
params.bridge_angle = float(surface.bridge_angle);
|
||||
|
||||
if (region_config.align_infill_direction_to_model) {
|
||||
auto m = layer.object()->trafo().matrix();
|
||||
params.angle += atan2((float) m(1, 0), (float) m(0, 0));
|
||||
}
|
||||
if (params.extrusion_role == erInternalInfill) {
|
||||
params.angle += float(Geometry::deg2rad(region_config.infill_direction.value));
|
||||
} else {
|
||||
params.angle += float(Geometry::deg2rad(region_config.solid_infill_direction.value));
|
||||
}
|
||||
|
||||
// Calculate the actual flow we'll be using for this infill.
|
||||
params.bridge = is_bridge || Fill::use_bridge_flow(params.pattern);
|
||||
@@ -892,8 +1090,12 @@ std::vector<SurfaceFill> group_fills(const Layer &layer, LockRegionParam &lock_p
|
||||
params.pattern = ipRectilinear;
|
||||
params.density = 100.f;
|
||||
params.extrusion_role = erSolidInfill;
|
||||
params.angle = float(Geometry::deg2rad(layerm.region().config().solid_infill_direction.value));
|
||||
// calculate the actual flow we'll be using for this infill
|
||||
const PrintRegionConfig ®ion_config = layerm.region().config();
|
||||
params.angle = calculate_infill_rotation_angle(layer.object(), layer.id(), region_config.solid_infill_direction.value,
|
||||
region_config.solid_infill_rotate_template.value);
|
||||
params.is_using_template_angle = !region_config.solid_infill_rotate_template.value.empty();
|
||||
|
||||
// calculate the actual flow we'll be using for this infill
|
||||
params.flow = layerm.flow(frSolidInfill);
|
||||
params.spacing = params.flow.spacing();
|
||||
surface_fills.emplace_back(params);
|
||||
@@ -996,6 +1198,7 @@ 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->is_using_template_angle = surface_fill.params.is_using_template_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();
|
||||
@@ -1054,184 +1257,7 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
|
||||
params.config = ®ion_config;
|
||||
params.pattern = surface_fill.params.pattern;
|
||||
|
||||
ConfigOptionFloats rotate_angles;
|
||||
const std::string search_string = "/NnZz$LlUuQq~^|#";
|
||||
std::string v(params.extrusion_role == erInternalInfill ? region_config.sparse_infill_rotate_template.value :
|
||||
region_config.solid_infill_rotate_template.value);
|
||||
if (regex_search(v, std::regex("[+\\-%*@\'\"cmSODMR" + search_string + "]"))) { // template metalanguage of rotating infill
|
||||
std::regex del("[\\s,]+");
|
||||
std::sregex_token_iterator it(v.begin(), v.end(), del, -1);
|
||||
std::vector<std::string> tk;
|
||||
std::sregex_token_iterator end;
|
||||
while (it != end) {
|
||||
tk.push_back(*it++);
|
||||
}
|
||||
int t = 0;
|
||||
int repeats = 0;
|
||||
double angle = 0;
|
||||
double angle_add = 0;
|
||||
double angle_steps = 1;
|
||||
double angle_start = 0;
|
||||
double limit_fill_z = this->object()->get_layer(0)->bottom_z();
|
||||
double start_fill_z = limit_fill_z;
|
||||
bool _noop = false;
|
||||
auto solid = std::string::npos; // -1 - sparse, 0 - native (D), 1 - internal solid (S), 2 - concentric (O), 3 - monotonic (M), 4 - rectilinear (R)
|
||||
auto fill_form = std::string::npos;
|
||||
bool _absolute = false;
|
||||
bool _negative = false;
|
||||
std::vector<bool> stop(tk.size(), false);
|
||||
|
||||
for (int i = 0; i <= this->id(); i++) {
|
||||
double fill_z = this->object()->get_layer(i)->bottom_z();
|
||||
|
||||
if (limit_fill_z < this->object()->get_layer(i)->slice_z) {
|
||||
if (repeats) { // if repeats >0 then restore parameters for new iteration
|
||||
limit_fill_z += limit_fill_z - start_fill_z;
|
||||
start_fill_z = fill_z;
|
||||
repeats--;
|
||||
} else {
|
||||
start_fill_z = fill_z;
|
||||
limit_fill_z = this->object()->get_layer(i)->print_z;
|
||||
solid = std::string::npos;
|
||||
fill_form = std::string::npos;
|
||||
do {
|
||||
if (!stop[t]) {
|
||||
_noop = false;
|
||||
_absolute = false;
|
||||
_negative = false;
|
||||
angle_start += angle_add;
|
||||
angle_add = 0;
|
||||
angle_steps = 1;
|
||||
repeats = 1;
|
||||
if (tk[t].find('!') != std::string::npos) // this is an one-time instruction
|
||||
stop[t] = true;
|
||||
|
||||
char* cs = &tk[t][0];
|
||||
|
||||
if ((cs[0] >= '0' && cs[0] <= '9') && !(cs[0] == '+' || cs[0] == '-')) // absolute/relative
|
||||
_absolute = true;
|
||||
|
||||
angle_add = strtod(cs, &cs); // read angle parameter
|
||||
|
||||
if (cs[0] == '%') { // percentage of angles
|
||||
angle_add *= 3.6;
|
||||
cs = &cs[1];
|
||||
}
|
||||
|
||||
int tit = tk[t].find('*');
|
||||
if (tit != std::string::npos) // overall angle_cycles
|
||||
repeats = strtol(&tk[t][tit + 1], &cs, 0);
|
||||
|
||||
if (repeats) { // run if overall cycles greater than 0
|
||||
solid = std::string("DSOMR").find(cs[0]); // solid infill
|
||||
if (solid != std::string::npos)
|
||||
cs = &cs[1];
|
||||
|
||||
if (cs[0] == 'B') {
|
||||
angle_steps = this->object()->print()->default_region_config().bottom_shell_layers.value;
|
||||
} else if (cs[0] == 'T') {
|
||||
angle_steps = this->object()->print()->default_region_config().top_shell_layers.value;
|
||||
} else {
|
||||
fill_form = search_string.find(cs[0]);
|
||||
if (fill_form != std::string::npos)
|
||||
cs = &cs[1];
|
||||
|
||||
_negative = (cs[0] == '-'); // negative parameter
|
||||
angle_steps = abs(strtod(cs, &cs));
|
||||
|
||||
if (angle_steps && cs[0] != '\0' && cs[0] != '!') {
|
||||
if (cs[0] == '%') // value in the percents of fill_z
|
||||
limit_fill_z = angle_steps * this->object()->height() * 1e-8;
|
||||
else if (cs[0] == '#') // value in the feet
|
||||
limit_fill_z = angle_steps * this->object()->config().layer_height;
|
||||
else if (cs[0] == '\'') // value in the feet
|
||||
limit_fill_z = angle_steps * 12 * 25.4;
|
||||
else if (cs[0] == '\"') // value in the inches
|
||||
limit_fill_z = angle_steps * 25.4;
|
||||
else if (cs[0] == 'c') // value in centimeters
|
||||
limit_fill_z = angle_steps * 10.;
|
||||
else if (cs[0] == 'm')
|
||||
if (cs[1] == 'm') { // value in the millimeters
|
||||
limit_fill_z = angle_steps * 1.;
|
||||
} else // value in the meters
|
||||
limit_fill_z = angle_steps * 1000.;
|
||||
limit_fill_z += fill_z;
|
||||
angle_steps = 0; // limit_fill_z has already count
|
||||
}
|
||||
}
|
||||
if (angle_steps) { // if limit_fill_z does not setting by lenght method. Get count the layer id above model height
|
||||
if (fill_form == std::string::npos && !_absolute)
|
||||
angle_add *= (int) angle_steps;
|
||||
int idx = i + std::max(angle_steps - 1, 0.);
|
||||
int sdx = std::max(0, idx - (int) this->object()->layers().size());
|
||||
idx = std::min(idx, (int) this->object()->layers().size() - 1);
|
||||
limit_fill_z = this->object()->get_layer(idx)->print_z + sdx * this->object()->config().layer_height;
|
||||
}
|
||||
repeats = std::max(--repeats, 0);
|
||||
} else
|
||||
_noop = true; // set the dumb cycle
|
||||
if (_absolute) { // is absolute
|
||||
angle_start = angle_add;
|
||||
angle_add = 0;
|
||||
}
|
||||
}
|
||||
if (++t >= tk.size())
|
||||
t = 0;
|
||||
} while (std::all_of(stop.begin(), stop.end(), [](bool v) { return v; }) ? false :
|
||||
(t ? _noop : false) || stop[t]); // if this is a dumb instruction which never reaprated twice
|
||||
}
|
||||
}
|
||||
double top_z = this->object()->get_layer(i)->print_z;
|
||||
double negvalue = (_negative ? limit_fill_z - top_z : top_z - start_fill_z) / (limit_fill_z - start_fill_z);
|
||||
|
||||
switch (fill_form) {
|
||||
case 0: break; // /-joint, linear
|
||||
case 1: negvalue -= sin(negvalue * PI * 2.) / (PI * 2.); break; // N-joint, sinus, vertical start
|
||||
case 2: negvalue -= sin(negvalue * PI * 2.) / (PI * 4.); break; // n-joint, sinus, vertical start, lazy
|
||||
case 3: negvalue += sin(negvalue * PI * 2.) / (PI * 2.); break; // Z-joint, sinus, horizontal start
|
||||
case 4: negvalue += sin(negvalue * PI * 2.) / (PI * 4.); break; // z-joint, sinus, horizontal start, lazy
|
||||
case 5: negvalue = asin(negvalue * 2. - 1.) / PI + 0.5; break; // $-joint, arcsin
|
||||
case 6: negvalue = sin(negvalue * PI / 2.); break; // L-joint, quarter of circle, horizontal start
|
||||
case 7: negvalue = 1. - cos(negvalue * PI / 2.); break; // l-joint, quarter of circle, vertical start
|
||||
case 8: negvalue = 1. - pow(1. - negvalue, 2); break; // U-joint, squared, x2
|
||||
case 9: negvalue = pow(1 - negvalue, 2); break; // u-joint, squared, x2 inverse
|
||||
case 10: negvalue = 1. - pow(1. - negvalue, 3); break; // Q-joint, cubic, x3
|
||||
case 11: negvalue = pow(1. - negvalue, 3); break; // q-joint, cubic, x3 inverse
|
||||
case 12: negvalue = (double) rand() / RAND_MAX; break; // ~-joint, random, fill the whole angle
|
||||
case 13: negvalue += (double) rand() / RAND_MAX - 0.5; break; // ^-joint, pseudorandom, disperse at middle line
|
||||
case 14: negvalue = 0.5; break; // |-joint, like #-joint but placed at middle angle
|
||||
case 15: negvalue = _negative ? 0. : 1.; break; // #-joint, vertical at the end angle
|
||||
}
|
||||
angle = angle_start + angle_add * negvalue;
|
||||
}
|
||||
if (solid != std::string::npos) {
|
||||
switch (solid) {
|
||||
case 1: params.pattern = region_config.internal_solid_infill_pattern.value; break; // selected solid pattern
|
||||
case 2: params.pattern = ipConcentric; break; // concentric pattern
|
||||
case 3: params.pattern = ipMonotonic; break; // monotonic pattern
|
||||
case 4: params.pattern = ipRectilinear; // rectilinear pattern
|
||||
} // or else use native pattern
|
||||
params.extrusion_role = erSolidInfill;
|
||||
params.density = 1.;
|
||||
surface_fill.params.pattern = params.pattern;
|
||||
|
||||
f = std::unique_ptr<Fill>(Fill::new_from_type(params.pattern)); // reinitialize surface
|
||||
f->set_bounding_box(bbox);
|
||||
f->layer_id = this->id();
|
||||
f->z = this->print_z;
|
||||
f->angle = surface_fill.params.angle;
|
||||
f->print_config = &this->object()->print()->config();
|
||||
f->print_object_config = &this->object()->config();
|
||||
params.use_arachne = surface_fill.params.pattern == ipConcentric || surface_fill.params.pattern == ipConcentricInternal;
|
||||
}
|
||||
f->rotate_angle = Geometry::deg2rad(angle);
|
||||
} else {
|
||||
rotate_angles.deserialize(v);
|
||||
auto rotate_angle_idx = f->layer_id % rotate_angles.size();
|
||||
f->rotate_angle = Geometry::deg2rad(rotate_angles.values[rotate_angle_idx]);
|
||||
}
|
||||
|
||||
if( surface_fill.params.pattern == ipLockedZag ) {
|
||||
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;
|
||||
@@ -1293,7 +1319,23 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
|
||||
assert(dynamic_cast<ExtrusionEntityCollection*>(layerm->fills.entities[i]) != nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate sparse-infill polylines for anchoring/analysis purposes.
|
||||
*
|
||||
* This produces the geometric polylines of internal sparse infill for the current
|
||||
* layer (using the same infill pattern, angle, rotation template, and spacing that
|
||||
* normal slicing would use), but it does not create extrusion entities.
|
||||
*
|
||||
* The returned polylines are consumed by internal-bridge detection on the next
|
||||
* layer to derive anchor lines and compute the bridge direction over sparse infill.
|
||||
*
|
||||
* Notes:
|
||||
* - Only `stInternal` surfaces are considered.
|
||||
* - Rotation templates (e.g. `sparse_infill_rotate_template`) are applied so the
|
||||
* anchors reflect the actual infill orientation.
|
||||
* - For lightning/adaptive patterns, the respective generators are wired so their
|
||||
* polylines match the final infill layout.
|
||||
*/
|
||||
Polylines Layer::generate_sparse_infill_polylines_for_anchoring(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive::Octree* support_fill_octree, FillLightning::Generator* lightning_generator) const
|
||||
{
|
||||
LockRegionParam skin_inner_param;
|
||||
@@ -1346,6 +1388,7 @@ Polylines Layer::generate_sparse_infill_polylines_for_anchoring(FillAdaptive::Oc
|
||||
f->layer_id = this->id() - this->object()->get_layer(0)->id(); // We need to subtract raft layers.
|
||||
f->z = this->print_z;
|
||||
f->angle = surface_fill.params.angle;
|
||||
f->is_using_template_angle = surface_fill.params.is_using_template_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();
|
||||
|
||||
@@ -15,8 +15,9 @@ 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; }
|
||||
// note: updated 3D Honeycomb doesn't need bridge flow because the
|
||||
// pattern is placed on top of previous layers
|
||||
bool use_bridge_flow() const override { return false; }
|
||||
bool is_self_crossing() override { return false; }
|
||||
|
||||
protected:
|
||||
|
||||
@@ -306,7 +306,9 @@ std::pair<float, Point> Fill::_infill_direction(const Surface *surface) const
|
||||
out_angle = float(surface->bridge_angle);
|
||||
} else if (this->layer_id != size_t(-1)) {
|
||||
// alternate fill direction
|
||||
out_angle += this->_layer_angle(this->layer_id / surface->thickness_layers);
|
||||
//Orca: if template angle is not empty, don't apply layer angle
|
||||
if(!is_using_template_angle)
|
||||
out_angle += this->_layer_angle(this->layer_id / surface->thickness_layers);
|
||||
} else {
|
||||
// printf("Layer_ID undefined!\n");
|
||||
}
|
||||
|
||||
@@ -119,8 +119,8 @@ public:
|
||||
coordf_t overlap;
|
||||
// in radians, ccw, 0 = East
|
||||
float angle;
|
||||
// Orca: enable angle shifting for layer change
|
||||
float rotate_angle{ M_PI/180.0 };
|
||||
// Orca: is_using_template_angle
|
||||
bool is_using_template_angle{false};
|
||||
// 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.
|
||||
@@ -182,7 +182,6 @@ protected:
|
||||
overlap(0.),
|
||||
// Initial angle is undefined.
|
||||
angle(FLT_MAX),
|
||||
rotate_angle(M_PI/180.0),
|
||||
link_max_length(0),
|
||||
loop_clipping(0),
|
||||
// The initial bounding box is empty, therefore undefined.
|
||||
@@ -204,7 +203,7 @@ protected:
|
||||
ExPolygon expolygon,
|
||||
ThickPolylines& thick_polylines_out) {}
|
||||
|
||||
virtual float _layer_angle(size_t idx) const { return rotate_angle; }
|
||||
virtual float _layer_angle(size_t idx) const { return is_using_template_angle ? 0.f : (idx & 1) ? float(M_PI/2.) : 0.f; }
|
||||
|
||||
virtual std::pair<float, Point> _infill_direction(const Surface *surface) const;
|
||||
|
||||
|
||||
@@ -3044,7 +3044,7 @@ Polylines FillRectilinear::fill_surface(const Surface *surface, const FillParams
|
||||
{
|
||||
Polylines polylines_out;
|
||||
// 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 (params.full_infill() || params.multiline == 1 || 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 {
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
#include <tbb/parallel_for.h>
|
||||
#include <mutex>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
@@ -157,8 +156,8 @@ vector<double> getGridValues(int i, int j, vector<vector<double>>& data)
|
||||
values.push_back(data[i][j]);
|
||||
return values;
|
||||
}
|
||||
bool needContour(double value, double contourValue) { return value >= contourValue; }
|
||||
Point interpolate(std::vector<std::vector<MarchingSquares::Point>>& posxy,
|
||||
static bool needContour(double value, double contourValue) { return value >= contourValue; }
|
||||
static Point interpolate(std::vector<std::vector<MarchingSquares::Point>>& posxy,
|
||||
std::vector<int> p1ij,
|
||||
std::vector<int> p2ij,
|
||||
double v1,
|
||||
@@ -186,7 +185,7 @@ Point interpolate(std::vector<std::vector<MarchingSquares::Point>>& posxy,
|
||||
return p;
|
||||
}
|
||||
|
||||
void process_block(int i,
|
||||
static void process_block(int i,
|
||||
int j,
|
||||
vector<vector<double>>& data,
|
||||
double contourValue,
|
||||
@@ -288,43 +287,7 @@ void process_block(int i,
|
||||
}
|
||||
}
|
||||
|
||||
// --- Chaikin Smooth ---
|
||||
|
||||
static Polyline chaikin_smooth(Polyline poly, int iterations , double weight )
|
||||
{
|
||||
if (poly.points.size() < 3) return poly;
|
||||
|
||||
const double w1 = 1.0 - weight;
|
||||
decltype(poly.points) buffer;
|
||||
buffer.reserve(poly.points.size() * 2);
|
||||
|
||||
for (int it = 0; it < iterations; ++it) {
|
||||
buffer.clear();
|
||||
buffer.push_back(poly.points.front());
|
||||
|
||||
for (size_t i = 0; i < poly.points.size() - 1; ++i) {
|
||||
const auto &p0 = poly.points[i];
|
||||
const auto &p1 = poly.points[i + 1];
|
||||
|
||||
buffer.emplace_back(
|
||||
p0.x() * w1 + p1.x() * weight,
|
||||
p0.y() * w1 + p1.y() * weight
|
||||
);
|
||||
buffer.emplace_back(
|
||||
p0.x() * weight + p1.x() * w1,
|
||||
p0.y() * weight + p1.y() * w1
|
||||
);
|
||||
}
|
||||
|
||||
buffer.push_back(poly.points.back());
|
||||
poly.points.swap(buffer);
|
||||
}
|
||||
|
||||
return poly;
|
||||
}
|
||||
|
||||
|
||||
void drawContour(double contourValue,
|
||||
static void drawContour(double contourValue,
|
||||
int gridSize_w,
|
||||
int gridSize_h,
|
||||
vector<vector<double>>& data,
|
||||
@@ -382,62 +345,18 @@ void drawContour(double contourValue,
|
||||
for (myPoint& pt : p) {
|
||||
repltmp.points.push_back(Slic3r::Point(pt.x, pt.y));
|
||||
}
|
||||
// symplify tolerance based on density
|
||||
const float min_tolerance = 0.005f;
|
||||
const float max_tolerance = 0.2f;
|
||||
float simplify_tolerance = (0.005f / params.density);
|
||||
simplify_tolerance = std::clamp(simplify_tolerance, min_tolerance, max_tolerance);
|
||||
repltmp.simplify(scale_(simplify_tolerance));
|
||||
repltmp = chaikin_smooth(repltmp, 2, 0.25);
|
||||
repls.push_back(repltmp);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace MarchingSquares
|
||||
|
||||
static float sin_table[360];
|
||||
static float cos_table[360];
|
||||
static std::once_flag trig_tables_once_flag;
|
||||
|
||||
#define PIratio 57.29577951308232 // 180/PI
|
||||
|
||||
static void initialize_lookup_tables()
|
||||
{
|
||||
for (int i = 0; i < 360; ++i) {
|
||||
float angle = i * (M_PI / 180.0);
|
||||
sin_table[i] = std::sin(angle);
|
||||
cos_table[i] = std::cos(angle);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline static void ensure_trig_tables_initialized()
|
||||
{
|
||||
std::call_once(trig_tables_once_flag, initialize_lookup_tables);
|
||||
}
|
||||
|
||||
inline static float get_sin(float angle)
|
||||
{
|
||||
angle = angle * PIratio;
|
||||
int index = static_cast<int>(std::fmod(angle, 360) + 360) % 360;
|
||||
return sin_table[index];
|
||||
}
|
||||
|
||||
inline static float get_cos(float angle)
|
||||
{
|
||||
angle = angle * PIratio;
|
||||
int index = static_cast<int>(std::fmod(angle, 360) + 360) % 360;
|
||||
return cos_table[index];
|
||||
}
|
||||
|
||||
void FillTpmsFK::_fill_surface_single(const FillParams& params,
|
||||
unsigned int thickness_layers,
|
||||
const std::pair<float, Point>& direction,
|
||||
ExPolygon expolygon,
|
||||
Polylines& polylines_out)
|
||||
{
|
||||
ensure_trig_tables_initialized();
|
||||
|
||||
auto infill_angle = float(this->angle + (CorrectionAngle * 2 * M_PI) / 360.);
|
||||
if(std::abs(infill_angle) >= EPSILON)
|
||||
expolygon.rotate(-infill_angle);
|
||||
@@ -452,40 +371,29 @@ void FillTpmsFK::_fill_surface_single(const FillParams& params,
|
||||
float xlen = boxsize.x();
|
||||
float ylen = boxsize.y();
|
||||
|
||||
const float delta = 0.5f; // mesh step (adjust for quality/performance)
|
||||
|
||||
const float delta = 0.4f; // mesh step (adjust for quality/performance)
|
||||
float myperiod = 2 * PI / vari_T;
|
||||
float c_z = myperiod * this->z; // z height
|
||||
|
||||
// scalar field Fischer-Koch
|
||||
auto scalar_field = [&](float x, float y) {
|
||||
float a_x = myperiod * x;
|
||||
float b_y = myperiod * y;
|
||||
|
||||
auto scalar_field = [&](float x, float y) -> float {
|
||||
const float a_x = myperiod * x;
|
||||
const float b_y = myperiod * y;
|
||||
|
||||
// Fischer - Koch S equation:
|
||||
// cos(2x)sin(y)cos(z) + cos(2y)sin(z)cos(x) + cos(2z)sin(x)cos(y) = 0
|
||||
const float cos2ax = get_cos(2*a_x);
|
||||
const float cos2by = get_cos(2*b_y);
|
||||
const float cos2cz = get_cos(2*c_z);
|
||||
const float sinby = get_sin(b_y);
|
||||
const float cosax = get_cos(a_x);
|
||||
const float sinax = get_sin(a_x);
|
||||
const float cosby = get_cos(b_y);
|
||||
const float sincz = get_sin(c_z);
|
||||
const float coscz = get_cos(c_z);
|
||||
|
||||
return cos2ax * sinby * coscz
|
||||
+ cos2by * sincz * cosax
|
||||
+ cos2cz * sinax * cosby;
|
||||
return cosf(2 * a_x) * sinf(b_y) * cosf(c_z)
|
||||
+ cosf(2 * b_y) * sinf(c_z) * cosf(a_x)
|
||||
+ cosf(2 * c_z) * sinf(a_x) * cosf(b_y);
|
||||
};
|
||||
|
||||
// Mesh generation
|
||||
std::vector<std::vector<MarchingSquares::Point>> posxy;
|
||||
int i = 0, j = 0;
|
||||
for (float y = -(ylen) / 2.0f - 2; y < (ylen) / 2.0f + 2; y = y + delta, i++) {
|
||||
for (float y = -(ylen) / 2.0f - 0.5f; y < (ylen) / 2.0f + 0.5f; y = y + delta, i++) {
|
||||
j = 0;
|
||||
std::vector<MarchingSquares::Point> colposxy;
|
||||
for (float x = -(xlen) / 2.0f - 2; x < (xlen) / 2.0f + 2; x = x + delta, j++) {
|
||||
for (float x = -(xlen) / 2.0f - 0.5f; x < (xlen) / 2.0f + 0.5f; x = x + delta, j++) {
|
||||
MarchingSquares::Point pt;
|
||||
pt.x = cenpos.x() + x;
|
||||
pt.y = cenpos.y() + y;
|
||||
@@ -510,33 +418,36 @@ void FillTpmsFK::_fill_surface_single(const FillParams& params,
|
||||
|
||||
|
||||
Polylines polylines;
|
||||
const double contour_value = 0.075; // offset from zero to avoid numerical issues
|
||||
const double contour_value = 0; // offset from theoretical surface
|
||||
MarchingSquares::drawContour(contour_value, width , height , data, posxy, polylines, params);
|
||||
|
||||
if (!polylines.empty()) {
|
||||
// Apply multiline offset if needed
|
||||
multiline_fill(polylines, params, spacing);
|
||||
// Apply multiline offset if needed
|
||||
multiline_fill(polylines, params, spacing);
|
||||
|
||||
polylines = intersection_pl(polylines, expolygon);
|
||||
|
||||
polylines = intersection_pl(polylines, expolygon);
|
||||
|
||||
// Remove very small bits, but be careful to not remove infill lines connecting thin walls!
|
||||
if (! polylines.empty()) {
|
||||
// Remove very small bits, but be careful to not remove infill lines connecting thin walls!
|
||||
// The infill perimeter lines should be separated by around a single infill line width.
|
||||
const double minlength = scale_(0.8 * this->spacing);
|
||||
polylines.erase(
|
||||
std::remove_if(polylines.begin(), polylines.end(), [minlength](const Polyline &pl) { return pl.length() < minlength; }),
|
||||
polylines.end());
|
||||
}
|
||||
|
||||
if (! polylines.empty()) {
|
||||
// connect lines
|
||||
size_t polylines_out_first_idx = polylines_out.size();
|
||||
chain_or_connect_infill(std::move(polylines), expolygon, polylines_out, this->spacing, params);
|
||||
|
||||
//chain_or_connect_infill(std::move(polylines), expolygon, polylines_out, this->spacing, params);
|
||||
//chain_infill not situable for this pattern due to internal "islands", this also affect performance a lot.
|
||||
connect_infill(std::move(polylines), expolygon, polylines_out, this->spacing, params);
|
||||
|
||||
// new paths must be rotated back
|
||||
if (std::abs(infill_angle) >= EPSILON) {
|
||||
for (auto it = polylines_out.begin() + polylines_out_first_idx; it != polylines_out.end(); ++ it)
|
||||
it->rotate(infill_angle);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1129,7 +1129,7 @@ void PerimeterGenerator::process_classic()
|
||||
coord_t ext_perimeter_spacing = this->ext_perimeter_flow.scaled_spacing();
|
||||
coord_t ext_perimeter_spacing2;
|
||||
// Orca: ignore precise_outer_wall if wall_sequence is not InnerOuter
|
||||
if(config->precise_outer_wall)
|
||||
if(config->precise_outer_wall && config->wall_sequence == WallSequence::InnerOuter)
|
||||
ext_perimeter_spacing2 = scaled<coord_t>(0.5f * (this->ext_perimeter_flow.width() + this->perimeter_flow.width()));
|
||||
else
|
||||
ext_perimeter_spacing2 = scaled<coord_t>(0.5f * (this->ext_perimeter_flow.spacing() + this->perimeter_flow.spacing()));
|
||||
@@ -2124,7 +2124,7 @@ void PerimeterGenerator::process_arachne()
|
||||
if (is_topmost_layer && loop_number > 0 && config->only_one_wall_top)
|
||||
loop_number = 0;
|
||||
|
||||
auto apply_precise_outer_wall = config->precise_outer_wall;
|
||||
auto apply_precise_outer_wall = config->precise_outer_wall && config->wall_sequence == WallSequence::InnerOuter;
|
||||
// Orca: properly adjust offset for the outer wall if precise_outer_wall is enabled.
|
||||
ExPolygons last = offset_ex(surface.expolygon.simplify_p(surface_simplify_resolution),
|
||||
apply_precise_outer_wall? -float(ext_perimeter_width - ext_perimeter_spacing )
|
||||
|
||||
@@ -788,7 +788,7 @@ static std::vector<std::string> s_Preset_print_options {
|
||||
"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","fill_multiline", "sparse_infill_pattern", "lateral_lattice_angle_1", "lateral_lattice_angle_2", "infill_overhang_angle", "top_surface_pattern", "bottom_surface_pattern",
|
||||
"infill_direction", "solid_infill_direction", "counterbore_hole_bridging","infill_shift_step", "sparse_infill_rotate_template", "solid_infill_rotate_template", "symmetric_infill_y_axis","skeleton_infill_density", "infill_lock_depth", "skin_infill_depth", "skin_infill_density",
|
||||
"align_infill_direction_to_model",
|
||||
"align_infill_direction_to_model", "extra_solid_infills",
|
||||
"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",
|
||||
|
||||
@@ -1627,6 +1627,12 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
|
||||
// }
|
||||
// }
|
||||
|
||||
// check wall sequence and precise outer wall
|
||||
if (m_default_region_config.precise_outer_wall && m_default_region_config.wall_sequence != WallSequence::InnerOuter) {
|
||||
warning->string = L("The precise wall option will be ignored for outer-inner or inner-outer-inner wall sequences.");
|
||||
warning->opt_key = "precise_outer_wall";
|
||||
}
|
||||
|
||||
} catch (std::exception& e) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "Orca: validate motion ability failed: " << e.what() << std::endl;
|
||||
}
|
||||
|
||||
@@ -679,7 +679,7 @@ void PrintConfigDef::init_common_params()
|
||||
|
||||
def = this->add("preferred_orientation", coFloat);
|
||||
def->label = L("Preferred orientation");
|
||||
def->tooltip = L("Automatically orient stls on the Z-axis upon initial import.");
|
||||
def->tooltip = L("Automatically orient stls on the Z axis upon initial import.");
|
||||
def->sidetext = "°"; // degrees, don't need translation
|
||||
def->max = 360;
|
||||
def->min = -360;
|
||||
@@ -1203,9 +1203,10 @@ void PrintConfigDef::init_fff_params()
|
||||
def = this->add("precise_outer_wall",coBool);
|
||||
def->label = L("Precise wall");
|
||||
def->category = L("Quality");
|
||||
def->tooltip = L("Improve shell precision by adjusting outer wall spacing. This also improves layer consistency.");
|
||||
def->set_default_value(new ConfigOptionBool{false});
|
||||
|
||||
def->tooltip = L("Improve shell precision by adjusting outer wall spacing. This also improves layer consistency. NOTE: This option "
|
||||
"will be ignored for outer-inner or inner-outer-inner wall sequences.");
|
||||
def->set_default_value(new ConfigOptionBool{true});
|
||||
|
||||
def = this->add("only_one_wall_top", coBool);
|
||||
def->label = L("Only one wall on top surfaces");
|
||||
def->category = L("Quality");
|
||||
@@ -1454,9 +1455,9 @@ void PrintConfigDef::init_fff_params()
|
||||
def = this->add("brim_ears_detection_length", coFloat);
|
||||
def->label = L("Brim ear detection radius");
|
||||
def->category = L("Support");
|
||||
def->tooltip = L("The geometry will be decimated before detecting sharp angles. This parameter indicates the "
|
||||
"minimum length of the deviation for the decimation. "
|
||||
"\n0 to deactivate.");
|
||||
def->tooltip = L("The geometry will be decimated before detecting sharp angles. "
|
||||
"This parameter indicates the minimum length of the deviation for the decimation.\n"
|
||||
"0 to deactivate.");
|
||||
def->sidetext = "mm"; // milimeters, don't need translation
|
||||
def->min = 0;
|
||||
def->mode = comAdvanced;
|
||||
@@ -2114,8 +2115,8 @@ void PrintConfigDef::init_fff_params()
|
||||
|
||||
def = this->add("default_filament_colour", coStrings);
|
||||
def->label = L("Default color");
|
||||
def->tooltip = L("Default filament color"
|
||||
"\nRight click to reset value to system default.");
|
||||
def->tooltip = L("Default filament color.\n"
|
||||
"Right click to reset value to system default.");
|
||||
def->gui_type = ConfigOptionDef::GUIType::color;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionStrings{""});
|
||||
@@ -2567,6 +2568,13 @@ void PrintConfigDef::init_fff_params()
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("extra_solid_infills", coString);
|
||||
def->label = L("Insert solid layers");
|
||||
def->category = L("Strength");
|
||||
def->tooltip = L("Insert solid infill at specific layers. Use N to insert every Nth layer, N#K to insert K consecutive solid layers every N layers (K is optional, e.g. '5#' equals '5#1'), or a comma-separated list (e.g. 1,7,9) to insert at explicit layers. Layers are 1-based.");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionString());
|
||||
|
||||
|
||||
// Infill multiline
|
||||
def = this->add("fill_multiline", coInt);
|
||||
@@ -2816,7 +2824,7 @@ void PrintConfigDef::init_fff_params()
|
||||
|
||||
def = this->add("default_junction_deviation", coFloat);
|
||||
def->label = L("Junction Deviation");
|
||||
def->tooltip = L("Marlin Firmware Junction Deviation (replaces the traditional XY Jerk setting)");
|
||||
def->tooltip = L("Marlin Firmware Junction Deviation (replaces the traditional XY Jerk setting).");
|
||||
def->sidetext = "mm"; // milimeters, don't need translation
|
||||
def->min = 0;
|
||||
def->mode = comAdvanced;
|
||||
@@ -3044,7 +3052,7 @@ void PrintConfigDef::init_fff_params()
|
||||
"This is the fast and straight algorithm without unnecessary nozzle shake that gives a smooth pattern. "
|
||||
"But it is more useful for forming loose walls in the entire they array.\n"
|
||||
"Combined: Joint mode [Displacement] + [Extrusion]. The appearance of the walls is similar to [Displacement] Mode, but it leaves no pores between the perimeters.\n\n"
|
||||
"Attention! The [Extrusion] and [Combined] modes works only the fuzzy_skin_thickness parameter not more than the thickness of printed loop."
|
||||
"Attention! The [Extrusion] and [Combined] modes works only the fuzzy_skin_thickness parameter not more than the thickness of printed loop. "
|
||||
"At the same time, the width of the extrusion for a particular layer should also not be below a certain level. "
|
||||
"It is usually equal 15-25%% of a layer height. Therefore, the maximum fuzzy skin thickness with a perimeter width of 0.4 mm and a layer height of 0.2 mm will be 0.4-(0.2*0.25)=±0.35mm! "
|
||||
"If you enter a higher parameter than this, the error Flow::spacing() will displayed, and the model will not be sliced. You can choose this number until this error is repeated." );
|
||||
@@ -3366,35 +3374,37 @@ void PrintConfigDef::init_fff_params()
|
||||
|
||||
//Orca
|
||||
def = this->add("sparse_infill_rotate_template", coString);
|
||||
def->label = L("Sparse infill rotatation template");
|
||||
def->label = L("Sparse infill rotation 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 sparse infill patterns support rotation.");
|
||||
def->tooltip = L("Rotate the sparse infill direction per layer using a template of angles. "
|
||||
"Enter comma-separated degrees (e.g., '0,30,60,90'). "
|
||||
"Angles are applied in order by layer and repeat when the list ends. "
|
||||
"Advanced syntax is supported: '+5' rotates +5° every layer; '+5#5' rotates +5° every 5 layers. See the Wiki for details. "
|
||||
"When a template is set, the standard infill direction setting is ignored. "
|
||||
"Note: some infill patterns (e.g., Gyroid) control rotation themselves; use with care.");
|
||||
def->sidetext = L("°");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionString("0,90"));
|
||||
def->set_default_value(new ConfigOptionString(""));
|
||||
|
||||
//Orca
|
||||
def = this->add("solid_infill_rotate_template", coString);
|
||||
def->label = L("Solid infill rotatation template");
|
||||
def->label = L("Solid infill rotation 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 solid infill patterns support rotation.");
|
||||
def->sidetext = L("°");
|
||||
def->sidetext = "°"; // degrees, don't need translation
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionString("0,90"));
|
||||
|
||||
def->set_default_value(new ConfigOptionString(""));
|
||||
|
||||
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->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;
|
||||
@@ -3404,9 +3414,10 @@ void PrintConfigDef::init_fff_params()
|
||||
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->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;
|
||||
@@ -3454,9 +3465,9 @@ void PrintConfigDef::init_fff_params()
|
||||
def->set_default_value(new ConfigOptionFloatOrPercent(100, true));
|
||||
|
||||
def = this->add("symmetric_infill_y_axis", coBool);
|
||||
def->label = L("Symmetric infill y axis");
|
||||
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,"
|
||||
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));
|
||||
@@ -3693,7 +3704,7 @@ void PrintConfigDef::init_fff_params()
|
||||
def = this->add("ironing_speed", coFloat);
|
||||
def->label = L("Ironing speed");
|
||||
def->category = L("Quality");
|
||||
def->tooltip = L("Print speed of ironing lines");
|
||||
def->tooltip = L("Print speed of ironing lines.");
|
||||
def->sidetext = "mm/s"; // milimeters per second, don't need translation
|
||||
def->min = 1;
|
||||
def->mode = comAdvanced;
|
||||
@@ -3858,7 +3869,7 @@ void PrintConfigDef::init_fff_params()
|
||||
def = this->add("machine_max_junction_deviation", coFloats);
|
||||
def->full_label = L("Maximum Junction Deviation");
|
||||
def->category = L("Machine limits");
|
||||
def->tooltip = L("Maximum junction deviation (M205 J, only apply if JD > 0 for Marlin Firmware)");
|
||||
def->tooltip = L("Maximum junction deviation (M205 J, only apply if JD > 0 for Marlin Firmware)");
|
||||
def->sidetext = "mm"; // milimeters, don't need translation
|
||||
def->min = 0;
|
||||
def->mode = comAdvanced;
|
||||
@@ -4044,7 +4055,7 @@ void PrintConfigDef::init_fff_params()
|
||||
|
||||
def = this->add("nozzle_diameter", coFloats);
|
||||
def->label = L("Nozzle diameter");
|
||||
def->tooltip = L("Diameter of nozzle");
|
||||
def->tooltip = L("The diameter of nozzle.");
|
||||
def->sidetext = "mm"; // milimeters, don't need translation
|
||||
def->mode = comAdvanced;
|
||||
def->max = 100;
|
||||
@@ -4218,7 +4229,7 @@ void PrintConfigDef::init_fff_params()
|
||||
def->gui_type = ConfigOptionDef::GUIType::i_enum_open;
|
||||
def->label = L("Walls");
|
||||
def->category = L("Extruders");
|
||||
def->tooltip = L("Filament to print walls");
|
||||
def->tooltip = L("Filament to print walls.");
|
||||
def->min = 1;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionInt(1));
|
||||
@@ -4277,7 +4288,7 @@ void PrintConfigDef::init_fff_params()
|
||||
|
||||
def = this->add("printer_model", coString);
|
||||
def->label = L("Printer type");
|
||||
def->tooltip = L("Type of the printer");
|
||||
def->tooltip = L("Type of the printer.");
|
||||
def->set_default_value(new ConfigOptionString());
|
||||
def->cli = ConfigOptionDef::nocli;
|
||||
|
||||
@@ -4812,10 +4823,10 @@ void PrintConfigDef::init_fff_params()
|
||||
def->min = 0;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloatOrPercent(80,true));
|
||||
|
||||
|
||||
def = this->add("skirt_distance", coFloat);
|
||||
def->label = L("Skirt distance");
|
||||
def->tooltip = L("Distance from skirt to brim or object");
|
||||
def->tooltip = L("The distance from the skirt to the brim or the object.");
|
||||
def->sidetext = "mm"; // milimeters, don't need translation
|
||||
def->min = 0;
|
||||
def->max = 60;
|
||||
@@ -4924,7 +4935,7 @@ void PrintConfigDef::init_fff_params()
|
||||
def->gui_type = ConfigOptionDef::GUIType::i_enum_open;
|
||||
def->label = L("Solid infill");
|
||||
def->category = L("Extruders");
|
||||
def->tooltip = L("Filament to print solid infill");
|
||||
def->tooltip = L("Filament to print solid infill.");
|
||||
def->min = 1;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionInt(1));
|
||||
@@ -5089,7 +5100,7 @@ void PrintConfigDef::init_fff_params()
|
||||
|
||||
def = this->add("enable_filament_ramming", coBool);
|
||||
def->label = L("Enable filament ramming");
|
||||
def->tooltip = L("Enable filament ramming.");
|
||||
def->tooltip = L("Enable filament ramming");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBool(true));
|
||||
|
||||
@@ -5940,7 +5951,7 @@ void PrintConfigDef::init_fff_params()
|
||||
|
||||
def = this->add("wipe_tower_rotation_angle", coFloat);
|
||||
def->label = L("Wipe tower rotation angle");
|
||||
def->tooltip = L("Wipe tower rotation angle with respect to x-axis.");
|
||||
def->tooltip = L("Wipe tower rotation angle with respect to X axis.");
|
||||
def->sidetext = "°"; // degrees, don't need translation
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(0.));
|
||||
@@ -5994,7 +6005,7 @@ void PrintConfigDef::init_fff_params()
|
||||
|
||||
def = this->add("wipe_tower_extra_rib_length", coFloat);
|
||||
def->label = L("Extra rib length");
|
||||
def->tooltip = L("Positive values can increase the size of the rib wall, while negative values can reduce the size."
|
||||
def->tooltip = L("Positive values can increase the size of the rib wall, while negative values can reduce the size. "
|
||||
"However, the size of the rib wall can not be smaller than that determined by the cleaning volume.");
|
||||
def->sidetext = "mm"; // milimeters, don't need translation
|
||||
def->max = 300;
|
||||
@@ -6003,7 +6014,7 @@ void PrintConfigDef::init_fff_params()
|
||||
|
||||
def = this->add("wipe_tower_rib_width", coFloat);
|
||||
def->label = L("Rib width");
|
||||
def->tooltip = L("Rib width");
|
||||
def->tooltip = L("Rib width.");
|
||||
def->sidetext = "mm"; // milimeters, don't need translation
|
||||
def->mode = comAdvanced;
|
||||
def->min = 0;
|
||||
@@ -9345,7 +9356,7 @@ CLIMiscConfigDef::CLIMiscConfigDef()
|
||||
def->set_default_value(new ConfigOptionString());
|
||||
|
||||
def = this->add("load_filament_ids", coInts);
|
||||
def->label = L("Load filament ids");
|
||||
def->label = L("Load filament IDs");
|
||||
def->tooltip = L("Load filament IDs for each object.");
|
||||
def->cli_params = "\"1,2,3,1\"";
|
||||
def->set_default_value(new ConfigOptionInts());
|
||||
@@ -9373,25 +9384,25 @@ CLIMiscConfigDef::CLIMiscConfigDef()
|
||||
|
||||
def = this->add("makerlab_name", coString);
|
||||
def->label = L("MakerLab name");
|
||||
def->tooltip = L("MakerLab name to generate this 3mf");
|
||||
def->tooltip = L("MakerLab name to generate this 3mf.");
|
||||
def->cli_params = "name";
|
||||
def->set_default_value(new ConfigOptionString());
|
||||
|
||||
def = this->add("makerlab_version", coString);
|
||||
def->label = L("MakerLab version");
|
||||
def->tooltip = L("MakerLab version to generate this 3mf");
|
||||
def->tooltip = L("MakerLab version to generate this 3mf.");
|
||||
def->cli_params = "version";
|
||||
def->set_default_value(new ConfigOptionString());
|
||||
|
||||
def = this->add("metadata_name", coStrings);
|
||||
def->label = L("metadata name list");
|
||||
def->tooltip = L("metadata name list added into 3mf");
|
||||
def->tooltip = L("metadata name list added into 3mf.");
|
||||
def->cli_params = "\"name1;name2;...\"";
|
||||
def->set_default_value(new ConfigOptionStrings());
|
||||
|
||||
def = this->add("metadata_value", coStrings);
|
||||
def->label = L("metadata value list");
|
||||
def->tooltip = L("metadata value list added into 3mf");
|
||||
def->tooltip = L("metadata value list added into 3mf.");
|
||||
def->cli_params = "\"value1;value2;...\"";
|
||||
def->set_default_value(new ConfigOptionStrings());
|
||||
|
||||
@@ -9741,11 +9752,11 @@ CustomGcodeSpecificConfigDef::CustomGcodeSpecificConfigDef()
|
||||
def->tooltip = L("Index of the current layer. One-based (i.e. first layer is number 1).");
|
||||
|
||||
def = this->add("layer_z", coFloat);
|
||||
def->label = L("Layer z");
|
||||
def->label = L("Layer Z");
|
||||
def->tooltip = L("Height of the current layer above the print bed, measured to the top of the layer.");
|
||||
|
||||
def = this->add("max_layer_z", coFloat);
|
||||
def->label = L("Maximal layer z");
|
||||
def->label = L("Maximal layer Z");
|
||||
def->tooltip = L("Height of the last layer above the print bed.");
|
||||
|
||||
def = this->add("filament_extruder_id", coInt);
|
||||
@@ -9755,32 +9766,32 @@ CustomGcodeSpecificConfigDef::CustomGcodeSpecificConfigDef()
|
||||
// change_filament_gcode
|
||||
new_def("previous_extruder", coInt, "Previous extruder", "Index of the extruder that is being unloaded. The index is zero based (first extruder has index 0).");
|
||||
new_def("next_extruder", coInt, "Next extruder", "Index of the extruder that is being loaded. The index is zero based (first extruder has index 0).");
|
||||
new_def("relative_e_axis", coBool, "Relative e-axis", "Indicates if relative positioning is being used");
|
||||
new_def("toolchange_count", coInt, "Toolchange count", "The number of toolchanges throught the print");
|
||||
new_def("relative_e_axis", coBool, "Relative e-axis", "Indicates if relative positioning is being used.");
|
||||
new_def("toolchange_count", coInt, "Toolchange count", "The number of toolchanges throught the print.");
|
||||
new_def("fan_speed", coNone, "", ""); //Option is no longer used and is zeroed by placeholder parser for compatability
|
||||
new_def("old_retract_length", coFloat, "Old retract length", "The retraction length of the previous filament");
|
||||
new_def("new_retract_length", coFloat, "New retract length", "The retraction lenght of the new filament");
|
||||
new_def("old_retract_length_toolchange", coFloat, "Old retract length toolchange", "The toolchange retraction length of the previous filament");
|
||||
new_def("new_retract_length_toolchange", coFloat, "New retract length toolchange", "The toolchange retraction length of the new filament");
|
||||
new_def("old_filament_temp", coInt, "Old filament temp", "The old filament temp");
|
||||
new_def("new_filament_temp", coInt, "New filament temp", "The new filament temp");
|
||||
new_def("x_after_toolchange", coFloat, "X after toolchange", "The x pos after toolchange");
|
||||
new_def("y_after_toolchange", coFloat, "Y after toolchange", "The y pos after toolchange");
|
||||
new_def("z_after_toolchange", coFloat, "Z after toolchange", "The z pos after toolchange");
|
||||
new_def("first_flush_volume", coFloat, "First flush volume", "The first flush volume");
|
||||
new_def("second_flush_volume", coFloat, "Second flush volume", "The second flush volume");
|
||||
new_def("old_filament_e_feedrate", coInt, "Old filament e feedrate", "The old filament extruder feedrate");
|
||||
new_def("new_filament_e_feedrate", coInt, "New filament e feedrate", "The new filament extruder feedrate");
|
||||
new_def("travel_point_1_x", coFloat, "Travel point 1 x", "The travel point 1 x");
|
||||
new_def("travel_point_1_y", coFloat, "Travel point 1 y", "The travel point 1 y");
|
||||
new_def("travel_point_2_x", coFloat, "Travel point 2 x", "The travel point 2 x");
|
||||
new_def("travel_point_2_y", coFloat, "Travel point 2 y", "The travel point 2 y");
|
||||
new_def("travel_point_3_x", coFloat, "Travel point 3 x", "The travel point 3 x");
|
||||
new_def("travel_point_3_y", coFloat, "Travel point 3 y", "The travel point 3 y");
|
||||
new_def("flush_length_1", coFloat, "Flush Length 1", "The first flush length");
|
||||
new_def("flush_length_2", coFloat, "Flush Length 2", "The second flush length");
|
||||
new_def("flush_length_3", coFloat, "Flush Length 3", "The third flush length");
|
||||
new_def("flush_length_4", coFloat, "Flush Length 4", "The fourth flush length");
|
||||
new_def("old_retract_length", coFloat, "Old retract length", "The retraction length of the previous filament.");
|
||||
new_def("new_retract_length", coFloat, "New retract length", "The retraction lenght of the new filament.");
|
||||
new_def("old_retract_length_toolchange", coFloat, "Old retract length toolchange", "The toolchange retraction length of the previous filament.");
|
||||
new_def("new_retract_length_toolchange", coFloat, "New retract length toolchange", "The toolchange retraction length of the new filament.");
|
||||
new_def("old_filament_temp", coInt, "Old filament temp", "The old filament temp.");
|
||||
new_def("new_filament_temp", coInt, "New filament temp", "The new filament temp.");
|
||||
new_def("x_after_toolchange", coFloat, "X after toolchange", "The X pos after toolchange.");
|
||||
new_def("y_after_toolchange", coFloat, "Y after toolchange", "The Y pos after toolchange.");
|
||||
new_def("z_after_toolchange", coFloat, "Z after toolchange", "The Z pos after toolchange.");
|
||||
new_def("first_flush_volume", coFloat, "First flush volume", "The first flush volume.");
|
||||
new_def("second_flush_volume", coFloat, "Second flush volume", "The second flush volume.");
|
||||
new_def("old_filament_e_feedrate", coInt, "Old filament e feedrate", "The old filament extruder feedrate.");
|
||||
new_def("new_filament_e_feedrate", coInt, "New filament e feedrate", "The new filament extruder feedrate.");
|
||||
new_def("travel_point_1_x", coFloat, "Travel point 1 X", "The travel point 1 X.");
|
||||
new_def("travel_point_1_y", coFloat, "Travel point 1 Y", "The travel point 1 Y.");
|
||||
new_def("travel_point_2_x", coFloat, "Travel point 2 X", "The travel point 2 X.");
|
||||
new_def("travel_point_2_y", coFloat, "Travel point 2 Y", "The travel point 2 Y.");
|
||||
new_def("travel_point_3_x", coFloat, "Travel point 3 X", "The travel point 3 X.");
|
||||
new_def("travel_point_3_y", coFloat, "Travel point 3 Y", "The travel point 3 Y.");
|
||||
new_def("flush_length_1", coFloat, "Flush Length 1", "The first flush length.");
|
||||
new_def("flush_length_2", coFloat, "Flush Length 2", "The second flush length.");
|
||||
new_def("flush_length_3", coFloat, "Flush Length 3", "The third flush length.");
|
||||
new_def("flush_length_4", coFloat, "Flush Length 4", "The fourth flush length.");
|
||||
|
||||
// change_extrusion_role_gcode
|
||||
std::string extrusion_role_types = "Possible Values:\n[\"Perimeter\", \"ExternalPerimeter\", "
|
||||
|
||||
@@ -1044,6 +1044,7 @@ PRINT_CONFIG_CLASS_DEFINE(
|
||||
((ConfigOptionFloat, lateral_lattice_angle_2))
|
||||
((ConfigOptionFloat, infill_overhang_angle))
|
||||
((ConfigOptionBool, align_infill_direction_to_model))
|
||||
((ConfigOptionString, extra_solid_infills))
|
||||
((ConfigOptionEnum<FuzzySkinType>, fuzzy_skin))
|
||||
((ConfigOptionFloat, fuzzy_skin_thickness))
|
||||
((ConfigOptionFloat, fuzzy_skin_point_distance))
|
||||
|
||||
@@ -1203,6 +1203,7 @@ bool PrintObject::invalidate_state_by_config_options(
|
||||
|| opt_key == "infill_direction"
|
||||
|| opt_key == "solid_infill_direction"
|
||||
|| opt_key == "align_infill_direction_to_model"
|
||||
|| opt_key == "extra_solid_infills"
|
||||
|| opt_key == "ensure_vertical_shell_thickness"
|
||||
|| opt_key == "bridge_angle"
|
||||
|| opt_key == "internal_bridge_angle" // ORCA: Internal bridge angle override
|
||||
@@ -1268,7 +1269,6 @@ bool PrintObject::invalidate_state_by_config_options(
|
||||
|| opt_key == "overhang_reverse_internal_only"
|
||||
|| opt_key == "overhang_reverse_threshold"
|
||||
|| opt_key == "wall_direction"
|
||||
//BBS
|
||||
|| opt_key == "enable_overhang_speed"
|
||||
|| opt_key == "detect_thin_wall"
|
||||
|| opt_key == "precise_outer_wall") {
|
||||
@@ -3613,16 +3613,14 @@ void PrintObject::discover_horizontal_shells()
|
||||
Layer *layer = m_layers[i];
|
||||
LayerRegion *layerm = layer->regions()[region_id];
|
||||
const PrintRegionConfig ®ion_config = layerm->region().config();
|
||||
#if 0
|
||||
if (region_config.solid_infill_every_layers.value > 0 && region_config.sparse_infill_density.value > 0 &&
|
||||
(i % region_config.solid_infill_every_layers) == 0) {
|
||||
// Insert a solid internal layer. Mark stInternal surfaces as stInternalSolid or stInternalBridge.
|
||||
SurfaceType type = (region_config.sparse_infill_density == 100 || region_config.solid_infill_every_layers == 1) ? stInternalSolid : stInternalBridge;
|
||||
for (Surface &surface : layerm->fill_surfaces.surfaces)
|
||||
|
||||
if (!region_config.extra_solid_infills.value.empty() &&
|
||||
check_layer_id_pattern(region_config.extra_solid_infills.value, i)) {
|
||||
// Insert a solid internal layer. Mark stInternal surfaces as stInternalSolid.
|
||||
for (Surface& surface : layerm->fill_surfaces.surfaces)
|
||||
if (surface.surface_type == stInternal)
|
||||
surface.surface_type = type;
|
||||
surface.surface_type = stInternalSolid;
|
||||
}
|
||||
#endif
|
||||
|
||||
// If ensure_vertical_shell_thickness, then the rest has already been performed by discover_vertical_shells().
|
||||
if (region_config.ensure_vertical_shell_thickness.value == evstAll)
|
||||
|
||||
@@ -695,6 +695,8 @@ void copy_directory_recursively(const boost::filesystem::path &source, const boo
|
||||
void save_string_file(const boost::filesystem::path& p, const std::string& str);
|
||||
void load_string_file(const boost::filesystem::path& p, std::string& str);
|
||||
|
||||
bool check_layer_id_pattern(const std::string& pattern, int layer_id);
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#if WIN32
|
||||
|
||||
@@ -1578,4 +1578,91 @@ void load_string_file(const boost::filesystem::path& p, std::string& str)
|
||||
file.read(&str[0], sz);
|
||||
}
|
||||
|
||||
// pattern string supprt these pattern: "
|
||||
// 1. 5#1, insert 1 solid layer every 5 layers. this can be simplified to 5
|
||||
// 2."1,7,9", explicitly insert solid layer at layer 1, 7, 9
|
||||
bool check_layer_id_pattern(const std::string& pattern, int layer_id){
|
||||
if (pattern.empty() || layer_id < 0)
|
||||
return false;
|
||||
|
||||
// layer_id is 0-based, so we need to add 1 to make it 1-based
|
||||
layer_id++;
|
||||
|
||||
// Remove whitespace and surrounding quotes.
|
||||
std::string p; p.reserve(pattern.size());
|
||||
for (char c : pattern) {
|
||||
if (c == ' ' || c == '\t' || c == '\n' || c == '\r')
|
||||
continue;
|
||||
p.push_back(c);
|
||||
}
|
||||
if (!p.empty() && (p.front() == '"' || p.front() == '\''))
|
||||
p.erase(p.begin());
|
||||
if (!p.empty() && (p.back() == '"' || p.back() == '\''))
|
||||
p.pop_back();
|
||||
if (p.empty())
|
||||
return false;
|
||||
|
||||
// Explicit list form: "1,7,9" or with counts per entry: "5,9#2,18"
|
||||
if (p.find(',') != std::string::npos) {
|
||||
size_t start = 0;
|
||||
while (start < p.size()) {
|
||||
size_t end = p.find(',', start);
|
||||
std::string token = p.substr(start, (end == std::string::npos) ? std::string::npos : end - start);
|
||||
if (!token.empty()) {
|
||||
try {
|
||||
size_t hash_pos_token = token.find('#');
|
||||
if (hash_pos_token == std::string::npos) {
|
||||
int value = std::stoi(token);
|
||||
if (value == layer_id)
|
||||
return true;
|
||||
} else {
|
||||
int base_layer = std::stoi(token.substr(0, hash_pos_token));
|
||||
std::string count_str = token.substr(hash_pos_token + 1);
|
||||
int local_count = 1;
|
||||
if (!count_str.empty())
|
||||
local_count = std::stoi(count_str);
|
||||
if (base_layer > 0 && local_count > 0) {
|
||||
if (layer_id >= base_layer && layer_id < base_layer + local_count)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (...) {
|
||||
// Ignore invalid tokens
|
||||
}
|
||||
}
|
||||
if (end == std::string::npos)
|
||||
break;
|
||||
start = end + 1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Interval form: "N#K" or simplified "N" (equals to N#1)
|
||||
int interval = 0;
|
||||
int count = 1;
|
||||
size_t hash_pos = p.find('#');
|
||||
try {
|
||||
if (hash_pos == std::string::npos) {
|
||||
interval = std::stoi(p);
|
||||
} else {
|
||||
interval = std::stoi(p.substr(0, hash_pos));
|
||||
std::string count_str = p.substr(hash_pos + 1);
|
||||
if (!count_str.empty())
|
||||
count = std::stoi(count_str);
|
||||
}
|
||||
} catch (...) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (interval <= 0 || count <= 0)
|
||||
return false;
|
||||
|
||||
// Layers are 1-based. Match layers interval, interval+1, ..., interval+count-1, then repeat every interval.
|
||||
if (layer_id < interval)
|
||||
return false;
|
||||
int mod = layer_id % interval; // For multiples, mod == 0
|
||||
return mod >= 0 && mod < count;
|
||||
}
|
||||
|
||||
|
||||
}; // namespace Slic3r
|
||||
|
||||
Reference in New Issue
Block a user