mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-15 00:45:57 +08:00
Fixing projection of bottom surfaces in MM segmentation and for
support blockers / enforcers. All slicing functions shall produce consistent results with the same mesh, same transformation matrix and slicing parameters. Namely, slice_mesh_slabs() shall produce consistent results with slice_mesh() and slice_mesh_ex() in the sense, that projections made by slice_mesh_slabs() shall fall onto slicing planes produced by slice_mesh(). Before this commit, slice_mesh_slabs() projected bottom facing faces upwards to its coplanar slicing plane, which is different from how slice_mesh() or slice_mesh_ex() work, leading to ignored support enforcer / blocker strokes.
This commit is contained in:
parent
93e91bcacb
commit
b6c4e94d81
@ -2284,6 +2284,7 @@ void PrintObject::project_and_append_custom_facets(
|
||||
seam, out);
|
||||
else {
|
||||
std::vector<Polygons> projected;
|
||||
// Support blockers or enforcers. Project downward facing painted areas upwards to their respective slicing plane.
|
||||
slice_mesh_slabs(custom_facets, zs_from_layers(this->layers()), this->trafo_centered() * mv->get_matrix(), nullptr, &projected, [](){});
|
||||
// Merge these projections with the output, layer by layer.
|
||||
assert(! projected.empty());
|
||||
|
@ -1645,12 +1645,13 @@ static inline std::tuple<Polygons, Polygons, Polygons, float> detect_overhangs(
|
||||
polygons_append(contact_polygons, diff_polygons);
|
||||
} // for each layer.region
|
||||
|
||||
if (has_enforcer) {
|
||||
if (has_enforcer)
|
||||
if (const Polygons &enforcer_polygons_src = annotations.enforcers_layers[layer_id]; ! enforcer_polygons_src.empty()) {
|
||||
// Enforce supports (as if with 90 degrees of slope) for the regions covered by the enforcer meshes.
|
||||
#ifdef SLIC3R_DEBUG
|
||||
ExPolygons enforcers_united = union_ex(annotations.enforcers_layers[layer_id]);
|
||||
ExPolygons enforcers_united = union_ex(enforcer_polygons_src);
|
||||
#endif // SLIC3R_DEBUG
|
||||
enforcer_polygons = diff(intersection(layer.lslices, annotations.enforcers_layers[layer_id]),
|
||||
enforcer_polygons = diff(intersection(layer.lslices, enforcer_polygons_src),
|
||||
// Inflate just a tiny bit to avoid intersection of the overhang areas with the object.
|
||||
expand(lower_layer_polygons, 0.05f * no_interface_offset, SUPPORT_SURFACES_OFFSET_PARAMETERS));
|
||||
#ifdef SLIC3R_DEBUG
|
||||
@ -1660,11 +1661,13 @@ static inline std::tuple<Polygons, Polygons, Polygons, float> detect_overhangs(
|
||||
{ enforcers_united, { "enforcers", "blue", 0.5f } },
|
||||
{ { union_safety_offset_ex(enforcer_polygons) }, { "new_contacts", "red", "black", "", scaled<coord_t>(0.1f), 0.5f } } });
|
||||
#endif /* SLIC3R_DEBUG */
|
||||
if (! enforcer_polygons.empty()) {
|
||||
polygons_append(overhang_polygons, enforcer_polygons);
|
||||
slices_margin_update(std::min(lower_layer_offset, float(scale_(gap_xy))), no_interface_offset);
|
||||
polygons_append(contact_polygons, diff(enforcer_polygons, slices_margin.all_polygons.empty() ? slices_margin.polygons : slices_margin.all_polygons));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return std::make_tuple(std::move(overhang_polygons), std::move(contact_polygons), std::move(enforcer_polygons), no_interface_offset);
|
||||
}
|
||||
|
@ -458,13 +458,23 @@ void slice_facet_with_slabs(
|
||||
// Slicing a horizontal triangle with a slicing plane. The triangle has to be upwards facing for ProjectionFromTop
|
||||
// and downwards facing for ! ProjectionFromTop.
|
||||
assert(min_layer != max_layer);
|
||||
size_t line_id = min_layer - zs.begin();
|
||||
// Slicing plane with which the triangle is coplanar.
|
||||
size_t slice_id = min_layer - zs.begin();
|
||||
#if 0
|
||||
// Project the coplanar bottom facing triangles to their slicing plane for both top and bottom facing surfaces.
|
||||
// This behavior is different from slice_mesh() / slice_mesh_ex(), which do not slice bottom facing faces exactly on slicing plane.
|
||||
size_t line_id = slice_id;
|
||||
#else
|
||||
// Project the coplanar bottom facing triangles to the plane above the slicing plane to match the behavior of slice_mesh() / slice_mesh_ex(),
|
||||
// where the slicing plane slices the top facing surfaces, but misses the bottom facing surfaces.
|
||||
if (size_t line_id = ProjectionFromTop ? slice_id : slice_id + 1; ProjectionFromTop || line_id < lines.at_slice.size())
|
||||
#endif
|
||||
for (int iedge = 0; iedge < 3; ++ iedge)
|
||||
if (facet_neighbors(iedge) == -1) {
|
||||
int i = iedge;
|
||||
int j = next_idx_modulo(i, 3);
|
||||
assert(vertices[i].z() == zs[line_id]);
|
||||
assert(vertices[j].z() == zs[line_id]);
|
||||
assert(vertices[i].z() == zs[slice_id]);
|
||||
assert(vertices[j].z() == zs[slice_id]);
|
||||
IntersectionLine il {
|
||||
{ to_2d(vertices[i]).cast<coord_t>(), to_2d(vertices[j]).cast<coord_t>() },
|
||||
indices(i), indices(j), -1, -1,
|
||||
@ -539,6 +549,7 @@ void slice_facet_with_slabs(
|
||||
assert(il.b_id == indices(next_idx_modulo(edge_id, 3)));
|
||||
} else {
|
||||
// The edge is oriented CW along the face perimeter.
|
||||
assert(type == FacetSliceType::Slicing);
|
||||
assert(il.edge_type == IntersectionLine::FacetEdgeType::Top);
|
||||
edge_id = il.b_id == indices(0) ? 0 : il.b_id == indices(1) ? 1 : 2;
|
||||
assert(il.b_id == indices(edge_id));
|
||||
@ -555,8 +566,11 @@ void slice_facet_with_slabs(
|
||||
int num_on_plane = (mesh_vertices[neighbor(0)].z() == z) + (mesh_vertices[neighbor(1)].z() == z) + (mesh_vertices[neighbor(2)].z() == z);
|
||||
assert(num_on_plane == 2 || num_on_plane == 3);
|
||||
#endif // NDEBUG
|
||||
#if 0
|
||||
if (mesh_vertices[neighbor(0)].z() == z && mesh_vertices[neighbor(1)].z() == z && mesh_vertices[neighbor(2)].z() == z) {
|
||||
// The neighbor triangle is horizontal.
|
||||
// Assign the horizontal projections to slicing planes differently from the usual triangle mesh slicing:
|
||||
// Slicing plane slices top surfaces when projecting from top, it slices bottom surfaces when projecting from bottom.
|
||||
// Is the corner convex or concave?
|
||||
if (il.edge_type == (ProjectionFromTop ? IntersectionLine::FacetEdgeType::Top : IntersectionLine::FacetEdgeType::Bottom)) {
|
||||
// Convex corner. Add this edge to both slabs, the edge is a boundary edge of both the projection patch below and
|
||||
@ -567,7 +581,12 @@ void slice_facet_with_slabs(
|
||||
// Concave corner. Ignore this edge, it is internal to the projection patch.
|
||||
type = FacetSliceType::Cutting;
|
||||
}
|
||||
} else if (il.edge_type == IntersectionLine::FacetEdgeType::Top) {
|
||||
} else
|
||||
#else
|
||||
// Project the coplanar bottom facing triangles to the plane above the slicing plane to match the behavior of slice_mesh() / slice_mesh_ex(),
|
||||
// where the slicing plane slices the top facing surfaces, but misses the bottom facing surfaces.
|
||||
#endif
|
||||
if (il.edge_type == IntersectionLine::FacetEdgeType::Top) {
|
||||
// Indicate that the edge belongs to both the slab below and above the plane.
|
||||
assert(type == FacetSliceType::Slicing);
|
||||
il.edge_type = IntersectionLine::FacetEdgeType::TopBottom;
|
||||
|
@ -46,6 +46,17 @@ struct MeshSlicingParamsEx : public MeshSlicingParams
|
||||
double resolution { 0 };
|
||||
};
|
||||
|
||||
// All the following slicing functions shall produce consistent results with the same mesh, same transformation matrix and slicing parameters.
|
||||
// Namely, slice_mesh_slabs() shall produce consistent results with slice_mesh() and slice_mesh_ex() in the sense, that projections made by
|
||||
// slice_mesh_slabs() shall fall onto slicing planes produced by slice_mesh().
|
||||
//
|
||||
// If a slicing plane slices a horizontal face of a mesh exactly,
|
||||
// an upward facing horizontal face is is considered on slicing plane,
|
||||
// while a downward facing horizontal face is considered not on slicing plane.
|
||||
//
|
||||
// slice_mesh_slabs() thus projects an upward facing horizontal slice to the slicing plane,
|
||||
// while slice_mesh_slabs() projects a downward facing horizontal slice to the slicing plane above if it exists.
|
||||
|
||||
std::vector<Polygons> slice_mesh(
|
||||
const indexed_triangle_set &mesh,
|
||||
const std::vector<float> &zs,
|
||||
|
Loading…
x
Reference in New Issue
Block a user