improve mesh repair functions
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user