0029734: Modeling Algorithms - Compute global properties of tessellated shape
authorifv <ifv@opencascade.com>
Thu, 17 May 2018 12:38:17 +0000 (15:38 +0300)
committerkgv <kgv@opencascade.com>
Sat, 23 Jun 2018 10:12:36 +0000 (13:12 +0300)
New algorithms calculating global properties on mesh data have been added:
- BRepGProp_MeshCinert computes the global properties of polylines represented by a set of points;
- BRepGProp_MeshProps computes the global properties of a surface mesh.

Existing tool BRepGProp now automatically uses new algorithm for triangulation-only faces.
By default, algorithm will use exact geometry objects (surfaces), when it is available (as before the patch);
this behavior can be switched by a new flag UseTriangulation, forcing usage of triangulation instead of exact geometry when both defined.

15 files changed:
dox/user_guides/draw_test_harness/draw_test_harness.md
src/BRepGProp/BRepGProp.cxx
src/BRepGProp/BRepGProp.hxx
src/BRepGProp/BRepGProp_MeshCinert.cxx [new file with mode: 0644]
src/BRepGProp/BRepGProp_MeshCinert.hxx [new file with mode: 0644]
src/BRepGProp/BRepGProp_MeshProps.cxx [new file with mode: 0644]
src/BRepGProp/BRepGProp_MeshProps.hxx [new file with mode: 0644]
src/BRepGProp/FILES
src/BRepTest/BRepTest_GPropCommands.cxx
src/BRepTools/BRepTools.cxx
src/BRepTools/BRepTools.hxx
src/DBRep/DBRep.cxx
tests/bugs/modalg_7/bug29731 [new file with mode: 0644]
tests/bugs/modalg_7/bug29734 [new file with mode: 0644]
tests/bugs/vis/bug173_1

index 6c03984..0c946af 100644 (file)
@@ -7209,15 +7209,26 @@ Analysis of shapes includes commands to compute length, area, volumes and inerti
 
 Syntax:      
 ~~~~~
-lprops shape 
-sprops shape 
-vprops shape 
+lprops shape  [x y z] [-skip] [-full] [-tri]
+sprops shape [epsilon] [c[losed]] [x y z] [-skip] [-full] [-tri]
+vprops shape [epsilon] [c[losed]] [x y z] [-skip] [-full] [-tri] 
 ~~~~~
 
 * **lprops** computes the mass properties of all edges in the shape with a linear density of 1;
 * **sprops** of all faces with a surface density of 1;
 * **vprops** of all solids with a density of 1. 
 
+For computation of properties of the shape, exact geomery (curves, surfaces) or
+some discrete data (polygons, triangulations) can be used for calculations.
+The epsilon, if given, defines relative precision of computation.
+The **closed** flag, if present, forces computation only closed shells of the shape.
+The centroid coordinates will be put to DRAW variables x y z (if given).
+Shared entities will be taken in account only one time in the **skip** mode.
+All values are output with the full precision in the **full** mode.
+Preferable source of geometry data are triangulations in case if it exists, 
+if the **-tri** key is used, otherwise preferable data is exact geometry.
+If epsilon is given, exact geometry (curves, surfaces) are used for calculations independently of using key **-tri**.
+
 All three commands print the mass, the coordinates of the center of gravity, the matrix of inertia and the moments. Mass is either the length, the area or the volume. The center and the main axis of inertia are displayed. 
 
 **Example:** 
index bb1364e..64ee561 100644 (file)
@@ -16,6 +16,8 @@
 #include <BRepGProp_Cinert.hxx>
 #include <BRepGProp_Sinert.hxx>
 #include <BRepGProp_Vinert.hxx>
+#include <BRepGProp_MeshProps.hxx>
+#include <BRepGProp_MeshCinert.hxx>
 #include <BRepGProp_VinertGK.hxx>
 #include <GProp_PGProps.hxx>
 #include <BRepGProp_Face.hxx>
@@ -29,6 +31,7 @@
 #include <TopTools_MapOfShape.hxx>
 #include <BRepCheck_Shell.hxx>
 #include <TopTools_ListIteratorOfListOfShape.hxx>
+
 #ifdef OCCT_DEBUG
 static Standard_Integer AffichEps = 0;
 #endif
@@ -38,18 +41,45 @@ static gp_Pnt roughBaryCenter(const TopoDS_Shape& S){
   gp_XYZ xyz(0,0,0);
   for (ex.Init(S,TopAbs_VERTEX), i = 0; ex.More(); ex.Next(), i++) 
     xyz += BRep_Tool::Pnt(TopoDS::Vertex(ex.Current())).XYZ();
-  if ( i > 0 ) xyz /= i;
+  if (i > 0)
+  {
+    xyz /= i;
+  }
+  else
+  {
+    //Try using triangulation
+    ex.Init(S, TopAbs_FACE);
+    for (; ex.More(); ex.Next())
+    {
+      const TopoDS_Shape& aF = ex.Current();
+      TopLoc_Location aLocDummy;
+      const Handle(Poly_Triangulation)& aTri =
+        BRep_Tool::Triangulation(TopoDS::Face(aF), aLocDummy);
+      if (!aTri.IsNull())
+      {
+        xyz = aTri->Node(1).XYZ();
+        if (!aLocDummy.IsIdentity())
+        {
+          aLocDummy.Transformation().Transforms(xyz);
+        }
+        break;
+      }
+    }
+  }
   return gp_Pnt(xyz);
 }
 
-void  BRepGProp::LinearProperties(const TopoDS_Shape& S, GProp_GProps& SProps, const Standard_Boolean SkipShared){
+
+
+void  BRepGProp::LinearProperties(const TopoDS_Shape& S, GProp_GProps& SProps, const Standard_Boolean SkipShared,
+                                  const Standard_Boolean UseTriangulation)
+{
   // find the origin
   gp_Pnt P(0,0,0);
   P.Transform(S.Location());
   SProps = GProp_GProps(P);
 
   BRepAdaptor_Curve   BAC;
-  Standard_Real eps = Epsilon(1.);
   TopTools_MapOfShape anEMap;
   TopExp_Explorer ex;
   for (ex.Init(S,TopAbs_EDGE); ex.More(); ex.Next()) {
@@ -58,27 +88,35 @@ void  BRepGProp::LinearProperties(const TopoDS_Shape& S, GProp_GProps& SProps, c
     {
       continue;
     }
-    if(!BRep_Tool::IsGeometric(aE))
+
+    Handle(TColgp_HArray1OfPnt) theNodes;
+    Standard_Boolean IsGeom = BRep_Tool::IsGeometric(aE);
+    if (UseTriangulation || !IsGeom)
     {
-      GProp_PGProps aPProps;
-      TopoDS_Iterator anIter(aE);
-      for(; anIter.More(); anIter.Next())
-      {
-        const TopoDS_Vertex& aV = TopoDS::Vertex(anIter.Value());
-        aPProps.AddPoint(BRep_Tool::Pnt(aV), eps);
-      }
-      SProps.Add(aPProps);
+      BRepGProp_MeshCinert::PreparePolygon(aE, theNodes);
+    }
+    if(!theNodes.IsNull())
+    {
+      BRepGProp_MeshCinert MG;
+      MG.SetLocation(P);
+      MG.Perform(theNodes->Array1());
+      SProps.Add(MG);
     }
     else
     {
-      BAC.Initialize(aE);
-      BRepGProp_Cinert CG(BAC,P);
-      SProps.Add(CG);
+      if (IsGeom)
+      {
+        BAC.Initialize(aE);
+        BRepGProp_Cinert CG(BAC, P);
+        SProps.Add(CG);
+      }
     }
   }
 }
 
-static Standard_Real surfaceProperties(const TopoDS_Shape& S, GProp_GProps& Props, const Standard_Real Eps, const Standard_Boolean SkipShared){
+static Standard_Real surfaceProperties(const TopoDS_Shape& S, GProp_GProps& Props, const Standard_Real Eps, const Standard_Boolean SkipShared,
+                                       const Standard_Boolean UseTriangulation)
+{
   Standard_Integer i;
 #ifdef OCCT_DEBUG
   Standard_Integer iErrorMax = 0;
@@ -87,66 +125,90 @@ static Standard_Real surfaceProperties(const TopoDS_Shape& S, GProp_GProps& Prop
   TopExp_Explorer ex; 
   gp_Pnt P(roughBaryCenter(S));
   BRepGProp_Sinert G;  G.SetLocation(P);
+  BRepGProp_MeshProps MG(BRepGProp_MeshProps::Sinert);  
+  MG.SetLocation(P);
 
   BRepGProp_Face   BF;
   BRepGProp_Domain BD;
   TopTools_MapOfShape aFMap;
   TopLoc_Location aLocDummy;
 
-  for (ex.Init(S,TopAbs_FACE), i = 1; ex.More(); ex.Next(), i++) {
+  for (ex.Init(S, TopAbs_FACE), i = 1; ex.More(); ex.Next(), i++) {
     const TopoDS_Face& F = TopoDS::Face(ex.Current());
-    if(SkipShared && !aFMap.Add(F))
+    if (SkipShared && !aFMap.Add(F))
     {
       continue;
     }
 
+    Standard_Boolean NoSurf = Standard_False, NoTri = Standard_False;
     {
-      const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface (F, aLocDummy);
+      const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface(F, aLocDummy);
       if (aSurf.IsNull())
       {
-        // skip faces without geometry
+        NoSurf = Standard_True;
+      }
+      const Handle(Poly_Triangulation)& aTri = BRep_Tool::Triangulation(F, aLocDummy);
+      if (aTri.IsNull())
+      {
+        NoTri = Standard_True;
+      }
+      if (NoTri && NoSurf)
+      {
         continue;
       }
     }
 
-    BF.Load(F);
-    Standard_Boolean IsNatRestr = (F.NbChildren() == 0);
-    if(!IsNatRestr) BD.Init(F);
-    if(Eps < 1.0) {
-      G.Perform(BF, BD, Eps); 
-      Error = G.GetEpsilon();
-      if(ErrorMax < Error) {
-        ErrorMax = Error;
+    if ((UseTriangulation && !NoTri) || (NoSurf && !NoTri))
+    {
+      TopAbs_Orientation anOri = F.Orientation();
+      const Handle(Poly_Triangulation)& aTri = BRep_Tool::Triangulation(F, aLocDummy);
+      MG.Perform(aTri, aLocDummy, anOri);
+      Props.Add(MG);
+    }
+    else
+    {
+      BF.Load(F);
+      Standard_Boolean IsNatRestr = (F.NbChildren() == 0);
+      if (!IsNatRestr) BD.Init(F);
+      if (Eps < 1.0) {
+        G.Perform(BF, BD, Eps);
+        Error = G.GetEpsilon();
+        if (ErrorMax < Error) {
+          ErrorMax = Error;
 #ifdef OCCT_DEBUG
-        iErrorMax = i;
+          iErrorMax = i;
 #endif
+        }
       }
-    } else {
-      if(IsNatRestr) G.Perform(BF);
-      else G.Perform(BF, BD);
-    }
-    Props.Add(G);
+      else {
+        if (IsNatRestr) G.Perform(BF);
+        else G.Perform(BF, BD);
+      }
+      Props.Add(G);
 #ifdef OCCT_DEBUG
-    if(AffichEps) cout<<"\n"<<i<<":\tEpsArea = "<< G.GetEpsilon();
+      if(AffichEps) cout<<"\n"<<i<<":\tEpsArea = "<< G.GetEpsilon();
 #endif
+    }
   }
 #ifdef OCCT_DEBUG
   if(AffichEps) cout<<"\n-----------------\n"<<iErrorMax<<":\tMaxError = "<<ErrorMax<<"\n";
 #endif
   return ErrorMax;
 }
-void  BRepGProp::SurfaceProperties(const TopoDS_Shape& S, GProp_GProps& Props, const Standard_Boolean SkipShared){
+void  BRepGProp::SurfaceProperties(const TopoDS_Shape& S, GProp_GProps& Props, const Standard_Boolean SkipShared,
+                                   const Standard_Boolean UseTriangulation)
+{
   // find the origin
   gp_Pnt P(0,0,0);
   P.Transform(S.Location());
   Props = GProp_GProps(P);
-  surfaceProperties(S,Props,1.0, SkipShared);
+  surfaceProperties(S,Props,1.0, SkipShared, UseTriangulation);
 }
 Standard_Real BRepGProp::SurfaceProperties(const TopoDS_Shape& S, GProp_GProps& Props, const Standard_Real Eps, const Standard_Boolean SkipShared){ 
   // find the origin
   gp_Pnt P(0,0,0);  P.Transform(S.Location());
   Props = GProp_GProps(P);
-  Standard_Real ErrorMax = surfaceProperties(S,Props,Eps,SkipShared);
+  Standard_Real ErrorMax = surfaceProperties(S,Props,Eps,SkipShared, Standard_False);
   return ErrorMax;
 }
 
@@ -155,7 +217,9 @@ Standard_Real BRepGProp::SurfaceProperties(const TopoDS_Shape& S, GProp_GProps&
 //purpose  : 
 //=======================================================================
 
-static Standard_Real volumeProperties(const TopoDS_Shape& S, GProp_GProps& Props, const Standard_Real Eps, const Standard_Boolean SkipShared){
+static Standard_Real volumeProperties(const TopoDS_Shape& S, GProp_GProps& Props, const Standard_Real Eps, const Standard_Boolean SkipShared,
+                                      const Standard_Boolean UseTriangulation)
+{
   Standard_Integer i;
 #ifdef OCCT_DEBUG
   Standard_Integer iErrorMax = 0;
@@ -164,6 +228,8 @@ static Standard_Real volumeProperties(const TopoDS_Shape& S, GProp_GProps& Props
   TopExp_Explorer ex; 
   gp_Pnt P(roughBaryCenter(S)); 
   BRepGProp_Vinert G;  G.SetLocation(P);
+  BRepGProp_MeshProps MG(BRepGProp_MeshProps::Vinert);
+  MG.SetLocation(P);
 
   BRepGProp_Face   BF;
   BRepGProp_Domain BD;
@@ -187,37 +253,56 @@ static Standard_Real volumeProperties(const TopoDS_Shape& S, GProp_GProps& Props
         continue;
       }
     }
+    Standard_Boolean NoSurf = Standard_False, NoTri = Standard_False;
     {
       const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface (F, aLocDummy);
       if (aSurf.IsNull())
       {
-        // skip faces without geometry
+        NoSurf = Standard_True;
+      }
+      const Handle(Poly_Triangulation)& aTri = BRep_Tool::Triangulation(F, aLocDummy);
+      if (aTri.IsNull())
+      {
+        NoTri = Standard_True;
+      }
+      if (NoTri && NoSurf)
+      {
         continue;
       }
     }
 
-    if (isFwd || isRvs){
-      BF.Load(F);
-      Standard_Boolean IsNatRestr = (F.NbChildren () == 0);
-      if(!IsNatRestr) BD.Init(F);
-      if(Eps < 1.0) {
-        G.Perform(BF, BD, Eps); 
-        Error = G.GetEpsilon();
-        if(ErrorMax < Error) {
-          ErrorMax = Error;
+    if (isFwd || isRvs)
+    {
+      if ((UseTriangulation && !NoTri) || (NoSurf && !NoTri))
+      {
+        const Handle(Poly_Triangulation)& aTri = BRep_Tool::Triangulation(F, aLocDummy);
+        MG.Perform(aTri, aLocDummy, anOri);
+        Props.Add(MG);
+      }
+      else
+      {
+        BF.Load(F);
+        Standard_Boolean IsNatRestr = (F.NbChildren () == 0);
+        if (!IsNatRestr) BD.Init(F);
+        if (Eps < 1.0) {
+          G.Perform(BF, BD, Eps);
+          Error = G.GetEpsilon();
+          if (ErrorMax < Error) {
+            ErrorMax = Error;
 #ifdef OCCT_DEBUG
-          iErrorMax = i;
+            iErrorMax = i;
 #endif
+          }
         }
-      }
-      else {
-        if(IsNatRestr) G.Perform(BF);
-        else G.Perform(BF, BD);
-      }
-      Props.Add(G);
+        else {
+          if (IsNatRestr) G.Perform(BF);
+          else G.Perform(BF, BD);
+        }
+        Props.Add(G);
 #ifdef OCCT_DEBUG
-      if(AffichEps) cout<<"\n"<<i<<":\tEpsVolume = "<< G.GetEpsilon();
+        if(AffichEps) cout<<"\n"<<i<<":\tEpsVolume = "<< G.GetEpsilon();
 #endif
+      }
     }
   }
 #ifdef OCCT_DEBUG
@@ -225,7 +310,9 @@ static Standard_Real volumeProperties(const TopoDS_Shape& S, GProp_GProps& Props
 #endif
   return ErrorMax;
 }
-void  BRepGProp::VolumeProperties(const TopoDS_Shape& S, GProp_GProps& Props, const Standard_Boolean OnlyClosed, const Standard_Boolean SkipShared){
+void  BRepGProp::VolumeProperties(const TopoDS_Shape& S, GProp_GProps& Props, const Standard_Boolean OnlyClosed, const Standard_Boolean SkipShared,
+                                  const Standard_Boolean UseTriangulation)
+{
   // find the origin
   gp_Pnt P(0,0,0);  P.Transform(S.Location());
   Props = GProp_GProps(P);
@@ -238,9 +325,9 @@ void  BRepGProp::VolumeProperties(const TopoDS_Shape& S, GProp_GProps& Props, co
       {
         continue;
       }
-      if(BRep_Tool::IsClosed(Sh)) volumeProperties(Sh,Props,1.0,SkipShared);
+      if(BRep_Tool::IsClosed(Sh)) volumeProperties(Sh,Props,1.0,SkipShared, UseTriangulation);
     }
-  } else volumeProperties(S,Props,1.0,SkipShared);
+  } else volumeProperties(S,Props,1.0,SkipShared, UseTriangulation);
 }
 
 //=======================================================================
@@ -269,7 +356,7 @@ Standard_Real BRepGProp::VolumeProperties(const TopoDS_Shape& S, GProp_GProps& P
         continue;
       }
       if(BRep_Tool::IsClosed(Sh)) {
-        Error = volumeProperties(Sh,Props,Eps,SkipShared);
+        Error = volumeProperties(Sh,Props,Eps,SkipShared, Standard_False);
         if(ErrorMax < Error) {
           ErrorMax = Error;
 #ifdef OCCT_DEBUG
@@ -278,7 +365,7 @@ Standard_Real BRepGProp::VolumeProperties(const TopoDS_Shape& S, GProp_GProps& P
         }
       }
     }
-  } else ErrorMax = volumeProperties(S,Props,Eps,SkipShared);
+  } else ErrorMax = volumeProperties(S,Props,Eps,SkipShared, Standard_False);
 #ifdef OCCT_DEBUG
   if(AffichEps) cout<<"\n\n==================="<<iErrorMax<<":\tMaxEpsVolume = "<<ErrorMax<<"\n";
 #endif
index 29a33b0..f13541d 100644 (file)
@@ -23,6 +23,8 @@
 
 #include <Standard_Real.hxx>
 #include <Standard_Boolean.hxx>
+#include <TColgp_Array1OfXYZ.hxx>
+
 class TopoDS_Shape;
 class GProp_GProps;
 class gp_Pln;
@@ -35,6 +37,7 @@ class BRepGProp_Vinert;
 class BRepGProp_VinertGK;
 class BRepGProp_UFunction;
 class BRepGProp_TFunction;
+class gp_XYZ;
 
 
 //! Provides global functions to compute a shape's global
@@ -85,10 +88,19 @@ public:
   //! No check is performed to verify that the shape S
   //! retains truly linear properties. If S is simply a vertex, it
   //! is not considered to present any additional global properties.
-  //! SkipShared is special flag, which allows to take in calculation shared topological entities or not
-  //! For ex., if SkipShared = True, edges, shared by two or more faces, are taken into calculation only once.
-  //! If we have cube with sizes 1, 1, 1, its linear properties = 12 for SkipEdges = true and 24 for SkipEdges = false.
-  Standard_EXPORT static void LinearProperties (const TopoDS_Shape& S, GProp_GProps& LProps, const Standard_Boolean SkipShared = Standard_False);
+  //! SkipShared is a special flag, which allows taking in calculation 
+  //! shared topological entities or not.
+  //! For ex., if SkipShared = True, edges, shared by two or more faces, 
+  //! are taken into calculation only once.
+  //! If we have cube with sizes 1, 1, 1, its linear properties = 12 
+  //! for SkipEdges = true and 24 for SkipEdges = false.
+  //! UseTriangulation is a special flag, which defines preferable 
+  //! source of geometry data. If UseTriangulation = Standard_False,
+  //! exact geometry objects (curves) are used, otherwise polygons of 
+  //! triangulation are used first.
+  Standard_EXPORT static void LinearProperties(const TopoDS_Shape& S, GProp_GProps& LProps, 
+                                  const Standard_Boolean SkipShared = Standard_False,
+                                  const Standard_Boolean UseTriangulation = Standard_False);
   
   //! Computes the surface global properties of the
   //! shape S, i.e. the global properties induced by each
@@ -122,9 +134,17 @@ public:
   //! retains truly surface properties. If S is simply a
   //! vertex, an edge or a wire, it is not considered to
   //! present any additional global properties.
-  //! SkipShared is special flag, which allows to take in calculation shared topological entities or not
-  //! For ex., if SkipShared = True, faces, shared by two or more shells, are taken into calculation only once.
-  Standard_EXPORT static void SurfaceProperties (const TopoDS_Shape& S, GProp_GProps& SProps, const Standard_Boolean SkipShared = Standard_False);
+  //! SkipShared is a special flag, which allows taking in calculation 
+  //! shared topological entities or not.
+  //! For ex., if SkipShared = True, faces, shared by two or more shells, 
+  //! are taken into calculation only once.
+  //! UseTriangulation is a special flag, which defines preferable 
+  //! source of geometry data. If UseTriangulation = Standard_False,
+  //! exact geometry objects (surfaces) are used, 
+  //! otherwise face triangulations are used first.
+  Standard_EXPORT static void SurfaceProperties(const TopoDS_Shape& S, GProp_GProps& SProps, 
+                                         const Standard_Boolean SkipShared = Standard_False,
+                                  const Standard_Boolean UseTriangulation = Standard_False);
   
   //! Updates <SProps> with the shape <S>, that contains its pricipal properties.
   //! The surface properties of all the faces in <S> are computed.
@@ -134,9 +154,12 @@ public:
   //! for two successive steps of adaptive integration.
   //! Method returns estimation of relative error reached for whole shape.
   //! WARNING: if Eps > 0.001 algorithm performs non-adaptive integration.
-  //! SkipShared is special flag, which allows to take in calculation shared topological entities or not
-  //! For ex., if SkipShared = True, faces, shared by two or more shells, are taken into calculation only once.
-  Standard_EXPORT static Standard_Real SurfaceProperties (const TopoDS_Shape& S, GProp_GProps& SProps, const Standard_Real Eps, const Standard_Boolean SkipShared = Standard_False);
+  //! SkipShared is a special flag, which allows taking in calculation 
+  //! shared topological entities or not
+  //! For ex., if SkipShared = True, faces, shared by two or more shells, 
+  //! are taken into calculation only once.
+  Standard_EXPORT static Standard_Real SurfaceProperties (const TopoDS_Shape& S, GProp_GProps& SProps,
+                        const Standard_Real Eps, const Standard_Boolean SkipShared = Standard_False);
   //!
   //! Computes the global volume properties of the solid
   //! S, and brings them together with the global
@@ -170,9 +193,19 @@ public:
   //! exempt of any free boundary. Note that these
   //! conditions of coherence are not checked by this
   //! algorithm, and results will be false if they are not respected. 
-  //! SkipShared is special flag, which allows to take in calculation shared topological entities or not
-  //! For ex., if SkipShared = True, the volumes formed by the equal (the same TShape, location and orientation) faces are taken into calculation only once.
-  Standard_EXPORT static void VolumeProperties (const TopoDS_Shape& S, GProp_GProps& VProps, const Standard_Boolean OnlyClosed = Standard_False, const Standard_Boolean SkipShared = Standard_False);
+  //! SkipShared a is special flag, which allows taking in calculation 
+  //! shared topological entities or not.
+  //! For ex., if SkipShared = True, the volumes formed by the equal 
+  //! (the same TShape, location and orientation) faces are taken 
+  //! into calculation only once.
+  //! UseTriangulation is a special flag, which defines preferable
+  //! source of geometry data. If UseTriangulation = Standard_False,
+  //! exact geometry objects (surfaces) are used, 
+  //! otherwise face triangulations are used first.
+  Standard_EXPORT static void VolumeProperties(const TopoDS_Shape& S, GProp_GProps& VProps, 
+                                        const Standard_Boolean OnlyClosed = Standard_False, 
+                                        const Standard_Boolean SkipShared = Standard_False,
+                                 const Standard_Boolean UseTriangulation = Standard_False);
   
   //! Updates <VProps> with the shape <S>, that contains its pricipal properties.
   //! The volume properties of all the FORWARD and REVERSED faces in <S> are computed.
@@ -183,9 +216,14 @@ public:
   //! for two successive steps of adaptive integration.
   //! Method returns estimation of relative error reached for whole shape.
   //! WARNING: if Eps > 0.001 algorithm performs non-adaptive integration.
-  //! SkipShared is special flag, which allows to take in calculation shared topological entities or not
-  //! For ex., if SkipShared = True, the volumes formed by the equal (the same TShape, location and orientation) faces are taken into calculation only once.
-  Standard_EXPORT static Standard_Real VolumeProperties (const TopoDS_Shape& S, GProp_GProps& VProps, const Standard_Real Eps, const Standard_Boolean OnlyClosed = Standard_False, const Standard_Boolean SkipShared = Standard_False);
+  //! SkipShared is a special flag, which allows taking in calculation shared
+  //! topological entities or not.
+  //! For ex., if SkipShared = True, the volumes formed by the equal 
+  //! (the same TShape, location and orientation) 
+  //! faces are taken into calculation only once.
+  Standard_EXPORT static Standard_Real VolumeProperties (const TopoDS_Shape& S, GProp_GProps& VProps, 
+                         const Standard_Real Eps, const Standard_Boolean OnlyClosed = Standard_False, 
+                                                 const Standard_Boolean SkipShared = Standard_False);
   
   //! Updates <VProps> with the shape <S>, that contains its pricipal properties.
   //! The volume properties of all the FORWARD and REVERSED faces in <S> are computed.
@@ -198,13 +236,27 @@ public:
   //! that is used for properties computation.
   //! Method returns estimation of relative error reached for whole shape.
   //! Returns negative value if the computation is failed.
-  //! SkipShared is special flag, which allows to take in calculation shared topological entities or not
-  //! For ex., if SkipShared = True, the volumes formed by the equal (the same TShape, location and orientation) faces are taken into calculation only once.
-  Standard_EXPORT static Standard_Real VolumePropertiesGK (const TopoDS_Shape& S, GProp_GProps& VProps, const Standard_Real Eps = 0.001, const Standard_Boolean OnlyClosed = Standard_False, const Standard_Boolean IsUseSpan = Standard_False, const Standard_Boolean CGFlag = Standard_False, const Standard_Boolean IFlag = Standard_False, const Standard_Boolean SkipShared = Standard_False);
+  //! SkipShared is a special flag, which allows taking in calculation
+  //! shared topological entities or not.
+  //! For ex., if SkipShared = True, the volumes formed by the equal 
+  //! (the same TShape, location and orientation) faces are taken into calculation only once.
+  Standard_EXPORT static Standard_Real VolumePropertiesGK (const TopoDS_Shape& S, 
+    GProp_GProps& VProps, 
+    const Standard_Real Eps = 0.001, 
+    const Standard_Boolean OnlyClosed = Standard_False, 
+    const Standard_Boolean IsUseSpan = Standard_False, 
+    const Standard_Boolean CGFlag = Standard_False, 
+    const Standard_Boolean IFlag = Standard_False, 
+    const Standard_Boolean SkipShared = Standard_False);
   
-  Standard_EXPORT static Standard_Real VolumePropertiesGK (const TopoDS_Shape& S, GProp_GProps& VProps, const gp_Pln& thePln, const Standard_Real Eps = 0.001, const Standard_Boolean OnlyClosed = Standard_False, const Standard_Boolean IsUseSpan = Standard_False, const Standard_Boolean CGFlag = Standard_False, const Standard_Boolean IFlag = Standard_False, const Standard_Boolean SkipShared = Standard_False);
-
-
+  Standard_EXPORT static Standard_Real VolumePropertiesGK (const TopoDS_Shape& S, 
+    GProp_GProps& VProps, 
+    const gp_Pln& thePln, const Standard_Real Eps = 0.001, 
+    const Standard_Boolean OnlyClosed = Standard_False, 
+    const Standard_Boolean IsUseSpan = Standard_False, 
+    const Standard_Boolean CGFlag = Standard_False, 
+    const Standard_Boolean IFlag = Standard_False, 
+    const Standard_Boolean SkipShared = Standard_False);
 
 
 protected:
diff --git a/src/BRepGProp/BRepGProp_MeshCinert.cxx b/src/BRepGProp/BRepGProp_MeshCinert.cxx
new file mode 100644 (file)
index 0000000..1daa658
--- /dev/null
@@ -0,0 +1,236 @@
+// Copyright (c) 2018 OPEN CASCADE SAS
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+
+#include <BRepGProp_MeshCinert.hxx>
+#include <gp_Pnt.hxx>
+#include <math.hxx>
+#include <TopoDS_Edge.hxx>
+#include <Poly_Polygon3D.hxx>
+#include <BRep_Tool.hxx>
+
+//=======================================================================
+//function : BRepGProp_MeshCinert
+//purpose  : 
+//=======================================================================
+
+BRepGProp_MeshCinert::BRepGProp_MeshCinert()
+{
+}
+
+//=======================================================================
+//function : SetLocation
+//purpose  : 
+//=======================================================================
+void BRepGProp_MeshCinert::SetLocation(const gp_Pnt& CLocation)
+{
+  loc = CLocation;
+}
+
+//=======================================================================
+//function : Perform
+//purpose  : 
+//=======================================================================
+void BRepGProp_MeshCinert::Perform(const TColgp_Array1OfPnt& theNodes)
+{
+
+  Standard_Real Ix, Iy, Iz, Ixx, Iyy, Izz, Ixy, Ixz, Iyz;
+  dim = Ix = Iy = Iz = Ixx = Iyy = Izz = Ixy = Ixz = Iyz = 0.0;
+
+  Standard_Integer Order = 2; 
+
+  Standard_Real ds;  
+  Standard_Real ur, um, u;
+  Standard_Real x, y, z; 
+  Standard_Real xloc, yloc, zloc;
+  Standard_Real Upper;
+  gp_XYZ P, D;
+
+  math_Vector GaussP (1, Order);
+  math_Vector GaussW (1, Order);
+
+  math::GaussPoints  (Order,GaussP);
+  math::GaussWeights (Order,GaussW);
+
+  Standard_Integer nIndex = 0;
+
+  for(nIndex = 1; nIndex < theNodes.Length(); nIndex++) 
+  {
+    const gp_XYZ& aP1 = theNodes(nIndex).XYZ();
+    const gp_XYZ& aP2 = theNodes(nIndex + 1).XYZ();
+    Standard_Real dimLocal, IxLocal, IyLocal, IzLocal, IxxLocal, IyyLocal, IzzLocal, IxyLocal, IxzLocal, IyzLocal;
+    dimLocal = IxLocal = IyLocal = IzLocal = IxxLocal = IyyLocal = IzzLocal = IxyLocal = IxzLocal = IyzLocal = 0.0;
+
+    loc.Coord (xloc, yloc, zloc);
+
+    Standard_Integer i;
+
+    Upper = (aP2 - aP1).Modulus();
+    if (Upper < gp::Resolution())
+    {
+      continue;
+    }
+    um = 0.5 * Upper;
+    ur =um;
+    D = (aP2 - aP1) / Upper;
+
+    for (i = 1; i <= Order; i++) {
+      u = um + ur * GaussP (i);
+      P = aP1 + u * D;
+      P.Coord (x, y, z);
+      x   -= xloc;
+      y   -= yloc;
+      z   -= zloc;
+      ds = GaussW (i);
+      dimLocal += ds; 
+      IxLocal  += x * ds;  
+      IyLocal  += y * ds;
+      IzLocal  += z * ds;
+      IxyLocal += x * y * ds;
+      IyzLocal += y * z * ds;
+      IxzLocal += x * z * ds;
+      x   *= x;      
+      y   *= y;      
+      z   *= z;      
+      IxxLocal += (y + z) * ds;
+      IyyLocal += (x + z) * ds;
+      IzzLocal += (x + y) * ds;
+    }
+
+    dimLocal *= ur;
+    IxLocal  *= ur;
+    IyLocal  *= ur;
+    IzLocal  *= ur;
+    IxxLocal *= ur;
+    IyyLocal *= ur;
+    IzzLocal *= ur;
+    IxyLocal *= ur;
+    IxzLocal *= ur;
+    IyzLocal *= ur;
+
+    dim += dimLocal;
+    Ix += IxLocal;
+    Iy += IyLocal;
+    Iz += IzLocal;
+    Ixx += IxxLocal;
+    Iyy += IyyLocal;
+    Izz += IzzLocal;
+    Ixy += IxyLocal;
+    Ixz += IxzLocal;
+    Iyz += IyzLocal;
+  }
+
+  inertia = gp_Mat (gp_XYZ (Ixx, -Ixy, -Ixz),
+    gp_XYZ (-Ixy, Iyy, -Iyz),
+    gp_XYZ (-Ixz, -Iyz, Izz));
+
+  if (Abs(dim) < gp::Resolution())
+    g = P;
+  else
+    g.SetCoord (Ix/dim, Iy/dim, Iz/dim);
+}
+
+//=======================================================================
+//function : PreparePolygon
+//purpose  : 
+//=======================================================================
+void BRepGProp_MeshCinert::PreparePolygon(const TopoDS_Edge& theE, 
+                                          Handle(TColgp_HArray1OfPnt)& thePolyg)
+{
+  TopLoc_Location aLoc;
+  const Handle(Poly_Polygon3D)& aPolyg = BRep_Tool::Polygon3D(theE, aLoc);
+  if (!aPolyg.IsNull())
+  {
+    const TColgp_Array1OfPnt& aNodes = aPolyg->Nodes();
+    thePolyg = new TColgp_HArray1OfPnt(1, aNodes.Length());
+    Standard_Integer i;
+    if (aLoc.IsIdentity())
+    {
+      for (i = 1; i <= aNodes.Length(); ++i)
+      {
+        thePolyg->SetValue(i, aNodes(i));
+      }
+    }
+    else
+    {
+      const gp_Trsf& aTr = aLoc.Transformation();
+      for (i = 1; i <= aNodes.Length(); ++i)
+      {
+        thePolyg->SetValue(i, aNodes.Value(i).Transformed(aTr));
+      }
+    }
+    return;
+  }
+
+  //Try to get PolygonOnTriangulation
+  Handle(Poly_Triangulation) aTri;
+  Handle(Poly_PolygonOnTriangulation) aPOnTri;
+  BRep_Tool::PolygonOnTriangulation(theE, aPOnTri, aTri, aLoc);
+  if (!aPOnTri.IsNull())
+  {
+    Standard_Integer aNbNodes = aPOnTri->NbNodes();
+    thePolyg = new TColgp_HArray1OfPnt(1, aNbNodes);
+    const TColStd_Array1OfInteger& aNodeInds = aPOnTri->Nodes();
+    const TColgp_Array1OfPnt& aNodes = aTri->Nodes();
+    Standard_Integer i;
+    if (aLoc.IsIdentity())
+    {
+      for (i = 1; i <= aNbNodes; ++i)
+      {
+        thePolyg->SetValue(i, aNodes(aNodeInds(i)));
+      }
+    }
+    else
+    {
+      const gp_Trsf& aTr = aLoc.Transformation();
+      for (i = 1; i <= aNbNodes; ++i)
+      {
+        thePolyg->SetValue(i, aNodes.Value(aNodeInds(i)).Transformed(aTr));
+      }
+    }
+    return;
+  }
+  //
+  //Try to get Polygon2D on Surface
+  Handle(Poly_Polygon2D) aPolyg2D;
+  Handle(Geom_Surface) aS;
+  BRep_Tool::PolygonOnSurface(theE, aPolyg2D, aS, aLoc);
+  if (!aPolyg2D.IsNull())
+  {
+    Standard_Integer aNbNodes = aPolyg2D->NbNodes();
+    thePolyg = new TColgp_HArray1OfPnt(1, aNbNodes);
+    const TColgp_Array1OfPnt2d& aNodes2D = aPolyg2D->Nodes();
+    Standard_Integer i;
+    if (aLoc.IsIdentity())
+    {
+      for (i = 1; i <= aNbNodes; ++i)
+      {
+        const gp_Pnt2d& aP2d = aNodes2D(i);
+        gp_Pnt aP = aS->Value(aP2d.X(), aP2d.Y());
+        thePolyg->SetValue(i, aP);
+      }
+    }
+    else
+    {
+      const gp_Trsf& aTr = aLoc.Transformation();
+      for (i = 1; i <= aNbNodes; ++i)
+      {
+        const gp_Pnt2d& aP2d = aNodes2D(i);
+        gp_Pnt aP = aS->Value(aP2d.X(), aP2d.Y());
+        aP.Transform(aTr);
+        thePolyg->SetValue(i, aP);
+      }
+    }
+    return;
+  }
+
+}
diff --git a/src/BRepGProp/BRepGProp_MeshCinert.hxx b/src/BRepGProp/BRepGProp_MeshCinert.hxx
new file mode 100644 (file)
index 0000000..d9f2d8b
--- /dev/null
@@ -0,0 +1,67 @@
+// Copyright (c) 2018 OPEN CASCADE SAS
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BRepGProp_MeshCinert_HeaderFile
+#define _BRepGProp_MeshCinert_HeaderFile
+
+#include <Standard.hxx>
+#include <Standard_DefineAlloc.hxx>
+#include <Standard_Handle.hxx>
+#include <TColgp_Array1OfPnt.hxx>
+#include <TColgp_HArray1OfPnt.hxx>
+#include <GProp_GProps.hxx>
+class gp_Pnt;
+class TopoDS_Edge;
+
+
+
+//! Computes the  global properties of 
+//! of polylines  represented by set of points.
+//! This class is used for computation of global
+//! properties of edge, which has no exact geometry
+//! (3d or 2d curve), but has any of allowed
+//! polygons.
+//! 
+class BRepGProp_MeshCinert  : public GProp_GProps
+{
+public:
+
+  DEFINE_STANDARD_ALLOC
+
+  
+  Standard_EXPORT BRepGProp_MeshCinert();
+    
+  Standard_EXPORT void SetLocation (const gp_Pnt& CLocation);
+  
+  //! Computes the  global properties of 
+  //! of polylines  represented by set of points.
+  Standard_EXPORT void Perform(const TColgp_Array1OfPnt& theNodes);
+
+  //! Prepare set of 3d points on base of any available edge polygons:
+  //! 3D polygon, polygon on triangulation, 2d polygon on surface
+  //! If edge has no polygons, array thePolyg is left unchanged
+  Standard_EXPORT static void PreparePolygon(const TopoDS_Edge& theE, Handle(TColgp_HArray1OfPnt)& thePolyg);
+
+protected:
+
+
+
+
+
+private:
+
+
+
+
+};
+
+#endif // _BRepGProp_MeshCinert_HeaderFile
diff --git a/src/BRepGProp/BRepGProp_MeshProps.cxx b/src/BRepGProp/BRepGProp_MeshProps.cxx
new file mode 100644 (file)
index 0000000..9611dce
--- /dev/null
@@ -0,0 +1,291 @@
+// Copyright (c) 2018 OPEN CASCADE SAS
+// This file is part of commercial software by OPEN CASCADE SAS, 
+// furnished in accordance with the terms and conditions of the contract 
+// and with the inclusion of this copyright notice. 
+// This file or any part thereof may not be provided or otherwise 
+// made available to any third party. 
+// 
+// No ownership title to the software is transferred hereby. 
+// 
+// OPEN CASCADE SAS makes no representation or warranties with respect to the 
+// performance of this software, and specifically disclaims any responsibility 
+// for any damages, special or consequential, connected with its use.
+
+#include <BRepGProp_MeshProps.hxx>
+#include <gp_Pnt.hxx>
+#include <Poly_Triangulation.hxx>
+#include <Poly_Triangle.hxx>
+#include<ElSLib.hxx>
+#include<gp_Ax3.hxx>
+#include <BRepGProp.hxx>
+#include <TopLoc_Location.hxx>
+#include <GProp.hxx>
+
+//=======================================================================
+//function : CalculateElSProps
+//purpose  : Calculate one Gauss point for surface properties 
+//           of triangle p1, p2, p3
+//           relatively point Apex 
+//=======================================================================
+static void CalculateElSProps(const Standard_Real x, 
+  const Standard_Real y,
+  const Standard_Real z, const Standard_Real ds, Standard_Real* GProps)
+{
+  //GProps[0] = Volume
+  // Static moments of inertia.
+  //GProps[1] = Ix, GProps[2] = Iy, GProps[3] = Iz
+  //Matrix of moments of inertia.
+  //GProps[4] = Ixx, GProps[5] = Iyy, GProps[6] = Izz,
+  //GProps[7] = Ixy, aGProps[8] = Ixz, GProps[9] = Iyz,
+  //
+  Standard_Real x2, y2, z2;
+  x2 = x * x;
+  y2 = y * y;
+  z2 = z * z;
+
+  GProps[0] += ds;       //Area       
+  GProps[1] += x * ds;  //Ix
+  GProps[2] += y * ds;  //Iy
+  GProps[3] += z * ds;  //Iz
+  //
+  GProps[7] += x * y * ds; //Ixy
+  GProps[8] += x * z * ds; //Ixz
+  GProps[9] += y * z * ds; //Iyz
+  GProps[4] += (y2 + z2) * ds; //Ixx
+  GProps[5] += (x2 + z2) * ds; //Iyy
+  GProps[6] += (x2 + y2) * ds; //Izz
+}
+//=======================================================================
+//function : CalculateElVProps
+//purpose  : Calculate one Gauss point for volume properties of pyramid, 
+//           based on triangle p1, p2, p3 with apex Apex 
+//=======================================================================
+static void CalculateElVProps(const Standard_Real x, 
+  const Standard_Real y,
+  const Standard_Real z, const Standard_Real dv, Standard_Real* GProps)
+{
+  Standard_Real x2, y2, z2;
+  x2 = x * x;
+  y2 = y * y;
+  z2 = z * z;
+  GProps[0] += dv / 3.0;       //Volume       
+  GProps[1] += 0.25 * x * dv;  //Ix
+  GProps[2] += 0.25 * y * dv;  //Iy
+  GProps[3] += 0.25 * z * dv;  //Iz
+  Standard_Real dv1 = 0.2 * dv;
+  GProps[7] += x * y * dv1; //Ixy
+  GProps[8] += x * z * dv1; //Ixz
+  GProps[9] += y * z * dv1; //Iyz
+  GProps[4] += (y2 + z2) * dv1; //Ixx
+  GProps[5] += (x2 + z2) * dv1; //Iyy
+  GProps[6] += (x2 + y2) * dv1; //Izz
+}
+//=======================================================================
+//function : CalculateProps
+//purpose  : Calculate global surface properties of triangle 
+//           or volume properties of pyramid, based on triangle
+//           p1, p2, p3 with apex Apex by Gauss integration over triangle area.
+//=======================================================================
+ void BRepGProp_MeshProps::CalculateProps(const gp_Pnt& p1, const gp_Pnt& p2, 
+                                          const gp_Pnt& p3,
+                                          const gp_Pnt& Apex,
+                                          const Standard_Boolean isVolume,
+                                          Standard_Real GProps[10],
+                                          const Standard_Integer NbGaussPoints,
+                                          const Standard_Real* GaussPnts)
+{
+  //GProps[0] = Volume
+  // Static moments of inertia.
+  //GProps[1] = Ix, GProps[2] = Iy, GProps[3] = Iz
+  //Matrix of moments of inertia.
+  //GProps[4] = Ixx, GProps[5] = Iyy, GProps[6] = Izz,
+  //GProps[7] = Ixy, aGProps[8] = Ixz, GProps[9] = Iyz,
+  //
+
+  //Define plane and coordinates of triangle nodes on plane 
+  gp_Vec aV12(p2, p1);
+  gp_Vec aV23(p3, p2);
+  gp_Vec aNorm = aV12 ^ aV23;
+  Standard_Real aDet = aNorm.Magnitude();
+  if (aDet <= gp::Resolution())
+  {
+    return;
+  }
+  gp_XYZ aCenter = (p1.XYZ() + p2.XYZ() + p3.XYZ()) / 3.;
+  gp_Pnt aPC(aCenter);
+  gp_Dir aDN(aNorm);
+  gp_Ax3 aPosPln(aPC, aDN);
+  //Coordinates of nodes on plane
+  Standard_Real x1, y1, x2, y2, x3, y3;
+  ElSLib::PlaneParameters(aPosPln, p1, x1, y1);
+  ElSLib::PlaneParameters(aPosPln, p2, x2, y2);
+  ElSLib::PlaneParameters(aPosPln, p3, x3, y3);
+  //
+  Standard_Real l1, l2; //barycentriche coordinates
+  Standard_Real x, y, z;
+  Standard_Real w; //weight
+  Standard_Integer i;
+  for (i = 0; i < NbGaussPoints; ++i)
+  {
+    Standard_Integer ind = 3 * i;
+    l1 = GaussPnts[ind];
+    l2 = GaussPnts[ind + 1];
+    w = GaussPnts[ind + 2];
+    w *= aDet;
+    x = l1*(x1 - x3) + l2*(x2 - x3) + x3;
+    y = l1*(y1 - y3) + l2*(y2 - y3) + y3;
+    gp_Pnt aP = ElSLib::PlaneValue(x, y, aPosPln);
+    x = aP.X() - Apex.X();
+    y = aP.Y() - Apex.Y();
+    z = aP.Z() - Apex.Z();
+    //
+    if (isVolume)
+    {
+      Standard_Real xn = aDN.X() * w;
+      Standard_Real yn = aDN.Y() * w;
+      Standard_Real zn = aDN.Z() * w;
+      Standard_Real dv = x * xn + y * yn + z * zn;
+      CalculateElVProps(x, y, z, dv, GProps);
+    }
+    else
+    {
+      Standard_Real ds = w;
+      CalculateElSProps(x, y, z, ds, GProps);
+    }
+
+  }
+}
+
+//=======================================================================
+//function : Perform
+//purpose  : 
+//=======================================================================
+void BRepGProp_MeshProps::Perform(const Handle(Poly_Triangulation)& theMesh,
+                                  const TopLoc_Location& theLoc,
+                                  const TopAbs_Orientation theOri)
+{
+  if (theLoc.IsIdentity())
+  {
+    Perform(theMesh->Nodes(), theMesh->Triangles(), theOri);
+  }
+  else
+  {
+    const gp_Trsf& aTr = theLoc.Transformation();
+    //
+    Standard_Boolean isToCopy = aTr.ScaleFactor()*aTr.HVectorialPart().Determinant() < 0. ||
+                                Abs(Abs(aTr.ScaleFactor()) - 1.) > gp::Resolution();
+    if (isToCopy)
+    {
+      TColgp_Array1OfPnt aNodes(1, theMesh->NbNodes());
+      const TColgp_Array1OfPnt& aMeshNodes = theMesh->Nodes();
+      Standard_Integer i;
+      for (i = 1; i <= aMeshNodes.Length(); ++i)
+      {
+        aNodes(i) = aMeshNodes.Value(i).Transformed(aTr);
+      }
+      Perform(aNodes, theMesh->Triangles(), theOri);
+      return;
+    }
+    //
+    gp_Trsf aTrInv = aTr.Inverted();
+    gp_Pnt loc_save = loc;
+    loc.Transform(aTrInv);
+    Perform(theMesh->Nodes(), theMesh->Triangles(), theOri);
+    //Computes the inertia tensor at mesh gravity center
+    gp_Mat HMat, inertia0;
+    gp_Pnt g0 = g;
+    g.SetXYZ(g.XYZ() + loc.XYZ());
+    if (g0.XYZ().Modulus() > gp::Resolution())
+    {
+      GProp::HOperator(g, loc, dim, HMat);
+      inertia0 = inertia - HMat;
+    }
+    else
+    {
+      inertia0 = inertia;
+    }
+    //Transform inertia tensor for rotation
+    gp_Mat HVec = aTrInv.HVectorialPart();
+    gp_Mat HVecT = HVec.Transposed();
+    HVecT.Multiply(inertia0);
+    inertia0 = HVecT.Multiplied(HVec);
+    //Put gravity center in true position of mesh  
+    g.Transform(aTr);
+    g0 = g;
+    g.SetXYZ(g.XYZ() - loc_save.XYZ());
+    loc = loc_save;
+    //
+    //Computes the inertia tensor for loc
+    GProp::HOperator(g0, loc, dim, HMat);
+    inertia = inertia0 + HMat;
+  }
+}
+//=======================================================================
+//function : Perform
+//purpose  : 
+//=======================================================================
+void BRepGProp_MeshProps::Perform(const TColgp_Array1OfPnt& theNodes,
+                                   const Poly_Array1OfTriangle& theTriangles,
+                                   const TopAbs_Orientation theOri)
+{
+  //
+  // Gauss points for barycentriche coordinates
+  static const Standard_Real GPtsWg[] =
+  {  1. / 6., 1. / 6., 1. / 6., /*3 points*/
+     2. / 3., 1. / 6., 1. / 6.,
+     1. / 6., 2. / 3., 1. / 6. };
+  //
+  Standard_Integer aNbGaussPoints = 3;
+  
+  // Array to store global properties
+  Standard_Real aGProps[10] = { 0., 0., 0., 0., 0., 0., 0., 0., 0., 0 };
+  //aGProps[0] = Volume
+  // Static moments of inertia.
+  //aGProps[1] = Ix, aGProps[2] = Iy, aGProps[3] = Iz
+  //Matrix of moments of inertia.
+  //aGProps[4] = Ixx, aGProps[5] = Iyy, aGProps[6] = Izz,
+  //aGProps[7] = Ixy, aGProps[8] = Ixz, aGProps[9] = Iyz,
+
+  Standard_Boolean isVolume = myType == Vinert;
+  Standard_Integer i;
+  Standard_Integer n1, n2, n3; //node indeces
+  for (i = theTriangles.Lower(); i <= theTriangles.Upper(); ++i)
+  {
+    const Poly_Triangle& aTri = theTriangles(i);
+    aTri.Get(n1, n2, n3);
+    if (theOri == TopAbs_REVERSED)
+    {
+      Standard_Integer nn = n2;
+      n2 = n3;
+      n3 = nn;
+    }
+    // Calculate properties of a pyramid built on face and apex
+    const gp_Pnt& p1 = theNodes(n1);
+    const gp_Pnt& p2 = theNodes(n2);
+    const gp_Pnt& p3 = theNodes(n3);
+    CalculateProps(p1, p2, p3, loc, isVolume, aGProps, aNbGaussPoints, GPtsWg);
+  }
+
+  dim = aGProps[0];
+  if (Abs(dim) >= 1.e-20) //To be consistent with GProp_GProps
+  {
+    g.SetX(aGProps[1] / dim);
+    g.SetY(aGProps[2] / dim);
+    g.SetZ(aGProps[3] / dim);
+  }
+  else
+  {
+    g.SetX(aGProps[1]);
+    g.SetY(aGProps[2]);
+    g.SetZ(aGProps[3]);
+  }
+  inertia(1, 1) = aGProps[4];
+  inertia(1, 2) = -aGProps[7];
+  inertia(1, 3) = -aGProps[8];
+  inertia(2, 1) = -aGProps[7];
+  inertia(2, 2) = aGProps[5];
+  inertia(2, 3) = -aGProps[9];
+  inertia(3, 1) = -aGProps[8];
+  inertia(3, 2) = -aGProps[9];
+  inertia(3, 3) = aGProps[6];
+}
diff --git a/src/BRepGProp/BRepGProp_MeshProps.hxx b/src/BRepGProp/BRepGProp_MeshProps.hxx
new file mode 100644 (file)
index 0000000..77bc69d
--- /dev/null
@@ -0,0 +1,90 @@
+// Copyright (c) 2018 OPEN CASCADE SAS
+// This file is part of commercial software by OPEN CASCADE SAS, 
+// furnished in accordance with the terms and conditions of the contract 
+// and with the inclusion of this copyright notice. 
+// This file or any part thereof may not be provided or otherwise 
+// made available to any third party. 
+// 
+// No ownership title to the software is transferred hereby. 
+// 
+// OPEN CASCADE SAS makes no representation or warranties with respect to the 
+// performance of this software, and specifically disclaims any responsibility 
+// for any damages, special or consequential, connected with its use.
+
+#ifndef _BRepGProp_MeshProps_HeaderFile
+#define _BRepGProp_MeshProps_HeaderFile
+
+#include <Standard.hxx>
+#include <Standard_DefineAlloc.hxx>
+#include <Standard_Handle.hxx>
+#include <Standard_Type.hxx>
+#include <GProp_GProps.hxx>
+#include <TopAbs_Orientation.hxx>
+#include <Poly_Array1OfTriangle.hxx>
+#include <TColgp_Array1OfPnt.hxx>
+
+class Poly_Triangulation;
+class TopLoc_Location;
+class gp_Pnt;
+
+
+//! Computes the global properties of a surface mesh. The mesh can be
+//! interpreted as just a surface or as a piece of volume limited by this surface.
+class BRepGProp_MeshProps : public GProp_GProps
+{
+public:
+
+  DEFINE_STANDARD_ALLOC
+
+    //! Describes types of geometric objects.
+    //! - Vinert is 3D closed region of space delimited with
+    //!   Point and surface mesh;
+    //! - Sinert is surface mesh in 3D space.
+    typedef enum { Vinert = 0, Sinert } BRepGProp_MeshObjType;
+
+  //! Constructor takes the type of object.
+  BRepGProp_MeshProps(const BRepGProp_MeshObjType theType) :
+    myType(theType)
+  {}
+
+  //! Sets the point relative which the calculation is to be done
+  void SetLocation(const gp_Pnt& theLocation) { loc = theLocation; }
+
+  //! Computes the global properties of a surface mesh of 3D space.
+  //! Calculation of surface properties is performed by numerical integration
+  //! over triangle surfaces using Gauss cubature formulas. 
+  //! Depending on the mesh object type used in constructor this method can 
+  //! calculate the surface or volume properties of the mesh.
+  Standard_EXPORT void Perform(const Handle(Poly_Triangulation)& theMesh,
+                               const TopLoc_Location& theLoc,
+                               const TopAbs_Orientation theOri);
+
+  Standard_EXPORT void Perform(const TColgp_Array1OfPnt& theNodes,
+                               const Poly_Array1OfTriangle& theTriangles, 
+                               const TopAbs_Orientation theOri);
+
+  //! Computes the global properties of triangle {p1, p2, p3} relatively 
+  //! point Apex
+  //! If isVolume = true, volume properties are calculated
+  //! otherwise - surface ones
+  Standard_EXPORT static void CalculateProps(const gp_Pnt& p1, const gp_Pnt& p2, const gp_Pnt& p3,
+                                             const gp_Pnt& Apex,
+                                             const Standard_Boolean isVolume,
+                                             Standard_Real GProps[10],
+                                             const Standard_Integer NbGaussPoints,
+                                             const Standard_Real* GaussPnts);
+
+  //! Get type of mesh object
+  BRepGProp_MeshObjType GetMeshObjType() const
+  {
+    return myType;
+  }
+
+private: //! @name private fields
+
+
+  BRepGProp_MeshObjType myType; //!< Type of geometric object
+
+};
+
+#endif // _BRepGProp_MeshProps_HeaderFile
index abbd729..7018d72 100644 (file)
@@ -24,3 +24,7 @@ BRepGProp_Vinert.cxx
 BRepGProp_Vinert.hxx
 BRepGProp_VinertGK.cxx
 BRepGProp_VinertGK.hxx
+BRepGProp_MeshCinert.hxx
+BRepGProp_MeshCinert.cxx
+BRepGProp_MeshProps.hxx
+BRepGProp_MeshProps.cxx
index edf6e81..da09f0b 100644 (file)
@@ -41,16 +41,25 @@ Standard_IMPORT Draw_Viewer dout;
 Standard_Integer props(Draw_Interpretor& di, Standard_Integer n, const char** a)
 {
   if (n < 2) {
-    di << "Use: " << a[0] << " shape [epsilon] [c[losed]] [x y z] [-skip] [-full]\n";
-    di << "Compute properties of the shape\n";
+    di << "Use: " << a[0] << " shape [epsilon] [c[losed]] [x y z] [-skip] [-full] [-tri]\n";
+    di << "Compute properties of the shape, exact geometry (curves, surfaces) or\n";
+    di << "some discrete data (polygons, triangulations) can be used for calculations\n";
     di << "The epsilon, if given, defines relative precision of computation\n";
     di << "The \"closed\" flag, if present, do computation only closed shells of the shape\n";
     di << "The centroid coordinates will be put to DRAW variables x y z (if given)\n";
     di << "Shared entities will be take in account only one time in the skip mode\n";
-    di << "All values are outputted with the full precision in the full mode.\n\n";
+    di << "All values are outputted with the full precision in the full mode.\n";
+    di << "Preferable source of geometry data are triangulations in case if it exists, if the -tri key is used.\n";
+    di << "If epsilon is given, exact geometry (curves, surfaces) are used for calculations independently of using key -tri\n\n";
     return 1;
   }
 
+  Standard_Boolean UseTriangulation = Standard_False;
+  if (n >= 2 && strcmp(a[n - 1], "-tri") == 0)
+  {
+    UseTriangulation = Standard_True;
+    --n;
+  }
   Standard_Boolean isFullMode = Standard_False;
   if (n >= 2 && strcmp(a[n-1], "-full") == 0)
   {
@@ -86,11 +95,11 @@ Standard_Integer props(Draw_Interpretor& di, Standard_Integer n, const char** a)
   }
   else {
     if (*a[0] == 'l')
-      BRepGProp::LinearProperties(S,G,SkipShared);
+      BRepGProp::LinearProperties(S, G, SkipShared, UseTriangulation);
     else if (*a[0] == 's')
-      BRepGProp::SurfaceProperties(S,G,SkipShared);
+      BRepGProp::SurfaceProperties(S, G, SkipShared, UseTriangulation);
     else 
-      BRepGProp::VolumeProperties(S,G,onlyClosed,SkipShared);
+      BRepGProp::VolumeProperties(S,G,onlyClosed,SkipShared, UseTriangulation);
   }
   
   gp_Pnt P = G.CentreOfMass();
@@ -313,6 +322,7 @@ Standard_Integer vpropsgk(Draw_Interpretor& di, Standard_Integer n, const char**
 }
 
 
+
 //=======================================================================
 //function : GPropCommands
 //purpose  : 
@@ -328,11 +338,11 @@ void  BRepTest::GPropCommands(Draw_Interpretor& theCommands)
 
   const char* g = "Global properties";
   theCommands.Add("lprops",
-    "lprops name [x y z] [-skip] [-full] : compute linear properties",
+    "lprops name [x y z] [-skip] [-full] [-tri]: compute linear properties",
     __FILE__, props, g);
-  theCommands.Add("sprops", "sprops name [epsilon] [x y z] [-skip] [-full] :\n"
+  theCommands.Add("sprops", "sprops name [epsilon] [x y z] [-skip] [-full] [-tri]:\n"
 "  compute surfacic properties", __FILE__, props, g);
-  theCommands.Add("vprops", "vprops name [epsilon] [c[losed]] [x y z] [-skip] [-full] :\n"
+  theCommands.Add("vprops", "vprops name [epsilon] [c[losed]] [x y z] [-skip] [-full] [-tri]:\n"
 "  compute volumic properties", __FILE__, props, g);
 
   theCommands.Add("vpropsgk",
index 617ce09..7572bdc 100644 (file)
@@ -826,6 +826,43 @@ void BRepTools::Clean(const TopoDS_Shape& theShape)
     aBuilder.UpdateEdge (aEdge, aNullPoly3d);  
   }
 }
+//=======================================================================
+//function : CleanGeometry
+//purpose  : 
+//=======================================================================
+
+void BRepTools::CleanGeometry(const TopoDS_Shape& theShape)
+{
+  if (theShape.IsNull())
+    return;
+
+  BRep_Builder aBuilder;
+
+  for (TopExp_Explorer aFaceIt(theShape, TopAbs_FACE); aFaceIt.More(); aFaceIt.Next())
+  {
+    TopLoc_Location aLocation;
+    const TopoDS_Face& aFace = TopoDS::Face(aFaceIt.Current());
+    const Handle(Geom_Surface)& aSurface = BRep_Tool::Surface(aFace, aLocation);
+
+    for (TopExp_Explorer aEdgeIt(aFace, TopAbs_EDGE); aEdgeIt.More(); aEdgeIt.Next())
+    {
+      const TopoDS_Edge& anEdge = TopoDS::Edge(aEdgeIt.Current());
+      aBuilder.UpdateEdge(anEdge, Handle(Geom2d_Curve)(), aSurface,
+        aLocation, BRep_Tool::Tolerance(anEdge));
+    }
+
+    aBuilder.UpdateFace(aFace, Handle(Geom_Surface)(), aFace.Location(), BRep_Tool::Tolerance(aFace));
+  }
+
+  for (TopExp_Explorer aEdgeIt2(theShape, TopAbs_EDGE); aEdgeIt2.More(); aEdgeIt2.Next())
+  {
+    const TopoDS_Edge& anEdge = TopoDS::Edge(aEdgeIt2.Current());
+
+    aBuilder.UpdateEdge(anEdge, Handle(Geom_Curve)(),
+      TopLoc_Location(), BRep_Tool::Tolerance(anEdge));
+  }
+}
+
 
 //=======================================================================
 //function : RemoveUnusedPCurves
index b5113a9..e6bc4b5 100644 (file)
@@ -155,6 +155,9 @@ public:
   //! edges.
   Standard_EXPORT static void Clean (const TopoDS_Shape& S);
   
+  //! Removes geometry (curves and surfaces) from all edges and faces of the shape
+  Standard_EXPORT static void CleanGeometry(const TopoDS_Shape& theShape);
+
   //! Removes all the pcurves of the edges of <S> that
   //! refer to surfaces not belonging to any face of <S>
   Standard_EXPORT static void RemoveUnusedPCurves (const TopoDS_Shape& S);
index 1295d42..27dd671 100644 (file)
@@ -370,11 +370,22 @@ static Standard_Integer triangles(Draw_Interpretor& ,
 static Standard_Integer tclean(Draw_Interpretor& , 
                               Standard_Integer n, const char** a)
 {
-  if (n < 1) return 1;
-  
-  for (Standard_Integer i = 1; i < n; i++) {
+  if (n == 1) return 1;
+
+  Standard_Integer aStart = 1;
+  Standard_Boolean toRemoveGeometry = Standard_False;
+  if (strcmp(a[1], "-geom") == 0)
+  {
+    aStart++;
+    toRemoveGeometry = Standard_True;
+  }
+
+  for (Standard_Integer i = aStart; i < n; i++) {
     TopoDS_Shape S = DBRep::Get(a[i]);
-    BRepTools::Clean(S);
+    if (toRemoveGeometry)
+      BRepTools::CleanGeometry(S);
+    else
+      BRepTools::Clean(S);
   }
   return 0;
 }
@@ -1412,7 +1423,10 @@ void  DBRep::BasicCommands(Draw_Interpretor& theCommands)
   theCommands.Add("hlr" ,"[no]hlr, rg1, rgn, hid, ang",__FILE__,hlr ,g);
   theCommands.Add("vori","vori [name1 ...], edges are colored by orientation (see vconn)",__FILE__,dispor,g);
   theCommands.Add("triangles", "triangles [name1]..., display triangles of shapes if exists",__FILE__, triangles, g);
-  theCommands.Add("tclean", "tclean [name1]..., erase triangulations and polygons on triangulations from shapes",__FILE__, tclean, g); 
+  theCommands.Add("tclean", "tclean [-geom] [name1]..., depending on using or not key -geom, \n" 
+                   "\t erase geometry objects from shapes - key is used or \n"
+                   "\t erase triangulations and polygons on triangulations from shapes - key is omitted \n",
+                    __FILE__, tclean, g); 
   theCommands.Add("polygons", "polygons [name1]..., display polygons of shapes if exists",__FILE__, polygons, g);
   theCommands.Add("vconn","vconn [name1 ...] , edges are colored by number of faces (see vori)",__FILE__,dispor,g);
   theCommands.Add("discretisation","discretisation [nbpoints]",__FILE__,discretisation,g);
diff --git a/tests/bugs/modalg_7/bug29731 b/tests/bugs/modalg_7/bug29731
new file mode 100644 (file)
index 0000000..39a00f1
--- /dev/null
@@ -0,0 +1,19 @@
+
+puts "0029731: Modeling Algorithms - calculation of surface/volume of tessellated geometry"
+puts ""
+
+#############################################################
+# Surface and volume calculation on the triangulation built on a sphere
+#############################################################
+
+psphere sp1 10
+checkprops sp1 -v 4188.79
+checkprops sp1 -s 1256.64
+checkprops sp1 -l 62.8319
+
+incmesh sp1 0.01
+tclean -geom sp1
+
+checkprops sp1 -v 4183.13
+checkprops sp1 -s 1255.75
+checkprops sp1 -l 62.8215
diff --git a/tests/bugs/modalg_7/bug29734 b/tests/bugs/modalg_7/bug29734
new file mode 100644 (file)
index 0000000..81a8fe5
--- /dev/null
@@ -0,0 +1,64 @@
+puts "========"
+puts "OCC29734"
+puts "========"
+puts ""
+#######################
+# Compute global properties of tessellated shape
+#######################
+proc compmass { mass props1 props2 } {
+  regexp {Mass +: +([-0-9.+eE]+)} ${props1} full m1
+  regexp {Mass +: +([-0-9.+eE]+)} ${props2} full m2 
+  if { abs ($m1 - $m2) > 1.e-7  } {
+    puts "Error : The $mass by geometry is $m1, by triangulation is  $m2"
+  } else {
+    puts "The $mass are equal  $m1"
+  }
+}
+#
+proc compmoms { props1 props2 } {
+  set moments {"IX" "IY" "IZ"}
+  foreach moment $moments {
+    set exp_string "${moment} = +(\[-0-9.+eE\]+)" 
+    regexp "${exp_string}" ${props1} full m1
+    regexp "${exp_string}" ${props2} full m2
+    if { abs ($m1 - $m2) > 1.e-7  } {
+      puts "Error : The ${moment} by geometry is $m1, by triangulation is  $m2"
+    } else {
+      puts "The moments ${moment} are equal  $m1"
+    }
+  }
+}
+#
+proc compprops { shape } {
+  upvar ${shape} ${shape}
+  set commands {"lprops" "sprops" "vprops"}
+  foreach command ${commands} {
+    switch $command {
+      "lprops"    { set mass "length" }
+      "sprops"    { set mass "area" }
+      "vprops"    { set mass "volume" }
+    }
+    puts ""
+    set props1 [eval $command ${shape} -full]
+    set props2 [eval $command ${shape} -full -tri]
+    compmass $mass $props1 $props2
+    compmoms $props1 $props2
+  }
+}
+
+#For shapes consisted from planar polygonal faces 
+#results of computation of global properties using exact geometry 
+#and using triangulations must be the same
+#It is checked by this test
+box b1 1 2 3
+box b2 3 2 1
+ttranslate b2 .5 .5 .5
+trotate b2 0 0 0 1 1 1 30
+bfuse ff b1 b2
+incmesh ff .01
+set tri_info [eval trinfo ff]
+puts $tri_info
+
+# check of equality calculations by triangulation and exact geometry
+#set shape "ff"
+compprops ff
index 903669a..82866ef 100755 (executable)
@@ -11,8 +11,8 @@ puts ""
 restore [locate_data_file OCC173.brep] result
 checkshape result
 
-vinit result
-tclean 
+vinit 
+tclean result
 vdisplay result
 vfit
 vsetdispmode result 1