1 // File: MeshTest_CheckTopology.cxx
3 // Author: Michael SAZONOV
5 #include <MeshTest_CheckTopology.hxx>
6 #include <BRep_Tool.hxx>
7 #include <TColStd_PackedMapOfInteger.hxx>
9 #include <TopExp_Explorer.hxx>
10 #include <TopoDS_Edge.hxx>
12 #include <TopoDS_Face.hxx>
13 #include <TopLoc_Location.hxx>
14 #include <TopTools_IndexedMapOfShape.hxx>
15 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
16 #include <TopTools_ListOfShape.hxx>
17 #include <TopTools_ListIteratorOfListOfShape.hxx>
18 #include <Poly_Triangulation.hxx>
19 #include <Poly_PolygonOnTriangulation.hxx>
20 #include <Poly_Connect.hxx>
22 //=======================================================================
24 //purpose : Performs checking
25 //=======================================================================
27 void MeshTest_CheckTopology::Perform ()
29 TopTools_IndexedMapOfShape aMapF;
30 TopTools_IndexedDataMapOfShapeListOfShape aMapEF;
31 TopExp::MapShapes (myShape, TopAbs_FACE, aMapF);
32 TopExp::MapShapesAndAncestors (myShape, TopAbs_EDGE, TopAbs_FACE, aMapEF);
36 for (ie=1; ie <= aMapEF.Extent(); ie++) {
37 const TopoDS_Edge& aEdge = TopoDS::Edge(aMapEF.FindKey(ie));
38 const TopTools_ListOfShape& aFaces = aMapEF(ie);
39 if (aFaces.Extent() < 2) continue;
41 // get polygon on first face
42 const TopoDS_Face& aFace1 = TopoDS::Face(aFaces.First());
43 TopLoc_Location aLoc1;
44 Handle(Poly_Triangulation) aT1 = BRep_Tool::Triangulation(aFace1, aLoc1);
45 Handle(Poly_PolygonOnTriangulation) aPoly1 =
46 BRep_Tool::PolygonOnTriangulation(aEdge, aT1, aLoc1);
47 if (aPoly1.IsNull() || aT1.IsNull()) {
49 cout<<"problem getting PolygonOnTriangulation of edge "<<ie<<endl;
53 const TColStd_Array1OfInteger& aNodes1 = aPoly1->Nodes();
55 // cycle on other polygons
56 TopTools_ListIteratorOfListOfShape it(aFaces);
58 for (; it.More(); it.Next()) {
59 const TopoDS_Face& aFace2 = TopoDS::Face(it.Value());
60 TopLoc_Location aLoc2;
61 Handle(Poly_Triangulation) aT2 = BRep_Tool::Triangulation(aFace2, aLoc2);
62 Handle(Poly_PolygonOnTriangulation) aPoly2 =
63 BRep_Tool::PolygonOnTriangulation(aEdge, aT2, aLoc2);
64 if (aPoly2.IsNull() || aT2.IsNull()) {
66 cout<<"problem getting PolygonOnTriangulation of edge "<<ie<<endl;
70 const TColStd_Array1OfInteger& aNodes2 = aPoly2->Nodes();
72 // check equality of polygons lengths
73 if (aNodes2.Length() != aNodes1.Length()) {
74 myAsyncEdges.Append(ie);
78 // check distances between corresponding points
79 Standard_Real aDefle = Max(aT1->Deflection(), aT2->Deflection());
80 const TColgp_Array1OfPnt& aPoints1 = aT1->Nodes();
81 const TColgp_Array1OfPnt& aPoints2 = aT2->Nodes();
82 Standard_Integer iF1 = aMapF.FindIndex(aFace1);
83 Standard_Integer iF2 = aMapF.FindIndex(aFace2);
84 Standard_Integer i1 = aNodes1.Lower();
85 Standard_Integer i2 = aNodes2.Lower();
86 gp_Trsf aTrsf1 = aFace1.Location().Transformation();
87 gp_Trsf aTrsf2 = aFace2.Location().Transformation();
88 for (; i1 <= aNodes1.Upper(); i1++, i2++) {
89 gp_Pnt aP1 = aPoints1(aNodes1(i1)).Transformed(aTrsf1);
90 gp_Pnt aP2 = aPoints2(aNodes2(i2)).Transformed(aTrsf2);
91 Standard_Real aDist = aP1.Distance(aP2);
97 myErrorsVal.Append(aDist);
103 // check triangulations
105 for (iF=1; iF <= aMapF.Extent(); iF++) {
106 const TopoDS_Face& aFace = TopoDS::Face(aMapF.FindKey(iF));
107 TopLoc_Location aLoc;
108 Handle(Poly_Triangulation) aT = BRep_Tool::Triangulation(aFace, aLoc);
110 cout<< "face "<<iF<<" has no triangulation"<<endl;
114 // remember boundary nodes
115 TColStd_PackedMapOfInteger aMapBndNodes;
116 TopExp_Explorer ex(aFace, TopAbs_EDGE);
117 for (; ex.More(); ex.Next()) {
118 const TopoDS_Edge& aEdge = TopoDS::Edge(ex.Current());
119 Handle(Poly_PolygonOnTriangulation) aPoly =
120 BRep_Tool::PolygonOnTriangulation(aEdge, aT, aLoc);
121 if (aPoly.IsNull()) continue;
122 const TColStd_Array1OfInteger& aNodes = aPoly->Nodes();
124 for (i=aNodes.Lower(); i <= aNodes.Upper(); i++)
125 aMapBndNodes.Add(aNodes(i));
128 TColStd_PackedMapOfInteger aUsedNodes;
130 // check of free links and nodes
131 Poly_Connect aConn(aT);
132 const Poly_Array1OfTriangle& aTriangles = aT->Triangles();
133 Standard_Integer nbTri = aT->NbTriangles(), i, j, n[3], t[3];
134 for (i = 1; i <= nbTri; i++) {
135 aTriangles(i).Get(n[0], n[1], n[2]);
137 aUsedNodes.Add (n[0]);
138 aUsedNodes.Add (n[1]);
139 aUsedNodes.Add (n[2]);
141 aConn.Triangles(i, t[0], t[1], t[2]);
142 for (j = 0; j < 3; j++) {
145 Standard_Integer k = (j+1) % 3; // the following node of the edge
146 Standard_Integer n1 = n[j];
147 Standard_Integer n2 = n[k];
148 // skip if it is on boundary
149 if (aMapBndNodes.Contains(n1) && aMapBndNodes.Contains(n2))
151 if (!myMapFaceLinks.Contains(iF)) {
152 //myMapFaceLinks.Add(iF, TColStd_SequenceOfInteger());
153 TColStd_SequenceOfInteger tmpSeq;
154 myMapFaceLinks.Add(iF, tmpSeq);
156 TColStd_SequenceOfInteger& aSeq = myMapFaceLinks.ChangeFromKey(iF);
163 // check of free nodes
164 Standard_Integer aNbNodes = aT->NbNodes();
165 for (Standard_Integer i = 1; i <= aNbNodes; i++)
166 if ( ! aUsedNodes.Contains(i) )
168 myFreeNodeFaces.Append (iF);
169 myFreeNodeNums.Append (i);
174 //=======================================================================
175 //function : GetFreeLink
176 //purpose : gets the numbers of nodes of a free link with the given index
177 // in the face with the given index
178 //=======================================================================
180 void MeshTest_CheckTopology::GetFreeLink(const Standard_Integer theFaceIndex,
181 const Standard_Integer theLinkIndex,
182 Standard_Integer& theNode1,
183 Standard_Integer& theNode2) const
185 const TColStd_SequenceOfInteger& aSeq = myMapFaceLinks(theFaceIndex);
186 Standard_Integer aInd = (theLinkIndex-1)*2 + 1;
187 theNode1 = aSeq(aInd);
188 theNode2 = aSeq(aInd+1);
191 //=======================================================================
192 //function : GetCrossFaceError
193 //purpose : gets the attributes of a cross face error with the given index
194 //=======================================================================
196 void MeshTest_CheckTopology::GetCrossFaceError(const Standard_Integer theIndex,
197 Standard_Integer& theFace1,
198 Standard_Integer& theNode1,
199 Standard_Integer& theFace2,
200 Standard_Integer& theNode2,
201 Standard_Real& theValue) const
203 Standard_Integer aInd = (theIndex-1)*4 + 1;
204 theFace1 = myErrors(aInd);
205 theNode1 = myErrors(aInd+1);
206 theFace2 = myErrors(aInd+2);
207 theNode2 = myErrors(aInd+3);
208 theValue = myErrorsVal(theIndex);