mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-11 14:59:01 +08:00
Perimeter loop:
- change seam function, old behavior for nearest is now on "hiding", nearest now prioritize the nearest heavily. - add lopping_peri seam option : rear => it put the externals ones on -y and the internal ones on +y, if possible. - debug looping_peri max_width (from 0.8 to 1.4)
This commit is contained in:
parent
b8dca4cb9d
commit
c1d46264ba
@ -1920,7 +1920,7 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// extrude all loops ccw
|
||||
//no! this was decided in perimeter_generator
|
||||
bool was_clockwise = false;// loop.make_counter_clockwise();
|
||||
@ -1934,7 +1934,7 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
|
||||
Point last_pos = this->last_pos();
|
||||
if (m_config.spiral_vase) {
|
||||
loop.split_at(last_pos, false);
|
||||
} else if (seam_position == spNearest || seam_position == spAligned || seam_position == spRear) {
|
||||
} else if (seam_position == spNearest || seam_position == spAligned || seam_position == spRear || seam_position == spHidden) {
|
||||
Polygon polygon = loop.polygon();
|
||||
const coordf_t nozzle_dmr = EXTRUDER_CONFIG(nozzle_diameter);
|
||||
const coord_t nozzle_r = coord_t(scale_(0.5 * nozzle_dmr) + 0.5);
|
||||
@ -1949,11 +1949,18 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
|
||||
last_pos_weight = 1.f;
|
||||
}
|
||||
break;
|
||||
case spNearest:
|
||||
last_pos_weight = 5.f;
|
||||
break;
|
||||
case spRear:
|
||||
last_pos = m_layer->object()->bounding_box().center();
|
||||
last_pos.y += coord_t(3. * m_layer->object()->bounding_box().radius());
|
||||
last_pos_weight = 5.f;
|
||||
break;
|
||||
case spHidden:
|
||||
last_pos_weight = 0.1f;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
// Insert a projection of last_pos into the polygon.
|
||||
@ -1975,7 +1982,16 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
|
||||
const float penaltySeam = 1.3f;
|
||||
const float penaltyOverhangHalf = 10.f;
|
||||
// Penalty for visible seams.
|
||||
for (size_t i = 0; i < polygon.points.size(); ++ i) {
|
||||
float dist_max = 0.1f * lengths.back();// 5.f * nozzle_dmr
|
||||
if (this->config().seam_travel) {
|
||||
dist_max = 0;
|
||||
for (size_t i = 0; i < polygon.points.size(); ++i) {
|
||||
dist_max = std::max(dist_max, (float)polygon.points[i].distance_to(last_pos_proj));
|
||||
}
|
||||
}
|
||||
//TODO: ignore the angle penalty if the new point is not in an external path (bot/top/ext_peri)
|
||||
for (size_t i = 0; i < polygon.points.size(); ++i) {
|
||||
//std::cout << "check point @" << unscale(polygon.points[i].x) << ":" << unscale(polygon.points[i].y);
|
||||
float ccwAngle = penalties[i];
|
||||
if (was_clockwise)
|
||||
ccwAngle = - ccwAngle;
|
||||
@ -1996,13 +2012,15 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
|
||||
// Interpolate penalty between maximum and the penalty for a convex vertex.
|
||||
penalty = penaltyConvexVertex + (penaltyFlatSurface - penaltyConvexVertex) * bspline_kernel(ccwAngle * float(PI * 2. / 3.));
|
||||
}
|
||||
// Give a negative penalty for points close to the last point or the prefered seam location.
|
||||
//float dist_to_last_pos_proj = last_pos_proj.distance_to(polygon.points[i]);
|
||||
float dist_to_last_pos_proj = (i < last_pos_proj_idx) ?
|
||||
std::min(lengths[last_pos_proj_idx] - lengths[i], lengths.back() - lengths[last_pos_proj_idx] + lengths[i]) :
|
||||
std::min(lengths[i] - lengths[last_pos_proj_idx], lengths.back() - lengths[i] + lengths[last_pos_proj_idx]);
|
||||
float dist_max = 0.1f * lengths.back(); // 5.f * nozzle_dmr
|
||||
penalty -= last_pos_weight * bspline_kernel(dist_to_last_pos_proj / dist_max);
|
||||
if (this->config().seam_travel) {
|
||||
penalty += last_pos_weight * polygon.points[i].distance_to(last_pos_proj) / dist_max;
|
||||
}else{
|
||||
// Give a negative penalty for points close to the last point or the prefered seam location.
|
||||
float dist_to_last_pos_proj = (i < last_pos_proj_idx) ?
|
||||
std::min(lengths[last_pos_proj_idx] - lengths[i], lengths.back() - lengths[last_pos_proj_idx] + lengths[i]) :
|
||||
std::min(lengths[i] - lengths[last_pos_proj_idx], lengths.back() - lengths[i] + lengths[last_pos_proj_idx]);
|
||||
penalty -= last_pos_weight * bspline_kernel(dist_to_last_pos_proj / dist_max);
|
||||
}
|
||||
penalties[i] = std::max(0.f, penalty);
|
||||
}
|
||||
|
||||
|
@ -45,9 +45,9 @@ public:
|
||||
int idx = -1;
|
||||
if (! this->points.empty()) {
|
||||
idx = 0;
|
||||
double dist_min = this->points.front().distance_to(point);
|
||||
double dist_min = this->points.front().distance_to_sq(point);
|
||||
for (int i = 1; i < int(this->points.size()); ++ i) {
|
||||
double d = this->points[i].distance_to(point);
|
||||
double d = this->points[i].distance_to_sq(point);
|
||||
if (d < dist_min) {
|
||||
dist_min = d;
|
||||
idx = i;
|
||||
|
@ -644,10 +644,10 @@ ExtrusionEntityCollection PerimeterGenerator::_traverse_loops(
|
||||
}
|
||||
|
||||
PerimeterIntersectionPoint
|
||||
get_nearest_point(const PerimeterGeneratorLoops &children, ExtrusionLoop &myPolylines, const coord_t dist_cut, const coord_t max_dist) {
|
||||
PerimeterGenerator::_get_nearest_point(const PerimeterGeneratorLoops &children, ExtrusionLoop &myPolylines, const coord_t dist_cut, const coord_t max_dist) const {
|
||||
//find best points of intersections
|
||||
PerimeterIntersectionPoint intersect;
|
||||
intersect.distance = 0x7FFFFFFF;
|
||||
intersect.distance = 0x7FFFFFFF; // ! assumption on intersect type & max value
|
||||
intersect.idx_polyline_outter = -1;
|
||||
intersect.idx_children = -1;
|
||||
for (size_t idx_child = 0; idx_child < children.size(); idx_child++) {
|
||||
@ -656,23 +656,54 @@ get_nearest_point(const PerimeterGeneratorLoops &children, ExtrusionLoop &myPoly
|
||||
if (myPolylines.paths[idx_poly].extruder_id == (unsigned int)-1) continue;
|
||||
if (myPolylines.paths[idx_poly].length() < dist_cut + SCALED_RESOLUTION) continue;
|
||||
|
||||
//first, try to find 2 point near enough
|
||||
for (size_t idx_point = 0; idx_point < myPolylines.paths[idx_poly].polyline.points.size(); idx_point++) {
|
||||
const Point &p = myPolylines.paths[idx_poly].polyline.points[idx_point];
|
||||
const Point &nearest_p = *child.polygon.closest_point(p);
|
||||
const coord_t dist = (coord_t)nearest_p.distance_to(p);
|
||||
if (dist + SCALED_EPSILON / 2 < intersect.distance) {
|
||||
//ok, copy the idx
|
||||
intersect.distance = dist;
|
||||
intersect.idx_children = idx_child;
|
||||
intersect.idx_polyline_outter = idx_poly;
|
||||
intersect.outter_best = p;
|
||||
intersect.child_best = nearest_p;
|
||||
if ((myPolylines.paths[idx_poly].role() == erExternalPerimeter || child.is_external() )
|
||||
&& this->object_config->seam_position.value != SeamPosition::spRandom) {
|
||||
//first, try to find 2 point near enough
|
||||
for (size_t idx_point = 0; idx_point < myPolylines.paths[idx_poly].polyline.points.size(); idx_point++) {
|
||||
const Point &p = myPolylines.paths[idx_poly].polyline.points[idx_point];
|
||||
const Point &nearest_p = *child.polygon.closest_point(p);
|
||||
const double dist = nearest_p.distance_to(p);
|
||||
//Try to find a point in the far side, aligning them
|
||||
if (dist + dist_cut / 20 < intersect.distance ||
|
||||
(config->perimeter_loop_seam.value == spRear && (intersect.idx_polyline_outter <0 || p.y > intersect.outter_best.y)
|
||||
&& dist <= max_dist && intersect.distance + dist_cut / 20)) {
|
||||
//ok, copy the idx
|
||||
intersect.distance = (coord_t)nearest_p.distance_to(p);
|
||||
intersect.idx_children = idx_child;
|
||||
intersect.idx_polyline_outter = idx_poly;
|
||||
intersect.outter_best = p;
|
||||
intersect.child_best = nearest_p;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//first, try to find 2 point near enough
|
||||
for (size_t idx_point = 0; idx_point < myPolylines.paths[idx_poly].polyline.points.size(); idx_point++) {
|
||||
const Point &p = myPolylines.paths[idx_poly].polyline.points[idx_point];
|
||||
const Point &nearest_p = *child.polygon.closest_point(p);
|
||||
const double dist = nearest_p.distance_to(p);
|
||||
if (dist + SCALED_EPSILON < intersect.distance ||
|
||||
(config->perimeter_loop_seam.value == spRear && (intersect.idx_polyline_outter<0 || p.y < intersect.outter_best.y)
|
||||
&& dist <= max_dist && intersect.distance + dist_cut / 20)) {
|
||||
//ok, copy the idx
|
||||
intersect.distance = (coord_t)nearest_p.distance_to(p);
|
||||
intersect.idx_children = idx_child;
|
||||
intersect.idx_polyline_outter = idx_poly;
|
||||
intersect.outter_best = p;
|
||||
intersect.child_best = nearest_p;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (intersect.distance <= max_dist) {
|
||||
return intersect;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (intersect.distance <= max_dist) {
|
||||
return intersect;
|
||||
}
|
||||
|
||||
for (size_t idx_child = 0; idx_child < children.size(); idx_child++) {
|
||||
const PerimeterGeneratorLoop &child = children[idx_child];
|
||||
for (size_t idx_poly = 0; idx_poly < myPolylines.paths.size(); idx_poly++) {
|
||||
if (myPolylines.paths[idx_poly].extruder_id == (unsigned int)-1) continue;
|
||||
if (myPolylines.paths[idx_poly].length() < dist_cut + SCALED_RESOLUTION) continue;
|
||||
|
||||
//second, try to check from one of my points
|
||||
//don't check the last point, as it's used to go outter, can't use it to go inner.
|
||||
@ -692,9 +723,18 @@ get_nearest_point(const PerimeterGeneratorLoops &children, ExtrusionLoop &myPoly
|
||||
intersect.child_best = nearest_p;
|
||||
}
|
||||
}
|
||||
if (intersect.distance <= max_dist) {
|
||||
return intersect;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (intersect.distance <= max_dist) {
|
||||
return intersect;
|
||||
}
|
||||
|
||||
for (size_t idx_child = 0; idx_child < children.size(); idx_child++) {
|
||||
const PerimeterGeneratorLoop &child = children[idx_child];
|
||||
for (size_t idx_poly = 0; idx_poly < myPolylines.paths.size(); idx_poly++) {
|
||||
if (myPolylines.paths[idx_poly].extruder_id == (unsigned int)-1) continue;
|
||||
if (myPolylines.paths[idx_poly].length() < dist_cut + SCALED_RESOLUTION) continue;
|
||||
|
||||
//lastly, try to check from one of his points
|
||||
for (size_t idx_point = 0; idx_point < child.polygon.points.size(); idx_point++) {
|
||||
const Point &p = child.polygon.points[idx_point];
|
||||
@ -898,17 +938,14 @@ PerimeterGenerator::_traverse_and_join_loops(const PerimeterGeneratorLoop &loop,
|
||||
//TODO change this->external_perimeter_flow.scaled_width() if it's the first one!
|
||||
const coord_t max_width_extrusion = this->perimeter_flow.scaled_width();
|
||||
ExtrusionLoop my_loop = _extrude_and_cut_loop(loop, entry_point);
|
||||
vector<bool> path_is_ccw;
|
||||
|
||||
for (size_t idx_poly = 0; idx_poly < my_loop.paths.size(); idx_poly++) {
|
||||
path_is_ccw.push_back(true);
|
||||
}
|
||||
|
||||
int child_idx = 0;
|
||||
//Polylines myPolylines = { myPolyline };
|
||||
//iterate on each point ot find the best place to go into the child
|
||||
vector<PerimeterGeneratorLoop> childs = children;
|
||||
while (!childs.empty()) {
|
||||
PerimeterIntersectionPoint nearest = get_nearest_point(childs, my_loop, this->perimeter_flow.scaled_width(), this->perimeter_flow.scaled_width()* 0.8);
|
||||
child_idx++;
|
||||
PerimeterIntersectionPoint nearest = this->_get_nearest_point(childs, my_loop, this->perimeter_flow.scaled_width(), this->perimeter_flow.scaled_width()* 1.42);
|
||||
if (nearest.idx_children == (size_t)-1) {
|
||||
//return ExtrusionEntityCollection();
|
||||
break;
|
||||
@ -920,9 +957,7 @@ PerimeterGenerator::_traverse_and_join_loops(const PerimeterGeneratorLoop &loop,
|
||||
//PerimeterGeneratorLoops less_childs = childs;
|
||||
//less_childs.erase(less_childs.begin() + nearest.idx_children);
|
||||
//create new node with recursive ask for the inner perimeter & COPY of the points, ready to be cut
|
||||
const bool cut_path_is_ccw = path_is_ccw[nearest.idx_polyline_outter];
|
||||
my_loop.paths.insert(my_loop.paths.begin() + nearest.idx_polyline_outter + 1, my_loop.paths[nearest.idx_polyline_outter]);
|
||||
path_is_ccw.insert(path_is_ccw.begin() + nearest.idx_polyline_outter + 1, cut_path_is_ccw);
|
||||
|
||||
ExtrusionPath *outer_start = &my_loop.paths[nearest.idx_polyline_outter];
|
||||
ExtrusionPath *outer_end = &my_loop.paths[nearest.idx_polyline_outter + 1];
|
||||
@ -981,7 +1016,6 @@ PerimeterGenerator::_traverse_and_join_loops(const PerimeterGeneratorLoop &loop,
|
||||
const size_t child_paths_size = child_loop.paths.size();
|
||||
if (child_paths_size == 0) continue;
|
||||
my_loop.paths.insert(my_loop.paths.begin() + nearest.idx_polyline_outter + 1, child_loop.paths.begin(), child_loop.paths.end());
|
||||
for (size_t i = 0; i < child_paths_size; i++) path_is_ccw.insert(path_is_ccw.begin() + nearest.idx_polyline_outter + 1, !cut_path_is_ccw);
|
||||
|
||||
//add paths into my_loop => need to re-get the refs
|
||||
outer_start = &my_loop.paths[nearest.idx_polyline_outter];
|
||||
@ -1005,8 +1039,8 @@ PerimeterGenerator::_traverse_and_join_loops(const PerimeterGeneratorLoop &loop,
|
||||
else
|
||||
inner_start->polyline.clip_start(inner_start->polyline.length()/2);
|
||||
} else {
|
||||
coord_t length_poly_1 = outer_start->polyline.length();
|
||||
coord_t length_poly_2 = outer_end->polyline.length();
|
||||
double length_poly_1 = outer_start->polyline.length();
|
||||
double length_poly_2 = outer_end->polyline.length();
|
||||
coord_t length_trim_1 = outer_start_spacing / 2;
|
||||
coord_t length_trim_2 = outer_end_spacing / 2;
|
||||
if (length_poly_1 < length_trim_1) {
|
||||
@ -1065,9 +1099,9 @@ PerimeterGenerator::_traverse_and_join_loops(const PerimeterGeneratorLoop &loop,
|
||||
my_loop.paths[idx].reverse();
|
||||
}
|
||||
outer_start = &my_loop.paths[nearest.idx_polyline_outter];
|
||||
outer_end = &my_loop.paths[nearest.idx_polyline_outter + child_paths_size + 1];
|
||||
inner_start = &my_loop.paths[nearest.idx_polyline_outter + 1];
|
||||
inner_end = &my_loop.paths[nearest.idx_polyline_outter + child_paths_size];
|
||||
outer_end = &my_loop.paths[nearest.idx_polyline_outter + child_paths_size + 1];
|
||||
}
|
||||
|
||||
}
|
||||
@ -1152,7 +1186,8 @@ PerimeterGenerator::_traverse_and_join_loops(const PerimeterGeneratorLoop &loop,
|
||||
travel_path_end[0].polyline.append(outer_end->polyline.points.front());
|
||||
}
|
||||
//check if we add path or reuse bits
|
||||
if (outer_start->polyline.points.size() == 1) {
|
||||
//FIXME
|
||||
/*if (outer_start->polyline.points.size() == 1) {
|
||||
outer_start->polyline = travel_path_begin.front().polyline;
|
||||
travel_path_begin.erase(travel_path_begin.begin());
|
||||
outer_start->extruder_id = -1;
|
||||
@ -1160,15 +1195,13 @@ PerimeterGenerator::_traverse_and_join_loops(const PerimeterGeneratorLoop &loop,
|
||||
outer_end->polyline = travel_path_end.back().polyline;
|
||||
travel_path_end.erase(travel_path_end.end() - 1);
|
||||
outer_end->extruder_id = -1;
|
||||
}
|
||||
}*/
|
||||
//add paths into my_loop => after that all ref are wrong!
|
||||
for (int i = travel_path_end.size() - 1; i >= 0; i--) {
|
||||
my_loop.paths.insert(my_loop.paths.begin() + nearest.idx_polyline_outter + child_paths_size + 1, travel_path_end[i]);
|
||||
path_is_ccw.insert(path_is_ccw.begin() + nearest.idx_polyline_outter + child_paths_size + 1, cut_path_is_ccw);
|
||||
}
|
||||
for (int i = travel_path_begin.size() - 1; i >= 0; i--) {
|
||||
my_loop.paths.insert(my_loop.paths.begin() + nearest.idx_polyline_outter + 1, travel_path_begin[i]);
|
||||
path_is_ccw.insert(path_is_ccw.begin() + nearest.idx_polyline_outter + 1, cut_path_is_ccw);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,6 +103,7 @@ private:
|
||||
ThickPolylines &thin_walls) const;
|
||||
ExtrusionLoop _traverse_and_join_loops(const PerimeterGeneratorLoop &loop, const PerimeterGeneratorLoops &childs, const Point entryPoint) const;
|
||||
ExtrusionLoop _extrude_and_cut_loop(const PerimeterGeneratorLoop &loop, const Point entryPoint, const Line &direction = Line(Point(0,0),Point(0,0))) const;
|
||||
PerimeterIntersectionPoint _get_nearest_point(const PerimeterGeneratorLoops &children, ExtrusionLoop &myPolylines, const coord_t dist_cut, const coord_t max_dist) const;
|
||||
ExtrusionEntityCollection _variable_width
|
||||
(const ThickPolylines &polylines, ExtrusionRole role, Flow flow) const;
|
||||
};
|
||||
|
@ -400,13 +400,25 @@ PrintConfigDef::PrintConfigDef()
|
||||
def->default_value = new ConfigOptionBool(false);
|
||||
|
||||
def = this->add("perimeter_loop", coBool);
|
||||
def->label = L("Looping perimeters");
|
||||
def->label = L(" ");
|
||||
def->category = L("Layers and Perimeters");
|
||||
def->tooltip = L("Join the perimeters to create only one continuous extrusion without any z-hop."
|
||||
" Long inside travel (from external to holes) are not extruded to give some place to the infill.");
|
||||
def->cli = "loop-perimeter!";
|
||||
def->default_value = new ConfigOptionBool(false);
|
||||
|
||||
|
||||
def = this->add("perimeter_loop_seam", coEnum);
|
||||
def->label = L("Seam position");
|
||||
def->category = L("Layers and Perimeters");
|
||||
def->tooltip = L("Position of perimeters starting points.");
|
||||
def->cli = "perimeter-seam-position=s";
|
||||
def->enum_keys_map = &ConfigOptionEnum<SeamPosition>::get_enum_values();
|
||||
def->enum_values.push_back("nearest");
|
||||
def->enum_values.push_back("rear");
|
||||
def->enum_labels.push_back(L("Nearest"));
|
||||
def->enum_labels.push_back(L("Rear"));
|
||||
def->default_value = new ConfigOptionEnum<SeamPosition>(spRear);
|
||||
|
||||
def = this->add("extra_perimeters", coBool);
|
||||
def->label = L("Extra perimeters if needed");
|
||||
def->category = L("Layers and Perimeters");
|
||||
@ -1600,12 +1612,21 @@ PrintConfigDef::PrintConfigDef()
|
||||
def->enum_values.push_back("nearest");
|
||||
def->enum_values.push_back("aligned");
|
||||
def->enum_values.push_back("rear");
|
||||
def->enum_values.push_back("hidden");
|
||||
def->enum_labels.push_back(L("Random"));
|
||||
def->enum_labels.push_back(L("Nearest"));
|
||||
def->enum_labels.push_back(L("Aligned"));
|
||||
def->enum_labels.push_back(L("Rear"));
|
||||
def->enum_labels.push_back(L("Rear"));
|
||||
def->enum_labels.push_back(L("Hidden"));
|
||||
def->default_value = new ConfigOptionEnum<SeamPosition>(spAligned);
|
||||
|
||||
def = this->add("seam_travel", coBool);
|
||||
def->label = L("Travel move reduced");
|
||||
def->category = L("Layers and Perimeters");
|
||||
def->tooltip = L("Add a big cost to travel paths when possible (when going into a loop), so it will prefer a less optimal seam posistion if it's nearer.");
|
||||
def->cli = "seam-travel!";
|
||||
def->default_value = new ConfigOptionBool(false);
|
||||
|
||||
#if 0
|
||||
def = this->add("seam_preferred_direction", coFloat);
|
||||
// def->gui_type = "slider";
|
||||
|
@ -42,7 +42,7 @@ enum SupportMaterialPattern {
|
||||
};
|
||||
|
||||
enum SeamPosition {
|
||||
spRandom, spNearest, spAligned, spRear
|
||||
spRandom, spNearest, spAligned, spRear, spHidden
|
||||
};
|
||||
|
||||
enum FilamentType {
|
||||
@ -120,6 +120,7 @@ template<> inline t_config_enum_values& ConfigOptionEnum<SeamPosition>::get_enum
|
||||
keys_map["nearest"] = spNearest;
|
||||
keys_map["aligned"] = spAligned;
|
||||
keys_map["rear"] = spRear;
|
||||
keys_map["hidden"] = spHidden;
|
||||
}
|
||||
return keys_map;
|
||||
}
|
||||
@ -350,6 +351,7 @@ public:
|
||||
ConfigOptionFloat layer_height;
|
||||
ConfigOptionInt raft_layers;
|
||||
ConfigOptionEnum<SeamPosition> seam_position;
|
||||
ConfigOptionBool seam_travel;
|
||||
// ConfigOptionFloat seam_preferred_direction;
|
||||
// ConfigOptionFloat seam_preferred_direction_jitter;
|
||||
ConfigOptionBool support_material;
|
||||
@ -395,6 +397,7 @@ protected:
|
||||
OPT_PTR(layer_height);
|
||||
OPT_PTR(raft_layers);
|
||||
OPT_PTR(seam_position);
|
||||
OPT_PTR(seam_travel);
|
||||
// OPT_PTR(seam_preferred_direction);
|
||||
// OPT_PTR(seam_preferred_direction_jitter);
|
||||
OPT_PTR(support_material);
|
||||
@ -444,6 +447,7 @@ public:
|
||||
ConfigOptionFloatOrPercent external_perimeter_speed;
|
||||
ConfigOptionBool external_perimeters_first;
|
||||
ConfigOptionBool perimeter_loop;
|
||||
ConfigOptionEnum<SeamPosition> perimeter_loop_seam;
|
||||
ConfigOptionBool extra_perimeters;
|
||||
ConfigOptionBool only_one_perimeter_top;
|
||||
ConfigOptionFloat fill_angle;
|
||||
@ -499,6 +503,7 @@ protected:
|
||||
OPT_PTR(external_perimeter_speed);
|
||||
OPT_PTR(external_perimeters_first);
|
||||
OPT_PTR(perimeter_loop);
|
||||
OPT_PTR(perimeter_loop_seam);
|
||||
OPT_PTR(extra_perimeters);
|
||||
OPT_PTR(only_one_perimeter_top);
|
||||
OPT_PTR(fill_angle);
|
||||
|
@ -157,6 +157,7 @@ bool PrintObject::invalidate_state_by_config_options(const std::vector<t_config_
|
||||
|| opt_key == "thin_walls"
|
||||
|| opt_key == "external_perimeters_first"
|
||||
|| opt_key == "perimeter_loop"
|
||||
|| opt_key == "perimeter_loop_seam"
|
||||
|| opt_key == "no_perimeter_unsupported"
|
||||
|| opt_key == "min_perimeter_unsupported"
|
||||
|| opt_key == "noperi_bridge_only") {
|
||||
@ -241,6 +242,7 @@ bool PrintObject::invalidate_state_by_config_options(const std::vector<t_config_
|
||||
steps.emplace_back(posInfill);
|
||||
} else if (
|
||||
opt_key == "seam_position"
|
||||
|| opt_key == "seam_travel"
|
||||
|| opt_key == "seam_preferred_direction"
|
||||
|| opt_key == "seam_preferred_direction_jitter"
|
||||
|| opt_key == "support_material_speed"
|
||||
|
@ -527,7 +527,28 @@ void Choice::set_value(const boost::any& value, bool change_event)
|
||||
}
|
||||
else
|
||||
val = 0;
|
||||
}
|
||||
} else if (m_opt_id.compare("perimeter_loop_seam") == 0) {
|
||||
if (!m_opt.enum_values.empty()) {
|
||||
std::string key;
|
||||
t_config_enum_values map_names = ConfigOptionEnum<SeamPosition>::get_enum_values();
|
||||
for (auto it : map_names) {
|
||||
if (val == it.second) {
|
||||
key = it.first;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
size_t idx = 0;
|
||||
for (auto el : m_opt.enum_values) {
|
||||
if (el.compare(key) == 0)
|
||||
break;
|
||||
++idx;
|
||||
}
|
||||
|
||||
val = idx == m_opt.enum_values.size() ? 0 : idx;
|
||||
} else
|
||||
val = 3;
|
||||
}
|
||||
dynamic_cast<wxComboBox*>(window)->SetSelection(val);
|
||||
break;
|
||||
}
|
||||
@ -588,10 +609,18 @@ boost::any& Choice::get_value()
|
||||
else if (m_opt_id.compare("gcode_flavor") == 0)
|
||||
m_value = static_cast<GCodeFlavor>(ret_enum);
|
||||
else if (m_opt_id.compare("support_material_pattern") == 0)
|
||||
m_value = static_cast<SupportMaterialPattern>(ret_enum);
|
||||
else if (m_opt_id.compare("seam_position") == 0)
|
||||
m_value = static_cast<SupportMaterialPattern>(ret_enum);
|
||||
else if (m_opt_id.compare("seam_position") == 0)
|
||||
m_value = static_cast<SeamPosition>(ret_enum);
|
||||
else if (m_opt_id.compare("host_type") == 0)
|
||||
else if (m_opt_id.compare("perimeter_loop_seam") == 0) {
|
||||
if (!m_opt.enum_values.empty()) {
|
||||
std::string key = m_opt.enum_values[ret_enum];
|
||||
t_config_enum_values map_names = ConfigOptionEnum<SeamPosition>::get_enum_values();
|
||||
int value = map_names.at(key);
|
||||
m_value = static_cast<SeamPosition>(value);
|
||||
} else
|
||||
m_value = static_cast<SeamPosition>(3);
|
||||
} else if (m_opt_id.compare("host_type") == 0)
|
||||
m_value = static_cast<PrintHostType>(ret_enum);
|
||||
else if (m_opt_id.compare("infill_dense_algo") == 0)
|
||||
m_value = static_cast<DenseInfillAlgo>(ret_enum);
|
||||
|
@ -602,9 +602,9 @@ void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt
|
||||
else if (opt_key.compare("gcode_flavor") == 0)
|
||||
config.set_key_value(opt_key, new ConfigOptionEnum<GCodeFlavor>(boost::any_cast<GCodeFlavor>(value)));
|
||||
else if (opt_key.compare("support_material_pattern") == 0)
|
||||
config.set_key_value(opt_key, new ConfigOptionEnum<SupportMaterialPattern>(boost::any_cast<SupportMaterialPattern>(value)));
|
||||
else if (opt_key.compare("seam_position") == 0)
|
||||
config.set_key_value(opt_key, new ConfigOptionEnum<SeamPosition>(boost::any_cast<SeamPosition>(value)));
|
||||
config.set_key_value(opt_key, new ConfigOptionEnum<SupportMaterialPattern>(boost::any_cast<SupportMaterialPattern>(value)));
|
||||
else if (opt_key.compare("seam_position") == 0 || opt_key.compare("perimeter_loop_seam") == 0)
|
||||
config.set_key_value(opt_key, new ConfigOptionEnum<SeamPosition>(boost::any_cast<SeamPosition>(value)));
|
||||
else if (opt_key.compare("host_type") == 0)
|
||||
config.set_key_value(opt_key, new ConfigOptionEnum<PrintHostType>(boost::any_cast<PrintHostType>(value)));
|
||||
else if (opt_key.compare("infill_dense_algo") == 0)
|
||||
|
@ -458,10 +458,10 @@ boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config
|
||||
}
|
||||
else if (opt_key.compare("support_material_pattern") == 0){
|
||||
ret = static_cast<int>(config.option<ConfigOptionEnum<SupportMaterialPattern>>(opt_key)->value);
|
||||
}
|
||||
else if (opt_key.compare("seam_position") == 0){
|
||||
ret = static_cast<int>(config.option<ConfigOptionEnum<SeamPosition>>(opt_key)->value);
|
||||
}
|
||||
}
|
||||
else if (opt_key.compare("seam_position") == 0 || opt_key.compare("perimeter_loop_seam") == 0) {
|
||||
ret = static_cast<int>(config.option<ConfigOptionEnum<SeamPosition>>(opt_key)->value);
|
||||
}
|
||||
else if (opt_key.compare("host_type") == 0){
|
||||
ret = static_cast<int>(config.option<ConfigOptionEnum<PrintHostType>>(opt_key)->value);
|
||||
}
|
||||
|
@ -307,7 +307,7 @@ const std::vector<std::string>& Preset::print_options()
|
||||
"wipe_tower", "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_rotation_angle", "wipe_tower_bridging",
|
||||
"only_one_perimeter_top", "single_extruder_multi_material_priming", "compatible_printers", "compatible_printers_condition", "inherits",
|
||||
"infill_dense", "infill_dense_algo", "no_perimeter_unsupported", "min_perimeter_unsupported", "noperi_bridge_only",
|
||||
"support_material_solid_first_layer", "perimeter_loop"
|
||||
"support_material_solid_first_layer", "perimeter_loop", "perimeter_loop_seam", "seam_travel"
|
||||
};
|
||||
return s_opts;
|
||||
}
|
||||
|
@ -818,10 +818,16 @@ void TabPrint::build()
|
||||
line.append_option(optgroup->get_option("noperi_bridge_only"));
|
||||
optgroup->append_line(line);
|
||||
|
||||
optgroup = page->new_optgroup(_(L("Advanced")));
|
||||
optgroup->append_single_option_line("seam_position");
|
||||
optgroup = page->new_optgroup(_(L("Advanced")));
|
||||
line = { _(L("Avoid unsupported perimeters")), "" };
|
||||
line.append_option(optgroup->get_option("seam_position"));
|
||||
line.append_option(optgroup->get_option("seam_travel"));
|
||||
optgroup->append_line(line);
|
||||
optgroup->append_single_option_line("external_perimeters_first");
|
||||
optgroup->append_single_option_line("perimeter_loop");
|
||||
line = { _(L("Looping perimeter")), "" };
|
||||
line.append_option(optgroup->get_option("perimeter_loop"));
|
||||
line.append_option(optgroup->get_option("perimeter_loop_seam"));
|
||||
optgroup->append_line(line);
|
||||
|
||||
page = add_options_page(_(L("Infill")), "infill.png");
|
||||
optgroup = page->new_optgroup(_(L("Infill")));
|
||||
@ -1167,11 +1173,13 @@ void TabPrint::update()
|
||||
}
|
||||
}
|
||||
|
||||
bool have_perimeters = m_config->opt_int("perimeters") > 0;
|
||||
for (auto el : {"extra_perimeters", "only_one_perimeter_top", "ensure_vertical_shell_thickness", "thin_walls", "overhangs",
|
||||
"seam_position", "external_perimeters_first", "external_perimeter_extrusion_width",
|
||||
"perimeter_speed", "small_perimeter_speed", "external_perimeter_speed", "perimeter_loop" })
|
||||
get_field(el)->toggle(have_perimeters);
|
||||
bool have_perimeters = m_config->opt_int("perimeters") > 0;
|
||||
for (auto el : { "extra_perimeters", "only_one_perimeter_top", "ensure_vertical_shell_thickness", "thin_walls", "overhangs",
|
||||
"seam_position", "external_perimeters_first", "external_perimeter_extrusion_width",
|
||||
"perimeter_speed", "small_perimeter_speed", "external_perimeter_speed", "perimeter_loop", "perimeter_loop_seam" })
|
||||
get_field(el)->toggle(have_perimeters);
|
||||
|
||||
get_field("perimeter_loop_seam")->toggle(m_config->opt_bool("perimeter_loop"));
|
||||
|
||||
bool have_no_perimeter_unsupported = have_perimeters && m_config->opt_bool("no_perimeter_unsupported");
|
||||
for (auto el : { "min_perimeter_unsupported", "noperi_bridge_only" })
|
||||
|
Loading…
x
Reference in New Issue
Block a user