improve mesh validation functions

This commit is contained in:
wmayer
2018-12-17 16:14:28 +01:00
parent 5213f26846
commit bf1603b388
5 changed files with 132 additions and 0 deletions

View File

@@ -701,6 +701,34 @@ bool MeshFixDeformedFacets::Fixup()
// ----------------------------------------------------------------------
bool MeshFixMergeFacets::Fixup()
{
MeshCore::MeshRefPointToPoints vv_it(_rclMesh);
MeshCore::MeshRefPointToFacets vf_it(_rclMesh);
unsigned long countPoints = _rclMesh.CountPoints();
std::vector<MeshFacet> newFacets;
newFacets.reserve(countPoints/20); // 5% should be sufficient
MeshTopoAlgorithm topAlg(_rclMesh);
for (unsigned long i=0; i<countPoints; i++) {
if (vv_it[i].size() == 3 && vf_it[i].size() == 3) {
VertexCollapse vc;
vc._point = i;
const std::set<unsigned long>& adjPts = vv_it[i];
vc._circumPoints.insert(vc._circumPoints.begin(), adjPts.begin(), adjPts.end());
const std::set<unsigned long>& adjFts = vf_it[i];
vc._circumFacets.insert(vc._circumFacets.begin(), adjFts.begin(), adjFts.end());
topAlg.CollapseVertex(vc);
}
}
topAlg.Cleanup();
return true;
}
// ----------------------------------------------------------------------
bool MeshEvalDentsOnSurface::Evaluate()
{
this->indices.clear();

View File

@@ -398,6 +398,32 @@ private:
float fEpsilon;
};
/**
* The MeshFixMergeFacets class removes vertexes which have three adjacent vertexes and is referenced by three facets.
* Usually all the three facets that reference this vertex are not well-formed. If the number of adjacent vertexes
* is equal to the number of adjacent facets the affected vertex never lies on the boundary and thus it's safe to delete
* and replace the three facets with a single facet.
* Effectively this algorithm does the opposite of \ref MeshTopoAlgorithm::InsertVertex
* @author Werner Mayer
*/
class MeshExport MeshFixMergeFacets : public MeshValidation
{
public:
/**
* Construction.
*/
MeshFixMergeFacets (MeshKernel &rclM)
: MeshValidation(rclM) { }
/**
* Destruction.
*/
~MeshFixMergeFacets () { }
/**
* Removes deformed facets.
*/
bool Fixup ();
};
/**
* If an adjacent point (A) of a point (P) can be projected onto a triangle shared
* by (P) but not by (A) then we have a local dent. The topology is not affected.

View File

@@ -79,6 +79,13 @@ struct MeshExport EdgeCollapse
std::vector<unsigned long> _changeFacets;
};
struct MeshExport VertexCollapse
{
unsigned long _point;
std::vector<unsigned long> _circumPoints;
std::vector<unsigned long> _circumFacets;
};
/**
* The MeshPoint class represents a point in the mesh data structure. The class inherits from
* Vector3f and provides some additional information such as flag state and property value.

View File

@@ -835,6 +835,72 @@ void MeshTopoAlgorithm::Cleanup()
_needsCleanup = false;
}
bool MeshTopoAlgorithm::CollapseVertex(const VertexCollapse& vc)
{
if (vc._circumFacets.size() != vc._circumPoints.size())
return false;
if (vc._circumFacets.size() != 3)
return false;
if (!_rclMesh._aclPointArray[vc._point].IsValid())
return false; // the point is marked invalid from a previous run
MeshFacet& rFace1 = _rclMesh._aclFacetArray[vc._circumFacets[0]];
MeshFacet& rFace2 = _rclMesh._aclFacetArray[vc._circumFacets[1]];
MeshFacet& rFace3 = _rclMesh._aclFacetArray[vc._circumFacets[2]];
// get the point that is not shared by rFace1
unsigned long ptIndex = ULONG_MAX;
std::vector<unsigned long>::const_iterator it;
for (it = vc._circumPoints.begin(); it != vc._circumPoints.end(); ++it) {
if (!rFace1.HasPoint(*it)) {
ptIndex = *it;
break;
}
}
if (ptIndex == ULONG_MAX)
return false;
unsigned long neighbour1 = ULONG_MAX;
unsigned long neighbour2 = ULONG_MAX;
const std::vector<unsigned long>& faces = vc._circumFacets;
// get neighbours that are not part of the faces to be removed
for (int i=0; i<3; i++) {
if (std::find(faces.begin(), faces.end(), rFace2._aulNeighbours[i]) == faces.end()) {
neighbour1 = rFace2._aulNeighbours[i];
}
if (std::find(faces.begin(), faces.end(), rFace3._aulNeighbours[i]) == faces.end()) {
neighbour2 = rFace3._aulNeighbours[i];
}
}
// adjust point and neighbour indices
rFace1.Transpose(vc._point, ptIndex);
rFace1.ReplaceNeighbour(vc._circumFacets[1], neighbour1);
rFace1.ReplaceNeighbour(vc._circumFacets[2], neighbour2);
if (neighbour1 != ULONG_MAX) {
MeshFacet& rFace4 = _rclMesh._aclFacetArray[neighbour1];
rFace4.ReplaceNeighbour(vc._circumFacets[1], vc._circumFacets[0]);
}
if (neighbour2 != ULONG_MAX) {
MeshFacet& rFace5 = _rclMesh._aclFacetArray[neighbour2];
rFace5.ReplaceNeighbour(vc._circumFacets[2], vc._circumFacets[0]);
}
// the two facets and the point can be marked for removal
rFace2.SetInvalid();
rFace3.SetInvalid();
_rclMesh._aclPointArray[vc._point].SetInvalid();
_needsCleanup = true;
return true;
}
bool MeshTopoAlgorithm::CollapseEdge(unsigned long ulFacetPos, unsigned long ulNeighbour)
{
MeshFacet& rclF = _rclMesh._aclFacetArray[ulFacetPos];

View File

@@ -111,6 +111,11 @@ public:
*/
void SplitFacet(unsigned long ulFacetPos, const Base::Vector3f& rP1,
const Base::Vector3f& rP2);
/**
* Collapse a vertex. At the moment only removing inner vertexes referenced
* by three facets is supposrted.
*/
bool CollapseVertex(const VertexCollapse& vc);
/**
* Collapses the common edge of two adjacent facets. This operation removes
* one common point of the collapsed edge and the facets \a ulFacetPos and