mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-14 23:25:59 +08:00
Prevent small useless cutted pieces by set requirement for minimal source contour outline points
This commit is contained in:
parent
60c2e74207
commit
848dbcb9ca
@ -392,6 +392,14 @@ void collect_surface_data(std::queue<FI> &process,
|
|||||||
FaceTypeMap &face_type_map,
|
FaceTypeMap &face_type_map,
|
||||||
const CutMesh &mesh);
|
const CutMesh &mesh);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check if contour contain at least 2 unique source contour points
|
||||||
|
/// </summary>
|
||||||
|
bool is_valid(const std::vector<HI> &outlines,
|
||||||
|
const VertexShapeMap &vert_shape_map,
|
||||||
|
const CutMesh &mesh,
|
||||||
|
size_t min_count = 2);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Copy triangles from CGAL mesh into index triangle set
|
/// Copy triangles from CGAL mesh into index triangle set
|
||||||
/// NOTE: Skip vertices created by edge in center of Quad.
|
/// NOTE: Skip vertices created by edge in center of Quad.
|
||||||
@ -993,21 +1001,24 @@ void priv::flood_fill_inner(const CutMesh &mesh,
|
|||||||
};
|
};
|
||||||
|
|
||||||
for (FI fi : mesh.faces()) {
|
for (FI fi : mesh.faces()) {
|
||||||
if (face_type_map[fi] != FaceType::not_constrained) continue;
|
FaceType type = face_type_map[fi];
|
||||||
|
if (type != FaceType::not_constrained &&
|
||||||
|
type != FaceType::inside_parallel) continue;
|
||||||
if (!has_inside_neighbor(fi)) continue;
|
if (!has_inside_neighbor(fi)) continue;
|
||||||
assert(process.empty());
|
assert(process.empty());
|
||||||
process.push_back(fi);
|
process.push_back(fi);
|
||||||
//store(mesh, face_type_map, DEBUG_OUTPUT_DIR + "progress.off");
|
//store(mesh, face_type_map, DEBUG_OUTPUT_DIR + "progress.off");
|
||||||
|
|
||||||
while (!process.empty()) {
|
while (!process.empty()) {
|
||||||
FI fi = process.back();
|
FI process_fi = process.back();
|
||||||
process.pop_back();
|
process.pop_back();
|
||||||
// Do not fill twice
|
// Do not fill twice
|
||||||
if (face_type_map[fi] == FaceType::inside) continue;
|
FaceType& process_type = face_type_map[process_fi];
|
||||||
face_type_map[fi] = FaceType::inside;
|
if (process_type == FaceType::inside) continue;
|
||||||
|
process_type = FaceType::inside;
|
||||||
|
|
||||||
// check neighbor triangle
|
// check neighbor triangle
|
||||||
HI hi = mesh.halfedge(fi);
|
HI hi = mesh.halfedge(process_fi);
|
||||||
HI hi_end = hi;
|
HI hi_end = hi;
|
||||||
auto exist_next = [&hi, &hi_end, &mesh]() -> bool {
|
auto exist_next = [&hi, &hi_end, &mesh]() -> bool {
|
||||||
hi = mesh.next(hi);
|
hi = mesh.next(hi);
|
||||||
@ -1019,9 +1030,9 @@ void priv::flood_fill_inner(const CutMesh &mesh,
|
|||||||
if (!hi_opposite.is_valid()) continue;
|
if (!hi_opposite.is_valid()) continue;
|
||||||
FI fi_opposite = mesh.face(hi_opposite);
|
FI fi_opposite = mesh.face(hi_opposite);
|
||||||
if (!fi_opposite.is_valid()) continue;
|
if (!fi_opposite.is_valid()) continue;
|
||||||
FaceType &side = face_type_map[fi_opposite];
|
FaceType type_opposite = face_type_map[fi_opposite];
|
||||||
if (side == FaceType::not_constrained ||
|
if (type_opposite == FaceType::not_constrained ||
|
||||||
side == FaceType::inside_parallel )
|
type_opposite == FaceType::inside_parallel)
|
||||||
process.push_back(fi_opposite);
|
process.push_back(fi_opposite);
|
||||||
} while (exist_next());
|
} while (exist_next());
|
||||||
}
|
}
|
||||||
@ -1089,25 +1100,54 @@ void priv::Visitor::new_vertex_added(std::size_t i_id, VI v, const CutMesh &tm)
|
|||||||
vert_shape_map[v] = intersection_ptr;
|
vert_shape_map[v] = intersection_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool priv::is_valid(const std::vector<HI> &outlines,
|
||||||
|
const VertexShapeMap &vert_shape_map,
|
||||||
|
const CutMesh &mesh,
|
||||||
|
size_t min_count)
|
||||||
|
{
|
||||||
|
// unique vector of indicies point from source contour(ExPolygon)
|
||||||
|
std::vector<uint32_t> point_indicies;
|
||||||
|
point_indicies.reserve(min_count);
|
||||||
|
for (HI hi : outlines) {
|
||||||
|
VI vi = mesh.source(hi);
|
||||||
|
const auto& shape = vert_shape_map[vi];
|
||||||
|
if (shape == nullptr) continue;
|
||||||
|
uint32_t pi = shape->point_index;
|
||||||
|
if (pi == std::numeric_limits<uint32_t>::max()) continue;
|
||||||
|
// is already stored in vector?
|
||||||
|
if (std::find(point_indicies.begin(), point_indicies.end(), pi)
|
||||||
|
!= point_indicies.end())
|
||||||
|
continue;
|
||||||
|
if (point_indicies.size() == min_count) return true;
|
||||||
|
point_indicies.push_back(pi);
|
||||||
|
}
|
||||||
|
// prevent weird small pieces
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void priv::collect_surface_data(std::queue<FI> &process,
|
void priv::collect_surface_data(std::queue<FI> &process,
|
||||||
std::vector<FI> &faces,
|
std::vector<FI> &faces,
|
||||||
std::vector<HI> &outlines,
|
std::vector<HI> &outlines,
|
||||||
FaceTypeMap &face_type_map,
|
FaceTypeMap &face_type_map,
|
||||||
const CutMesh &mesh)
|
const CutMesh &mesh)
|
||||||
{
|
{
|
||||||
|
assert(!process.empty());
|
||||||
|
assert(faces.empty());
|
||||||
|
assert(outlines.empty());
|
||||||
while (!process.empty()) {
|
while (!process.empty()) {
|
||||||
FI fi_ = process.front();
|
FI fi = process.front();
|
||||||
process.pop();
|
process.pop();
|
||||||
|
|
||||||
|
FaceType &fi_type = face_type_map[fi];
|
||||||
// Do not process twice
|
// Do not process twice
|
||||||
if (face_type_map[fi_] == FaceType::inside_processed) continue;
|
if (fi_type == FaceType::inside_processed) continue;
|
||||||
assert(face_type_map[fi_] == FaceType::inside);
|
assert(fi_type == FaceType::inside);
|
||||||
// flag face as processed
|
// flag face as processed
|
||||||
face_type_map[fi_] = FaceType::inside_processed;
|
fi_type = FaceType::inside_processed;
|
||||||
faces.push_back(fi_);
|
faces.push_back(fi);
|
||||||
|
|
||||||
// check neighbor triangle
|
// check neighbor triangle
|
||||||
HI hi = mesh.halfedge(fi_);
|
HI hi = mesh.halfedge(fi);
|
||||||
HI hi_end = hi;
|
HI hi_end = hi;
|
||||||
do {
|
do {
|
||||||
HI hi_opposite = mesh.opposite(hi);
|
HI hi_opposite = mesh.opposite(hi);
|
||||||
@ -1123,7 +1163,7 @@ void priv::collect_surface_data(std::queue<FI> &process,
|
|||||||
hi = mesh.next(hi);
|
hi = mesh.next(hi);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
FaceType side = face_type_map[fi_opposite];
|
FaceType side = face_type_map[fi_opposite];
|
||||||
if (side == FaceType::inside) {
|
if (side == FaceType::inside) {
|
||||||
process.emplace(fi_opposite);
|
process.emplace(fi_opposite);
|
||||||
} else if (side == FaceType::outside) {
|
} else if (side == FaceType::outside) {
|
||||||
@ -1378,7 +1418,6 @@ priv::CutAOIs priv::create_cut_area_of_interests(const CutMesh &mesh,
|
|||||||
// Process queue of faces to separate to surface_cut
|
// Process queue of faces to separate to surface_cut
|
||||||
process.push(fi);
|
process.push(fi);
|
||||||
collect_surface_data(process, faces, outlines, face_type_map, mesh);
|
collect_surface_data(process, faces, outlines, face_type_map, mesh);
|
||||||
|
|
||||||
assert(!faces.empty());
|
assert(!faces.empty());
|
||||||
assert(!outlines.empty());
|
assert(!outlines.empty());
|
||||||
result.emplace_back(std::move(cut));
|
result.emplace_back(std::move(cut));
|
||||||
@ -1496,9 +1535,18 @@ void priv::filter_cuts(CutAOIs &cuts,
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// filter small pieces
|
||||||
|
for (const CutAOI &cut : cuts) {
|
||||||
|
if (!is_valid(cut.second, vert_shape_map, mesh)) {
|
||||||
|
size_t index = &cut - &cuts.front();
|
||||||
|
del_cuts[index] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// filter top one cuts
|
// filter top one cuts
|
||||||
for (const CutAOI &cut : cuts) {
|
for (const CutAOI &cut : cuts) {
|
||||||
size_t cut_index = &cut - &cuts.front();
|
size_t cut_index = &cut - &cuts.front();
|
||||||
|
if (del_cuts[cut_index]) continue;
|
||||||
const std::vector<HI> &outlines = cut.second;
|
const std::vector<HI> &outlines = cut.second;
|
||||||
for (HI hi : outlines) {
|
for (HI hi : outlines) {
|
||||||
if (is_behind(mesh.source(hi), cut_index) ||
|
if (is_behind(mesh.source(hi), cut_index) ||
|
||||||
|
Loading…
x
Reference in New Issue
Block a user