mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-14 09:05:54 +08:00
fix seams
* fix the seam object * fix painting seam that will jump on nearest for no good reason * change hidden/near/nearer to cost with 2 boxes for setting the costs. fix preferences
This commit is contained in:
parent
3aaedd671b
commit
07be95fb69
@ -49,14 +49,15 @@ group:Overhangs
|
||||
setting:width$5:overhangs_reverse_threshold
|
||||
end_line
|
||||
group:Advanced
|
||||
setting:no_perimeter_unsupported_algo
|
||||
setting:width$25:no_perimeter_unsupported_algo
|
||||
line:Gap Fill
|
||||
setting:gap_fill
|
||||
setting:width$5:gap_fill_min_area
|
||||
end_line
|
||||
line:Seam
|
||||
setting:seam_position
|
||||
setting:seam_travel
|
||||
setting:sidetext_width$2:seam_position
|
||||
setting:label_width$10:width$3:sidetext_width$2:seam_angle_cost
|
||||
setting:label_width$10:width$3:sidetext_width$2:seam_travel_cost
|
||||
end_line
|
||||
line:Looping perimeter
|
||||
setting:perimeter_loop
|
||||
|
@ -60,9 +60,9 @@ void AppConfig::set_defaults()
|
||||
set("freecad_path", ".");
|
||||
|
||||
if (get("version_check").empty())
|
||||
set("version_check", "1");
|
||||
set("version_check", "0");
|
||||
if (get("preset_update").empty())
|
||||
set("preset_update", "1");
|
||||
set("preset_update", "0");
|
||||
|
||||
if (get("export_sources_full_pathnames").empty())
|
||||
set("export_sources_full_pathnames", "0");
|
||||
|
@ -3227,7 +3227,7 @@ void GCode::split_at_seam_pos(ExtrusionLoop& loop, std::unique_ptr<EdgeGrid::Gri
|
||||
? lower_layer_edge_grid->get()
|
||||
: nullptr;
|
||||
//TODO modify m_seam_placer to takers into account extra options.
|
||||
Point seam = m_seam_placer.get_seam(m_layer->id(), seam_position, loop,
|
||||
Point seam = m_seam_placer.get_seam(m_layer, seam_position, loop,
|
||||
last_pos, EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter, 0),
|
||||
(m_layer == NULL ? nullptr : m_layer->object()),
|
||||
was_clockwise, edge_grid_ptr);
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include "libslic3r/ExtrusionEntity.hpp"
|
||||
#include "libslic3r/Print.hpp"
|
||||
#include "libslic3r/Layer.hpp"
|
||||
#include "libslic3r/BoundingBox.hpp"
|
||||
#include "libslic3r/EdgeGrid.hpp"
|
||||
#include "libslic3r/ClipperUtils.hpp"
|
||||
@ -50,6 +51,7 @@ plot(p2.subs(r,0.2).subs(z,1.), (x, -1, 3), adaptive=False, nb_of_points=400)
|
||||
|
||||
// Return a value in <0, 1> of a cubic B-spline kernel centered around zero.
|
||||
// The B-spline is re-scaled so it has value 1 at zero.
|
||||
// 0 -> 1 ; ~0.465 -> 0.75 ; ~0.72 -> 0.5 ; 1 -> 0.25 ; ~1.23 -> 0.125 ; 2+ -> 0
|
||||
static inline float bspline_kernel(float x)
|
||||
{
|
||||
x = std::abs(x);
|
||||
@ -208,13 +210,16 @@ void SeamPlacer::init(const Print& print)
|
||||
|
||||
|
||||
|
||||
Point SeamPlacer::get_seam(const size_t layer_idx, const SeamPosition seam_position,
|
||||
Point SeamPlacer::get_seam(const Layer *layer, SeamPosition seam_position,
|
||||
const ExtrusionLoop& loop, Point last_pos, coordf_t nozzle_dmr,
|
||||
const PrintObject* po, bool was_clockwise, const EdgeGrid::Grid* lower_layer_edge_grid)
|
||||
{
|
||||
const size_t layer_idx = layer->id();
|
||||
Polygon polygon = loop.polygon();
|
||||
BoundingBox polygon_bb = polygon.bounding_box();
|
||||
const coord_t nozzle_r = coord_t(scale_(0.5 * nozzle_dmr) + 0.5);
|
||||
float last_pos_weight = 1.f;
|
||||
float angle_weight = 1.f;
|
||||
|
||||
if (this->is_custom_seam_on_layer(layer_idx)) {
|
||||
// Seam enf/blockers can begin and end in between the original vertices.
|
||||
@ -222,9 +227,53 @@ Point SeamPlacer::get_seam(const size_t layer_idx, const SeamPosition seam_posit
|
||||
polygon.densify(MINIMAL_POLYGON_SIDE);
|
||||
}
|
||||
|
||||
bool has_seam_custom = false;
|
||||
for (ModelVolume* v : po->model_object()->volumes)
|
||||
if (v->is_seam_position()) {
|
||||
has_seam_custom = true;
|
||||
break;
|
||||
}
|
||||
if (has_seam_custom) {
|
||||
// Look for all lambda-seam-modifiers below current z, choose the highest one
|
||||
ModelVolume* v_lambda_seam = nullptr;
|
||||
Vec3d lambda_pos;
|
||||
double lambda_dist;
|
||||
double lambda_radius;
|
||||
for (ModelVolume* v : po->model_object()->volumes)
|
||||
if (v->is_seam_position()) {
|
||||
//xy in object coordinates, z in plater coordinates
|
||||
Vec3d test_lambda_pos = po->model_object()->instances.front()->transform_vector(v->get_offset(), true);
|
||||
Vec3d test_lambda_pos_plater = po->model_object()->instances.front()->transform_vector(v->get_offset(), false);
|
||||
Point xy_lambda(scale_(test_lambda_pos.x()), scale_(test_lambda_pos.y()));
|
||||
Point nearest = polygon.point_projection(xy_lambda);
|
||||
Vec3d polygon_3dpoint{ unscaled(nearest.x()), unscaled(nearest.y()), (double)layer->print_z };
|
||||
double test_lambda_dist = (polygon_3dpoint - test_lambda_pos).norm();
|
||||
double sphere_radius = po->model_object()->instances.front()->transform_bounding_box(v->mesh().bounding_box(), true).size().x() / 2;
|
||||
//if (test_lambda_dist > sphere_radius)
|
||||
// continue;
|
||||
|
||||
//use this one if the first or nearer (in z)
|
||||
if (v_lambda_seam == nullptr || lambda_dist > test_lambda_dist) {
|
||||
v_lambda_seam = v;
|
||||
lambda_pos = test_lambda_pos;
|
||||
lambda_radius = sphere_radius;
|
||||
lambda_dist = test_lambda_dist;
|
||||
}
|
||||
}
|
||||
|
||||
if (v_lambda_seam != nullptr) {
|
||||
lambda_pos = po->model_object()->instances.front()->transform_vector(v_lambda_seam->get_offset(), true);
|
||||
// Found, get the center point and apply rotation and scaling of Model instance. Continues to spAligned if not found or Weight set to Zero.
|
||||
last_pos = Point::new_scale(lambda_pos.x(), lambda_pos.y());
|
||||
// Weight is set by user and stored in the radius of the sphere
|
||||
last_pos_weight = std::max(0.0, std::round(100 * (lambda_radius)));
|
||||
if (last_pos_weight > 0.0)
|
||||
seam_position = spCustom;
|
||||
}
|
||||
}
|
||||
|
||||
if (seam_position != spRandom) {
|
||||
// Retrieve the last start position for this object.
|
||||
float last_pos_weight = 1.f;
|
||||
|
||||
if (seam_position == spAligned) {
|
||||
// Seam is aligned to the seam at the preceding layer.
|
||||
@ -233,32 +282,51 @@ Point SeamPlacer::get_seam(const size_t layer_idx, const SeamPosition seam_posit
|
||||
if (pos.has_value()) {
|
||||
//last_pos = m_last_seam_position[po];
|
||||
last_pos = *pos;
|
||||
}
|
||||
last_pos_weight = is_custom_enforcer_on_layer(layer_idx) ? 0.f : 1.f;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (seam_position == spRear) {
|
||||
}else if (seam_position == spRear) {
|
||||
// Object is centered around (0,0) in its current coordinate system.
|
||||
last_pos.x() = 0;
|
||||
last_pos.y() += coord_t(3. * po->bounding_box().radius());
|
||||
last_pos_weight = 5.f;
|
||||
} if (seam_position == spNearest) {
|
||||
}else if (seam_position == spNearest) {
|
||||
// last_pos already contains current nozzle position
|
||||
// set base last_pos_weight to the same value as penaltyFlatSurface
|
||||
last_pos_weight = 5.f;
|
||||
if (po != nullptr) {
|
||||
last_pos_weight = po->config().seam_travel_cost.get_abs_value(last_pos_weight);
|
||||
angle_weight = po->config().seam_angle_cost.get_abs_value(angle_weight);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Insert a projection of last_pos into the polygon.
|
||||
size_t last_pos_proj_idx;
|
||||
{
|
||||
auto it = project_point_to_polygon_and_insert(polygon, last_pos, 0.1 * nozzle_r);
|
||||
Points::const_iterator it = project_point_to_polygon_and_insert(polygon, last_pos, 0.1 * nozzle_r );
|
||||
last_pos_proj_idx = it - polygon.points.begin();
|
||||
}
|
||||
Point last_pos_proj = polygon.points[last_pos_proj_idx];
|
||||
|
||||
// Parametrize the polygon by its length.
|
||||
std::vector<float> lengths = polygon.parameter_by_length();
|
||||
|
||||
//find the max dist the seam can be
|
||||
float dist_max = 0.1f * lengths.back();// 5.f * nozzle_dmr
|
||||
if (po != nullptr && po->config().seam_travel_cost.get_abs_value(1) >= 1) {
|
||||
last_pos_weight *= 2;
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
// For each polygon point, store a penalty.
|
||||
// First calculate the angles, store them as penalties. The angles are caluculated over a minimum arm length of nozzle_r.
|
||||
std::vector<float> penalties = polygon_angles_at_vertices(polygon, lengths, float(nozzle_r));
|
||||
std::vector<float> penalties = polygon_angles_at_vertices(polygon, lengths,
|
||||
this->is_custom_seam_on_layer(layer_idx) ? std::min(MINIMAL_POLYGON_SIDE / 2.f, float(nozzle_r)) : float(nozzle_r));
|
||||
// No penalty for reflex points, slight penalty for convex points, high penalty for flat surfaces.
|
||||
const float penaltyConvexVertex = 1.f;
|
||||
const float penaltyFlatSurface = 5.f;
|
||||
@ -269,26 +337,33 @@ Point SeamPlacer::get_seam(const size_t layer_idx, const SeamPosition seam_posit
|
||||
if (was_clockwise)
|
||||
ccwAngle = - ccwAngle;
|
||||
float penalty = 0;
|
||||
if (ccwAngle <- float(0.6 * PI))
|
||||
// Sharp reflex vertex. We love that, it hides the seam perfectly.
|
||||
penalty = 0.f;
|
||||
else if (ccwAngle > float(0.6 * PI))
|
||||
// Seams on sharp convex vertices are more visible than on reflex vertices.
|
||||
penalty = penaltyConvexVertex;
|
||||
else if (ccwAngle < 0.f) {
|
||||
//if (ccwAngle < -float(0.6 * PI))
|
||||
// penalty = 0.f;
|
||||
//else if (ccwAngle > float(0.6 * PI))
|
||||
//
|
||||
// penalty = penaltyConvexVertex;
|
||||
//else
|
||||
if (ccwAngle < 0.f) {
|
||||
// We love Sharp reflex vertex (high negative ccwAngle). It hides the seam perfectly.
|
||||
// Interpolate penalty between maximum and zero.
|
||||
penalty = penaltyFlatSurface * bspline_kernel(ccwAngle * float(PI * 2. / 3.));
|
||||
penalty = penaltyFlatSurface * bspline_kernel(ccwAngle);
|
||||
} else if (ccwAngle > float(0.67 * PI)) {
|
||||
//penalize too sharp convex angle, it's best to be nearer to ~100°
|
||||
penalty = penaltyConvexVertex + (penaltyFlatSurface - penaltyConvexVertex) * bspline_kernel( (PI - ccwAngle) * 1.5);
|
||||
} else {
|
||||
assert(ccwAngle >= 0.f);
|
||||
// Interpolate penalty between maximum and the penalty for a convex vertex.
|
||||
penalty = penaltyConvexVertex + (penaltyFlatSurface - penaltyConvexVertex) * bspline_kernel(ccwAngle * float(PI * 2. / 3.));
|
||||
penalty = penaltyConvexVertex + (penaltyFlatSurface - penaltyConvexVertex) * bspline_kernel(ccwAngle);
|
||||
}
|
||||
penalty *= angle_weight;
|
||||
if (po != nullptr && po->config().seam_travel_cost.get_abs_value(1) >= 1) {
|
||||
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]);
|
||||
float dist_max = 0.1f * lengths.back(); // 5.f * nozzle_dmr
|
||||
penalty -= last_pos_weight * bspline_kernel(dist_to_last_pos_proj / dist_max);
|
||||
}
|
||||
penalties[i] = std::max(0.f, penalty);
|
||||
}
|
||||
|
||||
@ -313,28 +388,29 @@ Point SeamPlacer::get_seam(const size_t layer_idx, const SeamPosition seam_posit
|
||||
|
||||
// Custom seam. Huge (negative) constant penalty is applied inside
|
||||
// blockers (enforcers) to rule out points that should not win.
|
||||
this->apply_custom_seam(polygon, penalties, lengths, layer_idx, seam_position);
|
||||
std::vector<float> penalties_with_custom_seam = penalties;
|
||||
this->apply_custom_seam(polygon, penalties_with_custom_seam, lengths, layer_idx, seam_position);
|
||||
|
||||
// Find a point with a minimum penalty.
|
||||
size_t idx_min = std::min_element(penalties.begin(), penalties.end()) - penalties.begin();
|
||||
size_t idx_min = std::min_element(penalties_with_custom_seam.begin(), penalties_with_custom_seam.end()) - penalties_with_custom_seam.begin();
|
||||
|
||||
if (seam_position != spAligned || ! is_custom_enforcer_on_layer(layer_idx)) {
|
||||
// Very likely the weight of idx_min is very close to the weight of last_pos_proj_idx.
|
||||
// In that case use last_pos_proj_idx instead.
|
||||
float penalty_aligned = penalties[last_pos_proj_idx];
|
||||
float penalty_min = penalties[idx_min];
|
||||
float penalty_diff_abs = std::abs(penalty_min - penalty_aligned);
|
||||
float penalty_max = std::max(penalty_min, penalty_aligned);
|
||||
float penalty_diff_abs = std::abs(penalties_with_custom_seam[idx_min] - penalties_with_custom_seam[last_pos_proj_idx]);
|
||||
float penalty_max = std::max(penalties[idx_min], penalties[last_pos_proj_idx]);
|
||||
float penalty_diff_rel = (penalty_max == 0.f) ? 0.f : penalty_diff_abs / penalty_max;
|
||||
// printf("Align seams, penalty aligned: %f, min: %f, diff abs: %f, diff rel: %f\n", penalty_aligned, penalty_min, penalty_diff_abs, penalty_diff_rel);
|
||||
if (std::abs(penalty_diff_rel) < 0.05) {
|
||||
if (std::abs(penalty_diff_rel) < 0.05 && penalty_diff_abs < 3) {
|
||||
// Penalty of the aligned point is very close to the minimum penalty.
|
||||
// Align the seams as accurately as possible.
|
||||
idx_min = last_pos_proj_idx;
|
||||
}
|
||||
}
|
||||
|
||||
if (seam_position == spAligned && loop.role() == erExternalPerimeter)
|
||||
if (loop.role() == erExternalPerimeter)
|
||||
m_seam_history.add_seam(po, polygon.points[idx_min], polygon_bb);
|
||||
|
||||
|
||||
|
@ -12,6 +12,7 @@ namespace Slic3r {
|
||||
class PrintObject;
|
||||
class ExtrusionLoop;
|
||||
class Print;
|
||||
class Layer;
|
||||
namespace EdgeGrid { class Grid; }
|
||||
|
||||
|
||||
@ -39,7 +40,7 @@ class SeamPlacer {
|
||||
public:
|
||||
void init(const Print& print);
|
||||
|
||||
Point get_seam(const size_t layer_idx, const SeamPosition seam_position,
|
||||
Point get_seam(const Layer *layer, const SeamPosition seam_position,
|
||||
const ExtrusionLoop& loop, Point last_pos,
|
||||
coordf_t nozzle_diameter, const PrintObject* po,
|
||||
bool was_clockwise, const EdgeGrid::Grid* lower_layer_edge_grid);
|
||||
|
@ -536,7 +536,8 @@ const std::vector<std::string>& Preset::print_options()
|
||||
"exact_last_layer_height",
|
||||
"perimeter_loop",
|
||||
"perimeter_loop_seam",
|
||||
"seam_travel",
|
||||
"seam_angle_cost",
|
||||
"seam_travel_cost",
|
||||
"infill_connection",
|
||||
"first_layer_infill_speed",
|
||||
"thin_walls_min_width",
|
||||
|
@ -932,7 +932,7 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
||||
}
|
||||
// Copy content of the ModelObject including its ID, do not change the parent.
|
||||
model_object.assign_copy(model_object_new);
|
||||
} else if (supports_differ || model_custom_supports_data_changed(model_object, model_object_new)) {
|
||||
} else if (supports_differ || seam_position_differ || model_custom_supports_data_changed(model_object, model_object_new)) {
|
||||
// First stop background processing before shuffling or deleting the ModelVolumes in the ModelObject's list.
|
||||
if (supports_differ) {
|
||||
this->call_cancel_callback();
|
||||
|
@ -2796,31 +2796,38 @@ void PrintConfigDef::init_fff_params()
|
||||
def->label = L("Seam position");
|
||||
def->category = OptionCategory::perimeter;
|
||||
def->tooltip = L("Position of perimeters starting points."
|
||||
"\n --- When using Custom seam ---"
|
||||
"\nYou have to create one or more seam sphere in the context menu of the object."
|
||||
" When an object has a seam object, this setting is not taken into account nymore for the object."
|
||||
" Refer to the wiki/help menu for more information.");
|
||||
"\n ");
|
||||
def->enum_keys_map = &ConfigOptionEnum<SeamPosition>::get_enum_values();
|
||||
def->enum_values.push_back("random");
|
||||
def->enum_values.push_back("near");
|
||||
def->enum_values.push_back("random");
|
||||
def->enum_values.push_back("aligned");
|
||||
def->enum_values.push_back("rear");
|
||||
def->enum_values.push_back("hidden");
|
||||
def->enum_labels.push_back(L("Cost-based"));
|
||||
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("Corners"));
|
||||
def->mode = comSimple;
|
||||
def->set_default_value(new ConfigOptionEnum<SeamPosition>(spHidden));
|
||||
def->set_default_value(new ConfigOptionEnum<SeamPosition>(spNearest));
|
||||
|
||||
def = this->add("seam_travel", coBool);
|
||||
def->label = L("Travel move reduced");
|
||||
def = this->add("seam_angle_cost", coPercent);
|
||||
def->label = L("Angle cost");
|
||||
def->full_label = L("Seam angle cost");
|
||||
def->category = OptionCategory::perimeter;
|
||||
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->tooltip = L("Cost of placing the seam at a bad angle. The worst angle (max penalty) is when it's flat.");
|
||||
def->sidetext = L("%");
|
||||
def->min = 0;
|
||||
def->mode = comExpert;
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
def->set_default_value(new ConfigOptionPercent(100));
|
||||
|
||||
def = this->add("seam_travel_cost", coPercent);
|
||||
def->label = L("Travel cost");
|
||||
def->full_label = L("Seam travel cost");
|
||||
def->category = OptionCategory::perimeter;
|
||||
def->tooltip = L("Cost of moving the extruder. The highest penalty is when the point is the farest from the position of the extruder before extruding the external periemter");
|
||||
def->sidetext = L("%");
|
||||
def->min = 0;
|
||||
def->mode = comExpert;
|
||||
def->set_default_value(new ConfigOptionPercent(100));
|
||||
|
||||
#if 0
|
||||
def = this->add("seam_preferred_direction", coFloat);
|
||||
@ -4769,8 +4776,19 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va
|
||||
value = "notconnected";
|
||||
else
|
||||
value = "connected";
|
||||
} else if (opt_key == "seam_travel") {
|
||||
if (value == "1") {
|
||||
opt_key = "seam_travel_cost";
|
||||
value = "200%";
|
||||
} else {
|
||||
opt_key = "";
|
||||
}
|
||||
} else if (opt_key == "seam_position") {
|
||||
if (value == "hidden") {
|
||||
opt_key = "seam_travel_cost";
|
||||
value = "20%";
|
||||
}
|
||||
}
|
||||
|
||||
// Ignore the following obsolete configuration keys:
|
||||
static std::set<std::string> ignore = {
|
||||
"duplicate_x", "duplicate_y", "gcode_arcs", "multiply_x", "multiply_y",
|
||||
|
@ -100,7 +100,7 @@ enum SupportMaterialPattern {
|
||||
};
|
||||
|
||||
enum SeamPosition {
|
||||
spRandom, spNearest, spAligned, spRear, spHidden, spCustom
|
||||
spRandom, spNearest, spAligned, spRear, spCustom
|
||||
};
|
||||
|
||||
enum SLAMaterial {
|
||||
@ -272,11 +272,11 @@ template<> inline const t_config_enum_values& ConfigOptionEnum<SeamPosition>::ge
|
||||
static t_config_enum_values keys_map;
|
||||
if (keys_map.empty()) {
|
||||
keys_map["random"] = spRandom;
|
||||
keys_map["nearest"] = spHidden;
|
||||
keys_map["nearest"] = spNearest;
|
||||
keys_map["near"] = spNearest;
|
||||
keys_map["aligned"] = spAligned;
|
||||
keys_map["rear"] = spRear;
|
||||
keys_map["hidden"] = spHidden;
|
||||
keys_map["hidden"] = spNearest;
|
||||
keys_map["custom"] = spCustom;
|
||||
}
|
||||
return keys_map;
|
||||
@ -587,7 +587,8 @@ public:
|
||||
ConfigOptionPercent perimeter_bonding;
|
||||
ConfigOptionInt raft_layers;
|
||||
ConfigOptionEnum<SeamPosition> seam_position;
|
||||
ConfigOptionBool seam_travel;
|
||||
ConfigOptionPercent seam_angle_cost;
|
||||
ConfigOptionPercent seam_travel_cost;
|
||||
// ConfigOptionFloat seam_preferred_direction;
|
||||
// ConfigOptionFloat seam_preferred_direction_jitter;
|
||||
ConfigOptionFloat slice_closing_radius;
|
||||
@ -650,7 +651,8 @@ protected:
|
||||
OPT_PTR(perimeter_bonding);
|
||||
OPT_PTR(raft_layers);
|
||||
OPT_PTR(seam_position);
|
||||
OPT_PTR(seam_travel);
|
||||
OPT_PTR(seam_angle_cost);
|
||||
OPT_PTR(seam_travel_cost);
|
||||
OPT_PTR(slice_closing_radius);
|
||||
// OPT_PTR(seam_preferred_direction);
|
||||
// OPT_PTR(seam_preferred_direction_jitter);
|
||||
|
@ -819,7 +819,8 @@ bool PrintObject::invalidate_state_by_config_options(const std::vector<t_config_
|
||||
|| opt_key == "seam_position"
|
||||
|| opt_key == "seam_preferred_direction"
|
||||
|| opt_key == "seam_preferred_direction_jitter"
|
||||
|| opt_key == "seam_travel"
|
||||
|| opt_key == "seam_angle_cost"
|
||||
|| opt_key == "seam_travel_cost"
|
||||
|| opt_key == "small_perimeter_speed"
|
||||
|| opt_key == "solid_infill_speed"
|
||||
|| opt_key == "support_material_interface_speed"
|
||||
@ -2274,7 +2275,9 @@ void PrintObject::_slice(const std::vector<coordf_t> &layer_height_profile)
|
||||
// slicing in parallel
|
||||
std::vector<ExPolygons> expolygons_by_layer = this->slice_region(region_id, slice_zs, slicing_mode);
|
||||
//scale for shrinkage
|
||||
double scale = print()->config().filament_shrink.get_abs_value(this->print()->regions()[region_id]->extruder(FlowRole::frPerimeter) - 1, 1);
|
||||
std::cout << (&(this->print()->regions())) << " =?= " << (&(this->print()->m_regions)) << "\n";
|
||||
const size_t extruder_id = this->print()->regions()[region_id]->extruder(FlowRole::frPerimeter) - 1;
|
||||
double scale = print()->config().filament_shrink.get_abs_value(extruder_id, 1);
|
||||
if (scale != 1) {
|
||||
scale = 1 / scale;
|
||||
for (ExPolygons &polys : expolygons_by_layer)
|
||||
|
@ -81,7 +81,7 @@ void PreferencesDialog::build()
|
||||
def.label = L("Check for application updates");
|
||||
def.type = coBool;
|
||||
def.tooltip = L("If enabled, SuperSlicer will check for the new versions of itself online. When a new version becomes available a notification is displayed at the next application startup (never during program usage). This is only a notification mechanisms, no automatic installation is done.");
|
||||
def.set_default_value(new ConfigOptionBool(app_config->get("version_check") == "0"));
|
||||
def.set_default_value(new ConfigOptionBool(app_config->get("version_check") == "1"));
|
||||
option = Option(def, "version_check");
|
||||
m_optgroup_general->append_single_option_line(option);
|
||||
|
||||
@ -97,7 +97,7 @@ void PreferencesDialog::build()
|
||||
def.label = L("Update built-in Presets automatically");
|
||||
def.type = coBool;
|
||||
def.tooltip = L("If enabled, Slic3r downloads updates of built-in system presets in the background. These updates are downloaded into a separate temporary location. When a new preset version becomes available it is offered at application startup.");
|
||||
def.set_default_value(new ConfigOptionBool(app_config->get("preset_update") == "0"));
|
||||
def.set_default_value(new ConfigOptionBool(app_config->get("preset_update") == "1"));
|
||||
option = Option(def, "preset_update");
|
||||
m_optgroup_general->append_single_option_line(option);
|
||||
|
||||
@ -124,19 +124,6 @@ void PreferencesDialog::build()
|
||||
option = Option(def, "objects_always_expert");
|
||||
m_optgroup_general->append_single_option_line(option);
|
||||
|
||||
m_optgroup_paths = std::make_shared<ConfigOptionsGroup>(this, _(L("General")));
|
||||
m_optgroup_paths->title_width = 10;
|
||||
m_optgroup_paths->m_on_change = [this](t_config_option_key opt_key, boost::any value) {
|
||||
m_values[opt_key] = boost::any_cast<std::string>(value);
|
||||
};
|
||||
def.label = L("FreeCAD path");
|
||||
def.type = coString;
|
||||
def.tooltip = L("If it point to a valid freecad instance (the bin directory or the python executable), you can use the built-in python script to quickly generate geometry.");
|
||||
def.set_default_value(new ConfigOptionString{ app_config->get("freecad_path") });
|
||||
option = Option(def, "freecad_path");
|
||||
option.opt.full_width = true;
|
||||
m_optgroup_paths->append_single_option_line(option);
|
||||
|
||||
def.label = L("Single Instance");
|
||||
def.type = coBool;
|
||||
#if __APPLE__
|
||||
@ -195,6 +182,21 @@ void PreferencesDialog::build()
|
||||
|
||||
m_optgroup_general->activate();
|
||||
|
||||
m_optgroup_paths = std::make_shared<ConfigOptionsGroup>(this, _(L("Paths")));
|
||||
m_optgroup_paths->title_width = 10;
|
||||
m_optgroup_paths->m_on_change = [this](t_config_option_key opt_key, boost::any value) {
|
||||
m_values[opt_key] = boost::any_cast<std::string>(value);
|
||||
};
|
||||
def.label = L("FreeCAD path");
|
||||
def.type = coString;
|
||||
def.tooltip = L("If it point to a valid freecad instance (the bin directory or the python executable), you can use the built-in python script to quickly generate geometry.");
|
||||
def.set_default_value(new ConfigOptionString{ app_config->get("freecad_path") });
|
||||
option = Option(def, "freecad_path");
|
||||
option.opt.full_width = true;
|
||||
m_optgroup_paths->append_single_option_line(option);
|
||||
|
||||
m_optgroup_paths->activate();
|
||||
|
||||
m_optgroup_camera = std::make_shared<ConfigOptionsGroup>(this, _L("Camera"));
|
||||
m_optgroup_camera->label_width = 40;
|
||||
m_optgroup_camera->m_on_change = [this](t_config_option_key opt_key, boost::any value) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user