mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-10 18:51:21 +03:00
OCC22503 Face triangulation causes shading display of whole shape to fail
This commit is contained in:
parent
587630c5be
commit
446e11f3c6
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#include <MeshTest_CheckTopology.hxx>
|
#include <MeshTest_CheckTopology.hxx>
|
||||||
#include <BRep_Tool.hxx>
|
#include <BRep_Tool.hxx>
|
||||||
#include <TColStd_MapOfInteger.hxx>
|
#include <TColStd_PackedMapOfInteger.hxx>
|
||||||
#include <TopExp.hxx>
|
#include <TopExp.hxx>
|
||||||
#include <TopExp_Explorer.hxx>
|
#include <TopExp_Explorer.hxx>
|
||||||
#include <TopoDS_Edge.hxx>
|
#include <TopoDS_Edge.hxx>
|
||||||
@ -112,8 +112,9 @@ void MeshTest_CheckTopology::Perform ()
|
|||||||
#endif
|
#endif
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// remember boundary nodes
|
// remember boundary nodes
|
||||||
TColStd_MapOfInteger aMapBndNodes;
|
TColStd_PackedMapOfInteger aMapBndNodes;
|
||||||
TopExp_Explorer ex(aFace, TopAbs_EDGE);
|
TopExp_Explorer ex(aFace, TopAbs_EDGE);
|
||||||
for (; ex.More(); ex.Next()) {
|
for (; ex.More(); ex.Next()) {
|
||||||
const TopoDS_Edge& aEdge = TopoDS::Edge(ex.Current());
|
const TopoDS_Edge& aEdge = TopoDS::Edge(ex.Current());
|
||||||
@ -126,11 +127,19 @@ void MeshTest_CheckTopology::Perform ()
|
|||||||
aMapBndNodes.Add(aNodes(i));
|
aMapBndNodes.Add(aNodes(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TColStd_PackedMapOfInteger aUsedNodes;
|
||||||
|
|
||||||
|
// check of free links and nodes
|
||||||
Poly_Connect aConn(aT);
|
Poly_Connect aConn(aT);
|
||||||
const Poly_Array1OfTriangle& aTriangles = aT->Triangles();
|
const Poly_Array1OfTriangle& aTriangles = aT->Triangles();
|
||||||
Standard_Integer nbTri = aT->NbTriangles(), i, j, n[3], t[3];
|
Standard_Integer nbTri = aT->NbTriangles(), i, j, n[3], t[3];
|
||||||
for (i = 1; i <= nbTri; i++) {
|
for (i = 1; i <= nbTri; i++) {
|
||||||
aTriangles(i).Get(n[0], n[1], n[2]);
|
aTriangles(i).Get(n[0], n[1], n[2]);
|
||||||
|
|
||||||
|
aUsedNodes.Add (n[0]);
|
||||||
|
aUsedNodes.Add (n[1]);
|
||||||
|
aUsedNodes.Add (n[2]);
|
||||||
|
|
||||||
aConn.Triangles(i, t[0], t[1], t[2]);
|
aConn.Triangles(i, t[0], t[1], t[2]);
|
||||||
for (j = 0; j < 3; j++) {
|
for (j = 0; j < 3; j++) {
|
||||||
if (t[j] == 0) {
|
if (t[j] == 0) {
|
||||||
@ -152,6 +161,15 @@ void MeshTest_CheckTopology::Perform ()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check of free nodes
|
||||||
|
Standard_Integer aNbNodes = aT->NbNodes();
|
||||||
|
for (Standard_Integer i = 1; i <= aNbNodes; i++)
|
||||||
|
if ( ! aUsedNodes.Contains(i) )
|
||||||
|
{
|
||||||
|
myFreeNodeFaces.Append (iF);
|
||||||
|
myFreeNodeNums.Append (i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,77 +11,96 @@
|
|||||||
#include <TColStd_SequenceOfInteger.hxx>
|
#include <TColStd_SequenceOfInteger.hxx>
|
||||||
#include <TColStd_SequenceOfReal.hxx>
|
#include <TColStd_SequenceOfReal.hxx>
|
||||||
|
|
||||||
// This class checks topology of the mesh presented by
|
//! This class checks topology of the mesh presented by
|
||||||
// triangulations of faces.
|
//! triangulations of faces.
|
||||||
//
|
//!
|
||||||
// The following error are reported:
|
//! The following error are reported:
|
||||||
// - free links. A link is considered free if it has only one
|
//! - free links. A link is considered free if it has only one
|
||||||
// neighboring triangle and at least one of its nodes belongs to
|
//! neighboring triangle and at least one of its nodes belongs to
|
||||||
// interior of the face rather than to its boundary.
|
//! interior of the face rather than to its boundary.
|
||||||
// - cross face errors. It is a situation when a point on a common
|
//! - cross face errors. It is a situation when a point on a common
|
||||||
// boundary between two faces has different 3d coordinates on each
|
//! boundary between two faces has different 3d coordinates on each
|
||||||
// triangulation. The error is reported if the distance is greater
|
//! triangulation. The error is reported if the distance is greater
|
||||||
// than a deflection written in triangulations.
|
//! than a deflection written in triangulations.
|
||||||
// - asynchronous edges. It is an edge having polygons on two neighboring
|
//! - asynchronous edges. It is an edge having polygons on two neighboring
|
||||||
// triangulations with different number of points in the polygons
|
//! triangulations with different number of points in the polygons.
|
||||||
|
//! - free nodes -- nodes not shared by any triangle.
|
||||||
|
|
||||||
class MeshTest_CheckTopology
|
class MeshTest_CheckTopology
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
//! constructor
|
||||||
MeshTest_CheckTopology(const TopoDS_Shape& theShape)
|
MeshTest_CheckTopology(const TopoDS_Shape& theShape)
|
||||||
: myShape(theShape) {}
|
: myShape(theShape) {}
|
||||||
// constructor
|
|
||||||
|
|
||||||
|
//! performs checking
|
||||||
Standard_EXPORT void Perform();
|
Standard_EXPORT void Perform();
|
||||||
// performs checking
|
|
||||||
|
|
||||||
|
//! returns the number of faces with free links
|
||||||
Standard_Integer NbFacesWithFL() const
|
Standard_Integer NbFacesWithFL() const
|
||||||
{ return myMapFaceLinks.Extent(); }
|
{ return myMapFaceLinks.Extent(); }
|
||||||
// returns the number of faces with free links
|
|
||||||
|
|
||||||
|
//! returns the number (in the shape) of a face with free links
|
||||||
|
//! with the given index
|
||||||
Standard_Integer GetFaceNumWithFL(const Standard_Integer theIndex) const
|
Standard_Integer GetFaceNumWithFL(const Standard_Integer theIndex) const
|
||||||
{ return myMapFaceLinks.FindKey(theIndex); }
|
{ return myMapFaceLinks.FindKey(theIndex); }
|
||||||
// returns the number (in the shape) of a face with free links
|
|
||||||
// with the given index
|
|
||||||
|
|
||||||
|
//! returns the number free links on a face with the given index
|
||||||
Standard_Integer NbFreeLinks(const Standard_Integer theIndex) const
|
Standard_Integer NbFreeLinks(const Standard_Integer theIndex) const
|
||||||
{ return myMapFaceLinks(theIndex).Length() / 2; }
|
{ return myMapFaceLinks(theIndex).Length() / 2; }
|
||||||
// returns the number free links on a face with the given index
|
|
||||||
|
|
||||||
|
//! gets the numbers of nodes of a free link with the given index
|
||||||
|
//! in the face with the given index
|
||||||
Standard_EXPORT void GetFreeLink(const Standard_Integer theFaceIndex,
|
Standard_EXPORT void GetFreeLink(const Standard_Integer theFaceIndex,
|
||||||
const Standard_Integer theLinkIndex,
|
const Standard_Integer theLinkIndex,
|
||||||
Standard_Integer& theNode1,
|
Standard_Integer& theNode1,
|
||||||
Standard_Integer& theNode2) const;
|
Standard_Integer& theNode2) const;
|
||||||
// gets the numbers of nodes of a free link with the given index
|
|
||||||
// in the face with the given index
|
|
||||||
|
|
||||||
|
//! returns the number of cross face errors
|
||||||
Standard_Integer NbCrossFaceErrors() const
|
Standard_Integer NbCrossFaceErrors() const
|
||||||
{ return myErrorsVal.Length(); }
|
{ return myErrorsVal.Length(); }
|
||||||
// returns the number of cross face errors
|
|
||||||
|
|
||||||
|
//! gets the attributes of a cross face error with the given index
|
||||||
Standard_EXPORT void GetCrossFaceError(const Standard_Integer theIndex,
|
Standard_EXPORT void GetCrossFaceError(const Standard_Integer theIndex,
|
||||||
Standard_Integer& theFace1,
|
Standard_Integer& theFace1,
|
||||||
Standard_Integer& theNode1,
|
Standard_Integer& theNode1,
|
||||||
Standard_Integer& theFace2,
|
Standard_Integer& theFace2,
|
||||||
Standard_Integer& theNode2,
|
Standard_Integer& theNode2,
|
||||||
Standard_Real& theValue) const;
|
Standard_Real& theValue) const;
|
||||||
// gets the attributes of a cross face error with the given index
|
|
||||||
|
|
||||||
|
//! returns the number of async edges
|
||||||
Standard_Integer NbAsyncEdges() const
|
Standard_Integer NbAsyncEdges() const
|
||||||
{ return myAsyncEdges.Length(); }
|
{ return myAsyncEdges.Length(); }
|
||||||
// returns the number of async edges
|
|
||||||
|
|
||||||
|
//! returns the number (in the shape) of an async edge with the given index
|
||||||
Standard_Integer GetAsyncEdgeNum(const Standard_Integer theIndex) const
|
Standard_Integer GetAsyncEdgeNum(const Standard_Integer theIndex) const
|
||||||
{ return myAsyncEdges(theIndex); }
|
{ return myAsyncEdges(theIndex); }
|
||||||
// returns the number (in the shape) of an async edge with the given index
|
|
||||||
|
//! returns the number of free nodes
|
||||||
|
Standard_Integer NbFreeNodes() const
|
||||||
|
{ return myFreeNodeFaces.Length(); }
|
||||||
|
|
||||||
|
//! returns the number of face containing the Index-th detected free node,
|
||||||
|
//! and number of this node in the triangulation of that face
|
||||||
|
void GetFreeNodeNum (const Standard_Integer theIndex,
|
||||||
|
Standard_Integer& theFaceNum,
|
||||||
|
Standard_Integer& theNodeNum) const
|
||||||
|
{
|
||||||
|
theFaceNum = myFreeNodeFaces(theIndex);
|
||||||
|
theNodeNum = myFreeNodeNums(theIndex);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TopoDS_Shape myShape;
|
TopoDS_Shape myShape;
|
||||||
NCollection_IndexedDataMap<Standard_Integer,TColStd_SequenceOfInteger>
|
NCollection_IndexedDataMap<Standard_Integer,TColStd_SequenceOfInteger>
|
||||||
myMapFaceLinks;
|
myMapFaceLinks;
|
||||||
|
|
||||||
TColStd_SequenceOfInteger myErrors;
|
TColStd_SequenceOfInteger myErrors;
|
||||||
TColStd_SequenceOfReal myErrorsVal;
|
TColStd_SequenceOfReal myErrorsVal;
|
||||||
|
|
||||||
TColStd_SequenceOfInteger myAsyncEdges;
|
TColStd_SequenceOfInteger myAsyncEdges;
|
||||||
|
TColStd_SequenceOfInteger myFreeNodeFaces;
|
||||||
|
TColStd_SequenceOfInteger myFreeNodeNums;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -318,8 +318,11 @@ static Standard_Integer checktopo (Draw_Interpretor& di, int n, const char ** a)
|
|||||||
TopExp::MapShapes (shape, TopAbs_FACE, aMapF);
|
TopExp::MapShapes (shape, TopAbs_FACE, aMapF);
|
||||||
Standard_CString name = ".";
|
Standard_CString name = ".";
|
||||||
|
|
||||||
|
// execute check
|
||||||
MeshTest_CheckTopology aCheck(shape);
|
MeshTest_CheckTopology aCheck(shape);
|
||||||
aCheck.Perform();
|
aCheck.Perform();
|
||||||
|
|
||||||
|
// dump info on free links inside the triangulation
|
||||||
Standard_Integer nbFree = 0;
|
Standard_Integer nbFree = 0;
|
||||||
Standard_Integer nbFac = aCheck.NbFacesWithFL(), i, k;
|
Standard_Integer nbFac = aCheck.NbFacesWithFL(), i, k;
|
||||||
if (nbFac > 0) {
|
if (nbFac > 0) {
|
||||||
@ -357,6 +360,7 @@ static Standard_Integer checktopo (Draw_Interpretor& di, int n, const char ** a)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// dump info on cross face errors
|
||||||
Standard_Integer nbErr = aCheck.NbCrossFaceErrors();
|
Standard_Integer nbErr = aCheck.NbCrossFaceErrors();
|
||||||
if (nbErr > 0) {
|
if (nbErr > 0) {
|
||||||
cout<<"cross face errors: {face1, node1, face2, node2, distance}"<<endl;
|
cout<<"cross face errors: {face1, node1, face2, node2, distance}"<<endl;
|
||||||
@ -369,6 +373,7 @@ static Standard_Integer checktopo (Draw_Interpretor& di, int n, const char ** a)
|
|||||||
cout<<endl;
|
cout<<endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// dump info on edges
|
||||||
Standard_Integer nbAsync = aCheck.NbAsyncEdges();
|
Standard_Integer nbAsync = aCheck.NbAsyncEdges();
|
||||||
if (nbAsync > 0) {
|
if (nbAsync > 0) {
|
||||||
cout<<"async edges:"<<endl;
|
cout<<"async edges:"<<endl;
|
||||||
@ -379,9 +384,23 @@ static Standard_Integer checktopo (Draw_Interpretor& di, int n, const char ** a)
|
|||||||
cout<<endl;
|
cout<<endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nbFree > 0 || nbErr > 0 || nbAsync > 0)
|
// dump info on free nodes
|
||||||
di<<"Free_links "<<nbFree
|
Standard_Integer nbFreeNodes = aCheck.NbFreeNodes();
|
||||||
<<" Cross_face_errors "<<nbErr
|
if (nbFreeNodes > 0) {
|
||||||
<<" Async_edges "<<nbAsync << " ";
|
cout << "free nodes (in pairs: face / node): " << endl;
|
||||||
|
for (i=1; i <= nbFreeNodes; i++) {
|
||||||
|
Standard_Integer iface, inode;
|
||||||
|
aCheck.GetFreeNodeNum(i, iface, inode);
|
||||||
|
cout << "{" << iface << " " << inode << "} ";
|
||||||
|
}
|
||||||
|
cout << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// output errors summary to DRAW
|
||||||
|
if ( nbFree > 0 || nbErr > 0 || nbAsync > 0 || nbFreeNodes > 0 )
|
||||||
|
di << "Free_links " << nbFree
|
||||||
|
<< " Cross_face_errors " << nbErr
|
||||||
|
<< " Async_edges " << nbAsync
|
||||||
|
<< " Free_nodes " << nbFreeNodes << " ";
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -204,15 +204,17 @@ void Poly_Connect::Initialize(const Standard_Integer N)
|
|||||||
mynode = N;
|
mynode = N;
|
||||||
myfirst = Triangle(N);
|
myfirst = Triangle(N);
|
||||||
mytr = myfirst;
|
mytr = myfirst;
|
||||||
|
|
||||||
Standard_Integer i, no[3];
|
|
||||||
const Poly_Array1OfTriangle& triangles = myTriangulation->Triangles();
|
|
||||||
triangles(myfirst).Get(no[0], no[1], no[2]);
|
|
||||||
for (i = 0; i < 3; i++)
|
|
||||||
if (no[i] == mynode) break;
|
|
||||||
myothernode = no[(i+2)%3];
|
|
||||||
mysense = Standard_True;
|
mysense = Standard_True;
|
||||||
mymore = Standard_True;
|
mymore = (myfirst != 0);
|
||||||
|
if (mymore)
|
||||||
|
{
|
||||||
|
Standard_Integer i, no[3];
|
||||||
|
const Poly_Array1OfTriangle& triangles = myTriangulation->Triangles();
|
||||||
|
triangles(myfirst).Get(no[0], no[1], no[2]);
|
||||||
|
for (i = 0; i < 3; i++)
|
||||||
|
if (no[i] == mynode) break;
|
||||||
|
myothernode = no[(i+2)%3];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//=======================================================================
|
//=======================================================================
|
||||||
|
Loading…
x
Reference in New Issue
Block a user