Mesh: detect points on edges

This commit is contained in:
wmayer
2021-09-28 22:30:21 +02:00
parent 086b1d2aac
commit 3922a6ac73
8 changed files with 184 additions and 0 deletions

View File

@@ -1163,3 +1163,59 @@ bool MeshFixCorruptedFacets::Fixup()
return true;
}
// ----------------------------------------------------------------------
bool MeshEvalPointOnEdge::Evaluate ()
{
MeshFacetGrid facetGrid(_rclMesh);
const MeshPointArray& points = _rclMesh.GetPoints();
const MeshFacetArray& facets = _rclMesh.GetFacets();
auto IsPointOnEdge = [&points](PointIndex idx, const MeshFacet& facet) {
// point must not be a corner of the facet
if (!facet.HasPoint(idx)) {
for (int i = 0; i < 3; i++) {
MeshGeomEdge edge;
edge._aclPoints[0] = points[facet._aulPoints[i]];
edge._aclPoints[1] = points[facet._aulPoints[(i+1)%3]];
if (edge.GetBoundBox().IsInBox(points[idx])) {
if (edge.IsPointOf(points[idx], 0.001f))
return true;
}
}
}
return false;
};
PointIndex maxPoints = _rclMesh.CountPoints();
for (PointIndex i = 0; i < maxPoints; i++) {
std::vector<FacetIndex> elements;
facetGrid.GetElements(points[i], elements);
for (const auto& it : elements) {
const MeshFacet& face = facets[it];
if (IsPointOnEdge(i, face)) {
pointsIndices.push_back(i);
}
}
}
return pointsIndices.empty();
}
std::vector<PointIndex> MeshEvalPointOnEdge::GetIndices() const
{
return pointsIndices;
}
bool MeshFixPointOnEdge::Fixup ()
{
if (pointsIndices.empty()) {
MeshEvalPointOnEdge eval(_rclMesh);
eval.Evaluate();
pointsIndices = eval.GetIndices();
}
_rclMesh.DeletePoints(pointsIndices);
return true;
}

View File

@@ -741,6 +741,62 @@ public:
bool Fixup ();
};
/**
* The MeshEvalPointOnEdge class searches for points that lie on or close to an edge of a triangle.
* @see MeshFixPointOnEdge
* @author Werner Mayer
*/
class MeshExport MeshEvalPointOnEdge : public MeshEvaluation
{
public:
/**
* Construction.
*/
MeshEvalPointOnEdge (const MeshKernel &rclM) : MeshEvaluation( rclM ) { }
/**
* Destruction.
*/
~MeshEvalPointOnEdge () { }
/**
* Searches for points that lie on edge of triangle.
*/
bool Evaluate ();
/**
* Returns the indices of all corrupt facets.
*/
std::vector<PointIndex> GetIndices() const;
private:
std::vector<PointIndex> pointsIndices;
};
/**
* The MeshFixPointOnEdge class removes points that lie on or close to an edge of a triangle.
* @see MeshEvalPointOnEdge
* @author Werner Mayer
*/
class MeshExport MeshFixPointOnEdge : public MeshValidation
{
public:
/**
* Construction.
*/
MeshFixPointOnEdge (MeshKernel &rclM) : MeshValidation( rclM ) { }
MeshFixPointOnEdge (MeshKernel &rclM, const std::vector<PointIndex>& points)
: MeshValidation( rclM ), pointsIndices(points) { }
/**
* Destruction.
*/
~MeshFixPointOnEdge () { }
/**
* Removes points that lie on edges of triangles.
*/
bool Fixup ();
private:
std::vector<PointIndex> pointsIndices;
};
} // namespace MeshCore
#endif // MESH_DEGENERATION_H

View File

@@ -350,6 +350,26 @@ void MeshGeomEdge::ClosestPointsToLine(const Base::Vector3f &linePt, const Base:
}
}
bool MeshGeomEdge::IsPointOf (const Base::Vector3f &rclPoint, float fDistance) const
{
float len2 = Base::DistanceP2(_aclPoints[0], _aclPoints[1]);
if (len2 == 0.0f) {
return _aclPoints[0].IsEqual(rclPoint, 0.0f);
}
Base::Vector3f p2p1 = _aclPoints[1] - _aclPoints[0];
Base::Vector3f pXp1 = rclPoint - _aclPoints[0];
float dot = pXp1 * p2p1;
float t = dot / len2;
if (t < 0.0f || t > 1.0f)
return false;
// point on the edge
Base::Vector3f ptEdge = t * p2p1 + _aclPoints[0];
return Base::Distance(ptEdge, rclPoint) <= fDistance;
}
// -----------------------------------------------------------------
MeshGeomFacet::MeshGeomFacet ()

View File

@@ -184,6 +184,12 @@ public:
*/
void ClosestPointsToLine(const Base::Vector3f &linePt, const Base::Vector3f &lineDir,
Base::Vector3f& rclPnt1, Base::Vector3f& rclPnt2) const;
/**
* Checks if the point is part of the facet. A point is regarded as part
* of a facet if the distance is lower \a fDistance and the projected point
* in the facet normal direction is inside the triangle.
*/
bool IsPointOf (const Base::Vector3f &rclPoint, float fDistance) const;
public:
Base::Vector3f _aclPoints[2]; /**< Corner points */

View File

@@ -1495,6 +1495,18 @@ void MeshObject::removeInvalidPoints()
deletePoints(nan.GetIndices());
}
bool MeshObject::hasPointsOnEdge() const
{
MeshCore::MeshEvalPointOnEdge nan(_kernel);
return !nan.Evaluate();
}
void MeshObject::removePointsOnEdge()
{
MeshCore::MeshFixPointOnEdge nan(_kernel);
nan.Fixup();
}
void MeshObject::mergeFacets()
{
unsigned long count = _kernel.CountFacets();

View File

@@ -298,6 +298,8 @@ public:
bool hasInvalidPoints() const;
void removeInvalidPoints();
void mergeFacets();
bool hasPointsOnEdge() const;
void removePointsOnEdge();
//@}
/** @name Mesh segments */

View File

@@ -291,6 +291,16 @@ for c in mesh.getSeparatecomponents():
<UserDocu>Remove points with invalid coordinates (NaN)</UserDocu>
</Documentation>
</Methode>
<Methode Name="hasPointsOnEdge" Const="true">
<Documentation>
<UserDocu>Check if points lie on edges</UserDocu>
</Documentation>
</Methode>
<Methode Name="removePointsOnEdge">
<Documentation>
<UserDocu>Remove points that lie on edges</UserDocu>
</Documentation>
</Methode>
<Methode Name="hasInvalidNeighbourhood" Const="true">
<Documentation>
<UserDocu>Check if the mesh has invalid neighbourhood indices</UserDocu>

View File

@@ -1094,6 +1094,28 @@ PyObject* MeshPy::removeInvalidPoints(PyObject *args)
Py_Return;
}
PyObject* MeshPy::hasPointsOnEdge(PyObject *args)
{
if (!PyArg_ParseTuple(args, ""))
return nullptr;
bool ok = getMeshObjectPtr()->hasPointsOnEdge();
return Py_BuildValue("O", (ok ? Py_True : Py_False));
}
PyObject* MeshPy::removePointsOnEdge(PyObject *args)
{
if (!PyArg_ParseTuple(args, ""))
return nullptr;
try {
getMeshObjectPtr()->removePointsOnEdge();
}
catch (const Base::Exception& e) {
PyErr_SetString(Base::BaseExceptionFreeCADError, e.what());
return nullptr;
}
Py_Return;
}
PyObject* MeshPy::flipNormals(PyObject *args)
{
if (!PyArg_ParseTuple(args, ""))