New utility function its_merge_vertices().
Implemented contour simplification inside slice_mesh_ex().
This commit is contained in:
parent
dfc6d399f7
commit
c28cd957d5
@ -779,6 +779,69 @@ std::vector<Vec3i> create_face_neighbors_index(const indexed_triangle_set &its,
|
|||||||
return create_face_neighbors_index_impl(its, throw_on_cancel_callback);
|
return create_face_neighbors_index_impl(its, throw_on_cancel_callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Merge duplicate vertices, return number of vertices removed.
|
||||||
|
int its_merge_vertices(indexed_triangle_set &its, bool shrink_to_fit)
|
||||||
|
{
|
||||||
|
// 1) Sort indices to vertices lexicographically by coordinates AND vertex index.
|
||||||
|
auto sorted = reserve_vector<int>(its.vertices.size());
|
||||||
|
for (int i = 0; i < int(its.vertices.size()); ++ i)
|
||||||
|
sorted.emplace_back(i);
|
||||||
|
std::sort(sorted.begin(), sorted.end(), [&its](int il, int ir) {
|
||||||
|
const Vec3f &l = its.vertices[il];
|
||||||
|
const Vec3f &r = its.vertices[ir];
|
||||||
|
// Sort lexicographically by coordinates AND vertex index.
|
||||||
|
return l.x() < r.x() || (l.x() == r.x() && (l.y() < r.y() || (l.y() == r.y() && (l.z() < r.z() || (l.z() == r.z() && il < ir)))));
|
||||||
|
});
|
||||||
|
|
||||||
|
// 2) Map duplicate vertices to the one with the lowest vertex index.
|
||||||
|
// The vertex to stay will have a map_vertices[...] == -1 index assigned, the other vertices will point to it.
|
||||||
|
std::vector<int> map_vertices(its.vertices.size(), -1);
|
||||||
|
for (int i = 0; i < int(sorted.size());) {
|
||||||
|
const int u = sorted[i];
|
||||||
|
const Vec3f &p = its.vertices[u];
|
||||||
|
int j = i;
|
||||||
|
for (++ j; j < int(sorted.size()); ++ j) {
|
||||||
|
const int v = sorted[j];
|
||||||
|
const Vec3f &q = its.vertices[v];
|
||||||
|
if (p != q)
|
||||||
|
break;
|
||||||
|
assert(v > u);
|
||||||
|
map_vertices[v] = u;
|
||||||
|
}
|
||||||
|
i = j;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3) Shrink its.vertices, update map_vertices with the new vertex indices.
|
||||||
|
int k = 0;
|
||||||
|
for (int i = 0; i < int(its.vertices.size()); ++ i) {
|
||||||
|
if (map_vertices[i] == -1) {
|
||||||
|
map_vertices[i] = k;
|
||||||
|
if (k < i)
|
||||||
|
its.vertices[k] = its.vertices[i];
|
||||||
|
++ k;
|
||||||
|
} else {
|
||||||
|
assert(map_vertices[i] < i);
|
||||||
|
map_vertices[i] = map_vertices[map_vertices[i]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int num_erased = int(its.vertices.size()) - k;
|
||||||
|
|
||||||
|
if (num_erased) {
|
||||||
|
// Shrink the vertices.
|
||||||
|
its.vertices.erase(its.vertices.begin() + k, its.vertices.end());
|
||||||
|
// Remap face indices.
|
||||||
|
for (stl_triangle_vertex_indices &face : its.indices)
|
||||||
|
for (int i = 0; i < 3; ++ i)
|
||||||
|
face(i) = map_vertices[face(i)];
|
||||||
|
// Optionally shrink to fit (reallocate) vertices.
|
||||||
|
if (shrink_to_fit)
|
||||||
|
its.vertices.shrink_to_fit();
|
||||||
|
}
|
||||||
|
|
||||||
|
return num_erased;
|
||||||
|
}
|
||||||
|
|
||||||
int its_remove_degenerate_faces(indexed_triangle_set &its, bool shrink_to_fit)
|
int its_remove_degenerate_faces(indexed_triangle_set &its, bool shrink_to_fit)
|
||||||
{
|
{
|
||||||
int last = 0;
|
int last = 0;
|
||||||
|
@ -98,10 +98,19 @@ std::vector<std::vector<size_t>> create_vertex_faces_index(const indexed_triangl
|
|||||||
// Used for chaining slice lines into polygons.
|
// Used for chaining slice lines into polygons.
|
||||||
std::vector<Vec3i> create_face_neighbors_index(const indexed_triangle_set &its);
|
std::vector<Vec3i> create_face_neighbors_index(const indexed_triangle_set &its);
|
||||||
std::vector<Vec3i> create_face_neighbors_index(const indexed_triangle_set &its, std::function<void()> throw_on_cancel_callback);
|
std::vector<Vec3i> create_face_neighbors_index(const indexed_triangle_set &its, std::function<void()> throw_on_cancel_callback);
|
||||||
|
|
||||||
|
// Merge duplicate vertices, return number of vertices removed.
|
||||||
|
// This function will happily create non-manifolds if more than two faces share the same vertex position
|
||||||
|
// or more than two faces share the same edge position!
|
||||||
|
int its_merge_vertices(indexed_triangle_set &its, bool shrink_to_fit = true);
|
||||||
|
|
||||||
// Remove degenerate faces, return number of faces removed.
|
// Remove degenerate faces, return number of faces removed.
|
||||||
int its_remove_degenerate_faces(indexed_triangle_set &its, bool shrink_to_fit = true);
|
int its_remove_degenerate_faces(indexed_triangle_set &its, bool shrink_to_fit = true);
|
||||||
|
|
||||||
// Remove vertices, which none of the faces references. Return number of freed vertices.
|
// Remove vertices, which none of the faces references. Return number of freed vertices.
|
||||||
int its_compactify_vertices(indexed_triangle_set &its, bool shrink_to_fit = true);
|
int its_compactify_vertices(indexed_triangle_set &its, bool shrink_to_fit = true);
|
||||||
|
|
||||||
|
// Shrink the vectors of its.vertices and its.faces to a minimum size by reallocating the two vectors.
|
||||||
void its_shrink_to_fit(indexed_triangle_set &its);
|
void its_shrink_to_fit(indexed_triangle_set &its);
|
||||||
|
|
||||||
TriangleMesh make_cube(double x, double y, double z);
|
TriangleMesh make_cube(double x, double y, double z);
|
||||||
|
@ -1057,6 +1057,10 @@ std::vector<Polygons> slice_mesh(
|
|||||||
std::vector<IntersectionLines> lines;
|
std::vector<IntersectionLines> lines;
|
||||||
|
|
||||||
{
|
{
|
||||||
|
//FIXME facets_edges is likely not needed and quite costly to calculate.
|
||||||
|
// Instead of edge identifiers, one shall use a sorted pair of edge vertex indices.
|
||||||
|
// However facets_edges assigns a single edge ID to two triangles only, thus when factoring facets_edges out, one will have
|
||||||
|
// to make sure that no code relies on it.
|
||||||
std::vector<Vec3i> facets_edges = create_face_neighbors_index(mesh);
|
std::vector<Vec3i> facets_edges = create_face_neighbors_index(mesh);
|
||||||
const bool identity = params.trafo.matrix() == Transform3d::Identity().matrix();
|
const bool identity = params.trafo.matrix() == Transform3d::Identity().matrix();
|
||||||
static constexpr const double s = 1. / SCALING_FACTOR;
|
static constexpr const double s = 1. / SCALING_FACTOR;
|
||||||
@ -1165,6 +1169,9 @@ std::vector<ExPolygons> slice_mesh_ex(
|
|||||||
const auto this_mode = layer_id < params.slicing_mode_normal_below_layer ? params.mode_below : params.mode;
|
const auto this_mode = layer_id < params.slicing_mode_normal_below_layer ? params.mode_below : params.mode;
|
||||||
if (this_mode == MeshSlicingParams::SlicingMode::PositiveLargestContour)
|
if (this_mode == MeshSlicingParams::SlicingMode::PositiveLargestContour)
|
||||||
keep_largest_contour_only(expolygons);
|
keep_largest_contour_only(expolygons);
|
||||||
|
if (params.resolution != 0.)
|
||||||
|
for (ExPolygon &ex : expolygons)
|
||||||
|
ex.simplify(params.resolution);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// BOOST_LOG_TRIVIAL(debug) << "slice_mesh make_expolygons in parallel - end";
|
// BOOST_LOG_TRIVIAL(debug) << "slice_mesh make_expolygons in parallel - end";
|
||||||
@ -1199,7 +1206,9 @@ static void triangulate_slice(
|
|||||||
{
|
{
|
||||||
std::vector<int> map_duplicate_vertex(int(its.vertices.size()) - num_original_vertices, -1);
|
std::vector<int> map_duplicate_vertex(int(its.vertices.size()) - num_original_vertices, -1);
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
int k = 0;
|
||||||
for (; i < int(map_vertex_to_index.size()); ++ i) {
|
for (; i < int(map_vertex_to_index.size()); ++ i) {
|
||||||
|
map_vertex_to_index[k ++] = map_vertex_to_index[i];
|
||||||
const Vec2f &ipos = map_vertex_to_index[i].first;
|
const Vec2f &ipos = map_vertex_to_index[i].first;
|
||||||
const int iidx = map_vertex_to_index[i].second;
|
const int iidx = map_vertex_to_index[i].second;
|
||||||
if (iidx >= num_original_vertices)
|
if (iidx >= num_original_vertices)
|
||||||
@ -1214,6 +1223,7 @@ static void triangulate_slice(
|
|||||||
map_duplicate_vertex[jidx - num_original_vertices] = iidx;
|
map_duplicate_vertex[jidx - num_original_vertices] = iidx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
map_vertex_to_index.erase(map_vertex_to_index.begin() + k, map_vertex_to_index.end());
|
||||||
for (stl_triangle_vertex_indices &f : its.indices)
|
for (stl_triangle_vertex_indices &f : its.indices)
|
||||||
for (i = 0; i < 3; ++ i)
|
for (i = 0; i < 3; ++ i)
|
||||||
if (f(i) >= num_original_vertices)
|
if (f(i) >= num_original_vertices)
|
||||||
|
@ -36,7 +36,7 @@ struct MeshSlicingParamsEx : public MeshSlicingParams
|
|||||||
float closing_radius { 0 };
|
float closing_radius { 0 };
|
||||||
// Positive offset applied when creating output expolygons.
|
// Positive offset applied when creating output expolygons.
|
||||||
float extra_offset { 0 };
|
float extra_offset { 0 };
|
||||||
// Resolution for contour simplification.
|
// Resolution for contour simplification, scaled!
|
||||||
// 0 = don't simplify.
|
// 0 = don't simplify.
|
||||||
double resolution { 0 };
|
double resolution { 0 };
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user