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_MeshProps.hxx>
20 #include <BRepGProp_MeshCinert.hxx>
21 #include <BRepGProp_VinertGK.hxx>
22 #include <GProp_PGProps.hxx>
23 #include <BRepGProp_Face.hxx>
24 #include <BRepGProp_Domain.hxx>
26 #include <BRepAdaptor_Curve.hxx>
28 #include <TopTools.hxx>
29 #include <BRep_Tool.hxx>
30 #include <TopTools_ListOfShape.hxx>
31 #include <TopTools_MapOfShape.hxx>
32 #include <BRepCheck_Shell.hxx>
33 #include <TopTools_ListIteratorOfListOfShape.hxx>
36 static Standard_Integer AffichEps = 0;
39 static gp_Pnt roughBaryCenter(const TopoDS_Shape& S){
40 Standard_Integer i; TopExp_Explorer ex;
42 for (ex.Init(S,TopAbs_VERTEX), i = 0; ex.More(); ex.Next(), i++)
43 xyz += BRep_Tool::Pnt(TopoDS::Vertex(ex.Current())).XYZ();
50 //Try using triangulation
51 ex.Init(S, TopAbs_FACE);
52 for (; ex.More(); ex.Next())
54 const TopoDS_Shape& aF = ex.Current();
55 TopLoc_Location aLocDummy;
56 const Handle(Poly_Triangulation)& aTri =
57 BRep_Tool::Triangulation(TopoDS::Face(aF), aLocDummy);
60 xyz = aTri->Node(1).XYZ();
61 if (!aLocDummy.IsIdentity())
63 aLocDummy.Transformation().Transforms(xyz);
74 void BRepGProp::LinearProperties(const TopoDS_Shape& S, GProp_GProps& SProps, const Standard_Boolean SkipShared,
75 const Standard_Boolean UseTriangulation)
79 P.Transform(S.Location());
80 SProps = GProp_GProps(P);
82 BRepAdaptor_Curve BAC;
83 TopTools_MapOfShape anEMap;
85 for (ex.Init(S,TopAbs_EDGE); ex.More(); ex.Next()) {
86 const TopoDS_Edge& aE = TopoDS::Edge(ex.Current());
87 if(SkipShared && !anEMap.Add(aE))
92 Handle(TColgp_HArray1OfPnt) theNodes;
93 Standard_Boolean IsGeom = BRep_Tool::IsGeometric(aE);
94 if (UseTriangulation || !IsGeom)
96 BRepGProp_MeshCinert::PreparePolygon(aE, theNodes);
98 if(!theNodes.IsNull())
100 BRepGProp_MeshCinert MG;
102 MG.Perform(theNodes->Array1());
110 BRepGProp_Cinert CG(BAC, P);
117 static Standard_Real surfaceProperties(const TopoDS_Shape& S, GProp_GProps& Props, const Standard_Real Eps, const Standard_Boolean SkipShared,
118 const Standard_Boolean UseTriangulation)
122 Standard_Integer iErrorMax = 0;
124 Standard_Real ErrorMax = 0.0, Error;
126 gp_Pnt P(roughBaryCenter(S));
127 BRepGProp_Sinert G; G.SetLocation(P);
128 BRepGProp_MeshProps MG(BRepGProp_MeshProps::Sinert);
133 TopTools_MapOfShape aFMap;
134 TopLoc_Location aLocDummy;
136 for (ex.Init(S, TopAbs_FACE), i = 1; ex.More(); ex.Next(), i++) {
137 const TopoDS_Face& F = TopoDS::Face(ex.Current());
138 if (SkipShared && !aFMap.Add(F))
143 Standard_Boolean NoSurf = Standard_False, NoTri = Standard_False;
145 const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface(F, aLocDummy);
148 NoSurf = Standard_True;
150 const Handle(Poly_Triangulation)& aTri = BRep_Tool::Triangulation(F, aLocDummy);
153 NoTri = Standard_True;
161 if ((UseTriangulation && !NoTri) || (NoSurf && !NoTri))
163 TopAbs_Orientation anOri = F.Orientation();
164 const Handle(Poly_Triangulation)& aTri = BRep_Tool::Triangulation(F, aLocDummy);
165 MG.Perform(aTri, aLocDummy, anOri);
171 Standard_Boolean IsNatRestr = (F.NbChildren() == 0);
172 if (!IsNatRestr) BD.Init(F);
174 G.Perform(BF, BD, Eps);
175 Error = G.GetEpsilon();
176 if (ErrorMax < Error) {
184 if (IsNatRestr) G.Perform(BF);
185 else G.Perform(BF, BD);
189 if(AffichEps) cout<<"\n"<<i<<":\tEpsArea = "<< G.GetEpsilon();
194 if(AffichEps) cout<<"\n-----------------\n"<<iErrorMax<<":\tMaxError = "<<ErrorMax<<"\n";
198 void BRepGProp::SurfaceProperties(const TopoDS_Shape& S, GProp_GProps& Props, const Standard_Boolean SkipShared,
199 const Standard_Boolean UseTriangulation)
203 P.Transform(S.Location());
204 Props = GProp_GProps(P);
205 surfaceProperties(S,Props,1.0, SkipShared, UseTriangulation);
207 Standard_Real BRepGProp::SurfaceProperties(const TopoDS_Shape& S, GProp_GProps& Props, const Standard_Real Eps, const Standard_Boolean SkipShared){
209 gp_Pnt P(0,0,0); P.Transform(S.Location());
210 Props = GProp_GProps(P);
211 Standard_Real ErrorMax = surfaceProperties(S,Props,Eps,SkipShared, Standard_False);
215 //=======================================================================
216 //function : volumeProperties
218 //=======================================================================
220 static Standard_Real volumeProperties(const TopoDS_Shape& S, GProp_GProps& Props, const Standard_Real Eps, const Standard_Boolean SkipShared,
221 const Standard_Boolean UseTriangulation)
225 Standard_Integer iErrorMax = 0;
227 Standard_Real ErrorMax = 0.0, Error = 0.0;
229 gp_Pnt P(roughBaryCenter(S));
230 BRepGProp_Vinert G; G.SetLocation(P);
231 BRepGProp_MeshProps MG(BRepGProp_MeshProps::Vinert);
236 TopTools_MapOfShape aFwdFMap;
237 TopTools_MapOfShape aRvsFMap;
238 TopLoc_Location aLocDummy;
240 for (ex.Init(S,TopAbs_FACE), i = 1; ex.More(); ex.Next(), i++) {
241 const TopoDS_Face& F = TopoDS::Face(ex.Current());
242 TopAbs_Orientation anOri = F.Orientation();
243 Standard_Boolean isFwd = anOri == TopAbs_FORWARD;
244 Standard_Boolean isRvs = Standard_False;
247 isRvs = anOri == TopAbs_REVERSED;
251 if((isFwd && !aFwdFMap.Add(F)) || (isRvs && !aRvsFMap.Add(F)))
256 Standard_Boolean NoSurf = Standard_False, NoTri = Standard_False;
258 const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface (F, aLocDummy);
261 NoSurf = Standard_True;
263 const Handle(Poly_Triangulation)& aTri = BRep_Tool::Triangulation(F, aLocDummy);
266 NoTri = Standard_True;
276 if ((UseTriangulation && !NoTri) || (NoSurf && !NoTri))
278 const Handle(Poly_Triangulation)& aTri = BRep_Tool::Triangulation(F, aLocDummy);
279 MG.Perform(aTri, aLocDummy, anOri);
285 Standard_Boolean IsNatRestr = (F.NbChildren () == 0);
286 if (!IsNatRestr) BD.Init(F);
288 G.Perform(BF, BD, Eps);
289 Error = G.GetEpsilon();
290 if (ErrorMax < Error) {
298 if (IsNatRestr) G.Perform(BF);
299 else G.Perform(BF, BD);
303 if(AffichEps) cout<<"\n"<<i<<":\tEpsVolume = "<< G.GetEpsilon();
309 if(AffichEps) cout<<"\n-----------------\n"<<iErrorMax<<":\tMaxError = "<<ErrorMax<<"\n";
313 void BRepGProp::VolumeProperties(const TopoDS_Shape& S, GProp_GProps& Props, const Standard_Boolean OnlyClosed, const Standard_Boolean SkipShared,
314 const Standard_Boolean UseTriangulation)
317 gp_Pnt P(0,0,0); P.Transform(S.Location());
318 Props = GProp_GProps(P);
320 TopTools_MapOfShape aShMap;
321 TopExp_Explorer ex(S,TopAbs_SHELL);
322 for (; ex.More(); ex.Next()) {
323 const TopoDS_Shape& Sh = ex.Current();
324 if(SkipShared && !aShMap.Add(Sh))
328 if(BRep_Tool::IsClosed(Sh)) volumeProperties(Sh,Props,1.0,SkipShared, UseTriangulation);
330 } else volumeProperties(S,Props,1.0,SkipShared, UseTriangulation);
333 //=======================================================================
334 //function : VolumeProperties
336 //=======================================================================
338 Standard_Real BRepGProp::VolumeProperties(const TopoDS_Shape& S, GProp_GProps& Props,
339 const Standard_Real Eps, const Standard_Boolean OnlyClosed, const Standard_Boolean SkipShared)
342 gp_Pnt P(0,0,0); P.Transform(S.Location());
343 Props = GProp_GProps(P);
346 Standard_Integer iErrorMax = 0;
348 Standard_Real ErrorMax = 0.0, Error = 0.0;
350 TopTools_MapOfShape aShMap;
351 TopExp_Explorer ex(S,TopAbs_SHELL);
352 for (i = 1; ex.More(); ex.Next(), i++) {
353 const TopoDS_Shape& Sh = ex.Current();
354 if(SkipShared && !aShMap.Add(Sh))
358 if(BRep_Tool::IsClosed(Sh)) {
359 Error = volumeProperties(Sh,Props,Eps,SkipShared, Standard_False);
360 if(ErrorMax < Error) {
368 } else ErrorMax = volumeProperties(S,Props,Eps,SkipShared, Standard_False);
370 if(AffichEps) cout<<"\n\n==================="<<iErrorMax<<":\tMaxEpsVolume = "<<ErrorMax<<"\n";
375 //===========================================================================================//
376 // Volume properties by Gauss-Kronrod integration
377 //===========================================================================================//
378 //=======================================================================
379 //function : VolumePropertiesGK
381 //=======================================================================
383 static Standard_Real volumePropertiesGK(const TopoDS_Shape &theShape,
384 GProp_GProps &theProps,
385 const Standard_Real theTol,
386 const Standard_Boolean IsUseSpan,
387 const Standard_Boolean CGFlag,
388 const Standard_Boolean IFlag, const Standard_Boolean SkipShared)
390 TopExp_Explorer anExp;
391 anExp.Init(theShape, TopAbs_FACE);
393 Standard_Real aTol = theTol;
395 // Compute properties.
396 gp_Pnt aLoc(roughBaryCenter(theShape));
397 BRepGProp_VinertGK aVProps;
398 BRepGProp_Face aPropFace(IsUseSpan);
399 BRepGProp_Domain aPropDomain;
400 Standard_Real aLocalError;
401 Standard_Real anError = 0.;
402 TopTools_MapOfShape aFwdFMap;
403 TopTools_MapOfShape aRvsFMap;
404 TopLoc_Location aLocDummy;
406 aVProps.SetLocation(aLoc);
408 for (; anExp.More(); anExp.Next()) {
409 TopoDS_Face aFace = TopoDS::Face(anExp.Current());
410 TopAbs_Orientation anOri = aFace.Orientation();
411 Standard_Boolean isFwd = anOri == TopAbs_FORWARD;
412 Standard_Boolean isRvs = Standard_False;
415 isRvs = anOri == TopAbs_REVERSED;
419 if((isFwd && !aFwdFMap.Add(aFace)) || (isRvs && !aRvsFMap.Add(aFace)))
425 const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface (aFace, aLocDummy);
428 // skip faces without geometry
434 aPropFace.Load(aFace);
436 Standard_Boolean IsNatRestr = (aFace.NbChildren () == 0);
438 aLocalError = aVProps.Perform(aPropFace, aTol, CGFlag, IFlag);
440 aPropDomain.Init(aFace);
441 aLocalError = aVProps.Perform(aPropFace, aPropDomain, aTol, CGFlag, IFlag);
444 if (aLocalError < 0.)
447 anError += aLocalError;
448 theProps.Add(aVProps);
455 //=======================================================================
456 //function : VolumePropertiesGK
458 //=======================================================================
460 Standard_Real BRepGProp::VolumePropertiesGK(const TopoDS_Shape &S,
462 const Standard_Real Eps,
463 const Standard_Boolean OnlyClosed,
464 const Standard_Boolean IsUseSpan,
465 const Standard_Boolean CGFlag,
466 const Standard_Boolean IFlag, const Standard_Boolean SkipShared)
469 Standard_Real anError = 0.;
471 P.Transform(S.Location());
472 Props = GProp_GProps(P);
475 // To select closed shells.
476 TopExp_Explorer anExp;
477 TopTools_ListOfShape aClosedShells;
478 TopTools_MapOfShape aShMap;
480 anExp.Init(S, TopAbs_SHELL);
482 for (; anExp.More(); anExp.Next()) {
483 const TopoDS_Shape &aShell = anExp.Current();
484 if(SkipShared && !aShMap.Add(aShell))
489 BRepCheck_Shell aChecker(TopoDS::Shell(aShell));
490 BRepCheck_Status aStatus = aChecker.Closed(Standard_False);
492 if(aStatus == BRepCheck_NoError)
493 aClosedShells.Append(aShell);
497 if (aClosedShells.IsEmpty())
500 // Compute the properties for each closed shell.
501 Standard_Real aTol = Eps;
502 Standard_Real aLocalError;
503 TopTools_ListIteratorOfListOfShape anIter(aClosedShells);
505 for (; anIter.More(); anIter.Next()) {
506 const TopoDS_Shape &aShell = anIter.Value();
508 aLocalError = volumePropertiesGK(aShell, Props, aTol, IsUseSpan, CGFlag, IFlag,SkipShared);
513 anError += aLocalError;
517 anError = volumePropertiesGK(S, Props, Eps, IsUseSpan, CGFlag, IFlag,SkipShared);
519 Standard_Real vol = Props.Mass();
520 if(vol > Epsilon(1.)) anError /= vol;
524 //=======================================================================
525 //function : VolumeProperties
527 //=======================================================================
529 static Standard_Real volumePropertiesGK(const TopoDS_Shape &theShape,
530 GProp_GProps &theProps,
531 const gp_Pln &thePln,
532 const Standard_Real theTol,
533 const Standard_Boolean IsUseSpan,
534 const Standard_Boolean CGFlag,
535 const Standard_Boolean IFlag, const Standard_Boolean SkipShared)
537 TopExp_Explorer anExp;
538 anExp.Init(theShape, TopAbs_FACE);
540 Standard_Real aTol = theTol;
542 // Compute properties.
543 gp_Pnt aLoc(roughBaryCenter(theShape));
544 BRepGProp_VinertGK aVProps;
545 BRepGProp_Face aPropFace(IsUseSpan);
546 BRepGProp_Domain aPropDomain;
547 Standard_Real aLocalError;
548 Standard_Real anError = 0.;
549 TopTools_MapOfShape aFwdFMap;
550 TopTools_MapOfShape aRvsFMap;
551 TopLoc_Location aLocDummy;
553 aVProps.SetLocation(aLoc);
555 for (; anExp.More(); anExp.Next()) {
556 TopoDS_Face aFace = TopoDS::Face(anExp.Current());
557 TopAbs_Orientation anOri = aFace.Orientation();
558 Standard_Boolean isFwd = anOri == TopAbs_FORWARD;
559 Standard_Boolean isRvs = Standard_False;
562 isRvs = anOri == TopAbs_REVERSED;
566 if((isFwd && !aFwdFMap.Add(aFace)) || (isRvs && !aRvsFMap.Add(aFace)))
572 const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface (aFace, aLocDummy);
575 // skip faces without geometry
581 aPropFace.Load(aFace);
583 Standard_Boolean IsNatRestr = (aFace.NbChildren () == 0);
585 aLocalError = aVProps.Perform(aPropFace, thePln, aTol, CGFlag, IFlag);
587 aPropDomain.Init(aFace);
588 aLocalError = aVProps.Perform(aPropFace, aPropDomain, thePln, aTol, CGFlag, IFlag);
591 if (aLocalError < 0.)
594 anError += aLocalError;
595 theProps.Add(aVProps);
602 //=======================================================================
603 //function : VolumeProperties
605 //=======================================================================
607 Standard_Real BRepGProp::VolumePropertiesGK(const TopoDS_Shape &S,
609 const gp_Pln &thePln,
610 const Standard_Real Eps,
611 const Standard_Boolean OnlyClosed,
612 const Standard_Boolean IsUseSpan,
613 const Standard_Boolean CGFlag,
614 const Standard_Boolean IFlag, const Standard_Boolean SkipShared)
617 Standard_Real anError = 0.;
619 P.Transform(S.Location());
620 Props = GProp_GProps(P);
623 // To select closed shells.
624 TopExp_Explorer anExp;
625 TopTools_ListOfShape aClosedShells;
626 TopTools_MapOfShape aShMap;
628 anExp.Init(S, TopAbs_SHELL);
630 for (; anExp.More(); anExp.Next()) {
631 const TopoDS_Shape &aShell = anExp.Current();
632 if(SkipShared && !aShMap.Add(aShell))
637 BRepCheck_Shell aChecker(TopoDS::Shell(aShell));
638 BRepCheck_Status aStatus = aChecker.Closed(Standard_False);
640 if(aStatus == BRepCheck_NoError)
641 aClosedShells.Append(aShell);
645 if (aClosedShells.IsEmpty())
648 // Compute the properties for each closed shell.
649 Standard_Real aTol = Eps;
650 Standard_Real aLocalError;
651 TopTools_ListIteratorOfListOfShape anIter(aClosedShells);
653 for (; anIter.More(); anIter.Next()) {
654 const TopoDS_Shape &aShell = anIter.Value();
656 aLocalError = volumePropertiesGK(aShell, Props, thePln, aTol, IsUseSpan, CGFlag, IFlag,SkipShared);
661 anError += aLocalError;
664 anError = volumePropertiesGK(S, Props, thePln, Eps, IsUseSpan, CGFlag, IFlag,SkipShared);
666 Standard_Real vol = Props.Mass();
667 if(vol > Epsilon(1.)) anError /= vol;