0026640: ShapeFix_Edge::FixAddPCurve problem in OCC 6.8
[occt.git] / src / MeshTest / MeshTest_CheckTopology.cxx
CommitLineData
b311480e 1// Created on: 2004-05-10
2// Created by: Michael SAZONOV
973c2be1 3// Copyright (c) 2004-2014 OPEN CASCADE SAS
b311480e 4//
973c2be1 5// This file is part of Open CASCADE Technology software library.
b311480e 6//
d5f74e42 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
973c2be1 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.
b311480e 12//
973c2be1 13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
7fd59977 15
16#include <MeshTest_CheckTopology.hxx>
17#include <BRep_Tool.hxx>
446e11f3 18#include <TColStd_PackedMapOfInteger.hxx>
7fd59977 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
d2c43192 38void MeshTest_CheckTopology::Perform (Draw_Interpretor& di)
7fd59977 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()) {
0797d9d3 59#ifdef OCCT_DEBUG
7fd59977 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()) {
0797d9d3 76#ifdef OCCT_DEBUG
7fd59977 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()) {
d2c43192 121 di << "face " <<iF <<" has no triangulation" << "\n";
7fd59977 122 continue;
123 }
446e11f3 124
7fd59977 125 // remember boundary nodes
446e11f3 126 TColStd_PackedMapOfInteger aMapBndNodes;
7fd59977 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
446e11f3
A
139 TColStd_PackedMapOfInteger aUsedNodes;
140
141 // check of free links and nodes
7fd59977 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]);
446e11f3
A
147
148 aUsedNodes.Add (n[0]);
149 aUsedNodes.Add (n[1]);
150 aUsedNodes.Add (n[2]);
151
7fd59977 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)) {
e3a6386d 163 Handle(TColStd_HSequenceOfInteger) tmpSeq = new TColStd_HSequenceOfInteger;
7fd59977 164 myMapFaceLinks.Add(iF, tmpSeq);
165 }
e3a6386d 166 Handle(TColStd_HSequenceOfInteger)& aSeq = myMapFaceLinks.ChangeFromKey(iF);
167 aSeq->Append(n1);
168 aSeq->Append(n2);
7fd59977 169 }
170 }
171 }
446e11f3
A
172
173 // check of free nodes
174 Standard_Integer aNbNodes = aT->NbNodes();
175 for (Standard_Integer i = 1; i <= aNbNodes; i++)
176 if ( ! aUsedNodes.Contains(i) )
177 {
178 myFreeNodeFaces.Append (iF);
179 myFreeNodeNums.Append (i);
180 }
7fd59977 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
190void MeshTest_CheckTopology::GetFreeLink(const Standard_Integer theFaceIndex,
191 const Standard_Integer theLinkIndex,
192 Standard_Integer& theNode1,
193 Standard_Integer& theNode2) const
194{
e3a6386d 195 const Handle(TColStd_HSequenceOfInteger)& aSeq = myMapFaceLinks(theFaceIndex);
7fd59977 196 Standard_Integer aInd = (theLinkIndex-1)*2 + 1;
e3a6386d 197 theNode1 = aSeq->Value(aInd);
198 theNode2 = aSeq->Value(aInd+1);
7fd59977 199}
200
201//=======================================================================
202//function : GetCrossFaceError
203//purpose : gets the attributes of a cross face error with the given index
204//=======================================================================
205
206void 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}