Warnings on vc14 were eliminated
[occt.git] / src / MeshTest / MeshTest_CheckTopology.cxx
1 // Created on: 2004-05-10
2 // Created by: Michael SAZONOV
3 // Copyright (c) 2004-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <MeshTest_CheckTopology.hxx>
17 #include <BRep_Tool.hxx>
18 #include <TColStd_PackedMapOfInteger.hxx>
19 #include <TopExp.hxx>
20 #include <TopExp_Explorer.hxx>
21 #include <TopoDS_Edge.hxx>
22 #include <TopoDS.hxx>
23 #include <TopoDS_Face.hxx>
24 #include <TopLoc_Location.hxx>
25 #include <TopTools_IndexedMapOfShape.hxx>
26 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
27 #include <TopTools_ListOfShape.hxx>
28 #include <TopTools_ListIteratorOfListOfShape.hxx>
29 #include <Poly_Triangulation.hxx>
30 #include <Poly_PolygonOnTriangulation.hxx>
31 #include <Poly_Connect.hxx>
32
33 //=======================================================================
34 //function : Perform
35 //purpose  : Performs checking
36 //=======================================================================
37
38 void MeshTest_CheckTopology::Perform (Draw_Interpretor& di)
39 {
40   TopTools_IndexedMapOfShape aMapF;
41   TopTools_IndexedDataMapOfShapeListOfShape aMapEF;
42   TopExp::MapShapes (myShape, TopAbs_FACE, aMapF);
43   TopExp::MapShapesAndAncestors (myShape, TopAbs_EDGE, TopAbs_FACE, aMapEF);
44
45   // check polygons
46   Standard_Integer ie;
47   for (ie=1; ie <= aMapEF.Extent(); ie++) {
48     const TopoDS_Edge& aEdge = TopoDS::Edge(aMapEF.FindKey(ie));
49     const TopTools_ListOfShape& aFaces = aMapEF(ie);
50     if (aFaces.Extent() < 2) continue;
51
52     // get polygon on first face
53     const TopoDS_Face& aFace1 = TopoDS::Face(aFaces.First());
54     TopLoc_Location aLoc1;
55     Handle(Poly_Triangulation) aT1 = BRep_Tool::Triangulation(aFace1, aLoc1);
56     Handle(Poly_PolygonOnTriangulation) aPoly1 =
57       BRep_Tool::PolygonOnTriangulation(aEdge, aT1, aLoc1);
58     if (aPoly1.IsNull() || aT1.IsNull()) {
59 #ifdef OCCT_DEBUG
60       cout<<"problem getting PolygonOnTriangulation of edge "<<ie<<endl;
61 #endif
62       continue;
63     }
64     const TColStd_Array1OfInteger& aNodes1 = aPoly1->Nodes();
65
66     // cycle on other polygons
67     TopTools_ListIteratorOfListOfShape it(aFaces);
68     it.Next();
69     for (; it.More(); it.Next()) {
70       const TopoDS_Face& aFace2 = TopoDS::Face(it.Value());
71       TopLoc_Location aLoc2;
72       Handle(Poly_Triangulation) aT2 = BRep_Tool::Triangulation(aFace2, aLoc2);
73       Handle(Poly_PolygonOnTriangulation) aPoly2 =
74         BRep_Tool::PolygonOnTriangulation(aEdge, aT2, aLoc2);
75       if (aPoly2.IsNull() || aT2.IsNull()) {
76 #ifdef OCCT_DEBUG
77         cout<<"problem getting PolygonOnTriangulation of edge "<<ie<<endl;
78 #endif
79         continue;
80       }
81       const TColStd_Array1OfInteger& aNodes2 = aPoly2->Nodes();
82
83       // check equality of polygons lengths
84       if (aNodes2.Length() != aNodes1.Length()) {
85         myAsyncEdges.Append(ie);
86         break;
87       }
88
89       // check distances between corresponding points
90       Standard_Real aDefle = Max(aT1->Deflection(), aT2->Deflection());
91       const TColgp_Array1OfPnt& aPoints1 = aT1->Nodes();
92       const TColgp_Array1OfPnt& aPoints2 = aT2->Nodes();
93       Standard_Integer iF1 = aMapF.FindIndex(aFace1);
94       Standard_Integer iF2 = aMapF.FindIndex(aFace2);
95       Standard_Integer i1 = aNodes1.Lower();
96       Standard_Integer i2 = aNodes2.Lower();
97       gp_Trsf aTrsf1 = aFace1.Location().Transformation();
98       gp_Trsf aTrsf2 = aFace2.Location().Transformation();
99       for (; i1 <= aNodes1.Upper(); i1++, i2++) {
100         gp_Pnt aP1 = aPoints1(aNodes1(i1)).Transformed(aTrsf1);
101         gp_Pnt aP2 = aPoints2(aNodes2(i2)).Transformed(aTrsf2);
102         Standard_Real aDist = aP1.Distance(aP2);
103         if (aDist > aDefle) {
104           myErrors.Append(iF1);
105           myErrors.Append(i1);
106           myErrors.Append(iF2);
107           myErrors.Append(i2);
108           myErrorsVal.Append(aDist);
109         }
110       }
111     }
112   }
113
114   // check triangulations
115   Standard_Integer iF;
116   for (iF=1; iF <= aMapF.Extent(); iF++) {
117     const TopoDS_Face& aFace = TopoDS::Face(aMapF.FindKey(iF));
118     TopLoc_Location aLoc;
119     Handle(Poly_Triangulation) aT = BRep_Tool::Triangulation(aFace, aLoc);
120     if (aT.IsNull()) {
121       di << "face " <<iF <<" has no triangulation\n";
122       continue;
123     }
124
125     // remember boundary nodes
126     TColStd_PackedMapOfInteger aMapBndNodes;
127     TopExp_Explorer ex(aFace, TopAbs_EDGE);
128     for (; ex.More(); ex.Next()) {
129       const TopoDS_Edge& aEdge = TopoDS::Edge(ex.Current());
130       Handle(Poly_PolygonOnTriangulation) aPoly =
131         BRep_Tool::PolygonOnTriangulation(aEdge, aT, aLoc);
132       if (aPoly.IsNull()) continue;
133       const TColStd_Array1OfInteger& aNodes = aPoly->Nodes();
134       Standard_Integer i;
135       for (i=aNodes.Lower(); i <= aNodes.Upper(); i++)
136         aMapBndNodes.Add(aNodes(i));
137     }
138
139     TColStd_PackedMapOfInteger aUsedNodes;
140
141     // check of free links and nodes
142     Poly_Connect aConn(aT);
143     const Poly_Array1OfTriangle& aTriangles = aT->Triangles();
144     Standard_Integer nbTri = aT->NbTriangles(), i, j, n[3], t[3];
145     for (i = 1; i <= nbTri; i++) {
146       aTriangles(i).Get(n[0], n[1], n[2]);
147       
148       aUsedNodes.Add (n[0]);
149       aUsedNodes.Add (n[1]);
150       aUsedNodes.Add (n[2]);
151
152       aConn.Triangles(i, t[0], t[1], t[2]);
153       for (j = 0; j < 3; j++) {
154         if (t[j] == 0) {
155           // free link found
156           Standard_Integer k = (j+1) % 3;  // the following node of the edge
157           Standard_Integer n1 = n[j];
158           Standard_Integer n2 = n[k];
159           // skip if it is on boundary
160           if (aMapBndNodes.Contains(n1) && aMapBndNodes.Contains(n2))
161             continue;
162           if (!myMapFaceLinks.Contains(iF)) {
163             Handle(TColStd_HSequenceOfInteger) tmpSeq = new TColStd_HSequenceOfInteger;
164             myMapFaceLinks.Add(iF, tmpSeq);
165           }
166           Handle(TColStd_HSequenceOfInteger)& aSeq = myMapFaceLinks.ChangeFromKey(iF);
167           aSeq->Append(n1);
168           aSeq->Append(n2);
169         }
170       }
171     }
172     
173     // check of free nodes
174     Standard_Integer aNbNodes = aT->NbNodes();
175     for (Standard_Integer k = 1; k <= aNbNodes; k++)
176       if ( ! aUsedNodes.Contains(k) )
177       {
178         myFreeNodeFaces.Append (iF);
179         myFreeNodeNums.Append (k);
180       }
181   }
182 }
183
184 //=======================================================================
185 //function : GetFreeLink
186 //purpose  : gets the numbers of nodes of a free link with the given index
187 //           in the face with the given index
188 //=======================================================================
189
190 void MeshTest_CheckTopology::GetFreeLink(const Standard_Integer theFaceIndex,
191                                          const Standard_Integer theLinkIndex,
192                                          Standard_Integer& theNode1,
193                                          Standard_Integer& theNode2) const
194 {
195   const Handle(TColStd_HSequenceOfInteger)& aSeq = myMapFaceLinks(theFaceIndex);
196   Standard_Integer aInd = (theLinkIndex-1)*2 + 1;
197   theNode1 = aSeq->Value(aInd);
198   theNode2 = aSeq->Value(aInd+1);
199 }
200
201 //=======================================================================
202 //function : GetCrossFaceError
203 //purpose  : gets the attributes of a cross face error with the given index
204 //=======================================================================
205
206 void MeshTest_CheckTopology::GetCrossFaceError(const Standard_Integer theIndex,
207                                                Standard_Integer& theFace1,
208                                                Standard_Integer& theNode1,
209                                                Standard_Integer& theFace2,
210                                                Standard_Integer& theNode2,
211                                                Standard_Real&    theValue) const
212 {
213   Standard_Integer aInd = (theIndex-1)*4 + 1;
214   theFace1 = myErrors(aInd);
215   theNode1 = myErrors(aInd+1);
216   theFace2 = myErrors(aInd+2);
217   theNode2 = myErrors(aInd+3);
218   theValue = myErrorsVal(theIndex);
219 }