d49be1bdec68c2d4cbd133719f5c71466223def8
[occt.git] / src / BRepCheck / BRepCheck_Solid.cxx
1 // Created by: Peter KURNEV
2 // Copyright (c) 2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 #include <BRepCheck_Solid.ixx>
16 //
17 #include <Standard_DefineHandle.hxx>
18 #include <MMgt_TShared.hxx>
19 //
20 #include <NCollection_Vector.hxx>
21 #include <NCollection_Map.hxx>
22 //
23 #include <gp_Pnt.hxx>
24 //
25 #include <Geom_Curve.hxx>
26 //
27 #include <TopoDS_Iterator.hxx>
28 #include <TopoDS_Solid.hxx>
29 #include <TopoDS_Shell.hxx>
30 #include <TopoDS_Edge.hxx>
31 #include <TopoDS_Builder.hxx>
32 #include <BRep_Tool.hxx>
33 //
34 #include <TopExp_Explorer.hxx>
35 //
36 #include <TopTools_MapOfShape.hxx>
37 #include <TopTools_ShapeMapHasher.hxx>
38 //
39 #include <BRepClass3d_SolidClassifier.hxx>
40 //
41 #include <BRepCheck.hxx>
42 #include <BRepCheck_ListOfStatus.hxx>
43
44
45 DEFINE_STANDARD_HANDLE(BRepCheck_HSC, MMgt_TShared);
46 //=======================================================================
47 //class    : BRepCheck_HSC
48 //purpose  :
49 //=======================================================================
50 class BRepCheck_HSC : public MMgt_TShared {
51  public: 
52   //
53   Standard_EXPORT
54     BRepCheck_HSC(){
55     };
56   //
57   Standard_EXPORT
58     virtual ~BRepCheck_HSC(){
59   };
60   //
61   Standard_EXPORT
62     BRepClass3d_SolidClassifier& SolidClassifier(){
63       return mySC;
64     };
65   //
66   DEFINE_STANDARD_RTTI(BRepCheck_HSC);
67
68  protected:
69   BRepClass3d_SolidClassifier mySC;
70 };
71 IMPLEMENT_STANDARD_HANDLE(BRepCheck_HSC, MMgt_TShared);
72 IMPLEMENT_STANDARD_RTTIEXT(BRepCheck_HSC, MMgt_TShared);
73 //
74 //=======================================================================
75 //class    : BRepCheck_ToolSolid
76 //purpose  : 
77 //=======================================================================
78 class BRepCheck_ToolSolid  {
79
80  public:
81   DEFINE_STANDARD_ALLOC
82
83   BRepCheck_ToolSolid() {
84     myIsHole=Standard_False;
85     myPnt.SetCoord(-1.,-1.,-1.);
86   };
87    
88   virtual ~BRepCheck_ToolSolid() {
89   };
90   // 
91   void SetSolid(const TopoDS_Solid& aZ) {
92     mySolid=aZ;
93   };
94   //
95   const TopoDS_Solid& Solid()const {
96     return mySolid;
97   };
98   //
99   Standard_Boolean IsHole() const {
100     return myIsHole;
101   };
102   //
103   const gp_Pnt& InnerPoint() {
104     return myPnt;
105   }
106   //
107   // IsOut
108   Standard_Boolean IsOut(BRepCheck_ToolSolid& aOther)  {
109     Standard_Boolean bFlag;
110     TopAbs_State aState;
111     //
112     BRepClass3d_SolidClassifier& aSC=myHSC->SolidClassifier();
113     //
114     aSC.Perform(aOther.myPnt, ::RealSmall());
115     aState=aSC.State();
116     bFlag=(aState==TopAbs_OUT);
117     //
118     return bFlag;
119   };
120   //
121   // Init
122   void Init() {
123     Standard_Real aT, aT1, aT2, aPAR_T;
124     TopExp_Explorer aExp;
125     //
126     // 0.myHSC
127     myHSC=new BRepCheck_HSC();
128     //
129     BRepClass3d_SolidClassifier& aSC=myHSC->SolidClassifier();
130     // 1. Load
131     aSC.Load(mySolid);
132     //
133     // 2. myIsHole
134     aSC.PerformInfinitePoint(::RealSmall());
135     myIsHole=(aSC.State()==TopAbs_IN);
136     // 
137     // 3. myPnt
138     aPAR_T=0.43213918; // 10*e^(-PI)
139     aExp.Init(mySolid, TopAbs_EDGE);
140     for (; aExp.More();  aExp.Next()) {
141       const TopoDS_Edge& aE=*((TopoDS_Edge*)&aExp.Current());
142       if (!BRep_Tool::Degenerated(aE)) {
143         Handle(Geom_Curve) aC3D=BRep_Tool::Curve(aE, aT1, aT2);
144         aT=(1.-aPAR_T)*aT1 + aPAR_T*aT2;
145         myPnt=aC3D->Value(aT);
146         break;
147       }
148     }
149   };
150   //
151  protected:
152   Standard_Boolean myIsHole;
153   gp_Pnt myPnt;
154   TopoDS_Solid mySolid;
155   Handle(BRepCheck_HSC) myHSC;
156 };
157 //
158 typedef NCollection_Vector<BRepCheck_ToolSolid>
159   BRepCheck_VectorOfToolSolid;
160 //
161
162 //=======================================================================
163 //function : BRepCheck_Solid
164 //purpose  : 
165 //=======================================================================
166 BRepCheck_Solid::BRepCheck_Solid (const TopoDS_Solid& S)
167 {
168   Init(S);
169 }
170 //=======================================================================
171 //function : Blind
172 //purpose  : 
173 //=======================================================================
174 void BRepCheck_Solid::Blind()
175 {
176   if (!myBlind) {
177     // nothing more than in the minimum
178     myBlind = Standard_True;
179   }
180 }
181 //=======================================================================
182 //function : InContext
183 //purpose  : 
184 //=======================================================================
185 void BRepCheck_Solid::InContext(const TopoDS_Shape& )
186 {
187 }
188 //=======================================================================
189 //function : Minimum
190 //purpose  : 
191 //=======================================================================
192 void BRepCheck_Solid::Minimum()
193 {
194   if (myMin) {
195     return;
196   }
197   myMin = Standard_True;
198   //
199   Standard_Boolean bFound, bIsHole, bFlag;
200   Standard_Integer i, j, aNbVTS, aNbVTS1, iCntSh, iCntShInt;
201   TopoDS_Solid aZ;
202   TopoDS_Iterator aIt, aItF;
203   TopoDS_Builder aBB;
204   TopExp_Explorer aExp;
205   TopTools_MapOfShape aMSS;
206   TopAbs_Orientation aOr; 
207   BRepCheck_VectorOfToolSolid aVTS;
208   BRepCheck_ListOfStatus thelist;
209   //
210   myMap.Bind(myShape, thelist);
211   BRepCheck_ListOfStatus& aLST = myMap(myShape);
212   aLST.Append(BRepCheck_NoError);
213   //
214   //-------------------------------------------------
215   // 1. InvalidImbricationOfShells
216   bFound=Standard_False;
217   aExp.Init(myShape, TopAbs_FACE);
218   for (; !bFound && aExp.More(); aExp.Next()) {
219     const TopoDS_Shape& aF=aExp.Current();
220     if (!aMSS.Add(aF)) {
221       BRepCheck::Add(myMap(myShape), 
222                      BRepCheck_InvalidImbricationOfShells);
223       bFound=!bFound;
224     }
225   } 
226   //
227   //-------------------------------------------------
228   // 2. 
229   //    - Too many growths,
230   //    - There is smt of the solid that is out of solid
231   iCntSh=0;
232   iCntShInt=0;
233   aIt.Initialize(myShape);
234   for (; aIt.More(); aIt.Next()) {
235     const TopoDS_Shape& aSx=aIt.Value();
236     //
237     if (aSx.ShapeType()!=TopAbs_SHELL) {
238       aOr=aSx.Orientation();
239       if (aOr!=TopAbs_INTERNAL) {
240         BRepCheck::Add(myMap(myShape), 
241                        BRepCheck_BadOrientationOfSubshape);
242       } 
243       continue;
244     }
245     //
246     const TopoDS_Shell& aSh=*((TopoDS_Shell*)&aSx);
247     //
248     // Skip internal shells
249     bFound=Standard_False;
250     aItF.Initialize(aSh);
251     for (; !bFound && aItF.More(); aItF.Next()) {
252       const TopoDS_Shape& aF=aItF.Value();
253       aOr=aF.Orientation();
254       if (aOr==TopAbs_INTERNAL) {
255         bFound=!bFound;
256       }
257     }
258     if (bFound) {
259       ++iCntShInt;
260       continue;
261     }
262     //
263     ++iCntSh;
264     //
265     // Skip not closed shells
266     if (!BRep_Tool::IsClosed(aSh)) {
267       continue;
268     }
269     //
270     aBB.MakeSolid(aZ);
271     aBB.Add(aZ, aSh);
272     //
273     BRepCheck_ToolSolid aTS;
274     //
275     aTS.SetSolid(aZ);
276     aVTS.Append(aTS);
277   }//for (; aIt.More(); aIt.Next()) {
278   //
279   if (!iCntSh && iCntShInt) {
280     // all shells in the solid are internal
281     BRepCheck::Add(myMap(myShape), 
282                    BRepCheck_BadOrientationOfSubshape);
283   }
284   //
285   aNbVTS=aVTS.Size();
286   if (aNbVTS<2) {
287     return;
288   }
289   //
290   aNbVTS1=0;
291   for (i=0; i<aNbVTS; ++i) {
292     BRepCheck_ToolSolid& aTS=aVTS(i);
293     //
294     aTS.Init();
295     bIsHole=aTS.IsHole();
296     if (!bIsHole) {
297       ++aNbVTS1;
298       if (aNbVTS1>1) {
299         // Too many growths
300         BRepCheck::Add(myMap(myShape), 
301                        BRepCheck_EnclosedRegion);
302         break;
303       }
304     }
305   }
306   //
307   bFound=Standard_False;
308   aNbVTS1=aNbVTS-1;
309   for (i=0; !bFound && i<aNbVTS1; ++i) {
310     BRepCheck_ToolSolid& aTSi=aVTS(i);
311     //
312     for (j=i+1; !bFound && j<aNbVTS; ++j) {
313       BRepCheck_ToolSolid& aTSj=aVTS(j);
314       //
315       bFlag=aTSi.IsOut(aTSj);
316       if (bFlag) {
317         // smt of solid is out of solid
318         BRepCheck::Add(myMap(myShape), 
319                        BRepCheck_SubshapeNotInShape);
320         bFound=!bFound;
321       }
322     }
323   }
324   //
325   //myMin = Standard_True;
326 }