mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-12 20:39:00 +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;
|
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 expand_merge_surfaces(
|
||||||
Surfaces &surfaces,
|
Surfaces &surfaces,
|
||||||
SurfaceType surface_type,
|
SurfaceType surface_type,
|
||||||
ExPolygons &shells,
|
std::vector<ExpansionZone>& expansion_zones,
|
||||||
const Algorithm::RegionExpansionParameters &expansion_params_into_solid_infill,
|
const float closing_radius,
|
||||||
ExPolygons &sparse,
|
const double bridge_angle
|
||||||
const Algorithm::RegionExpansionParameters &expansion_params_into_sparse_infill,
|
)
|
||||||
const float closing_radius,
|
|
||||||
const double bridge_angle = -1.)
|
|
||||||
{
|
{
|
||||||
using namespace Slic3r::Algorithm;
|
using namespace Slic3r::Algorithm;
|
||||||
|
|
||||||
@ -454,17 +450,17 @@ Surfaces expand_merge_surfaces(
|
|||||||
if (src.empty())
|
if (src.empty())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
std::vector<RegionExpansion> expansions = propagate_waves(src, shells, expansion_params_into_solid_infill);
|
unsigned processed_expolygons_count = 0;
|
||||||
bool expanded_into_shells = !expansions.empty();
|
std::vector<RegionExpansion> expansions;
|
||||||
bool expanded_into_sparse = false;
|
for (ExpansionZone& expansion_zone : expansion_zones) {
|
||||||
{
|
std::vector<RegionExpansion> zone_expansions = propagate_waves(src, expansion_zone.expolygons, expansion_zone.parameters);
|
||||||
std::vector<RegionExpansion> expansions2 = propagate_waves(src, sparse, expansion_params_into_sparse_infill);
|
expansion_zone.expanded_into = !zone_expansions.empty();
|
||||||
if (! expansions2.empty()) {
|
|
||||||
expanded_into_sparse = true;
|
for (RegionExpansion &expansion : zone_expansions)
|
||||||
for (RegionExpansion &expansion : expansions2)
|
expansion.boundary_id += processed_expolygons_count;
|
||||||
expansion.boundary_id += uint32_t(shells.size());
|
|
||||||
append(expansions, std::move(expansions2));
|
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));
|
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.
|
// 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.
|
// look for narrow_ensure_vertical_wall_thickness_region_radius filter.
|
||||||
expanded = closing_ex(expanded, closing_radius);
|
expanded = closing_ex(expanded, closing_radius);
|
||||||
// Trim the shells by the expanded expolygons.
|
// Trim the zones by the expanded expolygons.
|
||||||
if (expanded_into_shells)
|
for (ExpansionZone& expansion_zone : expansion_zones)
|
||||||
shells = diff_ex(shells, expanded);
|
if (expansion_zone.expanded_into)
|
||||||
if (expanded_into_sparse)
|
expansion_zone.expolygons = diff_ex(expansion_zone.expolygons, expanded);
|
||||||
sparse = diff_ex(sparse, expanded);
|
|
||||||
|
|
||||||
Surface templ{ surface_type, {} };
|
Surface templ{ surface_type, {} };
|
||||||
templ.bridge_angle = bridge_angle;
|
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;
|
BOOST_LOG_TRIVIAL(trace) << "Processing external surface, detecting bridges. layer" << this->layer()->print_z;
|
||||||
const double custom_angle = this->region().config().bridge_angle.value;
|
const double custom_angle = this->region().config().bridge_angle.value;
|
||||||
bridges.surfaces = custom_angle > 0 ?
|
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);
|
expand_bridges_detect_orientations(m_fill_surfaces.surfaces, expansion_zones, closing_radius);
|
||||||
BOOST_LOG_TRIVIAL(trace) << "Processing external surface, detecting bridges - done";
|
BOOST_LOG_TRIVIAL(trace) << "Processing external surface, detecting bridges - done";
|
||||||
#if 0
|
#if 0
|
||||||
@ -549,16 +544,18 @@ void LayerRegion::process_external_surfaces(const Layer *lower_layer, const Poly
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
Surfaces bottoms = expand_merge_surfaces(m_fill_surfaces.surfaces, stBottom, expansion_zones[0].expolygons,
|
expansion_zones.at(0).parameters = RegionExpansionParameters::build(expansion_bottom, expansion_step, max_nr_expansion_steps);
|
||||||
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[1].expolygons, expansion_params_into_sparse_infill, closing_radius);
|
|
||||||
Surfaces tops = expand_merge_surfaces(m_fill_surfaces.surfaces, stTop, expansion_zones[0].expolygons,
|
expansion_zones.at(0).parameters = RegionExpansionParameters::build(expansion_top, expansion_step, max_nr_expansion_steps);
|
||||||
RegionExpansionParameters::build(expansion_top, expansion_step, max_nr_expansion_steps),
|
Surfaces tops = expand_merge_surfaces(m_fill_surfaces.surfaces, stTop, expansion_zones, closing_radius);
|
||||||
expansion_zones[1].expolygons, expansion_params_into_sparse_infill, closing_radius);
|
|
||||||
|
|
||||||
// m_fill_surfaces.remove_types({ stBottomBridge, stBottom, stTop, stInternal, stInternalSolid });
|
// m_fill_surfaces.remove_types({ stBottomBridge, stBottom, stTop, stInternal, stInternalSolid });
|
||||||
m_fill_surfaces.clear();
|
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, {});
|
Surface solid_templ(stInternalSolid, {});
|
||||||
solid_templ.thickness = layer_thickness;
|
solid_templ.thickness = layer_thickness;
|
||||||
|
@ -173,6 +173,18 @@ Surfaces expand_bridges_detect_orientations(
|
|||||||
const float closing_radius
|
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_
|
#endif // slic3r_LayerRegion_hpp_
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
#include "libslic3r/ClipperUtils.hpp"
|
#include "libslic3r/ClipperUtils.hpp"
|
||||||
|
#include "libslic3r/Geometry.hpp"
|
||||||
#include "libslic3r/Point.hpp"
|
#include "libslic3r/Point.hpp"
|
||||||
#include "libslic3r/SVG.hpp"
|
#include "libslic3r/SVG.hpp"
|
||||||
#include <catch2/catch.hpp>
|
#include <catch2/catch.hpp>
|
||||||
#include <libslic3r/LayerRegion.hpp>
|
#include <libslic3r/LayerRegion.hpp>
|
||||||
|
|
||||||
using namespace Slic3r;
|
using namespace Slic3r;
|
||||||
|
using namespace Slic3r::Algorithm;
|
||||||
|
|
||||||
constexpr bool export_svgs = true;
|
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]") {
|
struct LayerRegionFixture {
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("test the bridge expansion with the bridge angle detection", "[LayerRegion]") {
|
|
||||||
using namespace Slic3r::Algorithm;
|
|
||||||
Surfaces surfaces{
|
Surfaces surfaces{
|
||||||
Surface{
|
Surface{
|
||||||
stBottomBridge,
|
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;
|
static constexpr const size_t max_nr_expansion_steps = 5;
|
||||||
const float closing_radius = 0.55f * 0.65f * 1.05f * scaled_spacing;
|
const float closing_radius = 0.55f * 0.65f * 1.05f * scaled_spacing;
|
||||||
const int shells_expansion_depth = scaled(0.6);
|
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,
|
shells_expansion_depth,
|
||||||
expansion_step,
|
expansion_step,
|
||||||
max_nr_expansion_steps
|
max_nr_expansion_steps
|
||||||
);
|
);
|
||||||
const int sparse_expansion_depth = scaled(0.3);
|
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,
|
sparse_expansion_depth,
|
||||||
expansion_step,
|
expansion_step,
|
||||||
max_nr_expansion_steps
|
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,
|
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 result{expand_bridges_detect_orientations(
|
||||||
surfaces,
|
surfaces,
|
||||||
expansion_zones,
|
expansion_zones,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user