Skip to content

Commit

Permalink
Top surface inner outer wall config (#1963)
Browse files Browse the repository at this point in the history
  • Loading branch information
rburema authored Oct 6, 2023
2 parents a8cc7b7 + 08dd09a commit 0a52242
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 4 deletions.
2 changes: 2 additions & 0 deletions include/settings/MeshPathConfigs.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ struct MeshPathConfigs
{
GCodePathConfig inset0_config{};
GCodePathConfig insetX_config{};
GCodePathConfig inset0_roofing_config{};
GCodePathConfig insetX_roofing_config{};
GCodePathConfig bridge_inset0_config{};
GCodePathConfig bridge_insetX_config{};
GCodePathConfig skin_config{};
Expand Down
101 changes: 99 additions & 2 deletions src/FffGcodeWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
#include "utils/math.h"
#include "utils/orderOptimizer.h"

#include <range/v3/view/sliding.hpp>
#include <range/v3/view/transform.hpp>
#include <range/v3/view/zip.hpp>
#include <spdlog/spdlog.h>

Expand Down Expand Up @@ -2392,6 +2394,101 @@ bool FffGcodeWriter::processInsets(
}
else
{
// for layers that (partially) do not have any layers above we apply the roofing configuration
auto use_roofing_config = [&part, &mesh, &gcode_layer]()
{
const auto getOutlineOnLayer = [mesh](const SliceLayerPart& part_here, const LayerIndex layer2_nr) -> Polygons
{
Polygons result;
if (layer2_nr >= static_cast<int>(mesh.layers.size()))
{
return result;
}
const SliceLayer& layer2 = mesh.layers[layer2_nr];
for (const SliceLayerPart& part2 : layer2.parts)
{
if (part_here.boundaryBox.hit(part2.boundaryBox))
{
result.add(part2.outline);
}
}
return result;
};

const auto filled_area_above = [&getOutlineOnLayer, &part, &mesh, &gcode_layer]() -> Polygons
{
const size_t roofing_layer_count = std::min(mesh.settings.get<size_t>("roofing_layer_count"), mesh.settings.get<size_t>("top_layers"));
const bool no_small_gaps_heuristic = mesh.settings.get<bool>("skin_no_small_gaps_heuristic");
const int layer_nr = gcode_layer.getLayerNr();
auto filled_area_above = getOutlineOnLayer(part, layer_nr + roofing_layer_count);
if (! no_small_gaps_heuristic)
{
for (int layer_nr_above = layer_nr + 1; layer_nr_above < layer_nr + roofing_layer_count; layer_nr_above++)
{
Polygons outlines_above = getOutlineOnLayer(part, layer_nr_above);
filled_area_above = filled_area_above.intersection(outlines_above);
}
}
if (layer_nr > 0)
{
// if the skin has air below it then cutting it into regions could cause a region
// to be wholely or partly above air and it may not be printable so restrict
// the regions that have air above (the visible regions) to not include any area that
// has air below (fixes https://github.com/Ultimaker/Cura/issues/2656)

// set air_below to the skin area for the current layer that has air below it
Polygons air_below = getOutlineOnLayer(part, layer_nr).difference(getOutlineOnLayer(part, layer_nr - 1));

if (! air_below.empty())
{
// add the polygons that have air below to the no air above polygons
filled_area_above = filled_area_above.unionPolygons(air_below);
}
}

return filled_area_above;
}();

if (filled_area_above.empty())
{
return true;
}

const auto point_view = ranges::views::transform(
[](auto extrusion_junction)
{
return extrusion_junction.p;
});

for (const auto& path : part.wall_toolpaths)
{
for (const auto& wall : path)
{
for (const auto& p : wall | point_view)
{
if (! filled_area_above.inside(p))
{
return true;
}
}

for (const auto& window : wall | point_view | ranges::views::sliding(2))
{
auto p0 = window[0];
auto p1 = window[1];
if (PolygonUtils::polygonCollidesWithLineSegment(filled_area_above, p0, p1))
{
return true;
}
}
}
}
return false;
}();

const GCodePathConfig& inset0_config = use_roofing_config ? mesh_config.inset0_roofing_config : mesh_config.inset0_config;
const GCodePathConfig& insetX_config = use_roofing_config ? mesh_config.insetX_roofing_config : mesh_config.insetX_config;

// Main case: Optimize the insets with the InsetOrderOptimizer.
const coord_t wall_x_wipe_dist = 0;
const ZSeamConfig z_seam_config(
Expand All @@ -2405,8 +2502,8 @@ bool FffGcodeWriter::processInsets(
gcode_layer,
mesh.settings,
extruder_nr,
mesh_config.inset0_config,
mesh_config.insetX_config,
inset0_config,
insetX_config,
mesh_config.bridge_inset0_config,
mesh_config.bridge_insetX_config,
mesh.settings.get<bool>("travel_retract_before_outer_wall"),
Expand Down
20 changes: 20 additions & 0 deletions src/settings/MeshPathConfigs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,26 @@ MeshPathConfigs::MeshPathConfigs(const SliceMeshStorage& mesh, const coord_t lay
.speed_derivatives = { .speed = mesh.settings.get<Velocity>("speed_wall_x"),
.acceleration = mesh.settings.get<Acceleration>("acceleration_wall_x"),
.jerk = mesh.settings.get<Velocity>("jerk_wall_x") } }
, inset0_roofing_config{ .type = PrintFeatureType::OuterWall,
.line_width = static_cast<coord_t>(
mesh.settings.get<coord_t>("wall_line_width_0")
* line_width_factor_per_extruder[mesh.settings.get<ExtruderTrain&>("wall_0_extruder_nr").extruder_nr]),
.layer_thickness = layer_thickness,
.flow
= mesh.settings.get<Ratio>("wall_0_material_flow_roofing") * (layer_nr == 0 ? mesh.settings.get<Ratio>("wall_0_material_flow_layer_0") : Ratio{ 1.0 }),
.speed_derivatives = { .speed = mesh.settings.get<Velocity>("speed_wall_0_roofing"),
.acceleration = mesh.settings.get<Acceleration>("acceleration_wall_0_roofing"),
.jerk = mesh.settings.get<Velocity>("jerk_wall_0_roofing") } }
, insetX_roofing_config{ .type = PrintFeatureType::OuterWall,
.line_width = static_cast<coord_t>(
mesh.settings.get<coord_t>("wall_line_width_x")
* line_width_factor_per_extruder[mesh.settings.get<ExtruderTrain&>("wall_x_extruder_nr").extruder_nr]),
.layer_thickness = layer_thickness,
.flow
= mesh.settings.get<Ratio>("wall_x_material_flow_roofing") * (layer_nr == 0 ? mesh.settings.get<Ratio>("wall_x_material_flow_layer_0") : Ratio{ 1.0 }),
.speed_derivatives = { .speed = mesh.settings.get<Velocity>("speed_wall_x_roofing"),
.acceleration = mesh.settings.get<Acceleration>("acceleration_wall_x_roofing"),
.jerk = mesh.settings.get<Velocity>("jerk_wall_x_roofing") } }
, bridge_inset0_config{ .type = PrintFeatureType::OuterWall,
.line_width = static_cast<coord_t>(
mesh.settings.get<coord_t>("wall_line_width_0")
Expand Down
2 changes: 0 additions & 2 deletions src/skin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -346,8 +346,6 @@ void SkinInfillAreaComputation::generateRoofingFillAndSkinFill(SliceLayerPart& p
*/
Polygons SkinInfillAreaComputation::generateFilledAreaAbove(SliceLayerPart& part, size_t roofing_layer_count)
{
const size_t wall_idx = std::min(size_t(2), mesh.settings.get<size_t>("wall_line_count"));

Polygons filled_area_above = getOutlineOnLayer(part, layer_nr + roofing_layer_count);
if (! no_small_gaps_heuristic)
{
Expand Down

0 comments on commit 0a52242

Please sign in to comment.