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:
supermerill 2020-10-25 02:56:22 +02:00
parent 3aaedd671b
commit 07be95fb69
11 changed files with 199 additions and 95 deletions

View File

@ -49,14 +49,15 @@ group:Overhangs
setting:width$5:overhangs_reverse_threshold setting:width$5:overhangs_reverse_threshold
end_line end_line
group:Advanced group:Advanced
setting:no_perimeter_unsupported_algo setting:width$25:no_perimeter_unsupported_algo
line:Gap Fill line:Gap Fill
setting:gap_fill setting:gap_fill
setting:width$5:gap_fill_min_area setting:width$5:gap_fill_min_area
end_line end_line
line:Seam line:Seam
setting:seam_position setting:sidetext_width$2:seam_position
setting:seam_travel 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 end_line
line:Looping perimeter line:Looping perimeter
setting:perimeter_loop setting:perimeter_loop

View File

@ -60,9 +60,9 @@ void AppConfig::set_defaults()
set("freecad_path", "."); set("freecad_path", ".");
if (get("version_check").empty()) if (get("version_check").empty())
set("version_check", "1"); set("version_check", "0");
if (get("preset_update").empty()) if (get("preset_update").empty())
set("preset_update", "1"); set("preset_update", "0");
if (get("export_sources_full_pathnames").empty()) if (get("export_sources_full_pathnames").empty())
set("export_sources_full_pathnames", "0"); set("export_sources_full_pathnames", "0");

View File

@ -3227,7 +3227,7 @@ void GCode::split_at_seam_pos(ExtrusionLoop& loop, std::unique_ptr<EdgeGrid::Gri
? lower_layer_edge_grid->get() ? lower_layer_edge_grid->get()
: nullptr; : nullptr;
//TODO modify m_seam_placer to takers into account extra options. //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), last_pos, EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter, 0),
(m_layer == NULL ? nullptr : m_layer->object()), (m_layer == NULL ? nullptr : m_layer->object()),
was_clockwise, edge_grid_ptr); was_clockwise, edge_grid_ptr);

View File

@ -2,6 +2,7 @@
#include "libslic3r/ExtrusionEntity.hpp" #include "libslic3r/ExtrusionEntity.hpp"
#include "libslic3r/Print.hpp" #include "libslic3r/Print.hpp"
#include "libslic3r/Layer.hpp"
#include "libslic3r/BoundingBox.hpp" #include "libslic3r/BoundingBox.hpp"
#include "libslic3r/EdgeGrid.hpp" #include "libslic3r/EdgeGrid.hpp"
#include "libslic3r/ClipperUtils.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. // 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. // 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) static inline float bspline_kernel(float x)
{ {
x = std::abs(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 ExtrusionLoop& loop, Point last_pos, coordf_t nozzle_dmr,
const PrintObject* po, bool was_clockwise, const EdgeGrid::Grid* lower_layer_edge_grid) const PrintObject* po, bool was_clockwise, const EdgeGrid::Grid* lower_layer_edge_grid)
{ {
const size_t layer_idx = layer->id();
Polygon polygon = loop.polygon(); Polygon polygon = loop.polygon();
BoundingBox polygon_bb = polygon.bounding_box(); BoundingBox polygon_bb = polygon.bounding_box();
const coord_t nozzle_r = coord_t(scale_(0.5 * nozzle_dmr) + 0.5); 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)) { if (this->is_custom_seam_on_layer(layer_idx)) {
// Seam enf/blockers can begin and end in between the original vertices. // 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); 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) { if (seam_position != spRandom) {
// Retrieve the last start position for this object. // Retrieve the last start position for this object.
float last_pos_weight = 1.f;
if (seam_position == spAligned) { if (seam_position == spAligned) {
// Seam is aligned to the seam at the preceding layer. // 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()) { if (pos.has_value()) {
//last_pos = m_last_seam_position[po]; //last_pos = m_last_seam_position[po];
last_pos = *pos; last_pos = *pos;
last_pos_weight = is_custom_enforcer_on_layer(layer_idx) ? 0.f : 1.f;
} }
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. // Object is centered around (0,0) in its current coordinate system.
last_pos.x() = 0; last_pos.x() = 0;
last_pos.y() += coord_t(3. * po->bounding_box().radius()); last_pos.y() += coord_t(3. * po->bounding_box().radius());
last_pos_weight = 5.f; last_pos_weight = 5.f;
} if (seam_position == spNearest) { }else if (seam_position == spNearest) {
// last_pos already contains current nozzle position // 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. // Insert a projection of last_pos into the polygon.
size_t last_pos_proj_idx; 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(); last_pos_proj_idx = it - polygon.points.begin();
} }
Point last_pos_proj = polygon.points[last_pos_proj_idx];
// Parametrize the polygon by its length. // Parametrize the polygon by its length.
std::vector<float> lengths = polygon.parameter_by_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. // 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. // 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. // No penalty for reflex points, slight penalty for convex points, high penalty for flat surfaces.
const float penaltyConvexVertex = 1.f; const float penaltyConvexVertex = 1.f;
const float penaltyFlatSurface = 5.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) if (was_clockwise)
ccwAngle = - ccwAngle; ccwAngle = - ccwAngle;
float penalty = 0; float penalty = 0;
if (ccwAngle <- float(0.6 * PI)) //if (ccwAngle < -float(0.6 * PI))
// Sharp reflex vertex. We love that, it hides the seam perfectly. // penalty = 0.f;
penalty = 0.f; //else if (ccwAngle > float(0.6 * PI))
else if (ccwAngle > float(0.6 * PI)) //
// Seams on sharp convex vertices are more visible than on reflex vertices. // penalty = penaltyConvexVertex;
penalty = penaltyConvexVertex; //else
else if (ccwAngle < 0.f) { if (ccwAngle < 0.f) {
// We love Sharp reflex vertex (high negative ccwAngle). It hides the seam perfectly.
// Interpolate penalty between maximum and zero. // 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 { } else {
assert(ccwAngle >= 0.f);
// Interpolate penalty between maximum and the penalty for a convex vertex. // 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]);
penalty -= last_pos_weight * bspline_kernel(dist_to_last_pos_proj / dist_max);
} }
// 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); 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 // Custom seam. Huge (negative) constant penalty is applied inside
// blockers (enforcers) to rule out points that should not win. // 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. // 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)) { 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. // 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. // In that case use last_pos_proj_idx instead.
float penalty_aligned = penalties[last_pos_proj_idx]; float penalty_aligned = penalties[last_pos_proj_idx];
float penalty_min = penalties[idx_min]; float penalty_min = penalties[idx_min];
float penalty_diff_abs = std::abs(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(penalty_min, penalty_aligned); 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; 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); // 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. // Penalty of the aligned point is very close to the minimum penalty.
// Align the seams as accurately as possible. // Align the seams as accurately as possible.
idx_min = last_pos_proj_idx; 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); m_seam_history.add_seam(po, polygon.points[idx_min], polygon_bb);

View File

@ -12,6 +12,7 @@ namespace Slic3r {
class PrintObject; class PrintObject;
class ExtrusionLoop; class ExtrusionLoop;
class Print; class Print;
class Layer;
namespace EdgeGrid { class Grid; } namespace EdgeGrid { class Grid; }
@ -39,7 +40,7 @@ class SeamPlacer {
public: public:
void init(const Print& print); 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, const ExtrusionLoop& loop, Point last_pos,
coordf_t nozzle_diameter, const PrintObject* po, coordf_t nozzle_diameter, const PrintObject* po,
bool was_clockwise, const EdgeGrid::Grid* lower_layer_edge_grid); bool was_clockwise, const EdgeGrid::Grid* lower_layer_edge_grid);

View File

@ -536,7 +536,8 @@ const std::vector<std::string>& Preset::print_options()
"exact_last_layer_height", "exact_last_layer_height",
"perimeter_loop", "perimeter_loop",
"perimeter_loop_seam", "perimeter_loop_seam",
"seam_travel", "seam_angle_cost",
"seam_travel_cost",
"infill_connection", "infill_connection",
"first_layer_infill_speed", "first_layer_infill_speed",
"thin_walls_min_width", "thin_walls_min_width",

View File

@ -932,28 +932,28 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
} }
// Copy content of the ModelObject including its ID, do not change the parent. // Copy content of the ModelObject including its ID, do not change the parent.
model_object.assign_copy(model_object_new); 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. // First stop background processing before shuffling or deleting the ModelVolumes in the ModelObject's list.
if (supports_differ) { if (supports_differ) {
this->call_cancel_callback(); this->call_cancel_callback();
update_apply_status(false); update_apply_status(false);
} }
// Invalidate just the supports step. // Invalidate just the supports step.
auto range = print_object_status.equal_range(PrintObjectStatus(model_object.id())); auto range = print_object_status.equal_range(PrintObjectStatus(model_object.id()));
for (auto it = range.first; it != range.second; ++ it) for (auto it = range.first; it != range.second; ++ it)
update_apply_status(it->print_object->invalidate_step(posSupportMaterial)); update_apply_status(it->print_object->invalidate_step(posSupportMaterial));
if (supports_differ) { if (supports_differ) {
// Copy just the support volumes. // Copy just the support volumes.
model_volume_list_update_supports_seams(model_object, model_object_new); model_volume_list_update_supports_seams(model_object, model_object_new);
}else if (seam_position_differ) { }else if (seam_position_differ) {
// First stop background processing before shuffling or deleting the ModelVolumes in the ModelObject's list. // First stop background processing before shuffling or deleting the ModelVolumes in the ModelObject's list.
this->call_cancel_callback(); this->call_cancel_callback();
update_apply_status(false); update_apply_status(false);
// Invalidate just the gcode step. // Invalidate just the gcode step.
invalidate_step(psGCodeExport); invalidate_step(psGCodeExport);
// Copy just the seam volumes. // Copy just the seam volumes.
model_volume_list_update_supports_seams(model_object, model_object_new); model_volume_list_update_supports_seams(model_object, model_object_new);
} }
} else if (model_custom_seam_data_changed(model_object, model_object_new)) { } else if (model_custom_seam_data_changed(model_object, model_object_new)) {
update_apply_status(this->invalidate_step(psGCodeExport)); update_apply_status(this->invalidate_step(psGCodeExport));
} }

View File

@ -2796,31 +2796,38 @@ void PrintConfigDef::init_fff_params()
def->label = L("Seam position"); def->label = L("Seam position");
def->category = OptionCategory::perimeter; def->category = OptionCategory::perimeter;
def->tooltip = L("Position of perimeters starting points." def->tooltip = L("Position of perimeters starting points."
"\n --- When using Custom seam ---" "\n ");
"\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.");
def->enum_keys_map = &ConfigOptionEnum<SeamPosition>::get_enum_values(); 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("near");
def->enum_values.push_back("random");
def->enum_values.push_back("aligned"); def->enum_values.push_back("aligned");
def->enum_values.push_back("rear"); 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("Random"));
def->enum_labels.push_back(L("Nearest"));
def->enum_labels.push_back(L("Aligned")); 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("Corners"));
def->mode = comSimple; 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 = this->add("seam_angle_cost", coPercent);
def->label = L("Travel move reduced"); def->label = L("Angle cost");
def->full_label = L("Seam angle cost");
def->category = OptionCategory::perimeter; 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->tooltip = L("Cost of placing the seam at a bad angle. The worst angle (max penalty) is when it's flat.");
def->cli = "seam-travel!"; def->sidetext = L("%");
def->min = 0;
def->mode = comExpert; 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 #if 0
def = this->add("seam_preferred_direction", coFloat); 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"; value = "notconnected";
else else
value = "connected"; 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: // Ignore the following obsolete configuration keys:
static std::set<std::string> ignore = { static std::set<std::string> ignore = {
"duplicate_x", "duplicate_y", "gcode_arcs", "multiply_x", "multiply_y", "duplicate_x", "duplicate_y", "gcode_arcs", "multiply_x", "multiply_y",

View File

@ -100,7 +100,7 @@ enum SupportMaterialPattern {
}; };
enum SeamPosition { enum SeamPosition {
spRandom, spNearest, spAligned, spRear, spHidden, spCustom spRandom, spNearest, spAligned, spRear, spCustom
}; };
enum SLAMaterial { enum SLAMaterial {
@ -272,11 +272,11 @@ template<> inline const t_config_enum_values& ConfigOptionEnum<SeamPosition>::ge
static t_config_enum_values keys_map; static t_config_enum_values keys_map;
if (keys_map.empty()) { if (keys_map.empty()) {
keys_map["random"] = spRandom; keys_map["random"] = spRandom;
keys_map["nearest"] = spHidden; keys_map["nearest"] = spNearest;
keys_map["near"] = spNearest; keys_map["near"] = spNearest;
keys_map["aligned"] = spAligned; keys_map["aligned"] = spAligned;
keys_map["rear"] = spRear; keys_map["rear"] = spRear;
keys_map["hidden"] = spHidden; keys_map["hidden"] = spNearest;
keys_map["custom"] = spCustom; keys_map["custom"] = spCustom;
} }
return keys_map; return keys_map;
@ -587,7 +587,8 @@ public:
ConfigOptionPercent perimeter_bonding; ConfigOptionPercent perimeter_bonding;
ConfigOptionInt raft_layers; ConfigOptionInt raft_layers;
ConfigOptionEnum<SeamPosition> seam_position; ConfigOptionEnum<SeamPosition> seam_position;
ConfigOptionBool seam_travel; ConfigOptionPercent seam_angle_cost;
ConfigOptionPercent seam_travel_cost;
// ConfigOptionFloat seam_preferred_direction; // ConfigOptionFloat seam_preferred_direction;
// ConfigOptionFloat seam_preferred_direction_jitter; // ConfigOptionFloat seam_preferred_direction_jitter;
ConfigOptionFloat slice_closing_radius; ConfigOptionFloat slice_closing_radius;
@ -650,7 +651,8 @@ protected:
OPT_PTR(perimeter_bonding); OPT_PTR(perimeter_bonding);
OPT_PTR(raft_layers); OPT_PTR(raft_layers);
OPT_PTR(seam_position); 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(slice_closing_radius);
// OPT_PTR(seam_preferred_direction); // OPT_PTR(seam_preferred_direction);
// OPT_PTR(seam_preferred_direction_jitter); // OPT_PTR(seam_preferred_direction_jitter);

View File

@ -819,7 +819,8 @@ bool PrintObject::invalidate_state_by_config_options(const std::vector<t_config_
|| opt_key == "seam_position" || opt_key == "seam_position"
|| opt_key == "seam_preferred_direction" || opt_key == "seam_preferred_direction"
|| opt_key == "seam_preferred_direction_jitter" || 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 == "small_perimeter_speed"
|| opt_key == "solid_infill_speed" || opt_key == "solid_infill_speed"
|| opt_key == "support_material_interface_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 // slicing in parallel
std::vector<ExPolygons> expolygons_by_layer = this->slice_region(region_id, slice_zs, slicing_mode); std::vector<ExPolygons> expolygons_by_layer = this->slice_region(region_id, slice_zs, slicing_mode);
//scale for shrinkage //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) { if (scale != 1) {
scale = 1 / scale; scale = 1 / scale;
for (ExPolygons &polys : expolygons_by_layer) for (ExPolygons &polys : expolygons_by_layer)

View File

@ -81,7 +81,7 @@ void PreferencesDialog::build()
def.label = L("Check for application updates"); def.label = L("Check for application updates");
def.type = coBool; 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.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"); option = Option(def, "version_check");
m_optgroup_general->append_single_option_line(option); m_optgroup_general->append_single_option_line(option);
@ -97,7 +97,7 @@ void PreferencesDialog::build()
def.label = L("Update built-in Presets automatically"); def.label = L("Update built-in Presets automatically");
def.type = coBool; 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.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"); option = Option(def, "preset_update");
m_optgroup_general->append_single_option_line(option); m_optgroup_general->append_single_option_line(option);
@ -117,25 +117,12 @@ void PreferencesDialog::build()
option = Option(def, "show_incompatible_presets"); option = Option(def, "show_incompatible_presets");
m_optgroup_general->append_single_option_line(option); m_optgroup_general->append_single_option_line(option);
def.label = L("Main GUI always in expert mode"); def.label = L("Main GUI always in expert mode");
def.type = coBool; def.type = coBool;
def.tooltip = L("If enabled, the gui will be in expert mode even if the simple or advanced mode is selected (but not the setting tabs)."); def.tooltip = L("If enabled, the gui will be in expert mode even if the simple or advanced mode is selected (but not the setting tabs).");
def.set_default_value(new ConfigOptionBool{ app_config->get("objects_always_expert") == "1" }); def.set_default_value(new ConfigOptionBool{ app_config->get("objects_always_expert") == "1" });
option = Option(def, "objects_always_expert"); option = Option(def, "objects_always_expert");
m_optgroup_general->append_single_option_line(option); 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.label = L("Single Instance");
def.type = coBool; def.type = coBool;
@ -195,6 +182,21 @@ void PreferencesDialog::build()
m_optgroup_general->activate(); 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 = std::make_shared<ConfigOptionsGroup>(this, _L("Camera"));
m_optgroup_camera->label_width = 40; m_optgroup_camera->label_width = 40;
m_optgroup_camera->m_on_change = [this](t_config_option_key opt_key, boost::any value) { m_optgroup_camera->m_on_change = [this](t_config_option_key opt_key, boost::any value) {