diff --git a/src/Mod/Mesh/App/Core/Degeneration.cpp b/src/Mod/Mesh/App/Core/Degeneration.cpp index 11f87b37ac..5983307b19 100644 --- a/src/Mod/Mesh/App/Core/Degeneration.cpp +++ b/src/Mod/Mesh/App/Core/Degeneration.cpp @@ -38,6 +38,7 @@ #include "Info.h" #include "Grid.h" #include "TopoAlgorithm.h" +#include "Triangulation.h" #include #include @@ -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 MeshEvalPointOnEdge::GetIndices() const +std::vector MeshEvalPointOnEdge::GetPointIndices() const { return pointsIndices; } +std::vector 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 pointsIndices = eval.GetPointIndices(); + std::vector facetsIndices = eval.GetFacetIndices(); + + if (!pointsIndices.empty()) { + if (fillBoundary) { + MarkBoundaries(facetsIndices); + } + + _rclMesh.DeletePoints(pointsIndices); + + if (fillBoundary) { + std::list > borderList; + FindBoundaries(borderList); + if (!borderList.empty()) + FillBoundaries(borderList); + } } - _rclMesh.DeletePoints(pointsIndices); return true; } + +void MeshFixPointOnEdge::MarkBoundaries(const std::vector& facetsIndices) +{ + MeshAlgorithm meshalg(_rclMesh); + meshalg.ResetFacetFlag(MeshFacet::TMP0); + meshalg.SetFacetsFlag(facetsIndices, MeshFacet::TMP0); +} + +void MeshFixPointOnEdge::FindBoundaries(std::list >& borderList) +{ + std::vector tmp; + MeshAlgorithm meshalg(_rclMesh); + meshalg.GetFacetsFlag(tmp, MeshFacet::TMP0); + + if (!tmp.empty()) { + //TODO: Implement a method to handle all facets in 'tmp' + std::list border; + meshalg.GetMeshBorder(tmp.front(), border); + if (!border.empty()) { + borderList.emplace_back(border.begin(), border.end()); + } + } +} + +void MeshFixPointOnEdge::FillBoundaries(const std::list >& borderList) +{ + FlatTriangulator tria; + tria.SetVerifier(new MeshCore::TriangulationVerifierV2); + MeshTopoAlgorithm topalg(_rclMesh); + std::list > failed; + topalg.FillupHoles(1, tria, borderList, failed); +} diff --git a/src/Mod/Mesh/App/Core/Degeneration.h b/src/Mod/Mesh/App/Core/Degeneration.h index b544c294bc..80e6bf8fb6 100644 --- a/src/Mod/Mesh/App/Core/Degeneration.h +++ b/src/Mod/Mesh/App/Core/Degeneration.h @@ -762,12 +762,17 @@ public: */ bool Evaluate (); /** - * Returns the indices of all corrupt facets. + * Returns the indices of all points on edge. */ - std::vector GetIndices() const; + std::vector GetPointIndices() const; + /** + * Returns the indices of all facets with an open edge on that a point lies. + */ + std::vector GetFacetIndices() const; private: std::vector pointsIndices; + std::vector facetsIndices; }; /** @@ -781,9 +786,7 @@ public: /** * Construction. */ - MeshFixPointOnEdge (MeshKernel &rclM) : MeshValidation( rclM ) { } - MeshFixPointOnEdge (MeshKernel &rclM, const std::vector& 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 pointsIndices; + void MarkBoundaries(const std::vector& facetsIndices); + void FindBoundaries(std::list >& borderList); + void FillBoundaries(const std::list >& borderList); + +private: + bool fillBoundary; }; } // namespace MeshCore diff --git a/src/Mod/Mesh/App/Mesh.cpp b/src/Mod/Mesh/App/Mesh.cpp index cf215e0722..bc533ecaa5 100644 --- a/src/Mod/Mesh/App/Mesh.cpp +++ b/src/Mod/Mesh/App/Mesh.cpp @@ -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(); } diff --git a/src/Mod/Mesh/App/Mesh.h b/src/Mod/Mesh/App/Mesh.h index 810c5dbde5..7b307b2e78 100644 --- a/src/Mod/Mesh/App/Mesh.h +++ b/src/Mod/Mesh/App/Mesh.h @@ -299,7 +299,7 @@ public: void removeInvalidPoints(); void mergeFacets(); bool hasPointsOnEdge() const; - void removePointsOnEdge(); + void removePointsOnEdge(bool fillBoundary); //@} /** @name Mesh segments */ diff --git a/src/Mod/Mesh/App/MeshPy.xml b/src/Mod/Mesh/App/MeshPy.xml index 6ae9295dfb..b0f2992ad9 100644 --- a/src/Mod/Mesh/App/MeshPy.xml +++ b/src/Mod/Mesh/App/MeshPy.xml @@ -296,9 +296,12 @@ for c in mesh.getSeparatecomponents(): Check if points lie on edges - + - Remove points that lie on edges + 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. diff --git a/src/Mod/Mesh/App/MeshPyImp.cpp b/src/Mod/Mesh/App/MeshPyImp.cpp index b2e9fc3beb..7f368488b7 100644 --- a/src/Mod/Mesh/App/MeshPyImp.cpp +++ b/src/Mod/Mesh/App/MeshPyImp.cpp @@ -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());