diff --git a/include/PrimeTower.h b/include/PrimeTower.h index 5bb8192a82..fe29030ee2 100644 --- a/include/PrimeTower.h +++ b/include/PrimeTower.h @@ -40,13 +40,14 @@ class PrimeTower const unsigned int number_of_prime_tower_start_locations = 21; //!< The required size of \ref PrimeTower::wipe_locations std::vector pattern_per_extruder; //!< For each extruder the pattern to print on all layers of the prime tower. - std::vector pattern_extra_brim_per_layer; //!< For each layer with an extra brim, the pattern to be added + std::vector> pattern_extra_brim_per_layer; //!< For each layer of each extruder with an extra brim, the pattern to be added public: bool enabled; //!< Whether the prime tower is enabled. bool would_have_actual_tower; //!< Whether there is an actual tower. bool multiple_extruders_on_first_layer; //!< Whether multiple extruders are allowed on the first layer of the prime tower (e.g. when a raft is there) Polygons outer_poly; //!< The outline of the outermost prime tower. + Polygons footprint; //!< The outline of the prime tower on layer 0 /* * In which order, from outside to inside, will we be printing the prime @@ -101,7 +102,9 @@ class PrimeTower void subtractFromSupport(SliceDataStorage& storage); private: - ExtrusionMoves generatePaths_extraBrim(const Polygons &outer_poly, coord_t extra_radius, coord_t line_width, bool add_inset); + ExtrusionMoves generatePaths_base(const Polygons &outer_poly, coord_t extra_radius, coord_t line_width); + + ExtrusionMoves generatePaths_inset(const Polygons &outer_poly, coord_t line_width, coord_t initial_inset); /*! * \see WipeTower::generatePaths diff --git a/include/SkirtBrim.h b/include/SkirtBrim.h index aefbd5bdd6..05f10a17e4 100644 --- a/include/SkirtBrim.h +++ b/include/SkirtBrim.h @@ -118,15 +118,6 @@ class SkirtBrim */ std::vector generateBrimOffsetPlan(std::vector& starting_outlines); - /*! - * In case that the models have skirt 'adhesion', but the prime tower has a brim, the covered areas are different. - * - * Since the output of this function will need to be handled differently than the rest of the adhesion lines, have a separate function. - * Specifically, for skirt an additional 'approximate convex hull' is applied to the initial 'covered area', which is detrimental to brim. - * \return An ordered list of offsets of the prime-tower to perform in the order in which they are to be performed. - */ - std::vector generatePrimeTowerBrimForSkirtAdhesionOffsetPlan(); - /*! * Generate the primary skirt/brim of the one skirt_brim_extruder or of all extruders simultaneously. * diff --git a/src/FffGcodeWriter.cpp b/src/FffGcodeWriter.cpp index 71ebbdef42..f8dabab971 100644 --- a/src/FffGcodeWriter.cpp +++ b/src/FffGcodeWriter.cpp @@ -164,8 +164,6 @@ void FffGcodeWriter::writeGCode(SliceDataStorage& storage, TimeKeeper& time_keep run_multiple_producers_ordered_consumer( process_layer_starting_layer_nr, - //-Raft::getTotalExtraLayers(), - // total_layers + Raft::getFillerLayerCount() - 1, total_layers, [&storage, total_layers, this](int layer_nr) { @@ -687,8 +685,6 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage) raftLines.clear(); } - setExtruder_addPrime(storage, gcode_layer, storage.primeTower.extruder_order.front()); - layer_plan_buffer.handle(gcode_layer, gcode); last_planned_position = gcode_layer.getLastPlannedPositionOrStartingPosition(); } @@ -735,11 +731,6 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage) std::vector raft_outline_paths; const coord_t small_offset = gcode_layer.configs_storage.raft_interface_config.getLineWidth() / 2; // Do this manually because of micron-movement created in corners when insetting a polygon that was offset with round joint type. - if (storage.primeRaftOutline.area() > 0) - { - raft_outline_paths.emplace_back(storage.primeRaftOutline.offset(-small_offset)); - raft_outline_paths.back() = Simplify(interface_settings).polygon(raft_outline_paths.back()); // Remove those micron-movements. - } raft_outline_paths.emplace_back(storage.raftOutline.offset(-small_offset)); raft_outline_paths.back() = Simplify(interface_settings).polygon(raft_outline_paths.back()); // Remove those micron-movements. const coord_t infill_outline_width = gcode_layer.configs_storage.raft_interface_config.getLineWidth(); @@ -841,11 +832,6 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage) std::vector raft_outline_paths; const coord_t small_offset = gcode_layer.configs_storage.raft_interface_config.getLineWidth() / 2; // Do this manually because of micron-movement created in corners when insetting a polygon that was offset with round joint type. - if (storage.primeRaftOutline.area() > 0) - { - raft_outline_paths.emplace_back(storage.primeRaftOutline.offset(-small_offset)); - raft_outline_paths.back() = Simplify(interface_settings).polygon(raft_outline_paths.back()); // Remove those micron-movements. - } raft_outline_paths.emplace_back(storage.raftOutline.offset(-small_offset)); raft_outline_paths.back() = Simplify(interface_settings).polygon(raft_outline_paths.back()); // Remove those micron-movements. const coord_t infill_outline_width = gcode_layer.configs_storage.raft_interface_config.getLineWidth(); diff --git a/src/PrimeTower.cpp b/src/PrimeTower.cpp index 472edc4054..49de8b3db1 100644 --- a/src/PrimeTower.cpp +++ b/src/PrimeTower.cpp @@ -97,6 +97,18 @@ void PrimeTower::generateGroundpoly() middle = Point(x - tower_size / 2, y + tower_size / 2); post_wipe_point = Point(x - tower_size / 2, y + tower_size / 2); + + const bool base_enabled = mesh_group_settings.get("prime_tower_brim_enable"); + const coord_t base_extra_radius = mesh_group_settings.get("prime_tower_base_size"); + const coord_t base_height = mesh_group_settings.get("prime_tower_base_height"); + if (base_enabled && base_extra_radius > 0 && base_height > 0) + { + footprint = outer_poly.offset(base_extra_radius); + } + else + { + footprint = outer_poly; + } } void PrimeTower::generatePaths(const SliceDataStorage& storage) @@ -110,7 +122,7 @@ void PrimeTower::generatePaths(const SliceDataStorage& storage) } } -PrimeTower::ExtrusionMoves PrimeTower::generatePaths_extraBrim(const Polygons& outer_poly, coord_t extra_radius, coord_t line_width, bool add_inset) +PrimeTower::ExtrusionMoves PrimeTower::generatePaths_base(const Polygons& outer_poly, coord_t extra_radius, coord_t line_width) { const Scene& scene = Application::getInstance().current_slice->scene; const Settings& mesh_group_settings = scene.current_mesh_group->settings; @@ -118,16 +130,6 @@ PrimeTower::ExtrusionMoves PrimeTower::generatePaths_extraBrim(const Polygons& o ExtrusionMoves pattern; - if (add_inset) - { - Polygons inset = outer_poly.offset(-line_width / 2); - while (! inset.empty()) - { - pattern.polygons.add(inset); - inset = inset.offset(-line_width); - } - } - int circles = 0; Polygons outset = outer_poly.offset(line_width / 2); while (outset.max() - outset.min() < (tower_size + extra_radius * 2)) @@ -140,15 +142,34 @@ PrimeTower::ExtrusionMoves PrimeTower::generatePaths_extraBrim(const Polygons& o return pattern; } -void PrimeTower::generatePaths_denseInfill() +PrimeTower::ExtrusionMoves PrimeTower::generatePaths_inset(const Polygons& outer_poly, coord_t line_width, coord_t initial_inset) { - constexpr coord_t brim_extra_radius = 20000; - constexpr coord_t brim_extra_height = 20000; + const Scene& scene = Application::getInstance().current_slice->scene; + const Settings& mesh_group_settings = scene.current_mesh_group->settings; + + ExtrusionMoves pattern; + + Polygons inset = outer_poly.offset(-(initial_inset + line_width / 2)); + while (! inset.empty()) + { + pattern.polygons.add(inset); + inset = inset.offset(-line_width); + } + + return pattern; +} +void PrimeTower::generatePaths_denseInfill() +{ const Scene& scene = Application::getInstance().current_slice->scene; const Settings& mesh_group_settings = scene.current_mesh_group->settings; const coord_t layer_height = mesh_group_settings.get("layer_height"); + const bool base_enabled = mesh_group_settings.get("prime_tower_brim_enable"); + const coord_t base_extra_radius = scene.settings.get("prime_tower_base_size"); + const coord_t base_height = scene.settings.get("prime_tower_base_height"); + const int magnitude = scene.settings.get("prime_tower_base_curve_magnitude"); pattern_per_extruder.resize(extruder_count); + pattern_extra_brim_per_layer.resize(extruder_count); coord_t cumulative_inset = 0; // Each tower shape is going to be printed inside the other. This is the inset we're doing for each extruder. for (size_t extruder_nr : extruder_order) @@ -173,23 +194,33 @@ void PrimeTower::generatePaths_denseInfill() } } - // Only the most inside extruder needs to fill the inside of the prime tower - if (extruder_nr == extruder_order.front()) + // The most outside extruder is used for the base + if (base_enabled && extruder_nr == extruder_order.front()) { - // Generate the pattern for the first layer. - const coord_t line_width_layer0 = scene.extruders[extruder_nr].settings.get("raft_base_line_width"); - ExtrusionMoves pattern_layer0 = generatePaths_extraBrim(outer_poly, brim_extra_radius, line_width_layer0, true); - pattern_extra_brim_per_layer.push_back(pattern_layer0); - - for (coord_t z = layer_height; z < brim_extra_height; z += layer_height) + for (coord_t z = 0; z < base_height; z += layer_height) { - double brim_radius_factor = std::pow((1.0 - static_cast(z) / brim_extra_height), 4); - coord_t extra_radius = brim_extra_radius * brim_radius_factor; - ExtrusionMoves pattern = generatePaths_extraBrim(outer_poly, extra_radius, line_width, false); - pattern_extra_brim_per_layer.push_back(pattern); + double brim_radius_factor = std::pow((1.0 - static_cast(z) / base_height), magnitude); + coord_t extra_radius = base_extra_radius * brim_radius_factor; + ExtrusionMoves pattern = generatePaths_base(outer_poly, extra_radius, line_width); + if (pattern.polygons.empty() && pattern.lines.empty()) + { + break; + } + pattern_extra_brim_per_layer[extruder_nr].push_back(pattern); } } + cumulative_inset += wall_nr * line_width; + + // Only the most inside extruder needs to fill the inside of the prime tower + if (extruder_nr == extruder_order.back()) + { + ExtrusionMoves pattern = generatePaths_inset(outer_poly, line_width, cumulative_inset); + if (! pattern.polygons.empty() || ! pattern.lines.empty()) + { + pattern_extra_brim_per_layer[extruder_nr].push_back(pattern); + } + } } } @@ -215,7 +246,7 @@ void PrimeTower::addToGcode(const SliceDataStorage& storage, LayerPlan& gcode_la } const LayerIndex layer_nr = gcode_layer.getLayerNr(); - if (/*layer_nr < 0 ||*/ layer_nr > storage.max_print_height_second_to_last_extruder + 1) + if (layer_nr > storage.max_print_height_second_to_last_extruder + 1) { return; } @@ -252,26 +283,30 @@ void PrimeTower::addToGcode(const SliceDataStorage& storage, LayerPlan& gcode_la void PrimeTower::addToGcode_denseInfill(LayerPlan& gcode_layer, const size_t extruder_nr) const { - LayerIndex absolute_layer_number = gcode_layer.getLayerNr() + Raft::getTotalExtraLayers(); - assert(absolute_layer_number >= 0); + const Settings& mesh_group_settings = Application::getInstance().current_slice->scene.current_mesh_group->settings; + const ExtruderTrain& base_train = mesh_group_settings.get("raft_base_extruder_nr"); + const bool adhesion_raft = base_train.settings.get("adhesion_type") == EPlatformAdhesion::RAFT; + LayerIndex absolute_layer_number = gcode_layer.getLayerNr(); + if (adhesion_raft) + { + absolute_layer_number += Raft::getTotalExtraLayers(); + } - if (absolute_layer_number > 0) + if (! adhesion_raft || absolute_layer_number > 0) { // Actual prime pattern const GCodePathConfig& config = gcode_layer.configs_storage.prime_tower_config_per_extruder[extruder_nr]; - const ExtrusionMoves& pattern = pattern_per_extruder[extruder_nr]; gcode_layer.addPolygonsByOptimizer(pattern.polygons, config); gcode_layer.addLinesByOptimizer(pattern.lines, config, SpaceFillType::Lines); } - if (absolute_layer_number < pattern_extra_brim_per_layer.size() && extruder_nr == extruder_order.front()) + const std::vector& pattern_extra_brim = pattern_extra_brim_per_layer[extruder_nr]; + if (absolute_layer_number < pattern_extra_brim.size()) { - // Specific case for first layer => very high adhesion - const GCodePathConfig& config - = absolute_layer_number == 0 ? gcode_layer.configs_storage.raft_base_config : gcode_layer.configs_storage.prime_tower_config_per_extruder[extruder_nr]; - - const ExtrusionMoves& pattern = pattern_extra_brim_per_layer[absolute_layer_number]; + // Extra rings for stronger base + const GCodePathConfig& config = gcode_layer.configs_storage.prime_tower_config_per_extruder[extruder_nr]; + const ExtrusionMoves& pattern = pattern_extra_brim[absolute_layer_number]; gcode_layer.addPolygonsByOptimizer(pattern.polygons, config); gcode_layer.addLinesByOptimizer(pattern.lines, config, SpaceFillType::Lines); } diff --git a/src/SkirtBrim.cpp b/src/SkirtBrim.cpp index 94761b0717..2ec4d932c2 100644 --- a/src/SkirtBrim.cpp +++ b/src/SkirtBrim.cpp @@ -110,39 +110,15 @@ std::vector SkirtBrim::generateBrimOffsetPlan(std::vector SkirtBrim::generatePrimeTowerBrimForSkirtAdhesionOffsetPlan() -{ - std::vector prime_brim_offsets; - - const Settings& global_settings = Application::getInstance().current_slice->scene.current_mesh_group->settings; - const bool prime_tower_brim_enable = global_settings.get("prime_tower_brim_enable"); - if (adhesion_type == EPlatformAdhesion::SKIRT && prime_tower_brim_enable && storage.primeTower.enabled) - { - const int extruder_nr = storage.primeTower.extruder_order[0]; - const ExtruderTrain& extruder = extruders[extruder_nr]; - int line_count = extruder.settings.get("brim_line_count"); - coord_t gap = extruder.settings.get("brim_gap"); - for (int line_idx = 0; line_idx < line_count; line_idx++) - { - const bool is_last = line_idx == line_count - 1; - coord_t offset = gap + line_widths[extruder_nr] / 2 + line_widths[extruder_nr] * line_idx; - prime_brim_offsets.emplace_back(&storage.primeTower.outer_poly, external_polys_only[extruder_nr], offset, offset, line_idx, extruder_nr, is_last); - } - } - - std::sort(prime_brim_offsets.begin(), prime_brim_offsets.end(), OffsetSorter); - return prime_brim_offsets; -} - void SkirtBrim::generate() { std::vector starting_outlines(extruder_count); std::vector all_brim_offsets = generateBrimOffsetPlan(starting_outlines); - std::vector prime_brim_offsets_for_skirt = generatePrimeTowerBrimForSkirtAdhesionOffsetPlan(); constexpr LayerIndex layer_nr = 0; constexpr bool include_support = true; - Polygons covered_area = storage.getLayerOutlines(layer_nr, include_support, /*include_prime_tower*/ true, /*external_polys_only*/ false); + const bool include_prime_tower = adhesion_type == EPlatformAdhesion::SKIRT; + Polygons covered_area = storage.getLayerOutlines(layer_nr, include_support, include_prime_tower, /*external_polys_only*/ false); std::vector allowed_areas_per_extruder(extruder_count); for (int extruder_nr = 0; extruder_nr < extruder_count; extruder_nr++) @@ -161,14 +137,6 @@ void SkirtBrim::generate() } } - // Note that the brim generated here for the prime-tower is _only_ when the rest if the model uses skirt. - // If everything uses brim to begin with, _including_ the prime-tower, it's not generated here, but along the rest. - if (! prime_brim_offsets_for_skirt.empty()) - { - // Note that his ignores the returned lengths: Less 'correct' in a sense, will be predictable for the user. - generatePrimaryBrim(prime_brim_offsets_for_skirt, covered_area, allowed_areas_per_extruder); - } - // Apply 'approximate convex hull' if the adhesion is skirt _after_ any skirt but also prime-tower-brim adhesion. // Otherwise, the now expanded convex hull covered areas will mess with that brim. Fortunately this does not mess // with the other area calculation above, since they are either itself a simple/convex shape or relevant for brim. @@ -406,12 +374,7 @@ Polygons SkirtBrim::getFirstLayerOutline(const int extruder_nr /* = -1 */) if (skirt_around_prime_tower_brim) { - const int prime_tower_brim_extruder_nr = storage.primeTower.extruder_order[0]; - const ExtruderTrain& prime_tower_brim_extruder = extruders[prime_tower_brim_extruder_nr]; - int line_count = prime_tower_brim_extruder.settings.get("brim_line_count"); - coord_t tower_gap = prime_tower_brim_extruder.settings.get("brim_gap"); - coord_t brim_width = tower_gap + line_count * line_widths[prime_tower_brim_extruder_nr]; - first_layer_outline = first_layer_outline.unionPolygons(storage.primeTower.outer_poly.offset(brim_width)); + first_layer_outline = first_layer_outline.unionPolygons(storage.primeTower.footprint); } Polygons shields; @@ -435,7 +398,7 @@ Polygons SkirtBrim::getFirstLayerOutline(const int extruder_nr /* = -1 */) else { // add brim underneath support by removing support where there's brim around the model constexpr bool include_support = false; // Include manually below. - constexpr bool include_prime_tower = false; // Include manually below. + constexpr bool include_prime_tower = false; // Not included. constexpr bool external_outlines_only = false; // Remove manually below. first_layer_outline = storage.getLayerOutlines(layer_nr, include_support, include_prime_tower, external_outlines_only, extruder_nr); first_layer_outline = first_layer_outline.unionPolygons(); // To guard against overlapping outlines, which would produce holes according to the even-odd rule. @@ -480,10 +443,6 @@ Polygons SkirtBrim::getFirstLayerOutline(const int extruder_nr /* = -1 */) first_layer_outline.add(support_layer.support_bottom); first_layer_outline.add(support_layer.support_roof); } - if (storage.primeTower.enabled && global_settings.get("prime_tower_brim_enable") && (extruder_nr == -1 || int(storage.primeTower.extruder_order[0]) == extruder_nr)) - { - first_layer_outline.add(storage.primeTower.outer_poly); // don't remove parts of the prime tower, but make a brim for it - } } constexpr coord_t join_distance = 20; first_layer_outline = first_layer_outline.offset(join_distance).offset(-join_distance); // merge adjacent models into single polygon diff --git a/src/raft.cpp b/src/raft.cpp index 384958afc4..bee9cc643b 100644 --- a/src/raft.cpp +++ b/src/raft.cpp @@ -66,14 +66,14 @@ void Raft::generate(SliceDataStorage& storage) } } - // storage.primeRaftOutline = storage.primeTower.outer_poly.offset(distance, ClipperLib::jtRound); - // NOTE: the raft doesn't take the prime tower brim into account, because it's (currently) not being printed when printing a raft - // if (settings.get("raft_remove_inside_corners")) - //{ - // storage.primeRaftOutline = storage.primeRaftOutline.unionPolygons(storage.raftOutline); - // storage.primeRaftOutline.makeConvex(); - // } - // storage.primeRaftOutline = storage.primeRaftOutline.difference(storage.raftOutline); // In case of overlaps. + const coord_t prime_tower_distance = settings.get("prime_tower_base_size"); + storage.primeRaftOutline = storage.primeTower.outer_poly.offset(prime_tower_distance, ClipperLib::jtRound); + if (settings.get("raft_remove_inside_corners")) + { + storage.primeRaftOutline = storage.primeRaftOutline.unionPolygons(storage.raftOutline); + storage.primeRaftOutline.makeConvex(); + } + storage.primeRaftOutline = storage.primeRaftOutline.difference(storage.raftOutline); // In case of overlaps. } coord_t Raft::getTotalThickness() diff --git a/src/sliceDataStorage.cpp b/src/sliceDataStorage.cpp index 4533fbb8be..e5ba324ccb 100644 --- a/src/sliceDataStorage.cpp +++ b/src/sliceDataStorage.cpp @@ -333,7 +333,14 @@ Polygons { if (primeTower.enabled) { - total.add(primeTower.outer_poly); + if (layer_nr == 0) + { + total.add(primeTower.footprint); + } + else + { + total.add(primeTower.outer_poly); + } } } return total;