Skip to content
Draft
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions include/FffGcodeWriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -562,7 +562,7 @@ class FffGcodeWriter : public NoCopy
* \param mesh The mesh for which to add to the layer plan \p gcode_layer.
* \param extruder_nr The extruder for which to print all features of the mesh which should be printed with this extruder
* \param mesh_config the line config with which to print a print feature
* \param skin_part The skin part for which to create gcode
* \param skin_fill The shape of the skin for which to create gcode
* \param[out] added_something Whether this function added anything to the layer plan
*/
void processTopBottom(
Expand All @@ -571,7 +571,7 @@ class FffGcodeWriter : public NoCopy
const SliceMeshStorage& mesh,
const size_t extruder_nr,
const MeshPathConfigs& mesh_config,
const SkinPart& skin_part,
const Shape& skin_fill,
bool& added_something) const;

/*!
Expand Down
9 changes: 9 additions & 0 deletions include/utils/polygonUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,15 @@ class PolygonUtils
*/
static Shape clipPolygonWithAABB(const Shape& src, const AABB& aabb);

/*!
* Merges all parts of a smaller area with a bigger area whenever the smaller area is thinner (w.r.t. a given maximum width) than the larger one.
* This is done in-place as much as possible (hence no return value)!
* \param max_dist The width below which an area is considered 'too thin'.
* \param assume_bigger The area which functions as the bigger area that is merged _to_. Will be altered!
* \param assume_smaller The area which functions as the smaller area that is merged _from_. Will be altered!
*/
static void mergeThinOverlap(const coord_t max_dist, Shape& assume_bigger, Shape& assume_smaller);

/*!
* Generate a few outset circles around a base, according to the given line width
*
Expand Down
61 changes: 32 additions & 29 deletions src/FffGcodeWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3140,27 +3140,30 @@ bool FffGcodeWriter::processSkinPart(
const SkinPart& skin_part) const
{
bool added_something = false;
processRoofingFlooring(
storage,
gcode_layer,
mesh,
extruder_nr,
roofing_settings_names,
skin_part.roofing_fill,
mesh_config.roofing_config,
mesh.roofing_angles,
added_something);
processRoofingFlooring(
storage,
gcode_layer,
mesh,
extruder_nr,
flooring_settings_names,
skin_part.flooring_fill,
mesh_config.flooring_config,
mesh.flooring_angles,
added_something);
processTopBottom(storage, gcode_layer, mesh, extruder_nr, mesh_config, skin_part, added_something);

const coord_t decimate_roofing_flooring_distance = mesh.settings.get<coord_t>("top_bottom_skin_merge_distance");
Shape skin_fill = skin_part.skin_fill;
Shape roofing_fill = skin_part.roofing_fill;
Shape flooring_fill = skin_part.flooring_fill;
if (decimate_roofing_flooring_distance > 0)
{
// For each of these, have flooring take precedence over roofing;
// while roofing is likely visually more pleasing, the flooring settings are probably more important for structural integrity.
Comment thread
rburema marked this conversation as resolved.
Outdated

// First, if there _is_ a situation where skin is thinner than flooring/roofing, we probably want that merged into either of those instead of the other way around.
PolygonUtils::mergeThinOverlap(decimate_roofing_flooring_distance, flooring_fill, skin_fill);
PolygonUtils::mergeThinOverlap(decimate_roofing_flooring_distance, roofing_fill, skin_fill);
// Then, the less likely scenario that flooring and roofing are both present, next to each other, and one is far thinner than the other.
PolygonUtils::mergeThinOverlap(decimate_roofing_flooring_distance, flooring_fill, roofing_fill);
PolygonUtils::mergeThinOverlap(decimate_roofing_flooring_distance, roofing_fill, flooring_fill);
// Lastly, the most likely scenario, where flooring/roofing is thinner than skin (even after merging as much as possible into either), merge into skin.
PolygonUtils::mergeThinOverlap(decimate_roofing_flooring_distance, skin_fill, flooring_fill);
PolygonUtils::mergeThinOverlap(decimate_roofing_flooring_distance, skin_fill, roofing_fill);
}

processRoofingFlooring(storage, gcode_layer, mesh, extruder_nr, roofing_settings_names, roofing_fill, mesh_config.roofing_config, mesh.roofing_angles, added_something);
processRoofingFlooring(storage, gcode_layer, mesh, extruder_nr, flooring_settings_names, flooring_fill, mesh_config.flooring_config, mesh.flooring_angles, added_something);
processTopBottom(storage, gcode_layer, mesh, extruder_nr, mesh_config, skin_fill, added_something);
return added_something;
}

Expand Down Expand Up @@ -3214,10 +3217,10 @@ void FffGcodeWriter::processTopBottom(
const SliceMeshStorage& mesh,
const size_t extruder_nr,
const MeshPathConfigs& mesh_config,
const SkinPart& skin_part,
const Shape& skin_fill,
bool& added_something) const
{
if (skin_part.skin_fill.empty())
if (skin_fill.empty())
{
return; // bridgeAngle requires a non-empty skin_fill.
}
Expand Down Expand Up @@ -3272,9 +3275,9 @@ void FffGcodeWriter::processTopBottom(

Shape supported_skin_part_regions;

const std::optional<AngleDegrees> bridge_angle = bridgeAngle(mesh, skin_part.skin_fill, storage, layer_nr, bridge_layer, support_layer, supported_skin_part_regions);
const std::optional<AngleDegrees> bridge_angle = bridgeAngle(mesh, skin_fill, storage, layer_nr, bridge_layer, support_layer, supported_skin_part_regions);

if (bridge_angle.has_value() || (support_threshold > 0 && (supported_skin_part_regions.area() / (skin_part.skin_fill.area() + 1) < support_threshold)))
if (bridge_angle.has_value() || (support_threshold > 0 && (supported_skin_part_regions.area() / (skin_fill.area() + 1) < support_threshold)))
{
if (bridge_angle.has_value())
{
Expand Down Expand Up @@ -3338,7 +3341,7 @@ void FffGcodeWriter::processTopBottom(
{
// skin isn't a bridge but is it above support and we need to modify the fan speed?

AABB skin_bb(skin_part.skin_fill);
AABB skin_bb(skin_fill);

support_layer = &storage.support.supportLayers[support_layer_nr];

Expand All @@ -3349,7 +3352,7 @@ void FffGcodeWriter::processTopBottom(
AABB support_roof_bb(support_layer->support_roof);
if (skin_bb.hit(support_roof_bb))
{
supported = ! skin_part.skin_fill.intersection(support_layer->support_roof).empty();
supported = ! skin_fill.intersection(support_layer->support_roof).empty();
}
}
else
Expand All @@ -3359,7 +3362,7 @@ void FffGcodeWriter::processTopBottom(
AABB support_part_bb(support_part.getInfillArea());
if (skin_bb.hit(support_part_bb))
{
supported = ! skin_part.skin_fill.intersection(support_part.getInfillArea()).empty();
supported = ! skin_fill.intersection(support_part.getInfillArea()).empty();

if (supported)
{
Expand Down Expand Up @@ -3395,7 +3398,7 @@ void FffGcodeWriter::processTopBottom(
gcode_layer,
mesh,
extruder_nr,
skin_part.skin_fill,
skin_fill,
*skin_config,
pattern,
skin_angle,
Expand Down
14 changes: 14 additions & 0 deletions src/utils/polygonUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1518,6 +1518,20 @@ Shape PolygonUtils::clipPolygonWithAABB(const Shape& src, const AABB& aabb)
return out;
}

void PolygonUtils::mergeThinOverlap(const coord_t max_dist, Shape& assume_bigger, Shape& assume_smaller)
{
if (assume_bigger.area() == 0.0 || assume_smaller.area() == 0.0)
Comment thread
rburema marked this conversation as resolved.
Outdated
{
return;
}
const auto result_smaller = assume_smaller // Of the (supposedly) smaller area,
.difference(assume_bigger.offset(max_dist)) // take the difference with an offset of the bigger area,
.offset(max_dist) // then 'inflate' any leftover pieces (so, ones that are certainly big enough),
.intersection(assume_smaller); // and lastly intersect with the original area, so we don't go outside those bounds.
assume_bigger = assume_bigger.unionPolygons(assume_smaller.difference(result_smaller).offset(EPSILON)); // Glue any 'not leftover' pieces to the (supposedly) bigger area.
assume_smaller = result_smaller;
}

std::tuple<ClosedLinesSet, coord_t>
PolygonUtils::generateCirculatOutset(const Point2LL& center, const coord_t inner_radius, const coord_t outer_radius, coord_t line_width, const size_t circle_definition)
{
Expand Down
Loading