improve mesh repair functions

This commit is contained in:
wmayer
2019-04-16 17:25:36 +02:00
parent 83b92eb93c
commit da1481a2f3
3 changed files with 47 additions and 10 deletions

View File

@@ -524,13 +524,16 @@ bool MeshRemoveNeedles::Fixup()
std::vector<FaceEdgePriority>,
std::greater<FaceEdgePriority> > todo;
for (std::size_t index = 0; index < facetCount; index++) {
const MeshFacet& facet = rclFAry[index];
MeshGeomFacet tria(_rclMesh.GetFacet(facet));
float perimeter = tria.Perimeter();
float fMinLen = perimeter * fMinEdgeLength;
for (int i=0; i<3; i++) {
const MeshFacet& facet = rclFAry[index];
const Base::Vector3f& p1 = rclPAry[facet._aulPoints[i]];
const Base::Vector3f& p2 = rclPAry[facet._aulPoints[(i+1)%3]];
float distance = Base::Distance(p1, p2);
if (distance < fMinEdgeLength) {
if (distance < fMinLen) {
unsigned long facetIndex = static_cast<unsigned long>(index);
todo.push(std::make_pair(distance, std::make_pair(facetIndex, i)));
}
@@ -548,10 +551,13 @@ bool MeshRemoveNeedles::Fixup()
// the facet points may have changed, so check the current distance again
const MeshFacet& facet = rclFAry[faceedge.first];
MeshGeomFacet tria(_rclMesh.GetFacet(facet));
float perimeter = tria.Perimeter();
float fMinLen = perimeter * fMinEdgeLength;
const Base::Vector3f& p1 = rclPAry[facet._aulPoints[faceedge.second]];
const Base::Vector3f& p2 = rclPAry[facet._aulPoints[(faceedge.second+1)%3]];
float distance = Base::Distance(p1, p2);
if (distance >= fMinEdgeLength)
if (distance >= fMinLen)
continue;
// collect the collapse-edge information

View File

@@ -340,11 +340,13 @@ private:
class MeshExport MeshRemoveNeedles : public MeshValidation
{
public:
/**
* Construction.
*/
MeshRemoveNeedles (MeshKernel &rclM, float fMinEdgeLen = MeshDefinitions::_fMinPointDistance)
: MeshValidation(rclM), fMinEdgeLength(fMinEdgeLen) { }
/**
* Construction. The \arg fMinEdgeLen must be in the range of 0.0 and 0.25.
* It defines the amount of perimeter of a triangle for which the shortest
* edge is considered for removal.
*/
MeshRemoveNeedles (MeshKernel &rclM, float fMinEdgeLen = 0.05f)
: MeshValidation(rclM), fMinEdgeLength(std::min(fMinEdgeLen, 0.25f)) {}
/**
* Destruction.
*/

View File

@@ -973,6 +973,14 @@ bool MeshTopoAlgorithm::IsCollapseEdgeLegal(const EdgeCollapse& ec) const
return false;
}
// If the data structure is valid and the algorithm works as expected
// it should never happen to reject the edge-collapse here!
for (it = ec._removeFacets.begin(); it != ec._removeFacets.end(); ++it) {
MeshFacet f = _rclMesh._aclFacetArray[*it];
if (!f.IsValid())
return false;
}
if (!_rclMesh._aclPointArray[ec._fromPoint].IsValid())
return false;
@@ -988,12 +996,33 @@ bool MeshTopoAlgorithm::CollapseEdge(const EdgeCollapse& ec)
for (it = ec._removeFacets.begin(); it != ec._removeFacets.end(); ++it) {
MeshFacet& f = _rclMesh._aclFacetArray[*it];
f.SetInvalid();
// adjust the neighbourhood
std::vector<unsigned long> neighbours;
for (int i=0; i<3; i++) {
// get the neighbours of the facet that won't be invalidated
if (f._aulNeighbours[i] != ULONG_MAX) {
if (std::find(ec._removeFacets.begin(), ec._removeFacets.end(),
f._aulNeighbours[i]) == ec._removeFacets.end()) {
neighbours.push_back(f._aulNeighbours[i]);
}
}
}
if (neighbours.size() == 2) {
MeshFacet& n1 = _rclMesh._aclFacetArray[neighbours[0]];
n1.ReplaceNeighbour(*it, neighbours[1]);
MeshFacet& n2 = _rclMesh._aclFacetArray[neighbours[1]];
n2.ReplaceNeighbour(*it, neighbours[0]);
}
else if (neighbours.size() == 1) {
MeshFacet& n1 = _rclMesh._aclFacetArray[neighbours[0]];
n1.ReplaceNeighbour(*it, ULONG_MAX);
}
}
for (it = ec._changeFacets.begin(); it != ec._changeFacets.end(); ++it) {
MeshFacet& f = _rclMesh._aclFacetArray[*it];
// The neighbourhood might be broken from now on!!!
f.Transpose(ec._fromPoint, ec._toPoint);
}