mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-12 12:09:02 +08:00
Refactor: expand_merge_surfaces now uses expansion_zones.
This enables addition of other expansion zones in the future. For example to make sure bridges are anchored properly even if there is top fill next to them.
This commit is contained in:
parent
4d0bae1d3f
commit
bb2186cbcf
@ -435,17 +435,13 @@ Surfaces expand_bridges_detect_orientations(
|
||||
return out;
|
||||
}
|
||||
|
||||
// Extract bridging surfaces from "surfaces", expand them into "shells" using expansion_params.
|
||||
// Trim "shells" by the expanded bridges.
|
||||
Surfaces expand_merge_surfaces(
|
||||
Surfaces &surfaces,
|
||||
SurfaceType surface_type,
|
||||
ExPolygons &shells,
|
||||
const Algorithm::RegionExpansionParameters &expansion_params_into_solid_infill,
|
||||
ExPolygons &sparse,
|
||||
const Algorithm::RegionExpansionParameters &expansion_params_into_sparse_infill,
|
||||
const float closing_radius,
|
||||
const double bridge_angle = -1.)
|
||||
Surfaces &surfaces,
|
||||
SurfaceType surface_type,
|
||||
std::vector<ExpansionZone>& expansion_zones,
|
||||
const float closing_radius,
|
||||
const double bridge_angle
|
||||
)
|
||||
{
|
||||
using namespace Slic3r::Algorithm;
|
||||
|
||||
@ -454,17 +450,17 @@ Surfaces expand_merge_surfaces(
|
||||
if (src.empty())
|
||||
return {};
|
||||
|
||||
std::vector<RegionExpansion> expansions = propagate_waves(src, shells, expansion_params_into_solid_infill);
|
||||
bool expanded_into_shells = !expansions.empty();
|
||||
bool expanded_into_sparse = false;
|
||||
{
|
||||
std::vector<RegionExpansion> expansions2 = propagate_waves(src, sparse, expansion_params_into_sparse_infill);
|
||||
if (! expansions2.empty()) {
|
||||
expanded_into_sparse = true;
|
||||
for (RegionExpansion &expansion : expansions2)
|
||||
expansion.boundary_id += uint32_t(shells.size());
|
||||
append(expansions, std::move(expansions2));
|
||||
}
|
||||
unsigned processed_expolygons_count = 0;
|
||||
std::vector<RegionExpansion> expansions;
|
||||
for (ExpansionZone& expansion_zone : expansion_zones) {
|
||||
std::vector<RegionExpansion> zone_expansions = propagate_waves(src, expansion_zone.expolygons, expansion_zone.parameters);
|
||||
expansion_zone.expanded_into = !zone_expansions.empty();
|
||||
|
||||
for (RegionExpansion &expansion : zone_expansions)
|
||||
expansion.boundary_id += processed_expolygons_count;
|
||||
|
||||
processed_expolygons_count += expansion_zone.expolygons.size();
|
||||
append(expansions, std::move(zone_expansions));
|
||||
}
|
||||
|
||||
std::vector<ExPolygon> expanded = merge_expansions_into_expolygons(std::move(src), std::move(expansions));
|
||||
@ -472,11 +468,10 @@ Surfaces expand_merge_surfaces(
|
||||
// without the following closing operation, those regions will stay unfilled and cause small holes in the expanded surface.
|
||||
// look for narrow_ensure_vertical_wall_thickness_region_radius filter.
|
||||
expanded = closing_ex(expanded, closing_radius);
|
||||
// Trim the shells by the expanded expolygons.
|
||||
if (expanded_into_shells)
|
||||
shells = diff_ex(shells, expanded);
|
||||
if (expanded_into_sparse)
|
||||
sparse = diff_ex(sparse, expanded);
|
||||
// Trim the zones by the expanded expolygons.
|
||||
for (ExpansionZone& expansion_zone : expansion_zones)
|
||||
if (expansion_zone.expanded_into)
|
||||
expansion_zone.expolygons = diff_ex(expansion_zone.expolygons, expanded);
|
||||
|
||||
Surface templ{ surface_type, {} };
|
||||
templ.bridge_angle = bridge_angle;
|
||||
@ -538,7 +533,7 @@ void LayerRegion::process_external_surfaces(const Layer *lower_layer, const Poly
|
||||
BOOST_LOG_TRIVIAL(trace) << "Processing external surface, detecting bridges. layer" << this->layer()->print_z;
|
||||
const double custom_angle = this->region().config().bridge_angle.value;
|
||||
bridges.surfaces = custom_angle > 0 ?
|
||||
expand_merge_surfaces(m_fill_surfaces.surfaces, stBottomBridge, expansion_zones[0].expolygons, expansion_params_into_solid_infill, expansion_zones[1].expolygons, expansion_params_into_sparse_infill, closing_radius, Geometry::deg2rad(custom_angle)) :
|
||||
expand_merge_surfaces(m_fill_surfaces.surfaces, stBottomBridge, expansion_zones, closing_radius, Geometry::deg2rad(custom_angle)) :
|
||||
expand_bridges_detect_orientations(m_fill_surfaces.surfaces, expansion_zones, closing_radius);
|
||||
BOOST_LOG_TRIVIAL(trace) << "Processing external surface, detecting bridges - done";
|
||||
#if 0
|
||||
@ -549,16 +544,18 @@ void LayerRegion::process_external_surfaces(const Layer *lower_layer, const Poly
|
||||
#endif
|
||||
}
|
||||
|
||||
Surfaces bottoms = expand_merge_surfaces(m_fill_surfaces.surfaces, stBottom, expansion_zones[0].expolygons,
|
||||
RegionExpansionParameters::build(expansion_bottom, expansion_step, max_nr_expansion_steps),
|
||||
expansion_zones[1].expolygons, expansion_params_into_sparse_infill, closing_radius);
|
||||
Surfaces tops = expand_merge_surfaces(m_fill_surfaces.surfaces, stTop, expansion_zones[0].expolygons,
|
||||
RegionExpansionParameters::build(expansion_top, expansion_step, max_nr_expansion_steps),
|
||||
expansion_zones[1].expolygons, expansion_params_into_sparse_infill, closing_radius);
|
||||
expansion_zones.at(0).parameters = RegionExpansionParameters::build(expansion_bottom, expansion_step, max_nr_expansion_steps);
|
||||
Surfaces bottoms = expand_merge_surfaces(m_fill_surfaces.surfaces, stBottom, expansion_zones, closing_radius);
|
||||
|
||||
expansion_zones.at(0).parameters = RegionExpansionParameters::build(expansion_top, expansion_step, max_nr_expansion_steps);
|
||||
Surfaces tops = expand_merge_surfaces(m_fill_surfaces.surfaces, stTop, expansion_zones, closing_radius);
|
||||
|
||||
// m_fill_surfaces.remove_types({ stBottomBridge, stBottom, stTop, stInternal, stInternalSolid });
|
||||
m_fill_surfaces.clear();
|
||||
reserve_more(m_fill_surfaces.surfaces, expansion_zones[0].expolygons.size() + expansion_zones[1].expolygons.size() + bridges.size() + bottoms.size() + tops.size());
|
||||
unsigned zones_expolygons_count = 0;
|
||||
for (const ExpansionZone& zone : expansion_zones)
|
||||
zones_expolygons_count += zone.expolygons.size();
|
||||
reserve_more(m_fill_surfaces.surfaces, zones_expolygons_count + bridges.size() + bottoms.size() + tops.size());
|
||||
{
|
||||
Surface solid_templ(stInternalSolid, {});
|
||||
solid_templ.thickness = layer_thickness;
|
||||
|
@ -173,6 +173,18 @@ Surfaces expand_bridges_detect_orientations(
|
||||
const float closing_radius
|
||||
);
|
||||
|
||||
/**
|
||||
* Extract bridging surfaces from "surfaces", expand them into "shells" using expansion_params.
|
||||
* Trim "shells" by the expanded bridges.
|
||||
*/
|
||||
Surfaces expand_merge_surfaces(
|
||||
Surfaces &surfaces,
|
||||
SurfaceType surface_type,
|
||||
std::vector<ExpansionZone>& expansion_zones,
|
||||
const float closing_radius,
|
||||
const double bridge_angle = -1
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
#endif // slic3r_LayerRegion_hpp_
|
||||
|
@ -1,10 +1,12 @@
|
||||
#include "libslic3r/ClipperUtils.hpp"
|
||||
#include "libslic3r/Geometry.hpp"
|
||||
#include "libslic3r/Point.hpp"
|
||||
#include "libslic3r/SVG.hpp"
|
||||
#include <catch2/catch.hpp>
|
||||
#include <libslic3r/LayerRegion.hpp>
|
||||
|
||||
using namespace Slic3r;
|
||||
using namespace Slic3r::Algorithm;
|
||||
|
||||
constexpr bool export_svgs = true;
|
||||
|
||||
@ -17,11 +19,7 @@ ExPolygon rectangle(const Point& origin, const int width, const int height) {
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE("test the surface expansion", "[LayerRegion]") {
|
||||
}
|
||||
|
||||
TEST_CASE("test the bridge expansion with the bridge angle detection", "[LayerRegion]") {
|
||||
using namespace Slic3r::Algorithm;
|
||||
struct LayerRegionFixture {
|
||||
Surfaces surfaces{
|
||||
Surface{
|
||||
stBottomBridge,
|
||||
@ -50,13 +48,13 @@ TEST_CASE("test the bridge expansion with the bridge angle detection", "[LayerRe
|
||||
static constexpr const size_t max_nr_expansion_steps = 5;
|
||||
const float closing_radius = 0.55f * 0.65f * 1.05f * scaled_spacing;
|
||||
const int shells_expansion_depth = scaled(0.6);
|
||||
const auto expansion_params_into_solid_infill = RegionExpansionParameters::build(
|
||||
const RegionExpansionParameters expansion_params_into_solid_infill = RegionExpansionParameters::build(
|
||||
shells_expansion_depth,
|
||||
expansion_step,
|
||||
max_nr_expansion_steps
|
||||
);
|
||||
const int sparse_expansion_depth = scaled(0.3);
|
||||
const auto expansion_params_into_sparse_infill = RegionExpansionParameters::build(
|
||||
const RegionExpansionParameters expansion_params_into_sparse_infill = RegionExpansionParameters::build(
|
||||
sparse_expansion_depth,
|
||||
expansion_step,
|
||||
max_nr_expansion_steps
|
||||
@ -72,7 +70,48 @@ TEST_CASE("test the bridge expansion with the bridge angle detection", "[LayerRe
|
||||
expansion_params_into_sparse_infill,
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
TEST_CASE_METHOD(LayerRegionFixture, "test the surface expansion", "[LayerRegion]") {
|
||||
float custom_angle = 1.234;
|
||||
|
||||
Surfaces result{expand_merge_surfaces(
|
||||
surfaces, stBottomBridge,
|
||||
expansion_zones,
|
||||
closing_radius,
|
||||
custom_angle
|
||||
)};
|
||||
|
||||
if constexpr (export_svgs) {
|
||||
SVG svg("general_expansion.svg", BoundingBox{
|
||||
Point{scaled(-3.0), scaled(-1.0)},
|
||||
Point{scaled(2.0), scaled(2.0)}
|
||||
});
|
||||
|
||||
svg.draw(surfaces, "blue");
|
||||
svg.draw(expansion_zones[0].expolygons, "green");
|
||||
svg.draw(expansion_zones[1].expolygons, "red");
|
||||
svg.draw_outline(result, "black", "", scale_(0.01));
|
||||
}
|
||||
|
||||
REQUIRE(result.size() == 2);
|
||||
CHECK(result.at(0).bridge_angle == Approx(custom_angle));
|
||||
CHECK(result.at(1).bridge_angle == Approx(custom_angle));
|
||||
CHECK(result.at(0).expolygon.contour.size() == 22);
|
||||
CHECK(result.at(1).expolygon.contour.size() == 14);
|
||||
|
||||
// These lines in the polygons should correspond to the expansion depth.
|
||||
CHECK(result.at(0).expolygon.contour.lines().at(2).length() == shells_expansion_depth);
|
||||
CHECK(result.at(1).expolygon.contour.lines().at(7).length() == sparse_expansion_depth);
|
||||
CHECK(result.at(1).expolygon.contour.lines().at(11).length() == sparse_expansion_depth);
|
||||
|
||||
CHECK(intersection_ex({result.at(0).expolygon}, expansion_zones[0].expolygons).size() == 0);
|
||||
CHECK(intersection_ex({result.at(0).expolygon}, expansion_zones[1].expolygons).size() == 0);
|
||||
CHECK(intersection_ex({result.at(1).expolygon}, expansion_zones[0].expolygons).size() == 0);
|
||||
CHECK(intersection_ex({result.at(1).expolygon}, expansion_zones[1].expolygons).size() == 0);
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(LayerRegionFixture, "test the bridge expansion with the bridge angle detection", "[LayerRegion]") {
|
||||
Surfaces result{expand_bridges_detect_orientations(
|
||||
surfaces,
|
||||
expansion_zones,
|
||||
|
Loading…
x
Reference in New Issue
Block a user