WIP: Layers split into islands, islands overlapping in Z interconnected

into a graph with links to the layer above / below.

In addition:
Members of LayerRegion were made private, public interface const only.
this->m_xxx replaced with just m_xxx
SurfacesPtr was made a vector of const pointers.
This commit is contained in:
Vojtech Bubnik 2022-10-26 18:41:39 +02:00
parent f57744ad12
commit ee626eb65a
39 changed files with 751 additions and 356 deletions

View file

@ -43,30 +43,26 @@ Flow LayerRegion::bridging_flow(FlowRole role) const
}
}
// Fill in layerm->fill_surfaces by trimming the layerm->slices by the cummulative layerm->fill_surfaces.
// Fill in layerm->fill_surfaces by trimming the layerm->slices by layerm->fill_expolygons.
void LayerRegion::slices_to_fill_surfaces_clipped()
{
// Note: this method should be idempotent, but fill_surfaces gets modified
// in place. However we're now only using its boundaries (which are invariant)
// so we're safe. This guarantees idempotence of prepare_infill() also in case
// that combine_infill() turns some fill_surface into VOID surfaces.
// Collect polygons per surface type.
std::array<SurfacesPtr, size_t(stCount)> by_surface;
for (Surface &surface : this->slices.surfaces)
std::array<std::vector<const Surface*>, size_t(stCount)> by_surface;
for (const Surface &surface : this->slices())
by_surface[size_t(surface.surface_type)].emplace_back(&surface);
// Trim surfaces by the fill_boundaries.
this->fill_surfaces.surfaces.clear();
m_fill_surfaces.surfaces.clear();
for (size_t surface_type = 0; surface_type < size_t(stCount); ++ surface_type) {
const SurfacesPtr &this_surfaces = by_surface[surface_type];
const std::vector<const Surface*> &this_surfaces = by_surface[surface_type];
if (! this_surfaces.empty())
this->fill_surfaces.append(intersection_ex(this_surfaces, this->fill_expolygons), SurfaceType(surface_type));
m_fill_surfaces.append(intersection_ex(this_surfaces, this->fill_expolygons()), SurfaceType(surface_type));
}
}
void LayerRegion::make_perimeters(const SurfaceCollection &slices, SurfaceCollection* fill_surfaces)
{
this->perimeters.clear();
this->thin_fills.clear();
m_perimeters.clear();
m_thin_fills.clear();
const PrintConfig &print_config = this->layer()->object()->print()->config();
const PrintRegionConfig &region_config = this->region().config();
@ -87,8 +83,8 @@ void LayerRegion::make_perimeters(const SurfaceCollection &slices, SurfaceCollec
spiral_vase,
// output:
&this->perimeters,
&this->thin_fills,
&m_perimeters,
&m_thin_fills,
fill_surfaces
);
@ -131,7 +127,7 @@ void LayerRegion::process_external_surfaces(const Layer *lower_layer, const Poly
// Internal surfaces, not grown.
Surfaces internal;
// Areas, where an infill of various types (top, bottom, bottom bride, sparse, void) could be placed.
Polygons fill_boundaries = to_polygons(this->fill_expolygons);
Polygons fill_boundaries = to_polygons(this->fill_expolygons());
Polygons lower_layer_covered_tmp;
// Collect top surfaces and internal surfaces.
@ -141,7 +137,7 @@ void LayerRegion::process_external_surfaces(const Layer *lower_layer, const Poly
{
// Voids are sparse infills if infill rate is zero.
Polygons voids;
for (const Surface &surface : this->fill_surfaces.surfaces) {
for (const Surface &surface : this->fill_surfaces()) {
if (surface.is_top()) {
// Collect the top surfaces, inflate them and trim them by the bottom surfaces.
// This gives the priority to bottom surfaces.
@ -292,7 +288,7 @@ void LayerRegion::process_external_surfaces(const Layer *lower_layer, const Poly
bridges[idx_last].bridge_angle = bd.angle;
if (this->layer()->object()->has_support()) {
// polygons_append(this->bridged, bd.coverage());
append(this->unsupported_bridge_edges, bd.unsupported_edges());
append(m_unsupported_bridge_edges, bd.unsupported_edges());
}
} else if (custom_angle > 0) {
// Bridge was not detected (likely it is only supported at one side). Still it is a surface filled in
@ -365,7 +361,7 @@ void LayerRegion::process_external_surfaces(const Layer *lower_layer, const Poly
surfaces_append(new_surfaces, std::move(new_expolys), s1);
}
this->fill_surfaces.surfaces = std::move(new_surfaces);
m_fill_surfaces.surfaces = std::move(new_surfaces);
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
export_region_fill_surfaces_to_svg_debug("3_process_external_surfaces-final");
@ -389,12 +385,12 @@ void LayerRegion::prepare_fill_surfaces()
// For Lightning infill, infill_only_where_needed is ignored because both
// do a similar thing, and their combination doesn't make much sense.
if (! spiral_vase && this->region().config().top_solid_layers == 0) {
for (Surface &surface : this->fill_surfaces.surfaces)
for (Surface &surface : m_fill_surfaces)
if (surface.is_top())
surface.surface_type = this->layer()->object()->config().infill_only_where_needed && this->region().config().fill_pattern != ipLightning ? stInternalVoid : stInternal;
}
if (this->region().config().bottom_solid_layers == 0) {
for (Surface &surface : this->fill_surfaces.surfaces)
for (Surface &surface : m_fill_surfaces)
if (surface.is_bottom()) // (surface.surface_type == stBottom)
surface.surface_type = stInternal;
}
@ -403,7 +399,7 @@ void LayerRegion::prepare_fill_surfaces()
if (! spiral_vase && this->region().config().fill_density.value > 0) {
// scaling an area requires two calls!
double min_area = scale_(scale_(this->region().config().solid_infill_below_area.value));
for (Surface &surface : this->fill_surfaces.surfaces)
for (Surface &surface : m_fill_surfaces)
if (surface.surface_type == stInternal && surface.area() <= min_area)
surface.surface_type = stInternalSolid;
}
@ -423,38 +419,38 @@ double LayerRegion::infill_area_threshold() const
void LayerRegion::trim_surfaces(const Polygons &trimming_polygons)
{
#ifndef NDEBUG
for (const Surface &surface : this->slices.surfaces)
for (const Surface &surface : this->slices())
assert(surface.surface_type == stInternal);
#endif /* NDEBUG */
this->slices.set(intersection_ex(this->slices.surfaces, trimming_polygons), stInternal);
m_slices.set(intersection_ex(this->slices().surfaces, trimming_polygons), stInternal);
}
void LayerRegion::elephant_foot_compensation_step(const float elephant_foot_compensation_perimeter_step, const Polygons &trimming_polygons)
{
#ifndef NDEBUG
for (const Surface &surface : this->slices.surfaces)
for (const Surface &surface : this->slices())
assert(surface.surface_type == stInternal);
#endif /* NDEBUG */
Polygons tmp = intersection(this->slices.surfaces, trimming_polygons);
append(tmp, diff(this->slices.surfaces, opening(this->slices.surfaces, elephant_foot_compensation_perimeter_step)));
this->slices.set(union_ex(tmp), stInternal);
Polygons tmp = intersection(this->slices().surfaces, trimming_polygons);
append(tmp, diff(this->slices().surfaces, opening(this->slices().surfaces, elephant_foot_compensation_perimeter_step)));
m_slices.set(union_ex(tmp), stInternal);
}
void LayerRegion::export_region_slices_to_svg(const char *path) const
{
BoundingBox bbox;
for (Surfaces::const_iterator surface = this->slices.surfaces.begin(); surface != this->slices.surfaces.end(); ++surface)
bbox.merge(get_extents(surface->expolygon));
for (const Surface &surface : this->slices())
bbox.merge(get_extents(surface.expolygon));
Point legend_size = export_surface_type_legend_to_svg_box_size();
Point legend_pos(bbox.min(0), bbox.max(1));
bbox.merge(Point(std::max(bbox.min(0) + legend_size(0), bbox.max(0)), bbox.max(1) + legend_size(1)));
SVG svg(path, bbox);
const float transparency = 0.5f;
for (Surfaces::const_iterator surface = this->slices.surfaces.begin(); surface != this->slices.surfaces.end(); ++surface)
svg.draw(surface->expolygon, surface_type_to_color_name(surface->surface_type), transparency);
for (Surfaces::const_iterator surface = this->fill_surfaces.surfaces.begin(); surface != this->fill_surfaces.surfaces.end(); ++surface)
svg.draw(surface->expolygon.lines(), surface_type_to_color_name(surface->surface_type));
for (const Surface &surface : this->slices())
svg.draw(surface.expolygon, surface_type_to_color_name(surface.surface_type), transparency);
for (const Surface &surface : this->fill_surfaces())
svg.draw(surface.expolygon.lines(), surface_type_to_color_name(surface.surface_type));
export_surface_type_legend_to_svg(svg, legend_pos);
svg.Close();
}
@ -470,15 +466,15 @@ void LayerRegion::export_region_slices_to_svg_debug(const char *name) const
void LayerRegion::export_region_fill_surfaces_to_svg(const char *path) const
{
BoundingBox bbox;
for (Surfaces::const_iterator surface = this->fill_surfaces.surfaces.begin(); surface != this->fill_surfaces.surfaces.end(); ++surface)
bbox.merge(get_extents(surface->expolygon));
for (const Surface &surface : this->fill_surfaces())
bbox.merge(get_extents(surface.expolygon));
Point legend_size = export_surface_type_legend_to_svg_box_size();
Point legend_pos(bbox.min(0), bbox.max(1));
bbox.merge(Point(std::max(bbox.min(0) + legend_size(0), bbox.max(0)), bbox.max(1) + legend_size(1)));
SVG svg(path, bbox);
const float transparency = 0.5f;
for (const Surface &surface : this->fill_surfaces.surfaces) {
for (const Surface &surface : this->fill_surfaces()) {
svg.draw(surface.expolygon, surface_type_to_color_name(surface.surface_type), transparency);
svg.draw_outline(surface.expolygon, "black", "blue", scale_(0.05));
}