23#ifndef VCL_ALGORITHMS_MESH_CLEAN_H
24#define VCL_ALGORITHMS_MESH_CLEAN_H
26#include <vclib/algorithms/core/polygon/ear_cut.h>
27#include <vclib/algorithms/mesh/sort.h>
28#include <vclib/algorithms/mesh/stat/topology.h>
29#include <vclib/mesh/requirements.h>
30#include <vclib/space/complex/mesh_pos.h>
52template<
typename VertexPo
inter>
53class VertPositionComparator
56 inline bool operator()(
const VertexPointer& a,
const VertexPointer& b)
58 return (a->coord() == b->coord()) ? (a < b) : (a->coord() < b->coord());
74template<
typename IndexType,
typename SentinelType,
int N>
75class SortedIndexContainer
78 SortedIndexContainer() {}
80 template<Range RangeType>
81 SortedIndexContainer(SentinelType s, RangeType rng) : s(s), v(rng)
83 std::sort(v.begin(), v.end());
86 bool operator<(
const SortedIndexContainer& s)
const
88 if constexpr (N >= 0) {
89 for (uint i = 0; i < N; ++i) {
96 for (uint i = 0; i < v.size() && i < s.v.size(); ++i) {
100 return v.size() < s.v.size();
104 bool operator==(
const SortedIndexContainer& s)
const
106 if constexpr (N >= 0) {
107 for (uint i = 0; i < N; ++i) {
114 if (v.size() != s.v.size())
116 for (uint i = 0; i < v.size(); ++i) {
124 SentinelType sentinel()
const {
return s; }
127 Vector<IndexType, N> v;
131template<FaceMeshConcept MeshType>
132std::vector<bool> nonManifoldVerticesVectorBool(
const MeshType& m)
133 requires HasPerFaceAdjacentFaces<MeshType>
137 using FaceType = MeshType::FaceType;
139 std::vector<bool> nonManifoldVertices(m.vertexContainerSize(),
false);
141 std::vector<uint> TD(m.vertexContainerSize(), 0);
142 std::vector<bool> nonManifoldInc(m.vertexContainerSize(),
false);
145 for (
const FaceType& f : m.
faces()) {
146 for (uint i = 0; i < f.vertexNumber(); ++i) {
147 TD[m.index(f.vertex(i))]++;
148 if (!isFaceManifoldOnEdge(f, i)) {
149 nonManifoldInc[m.index(f.vertex(i))] =
true;
150 nonManifoldInc[m.index(f.vertexMod(i + 1))] =
true;
155 std::vector<bool> visited(m.vertexContainerSize(),
false);
156 for (
const FaceType& f : m.
faces()) {
157 for (uint i = 0; i < f.vertexNumber(); ++i) {
158 if (!visited[m.index(f.vertex(i))]) {
159 visited[m.index(f.vertex(i))] =
true;
161 uint starSize = pos.numberOfAdjacentFacesToV();
162 if (starSize != TD[m.index(f.vertex(i))])
163 nonManifoldVertices[m.index(f.vertex(i))] =
true;
168 return nonManifoldVertices;
171template<FaceMeshConcept MeshType>
174 uint& numBoundaryEdges,
175 uint& numNonManifoldEdges)
177 std::vector<ConstMeshEdgeUtil<MeshType>> edgeVec =
178 fillAndSortMeshEdgeUtilVector(m);
181 numBoundaryEdges = 0;
182 numNonManifoldEdges = 0;
184 size_t f_on_cur_edge = 1;
185 for (
size_t i = 0; i < edgeVec.size(); ++i) {
186 if (((i + 1) == edgeVec.size()) || !(edgeVec[i] == edgeVec[i + 1])) {
188 if (f_on_cur_edge == 1)
190 if (f_on_cur_edge > 2)
191 ++numNonManifoldEdges;
218template<MeshConcept MeshType>
246template<MeshConcept MeshType>
249 using VertexType = MeshType::VertexType;
259 if (
n <
m.vertexNumber()) {
264 for (
const VertexType& v :
m.vertices()) {
266 m.deleteVertex(
m.index(v));
300template<MeshConcept MeshType>
303 using VertexType = MeshType::VertexType;
306 if (
m.vertexNumber() == 0)
317 std::vector<VertexPointer>
perm(
m.vertexNumber());
321 for (VertexType& v :
m.vertices())
326 std::execution::par_unseq,
329 detail::VertPositionComparator<VertexPointer>());
335 while (
i <
perm.size() - 1) {
341 m.deleteVertex(
m.index(
perm[
j]));
385template<FaceMeshConcept MeshType>
388 using VertexType = MeshType::VertexType;
389 using FaceType = MeshType::FaceType;
393 std::vector<detail::SortedIndexContainer<
396 FaceType::VERTEX_NUMBER>>
399 for (FaceType& f :
m.faces()) {
400 fvec.emplace_back(&f, f.vertices());
404 std::sort(std::execution::par_unseq,
fvec.begin(),
fvec.end());
408 for (uint
i = 0;
i <
fvec.size() - 1; ++
i) {
411 m.deleteFace(
fvec[
i].sentinel());
440template<MeshConcept MeshType>
443 using VertexType = MeshType::VertexType;
449 for (VertexType& v :
m.vertices()) {
450 if (v.coord().isDegenerate()) {
459 using FaceType = MeshType::FaceType;
461 for (FaceType& f :
m.faces()) {
463 for (VertexType* v : f.vertices()) {
500template<FaceMeshConcept MeshType>
504 using FaceType = MeshType::FaceType;
508 for (FaceType& f :
m.faces()) {
510 for (uint
i = 0;
i < f.vertexNumber() && !
deg; ++
i) {
511 if (f.vertex(
i) == f.vertexMod(
i + 1)) {
513 m.deleteFace(
m.index(f));
539template<FaceMeshConcept MeshType>
543 detail::nonManifoldVerticesVectorBool(
m);
567template<FaceMeshConcept MeshType>
593template<FaceMeshConcept MeshType>
598 using VertexType = MeshType::VertexType;
599 using FaceType = MeshType::FaceType;
604 std::vector<bool>
visitedFaces(
m.faceContainerSize(),
false);
608 for (
const FaceType& f :
m.faces()) {
610 for (
const VertexType* v : f.vertices()) {
615 curPos.nextEdgeOnBorderAdjacentToV();
649template<FaceMeshConcept MeshType>
655 using FaceType = MeshType::FaceType;
657 std::vector<std::set<uint>>
cc;
660 std::vector<bool>
visitedFaces(
m.faceContainerSize(),
false);
664 std::stack<const FaceType*>
sf;
668 for (
const FaceType& f :
m.faces()) {
674 std::set<uint>&
ccf =
cc[
cc.size() - 1];
675 ccf.insert(
m.index(f));
680 while (!
sf.empty()) {
681 const FaceType*
fpt =
sf.top();
687 for (uint
j = 0;
j <
fpt->vertexNumber(); ++
j) {
688 const FaceType*
adjf =
fpt->adjFace(
j);
719template<FaceMeshConcept MeshType>
A class representing a line segment in n-dimensional space. The class is parameterized by a PointConc...
Definition segment.h:43
HasFaces concepts is satisfied when at least one of its template types is (or inherits from) a vcl::m...
Definition face_container.h:133
Concept that checks if a Mesh has the per Face AdjacentFaces component.
Definition per_face.h:79
std::vector< std::set< uint > > connectedComponents(const MeshType &m)
Computes the connected components of the input mesh based on its topology.
Definition clean.h:650
uint removeUnreferencedVertices(MeshType &m)
Marks as deleted all the non-deleted unreferenced vertices of the mesh.
Definition clean.h:247
uint removeDegeneratedVertices(MeshType &m, bool deleteAlsoFaces)
Removes all vertices that have coordinates with invalid floating point values (NaN or inf).
Definition clean.h:441
uint removeDegenerateFaces(MeshType &m)
Removes all degenerate faces from the input mesh.
Definition clean.h:501
uint removeDuplicatedFaces(MeshType &m)
Removes all duplicate faces of the mesh by looking only at their vertex references.
Definition clean.h:386
uint numberHoles(const MeshType &m)
Counts the number of holes in the input mesh.
Definition clean.h:594
uint removeDuplicatedVertices(MeshType &m)
Marks as deleted the duplicate vertices of the mesh, by looking only at their spatial positions.
Definition clean.h:301
uint numberNonManifoldVertices(const MeshType &m)
Counts the number of non-manifold vertices in the input mesh.
Definition clean.h:540
bool isWaterTight(const MeshType &m)
Determines whether the input mesh is water tight.
Definition clean.h:568
uint numberUnreferencedVertices(const MeshType &m)
Returns the number of non-deleted unreferenced vertices of the mesh.
Definition clean.h:219
uint numberConnectedComponents(const MeshType &m)
Computes the number of connected components of the input mesh based on its topology.
Definition clean.h:720
void requirePerFaceAdjacentFaces(const MeshType &m)
This function asserts that a Mesh has a FaceContainer, the Face has a AdjacentFaces Component,...
Definition face_requirements.h:698
constexpr uint UINT_NULL
The UINT_NULL value represent a null value of uint that is the maximum value that can be represented ...
Definition base.h:48
constexpr detail::FacesView faces
A view that allows to iterate overt the Face elements of an object.
Definition face.h:52