mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-13 10:58:59 +08:00
fix some perimeter & infill slicing issues
This commit is contained in:
parent
7ae60b6c82
commit
7d1ade1008
@ -1228,6 +1228,12 @@ ExPolygons variable_offset_inner_ex(const ExPolygon &expoly, const std::vector<s
|
||||
holes.reserve(expoly.holes.size());
|
||||
for (const Polygon& hole : expoly.holes)
|
||||
append(holes, fix_after_outer_offset(mittered_offset_path_scaled(hole.points, deltas[1 + &hole - expoly.holes.data()], miter_limit), ClipperLib::pftNegative, false));
|
||||
//tiny holes can be reduced to giberish, get rid of them.
|
||||
for (auto it = holes.begin(); it != holes.end();)
|
||||
if (ClipperLib::Area(*it) < CLIPPER_OFFSET_SCALE*CLIPPER_OFFSET_SCALE) {
|
||||
it = holes.erase(it);
|
||||
}
|
||||
else ++it;
|
||||
#ifndef NDEBUG
|
||||
for (auto &c : holes)
|
||||
assert(ClipperLib::Area(c) > 0.);
|
||||
|
@ -465,9 +465,12 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
|
||||
}
|
||||
|
||||
//init the surface with the current polygon
|
||||
surface_fill.surface.expolygon = std::move(expoly);
|
||||
//make fill
|
||||
f->fill_surface_extrusion(&surface_fill.surface, surface_fill.params, m_regions[surface_fill.region_id]->fills.entities);
|
||||
if (!expoly.contour.empty()) {
|
||||
surface_fill.surface.expolygon = std::move(expoly);
|
||||
|
||||
//make fill
|
||||
f->fill_surface_extrusion(&surface_fill.surface, surface_fill.params, m_regions[surface_fill.region_id]->fills.entities);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -525,6 +525,8 @@ void PerimeterGenerator::process()
|
||||
(float)(ext_min_spacing / 4),
|
||||
(round_peri ? ClipperLib::JoinType::jtRound : ClipperLib::JoinType::jtMiter),
|
||||
(round_peri ? min_round_spacing : 3)));
|
||||
|
||||
next_onion = intersection_ex(next_onion, last);
|
||||
}
|
||||
}
|
||||
if (m_spiral_vase && next_onion.size() > 1) {
|
||||
|
@ -3249,10 +3249,12 @@ namespace Slic3r {
|
||||
|
||||
coordf_t print_z = layer->print_z;
|
||||
coordf_t bottom_z = layer->bottom_z();
|
||||
// 0: topSolid, 1: botSolid, 2: boSolidBridged
|
||||
for (size_t idx_surface_type = 0; idx_surface_type < 3; ++idx_surface_type) {
|
||||
m_print->throw_if_canceled();
|
||||
SurfaceType type = (idx_surface_type == 0) ? (stPosTop | stDensSolid) :
|
||||
((idx_surface_type == 1) ? (stPosBottom | stDensSolid) : (stPosBottom | stDensSolid | stModBridge));
|
||||
((idx_surface_type == 1) ? (stPosBottom | stDensSolid) :
|
||||
(stPosBottom | stDensSolid | stModBridge));
|
||||
int num_solid_layers = ((type & stPosTop) == stPosTop) ? region_config.top_solid_layers.value : region_config.bottom_solid_layers.value;
|
||||
if (num_solid_layers == 0)
|
||||
continue;
|
||||
@ -3269,16 +3271,17 @@ namespace Slic3r {
|
||||
// Surfaces including the area of perimeters. Everything, that is visible from the top / bottom
|
||||
// (not covered by a layer above / below).
|
||||
// This does not contain the areas covered by perimeters!
|
||||
Polygons solid;
|
||||
ExPolygons solid;
|
||||
for (const Surface& surface : layerm->slices().surfaces)
|
||||
if (surface.surface_type == type)
|
||||
polygons_append(solid, to_polygons(surface.expolygon));
|
||||
solid.push_back(surface.expolygon);
|
||||
// Infill areas (slices without the perimeters).
|
||||
for (const Surface& surface : layerm->fill_surfaces.surfaces)
|
||||
if (surface.surface_type == type)
|
||||
polygons_append(solid, to_polygons(surface.expolygon));
|
||||
solid.push_back(surface.expolygon);
|
||||
if (solid.empty())
|
||||
continue;
|
||||
solid = union_ex(solid);
|
||||
// Slic3r::debugf "Layer %d has %s surfaces\n", $i, (($type & stTop) != 0) ? 'top' : 'bottom';
|
||||
|
||||
// Scatter top / bottom regions to other layers. Scattering process is inherently serial, it is difficult to parallelize without locking.
|
||||
@ -3304,13 +3307,14 @@ namespace Slic3r {
|
||||
// narrow bottom surfaces): reassigning $solid will consider the 'shadow' of the
|
||||
// upper perimeter as an obstacle and shell will not be propagated to more upper layers
|
||||
//FIXME How does it work for stInternalBRIDGE? This is set for sparse infill. Likely this does not work.
|
||||
Polygons new_internal_solid;
|
||||
ExPolygons new_internal_solid;
|
||||
{
|
||||
Polygons internal;
|
||||
ExPolygons internal;
|
||||
for (const Surface& surface : neighbor_layerm->fill_surfaces.surfaces)
|
||||
if (surface.has_pos_internal() && (surface.has_fill_sparse() || surface.has_fill_solid()))
|
||||
polygons_append(internal, to_polygons(surface.expolygon));
|
||||
new_internal_solid = intersection(solid, internal, true);
|
||||
internal.push_back(surface.expolygon);
|
||||
internal = union_ex(internal);
|
||||
new_internal_solid = intersection_ex(solid, internal, true);
|
||||
}
|
||||
if (new_internal_solid.empty()) {
|
||||
// No internal solid needed on this layer. In order to decide whether to continue
|
||||
@ -3335,18 +3339,23 @@ namespace Slic3r {
|
||||
// and it's not wanted in a hollow print even if it would make sense when
|
||||
// obeying the solid shell count option strictly (DWIM!)
|
||||
float margin = float(neighbor_layerm->flow(frExternalPerimeter).scaled_width());
|
||||
Polygons too_narrow = diff(
|
||||
ExPolygons too_narrow = diff_ex(
|
||||
new_internal_solid,
|
||||
offset2(new_internal_solid, -margin, +margin, jtMiter, 5),
|
||||
offset2_ex(new_internal_solid, -margin, +margin, jtMiter, 5),
|
||||
true);
|
||||
// Trim the regularized region by the original region.
|
||||
if (!too_narrow.empty())
|
||||
new_internal_solid = solid = diff(new_internal_solid, too_narrow);
|
||||
if (!too_narrow.empty()) {
|
||||
solid = new_internal_solid = diff_ex(new_internal_solid, too_narrow);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//merill: this is creating artifacts, and i can't recreate the issue it wants to fix.
|
||||
|
||||
// make sure the new internal solid is wide enough, as it might get collapsed
|
||||
// when spacing is added in Fill.pm
|
||||
{
|
||||
if(false){
|
||||
//FIXME Vojtech: Disable this and you will be sorry.
|
||||
// https://github.com/prusa3d/PrusaSlicer/issues/26 bottom
|
||||
float margin = 3.f * layerm->flow(frSolidInfill).scaled_width(); // require at least this size
|
||||
@ -3355,28 +3364,28 @@ namespace Slic3r {
|
||||
// get a triangle in $too_narrow; if we grow it below then the shell
|
||||
// would have a different shape from the external surface and we'd still
|
||||
// have the same angle, so the next shell would be grown even more and so on.
|
||||
Polygons too_narrow = diff(
|
||||
ExPolygons too_narrow = diff_ex(
|
||||
new_internal_solid,
|
||||
offset2(new_internal_solid, -margin, +margin, ClipperLib::jtMiter, 5),
|
||||
offset2_ex(new_internal_solid, -margin, +margin, ClipperLib::jtMiter, 5),
|
||||
true);
|
||||
if (!too_narrow.empty()) {
|
||||
// grow the collapsing parts and add the extra area to the neighbor layer
|
||||
// as well as to our original surfaces so that we support this
|
||||
// additional area in the next shell too
|
||||
// make sure our grown surfaces don't exceed the fill area
|
||||
Polygons internal;
|
||||
ExPolygons internal;
|
||||
for (const Surface& surface : neighbor_layerm->fill_surfaces.surfaces)
|
||||
if (surface.has_pos_internal() && !surface.has_mod_bridge())
|
||||
polygons_append(internal, to_polygons(surface.expolygon));
|
||||
polygons_append(new_internal_solid,
|
||||
intersection(
|
||||
offset(too_narrow, +margin),
|
||||
internal.push_back(surface.expolygon);
|
||||
expolygons_append(new_internal_solid,
|
||||
intersection_ex(
|
||||
offset_ex(too_narrow, +margin),
|
||||
// Discard bridges as they are grown for anchoring and we can't
|
||||
// remove such anchors. (This may happen when a bridge is being
|
||||
// anchored onto a wall where little space remains after the bridge
|
||||
// is grown, and that little space is an internal solid shell so
|
||||
// it triggers this too_narrow logic.)
|
||||
internal));
|
||||
union_ex(internal)));
|
||||
// see https://github.com/prusa3d/PrusaSlicer/pull/3426
|
||||
// solid = new_internal_solid;
|
||||
}
|
||||
@ -3385,30 +3394,31 @@ namespace Slic3r {
|
||||
// internal-solid are the union of the existing internal-solid surfaces
|
||||
// and new ones
|
||||
SurfaceCollection backup = std::move(neighbor_layerm->fill_surfaces);
|
||||
polygons_append(new_internal_solid, to_polygons(backup.filter_by_type(stPosInternal | stDensSolid)));
|
||||
expolygons_append(new_internal_solid, to_expolygons(backup.filter_by_type(stPosInternal | stDensSolid)));
|
||||
ExPolygons internal_solid = union_ex(new_internal_solid, false);
|
||||
// assign new internal-solid surfaces to layer
|
||||
neighbor_layerm->fill_surfaces.set(internal_solid, stPosInternal | stDensSolid);
|
||||
// subtract intersections from layer surfaces to get resulting internal surfaces
|
||||
Polygons polygons_internal = to_polygons(std::move(internal_solid));
|
||||
//ExPolygons polygons_internal = to_polygons(std::move(internal_solid));
|
||||
ExPolygons internal = diff_ex(
|
||||
to_polygons(backup.filter_by_type(stPosInternal | stDensSparse)),
|
||||
polygons_internal,
|
||||
to_expolygons(backup.filter_by_type(stPosInternal | stDensSparse)),
|
||||
internal_solid,
|
||||
true);
|
||||
// assign resulting internal surfaces to layer
|
||||
neighbor_layerm->fill_surfaces.append(internal, stPosInternal | stDensSparse);
|
||||
polygons_append(polygons_internal, to_polygons(std::move(internal)));
|
||||
expolygons_append(internal_solid, internal);
|
||||
// assign top and bottom surfaces to layer
|
||||
SurfaceType surface_types_solid[] = { stPosTop | stDensSolid, stPosBottom | stDensSolid, stPosBottom | stDensSolid | stModBridge };
|
||||
backup.keep_types(surface_types_solid, 3);
|
||||
//backup.keep_types_flag(stPosTop | stPosBottom);
|
||||
std::vector<SurfacesPtr> top_bottom_groups;
|
||||
backup.group(&top_bottom_groups);
|
||||
for (SurfacesPtr& group : top_bottom_groups)
|
||||
for (SurfacesPtr& group : top_bottom_groups) {
|
||||
neighbor_layerm->fill_surfaces.append(
|
||||
diff_ex(to_polygons(group), polygons_internal),
|
||||
diff_ex(to_expolygons(group), union_ex(internal_solid)),
|
||||
// Use an existing surface as a template, it carries the bridge angle etc.
|
||||
*group.front());
|
||||
}
|
||||
}
|
||||
EXTERNAL:;
|
||||
} // foreach type (stTop, stBottom, stBottomBridge)
|
||||
|
Loading…
x
Reference in New Issue
Block a user