0029814: Modeling Data - add method TopoDS_Shape::NbChildren() for simple check of...
[occt.git] / src / BRepGProp / BRepGProp.cxx
1 // Copyright (c) 1995-1999 Matra Datavision
2 // Copyright (c) 1999-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 <BRepGProp.hxx>
16 #include <BRepGProp_Cinert.hxx>
17 #include <BRepGProp_Sinert.hxx>
18 #include <BRepGProp_Vinert.hxx>
19 #include <BRepGProp_VinertGK.hxx>
20 #include <GProp_PGProps.hxx>
21 #include <BRepGProp_Face.hxx>
22 #include <BRepGProp_Domain.hxx>
23 #include <TopoDS.hxx>
24 #include <BRepAdaptor_Curve.hxx>
25
26 #include <TopTools.hxx>
27 #include <BRep_Tool.hxx>  
28 #include <TopTools_ListOfShape.hxx>
29 #include <TopTools_MapOfShape.hxx>
30 #include <BRepCheck_Shell.hxx>
31 #include <TopTools_ListIteratorOfListOfShape.hxx>
32 #ifdef OCCT_DEBUG
33 static Standard_Integer AffichEps = 0;
34 #endif
35
36 static gp_Pnt roughBaryCenter(const TopoDS_Shape& S){
37   Standard_Integer i;  TopExp_Explorer ex;
38   gp_XYZ xyz(0,0,0);
39   for (ex.Init(S,TopAbs_VERTEX), i = 0; ex.More(); ex.Next(), i++) 
40     xyz += BRep_Tool::Pnt(TopoDS::Vertex(ex.Current())).XYZ();
41   if ( i > 0 ) xyz /= i;
42   return gp_Pnt(xyz);
43 }
44
45 void  BRepGProp::LinearProperties(const TopoDS_Shape& S, GProp_GProps& SProps, const Standard_Boolean SkipShared){
46   // find the origin
47   gp_Pnt P(0,0,0);
48   P.Transform(S.Location());
49   SProps = GProp_GProps(P);
50
51   BRepAdaptor_Curve   BAC;
52   Standard_Real eps = Epsilon(1.);
53   TopTools_MapOfShape anEMap;
54   TopExp_Explorer ex;
55   for (ex.Init(S,TopAbs_EDGE); ex.More(); ex.Next()) {
56     const TopoDS_Edge& aE = TopoDS::Edge(ex.Current());
57     if(SkipShared && !anEMap.Add(aE))
58     {
59       continue;
60     }
61     if(!BRep_Tool::IsGeometric(aE))
62     {
63       GProp_PGProps aPProps;
64       TopoDS_Iterator anIter(aE);
65       for(; anIter.More(); anIter.Next())
66       {
67         const TopoDS_Vertex& aV = TopoDS::Vertex(anIter.Value());
68         aPProps.AddPoint(BRep_Tool::Pnt(aV), eps);
69       }
70       SProps.Add(aPProps);
71     }
72     else
73     {
74       BAC.Initialize(aE);
75       BRepGProp_Cinert CG(BAC,P);
76       SProps.Add(CG);
77     }
78   }
79 }
80
81 static Standard_Real surfaceProperties(const TopoDS_Shape& S, GProp_GProps& Props, const Standard_Real Eps, const Standard_Boolean SkipShared){
82   Standard_Integer i;
83 #ifdef OCCT_DEBUG
84   Standard_Integer iErrorMax = 0;
85 #endif
86   Standard_Real ErrorMax = 0.0, Error;
87   TopExp_Explorer ex; 
88   gp_Pnt P(roughBaryCenter(S));
89   BRepGProp_Sinert G;  G.SetLocation(P);
90
91   BRepGProp_Face   BF;
92   BRepGProp_Domain BD;
93   TopTools_MapOfShape aFMap;
94   TopLoc_Location aLocDummy;
95
96   for (ex.Init(S,TopAbs_FACE), i = 1; ex.More(); ex.Next(), i++) {
97     const TopoDS_Face& F = TopoDS::Face(ex.Current());
98     if(SkipShared && !aFMap.Add(F))
99     {
100       continue;
101     }
102
103     {
104       const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface (F, aLocDummy);
105       if (aSurf.IsNull())
106       {
107         // skip faces without geometry
108         continue;
109       }
110     }
111
112     BF.Load(F);
113     Standard_Boolean IsNatRestr = (F.NbChildren() == 0);
114     if(!IsNatRestr) BD.Init(F);
115     if(Eps < 1.0) {
116       G.Perform(BF, BD, Eps); 
117       Error = G.GetEpsilon();
118       if(ErrorMax < Error) {
119         ErrorMax = Error;
120 #ifdef OCCT_DEBUG
121         iErrorMax = i;
122 #endif
123       }
124     } else {
125       if(IsNatRestr) G.Perform(BF);
126       else G.Perform(BF, BD);
127     }
128     Props.Add(G);
129 #ifdef OCCT_DEBUG
130     if(AffichEps) cout<<"\n"<<i<<":\tEpsArea = "<< G.GetEpsilon();
131 #endif
132   }
133 #ifdef OCCT_DEBUG
134   if(AffichEps) cout<<"\n-----------------\n"<<iErrorMax<<":\tMaxError = "<<ErrorMax<<"\n";
135 #endif
136   return ErrorMax;
137 }
138 void  BRepGProp::SurfaceProperties(const TopoDS_Shape& S, GProp_GProps& Props, const Standard_Boolean SkipShared){
139   // find the origin
140   gp_Pnt P(0,0,0);
141   P.Transform(S.Location());
142   Props = GProp_GProps(P);
143   surfaceProperties(S,Props,1.0, SkipShared);
144 }
145 Standard_Real BRepGProp::SurfaceProperties(const TopoDS_Shape& S, GProp_GProps& Props, const Standard_Real Eps, const Standard_Boolean SkipShared){ 
146   // find the origin
147   gp_Pnt P(0,0,0);  P.Transform(S.Location());
148   Props = GProp_GProps(P);
149   Standard_Real ErrorMax = surfaceProperties(S,Props,Eps,SkipShared);
150   return ErrorMax;
151 }
152
153 //=======================================================================
154 //function : volumeProperties
155 //purpose  : 
156 //=======================================================================
157
158 static Standard_Real volumeProperties(const TopoDS_Shape& S, GProp_GProps& Props, const Standard_Real Eps, const Standard_Boolean SkipShared){
159   Standard_Integer i;
160 #ifdef OCCT_DEBUG
161   Standard_Integer iErrorMax = 0;
162 #endif
163   Standard_Real ErrorMax = 0.0, Error = 0.0;
164   TopExp_Explorer ex; 
165   gp_Pnt P(roughBaryCenter(S)); 
166   BRepGProp_Vinert G;  G.SetLocation(P);
167
168   BRepGProp_Face   BF;
169   BRepGProp_Domain BD;
170   TopTools_MapOfShape aFwdFMap;
171   TopTools_MapOfShape aRvsFMap;
172   TopLoc_Location aLocDummy;
173
174   for (ex.Init(S,TopAbs_FACE), i = 1; ex.More(); ex.Next(), i++) {
175     const TopoDS_Face& F = TopoDS::Face(ex.Current());
176     TopAbs_Orientation anOri = F.Orientation();
177     Standard_Boolean isFwd = anOri == TopAbs_FORWARD;
178     Standard_Boolean isRvs = Standard_False;
179     if(!isFwd)
180     {
181       isRvs = anOri == TopAbs_REVERSED;
182     }
183     if(SkipShared)
184     {
185       if((isFwd && !aFwdFMap.Add(F)) || (isRvs && !aRvsFMap.Add(F)))
186       {
187         continue;
188       }
189     }
190     {
191       const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface (F, aLocDummy);
192       if (aSurf.IsNull())
193       {
194         // skip faces without geometry
195         continue;
196       }
197     }
198
199     if (isFwd || isRvs){
200       BF.Load(F);
201       Standard_Boolean IsNatRestr = (F.NbChildren () == 0);
202       if(!IsNatRestr) BD.Init(F);
203       if(Eps < 1.0) {
204         G.Perform(BF, BD, Eps); 
205         Error = G.GetEpsilon();
206         if(ErrorMax < Error) {
207           ErrorMax = Error;
208 #ifdef OCCT_DEBUG
209           iErrorMax = i;
210 #endif
211         }
212       }
213       else {
214         if(IsNatRestr) G.Perform(BF);
215         else G.Perform(BF, BD);
216       }
217       Props.Add(G);
218 #ifdef OCCT_DEBUG
219       if(AffichEps) cout<<"\n"<<i<<":\tEpsVolume = "<< G.GetEpsilon();
220 #endif
221     }
222   }
223 #ifdef OCCT_DEBUG
224   if(AffichEps) cout<<"\n-----------------\n"<<iErrorMax<<":\tMaxError = "<<ErrorMax<<"\n";
225 #endif
226   return ErrorMax;
227 }
228 void  BRepGProp::VolumeProperties(const TopoDS_Shape& S, GProp_GProps& Props, const Standard_Boolean OnlyClosed, const Standard_Boolean SkipShared){
229   // find the origin
230   gp_Pnt P(0,0,0);  P.Transform(S.Location());
231   Props = GProp_GProps(P);
232   if(OnlyClosed){
233     TopTools_MapOfShape aShMap;
234     TopExp_Explorer ex(S,TopAbs_SHELL);
235     for (; ex.More(); ex.Next()) {
236       const TopoDS_Shape& Sh = ex.Current();
237       if(SkipShared && !aShMap.Add(Sh))
238       {
239         continue;
240       }
241       if(BRep_Tool::IsClosed(Sh)) volumeProperties(Sh,Props,1.0,SkipShared);
242     }
243   } else volumeProperties(S,Props,1.0,SkipShared);
244 }
245
246 //=======================================================================
247 //function : VolumeProperties
248 //purpose  : 
249 //=======================================================================
250
251 Standard_Real BRepGProp::VolumeProperties(const TopoDS_Shape& S, GProp_GProps& Props, 
252   const Standard_Real Eps, const Standard_Boolean OnlyClosed, const Standard_Boolean SkipShared)
253
254   // find the origin
255   gp_Pnt P(0,0,0);  P.Transform(S.Location());
256   Props = GProp_GProps(P);
257   Standard_Integer i;
258 #ifdef OCCT_DEBUG
259   Standard_Integer iErrorMax = 0;
260 #endif
261   Standard_Real ErrorMax = 0.0, Error = 0.0;
262   if(OnlyClosed){
263     TopTools_MapOfShape aShMap;
264     TopExp_Explorer ex(S,TopAbs_SHELL);
265     for (i = 1; ex.More(); ex.Next(), i++) {
266       const TopoDS_Shape& Sh = ex.Current();
267       if(SkipShared && !aShMap.Add(Sh))
268       {
269         continue;
270       }
271       if(BRep_Tool::IsClosed(Sh)) {
272         Error = volumeProperties(Sh,Props,Eps,SkipShared);
273         if(ErrorMax < Error) {
274           ErrorMax = Error;
275 #ifdef OCCT_DEBUG
276           iErrorMax = i;
277 #endif
278         }
279       }
280     }
281   } else ErrorMax = volumeProperties(S,Props,Eps,SkipShared);
282 #ifdef OCCT_DEBUG
283   if(AffichEps) cout<<"\n\n==================="<<iErrorMax<<":\tMaxEpsVolume = "<<ErrorMax<<"\n";
284 #endif
285   return ErrorMax;
286
287
288 //===========================================================================================//
289 // Volume properties by Gauss-Kronrod integration
290 //===========================================================================================//
291 //=======================================================================
292 //function : VolumePropertiesGK
293 //purpose  : 
294 //=======================================================================
295
296 static Standard_Real volumePropertiesGK(const TopoDS_Shape     &theShape,
297   GProp_GProps     &theProps,
298   const Standard_Real     theTol,
299   const Standard_Boolean  IsUseSpan,
300   const Standard_Boolean  CGFlag,
301   const Standard_Boolean  IFlag, const Standard_Boolean SkipShared)
302 {
303   TopExp_Explorer  anExp;
304   anExp.Init(theShape, TopAbs_FACE);
305
306   Standard_Real aTol = theTol;
307
308   // Compute properties.
309   gp_Pnt           aLoc(roughBaryCenter(theShape)); 
310   BRepGProp_VinertGK aVProps;
311   BRepGProp_Face   aPropFace(IsUseSpan);
312   BRepGProp_Domain aPropDomain;
313   Standard_Real    aLocalError;
314   Standard_Real    anError = 0.;
315   TopTools_MapOfShape aFwdFMap;
316   TopTools_MapOfShape aRvsFMap;
317   TopLoc_Location aLocDummy;
318
319   aVProps.SetLocation(aLoc);
320
321   for (; anExp.More(); anExp.Next()) {
322     TopoDS_Face aFace = TopoDS::Face(anExp.Current());
323     TopAbs_Orientation anOri = aFace.Orientation();
324     Standard_Boolean isFwd = anOri == TopAbs_FORWARD;
325     Standard_Boolean isRvs = Standard_False;
326     if(!isFwd)
327     {
328       isRvs = anOri == TopAbs_REVERSED;
329     }
330     if(SkipShared)
331     {
332       if((isFwd && !aFwdFMap.Add(aFace)) || (isRvs && !aRvsFMap.Add(aFace)))
333       {
334         continue;
335       }
336     }
337     {
338       const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface (aFace, aLocDummy);
339       if (aSurf.IsNull())
340       {
341         // skip faces without geometry
342         continue;
343       }
344     }
345
346     if (isFwd || isRvs){
347         aPropFace.Load(aFace);
348
349         Standard_Boolean IsNatRestr = (aFace.NbChildren () == 0);
350         if(IsNatRestr)
351           aLocalError = aVProps.Perform(aPropFace, aTol, CGFlag, IFlag);
352         else {
353           aPropDomain.Init(aFace);
354           aLocalError = aVProps.Perform(aPropFace, aPropDomain, aTol, CGFlag, IFlag);
355         }
356
357         if (aLocalError < 0.)
358           return aLocalError;
359
360         anError += aLocalError;
361         theProps.Add(aVProps);
362     }
363   }
364
365   return anError;
366 }
367
368 //=======================================================================
369 //function : VolumePropertiesGK
370 //purpose  : 
371 //=======================================================================
372
373 Standard_Real BRepGProp::VolumePropertiesGK(const TopoDS_Shape     &S,
374   GProp_GProps     &Props, 
375   const Standard_Real     Eps,
376   const Standard_Boolean  OnlyClosed,
377   const Standard_Boolean  IsUseSpan,
378   const Standard_Boolean  CGFlag,
379   const Standard_Boolean  IFlag, const Standard_Boolean SkipShared)
380
381   gp_Pnt        P(0,0,0);
382   Standard_Real anError = 0.;
383
384   P.Transform(S.Location());
385   Props = GProp_GProps(P);
386
387   if(OnlyClosed) {
388     // To select closed shells.
389     TopExp_Explorer  anExp;
390     TopTools_ListOfShape aClosedShells;
391     TopTools_MapOfShape aShMap;
392
393     anExp.Init(S, TopAbs_SHELL);
394
395     for (; anExp.More(); anExp.Next()) {
396       const TopoDS_Shape &aShell = anExp.Current();
397       if(SkipShared && !aShMap.Add(aShell))
398       {
399         continue;
400       }
401
402       BRepCheck_Shell aChecker(TopoDS::Shell(aShell));
403       BRepCheck_Status aStatus = aChecker.Closed(Standard_False);
404
405       if(aStatus == BRepCheck_NoError) 
406         aClosedShells.Append(aShell);
407
408     }
409
410     if (aClosedShells.IsEmpty())
411       return -1.;
412
413     // Compute the properties for each closed shell.
414     Standard_Real aTol    = Eps;
415     Standard_Real aLocalError;
416     TopTools_ListIteratorOfListOfShape anIter(aClosedShells);
417
418     for (; anIter.More(); anIter.Next()) {
419       const TopoDS_Shape &aShell = anIter.Value();
420
421       aLocalError = volumePropertiesGK(aShell, Props, aTol, IsUseSpan, CGFlag, IFlag,SkipShared);
422
423       if (aLocalError < 0)
424         return aLocalError;
425
426       anError += aLocalError;
427     }
428
429   } else
430     anError = volumePropertiesGK(S, Props, Eps, IsUseSpan, CGFlag, IFlag,SkipShared);
431
432   Standard_Real vol = Props.Mass();
433   if(vol > Epsilon(1.)) anError /= vol;
434   return anError;
435 }
436
437 //=======================================================================
438 //function : VolumeProperties
439 //purpose  : 
440 //=======================================================================
441
442 static Standard_Real volumePropertiesGK(const TopoDS_Shape     &theShape,
443   GProp_GProps     &theProps,
444   const gp_Pln           &thePln,
445   const Standard_Real     theTol,
446   const Standard_Boolean  IsUseSpan,
447   const Standard_Boolean  CGFlag,
448   const Standard_Boolean  IFlag, const Standard_Boolean SkipShared)
449 {
450   TopExp_Explorer  anExp;
451   anExp.Init(theShape, TopAbs_FACE);
452
453   Standard_Real aTol = theTol;
454
455   // Compute properties.
456   gp_Pnt           aLoc(roughBaryCenter(theShape)); 
457   BRepGProp_VinertGK aVProps;
458   BRepGProp_Face   aPropFace(IsUseSpan);
459   BRepGProp_Domain aPropDomain;
460   Standard_Real    aLocalError;
461   Standard_Real    anError = 0.;
462   TopTools_MapOfShape aFwdFMap;
463   TopTools_MapOfShape aRvsFMap;
464   TopLoc_Location aLocDummy;
465
466   aVProps.SetLocation(aLoc);
467
468   for (; anExp.More(); anExp.Next()) {
469     TopoDS_Face aFace = TopoDS::Face(anExp.Current());
470     TopAbs_Orientation anOri = aFace.Orientation();
471     Standard_Boolean isFwd = anOri == TopAbs_FORWARD;
472     Standard_Boolean isRvs = Standard_False;
473     if(!isFwd)
474     {
475       isRvs = anOri == TopAbs_REVERSED;
476     }
477     if(SkipShared)
478     {
479       if((isFwd && !aFwdFMap.Add(aFace)) || (isRvs && !aRvsFMap.Add(aFace)))
480       {
481         continue;
482       }
483     }
484     {
485       const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface (aFace, aLocDummy);
486       if (aSurf.IsNull())
487       {
488         // skip faces without geometry
489         continue;
490       }
491     }
492
493     if (isFwd || isRvs){
494         aPropFace.Load(aFace);
495
496         Standard_Boolean IsNatRestr = (aFace.NbChildren () == 0);
497         if(IsNatRestr)
498           aLocalError = aVProps.Perform(aPropFace, thePln, aTol, CGFlag, IFlag);
499         else {
500           aPropDomain.Init(aFace);
501           aLocalError = aVProps.Perform(aPropFace, aPropDomain, thePln, aTol, CGFlag, IFlag);
502         }
503
504         if (aLocalError < 0.)
505           return aLocalError;
506
507         anError += aLocalError;
508         theProps.Add(aVProps);
509     }
510   }
511
512   return anError;
513 }
514
515 //=======================================================================
516 //function : VolumeProperties
517 //purpose  : 
518 //=======================================================================
519
520 Standard_Real BRepGProp::VolumePropertiesGK(const TopoDS_Shape     &S,
521   GProp_GProps     &Props,
522   const gp_Pln           &thePln,
523   const Standard_Real     Eps,
524   const Standard_Boolean  OnlyClosed,
525   const Standard_Boolean  IsUseSpan,
526   const Standard_Boolean  CGFlag,
527   const Standard_Boolean  IFlag, const Standard_Boolean SkipShared)
528
529   gp_Pnt        P(0,0,0);
530   Standard_Real anError = 0.;
531
532   P.Transform(S.Location());
533   Props = GProp_GProps(P);
534
535   if(OnlyClosed) {
536     // To select closed shells.
537     TopExp_Explorer  anExp;
538     TopTools_ListOfShape aClosedShells;
539     TopTools_MapOfShape aShMap;
540
541     anExp.Init(S, TopAbs_SHELL);
542
543     for (; anExp.More(); anExp.Next()) {
544       const TopoDS_Shape &aShell = anExp.Current();
545       if(SkipShared && !aShMap.Add(aShell))
546       {
547         continue;
548       }
549
550       BRepCheck_Shell aChecker(TopoDS::Shell(aShell));
551       BRepCheck_Status aStatus = aChecker.Closed(Standard_False);
552
553       if(aStatus == BRepCheck_NoError) 
554         aClosedShells.Append(aShell);
555
556     }
557
558     if (aClosedShells.IsEmpty())
559       return -1.;
560
561     // Compute the properties for each closed shell.
562     Standard_Real aTol    = Eps;
563     Standard_Real aLocalError;
564     TopTools_ListIteratorOfListOfShape anIter(aClosedShells);
565
566     for (; anIter.More(); anIter.Next()) {
567       const TopoDS_Shape &aShell = anIter.Value();
568
569       aLocalError = volumePropertiesGK(aShell, Props, thePln, aTol, IsUseSpan, CGFlag, IFlag,SkipShared);
570
571       if (aLocalError < 0)
572         return aLocalError;
573
574       anError += aLocalError;
575     }
576   } else
577     anError = volumePropertiesGK(S, Props, thePln, Eps, IsUseSpan, CGFlag, IFlag,SkipShared);
578
579   Standard_Real vol = Props.Mass();
580   if(vol > Epsilon(1.)) anError /= vol;
581
582   return anError;
583 }