1
0
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:
ABV 2011-05-19 11:00:31 +00:00 committed by bugmaster
parent 587630c5be
commit 446e11f3c6
4 changed files with 97 additions and 39 deletions

View File

@ -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);
}
} }
} }

View File

@ -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

View File

@ -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;
} }

View File

@ -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];
}
} }
//======================================================================= //=======================================================================