1 // Copyright (c) 1995-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
4 // This file is part of Open CASCADE Technology software library.
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.
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
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>
24 #include <BRepAdaptor_Curve.hxx>
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>
33 static Standard_Integer AffichEps = 0;
36 static gp_Pnt roughBaryCenter(const TopoDS_Shape& S){
37 Standard_Integer i; TopExp_Explorer ex;
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;
45 void BRepGProp::LinearProperties(const TopoDS_Shape& S, GProp_GProps& SProps, const Standard_Boolean SkipShared){
48 P.Transform(S.Location());
49 SProps = GProp_GProps(P);
51 BRepAdaptor_Curve BAC;
52 Standard_Real eps = Epsilon(1.);
53 TopTools_MapOfShape anEMap;
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))
61 if(!BRep_Tool::IsGeometric(aE))
63 GProp_PGProps aPProps;
64 TopoDS_Iterator anIter(aE);
65 for(; anIter.More(); anIter.Next())
67 const TopoDS_Vertex& aV = TopoDS::Vertex(anIter.Value());
68 aPProps.AddPoint(BRep_Tool::Pnt(aV), eps);
75 BRepGProp_Cinert CG(BAC,P);
81 static Standard_Real surfaceProperties(const TopoDS_Shape& S, GProp_GProps& Props, const Standard_Real Eps, const Standard_Boolean SkipShared){
84 Standard_Integer iErrorMax = 0;
86 Standard_Real ErrorMax = 0.0, Error;
88 gp_Pnt P(roughBaryCenter(S));
89 BRepGProp_Sinert G; G.SetLocation(P);
93 TopTools_MapOfShape aFMap;
94 TopLoc_Location aLocDummy;
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))
104 const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface (F, aLocDummy);
107 // skip faces without geometry
113 Standard_Boolean IsNatRestr = (F.NbChildren() == 0);
114 if(!IsNatRestr) BD.Init(F);
116 G.Perform(BF, BD, Eps);
117 Error = G.GetEpsilon();
118 if(ErrorMax < Error) {
125 if(IsNatRestr) G.Perform(BF);
126 else G.Perform(BF, BD);
130 if(AffichEps) cout<<"\n"<<i<<":\tEpsArea = "<< G.GetEpsilon();
134 if(AffichEps) cout<<"\n-----------------\n"<<iErrorMax<<":\tMaxError = "<<ErrorMax<<"\n";
138 void BRepGProp::SurfaceProperties(const TopoDS_Shape& S, GProp_GProps& Props, const Standard_Boolean SkipShared){
141 P.Transform(S.Location());
142 Props = GProp_GProps(P);
143 surfaceProperties(S,Props,1.0, SkipShared);
145 Standard_Real BRepGProp::SurfaceProperties(const TopoDS_Shape& S, GProp_GProps& Props, const Standard_Real Eps, const Standard_Boolean SkipShared){
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);
153 //=======================================================================
154 //function : volumeProperties
156 //=======================================================================
158 static Standard_Real volumeProperties(const TopoDS_Shape& S, GProp_GProps& Props, const Standard_Real Eps, const Standard_Boolean SkipShared){
161 Standard_Integer iErrorMax = 0;
163 Standard_Real ErrorMax = 0.0, Error = 0.0;
165 gp_Pnt P(roughBaryCenter(S));
166 BRepGProp_Vinert G; G.SetLocation(P);
170 TopTools_MapOfShape aFwdFMap;
171 TopTools_MapOfShape aRvsFMap;
172 TopLoc_Location aLocDummy;
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;
181 isRvs = anOri == TopAbs_REVERSED;
185 if((isFwd && !aFwdFMap.Add(F)) || (isRvs && !aRvsFMap.Add(F)))
191 const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface (F, aLocDummy);
194 // skip faces without geometry
201 Standard_Boolean IsNatRestr = (F.NbChildren () == 0);
202 if(!IsNatRestr) BD.Init(F);
204 G.Perform(BF, BD, Eps);
205 Error = G.GetEpsilon();
206 if(ErrorMax < Error) {
214 if(IsNatRestr) G.Perform(BF);
215 else G.Perform(BF, BD);
219 if(AffichEps) cout<<"\n"<<i<<":\tEpsVolume = "<< G.GetEpsilon();
224 if(AffichEps) cout<<"\n-----------------\n"<<iErrorMax<<":\tMaxError = "<<ErrorMax<<"\n";
228 void BRepGProp::VolumeProperties(const TopoDS_Shape& S, GProp_GProps& Props, const Standard_Boolean OnlyClosed, const Standard_Boolean SkipShared){
230 gp_Pnt P(0,0,0); P.Transform(S.Location());
231 Props = GProp_GProps(P);
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))
241 if(BRep_Tool::IsClosed(Sh)) volumeProperties(Sh,Props,1.0,SkipShared);
243 } else volumeProperties(S,Props,1.0,SkipShared);
246 //=======================================================================
247 //function : VolumeProperties
249 //=======================================================================
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)
255 gp_Pnt P(0,0,0); P.Transform(S.Location());
256 Props = GProp_GProps(P);
259 Standard_Integer iErrorMax = 0;
261 Standard_Real ErrorMax = 0.0, Error = 0.0;
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))
271 if(BRep_Tool::IsClosed(Sh)) {
272 Error = volumeProperties(Sh,Props,Eps,SkipShared);
273 if(ErrorMax < Error) {
281 } else ErrorMax = volumeProperties(S,Props,Eps,SkipShared);
283 if(AffichEps) cout<<"\n\n==================="<<iErrorMax<<":\tMaxEpsVolume = "<<ErrorMax<<"\n";
288 //===========================================================================================//
289 // Volume properties by Gauss-Kronrod integration
290 //===========================================================================================//
291 //=======================================================================
292 //function : VolumePropertiesGK
294 //=======================================================================
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)
303 TopExp_Explorer anExp;
304 anExp.Init(theShape, TopAbs_FACE);
306 Standard_Real aTol = theTol;
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;
319 aVProps.SetLocation(aLoc);
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;
328 isRvs = anOri == TopAbs_REVERSED;
332 if((isFwd && !aFwdFMap.Add(aFace)) || (isRvs && !aRvsFMap.Add(aFace)))
338 const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface (aFace, aLocDummy);
341 // skip faces without geometry
347 aPropFace.Load(aFace);
349 Standard_Boolean IsNatRestr = (aFace.NbChildren () == 0);
351 aLocalError = aVProps.Perform(aPropFace, aTol, CGFlag, IFlag);
353 aPropDomain.Init(aFace);
354 aLocalError = aVProps.Perform(aPropFace, aPropDomain, aTol, CGFlag, IFlag);
357 if (aLocalError < 0.)
360 anError += aLocalError;
361 theProps.Add(aVProps);
368 //=======================================================================
369 //function : VolumePropertiesGK
371 //=======================================================================
373 Standard_Real BRepGProp::VolumePropertiesGK(const TopoDS_Shape &S,
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)
382 Standard_Real anError = 0.;
384 P.Transform(S.Location());
385 Props = GProp_GProps(P);
388 // To select closed shells.
389 TopExp_Explorer anExp;
390 TopTools_ListOfShape aClosedShells;
391 TopTools_MapOfShape aShMap;
393 anExp.Init(S, TopAbs_SHELL);
395 for (; anExp.More(); anExp.Next()) {
396 const TopoDS_Shape &aShell = anExp.Current();
397 if(SkipShared && !aShMap.Add(aShell))
402 BRepCheck_Shell aChecker(TopoDS::Shell(aShell));
403 BRepCheck_Status aStatus = aChecker.Closed(Standard_False);
405 if(aStatus == BRepCheck_NoError)
406 aClosedShells.Append(aShell);
410 if (aClosedShells.IsEmpty())
413 // Compute the properties for each closed shell.
414 Standard_Real aTol = Eps;
415 Standard_Real aLocalError;
416 TopTools_ListIteratorOfListOfShape anIter(aClosedShells);
418 for (; anIter.More(); anIter.Next()) {
419 const TopoDS_Shape &aShell = anIter.Value();
421 aLocalError = volumePropertiesGK(aShell, Props, aTol, IsUseSpan, CGFlag, IFlag,SkipShared);
426 anError += aLocalError;
430 anError = volumePropertiesGK(S, Props, Eps, IsUseSpan, CGFlag, IFlag,SkipShared);
432 Standard_Real vol = Props.Mass();
433 if(vol > Epsilon(1.)) anError /= vol;
437 //=======================================================================
438 //function : VolumeProperties
440 //=======================================================================
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)
450 TopExp_Explorer anExp;
451 anExp.Init(theShape, TopAbs_FACE);
453 Standard_Real aTol = theTol;
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;
466 aVProps.SetLocation(aLoc);
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;
475 isRvs = anOri == TopAbs_REVERSED;
479 if((isFwd && !aFwdFMap.Add(aFace)) || (isRvs && !aRvsFMap.Add(aFace)))
485 const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface (aFace, aLocDummy);
488 // skip faces without geometry
494 aPropFace.Load(aFace);
496 Standard_Boolean IsNatRestr = (aFace.NbChildren () == 0);
498 aLocalError = aVProps.Perform(aPropFace, thePln, aTol, CGFlag, IFlag);
500 aPropDomain.Init(aFace);
501 aLocalError = aVProps.Perform(aPropFace, aPropDomain, thePln, aTol, CGFlag, IFlag);
504 if (aLocalError < 0.)
507 anError += aLocalError;
508 theProps.Add(aVProps);
515 //=======================================================================
516 //function : VolumeProperties
518 //=======================================================================
520 Standard_Real BRepGProp::VolumePropertiesGK(const TopoDS_Shape &S,
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)
530 Standard_Real anError = 0.;
532 P.Transform(S.Location());
533 Props = GProp_GProps(P);
536 // To select closed shells.
537 TopExp_Explorer anExp;
538 TopTools_ListOfShape aClosedShells;
539 TopTools_MapOfShape aShMap;
541 anExp.Init(S, TopAbs_SHELL);
543 for (; anExp.More(); anExp.Next()) {
544 const TopoDS_Shape &aShell = anExp.Current();
545 if(SkipShared && !aShMap.Add(aShell))
550 BRepCheck_Shell aChecker(TopoDS::Shell(aShell));
551 BRepCheck_Status aStatus = aChecker.Closed(Standard_False);
553 if(aStatus == BRepCheck_NoError)
554 aClosedShells.Append(aShell);
558 if (aClosedShells.IsEmpty())
561 // Compute the properties for each closed shell.
562 Standard_Real aTol = Eps;
563 Standard_Real aLocalError;
564 TopTools_ListIteratorOfListOfShape anIter(aClosedShells);
566 for (; anIter.More(); anIter.Next()) {
567 const TopoDS_Shape &aShell = anIter.Value();
569 aLocalError = volumePropertiesGK(aShell, Props, thePln, aTol, IsUseSpan, CGFlag, IFlag,SkipShared);
574 anError += aLocalError;
577 anError = volumePropertiesGK(S, Props, thePln, Eps, IsUseSpan, CGFlag, IFlag,SkipShared);
579 Standard_Real vol = Props.Mass();
580 if(vol > Epsilon(1.)) anError /= vol;