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 
16 #include <BRep_Tool.hxx>
17 #include <BRepCheck.hxx>
18 #include <BRepCheck_ListOfStatus.hxx>
19 #include <BRepCheck_Solid.hxx>
20 #include <BRepClass3d_SolidClassifier.hxx>
21 #include <Geom_Curve.hxx>
22 #include <gp_Pnt.hxx>
23 #include <Standard_Transient.hxx>
24 #include <NCollection_Map.hxx>
25 #include <NCollection_Vector.hxx>
26 #include <Precision.hxx>
27 #include <Standard_Type.hxx>
28 #include <TopExp_Explorer.hxx>
29 #include <TopoDS_Builder.hxx>
30 #include <TopoDS_Edge.hxx>
31 #include <TopoDS_Iterator.hxx>
32 #include <TopoDS_Shape.hxx>
33 #include <TopoDS_Shell.hxx>
34 #include <TopoDS_Solid.hxx>
35 #include <TopTools_MapOfShape.hxx>
36 #include <TopTools_ShapeMapHasher.hxx>
37 
38 IMPLEMENT_STANDARD_RTTIEXT(BRepCheck_Solid,BRepCheck_Result)
39 
40 //
41 class BRepCheck_HSC;
42 DEFINE_STANDARD_HANDLE(BRepCheck_HSC, Standard_Transient)
43 //=======================================================================
44 //class    : BRepCheck_HSC
45 //purpose  :
46 //=======================================================================
47 class BRepCheck_HSC : public Standard_Transient {
48  public:
49   //
50   Standard_EXPORT
BRepCheck_HSC()51     BRepCheck_HSC(){
52     };
53   //
54   Standard_EXPORT
~BRepCheck_HSC()55     virtual ~BRepCheck_HSC(){
56   };
57   //
58   Standard_EXPORT
SolidClassifier()59     BRepClass3d_SolidClassifier& SolidClassifier(){
60       return mySC;
61     };
62   //
63   DEFINE_STANDARD_RTTI_INLINE(BRepCheck_HSC,Standard_Transient);
64 
65  protected:
66   BRepClass3d_SolidClassifier mySC;
67 };
68 
69 //
70 //=======================================================================
71 //class    : BRepCheck_ToolSolid
72 //purpose  :
73 //=======================================================================
74 class BRepCheck_ToolSolid  {
75 
76  public:
77   DEFINE_STANDARD_ALLOC
78 
BRepCheck_ToolSolid()79   BRepCheck_ToolSolid() {
80     myIsHole=Standard_False;
81     myPntTol=Precision::Confusion();
82     myPnt.SetCoord(-1.,-1.,-1.);
83   };
84 
~BRepCheck_ToolSolid()85   virtual ~BRepCheck_ToolSolid() {
86   };
87   //
SetSolid(const TopoDS_Solid & aZ)88   void SetSolid(const TopoDS_Solid& aZ) {
89     mySolid=aZ;
90   };
91   //
Solid() const92   const TopoDS_Solid& Solid()const {
93     return mySolid;
94   };
95   //
IsHole() const96   Standard_Boolean IsHole() const {
97     return myIsHole;
98   };
99   //
InnerPoint()100   const gp_Pnt& InnerPoint() {
101     return myPnt;
102   }
103   //
CheckTol() const104   Standard_Real CheckTol() const {
105     return myPntTol;
106   };
107   //
108   // IsOut
IsOut(BRepCheck_ToolSolid & aOther)109   Standard_Boolean IsOut(BRepCheck_ToolSolid& aOther)  {
110     Standard_Boolean bFlag;
111     TopAbs_State aState;
112     //
113     BRepClass3d_SolidClassifier& aSC=myHSC->SolidClassifier();
114     //
115     aSC.Perform(aOther.InnerPoint(), aOther.CheckTol());
116     aState=aSC.State();
117     bFlag=(aState==TopAbs_OUT);
118     //
119     return bFlag;
120   };
121   //
122   // Init
Init()123   void Init() {
124     Standard_Real aT, aT1, aT2, aPAR_T;
125     TopExp_Explorer aExp;
126     //
127     // 0.myHSC
128     myHSC=new BRepCheck_HSC();
129     //
130     BRepClass3d_SolidClassifier& aSC=myHSC->SolidClassifier();
131     // 1. Load
132     aSC.Load(mySolid);
133     //
134     // 2. myIsHole
135     aSC.PerformInfinitePoint(::RealSmall());
136     myIsHole=(aSC.State()==TopAbs_IN);
137     //
138     // 3. myPnt
139     aPAR_T=0.43213918; // 10*e^(-PI)
140     aExp.Init(mySolid, TopAbs_EDGE);
141     for (; aExp.More();  aExp.Next()) {
142       const TopoDS_Edge& aE=*((TopoDS_Edge*)&aExp.Current());
143       if (!BRep_Tool::Degenerated(aE)) {
144         Handle(Geom_Curve) aC3D=BRep_Tool::Curve(aE, aT1, aT2);
145         aT=(1.-aPAR_T)*aT1 + aPAR_T*aT2;
146         myPnt=aC3D->Value(aT);
147         myPntTol = BRep_Tool::Tolerance(aE);
148         break;
149       }
150     }
151   };
152   //
153  protected:
154   Standard_Boolean myIsHole;
155   gp_Pnt myPnt;
156   Standard_Real myPntTol;
157   TopoDS_Solid mySolid;
158   Handle(BRepCheck_HSC) myHSC;
159 };
160 //
161 typedef NCollection_Vector<BRepCheck_ToolSolid>
162   BRepCheck_VectorOfToolSolid;
163 //
164 
165 //=======================================================================
166 //function : BRepCheck_Solid
167 //purpose  :
168 //=======================================================================
BRepCheck_Solid(const TopoDS_Solid & S)169 BRepCheck_Solid::BRepCheck_Solid (const TopoDS_Solid& S)
170 {
171   Init(S);
172 }
173 //=======================================================================
174 //function : Blind
175 //purpose  :
176 //=======================================================================
Blind()177 void BRepCheck_Solid::Blind()
178 {
179   if (!myBlind) {
180     // nothing more than in the minimum
181     myBlind = Standard_True;
182   }
183 }
184 //=======================================================================
185 //function : InContext
186 //purpose  :
187 //=======================================================================
InContext(const TopoDS_Shape &)188 void BRepCheck_Solid::InContext(const TopoDS_Shape& )
189 {
190 }
191 //=======================================================================
192 //function : Minimum
193 //purpose  :
194 //=======================================================================
Minimum()195 void BRepCheck_Solid::Minimum()
196 {
197   if (myMin) {
198     return;
199   }
200   myMin = Standard_True;
201   //
202   Standard_Boolean bFound, bIsHole, bFlag;
203   Standard_Integer i, j, aNbVTS, aNbVTS1, iCntSh, iCntShInt;
204   TopoDS_Solid aZ;
205   TopoDS_Iterator aIt, aItF;
206   TopoDS_Builder aBB;
207   TopExp_Explorer aExp;
208   TopTools_MapOfShape aMSS;
209   TopAbs_Orientation aOr;
210   BRepCheck_VectorOfToolSolid aVTS;
211 
212   Handle(BRepCheck_HListOfStatus) aNewList = new BRepCheck_HListOfStatus();
213   BRepCheck_ListOfStatus& aLST = **myMap.Bound (myShape, aNewList);
214   aLST.Append(BRepCheck_NoError);
215   //
216   //-------------------------------------------------
217   // 1. InvalidImbricationOfShells
218   bFound=Standard_False;
219   aExp.Init(myShape, TopAbs_FACE);
220   for (; !bFound && aExp.More(); aExp.Next()) {
221     const TopoDS_Shape& aF=aExp.Current();
222     if (!aMSS.Add(aF)) {
223       BRepCheck::Add (aLST, BRepCheck_InvalidImbricationOfShells);
224       bFound=!bFound;
225     }
226   }
227   //
228   //-------------------------------------------------
229   // 2.
230   //    - Too many growths,
231   //    - There is smt of the solid that is out of solid
232   iCntSh=0;
233   iCntShInt=0;
234   aIt.Initialize(myShape);
235   for (; aIt.More(); aIt.Next()) {
236     const TopoDS_Shape& aSx=aIt.Value();
237     //
238     if (aSx.ShapeType()!=TopAbs_SHELL) {
239       aOr=aSx.Orientation();
240       if (aOr!=TopAbs_INTERNAL) {
241         BRepCheck::Add (aLST, 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 (aLST, BRepCheck_BadOrientationOfSubshape);
282   }
283   //
284   aNbVTS=aVTS.Size();
285   if (aNbVTS<2) {
286     return;
287   }
288   //
289   aNbVTS1=0;
290   for (i=0; i<aNbVTS; ++i) {
291     BRepCheck_ToolSolid& aTS=aVTS(i);
292     //
293     aTS.Init();
294     bIsHole=aTS.IsHole();
295     if (!bIsHole) {
296       ++aNbVTS1;
297       if (aNbVTS1>1) {
298         // Too many growths
299         BRepCheck::Add (aLST, BRepCheck_EnclosedRegion);
300         break;
301       }
302     }
303   }
304   //
305   bFound=Standard_False;
306   aNbVTS1=aNbVTS-1;
307   for (i=0; !bFound && i<aNbVTS1; ++i) {
308     BRepCheck_ToolSolid& aTSi=aVTS(i);
309     //
310     for (j=i+1; !bFound && j<aNbVTS; ++j) {
311       BRepCheck_ToolSolid& aTSj=aVTS(j);
312       //
313       bFlag=aTSi.IsOut(aTSj);
314       if (bFlag) {
315         // smt of solid is out of solid
316         BRepCheck::Add (aLST, BRepCheck_SubshapeNotInShape);
317         bFound=!bFound;
318       }
319     }
320   }
321   //
322   //myMin = Standard_True;
323 }
324