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