Mesh: detect points on edges
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 ()
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -298,6 +298,8 @@ public:
|
||||
bool hasInvalidPoints() const;
|
||||
void removeInvalidPoints();
|
||||
void mergeFacets();
|
||||
bool hasPointsOnEdge() const;
|
||||
void removePointsOnEdge();
|
||||
//@}
|
||||
|
||||
/** @name Mesh segments */
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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, ""))
|
||||
|
||||
Reference in New Issue
Block a user