Mesh: improve function to fix points on edge

This commit is contained in:
wmayer
2021-09-29 19:32:18 +02:00
parent fe7f4c4be7
commit 8ff9bbc930
6 changed files with 86 additions and 20 deletions

View File

@@ -38,6 +38,7 @@
#include "Info.h"
#include "Grid.h"
#include "TopoAlgorithm.h"
#include "Triangulation.h"
#include <boost/math/special_functions/fpclassify.hpp>
#include <Base/Sequencer.h>
@@ -1197,25 +1198,77 @@ bool MeshEvalPointOnEdge::Evaluate ()
const MeshFacet& face = facets[it];
if (IsPointOnEdge(i, face)) {
pointsIndices.push_back(i);
if (face.HasOpenEdge())
facetsIndices.push_back(it);
}
}
}
return pointsIndices.empty();
}
std::vector<PointIndex> MeshEvalPointOnEdge::GetIndices() const
std::vector<PointIndex> MeshEvalPointOnEdge::GetPointIndices() const
{
return pointsIndices;
}
std::vector<FacetIndex> MeshEvalPointOnEdge::GetFacetIndices() const
{
return facetsIndices;
}
bool MeshFixPointOnEdge::Fixup ()
{
if (pointsIndices.empty()) {
MeshEvalPointOnEdge eval(_rclMesh);
eval.Evaluate();
pointsIndices = eval.GetIndices();
MeshEvalPointOnEdge eval(_rclMesh);
eval.Evaluate();
std::vector<PointIndex> pointsIndices = eval.GetPointIndices();
std::vector<FacetIndex> facetsIndices = eval.GetFacetIndices();
if (!pointsIndices.empty()) {
if (fillBoundary) {
MarkBoundaries(facetsIndices);
}
_rclMesh.DeletePoints(pointsIndices);
if (fillBoundary) {
std::list<std::vector<PointIndex> > borderList;
FindBoundaries(borderList);
if (!borderList.empty())
FillBoundaries(borderList);
}
}
_rclMesh.DeletePoints(pointsIndices);
return true;
}
void MeshFixPointOnEdge::MarkBoundaries(const std::vector<FacetIndex>& facetsIndices)
{
MeshAlgorithm meshalg(_rclMesh);
meshalg.ResetFacetFlag(MeshFacet::TMP0);
meshalg.SetFacetsFlag(facetsIndices, MeshFacet::TMP0);
}
void MeshFixPointOnEdge::FindBoundaries(std::list<std::vector<PointIndex> >& borderList)
{
std::vector<FacetIndex> tmp;
MeshAlgorithm meshalg(_rclMesh);
meshalg.GetFacetsFlag(tmp, MeshFacet::TMP0);
if (!tmp.empty()) {
//TODO: Implement a method to handle all facets in 'tmp'
std::list<PointIndex> border;
meshalg.GetMeshBorder(tmp.front(), border);
if (!border.empty()) {
borderList.emplace_back(border.begin(), border.end());
}
}
}
void MeshFixPointOnEdge::FillBoundaries(const std::list<std::vector<PointIndex> >& borderList)
{
FlatTriangulator tria;
tria.SetVerifier(new MeshCore::TriangulationVerifierV2);
MeshTopoAlgorithm topalg(_rclMesh);
std::list<std::vector<PointIndex> > failed;
topalg.FillupHoles(1, tria, borderList, failed);
}

View File

@@ -762,12 +762,17 @@ public:
*/
bool Evaluate ();
/**
* Returns the indices of all corrupt facets.
* Returns the indices of all points on edge.
*/
std::vector<PointIndex> GetIndices() const;
std::vector<PointIndex> GetPointIndices() const;
/**
* Returns the indices of all facets with an open edge on that a point lies.
*/
std::vector<FacetIndex> GetFacetIndices() const;
private:
std::vector<PointIndex> pointsIndices;
std::vector<FacetIndex> facetsIndices;
};
/**
@@ -781,9 +786,7 @@ public:
/**
* Construction.
*/
MeshFixPointOnEdge (MeshKernel &rclM) : MeshValidation( rclM ) { }
MeshFixPointOnEdge (MeshKernel &rclM, const std::vector<PointIndex>& points)
: MeshValidation( rclM ), pointsIndices(points) { }
MeshFixPointOnEdge (MeshKernel &rclM, bool fill = false) : MeshValidation( rclM ), fillBoundary(fill) { }
/**
* Destruction.
*/
@@ -794,7 +797,12 @@ public:
bool Fixup ();
private:
std::vector<PointIndex> pointsIndices;
void MarkBoundaries(const std::vector<FacetIndex>& facetsIndices);
void FindBoundaries(std::list<std::vector<PointIndex> >& borderList);
void FillBoundaries(const std::list<std::vector<PointIndex> >& borderList);
private:
bool fillBoundary;
};
} // namespace MeshCore

View File

@@ -1501,9 +1501,9 @@ bool MeshObject::hasPointsOnEdge() const
return !nan.Evaluate();
}
void MeshObject::removePointsOnEdge()
void MeshObject::removePointsOnEdge(bool fillBoundary)
{
MeshCore::MeshFixPointOnEdge nan(_kernel);
MeshCore::MeshFixPointOnEdge nan(_kernel, fillBoundary);
nan.Fixup();
}

View File

@@ -299,7 +299,7 @@ public:
void removeInvalidPoints();
void mergeFacets();
bool hasPointsOnEdge() const;
void removePointsOnEdge();
void removePointsOnEdge(bool fillBoundary);
//@}
/** @name Mesh segments */

View File

@@ -296,9 +296,12 @@ for c in mesh.getSeparatecomponents():
<UserDocu>Check if points lie on edges</UserDocu>
</Documentation>
</Methode>
<Methode Name="removePointsOnEdge">
<Methode Name="removePointsOnEdge" Keyword="true">
<Documentation>
<UserDocu>Remove points that lie on edges</UserDocu>
<UserDocu>removePointsOnEdge(FillBoundary=False)
Remove points that lie on edges.
If FillBoundary is True then the holes by removing the affected facets
will be re-filled.</UserDocu>
</Documentation>
</Methode>
<Methode Name="hasInvalidNeighbourhood" Const="true">

View File

@@ -1102,12 +1102,14 @@ PyObject* MeshPy::hasPointsOnEdge(PyObject *args)
return Py_BuildValue("O", (ok ? Py_True : Py_False));
}
PyObject* MeshPy::removePointsOnEdge(PyObject *args)
PyObject* MeshPy::removePointsOnEdge(PyObject *args, PyObject *kwds)
{
if (!PyArg_ParseTuple(args, ""))
PyObject *fillBoundary = Py_False;
static char* keywords[] = {"FillBoundary", nullptr};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O!", keywords, &PyBool_Type, &fillBoundary))
return nullptr;
try {
getMeshObjectPtr()->removePointsOnEdge();
getMeshObjectPtr()->removePointsOnEdge(PyObject_IsTrue(fillBoundary) ? true : false);
}
catch (const Base::Exception& e) {
PyErr_SetString(Base::BaseExceptionFreeCADError, e.what());