diff options
-rw-r--r-- | src/libslic3r/ClipperUtils.cpp | 33 | ||||
-rw-r--r-- | src/libslic3r/ExtrusionEntity.cpp | 22 | ||||
-rw-r--r-- | src/libslic3r/ExtrusionEntity.hpp | 8 | ||||
-rw-r--r-- | src/libslic3r/PerimeterGenerator.cpp | 15 | ||||
-rw-r--r-- | src/libslic3r/PrintConfig.cpp | 13 | ||||
-rw-r--r-- | src/libslic3r/PrintObject.cpp | 7 | ||||
-rw-r--r-- | src/slic3r/GUI/ConfigManipulation.cpp | 2 | ||||
-rw-r--r-- | src/slic3r/GUI/Field.cpp | 8 |
8 files changed, 92 insertions, 16 deletions
diff --git a/src/libslic3r/ClipperUtils.cpp b/src/libslic3r/ClipperUtils.cpp index 45bb08599..d529e08d7 100644 --- a/src/libslic3r/ClipperUtils.cpp +++ b/src/libslic3r/ClipperUtils.cpp @@ -598,7 +598,21 @@ ClipperLib::PolyTree _clipper_do_pl(const ClipperLib::ClipType clipType, const P // read input ClipperLib::Paths input_subject = Slic3rMultiPoints_to_ClipperPaths(subject); ClipperLib::Paths input_clip = Slic3rMultiPoints_to_ClipperPaths(clip); - + + //perform y safing : if a line is on the same Y, clipper may not pick the good point. + std::set<coord_t> bad_y; + for (ClipperLib::Paths* input : {&input_subject, &input_clip} ) + for (ClipperLib::Path& path : *input) { + coord_t lasty = 0; + for (ClipperLib::IntPoint& pt : path) { + if (lasty == pt.Y) { + pt.Y+=1; + bad_y.insert(pt.Y); + } + lasty = pt.Y; + } + } + // perform safety offset if (safety_offset_) safety_offset(&input_clip); @@ -613,6 +627,23 @@ ClipperLib::PolyTree _clipper_do_pl(const ClipperLib::ClipType clipType, const P // perform operation ClipperLib::PolyTree retval; clipper.Execute(clipType, retval, fillType, fillType); + + //restore good y + if (!bad_y.empty()) { + std::vector<ClipperLib::PolyNode*> to_check; + to_check.push_back(&retval); + while (!to_check.empty()) { + ClipperLib::PolyNode* node = to_check.back(); + to_check.pop_back(); + for (ClipperLib::IntPoint& pt : node->Contour) { + if (bad_y.find(pt.Y) != bad_y.end()) { + pt.Y-=1; + } + } + to_check.insert(to_check.end(), node->Childs.begin(), node->Childs.end()); + } + } + return retval; } diff --git a/src/libslic3r/ExtrusionEntity.cpp b/src/libslic3r/ExtrusionEntity.cpp index 3ec8800bb..6b0611cca 100644 --- a/src/libslic3r/ExtrusionEntity.cpp +++ b/src/libslic3r/ExtrusionEntity.cpp @@ -388,6 +388,28 @@ void ExtrusionLength::use(const ExtrusionEntityCollection& collection) { } } + +void ExtrusionVisitorRecursiveConst::use(const ExtrusionMultiPath& multipath) { + for (const ExtrusionPath& path: multipath.paths) { + path.visit(*this); + } +} +void ExtrusionVisitorRecursiveConst::use(const ExtrusionMultiPath3D& multipath3D) { + for (const ExtrusionPath3D& path3D : multipath3D.paths) { + path3D.visit(*this); + } +} +void ExtrusionVisitorRecursiveConst::use(const ExtrusionLoop& loop) { + for (const ExtrusionPath& path : loop.paths) { + path.visit(*this); + } +} +void ExtrusionVisitorRecursiveConst::use(const ExtrusionEntityCollection& collection) { + for (const ExtrusionEntity* entity : collection.entities) { + entity->visit(*this); + } +} + //class ExtrusionTreeVisitor : ExtrusionVisitor { //public: // //virtual void use(ExtrusionEntity &entity) { assert(false); }; diff --git a/src/libslic3r/ExtrusionEntity.hpp b/src/libslic3r/ExtrusionEntity.hpp index 8ce95e910..5369998cf 100644 --- a/src/libslic3r/ExtrusionEntity.hpp +++ b/src/libslic3r/ExtrusionEntity.hpp @@ -606,6 +606,14 @@ public: } }; +class ExtrusionVisitorRecursiveConst : public ExtrusionVisitorConst { +public: + virtual void use(const ExtrusionMultiPath& multipath) override; + virtual void use(const ExtrusionMultiPath3D& multipath) override; + virtual void use(const ExtrusionLoop& loop) override; + virtual void use(const ExtrusionEntityCollection& collection) override; +}; + } #endif diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp index a5bedcc33..ed6e34549 100644 --- a/src/libslic3r/PerimeterGenerator.cpp +++ b/src/libslic3r/PerimeterGenerator.cpp @@ -1852,6 +1852,8 @@ PerimeterGenerator::_extrude_and_cut_loop(const PerimeterGeneratorLoop &loop, co for (ExtrusionPath &path : paths) { direction_polyline.points.insert(direction_polyline.points.end(), path.polyline.points.begin(), path.polyline.points.end()); } + for (int i = 0; i < direction_polyline.points.size() - 1; i++) + assert(direction_polyline.points[i] != direction_polyline.points[i + 1]); direction_polyline.clip_start(SCALED_RESOLUTION); direction_polyline.clip_end(SCALED_RESOLUTION); coord_t dot = direction.dot(Line(direction_polyline.points.back(), direction_polyline.points.front())); @@ -1950,11 +1952,12 @@ PerimeterGenerator::_traverse_and_join_loops(const PerimeterGeneratorLoop &loop, //create new node with recursive ask for the inner perimeter & COPY of the points, ready to be cut my_loop.paths.insert(my_loop.paths.begin() + nearest.idx_polyline_outter + 1, my_loop.paths[nearest.idx_polyline_outter]); + // outer_start == outer_end ExtrusionPath *outer_start = &my_loop.paths[nearest.idx_polyline_outter]; ExtrusionPath *outer_end = &my_loop.paths[nearest.idx_polyline_outter + 1]; Line deletedSection; - //cut our polyline + //cut our polyline, so outer_start has no common point with outer_end //separate them size_t nearest_idx_outter = outer_start->polyline.closest_point_index(nearest.outter_best); if (outer_start->polyline.points[nearest_idx_outter].coincides_with_epsilon(nearest.outter_best)) { @@ -2195,6 +2198,16 @@ PerimeterGenerator::_traverse_and_join_loops(const PerimeterGeneratorLoop &loop, my_loop.paths.insert(my_loop.paths.begin() + nearest.idx_polyline_outter + 1, travel_path_begin[i]); } } + //remove one-point extrusion + //FIXME prevent this instead of patching here? + for (int i = 0; i < my_loop.paths.size(); i++) { + if (my_loop.paths[i].polyline.size() < 2) { + if (my_loop.paths[i].polyline.size() == 1) + std::cout << "erase one-point extrusion : layer " << this->layer->id() << " " << my_loop.paths[i].polyline.points.front().x() << ":" << my_loop.paths[i].polyline.points.front().y() << "\n"; + my_loop.paths.erase(my_loop.paths.begin() + i); + i--; + } + } //update for next loop childs.erase(childs.begin() + nearest.idx_children); diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index c5ae79bd8..a4cc2f4d3 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -3849,7 +3849,10 @@ void PrintConfigDef::init_fff_params() def->set_default_value(new ConfigOptionBool(false)); def = this->add("solid_over_perimeters", coInt); - def->label = L("Max perimeters layer for solid infill"); + def->label = L("No solid infill over"); + def->full_label = L("No solid infill over perimeters"); + def->sidetext = L("perimeters"); + def->sidetext_width = 20; def->category = OptionCategory::perimeter; def->tooltip = L("When you have a medium/hight number of top/bottom solid layers, and a low/medium of perimeters," " then it have to put some solid infill inside the part to have enough solid layers." @@ -6482,6 +6485,7 @@ std::set<const DynamicPrintConfig*> DynamicPrintConfig::value_changed(const t_co } //FIXME localize this function. +//note: seems only called for config export & command line. Most of the validation work for the gui is done elsewhere... So this function may be a bit out-of-sync std::string FullPrintConfig::validate() { // --layer-height @@ -6558,7 +6562,7 @@ std::string FullPrintConfig::validate() // --fill-density if (fabs(this->fill_density.value - 100.) < EPSILON && (! print_config_def.get("top_fill_pattern")->has_enum_value(this->fill_pattern.serialize()) - || ! print_config_def.get("bottom_fill_pattern")->has_enum_value(this->fill_pattern.serialize()) + && ! print_config_def.get("bottom_fill_pattern")->has_enum_value(this->fill_pattern.serialize()) )) return "The selected fill pattern is not supposed to work at 100% density"; @@ -6581,11 +6585,6 @@ std::string FullPrintConfig::validate() if (em <= 0) return "Invalid value for --extrusion-multiplier"; - // --default-acceleration - if ((this->perimeter_acceleration.value != 0. || this->infill_acceleration.value != 0. || this->bridge_acceleration.value != 0. || this->first_layer_acceleration.value != 0.) && - this->default_acceleration.value == 0.) - return "Invalid zero value for --default-acceleration when using other acceleration settings"; - // --spiral-vase if (this->spiral_vase) { // Note that we might want to have more than one perimeter on the bottom diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index c9d48093f..126db9a2c 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -1672,7 +1672,7 @@ namespace Slic3r { size_t grain_size = std::max(num_layers / 16, size_t(1)); //solid_over_perimeters value, to remove solid fill where there's only perimeters on multiple layers - int nb_perimeter_layers_for_solid_fill = region.config().solid_over_perimeters.value; + const int nb_perimeter_layers_for_solid_fill = region.config().solid_over_perimeters.value; if (!top_bottom_surfaces_all_regions) { // This is either a single material print, or a multi-material print and interface_shells are enabled, meaning that the vertical shell thickness @@ -1899,8 +1899,9 @@ namespace Slic3r { //check if a polygon is only over perimeter, in this case evict it (depends from nb_perimeter_layers_for_solid_fill value) if (nb_perimeter_layers_for_solid_fill != 0) { for (int i = 0; i < shell.size(); i++) { - if (nb_perimeter_layers_for_solid_fill < 2 || intersection({ shell[i] }, max_perimeter_shell, false).empty()) { - toadd = intersection_ex({ shell[i] }, fill_shell); + if (nb_perimeter_layers_for_solid_fill < 2 || intersection_ex({ shell[i] }, max_perimeter_shell, false).empty()) { + ExPolygons expoly = intersection_ex({ shell[i] }, fill_shell); + toadd.insert(toadd.end(), expoly.begin(), expoly.end()); shell.erase(shell.begin() + i); i--; } diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index f70ac147a..76f0e0d33 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -400,7 +400,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config) toggle_field(el, have_infill_dense); bool has_spiral_vase = have_perimeters && config->opt_bool("spiral_vase"); - bool has_top_solid_infill = config->opt_int("top_solid_layers") > 0; + bool has_top_solid_infill = config->opt_int("top_solid_layers") > 0 || has_spiral_vase; bool has_bottom_solid_infill = config->opt_int("bottom_solid_layers") > 0; bool has_solid_infill = has_top_solid_infill || has_bottom_solid_infill || (have_infill && (config->opt_int("solid_infill_every_layers") > 0 || config->opt_float("solid_infill_below_area") > 0)); // solid_infill_extruder uses the same logic as in Print::extruders() diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index cbc49c29e..a4cf9cd41 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -311,8 +311,10 @@ void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true str.Replace(" ", "", true); str.Replace("m", "", true); - if (!str.ToCDouble(&val)) - { + if (m_opt.nullable && str == na_value()) { + val = ConfigOptionFloatsNullable::nil_value(); + str = "nan"; + } else if (!str.ToCDouble(&val)) { if (!check_value) { m_value.clear(); break; @@ -480,7 +482,6 @@ void TextCtrl::BUILD() { m_opt.default_value->getFloat() : m_opt.get_default_value<ConfigOptionPercents>()->get_at(m_opt_idx); text_value = double_to_string(val, m_opt.precision); - m_last_meaningful_value = text_value; break; } case coFloatsOrPercents: @@ -507,6 +508,7 @@ void TextCtrl::BUILD() { default: break; } + m_last_meaningful_value = text_value; const long style = m_opt.multiline ? wxTE_MULTILINE : wxTE_PROCESS_ENTER/*0*/; auto temp = new wxTextCtrl(m_parent, wxID_ANY, text_value, wxDefaultPosition, size, style); |